[Spice-commits] 799 commits - .gitignore MAINTAINERS Makefile Makefile.objs Makefile.target QMP/qmp-events.txt QMP/qmp-shell arch_init.c async.c backends/Makefile.objs backends/baum.c backends/msmouse.c backends/rng-egd.c backends/rng-random.c backends/tpm.c block-migration.c block.c block/blkdebug.c block/blkverify.c block/bochs.c block/cloop.c block/cow.c block/curl.c block/dmg.c block/gluster.c block/iscsi.c block/nbd.c block/parallels.c block/qcow.c block/qcow2-cluster.c block/qcow2-refcount.c block/qcow2-snapshot.c block/qcow2.c block/qcow2.h block/qed.c block/raw-posix.c block/raw-win32.c block/raw.c block/rbd.c block/sheepdog.c block/vdi.c block/vmdk.c block/vpc.c block/vvfat.c blockdev.c bt-host.c configure cpu-exec.c cpus.c default-configs/arm-softmmu.mak default-configs/i386-softmmu.mak default-configs/moxie-softmmu.mak default-configs/pci.mak default-configs/ppc-softmmu.mak default-configs/ppc64-softmmu.mak default-configs/ppcemb-softmmu.mak default-configs/x86_64-softmmu .mak device-hotplug.c disas.c disas/Makefile.objs disas/lm32.c disas/moxie.c docs/migration.txt docs/tracing.txt docs/usb-storage.txt exec.c gdbstub.c hmp-commands.hx hmp.c hmp.h hw/9p.h hw/9pfs hw/Makefile.objs hw/a15mpcore.c hw/a9mpcore.c hw/a9scu.c hw/ac97.c hw/acpi.c hw/acpi.h hw/acpi_ich9.c hw/acpi_ich9.h hw/acpi_piix4.c hw/adb.c hw/adb.h hw/adlib.c hw/ads7846.c hw/alpha hw/alpha_dp264.c hw/alpha_pci.c hw/alpha_sys.h hw/alpha_typhoon.c hw/an5206.c hw/apb_pci.c hw/apic.c hw/apic_common.c hw/apic_internal.h hw/apm.c hw/apm.h hw/applesmc.c hw/arm hw/arm-misc.h hw/arm11mpcore.c hw/arm_boot.c hw/arm_gic.c hw/arm_gic_common.c hw/arm_gic_internal.h hw/arm_l2x0.c hw/arm_mptimer.c hw/arm_pic.c hw/arm_sysctl.c hw/arm_timer.c hw/armv7m.c hw/armv7m_nvic.c hw/axis_dev88.c hw/baum.c hw/baum.h hw/bitbang_i2c.c hw/bitbang_i2c.h hw/blizzard.c hw/boards.h hw/bonito.c hw/bt-hci-csr.c hw/bt-hci.c hw/bt-hid.c hw/bt-l2cap.c hw/bt-sdp.c hw/bt.c hw/cadence_gem.c hw/cadence_ttc.c hw/cadence_uar t.c hw/cbus.c hw/ccid.h hw/cdrom.c hw/cirrus_vga.c hw/cirrus_vga_rop.h hw/collie.c hw/cris hw/cris-boot.c hw/cris_pic_cpu.c hw/cs4231.c hw/cs4231a.c hw/cuda.c hw/dataplane hw/debugcon.c hw/debugexit.c hw/dec_pci.c hw/device-hotplug.c hw/dma.c hw/dp8393x.c hw/ds1225y.c hw/ds1338.c hw/dummy_m68k.c hw/e1000.c hw/ecc.c hw/eccmemctl.c hw/eepro100.c hw/eeprom93xx.c hw/elf_ops.h hw/empty_slot.c hw/es1370.c hw/escc.c hw/esp-pci.c hw/esp.c hw/esp.h hw/etraxfs.h hw/etraxfs_dma.c hw/etraxfs_eth.c hw/etraxfs_pic.c hw/etraxfs_ser.c hw/etraxfs_timer.c hw/exynos4210.c hw/exynos4210_combiner.c hw/exynos4210_fimd.c hw/exynos4210_gic.c hw/exynos4210_i2c.c hw/exynos4210_mct.c hw/exynos4210_pmu.c hw/exynos4210_pwm.c hw/exynos4210_rtc.c hw/exynos4210_uart.c hw/exynos4_boards.c hw/fdc.c hw/fifo.c hw/fifo.h hw/fmopl.c hw/framebuffer.c hw/framebuffer.h hw/fw_cfg.c hw/g364fb.c hw/grackle_pci.c hw/grlib.h hw/grlib_apbuart.c hw/grlib_gptimer.c hw/grlib_irqmp.c hw/gt64xxx.c hw/gumstix.c hw/gus.c hw/gus emu_hal.c hw/gusemu_mixer.c hw/hda-audio.c hw/heathrow_pic.c hw/hid.c hw/highbank.c hw/hpet.c hw/hw.h hw/i2c.c hw/i2c.h hw/i386 hw/i82374.c hw/i82378.c hw/i8254.c hw/i8254.h hw/i8254_common.c hw/i8254_internal.h hw/i8259.c hw/i8259_common.c hw/i8259_internal.h hw/i82801b11.c hw/ich9.h hw/ide.h hw/imx_avic.c hw/imx_ccm.c hw/imx_serial.c hw/imx_timer.c hw/integratorcp.c hw/intel-hda.c hw/intel-hda.h hw/ioapic.c hw/ioapic_common.c hw/ioapic_internal.h hw/ioh3420.c hw/ioh3420.h hw/ipack.c hw/ipack.h hw/ipoctal232.c hw/irq.c hw/isa-bus.c hw/isa.h hw/isa_mmio.c hw/ivshmem.c hw/jazz_led.c hw/kvm hw/kvmvapic.c hw/kzm.c hw/lan9118.c hw/lance.c hw/leon3.c hw/lm32 hw/lm32_boards.c hw/lm32_hwsetup.h hw/lm32_juart.c hw/lm32_pic.c hw/lm32_sys.c hw/lm32_timer.c hw/lm32_uart.c hw/lm4549.c hw/lm832x.c hw/loader.c hw/loader.h hw/lpc_ich9.c hw/lsi53c895a.c hw/m25p80.c hw/m48t59.c hw/m68k hw/mac_dbdma.c hw/mac_nvram.c hw/macio.c hw/mainstone.c hw/marvell_88w8618_audio.c hw/max111x.c hw/max7310. c hw/mc146818rtc.c hw/mc146818rtc.h hw/mcf5206.c hw/mcf5208.c hw/mcf_fec.c hw/mcf_intc.c hw/mcf_uart.c hw/megasas.c hw/microblaze hw/microblaze_boot.c hw/microblaze_boot.h hw/microblaze_pic_cpu.c hw/milkymist-ac97.c hw/milkymist-hpdmc.c hw/milkymist-hw.h hw/milkymist-memcard.c hw/milkymist-minimac2.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.c hw/mips hw/mips_addr.c hw/mips_fulong2e.c hw/mips_int.c hw/mips_jazz.c hw/mips_malta.c hw/mips_mipssim.c hw/mips_r4k.c hw/mips_timer.c hw/mipsnet.c hw/moxie hw/mpc8544_guts.c hw/msmouse.c hw/msmouse.h hw/mst_fpga.c hw/multiboot.c hw/musicpal.c hw/nand.c hw/ne2000-isa.c hw/ne2000.c hw/nseries.c hw/omap1.c hw/omap2.c hw/omap_clk.c hw/omap_dma.c hw/omap_dss.c hw/omap_gpio.c hw/omap_gpmc.c hw/omap_gptimer.c hw/omap_i2c.c hw/omap_intc.c hw/omap_l4.c hw/omap_lcdc.c hw/omap_mmc.c hw/omap_sdrc.c hw/omap_spi.c hw/omap_sx1.c hw/omap_synctimer.c hw/om ap_tap.c hw/omap_uart.c hw/onenand.c hw/opencores_eth.c hw/openpic.c hw/openrisc hw/openrisc_pic.c hw/openrisc_sim.c hw/openrisc_timer.c hw/palm.c hw/pam.c hw/parallel.c hw/pc-testdev.c hw/pc.c hw/pc.h hw/pc87312.c hw/pc87312.h hw/pc_piix.c hw/pc_q35.c hw/pc_sysfw.c hw/pci hw/pci_bridge_dev.c hw/pckbd.c hw/pcnet-pci.c hw/pcnet.c hw/pcspk.c hw/pcspk.h hw/petalogix_ml605_mmu.c hw/petalogix_s3adsp1800_mmu.c hw/pflash_cfi01.c hw/pflash_cfi02.c hw/piix4.c hw/piix_pci.c hw/pl011.c hw/pl022.c hw/pl031.c hw/pl041.c hw/pl050.c hw/pl061.c hw/pl080.c hw/pl110.c hw/pl110_template.h hw/pl181.c hw/pl190.c hw/pl330.c hw/pm_smbus.c hw/ppc hw/ppc.c hw/ppc405.h hw/ppc405_boards.c hw/ppc405_uc.c hw/ppc440_bamboo.c hw/ppc4xx.h hw/ppc4xx_devs.c hw/ppc4xx_pci.c hw/ppc_booke.c hw/ppce500_pci.c hw/ppce500_spin.c hw/prep_pci.c hw/ps2.c hw/ptimer.c hw/puv3.c hw/puv3_dma.c hw/puv3_gpio.c hw/puv3_intc.c hw/puv3_ost.c hw/puv3_pm.c 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_pcmcia.c hw/pxa2xx_pic.c hw/pxa2xx_timer.c hw/q35.c hw/q35.h hw/qdev-addr.c hw/qdev-core.h hw/qdev-monitor.c hw/qdev-monitor.h hw/qdev-properties-system.c hw/qdev-properties.c hw/qdev-properties.h hw/qdev.c hw/qdev.h hw/qxl-logger.c hw/qxl-render.c hw/qxl.c hw/qxl.h hw/r2d.c hw/rc4030.c hw/realview.c hw/realview_gic.c hw/rtl8139.c hw/s390x hw/sb16.c hw/sbi.c hw/scsi-bus.c hw/scsi-disk.c hw/scsi-generic.c hw/scsi.h hw/sd.c hw/sdhci.c hw/sdhci.h hw/serial-isa.c hw/serial-pci.c hw/serial.c hw/serial.h hw/sga.c hw/sh.h hw/sh4 hw/sh7750.c hw/sh7750_regnames.c hw/sh_intc.c hw/sh_intc.h hw/sh_pci.c hw/sh_serial.c hw/sh_timer.c hw/shix.c hw/slavio_intctl.c hw/slavio_misc.c hw/slavio_timer.c hw/sm501.c hw/smbios.c hw/smbus.c hw/smbus.h hw/smbus_eeprom.c hw/smbus_ich9.c hw/smc91c111.c hw/soc_dma.c hw/spapr.c hw/spapr_events.c hw/spapr_hcall.c hw/spapr_iommu.c hw/spapr_llan.c hw/spapr_pci.c hw/spapr_pci.h hw/spapr_rtas.c hw/spapr_vio.c hw/spapr_vscsi.c hw/spapr_vty.c hw/sparc hw/sparc32_dma.c hw/sparc64 hw/spitz.c hw/ssd0303.c hw/ssd0323.c hw/ssi-sd.c hw/ssi.c hw/ssi.h hw/stellaris.c hw/stellaris_enet.c hw/stellaris_input.c hw/stream.c hw/strongarm.c hw/sun4c_intctl.c hw/sun4m.c hw/sun4m.h hw/sun4m_iommu.c hw/sun4u.c hw/sysbus.c hw/sysbus.h hw/tc58128.c hw/tc6393xb.c hw/tc6393xb_template.h hw/tcx.c hw/tmp105.c hw/tmp105.h hw/tosa.c hw/tpci200.c hw/tsc2005.c hw/tsc210x.c hw/tusb6010.c hw/twl92230.c hw/unicore32 hw/unin_pci.c hw/usb hw/usb.h hw/versatile_i2c.c hw/versatile_pci.c hw/versatilepb.c hw/vexpress.c hw/vfio_pci.c hw/vga-isa-mm.c hw/vga-isa.c hw/vga-pci.c hw/vga.c hw/vga_int.h hw/vhost.c hw/vhost_net.c hw/virtex_ml507.c hw/virtio-balloon.c hw/virtio-balloon.h hw/virtio-blk.c hw/virtio-blk.h hw/virtio-bus.c hw/virtio-bus.h hw/virtio-console.c hw/virtio-net.c hw/virtio-net.h hw/virtio-pci.c hw/virtio-pci.h hw/virtio-rng.c hw/virtio-rng.h hw/virtio-scsi.c hw/virtio-scsi.h hw/virtio-serial-bus.c hw/virtio-serial.h hw/v irtio.c hw/virtio.h hw/vmmouse.c hw/vmport.c hw/vmware_utils.h hw/vmware_vga.c hw/vmxnet3.c hw/vmxnet3.h hw/vmxnet_debug.h hw/vmxnet_rx_pkt.c hw/vmxnet_rx_pkt.h hw/vmxnet_tx_pkt.c hw/vmxnet_tx_pkt.h hw/vt82c686.c hw/wdt_i6300esb.c hw/wdt_ib700.c hw/wm8750.c hw/xen-host-pci-device.c hw/xen-host-pci-device.h hw/xen_apic.c hw/xen_backend.c hw/xen_backend.h hw/xen_common.h hw/xen_console.c hw/xen_devconfig.c hw/xen_disk.c hw/xen_domainbuild.c hw/xen_domainbuild.h hw/xen_machine_pv.c hw/xen_nic.c hw/xen_platform.c hw/xen_pt.c hw/xen_pt.h hw/xen_pt_config_init.c hw/xen_pt_msi.c hw/xenfb.c hw/xgmac.c hw/xics.c hw/xics.h hw/xilinx.h hw/xilinx_axidma.c hw/xilinx_axienet.c hw/xilinx_ethlite.c hw/xilinx_intc.c hw/xilinx_spi.c hw/xilinx_spips.c hw/xilinx_timer.c hw/xilinx_uartlite.c hw/xilinx_zynq.c hw/xio3130_downstream.c hw/xio3130_downstream.h hw/xio3130_upstream.c hw/xio3130_upstream.h hw/xtensa hw/xtensa_lx60.c hw/xtensa_pic.c hw/xtensa_sim.c hw/z2.c hw/zaurus.c hw/zynq_slcr.c incl ude/backends include/block include/char include/disas include/exec include/glib-compat.h include/migration include/monitor include/net include/qapi include/qemu include/qemu-common.h include/qom include/sysemu include/tpm include/ui kvm-all.c linux-headers/asm-arm linux-headers/asm-generic linux-headers/linux linux-user/main.c linux-user/mips64 linux-user/mipsn32 linux-user/signal.c linux-user/socket.h linux-user/sparc linux-user/strace.c linux-user/syscall.c main-loop.c memory.c migration-exec.c migration-fd.c migration-tcp.c migration-unix.c migration.c monitor.c nbd.c net/Makefile.objs net/checksum.c net/eth.c net/hub.c net/hub.h net/net.c net/queue.c net/slirp.c net/socket.c net/tap-linux.c net/tap-linux.h net/tap.c net/vde.c page_cache.c pc-bios/bios.bin pc-bios/efi-e1000.rom pc-bios/efi-eepro100.rom pc-bios/efi-ne2k_pci.rom pc-bios/efi-pcnet.rom pc-bios/efi-rtl8139.rom pc-bios/efi-virtio.rom po/Makefile po/de_DE.po po/fr_FR.po po/it.po po/messages.po qapi-schema.json q dev-monitor.c qemu-bridge-helper.c qemu-char.c qemu-coroutine-lock.c qemu-doc.texi qemu-img.c qemu-io.c qemu-nbd.c qemu-options.hx qga/channel-win32.c qga/commands-posix.c qga/commands-win32.c qga/guest-agent-core.h qga/main.c qga/qapi-schema.json qga/service-win32.c qmp-commands.hx qobject/qdict.c qobject/qstring.c qom/cpu.c qom/object.c qtest.c roms/Makefile roms/config.ipxe.general.h roms/configure-seabios.sh roms/ipxe roms/seabios savevm.c scripts/make_device_config.sh scripts/tracetool scripts/tracetool.py slirp/misc.c slirp/socket.c slirp/tcp_subr.c slirp/udp.c spice-qemu-char.c stubs/Makefile.objs stubs/pci-drive-hot-add.c stubs/vmstate.c target-alpha/cpu-qom.h target-alpha/cpu.c target-alpha/cpu.h target-alpha/helper.c target-alpha/translate.c target-arm/Makefile.objs target-arm/cpu-qom.h target-arm/cpu.c target-arm/cpu.h target-arm/helper.c target-arm/kvm.c target-arm/kvm_arm.h target-arm/op_helper.c target-arm/translate.c target-cris/cpu-qom.h target-cris/cpu.c tar get-cris/cpu.h target-cris/helper.c target-cris/translate.c target-i386/cpu-qom.h target-i386/cpu.c target-i386/cpu.h target-i386/fpu_helper.c target-i386/helper.c target-i386/kvm.c target-i386/machine.c target-i386/misc_helper.c target-i386/ops_sse.h target-i386/seg_helper.c target-i386/svm_helper.c target-i386/translate.c target-lm32/cpu-qom.h target-lm32/cpu.c target-lm32/cpu.h target-lm32/helper.c target-lm32/machine.c target-lm32/op_helper.c target-lm32/translate.c target-m68k/cpu-qom.h target-m68k/cpu.c target-m68k/cpu.h target-m68k/helper.c target-m68k/op_helper.c target-m68k/qregs.def target-m68k/translate.c target-microblaze/cpu-qom.h target-microblaze/cpu.c target-microblaze/cpu.h target-microblaze/helper.c target-microblaze/op_helper.c target-microblaze/translate.c target-mips/cpu-qom.h target-mips/cpu.c target-mips/cpu.h target-mips/dsp_helper.c target-mips/helper.c target-mips/op_helper.c target-mips/translate.c target-moxie/Makefile.objs target-moxie/cpu.c targ et-moxie/cpu.h target-moxie/helper.c target-moxie/helper.h target-moxie/machine.c target-moxie/machine.h target-moxie/mmu.c target-moxie/mmu.h target-moxie/translate.c target-openrisc/cpu.c target-openrisc/cpu.h target-openrisc/interrupt.c target-openrisc/interrupt_helper.c target-openrisc/sys_helper.c target-openrisc/translate.c target-ppc/Makefile.objs target-ppc/cpu-models.c target-ppc/cpu-models.h target-ppc/cpu-qom.h target-ppc/cpu.h target-ppc/excp_helper.c target-ppc/fpu_helper.c target-ppc/helper.h target-ppc/helper_regs.h target-ppc/kvm.c target-ppc/machine.c target-ppc/mem_helper.c target-ppc/misc_helper.c target-ppc/mmu-hash32.c target-ppc/mmu-hash32.h target-ppc/mmu-hash64.c target-ppc/mmu-hash64.h target-ppc/mmu_helper.c target-ppc/translate.c target-ppc/translate_init.c target-ppc/user_only_helper.c target-s390x/cpu-qom.h target-s390x/cpu.c target-s390x/cpu.h target-s390x/helper.c target-s390x/ioinst.c target-s390x/kvm.c target-s390x/translate.c target-sh4/cpu- qom.h target-sh4/cpu.c target-sh4/cpu.h target-sh4/helper.c target-sh4/op_helper.c target-sh4/translate.c target-sparc/cpu-qom.h target-sparc/cpu.c target-sparc/cpu.h target-sparc/helper.c target-sparc/int32_helper.c target-sparc/int64_helper.c target-sparc/translate.c target-unicore32/cpu-qom.h target-unicore32/cpu.c target-unicore32/cpu.h target-unicore32/helper.c target-unicore32/softmmu.c target-unicore32/translate.c target-xtensa/cpu-qom.h target-xtensa/cpu.c target-xtensa/cpu.h target-xtensa/helper.c target-xtensa/op_helper.c target-xtensa/translate.c tcg/README tcg/mips tcg/optimize.c tcg/sparc tcg/tcg.h tests/qemu-iotests tests/rtc-test.c tests/tcg tests/test-thread-pool.c tests/test-visitor-serialization.c thread-pool.c tpm/Makefile.objs tpm/tpm.c tpm/tpm_backend.c tpm/tpm_backend.h tpm/tpm_int.h tpm/tpm_passthrough.c tpm/tpm_tis.c tpm/tpm_tis.h trace-events trace/Makefile.objs trace/control-internal.h trace/control.c trace/control.h trace/default.c trace/event-inte rnal.h trace/simple.c trace/simple.h trace/stderr.c trace/stderr.h translate-all.c ui/cocoa.m ui/console.c ui/curses.c ui/gtk.c ui/sdl.c ui/spice-display.c ui/vnc-enc-tight.c ui/vnc-jobs.c ui/vnc.c ui/vnc.h util/Makefile.objs util/bitops.c util/cutils.c util/fifo8.c util/hexdump.c util/iov.c util/osdep.c util/oslib-posix.c util/oslib-win32.c util/qemu-config.c util/qemu-option.c util/qemu-sockets.c util/qemu-timer-common.c vl.c xen-all.c xen-mapcache.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Mon Apr 15 01:47:17 PDT 2013


 .gitignore                               |    7 
 MAINTAINERS                              |   24 
 Makefile                                 |   11 
 Makefile.objs                            |    2 
 Makefile.target                          |    1 
 QMP/qmp-events.txt                       |   18 
 QMP/qmp-shell                            |    7 
 arch_init.c                              |  108 
 async.c                                  |   11 
 backends/Makefile.objs                   |    6 
 backends/baum.c                          |  633 +++
 backends/msmouse.c                       |   84 
 backends/rng-egd.c                       |    6 
 backends/rng-random.c                    |    4 
 backends/tpm.c                           |  154 
 block-migration.c                        |  167 
 block.c                                  |  307 +
 block/blkdebug.c                         |    5 
 block/blkverify.c                        |    7 
 block/bochs.c                            |    2 
 block/cloop.c                            |    2 
 block/cow.c                              |    4 
 block/curl.c                             |    3 
 block/dmg.c                              |   15 
 block/gluster.c                          |    2 
 block/iscsi.c                            |  431 +-
 block/nbd.c                              |  137 
 block/parallels.c                        |    2 
 block/qcow.c                             |    4 
 block/qcow2-cluster.c                    |  514 ++
 block/qcow2-refcount.c                   |   53 
 block/qcow2-snapshot.c                   |   10 
 block/qcow2.c                            |   75 
 block/qcow2.h                            |   33 
 block/qed.c                              |    6 
 block/raw-posix.c                        |   23 
 block/raw-win32.c                        |   10 
 block/raw.c                              |    2 
 block/rbd.c                              |    3 
 block/sheepdog.c                         |  341 +
 block/vdi.c                              |    2 
 block/vmdk.c                             |    6 
 block/vpc.c                              |    2 
 block/vvfat.c                            |    5 
 blockdev.c                               |  119 
 bt-host.c                                |    2 
 configure                                |  111 
 cpu-exec.c                               |  134 
 cpus.c                                   |   17 
 default-configs/arm-softmmu.mak          |    3 
 default-configs/i386-softmmu.mak         |    2 
 default-configs/moxie-softmmu.mak        |    1 
 default-configs/pci.mak                  |    1 
 default-configs/ppc-softmmu.mak          |    1 
 default-configs/ppc64-softmmu.mak        |    2 
 default-configs/ppcemb-softmmu.mak       |    1 
 default-configs/x86_64-softmmu.mak       |    2 
 device-hotplug.c                         |   79 
 disas.c                                  |    6 
 disas/Makefile.objs                      |    1 
 disas/lm32.c                             |    8 
 disas/moxie.c                            |  360 ++
 docs/migration.txt                       |   20 
 docs/tracing.txt                         |   44 
 docs/usb-storage.txt                     |    4 
 exec.c                                   |   47 
 gdbstub.c                                |   13 
 hmp-commands.hx                          |   69 
 hmp.c                                    |   54 
 hmp.h                                    |    2 
 hw/9p.h                                  |   24 
 hw/9pfs/virtio-9p-device.c               |   53 
 hw/9pfs/virtio-9p-device.h               |   24 
 hw/9pfs/virtio-9p-proxy.c                |    1 
 hw/9pfs/virtio-9p.c                      |    3 
 hw/9pfs/virtio-9p.h                      |    1 
 hw/Makefile.objs                         |   12 
 hw/a15mpcore.c                           |   10 
 hw/a9mpcore.c                            |  159 
 hw/a9scu.c                               |  164 
 hw/ac97.c                                |    6 
 hw/acpi.c                                |  365 +-
 hw/acpi.h                                |    2 
 hw/acpi_ich9.c                           |   12 
 hw/acpi_ich9.h                           |    2 
 hw/acpi_piix4.c                          |   16 
 hw/adb.c                                 |    4 
 hw/adb.h                                 |    2 
 hw/adlib.c                               |    8 
 hw/ads7846.c                             |    2 
 hw/alpha/Makefile.objs                   |    4 
 hw/alpha/dp264.c                         |  182 +
 hw/alpha/pci.c                           |  109 
 hw/alpha_dp264.c                         |  182 -
 hw/alpha_pci.c                           |  109 
 hw/alpha_sys.h                           |   10 
 hw/alpha_typhoon.c                       |   26 
 hw/an5206.c                              |  100 
 hw/apb_pci.c                             |   16 
 hw/apic.c                                |   37 
 hw/apic_common.c                         |    6 
 hw/apic_internal.h                       |    2 
 hw/apm.c                                 |    6 
 hw/apm.h                                 |    2 
 hw/applesmc.c                            |    4 
 hw/arm-misc.h                            |    2 
 hw/arm/Makefile.objs                     |   45 
 hw/arm/armv7m.c                          |  284 +
 hw/arm/boot.c                            |  480 ++
 hw/arm/collie.c                          |   73 
 hw/arm/exynos4210.c                      |  349 +
 hw/arm/exynos4_boards.c                  |  170 
 hw/arm/gumstix.c                         |  141 
 hw/arm/highbank.c                        |  342 +
 hw/arm/integratorcp.c                    |  566 +++
 hw/arm/kzm.c                             |  157 
 hw/arm/mainstone.c                       |  190 +
 hw/arm/musicpal.c                        | 1717 +++++++++
 hw/arm/nseries.c                         | 1415 +++++++
 hw/arm/omap1.c                           | 4059 ++++++++++++++++++++++
 hw/arm/omap2.c                           | 2684 ++++++++++++++
 hw/arm/omap_sx1.c                        |  238 +
 hw/arm/palm.c                            |  284 +
 hw/arm/pic_cpu.c                         |   68 
 hw/arm/pxa2xx.c                          | 2294 ++++++++++++
 hw/arm/pxa2xx_gpio.c                     |  351 +
 hw/arm/pxa2xx_pic.c                      |  335 +
 hw/arm/realview.c                        |  404 ++
 hw/arm/spitz.c                           | 1138 ++++++
 hw/arm/stellaris.c                       | 1401 +++++++
 hw/arm/tosa.c                            |  302 +
 hw/arm/versatilepb.c                     |  403 ++
 hw/arm/vexpress.c                        |  559 +++
 hw/arm/xilinx_zynq.c                     |  247 +
 hw/arm/z2.c                              |  384 ++
 hw/arm11mpcore.c                         |   43 
 hw/arm_boot.c                            |  480 --
 hw/arm_gic.c                             |   27 
 hw/arm_gic_common.c                      |  140 
 hw/arm_gic_internal.h                    |   46 
 hw/arm_l2x0.c                            |    2 
 hw/arm_mptimer.c                         |  119 
 hw/arm_pic.c                             |   40 
 hw/arm_sysctl.c                          |  267 +
 hw/arm_timer.c                           |    6 
 hw/armv7m.c                              |  284 -
 hw/armv7m_nvic.c                         |   25 
 hw/axis_dev88.c                          |  366 --
 hw/baum.c                                |  627 ---
 hw/baum.h                                |   30 
 hw/bitbang_i2c.c                         |    6 
 hw/bitbang_i2c.h                         |    2 
 hw/blizzard.c                            |   51 
 hw/boards.h                              |    2 
 hw/bonito.c                              |   12 
 hw/bt-hci-csr.c                          |    5 
 hw/bt-hci.c                              |    4 
 hw/bt-hid.c                              |    4 
 hw/bt-l2cap.c                            |    2 
 hw/bt-sdp.c                              |    2 
 hw/bt.c                                  |    2 
 hw/cadence_gem.c                         |   38 
 hw/cadence_ttc.c                         |    2 
 hw/cadence_uart.c                        |    3 
 hw/cbus.c                                |    4 
 hw/ccid.h                                |    2 
 hw/cdrom.c                               |    2 
 hw/cirrus_vga.c                          |   66 
 hw/cirrus_vga_rop.h                      |    8 
 hw/collie.c                              |   73 
 hw/cris-boot.c                           |   98 
 hw/cris/Makefile.objs                    |   10 
 hw/cris/axis_dev88.c                     |  366 ++
 hw/cris/boot.c                           |   98 
 hw/cris/pic_cpu.c                        |   47 
 hw/cris_pic_cpu.c                        |   45 
 hw/cs4231.c                              |    2 
 hw/cs4231a.c                             |    8 
 hw/cuda.c                                |    6 
 hw/dataplane/Makefile.objs               |    2 
 hw/dataplane/event-poll.c                |  100 
 hw/dataplane/event-poll.h                |   40 
 hw/dataplane/ioq.c                       |    2 
 hw/dataplane/virtio-blk.c                |   63 
 hw/dataplane/vring.c                     |    3 
 hw/dataplane/vring.h                     |    2 
 hw/debugcon.c                            |    6 
 hw/debugexit.c                           |    4 
 hw/dec_pci.c                             |   19 
 hw/device-hotplug.c                      |   88 
 hw/dma.c                                 |    4 
 hw/dp8393x.c                             |    4 
 hw/ds1225y.c                             |    2 
 hw/ds1338.c                              |   10 
 hw/dummy_m68k.c                          |   84 
 hw/e1000.c                               |   35 
 hw/ecc.c                                 |    4 
 hw/eccmemctl.c                           |    2 
 hw/eepro100.c                            |    6 
 hw/eeprom93xx.c                          |    4 
 hw/elf_ops.h                             |   19 
 hw/empty_slot.c                          |    6 
 hw/es1370.c                              |    6 
 hw/escc.c                                |    6 
 hw/esp-pci.c                             |    6 
 hw/esp.c                                 |    4 
 hw/esp.h                                 |    2 
 hw/etraxfs.h                             |    2 
 hw/etraxfs_dma.c                         |    4 
 hw/etraxfs_eth.c                         |    4 
 hw/etraxfs_pic.c                         |    4 
 hw/etraxfs_ser.c                         |    2 
 hw/etraxfs_timer.c                       |    4 
 hw/exynos4210.c                          |  349 -
 hw/exynos4210_combiner.c                 |    4 
 hw/exynos4210_fimd.c                     |   19 
 hw/exynos4210_gic.c                      |    6 
 hw/exynos4210_i2c.c                      |    4 
 hw/exynos4210_mct.c                      |    6 
 hw/exynos4210_pmu.c                      |    2 
 hw/exynos4210_pwm.c                      |    6 
 hw/exynos4210_rtc.c                      |    8 
 hw/exynos4210_uart.c                     |    4 
 hw/exynos4_boards.c                      |  170 
 hw/fdc.c                                 |   10 
 hw/fifo.c                                |   78 
 hw/fifo.h                                |   99 
 hw/fmopl.c                               |    2 
 hw/framebuffer.c                         |    8 
 hw/framebuffer.h                         |    2 
 hw/fw_cfg.c                              |    8 
 hw/g364fb.c                              |   47 
 hw/grackle_pci.c                         |    8 
 hw/grlib.h                               |    4 
 hw/grlib_apbuart.c                       |    2 
 hw/grlib_gptimer.c                       |    4 
 hw/grlib_irqmp.c                         |    4 
 hw/gt64xxx.c                             |   12 
 hw/gumstix.c                             |  141 
 hw/gus.c                                 |   10 
 hw/gusemu_hal.c                          |    4 
 hw/gusemu_mixer.c                        |    4 
 hw/hda-audio.c                           |    8 
 hw/heathrow_pic.c                        |    4 
 hw/hid.c                                 |    4 
 hw/highbank.c                            |  342 -
 hw/hpet.c                                |   12 
 hw/hw.h                                  |    8 
 hw/i2c.c                                 |    2 
 hw/i2c.h                                 |    2 
 hw/i386/Makefile.objs                    |   17 
 hw/i386/kvmvapic.c                       |  820 ++++
 hw/i386/multiboot.c                      |  349 +
 hw/i386/pc.c                             | 1180 ++++++
 hw/i386/pc_piix.c                        |  718 +++
 hw/i386/pc_q35.c                         |  239 +
 hw/i386/smbios.c                         |  241 +
 hw/i386/xen_domainbuild.c                |  299 +
 hw/i386/xen_machine_pv.c                 |  126 
 hw/i82374.c                              |    2 
 hw/i82378.c                              |    8 
 hw/i8254.c                               |   10 
 hw/i8254.h                               |    4 
 hw/i8254_common.c                        |   10 
 hw/i8254_internal.h                      |    6 
 hw/i8259.c                               |    8 
 hw/i8259_common.c                        |    4 
 hw/i8259_internal.h                      |    6 
 hw/i82801b11.c                           |    6 
 hw/ich9.h                                |   37 
 hw/ide.h                                 |    4 
 hw/imx_avic.c                            |    4 
 hw/imx_ccm.c                             |    6 
 hw/imx_serial.c                          |    6 
 hw/imx_timer.c                           |    8 
 hw/integratorcp.c                        |  566 ---
 hw/intel-hda.c                           |   12 
 hw/intel-hda.h                           |    2 
 hw/ioapic.c                              |   10 
 hw/ioapic_common.c                       |    6 
 hw/ioapic_internal.h                     |    4 
 hw/ioh3420.c                             |   10 
 hw/ioh3420.h                             |    2 
 hw/ipack.c                               |    2 
 hw/ipack.h                               |    2 
 hw/ipoctal232.c                          |   44 
 hw/irq.c                                 |    2 
 hw/isa-bus.c                             |    6 
 hw/isa.h                                 |    2 
 hw/isa_mmio.c                            |    4 
 hw/ivshmem.c                             |    9 
 hw/jazz_led.c                            |   90 
 hw/kvm/arm_gic.c                         |  167 
 hw/kvmvapic.c                            |  822 ----
 hw/kzm.c                                 |  157 
 hw/lan9118.c                             |    6 
 hw/lance.c                               |    6 
 hw/leon3.c                               |  223 -
 hw/lm32/Makefile.objs                    |   10 
 hw/lm32/lm32_boards.c                    |  309 +
 hw/lm32/milkymist.c                      |  219 +
 hw/lm32_boards.c                         |  308 -
 hw/lm32_hwsetup.h                        |    2 
 hw/lm32_juart.c                          |    6 
 hw/lm32_pic.c                            |    8 
 hw/lm32_sys.c                            |    4 
 hw/lm32_timer.c                          |    6 
 hw/lm32_uart.c                           |    5 
 hw/lm4549.c                              |    4 
 hw/lm832x.c                              |    4 
 hw/loader.c                              |   87 
 hw/loader.h                              |    2 
 hw/lpc_ich9.c                            |   87 
 hw/lsi53c895a.c                          |    6 
 hw/m25p80.c                              |   64 
 hw/m48t59.c                              |    8 
 hw/m68k/Makefile.objs                    |    8 
 hw/m68k/an5206.c                         |  100 
 hw/m68k/dummy_m68k.c                     |   84 
 hw/m68k/mcf5206.c                        |  548 +++
 hw/m68k/mcf5208.c                        |  306 +
 hw/m68k/mcf_intc.c                       |  154 
 hw/mac_dbdma.c                           |   10 
 hw/mac_nvram.c                           |    6 
 hw/macio.c                               |   12 
 hw/mainstone.c                           |  190 -
 hw/marvell_88w8618_audio.c               |    8 
 hw/max111x.c                             |    2 
 hw/max7310.c                             |    2 
 hw/mc146818rtc.c                         |    6 
 hw/mc146818rtc.h                         |    4 
 hw/mcf5206.c                             |  548 ---
 hw/mcf5208.c                             |  306 -
 hw/mcf_fec.c                             |    4 
 hw/mcf_intc.c                            |  154 
 hw/mcf_uart.c                            |    5 
 hw/megasas.c                             |   12 
 hw/microblaze/Makefile.objs              |   11 
 hw/microblaze/boot.c                     |  177 
 hw/microblaze/petalogix_ml605_mmu.c      |  185 +
 hw/microblaze/petalogix_s3adsp1800_mmu.c |  127 
 hw/microblaze/pic_cpu.c                  |   47 
 hw/microblaze_boot.c                     |  177 
 hw/microblaze_boot.h                     |    2 
 hw/microblaze_pic_cpu.c                  |   44 
 hw/milkymist-ac97.c                      |    4 
 hw/milkymist-hpdmc.c                     |    4 
 hw/milkymist-hw.h                        |   30 
 hw/milkymist-memcard.c                   |    6 
 hw/milkymist-minimac2.c                  |   11 
 hw/milkymist-pfpu.c                      |    4 
 hw/milkymist-softusb.c                   |   29 
 hw/milkymist-sysctl.c                    |    6 
 hw/milkymist-tmu2.c                      |    4 
 hw/milkymist-uart.c                      |    5 
 hw/milkymist-vgafb.c                     |   33 
 hw/milkymist.c                           |  218 -
 hw/mips/Makefile.objs                    |    8 
 hw/mips/addr.c                           |   34 
 hw/mips/cputimer.c                       |  147 
 hw/mips/mips_fulong2e.c                  |  411 ++
 hw/mips/mips_int.c                       |   67 
 hw/mips/mips_jazz.c                      |  345 +
 hw/mips/mips_malta.c                     | 1037 +++++
 hw/mips/mips_mipssim.c                   |  240 +
 hw/mips/mips_r4k.c                       |  313 +
 hw/mips_addr.c                           |   34 
 hw/mips_fulong2e.c                       |  411 --
 hw/mips_int.c                            |   65 
 hw/mips_jazz.c                           |  345 -
 hw/mips_malta.c                          | 1037 -----
 hw/mips_mipssim.c                        |  240 -
 hw/mips_r4k.c                            |  313 -
 hw/mips_timer.c                          |  147 
 hw/mipsnet.c                             |    4 
 hw/moxie/Makefile.objs                   |    5 
 hw/moxie/moxiesim.c                      |  174 
 hw/mpc8544_guts.c                        |  143 
 hw/msmouse.c                             |   78 
 hw/msmouse.h                             |    7 
 hw/mst_fpga.c                            |    4 
 hw/multiboot.c                           |  349 -
 hw/musicpal.c                            | 1697 ---------
 hw/nand.c                                |   10 
 hw/ne2000-isa.c                          |   10 
 hw/ne2000.c                              |   10 
 hw/nseries.c                             | 1430 -------
 hw/omap1.c                               | 4056 ----------------------
 hw/omap2.c                               | 2684 --------------
 hw/omap_clk.c                            |    4 
 hw/omap_dma.c                            |    6 
 hw/omap_dss.c                            |    4 
 hw/omap_gpio.c                           |    6 
 hw/omap_gpmc.c                           |    6 
 hw/omap_gptimer.c                        |    4 
 hw/omap_i2c.c                            |    8 
 hw/omap_intc.c                           |    6 
 hw/omap_l4.c                             |    4 
 hw/omap_lcdc.c                           |   61 
 hw/omap_mmc.c                            |    6 
 hw/omap_sdrc.c                           |    4 
 hw/omap_spi.c                            |    4 
 hw/omap_sx1.c                            |  238 -
 hw/omap_synctimer.c                      |    4 
 hw/omap_tap.c                            |    4 
 hw/omap_uart.c                           |    6 
 hw/onenand.c                             |   11 
 hw/opencores_eth.c                       |    4 
 hw/openpic.c                             |   14 
 hw/openrisc/Makefile.objs                |    5 
 hw/openrisc/cputimer.c                   |  103 
 hw/openrisc/openrisc_sim.c               |  150 
 hw/openrisc/pic_cpu.c                    |   61 
 hw/openrisc_pic.c                        |   60 
 hw/openrisc_sim.c                        |  150 
 hw/openrisc_timer.c                      |  101 
 hw/palm.c                                |  291 -
 hw/pam.c                                 |    2 
 hw/parallel.c                            |    6 
 hw/pc-testdev.c                          |    6 
 hw/pc.c                                  | 1161 ------
 hw/pc.h                                  |   39 
 hw/pc87312.c                             |    3 
 hw/pc87312.h                             |    2 
 hw/pc_piix.c                             |  713 ---
 hw/pc_q35.c                              |  239 -
 hw/pc_sysfw.c                            |   11 
 hw/pci/pci-hotplug.c                     |    2 
 hw/pci/pci.c                             |  121 
 hw/pci/pci.h                             |   35 
 hw/pci/pci_bridge.c                      |   51 
 hw/pci/pci_bridge.h                      |   17 
 hw/pci/pci_bus.h                         |   10 
 hw/pci/pci_host.c                        |    2 
 hw/pci/pci_host.h                        |    1 
 hw/pci/pcie.c                            |   16 
 hw/pci/pcie.h                            |    1 
 hw/pci/pcie_port.c                       |   18 
 hw/pci/shpc.c                            |    3 
 hw/pci/slotid_cap.c                      |    1 
 hw/pci_bridge_dev.c                      |   23 
 hw/pckbd.c                               |    8 
 hw/pcnet-pci.c                           |    8 
 hw/pcnet.c                               |    4 
 hw/pcspk.c                               |   10 
 hw/pcspk.h                               |    4 
 hw/petalogix_ml605_mmu.c                 |  187 -
 hw/petalogix_s3adsp1800_mmu.c            |  127 
 hw/pflash_cfi01.c                        |   50 
 hw/pflash_cfi02.c                        |    6 
 hw/piix4.c                               |   10 
 hw/piix_pci.c                            |   49 
 hw/pl011.c                               |    2 
 hw/pl022.c                               |    4 
 hw/pl031.c                               |    2 
 hw/pl041.c                               |    6 
 hw/pl050.c                               |    9 
 hw/pl061.c                               |    2 
 hw/pl080.c                               |    2 
 hw/pl110.c                               |   38 
 hw/pl110_template.h                      |   12 
 hw/pl181.c                               |    4 
 hw/pl190.c                               |    2 
 hw/pl330.c                               | 1653 +++++++++
 hw/pm_smbus.c                            |    8 
 hw/ppc.c                                 | 1356 -------
 hw/ppc/Makefile.objs                     |   29 
 hw/ppc/e500-ccsr.h                       |    2 
 hw/ppc/e500.c                            |   10 
 hw/ppc/e500plat.c                        |    2 
 hw/ppc/mac_newworld.c                    |    2 
 hw/ppc/mpc8544_guts.c                    |  143 
 hw/ppc/mpc8544ds.c                       |    2 
 hw/ppc/ppc.c                             | 1364 +++++++
 hw/ppc/ppc405_boards.c                   |  662 +++
 hw/ppc/ppc405_uc.c                       | 2548 ++++++++++++++
 hw/ppc/ppc440_bamboo.c                   |  306 +
 hw/ppc/ppc4xx_devs.c                     |  721 ++++
 hw/ppc/ppc_booke.c                       |  273 +
 hw/ppc/ppce500_spin.c                    |  222 +
 hw/ppc/prep.c                            |    1 
 hw/ppc/spapr.c                           |  970 +++++
 hw/ppc/spapr_events.c                    |  321 +
 hw/ppc/spapr_hcall.c                     |  740 ++++
 hw/ppc/spapr_iommu.c                     |  293 +
 hw/ppc/spapr_rtas.c                      |  334 +
 hw/ppc/spapr_vio.c                       |  649 +++
 hw/ppc/virtex_ml507.c                    |  274 +
 hw/ppc/xics.c                            |  581 +++
 hw/ppc405.h                              |    2 
 hw/ppc405_boards.c                       |  662 ---
 hw/ppc405_uc.c                           | 2548 --------------
 hw/ppc440_bamboo.c                       |  306 -
 hw/ppc4xx.h                              |    2 
 hw/ppc4xx_devs.c                         |  721 ----
 hw/ppc4xx_pci.c                          |   12 
 hw/ppc_booke.c                           |  273 -
 hw/ppce500_pci.c                         |   10 
 hw/ppce500_spin.c                        |  222 -
 hw/prep_pci.c                            |   12 
 hw/ps2.c                                 |    4 
 hw/ptimer.c                              |    4 
 hw/puv3.c                                |  135 
 hw/puv3_dma.c                            |    6 
 hw/puv3_gpio.c                           |    6 
 hw/puv3_intc.c                           |    4 
 hw/puv3_ost.c                            |    6 
 hw/puv3_pm.c                             |    6 
 hw/pxa2xx.c                              | 2291 ------------
 hw/pxa2xx_dma.c                          |    6 
 hw/pxa2xx_gpio.c                         |  350 -
 hw/pxa2xx_keypad.c                       |    4 
 hw/pxa2xx_lcd.c                          |   55 
 hw/pxa2xx_mmci.c                         |    8 
 hw/pxa2xx_pcmcia.c                       |    6 
 hw/pxa2xx_pic.c                          |  334 -
 hw/pxa2xx_timer.c                        |    6 
 hw/q35.c                                 |    7 
 hw/q35.h                                 |   22 
 hw/qdev-addr.c                           |    7 
 hw/qdev-core.h                           |    3 
 hw/qdev-monitor.c                        |  683 ---
 hw/qdev-monitor.h                        |   16 
 hw/qdev-properties-system.c              |   15 
 hw/qdev-properties.c                     |  144 
 hw/qdev-properties.h                     |   53 
 hw/qdev.c                                |   37 
 hw/qdev.h                                |    5 
 hw/qxl-logger.c                          |    2 
 hw/qxl-render.c                          |   23 
 hw/qxl.c                                 |   63 
 hw/qxl.h                                 |    6 
 hw/r2d.c                                 |  364 --
 hw/rc4030.c                              |    4 
 hw/realview.c                            |  404 --
 hw/realview_gic.c                        |    2 
 hw/rtl8139.c                             |    8 
 hw/s390x/css.c                           |   11 
 hw/s390x/event-facility.c                |    4 
 hw/s390x/s390-virtio-bus.c               |   58 
 hw/s390x/s390-virtio-bus.h               |   24 
 hw/s390x/s390-virtio-ccw.c               |    5 
 hw/s390x/s390-virtio.c                   |   14 
 hw/s390x/sclp.c                          |    2 
 hw/s390x/sclpconsole.c                   |    5 
 hw/s390x/sclpquiesce.c                   |    4 
 hw/s390x/virtio-ccw.c                    |  144 
 hw/s390x/virtio-ccw.h                    |   39 
 hw/sb16.c                                |    8 
 hw/sbi.c                                 |    2 
 hw/scsi-bus.c                            |   20 
 hw/scsi-disk.c                           |   40 
 hw/scsi-generic.c                        |    4 
 hw/scsi.h                                |    5 
 hw/sd.c                                  |    6 
 hw/sdhci.c                               | 1300 +++++++
 hw/sdhci.h                               |  312 +
 hw/serial-isa.c                          |    4 
 hw/serial-pci.c                          |    4 
 hw/serial.c                              |   34 
 hw/serial.h                              |    4 
 hw/sga.c                                 |    6 
 hw/sh.h                                  |    2 
 hw/sh4/Makefile.objs                     |    6 
 hw/sh4/r2d.c                             |  364 ++
 hw/sh4/sh7750.c                          |  842 ++++
 hw/sh4/sh7750_regnames.c                 |   97 
 hw/sh4/shix.c                            |  103 
 hw/sh7750.c                              |  838 ----
 hw/sh7750_regnames.c                     |   97 
 hw/sh_intc.c                             |   20 
 hw/sh_intc.h                             |    2 
 hw/sh_pci.c                              |   10 
 hw/sh_serial.c                           |    8 
 hw/sh_timer.c                            |    6 
 hw/shix.c                                |  103 
 hw/slavio_intctl.c                       |    4 
 hw/slavio_misc.c                         |    2 
 hw/slavio_timer.c                        |    6 
 hw/sm501.c                               |   58 
 hw/smbios.c                              |  241 -
 hw/smbus.c                               |    6 
 hw/smbus.h                               |    2 
 hw/smbus_eeprom.c                        |    6 
 hw/smbus_ich9.c                          |   14 
 hw/smc91c111.c                           |    4 
 hw/soc_dma.c                             |    2 
 hw/spapr.c                               |  963 -----
 hw/spapr_events.c                        |  321 -
 hw/spapr_hcall.c                         |  741 ----
 hw/spapr_iommu.c                         |  293 -
 hw/spapr_llan.c                          |   10 
 hw/spapr_pci.c                           |   42 
 hw/spapr_pci.h                           |    4 
 hw/spapr_rtas.c                          |  334 -
 hw/spapr_vio.c                           |  649 ---
 hw/spapr_vscsi.c                         |    8 
 hw/spapr_vty.c                           |    2 
 hw/sparc/Makefile.objs                   |    6 
 hw/sparc/leon3.c                         |  227 +
 hw/sparc/sun4m.c                         | 1944 ++++++++++
 hw/sparc32_dma.c                         |    8 
 hw/sparc64/Makefile.objs                 |    4 
 hw/sparc64/sun4u.c                       | 1020 +++++
 hw/spitz.c                               | 1138 ------
 hw/ssd0303.c                             |   19 
 hw/ssd0323.c                             |   21 
 hw/ssi-sd.c                              |    4 
 hw/ssi.c                                 |    2 
 hw/ssi.h                                 |    2 
 hw/stellaris.c                           | 1401 -------
 hw/stellaris_enet.c                      |    2 
 hw/stellaris_input.c                     |    4 
 hw/stream.c                              |    2 
 hw/strongarm.c                           |    8 
 hw/sun4c_intctl.c                        |    6 
 hw/sun4m.c                               | 1936 ----------
 hw/sun4m.h                               |    2 
 hw/sun4m_iommu.c                         |    4 
 hw/sun4u.c                               | 1014 -----
 hw/sysbus.c                              |   50 
 hw/sysbus.h                              |    9 
 hw/tc58128.c                             |    6 
 hw/tc6393xb.c                            |   44 
 hw/tc6393xb_template.h                   |    5 
 hw/tcx.c                                 |   68 
 hw/tmp105.c                              |    6 
 hw/tmp105.h                              |    4 
 hw/tosa.c                                |  302 -
 hw/tpci200.c                             |    4 
 hw/tsc2005.c                             |    4 
 hw/tsc210x.c                             |    6 
 hw/tusb6010.c                            |   10 
 hw/twl92230.c                            |    4 
 hw/unicore32/Makefile.objs               |    2 
 hw/unicore32/puv3.c                      |  137 
 hw/unin_pci.c                            |   12 
 hw/usb.h                                 |    2 
 hw/usb/dev-network.c                     |    1 
 hw/usb/dev-serial.c                      |    2 
 hw/usb/dev-storage.c                     |    2 
 hw/usb/hcd-xhci.c                        |    2 
 hw/usb/redirect.c                        |    4 
 hw/versatile_i2c.c                       |    4 
 hw/versatile_pci.c                       |    8 
 hw/versatilepb.c                         |  403 --
 hw/vexpress.c                            |  500 --
 hw/vfio_pci.c                            | 1180 ++++++
 hw/vga-isa-mm.c                          |   11 
 hw/vga-isa.c                             |   12 
 hw/vga-pci.c                             |   12 
 hw/vga.c                                 |  135 
 hw/vga_int.h                             |    2 
 hw/vhost.c                               |   51 
 hw/vhost_net.c                           |    6 
 hw/virtex_ml507.c                        |  274 -
 hw/virtio-balloon.c                      |  131 
 hw/virtio-balloon.h                      |   21 
 hw/virtio-blk.c                          |  157 
 hw/virtio-blk.h                          |   41 
 hw/virtio-bus.c                          |    8 
 hw/virtio-bus.h                          |    4 
 hw/virtio-console.c                      |   54 
 hw/virtio-net.c                          |   83 
 hw/virtio-net.h                          |   54 
 hw/virtio-pci.c                          |  474 +-
 hw/virtio-pci.h                          |   60 
 hw/virtio-rng.c                          |   26 
 hw/virtio-rng.h                          |   19 
 hw/virtio-scsi.c                         |  140 
 hw/virtio-scsi.h                         |   42 
 hw/virtio-serial-bus.c                   |   84 
 hw/virtio-serial.h                       |   51 
 hw/virtio.c                              |    4 
 hw/virtio.h                              |   12 
 hw/vmmouse.c                             |    8 
 hw/vmport.c                              |    8 
 hw/vmware_utils.h                        |  143 
 hw/vmware_vga.c                          |  115 
 hw/vmxnet3.c                             | 2461 +++++++++++++
 hw/vmxnet3.h                             |  760 ++++
 hw/vmxnet_debug.h                        |  115 
 hw/vmxnet_rx_pkt.c                       |  187 +
 hw/vmxnet_rx_pkt.h                       |  174 
 hw/vmxnet_tx_pkt.c                       |  567 +++
 hw/vmxnet_tx_pkt.h                       |  148 
 hw/vt82c686.c                            |   28 
 hw/wdt_i6300esb.c                        |    6 
 hw/wdt_ib700.c                           |    8 
 hw/wm8750.c                              |    4 
 hw/xen-host-pci-device.c                 |    2 
 hw/xen-host-pci-device.h                 |    2 
 hw/xen_apic.c                            |    2 
 hw/xen_backend.c                         |   19 
 hw/xen_backend.h                         |    4 
 hw/xen_common.h                          |    4 
 hw/xen_console.c                         |   22 
 hw/xen_devconfig.c                       |    2 
 hw/xen_disk.c                            |   84 
 hw/xen_domainbuild.c                     |  299 -
 hw/xen_domainbuild.h                     |    2 
 hw/xen_machine_pv.c                      |  126 
 hw/xen_nic.c                             |    4 
 hw/xen_platform.c                        |   12 
 hw/xen_pt.c                              |    8 
 hw/xen_pt.h                              |    6 
 hw/xen_pt_config_init.c                  |    4 
 hw/xen_pt_msi.c                          |    6 
 hw/xenfb.c                               |   61 
 hw/xgmac.c                               |    2 
 hw/xics.c                                |  588 ---
 hw/xics.h                                |    3 
 hw/xilinx.h                              |    3 
 hw/xilinx_axidma.c                       |    8 
 hw/xilinx_axienet.c                      |    7 
 hw/xilinx_ethlite.c                      |    4 
 hw/xilinx_intc.c                         |    4 
 hw/xilinx_spi.c                          |    6 
 hw/xilinx_spips.c                        |   72 
 hw/xilinx_timer.c                        |    4 
 hw/xilinx_uartlite.c                     |    2 
 hw/xilinx_zynq.c                         |  215 -
 hw/xio3130_downstream.c                  |   10 
 hw/xio3130_downstream.h                  |    2 
 hw/xio3130_upstream.c                    |   10 
 hw/xio3130_upstream.h                    |    2 
 hw/xtensa/Makefile.objs                  |    4 
 hw/xtensa/pic_cpu.c                      |  166 
 hw/xtensa/xtensa_lx60.c                  |  315 +
 hw/xtensa/xtensa_sim.c                   |  117 
 hw/xtensa_lx60.c                         |  315 -
 hw/xtensa_pic.c                          |  164 
 hw/xtensa_sim.c                          |  117 
 hw/z2.c                                  |  384 --
 hw/zaurus.c                              |    6 
 hw/zynq_slcr.c                           |    4 
 include/backends/tpm.h                   |  170 
 include/block/aio.h                      |    6 
 include/block/block.h                    |    7 
 include/block/block_int.h                |   20 
 include/block/coroutine.h                |    1 
 include/block/nbd.h                      |    4 
 include/block/thread-pool.h              |   15 
 include/char/char.h                      |   86 
 include/disas/bfd.h                      |    2 
 include/exec/cpu-all.h                   |   15 
 include/exec/cpu-defs.h                  |    2 
 include/exec/gen-icount.h                |   18 
 include/glib-compat.h                    |   27 
 include/migration/migration.h            |   14 
 include/migration/page_cache.h           |    3 
 include/migration/qemu-file.h            |   29 
 include/migration/vmstate.h              |  118 
 include/monitor/monitor.h                |    1 
 include/monitor/qdev.h                   |   15 
 include/net/checksum.h                   |   26 
 include/net/eth.h                        |  347 +
 include/net/net.h                        |    7 
 include/qapi/qmp/qdict.h                 |    2 
 include/qapi/qmp/qstring.h               |    1 
 include/qemu-common.h                    |   39 
 include/qemu/atomic.h                    |    1 
 include/qemu/compiler.h                  |    2 
 include/qemu/fifo8.h                     |   99 
 include/qemu/main-loop.h                 |    5 
 include/qemu/option.h                    |    1 
 include/qemu/osdep.h                     |    7 
 include/qemu/sockets.h                   |   10 
 include/qemu/timer.h                     |    3 
 include/qom/cpu.h                        |   66 
 include/qom/object.h                     |    2 
 include/sysemu/arch_init.h               |    4 
 include/sysemu/blockdev.h                |    2 
 include/sysemu/sysemu.h                  |    6 
 include/tpm/tpm.h                        |   25 
 include/ui/console.h                     |  278 -
 include/ui/qemu-spice.h                  |    7 
 include/ui/spice-display.h               |    9 
 kvm-all.c                                |    6 
 linux-headers/asm-arm/kvm.h              |  180 +
 linux-headers/asm-arm/kvm_para.h         |    1 
 linux-headers/asm-generic/kvm_para.h     |    4 
 linux-headers/linux/kvm.h                |   17 
 linux-headers/linux/vfio.h               |    9 
 linux-user/main.c                        |  125 
 linux-user/mips64/syscall.h              |   18 
 linux-user/mips64/syscall_nr.h           |  920 +++--
 linux-user/mipsn32/syscall.h             |  224 -
 linux-user/mipsn32/syscall_nr.h          |  311 -
 linux-user/mipsn32/target_signal.h       |   29 
 linux-user/mipsn32/termbits.h            |  245 -
 linux-user/signal.c                      |  245 -
 linux-user/socket.h                      |   69 
 linux-user/sparc/syscall_nr.h            |    2 
 linux-user/strace.c                      |  105 
 linux-user/syscall.c                     |  134 
 main-loop.c                              |   30 
 memory.c                                 |    2 
 migration-exec.c                         |   39 
 migration-fd.c                           |   47 
 migration-tcp.c                          |   33 
 migration-unix.c                         |   33 
 migration.c                              |  362 --
 monitor.c                                |  129 
 nbd.c                                    |   21 
 net/Makefile.objs                        |    1 
 net/checksum.c                           |   42 
 net/eth.c                                |  217 +
 net/hub.c                                |   14 
 net/hub.h                                |    1 
 net/net.c                                |   27 
 net/queue.c                              |   15 
 net/slirp.c                              |    1 
 net/socket.c                             |   41 
 net/tap-linux.c                          |   10 
 net/tap-linux.h                          |    9 
 net/tap.c                                |   14 
 net/vde.c                                |    2 
 page_cache.c                             |   25 
 pc-bios/bios.bin                         |binary
 pc-bios/efi-e1000.rom                    |binary
 pc-bios/efi-eepro100.rom                 |binary
 pc-bios/efi-ne2k_pci.rom                 |binary
 pc-bios/efi-pcnet.rom                    |binary
 pc-bios/efi-rtl8139.rom                  |binary
 pc-bios/efi-virtio.rom                   |binary
 po/Makefile                              |   16 
 po/de_DE.po                              |   41 
 po/fr_FR.po                              |   62 
 po/it.po                                 |   41 
 po/messages.po                           |   36 
 qapi-schema.json                         |  293 +
 qdev-monitor.c                           |  684 +++
 qemu-bridge-helper.c                     |   18 
 qemu-char.c                              | 1296 ++++---
 qemu-coroutine-lock.c                    |   55 
 qemu-doc.texi                            |   22 
 qemu-img.c                               |    6 
 qemu-io.c                                |    4 
 qemu-nbd.c                               |    2 
 qemu-options.hx                          |  119 
 qga/channel-win32.c                      |    2 
 qga/commands-posix.c                     |  270 +
 qga/commands-win32.c                     |   23 
 qga/guest-agent-core.h                   |    1 
 qga/main.c                               |  185 +
 qga/qapi-schema.json                     |  111 
 qga/service-win32.c                      |    2 
 qmp-commands.hx                          |  155 
 qobject/qdict.c                          |   22 
 qobject/qstring.c                        |    8 
 qom/cpu.c                                |    7 
 qom/object.c                             |   19 
 qtest.c                                  |    2 
 roms/Makefile                            |   49 
 roms/config.ipxe.general.h               |    2 
 roms/configure-seabios.sh                |    2 
 roms/ipxe                                |    2 
 roms/seabios                             |    2 
 savevm.c                                 |  351 +
 scripts/make_device_config.sh            |    4 
 scripts/tracetool.py                     |    4 
 scripts/tracetool/backend/__init__.py    |   16 
 scripts/tracetool/backend/dtrace.py      |    3 
 scripts/tracetool/backend/events.py      |   23 
 scripts/tracetool/backend/simple.py      |   22 
 scripts/tracetool/backend/stderr.py      |   28 
 scripts/tracetool/backend/ust.py         |    3 
 scripts/tracetool/format/events_c.py     |   39 
 scripts/tracetool/format/events_h.py     |   50 
 scripts/tracetool/format/h.py            |    9 
 slirp/misc.c                             |    6 
 slirp/socket.c                           |    4 
 slirp/tcp_subr.c                         |  145 
 slirp/udp.c                              |    2 
 spice-qemu-char.c                        |  112 
 stubs/Makefile.objs                      |    1 
 stubs/pci-drive-hot-add.c                |   10 
 stubs/vmstate.c                          |    2 
 target-alpha/cpu-qom.h                   |    3 
 target-alpha/cpu.c                       |    1 
 target-alpha/cpu.h                       |    5 
 target-alpha/helper.c                    |    4 
 target-alpha/translate.c                 |    7 
 target-arm/Makefile.objs                 |    1 
 target-arm/cpu-qom.h                     |    5 
 target-arm/cpu.c                         |   15 
 target-arm/cpu.h                         |    6 
 target-arm/helper.c                      |   36 
 target-arm/kvm.c                         |  493 ++
 target-arm/kvm_arm.h                     |   32 
 target-arm/op_helper.c                   |    4 
 target-arm/translate.c                   |  145 
 target-cris/cpu-qom.h                    |    3 
 target-cris/cpu.c                        |    1 
 target-cris/cpu.h                        |    5 
 target-cris/helper.c                     |  402 +-
 target-cris/translate.c                  |    7 
 target-i386/cpu-qom.h                    |   11 
 target-i386/cpu.c                        |   29 
 target-i386/cpu.h                        |   29 
 target-i386/fpu_helper.c                 |    1 
 target-i386/helper.c                     |   20 
 target-i386/kvm.c                        |   50 
 target-i386/machine.c                    |  215 -
 target-i386/misc_helper.c                |   21 
 target-i386/ops_sse.h                    |   64 
 target-i386/seg_helper.c                 |    5 
 target-i386/svm_helper.c                 |    9 
 target-i386/translate.c                  |   12 
 target-lm32/cpu-qom.h                    |    7 
 target-lm32/cpu.c                        |    7 
 target-lm32/cpu.h                        |   17 
 target-lm32/helper.c                     |   12 
 target-lm32/machine.c                    |   25 
 target-lm32/op_helper.c                  |   24 
 target-lm32/translate.c                  |   27 
 target-m68k/cpu-qom.h                    |    3 
 target-m68k/cpu.c                        |    1 
 target-m68k/cpu.h                        |    5 
 target-m68k/helper.c                     |   10 
 target-m68k/op_helper.c                  |   14 
 target-m68k/qregs.def                    |    1 
 target-m68k/translate.c                  |   12 
 target-microblaze/cpu-qom.h              |    3 
 target-microblaze/cpu.c                  |    1 
 target-microblaze/cpu.h                  |    5 
 target-microblaze/helper.c               |    9 
 target-microblaze/op_helper.c            |    2 
 target-microblaze/translate.c            |   21 
 target-mips/cpu-qom.h                    |    3 
 target-mips/cpu.c                        |    2 
 target-mips/cpu.h                        |    8 
 target-mips/dsp_helper.c                 |  129 
 target-mips/helper.c                     |    5 
 target-mips/op_helper.c                  |   23 
 target-mips/translate.c                  |  168 
 target-moxie/Makefile.objs               |    2 
 target-moxie/cpu.c                       |  173 
 target-moxie/cpu.h                       |  167 
 target-moxie/helper.c                    |  174 
 target-moxie/helper.h                    |    9 
 target-moxie/machine.c                   |   28 
 target-moxie/machine.h                   |    1 
 target-moxie/mmu.c                       |   36 
 target-moxie/mmu.h                       |   19 
 target-moxie/translate.c                 |  926 +++++
 target-openrisc/cpu.c                    |    1 
 target-openrisc/cpu.h                    |    8 
 target-openrisc/interrupt.c              |    4 
 target-openrisc/interrupt_helper.c       |    3 
 target-openrisc/sys_helper.c             |    3 
 target-openrisc/translate.c              |    4 
 target-ppc/Makefile.objs                 |    8 
 target-ppc/cpu-models.c                  | 1419 +++++++
 target-ppc/cpu-models.h                  |  741 ++++
 target-ppc/cpu-qom.h                     |   24 
 target-ppc/cpu.h                         |  123 
 target-ppc/excp_helper.c                 |   34 
 target-ppc/fpu_helper.c                  |    5 
 target-ppc/helper.h                      |    1 
 target-ppc/helper_regs.h                 |   11 
 target-ppc/kvm.c                         |  330 +
 target-ppc/machine.c                     |    4 
 target-ppc/mem_helper.c                  |   38 
 target-ppc/misc_helper.c                 |    6 
 target-ppc/mmu-hash32.c                  |  560 +++
 target-ppc/mmu-hash32.h                  |  102 
 target-ppc/mmu-hash64.c                  |  546 +++
 target-ppc/mmu-hash64.h                  |  124 
 target-ppc/mmu_helper.c                  |  835 ----
 target-ppc/translate.c                   |  233 -
 target-ppc/translate_init.c              | 5578 +++++++++----------------------
 target-ppc/user_only_helper.c            |   44 
 target-s390x/cpu-qom.h                   |    3 
 target-s390x/cpu.c                       |    9 
 target-s390x/cpu.h                       |   14 
 target-s390x/helper.c                    |   19 
 target-s390x/ioinst.c                    |    2 
 target-s390x/kvm.c                       |   12 
 target-s390x/translate.c                 |    7 
 target-sh4/cpu-qom.h                     |   16 
 target-sh4/cpu.c                         |  181 +
 target-sh4/cpu.h                         |    8 
 target-sh4/helper.c                      |   13 
 target-sh4/op_helper.c                   |    4 
 target-sh4/translate.c                   |   88 
 target-sparc/cpu-qom.h                   |    3 
 target-sparc/cpu.c                       |    2 
 target-sparc/cpu.h                       |    6 
 target-sparc/helper.c                    |    4 
 target-sparc/int32_helper.c              |    4 
 target-sparc/int64_helper.c              |    4 
 target-sparc/translate.c                 |    4 
 target-unicore32/cpu-qom.h               |    3 
 target-unicore32/cpu.c                   |    1 
 target-unicore32/cpu.h                   |    5 
 target-unicore32/helper.c                |    5 
 target-unicore32/softmmu.c               |    6 
 target-unicore32/translate.c             |    4 
 target-xtensa/cpu-qom.h                  |    3 
 target-xtensa/cpu.c                      |    1 
 target-xtensa/cpu.h                      |    1 
 target-xtensa/helper.c                   |    5 
 target-xtensa/op_helper.c                |    5 
 target-xtensa/translate.c                |    4 
 tcg/README                               |   14 
 tcg/mips/tcg-target.c                    |    6 
 tcg/mips/tcg-target.h                    |    2 
 tcg/optimize.c                           |   34 
 tcg/sparc/tcg-target.c                   |    2 
 tcg/tcg.h                                |   49 
 tests/qemu-iotests/007                   |    7 
 tests/qemu-iotests/038.out               |   10 
 tests/qemu-iotests/044.out               |    4 
 tests/qemu-iotests/046                   |   49 
 tests/qemu-iotests/046.out               |   76 
 tests/qemu-iotests/050                   |   75 
 tests/qemu-iotests/050.out               |   17 
 tests/qemu-iotests/052                   |   61 
 tests/qemu-iotests/052.out               |   13 
 tests/qemu-iotests/group                 |    2 
 tests/rtc-test.c                         |    4 
 tests/tcg/lm32/test_cmpgei.S             |   15 
 tests/tcg/lm32/test_cmpgeui.S            |   15 
 tests/tcg/lm32/test_cmpgi.S              |   15 
 tests/tcg/lm32/test_cmpgui.S             |   17 
 tests/tcg/mips/mips32-dsp/extr_r_w.c     |   23 
 tests/tcg/mips/mips32-dsp/extr_rs_w.c    |   46 
 tests/tcg/mips/mips32-dsp/extr_w.c       |   23 
 tests/tcg/mips/mips32-dsp/subq_s_ph.c    |   22 
 tests/tcg/mips/mips32-dsp/subq_s_w.c     |   36 
 tests/test-thread-pool.c                 |   44 
 tests/test-visitor-serialization.c       |   12 
 thread-pool.c                            |  243 -
 tpm/Makefile.objs                        |    6 
 tpm/tpm.c                                |  365 ++
 tpm/tpm_backend.c                        |   58 
 tpm/tpm_backend.h                        |   45 
 tpm/tpm_int.h                            |   95 
 tpm/tpm_passthrough.c                    |  560 +++
 tpm/tpm_tis.c                            |  930 +++++
 tpm/tpm_tis.h                            |   80 
 trace-events                             |   19 
 trace/Makefile.objs                      |   24 
 trace/control-internal.h                 |   67 
 trace/control.c                          |  106 
 trace/control.h                          |  190 -
 trace/default.c                          |    5 
 trace/event-internal.h                   |   33 
 trace/simple.c                           |   35 
 trace/simple.h                           |    6 
 trace/stderr.c                           |   34 
 trace/stderr.h                           |   11 
 translate-all.c                          |   95 
 ui/cocoa.m                               |   60 
 ui/console.c                             |  538 +-
 ui/curses.c                              |   28 
 ui/gtk.c                                 |  234 -
 ui/sdl.c                                 |  118 
 ui/spice-display.c                       |   81 
 ui/vnc-enc-tight.c                       |    7 
 ui/vnc-jobs.c                            |    1 
 ui/vnc.c                                 |  145 
 ui/vnc.h                                 |    4 
 util/Makefile.objs                       |    2 
 util/bitops.c                            |   18 
 util/cutils.c                            |   60 
 util/fifo8.c                             |   79 
 util/hexdump.c                           |   37 
 util/iov.c                               |   36 
 util/osdep.c                             |    8 
 util/oslib-posix.c                       |    6 
 util/oslib-win32.c                       |    4 
 util/qemu-config.c                       |    1 
 util/qemu-option.c                       |   34 
 util/qemu-sockets.c                      |   72 
 util/qemu-timer-common.c                 |    4 
 vl.c                                     |  137 
 xen-all.c                                |   10 
 xen-mapcache.c                           |   58 
 1081 files changed, 84275 insertions(+), 62622 deletions(-)

New commits:
commit 9196dd411d580c27f85daa209ff9a501d719ebc0
Merge: 893986f 32aea75
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Apr 6 12:53:54 2013 +0000

    Merge branch 'arm-devs.next' of git://git.linaro.org/people/pmaydell/qemu-arm
    
    * 'arm-devs.next' of git://git.linaro.org/people/pmaydell/qemu-arm:
      hw/nand.c: Fix nand erase operation
      cadence_uart: Flush queued characters on reset
      pl330: Don't inhibit ES bits on INTEN
      pflash_cfi01: Implement migration support
      pflash_cfi01: Drop unused 'bypass' field
      hw/arm_gic_common: Use vmstate struct rather than save/load functions
      arm_gic: Fix sizes of state fields in preparation for vmstate support
      vmstate: Add support for two dimensional arrays
      hw/onenand.c: fix migration of dynamically allocated buffer "otp"
      hw/sd.c: fix migration of dynamically allocated buffer "buf"
      vmstate.h: introduce VMSTATE_BUFFER_POINTER_UNSAFE macro
      hw/arm_mptimer: Save the timer state
      pl050: Don't send always-constant is_mouse field
      hw/arm/nseries: don't print to stdout or stderr

commit 893986fe94eb229f2317f50fac0e35e068eb66ba
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Apr 5 08:46:00 2013 -0500

    main-loop: drop the BQL if the I/O appears to be spinning
    
    The char-flow refactoring introduced a busy-wait that depended on
    an action from the VCPU thread.  However, the VCPU thread could
    never take that action because the busy-wait starved the VCPU thread
    of the BQL because it never dropped the mutex while running select.
    
    Paolo doesn't want to drop this optimization for fear that we will
    stop detecting these busy waits.  I'm afraid to keep this optimization
    even with the busy-wait fixed because I think a similar problem can
    occur just with heavy I/O thread load manifesting itself as VCPU pauses.
    
    As a compromise, introduce an artificial timeout after a thousand
    iterations but print a rate limited warning when this happens.  This
    let's us still detect when this condition occurs without it being
    a fatal error.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1365169560-11012-1-git-send-email-aliguori at us.ibm.com

diff --git a/main-loop.c b/main-loop.c
index eb80ff3..f46aece 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -188,14 +188,39 @@ static void glib_pollfds_poll(void)
     }
 }
 
+#define MAX_MAIN_LOOP_SPIN (1000)
+
 static int os_host_main_loop_wait(uint32_t timeout)
 {
     int ret;
+    static int spin_counter;
 
     glib_pollfds_fill(&timeout);
 
+    /* If the I/O thread is very busy or we are incorrectly busy waiting in
+     * the I/O thread, this can lead to starvation of the BQL such that the
+     * VCPU threads never run.  To make sure we can detect the later case,
+     * print a message to the screen.  If we run into this condition, create
+     * a fake timeout in order to give the VCPU threads a chance to run.
+     */
+    if (spin_counter > MAX_MAIN_LOOP_SPIN) {
+        static bool notified;
+
+        if (!notified) {
+            fprintf(stderr,
+                    "main-loop: WARNING: I/O thread spun for %d iterations\n",
+                    MAX_MAIN_LOOP_SPIN);
+            notified = true;
+        }
+
+        timeout = 1;
+    }
+
     if (timeout > 0) {
+        spin_counter = 0;
         qemu_mutex_unlock_iothread();
+    } else {
+        spin_counter++;
     }
 
     ret = g_poll((GPollFD *)gpollfds->data, gpollfds->len, timeout);
commit d185c094b404b4ff392b77d1244c0233da7d53bd
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Apr 5 17:59:33 2013 +0200

    qemu-char: eliminate busy waiting on can_read returning zero
    
    The character backend refactoring introduced an undesirable busy wait.
    The busy wait happens if can_read returns zero and there is data available
    on the character device's file descriptor.  Then, the I/O watch will
    fire continuously and, with TCG, the CPU thread will never run.
    
        1) Char backend asks front end if it can write
        2) Front end says no
        3) poll() finds the char backend's descriptor is available
        4) Goto (1)
    
    What we really want is this (note that step 3 avoids the busy wait):
    
        1) Char backend asks front end if it can write
        2) Front end says no
        3) poll() goes on without char backend's descriptor
        4) Goto (1) until qemu_chr_accept_input() called
    
        5) Char backend asks front end if it can write
        6) Front end says yes
        7) poll() finds the char backend's descriptor is available
        8) Backend handler called
    
    After this patch, the IOWatchPoll source and the watch source are
    separated.  The IOWatchPoll is simply a hook that runs during the prepare
    phase on each main loop iteration.  The hook adds/removes the actual
    source depending on the return value from can_read.
    
    A simple reproducer is
    
        qemu-system-i386 -serial mon:stdio
    
    ... followed by banging on the terminal as much as you can. :)  Without
    this patch, emulation will hang.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1365177573-11817-1-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index 0f7f32d..dd410ce 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -594,65 +594,51 @@ int recv_all(int fd, void *_buf, int len1, bool single_read)
 
 typedef struct IOWatchPoll
 {
+    GSource parent;
+
     GSource *src;
-    int max_size;
 
     IOCanReadHandler *fd_can_read;
     void *opaque;
-
-    QTAILQ_ENTRY(IOWatchPoll) node;
 } IOWatchPoll;
 
-static QTAILQ_HEAD(, IOWatchPoll) io_watch_poll_list =
-    QTAILQ_HEAD_INITIALIZER(io_watch_poll_list);
-
 static IOWatchPoll *io_watch_poll_from_source(GSource *source)
 {
-    IOWatchPoll *i;
-
-    QTAILQ_FOREACH(i, &io_watch_poll_list, node) {
-        if (i->src == source) {
-            return i;
-        }
-    }
-
-    return NULL;
+    return container_of(source, IOWatchPoll, parent);
 }
 
 static gboolean io_watch_poll_prepare(GSource *source, gint *timeout_)
 {
     IOWatchPoll *iwp = io_watch_poll_from_source(source);
-
-    iwp->max_size = iwp->fd_can_read(iwp->opaque);
-    if (iwp->max_size == 0) {
+    bool now_active = iwp->fd_can_read(iwp->opaque) > 0;
+    bool was_active = g_source_get_context(iwp->src) != NULL;
+    if (was_active == now_active) {
         return FALSE;
     }
 
-    return g_io_watch_funcs.prepare(source, timeout_);
+    if (now_active) {
+        g_source_attach(iwp->src, NULL);
+    } else {
+        g_source_remove(g_source_get_id(iwp->src));
+    }
+    return FALSE;
 }
 
 static gboolean io_watch_poll_check(GSource *source)
 {
-    IOWatchPoll *iwp = io_watch_poll_from_source(source);
-
-    if (iwp->max_size == 0) {
-        return FALSE;
-    }
-
-    return g_io_watch_funcs.check(source);
+    return FALSE;
 }
 
 static gboolean io_watch_poll_dispatch(GSource *source, GSourceFunc callback,
                                        gpointer user_data)
 {
-    return g_io_watch_funcs.dispatch(source, callback, user_data);
+    abort();
 }
 
 static void io_watch_poll_finalize(GSource *source)
 {
     IOWatchPoll *iwp = io_watch_poll_from_source(source);
-    QTAILQ_REMOVE(&io_watch_poll_list, iwp, node);
-    g_io_watch_funcs.finalize(source);
+    g_source_unref(iwp->src);
 }
 
 static GSourceFuncs io_watch_poll_funcs = {
@@ -669,24 +655,14 @@ static guint io_add_watch_poll(GIOChannel *channel,
                                gpointer user_data)
 {
     IOWatchPoll *iwp;
-    GSource *src;
-    guint tag;
-
-    src = g_io_create_watch(channel, G_IO_IN | G_IO_ERR | G_IO_HUP);
-    g_source_set_funcs(src, &io_watch_poll_funcs);
-    g_source_set_callback(src, (GSourceFunc)fd_read, user_data, NULL);
-    tag = g_source_attach(src, NULL);
-    g_source_unref(src);
 
-    iwp = g_malloc0(sizeof(*iwp));
-    iwp->src = src;
-    iwp->max_size = 0;
+    iwp = (IOWatchPoll *) g_source_new(&io_watch_poll_funcs, sizeof(IOWatchPoll));
     iwp->fd_can_read = fd_can_read;
     iwp->opaque = user_data;
+    iwp->src = g_io_create_watch(channel, G_IO_IN | G_IO_ERR | G_IO_HUP);
+    g_source_set_callback(iwp->src, (GSourceFunc)fd_read, user_data, NULL);
 
-    QTAILQ_INSERT_HEAD(&io_watch_poll_list, iwp, node);
-
-    return tag;
+    return g_source_attach(&iwp->parent, NULL);
 }
 
 #ifndef _WIN32
commit 91b53e4407ed8379d2d40f88a585e0b767681927
Merge: 54baa6f f1922e3
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Apr 5 12:52:48 2013 -0500

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging
    
    # By Peter Crosthwaite (2) and others
    # Via Stefan Hajnoczi
    * stefanha/trivial-patches:
      xilinx_zynq: Cleanup ssi_create_slave
      petalogix_ml605_mmu: Cleanup ssi_create_slave()
      target-s390: Fix SRNMT
      linux-user: Don't omit comma for strace of rt_sigaction()
      test-visitor-serialization: Fix some memory leaks

commit 54baa6f3c07a155939a6edda6d17706a6e9ab11c
Merge: 5098699 9246ce8
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Apr 5 12:52:32 2013 -0500

    Merge remote-tracking branch 'sstabellini/xen-2013-04-05' into staging
    
    # By Alex Bligh (2) and Felipe Franciosi (2)
    # Via Stefano Stabellini
    * sstabellini/xen-2013-04-05:
      Allow xen guests to plug disks of 1 TiB or more
      Introduce 64 bit integer write interface to xenstore
      Xen PV backend: Disable use of O_DIRECT by default as it results in crashes.
      Xen PV backend: Move call to bdrv_new from blk_init to blk_connect

commit 5098699a51756f7e8934dc035112c8f8aa2a0ec3
Merge: 150a470 c2b6ff5
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Apr 5 12:49:10 2013 -0500

    Merge remote-tracking branch 'kwolf/for-anthony' into staging
    
    # By Stefan Hajnoczi (4) and Kevin Wolf (3)
    # Via Kevin Wolf
    * kwolf/for-anthony:
      qcow2: Fix L1 write error handling in qcow2_update_snapshot_refcount
      qcow2: Return real error in qcow2_update_snapshot_refcount
      block: clean up I/O throttling wait_time code
      block: drop duplicated slice extension code
      block: keep I/O throttling slice time constant
      block: fix I/O throttling accounting blind spot
      usb-storage: Forward serial number to scsi-disk

commit c2b6ff51e4a3ad1f7ec5dbc94970e9778b31d718
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Apr 5 12:57:10 2013 +0200

    qcow2: Fix L1 write error handling in qcow2_update_snapshot_refcount
    
    It ignored the error code, and at least the 'goto fail' is obvious
    nonsense as it creates an endless loop (if the next attempt doesn't
    magically succeed) and leaves the in-memory L1 table in big-endian
    instead of converting it back.
    
    In error cases, there's no point in writing an updated L1 table, so
    skip this part for them.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 4799681..b32738f 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -851,14 +851,16 @@ fail:
     }
 
     /* Update L1 only if it isn't deleted anyway (addend = -1) */
-    if (addend >= 0 && l1_modified) {
-        for(i = 0; i < l1_size; i++)
+    if (ret == 0 && addend >= 0 && l1_modified) {
+        for (i = 0; i < l1_size; i++) {
             cpu_to_be64s(&l1_table[i]);
-        if (bdrv_pwrite_sync(bs->file, l1_table_offset, l1_table,
-                        l1_size2) < 0)
-            goto fail;
-        for(i = 0; i < l1_size; i++)
+        }
+
+        ret = bdrv_pwrite_sync(bs->file, l1_table_offset, l1_table, l1_size2);
+
+        for (i = 0; i < l1_size; i++) {
             be64_to_cpus(&l1_table[i]);
+        }
     }
     if (l1_allocated)
         g_free(l1_table);
commit c2bc78b6a975ea2dcd7eee9f0dce22cc060cdcdc
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Apr 5 12:51:31 2013 +0200

    qcow2: Return real error in qcow2_update_snapshot_refcount
    
    This fixes the error message triggered by the following script:
    
        cat > /tmp/blkdebug.cfg <<EOF
        [inject-error]
        event = "cluster_free"
        errno = "28"
        immediately = "off"
        EOF
    
        $qemu_img create -f qcow2 test.qcow2 10G
        $qemu_img snapshot -c snap test.qcow2
        $qemu_img snapshot -d snap blkdebug:/tmp/blkdebug.cfg:test.qcow2
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index c38e970..4799681 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -747,10 +747,9 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
     if (l1_table_offset != s->l1_table_offset) {
         l1_table = g_malloc0(align_offset(l1_size2, 512));
         l1_allocated = 1;
-        if (bdrv_pread(bs->file, l1_table_offset,
-                       l1_table, l1_size2) != l1_size2)
-        {
-            ret = -EIO;
+
+        ret = bdrv_pread(bs->file, l1_table_offset, l1_table, l1_size2);
+        if (ret < 0) {
             goto fail;
         }
 
@@ -802,7 +801,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
                         }
 
                         if (refcount < 0) {
-                            ret = -EIO;
+                            ret = refcount;
                             goto fail;
                         }
                     }
@@ -833,7 +832,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
                 refcount = get_refcount(bs, l2_offset >> s->cluster_bits);
             }
             if (refcount < 0) {
-                ret = -EIO;
+                ret = refcount;
                 goto fail;
             } else if (refcount == 1) {
                 l2_offset |= QCOW_OFLAG_COPIED;
commit 0775437fafc5c733564645a22f75490770bf41f7
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Apr 5 11:32:22 2013 +0200

    block: clean up I/O throttling wait_time code
    
    The wait_time variable is in seconds.  Reflect this in a comment and use
    NANOSECONDS_PER_SECOND instead of BLOCK_IO_SLICE_TIME * 10 (which
    happens to have the right value).
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Tested-By: Benoit Canet <benoit at irqsave.net>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index aa16fc4..602d8a4 100644
--- a/block.c
+++ b/block.c
@@ -3800,7 +3800,7 @@ static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors,
                 BLOCK_IO_SLICE_TIME;
     bs->slice_end += extension;
     if (wait) {
-        *wait = wait_time * BLOCK_IO_SLICE_TIME * 10;
+        *wait = wait_time * NANOSECONDS_PER_SECOND;
     }
 
     return true;
@@ -3841,7 +3841,7 @@ static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write,
         return false;
     }
 
-    /* Calc approx time to dispatch */
+    /* Calc approx time to dispatch, in seconds */
     wait_time = (ios_base + 1) / iops_limit;
     if (wait_time > elapsed_time) {
         wait_time = wait_time - elapsed_time;
@@ -3852,7 +3852,7 @@ static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write,
     /* Exceeded current slice, extend it by another slice time */
     bs->slice_end += BLOCK_IO_SLICE_TIME;
     if (wait) {
-        *wait = wait_time * BLOCK_IO_SLICE_TIME * 10;
+        *wait = wait_time * NANOSECONDS_PER_SECOND;
     }
 
     return true;
commit e660fb8b3ccc94652774d5895d122c0f13aecb89
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Apr 5 11:32:21 2013 +0200

    block: drop duplicated slice extension code
    
    The current slice is extended when an I/O request exceeds the limit.
    There is no need to extend the slice every time we check a request.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Tested-By: Benoit Canet <benoit at irqsave.net>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 00eca27..aa16fc4 100644
--- a/block.c
+++ b/block.c
@@ -3867,10 +3867,7 @@ static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors,
     int      bps_ret, iops_ret;
 
     now = qemu_get_clock_ns(vm_clock);
-    if ((bs->slice_start < now)
-        && (bs->slice_end > now)) {
-        bs->slice_end = now + BLOCK_IO_SLICE_TIME;
-    } else {
+    if (now > bs->slice_end) {
         bs->slice_start = now;
         bs->slice_end   = now + BLOCK_IO_SLICE_TIME;
         memset(&bs->slice_submitted, 0, sizeof(bs->slice_submitted));
commit ae29d6c64bd8d55873a2cb1df50ae4321b497447
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Apr 5 11:32:20 2013 +0200

    block: keep I/O throttling slice time constant
    
    It is not necessary to adjust the slice time at runtime.  We already
    extend the current slice in order to carry over accounting into the next
    slice.  Changing the actual slice time value introduces oscillations.
    
    The guest may experience large changes in throughput or IOPS from one
    moment to the next when slice times are adjusted.
    
    Reported-by: Benoît Canet <benoit at irqsave.net>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Tested-By: Benoit Canet <benoit at irqsave.net>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 25976b5..00eca27 100644
--- a/block.c
+++ b/block.c
@@ -140,7 +140,6 @@ void bdrv_io_limits_disable(BlockDriverState *bs)
 
     bs->slice_start = 0;
     bs->slice_end   = 0;
-    bs->slice_time  = 0;
 }
 
 static void bdrv_block_timer(void *opaque)
@@ -1432,7 +1431,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
     bs_dest->enable_write_cache = bs_src->enable_write_cache;
 
     /* i/o timing parameters */
-    bs_dest->slice_time         = bs_src->slice_time;
     bs_dest->slice_start        = bs_src->slice_start;
     bs_dest->slice_end          = bs_src->slice_end;
     bs_dest->slice_submitted    = bs_src->slice_submitted;
@@ -3749,6 +3747,7 @@ static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors,
                  bool is_write, double elapsed_time, uint64_t *wait)
 {
     uint64_t bps_limit = 0;
+    uint64_t extension;
     double   bytes_limit, bytes_base, bytes_res;
     double   slice_time, wait_time;
 
@@ -3796,8 +3795,10 @@ static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors,
      * info can be kept until the timer fire, so it is increased and tuned
      * based on the result of experiment.
      */
-    bs->slice_time = wait_time * BLOCK_IO_SLICE_TIME * 10;
-    bs->slice_end += bs->slice_time - 3 * BLOCK_IO_SLICE_TIME;
+    extension = wait_time * NANOSECONDS_PER_SECOND;
+    extension = DIV_ROUND_UP(extension, BLOCK_IO_SLICE_TIME) *
+                BLOCK_IO_SLICE_TIME;
+    bs->slice_end += extension;
     if (wait) {
         *wait = wait_time * BLOCK_IO_SLICE_TIME * 10;
     }
@@ -3848,8 +3849,8 @@ static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write,
         wait_time = 0;
     }
 
-    bs->slice_time = wait_time * BLOCK_IO_SLICE_TIME * 10;
-    bs->slice_end += bs->slice_time - 3 * BLOCK_IO_SLICE_TIME;
+    /* Exceeded current slice, extend it by another slice time */
+    bs->slice_end += BLOCK_IO_SLICE_TIME;
     if (wait) {
         *wait = wait_time * BLOCK_IO_SLICE_TIME * 10;
     }
@@ -3868,12 +3869,10 @@ static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors,
     now = qemu_get_clock_ns(vm_clock);
     if ((bs->slice_start < now)
         && (bs->slice_end > now)) {
-        bs->slice_end = now + bs->slice_time;
+        bs->slice_end = now + BLOCK_IO_SLICE_TIME;
     } else {
-        bs->slice_time  =  5 * BLOCK_IO_SLICE_TIME;
         bs->slice_start = now;
-        bs->slice_end   = now + bs->slice_time;
-
+        bs->slice_end   = now + BLOCK_IO_SLICE_TIME;
         memset(&bs->slice_submitted, 0, sizeof(bs->slice_submitted));
     }
 
diff --git a/blockdev.c b/blockdev.c
index 8cdc9ce..6dc999d 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1069,7 +1069,6 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
     }
 
     bs->io_limits = io_limits;
-    bs->slice_time = BLOCK_IO_SLICE_TIME;
 
     if (!bs->io_limits_enabled && bdrv_io_limits_enabled(bs)) {
         bdrv_io_limits_enable(bs);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 83941d8..9aa98b5 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -252,7 +252,6 @@ struct BlockDriverState {
     unsigned int copy_on_read_in_flight;
 
     /* the time for latest disk I/O */
-    int64_t slice_time;
     int64_t slice_start;
     int64_t slice_end;
     BlockIOLimit io_limits;
commit 5905fbc9c94ccd744c1b249472eafcc2d827548a
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Apr 5 11:32:19 2013 +0200

    block: fix I/O throttling accounting blind spot
    
    I/O throttling relies on bdrv_acct_done() which is called when a request
    completes.  This leaves a blind spot since we only charge for completed
    requests, not submitted requests.
    
    For example, if there is 1 operation remaining in this time slice the
    guest could submit 3 operations and they will all be submitted
    successfully since they don't actually get accounted for until they
    complete.
    
    Originally we probably thought this is okay since the requests will be
    accounted when the time slice is extended.  In practice it causes
    fluctuations since the guest can exceed its I/O limit and it will be
    punished for this later on.
    
    Account for I/O upon submission so that I/O limits are enforced
    properly.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Tested-By: Benoit Canet <benoit at irqsave.net>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 0ae2e93..25976b5 100644
--- a/block.c
+++ b/block.c
@@ -141,7 +141,6 @@ void bdrv_io_limits_disable(BlockDriverState *bs)
     bs->slice_start = 0;
     bs->slice_end   = 0;
     bs->slice_time  = 0;
-    memset(&bs->io_base, 0, sizeof(bs->io_base));
 }
 
 static void bdrv_block_timer(void *opaque)
@@ -1436,8 +1435,8 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
     bs_dest->slice_time         = bs_src->slice_time;
     bs_dest->slice_start        = bs_src->slice_start;
     bs_dest->slice_end          = bs_src->slice_end;
+    bs_dest->slice_submitted    = bs_src->slice_submitted;
     bs_dest->io_limits          = bs_src->io_limits;
-    bs_dest->io_base            = bs_src->io_base;
     bs_dest->throttled_reqs     = bs_src->throttled_reqs;
     bs_dest->block_timer        = bs_src->block_timer;
     bs_dest->io_limits_enabled  = bs_src->io_limits_enabled;
@@ -3768,9 +3767,9 @@ static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors,
     slice_time = bs->slice_end - bs->slice_start;
     slice_time /= (NANOSECONDS_PER_SECOND);
     bytes_limit = bps_limit * slice_time;
-    bytes_base  = bs->nr_bytes[is_write] - bs->io_base.bytes[is_write];
+    bytes_base  = bs->slice_submitted.bytes[is_write];
     if (bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL]) {
-        bytes_base += bs->nr_bytes[!is_write] - bs->io_base.bytes[!is_write];
+        bytes_base += bs->slice_submitted.bytes[!is_write];
     }
 
     /* bytes_base: the bytes of data which have been read/written; and
@@ -3828,9 +3827,9 @@ static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write,
     slice_time = bs->slice_end - bs->slice_start;
     slice_time /= (NANOSECONDS_PER_SECOND);
     ios_limit  = iops_limit * slice_time;
-    ios_base   = bs->nr_ops[is_write] - bs->io_base.ios[is_write];
+    ios_base   = bs->slice_submitted.ios[is_write];
     if (bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL]) {
-        ios_base += bs->nr_ops[!is_write] - bs->io_base.ios[!is_write];
+        ios_base += bs->slice_submitted.ios[!is_write];
     }
 
     if (ios_base + 1 <= ios_limit) {
@@ -3875,11 +3874,7 @@ static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors,
         bs->slice_start = now;
         bs->slice_end   = now + bs->slice_time;
 
-        bs->io_base.bytes[is_write]  = bs->nr_bytes[is_write];
-        bs->io_base.bytes[!is_write] = bs->nr_bytes[!is_write];
-
-        bs->io_base.ios[is_write]    = bs->nr_ops[is_write];
-        bs->io_base.ios[!is_write]   = bs->nr_ops[!is_write];
+        memset(&bs->slice_submitted, 0, sizeof(bs->slice_submitted));
     }
 
     elapsed_time  = now - bs->slice_start;
@@ -3907,6 +3902,10 @@ static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors,
         *wait = 0;
     }
 
+    bs->slice_submitted.bytes[is_write] += (int64_t)nb_sectors *
+                                           BDRV_SECTOR_SIZE;
+    bs->slice_submitted.ios[is_write]++;
+
     return false;
 }
 
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 0986a2d..83941d8 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -256,7 +256,7 @@ struct BlockDriverState {
     int64_t slice_start;
     int64_t slice_end;
     BlockIOLimit io_limits;
-    BlockIOBaseValue  io_base;
+    BlockIOBaseValue slice_submitted;
     CoQueue      throttled_reqs;
     QEMUTimer    *block_timer;
     bool         io_limits_enabled;
commit 76534da749ceb3b4c13ec09b173bcf6d6c2e36d4
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Apr 3 12:41:46 2013 +0200

    usb-storage: Forward serial number to scsi-disk
    
    usb-storage takes care to fetch the USB serial number from -drive
    options, but it neglected to pass its own 'serial' property to the
    scsi-disk it creates. With this patch, the 'serial' qdev property and
    the 'serial' option in -drive behave the same and correctly apply the
    serial number on both USB and SCSI level.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/pci/pci-hotplug.c b/hw/pci/pci-hotplug.c
index f38df30..180ee07 100644
--- a/hw/pci/pci-hotplug.c
+++ b/hw/pci/pci-hotplug.c
@@ -99,7 +99,7 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
     dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
     dinfo->bus = scsibus->busnr;
     scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit,
-                                        false, -1);
+                                        false, -1, NULL);
     if (!scsidev) {
         return -1;
     }
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 08787c2..ac2093a 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -207,7 +207,8 @@ static int scsi_qdev_exit(DeviceState *qdev)
 
 /* handle legacy '-drive if=scsi,...' cmd line args */
 SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
-                                      int unit, bool removable, int bootindex)
+                                      int unit, bool removable, int bootindex,
+                                      const char *serial)
 {
     const char *driver;
     DeviceState *dev;
@@ -221,6 +222,9 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
     if (object_property_find(OBJECT(dev), "removable", NULL)) {
         qdev_prop_set_bit(dev, "removable", removable);
     }
+    if (serial) {
+        qdev_prop_set_string(dev, "serial", serial);
+    }
     if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) {
         qdev_free(dev);
         return NULL;
@@ -243,7 +247,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
             continue;
         }
         qemu_opts_loc_restore(dinfo->opts);
-        if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1)) {
+        if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1, NULL)) {
             res = -1;
             break;
         }
diff --git a/hw/scsi.h b/hw/scsi.h
index 33e2e0b..02a1497 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -160,7 +160,8 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
 }
 
 SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
-                                      int unit, bool removable, int bootindex);
+                                      int unit, bool removable, int bootindex,
+                                      const char *serial);
 int scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
 
 /*
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index d3f01aa..21651b3 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -625,7 +625,7 @@ static int usb_msd_initfn_storage(USBDevice *dev)
     usb_desc_init(dev);
     scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info_storage);
     scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable,
-                                            s->conf.bootindex);
+                                            s->conf.bootindex, s->serial);
     if (!scsi_dev) {
         return -1;
     }
commit 32aea752f47f30c00878dcc323ac4debf0c9e645
Author: Wendy Liang <wendy.liang at xilinx.com>
Date:   Wed Apr 3 15:33:08 2013 +1000

    hw/nand.c: Fix nand erase operation
    
    Usually, nand erase operation has only 2 or 3 address cycles.
    We need to mask s->addr to zero unset stale high-order bytes in the nand address
    before using it as the erase address.
    
    This fixes the NAND erase operation in Linux.
    
    [PC: Generalised to work for any number of address cycles rather than just 3]
    
    Signed-off-by: Wendy Liang <jliang at xilinx.com>
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 1364967188-26711-1-git-send-email-peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/nand.c b/hw/nand.c
index de3e502..6362093 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -297,6 +297,7 @@ static void nand_command(NANDFlashState *s)
         break;
 
     case NAND_CMD_BLOCKERASE2:
+        s->addr &= (1ull << s->addrlen * 8) - 1;
         if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP)
             s->addr <<= 16;
         else
commit 1db8b5efe0c2b5000e50691eea61264a615f43de
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Wed Apr 3 14:52:21 2013 +1000

    cadence_uart: Flush queued characters on reset
    
    Reset can be used to empty the rx-fifo. As the fifo full condition is
    used to return false from can_receive, queued rx data should be flushed
    on reset accordingly.
    
    Cc: Wendy Liang <jliang at xilinx.com>
    Cc: Jason Wu <huanyu at xilinx.com>
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Reported-by: Jason Wu <huanyu at xilinx.com>
    Message-id: 494c1e005e225c915d295ddfd75d992ad2dabc3c.1364964526.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c
index 5426f10..421ec99 100644
--- a/hw/cadence_uart.c
+++ b/hw/cadence_uart.c
@@ -157,6 +157,7 @@ static void uart_rx_reset(UartState *s)
 {
     s->rx_wpos = 0;
     s->rx_count = 0;
+    qemu_chr_accept_input(s->chr);
 
     s->r[R_SR] |= UART_SR_INTR_REMPTY;
     s->r[R_SR] &= ~UART_SR_INTR_RFUL;
commit fd7f8a99f3b08640a7fe2b2f3c3e6b68068b4983
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Tue Apr 2 17:59:29 2013 +0000

    pl330: Don't inhibit ES bits on INTEN
    
    This if-else logic inhibits setting of the event status (ES) bits
    when interrupts are enabled. This is incorrect. ES should be set
    regardless on INTEN state. INTEN only inhibits the signalling of
    events to PL330 threads, not setting of the ES register.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/pl330.c b/hw/pl330.c
index 1a04773..60aa4a8 100644
--- a/hw/pl330.c
+++ b/hw/pl330.c
@@ -870,9 +870,8 @@ static void pl330_dmasev(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
         ch->parent->int_status |= (1 << ev_id);
         DB_PRINT("event interrupt raised %d\n", ev_id);
         qemu_irq_raise(ch->parent->irq[ev_id]);
-    } else {
-        ch->parent->ev_status |= (1 << ev_id);
     }
+    ch->parent->ev_status |= (1 << ev_id);
 }
 
 static void pl330_dmast(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
commit 9246ce881128df2a69178779c1ef33c83df3c70d
Author: Felipe Franciosi <felipe.franciosi at citrix.com>
Date:   Fri Apr 5 15:47:59 2013 +0000

    Allow xen guests to plug disks of 1 TiB or more
    
    The current xen backend driver implementation uses int64_t variables
    to store the size of the corresponding backend disk/file. It also uses
    an int64_t variable to store the block size of that image. When writing
    the number of sectors (file_size/block_size) to xenstore, however, it
    passes these values as 32 bit signed integers. This will cause an
    overflow for any disk of 1 TiB or more.
    
    This patch changes the xen backend driver to use a 64 bit integer write
    xenstore function.
    
    Signed-off-by: Felipe Franciosi <felipe at paradoxo.org>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 1a30f0a..47a51cf 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -825,8 +825,8 @@ static int blk_connect(struct XenDevice *xendev)
 
     /* Fill in number of sector size and number of sectors */
     xenstore_write_be_int(&blkdev->xendev, "sector-size", blkdev->file_blk);
-    xenstore_write_be_int(&blkdev->xendev, "sectors",
-                          blkdev->file_size / blkdev->file_blk);
+    xenstore_write_be_int64(&blkdev->xendev, "sectors",
+                            blkdev->file_size / blkdev->file_blk);
 
     if (xenstore_read_fe_int(&blkdev->xendev, "ring-ref", &blkdev->ring_ref) == -1) {
         return -1;
commit 10bb3c623478117aee5117c312736f10833decc2
Author: Felipe Franciosi <felipe.franciosi at citrix.com>
Date:   Fri Apr 5 15:37:32 2013 +0000

    Introduce 64 bit integer write interface to xenstore
    
    The current implementation of xen_backend only provides 32 bit integer
    functions to write to xenstore. This patch adds two functions that
    allow writing 64 bit integers (one generic function and another for
    the backend only).
    
    This patch also fixes the size of the char arrays used to represent
    these integers as strings (originally 32 bytes, however no more than
    12 bytes are needed for 32 bit integers and no more than 21 bytes are
    needed for 64 bit integers).
    
    Signed-off-by: Felipe Franciosi <felipe at paradoxo.org>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/xen_backend.c b/hw/xen_backend.c
index 24381b5..02693d7 100644
--- a/hw/xen_backend.c
+++ b/hw/xen_backend.c
@@ -85,12 +85,20 @@ char *xenstore_read_str(const char *base, const char *node)
 
 int xenstore_write_int(const char *base, const char *node, int ival)
 {
-    char val[32];
+    char val[12];
 
     snprintf(val, sizeof(val), "%d", ival);
     return xenstore_write_str(base, node, val);
 }
 
+int xenstore_write_int64(const char *base, const char *node, int64_t ival)
+{
+    char val[21];
+
+    snprintf(val, sizeof(val), "%"PRId64, ival);
+    return xenstore_write_str(base, node, val);
+}
+
 int xenstore_read_int(const char *base, const char *node, int *ival)
 {
     char *val;
@@ -114,6 +122,11 @@ int xenstore_write_be_int(struct XenDevice *xendev, const char *node, int ival)
     return xenstore_write_int(xendev->be, node, ival);
 }
 
+int xenstore_write_be_int64(struct XenDevice *xendev, const char *node, int64_t ival)
+{
+    return xenstore_write_int64(xendev->be, node, ival);
+}
+
 char *xenstore_read_be_str(struct XenDevice *xendev, const char *node)
 {
     return xenstore_read_str(xendev->be, node);
diff --git a/hw/xen_backend.h b/hw/xen_backend.h
index 6d5c699..d04b985 100644
--- a/hw/xen_backend.h
+++ b/hw/xen_backend.h
@@ -63,11 +63,13 @@ extern const char *xen_protocol;
 /* xenstore helper functions */
 int xenstore_write_str(const char *base, const char *node, const char *val);
 int xenstore_write_int(const char *base, const char *node, int ival);
+int xenstore_write_int64(const char *base, const char *node, int64_t ival);
 char *xenstore_read_str(const char *base, const char *node);
 int xenstore_read_int(const char *base, const char *node, int *ival);
 
 int xenstore_write_be_str(struct XenDevice *xendev, const char *node, const char *val);
 int xenstore_write_be_int(struct XenDevice *xendev, const char *node, int ival);
+int xenstore_write_be_int64(struct XenDevice *xendev, const char *node, int64_t ival);
 char *xenstore_read_be_str(struct XenDevice *xendev, const char *node);
 int xenstore_read_be_int(struct XenDevice *xendev, const char *node, int *ival);
 char *xenstore_read_fe_str(struct XenDevice *xendev, const char *node);
commit c1a88ad1f4ac994cd70695bf08141d161e21533e
Author: Alex Bligh <alex at alex.org.uk>
Date:   Fri Apr 5 15:45:15 2013 +0000

    Xen PV backend: Disable use of O_DIRECT by default as it results in crashes.
    
    Due to what is almost certainly a kernel bug, writes with O_DIRECT may
    continue to reference the page after the write has been marked as
    completed, particularly in the case of TCP retransmit. In other
    scenarios, this "merely" risks data corruption on the write, but with
    Xen pages from domU are only transiently mapped into dom0's memory,
    resulting in kernel panics when they are subsequently accessed.
    
    This brings PV devices in line with emulated devices.  Removing
    O_DIRECT is safe as barrier operations are now correctly passed
    through.
    
    See:
       http://lists.xen.org/archives/html/xen-devel/2012-12/msg01154.html
    for more details.
    
    Signed-off-by: Alex Bligh <alex at alex.org.uk>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 24e8b24..1a30f0a 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -782,7 +782,7 @@ static int blk_connect(struct XenDevice *xendev)
     int pers, index, qflags;
 
     /* read-only ? */
-    qflags = BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NATIVE_AIO;
+    qflags = BDRV_O_CACHE_WB | BDRV_O_NATIVE_AIO;
     if (strcmp(blkdev->mode, "w") == 0) {
         qflags |= BDRV_O_RDWR;
     }
commit 86f425db3b1c4b6c4a2927eaec35627f9ab2e703
Author: Alex Bligh <alex at alex.org.uk>
Date:   Fri Apr 5 15:45:10 2013 +0000

    Xen PV backend: Move call to bdrv_new from blk_init to blk_connect
    
    This commit delays the point at which bdrv_new (and hence blk_open
    on the underlying device) is called from blk_init to blk_connect.
    This ensures that in an inbound live migrate, the block device is
    not opened until it has been closed at the other end. This is in
    preparation for supporting devices with open/close consistency
    without using O_DIRECT. This commit does NOT itself change O_DIRECT
    semantics.
    
    Signed-off-by: Alex Bligh <alex at alex.org.uk>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 83329e2..24e8b24 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -700,7 +700,7 @@ static void blk_alloc(struct XenDevice *xendev)
 static int blk_init(struct XenDevice *xendev)
 {
     struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
-    int index, qflags, info = 0;
+    int info = 0;
 
     /* read xenstore entries */
     if (blkdev->params == NULL) {
@@ -743,10 +743,7 @@ static int blk_init(struct XenDevice *xendev)
     }
 
     /* read-only ? */
-    qflags = BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NATIVE_AIO;
-    if (strcmp(blkdev->mode, "w") == 0) {
-        qflags |= BDRV_O_RDWR;
-    } else {
+    if (strcmp(blkdev->mode, "w")) {
         info  |= VDISK_READONLY;
     }
 
@@ -755,6 +752,41 @@ static int blk_init(struct XenDevice *xendev)
         info  |= VDISK_CDROM;
     }
 
+    blkdev->file_blk  = BLOCK_SIZE;
+
+    /* fill info
+     * blk_connect supplies sector-size and sectors
+     */
+    xenstore_write_be_int(&blkdev->xendev, "feature-flush-cache", 1);
+    xenstore_write_be_int(&blkdev->xendev, "feature-persistent", 1);
+    xenstore_write_be_int(&blkdev->xendev, "info", info);
+    return 0;
+
+out_error:
+    g_free(blkdev->params);
+    blkdev->params = NULL;
+    g_free(blkdev->mode);
+    blkdev->mode = NULL;
+    g_free(blkdev->type);
+    blkdev->type = NULL;
+    g_free(blkdev->dev);
+    blkdev->dev = NULL;
+    g_free(blkdev->devtype);
+    blkdev->devtype = NULL;
+    return -1;
+}
+
+static int blk_connect(struct XenDevice *xendev)
+{
+    struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
+    int pers, index, qflags;
+
+    /* read-only ? */
+    qflags = BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NATIVE_AIO;
+    if (strcmp(blkdev->mode, "w") == 0) {
+        qflags |= BDRV_O_RDWR;
+    }
+
     /* init qemu block driver */
     index = (blkdev->xendev.dev - 202 * 256) / 16;
     blkdev->dinfo = drive_get(IF_XEN, 0, index);
@@ -770,7 +802,7 @@ static int blk_init(struct XenDevice *xendev)
             }
         }
         if (!blkdev->bs) {
-            goto out_error;
+            return -1;
         }
     } else {
         /* setup via qemu cmdline -> already setup for us */
@@ -778,7 +810,6 @@ static int blk_init(struct XenDevice *xendev)
         blkdev->bs = blkdev->dinfo->bdrv;
     }
     bdrv_attach_dev_nofail(blkdev->bs, blkdev);
-    blkdev->file_blk  = BLOCK_SIZE;
     blkdev->file_size = bdrv_getlength(blkdev->bs);
     if (blkdev->file_size < 0) {
         xen_be_printf(&blkdev->xendev, 1, "bdrv_getlength: %d (%s) | drv %s\n",
@@ -792,33 +823,10 @@ static int blk_init(struct XenDevice *xendev)
                   blkdev->type, blkdev->fileproto, blkdev->filename,
                   blkdev->file_size, blkdev->file_size >> 20);
 
-    /* fill info */
-    xenstore_write_be_int(&blkdev->xendev, "feature-flush-cache", 1);
-    xenstore_write_be_int(&blkdev->xendev, "feature-persistent", 1);
-    xenstore_write_be_int(&blkdev->xendev, "info",            info);
-    xenstore_write_be_int(&blkdev->xendev, "sector-size",     blkdev->file_blk);
+    /* Fill in number of sector size and number of sectors */
+    xenstore_write_be_int(&blkdev->xendev, "sector-size", blkdev->file_blk);
     xenstore_write_be_int(&blkdev->xendev, "sectors",
                           blkdev->file_size / blkdev->file_blk);
-    return 0;
-
-out_error:
-    g_free(blkdev->params);
-    blkdev->params = NULL;
-    g_free(blkdev->mode);
-    blkdev->mode = NULL;
-    g_free(blkdev->type);
-    blkdev->type = NULL;
-    g_free(blkdev->dev);
-    blkdev->dev = NULL;
-    g_free(blkdev->devtype);
-    blkdev->devtype = NULL;
-    return -1;
-}
-
-static int blk_connect(struct XenDevice *xendev)
-{
-    struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
-    int pers;
 
     if (xenstore_read_fe_int(&blkdev->xendev, "ring-ref", &blkdev->ring_ref) == -1) {
         return -1;
commit d8d24fb78cf21205bf672d85231712dc1f0bbb39
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 5 16:18:00 2013 +0100

    pflash_cfi01: Implement migration support
    
    Add a vmstate to pflash_cfi01, so that it can be live migrated.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1363717469-30980-3-git-send-email-peter.maydell at linaro.org

diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index 20d10b3..646dc79 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -67,7 +67,7 @@ struct pflash_t {
     uint64_t sector_len;
     uint8_t width;
     uint8_t be;
-    int wcycle; /* if 0, the flash is read normally */
+    uint8_t wcycle; /* if 0, the flash is read normally */
     int ro;
     uint8_t cmd;
     uint8_t status;
@@ -77,7 +77,7 @@ struct pflash_t {
     uint16_t ident3;
     uint8_t cfi_len;
     uint8_t cfi_table[0x52];
-    hwaddr counter;
+    uint64_t counter;
     unsigned int writeblock_size;
     QEMUTimer *timer;
     MemoryRegion mem;
@@ -85,6 +85,19 @@ struct pflash_t {
     void *storage;
 };
 
+static const VMStateDescription vmstate_pflash = {
+    .name = "pflash_cfi01",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(wcycle, pflash_t),
+        VMSTATE_UINT8(cmd, pflash_t),
+        VMSTATE_UINT8(status, pflash_t),
+        VMSTATE_UINT64(counter, pflash_t),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static void pflash_timer (void *opaque)
 {
     pflash_t *pfl = opaque;
@@ -223,7 +236,7 @@ static inline void pflash_data_write(pflash_t *pfl, hwaddr offset,
     uint8_t *p = pfl->storage;
 
     DPRINTF("%s: block write offset " TARGET_FMT_plx
-            " value %x counter " TARGET_FMT_plx "\n",
+            " value %x counter %016" PRIx64 "\n",
             __func__, offset, value, pfl->counter);
     switch (width) {
     case 1:
@@ -701,6 +714,7 @@ static void pflash_cfi01_class_init(ObjectClass *klass, void *data)
 
     k->init = pflash_cfi01_init;
     dc->props = pflash_cfi01_properties;
+    dc->vmsd = &vmstate_pflash;
 }
 
 
commit 5d79b80b335c5f65f148d1bb1672d9d534ace73b
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 5 16:18:00 2013 +0100

    pflash_cfi01: Drop unused 'bypass' field
    
    For pflash_cfi01 the 'bypass' field is set to zero and never changes,
    so remove it (it is a leftover from pflash_cfi02, where bypass is
    implemented).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1363717469-30980-2-git-send-email-peter.maydell at linaro.org

diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index 5d57bab..20d10b3 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -68,7 +68,6 @@ struct pflash_t {
     uint8_t width;
     uint8_t be;
     int wcycle; /* if 0, the flash is read normally */
-    int bypass;
     int ro;
     uint8_t cmd;
     uint8_t status;
@@ -93,12 +92,8 @@ static void pflash_timer (void *opaque)
     DPRINTF("%s: command %02x done\n", __func__, pfl->cmd);
     /* Reset flash */
     pfl->status ^= 0x80;
-    if (pfl->bypass) {
-        pfl->wcycle = 2;
-    } else {
-        memory_region_rom_device_set_readable(&pfl->mem, true);
-        pfl->wcycle = 0;
-    }
+    memory_region_rom_device_set_readable(&pfl->mem, true);
+    pfl->wcycle = 0;
     pfl->cmd = 0;
 }
 
@@ -452,7 +447,6 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
  reset_flash:
     memory_region_rom_device_set_readable(&pfl->mem, true);
 
-    pfl->bypass = 0;
     pfl->wcycle = 0;
     pfl->cmd = 0;
 }
commit 2e19a7035a8e721f32610c8d22223ab748c4232f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 5 16:18:00 2013 +0100

    hw/arm_gic_common: Use vmstate struct rather than save/load functions
    
    Update the GIC save/restore to use vmstate rather than hand-rolled
    save/load functions.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Igor Mitsyanko <i.mitsyanko at gmail.com>
    Message-id: 1363975375-3166-4-git-send-email-peter.maydell at linaro.org

diff --git a/hw/arm_gic_common.c b/hw/arm_gic_common.c
index f95bec3..71594f1 100644
--- a/hw/arm_gic_common.c
+++ b/hw/arm_gic_common.c
@@ -20,90 +20,65 @@
 
 #include "hw/arm_gic_internal.h"
 
-static void gic_save(QEMUFile *f, void *opaque)
+static void gic_pre_save(void *opaque)
 {
     GICState *s = (GICState *)opaque;
     ARMGICCommonClass *c = ARM_GIC_COMMON_GET_CLASS(s);
-    int i;
-    int j;
 
     if (c->pre_save) {
         c->pre_save(s);
     }
-
-    qemu_put_be32(f, s->enabled);
-    for (i = 0; i < s->num_cpu; i++) {
-        qemu_put_be32(f, s->cpu_enabled[i]);
-        for (j = 0; j < GIC_INTERNAL; j++) {
-            qemu_put_be32(f, s->priority1[j][i]);
-        }
-        for (j = 0; j < s->num_irq; j++) {
-            qemu_put_be32(f, s->last_active[j][i]);
-        }
-        qemu_put_be32(f, s->priority_mask[i]);
-        qemu_put_be32(f, s->running_irq[i]);
-        qemu_put_be32(f, s->running_priority[i]);
-        qemu_put_be32(f, s->current_pending[i]);
-    }
-    for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
-        qemu_put_be32(f, s->priority2[i]);
-    }
-    for (i = 0; i < s->num_irq; i++) {
-        qemu_put_be32(f, s->irq_target[i]);
-        qemu_put_byte(f, s->irq_state[i].enabled);
-        qemu_put_byte(f, s->irq_state[i].pending);
-        qemu_put_byte(f, s->irq_state[i].active);
-        qemu_put_byte(f, s->irq_state[i].level);
-        qemu_put_byte(f, s->irq_state[i].model);
-        qemu_put_byte(f, s->irq_state[i].trigger);
-    }
 }
 
-static int gic_load(QEMUFile *f, void *opaque, int version_id)
+static int gic_post_load(void *opaque, int version_id)
 {
     GICState *s = (GICState *)opaque;
     ARMGICCommonClass *c = ARM_GIC_COMMON_GET_CLASS(s);
-    int i;
-    int j;
-
-    if (version_id != 3) {
-        return -EINVAL;
-    }
-
-    s->enabled = qemu_get_be32(f);
-    for (i = 0; i < s->num_cpu; i++) {
-        s->cpu_enabled[i] = qemu_get_be32(f);
-        for (j = 0; j < GIC_INTERNAL; j++) {
-            s->priority1[j][i] = qemu_get_be32(f);
-        }
-        for (j = 0; j < s->num_irq; j++) {
-            s->last_active[j][i] = qemu_get_be32(f);
-        }
-        s->priority_mask[i] = qemu_get_be32(f);
-        s->running_irq[i] = qemu_get_be32(f);
-        s->running_priority[i] = qemu_get_be32(f);
-        s->current_pending[i] = qemu_get_be32(f);
-    }
-    for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
-        s->priority2[i] = qemu_get_be32(f);
-    }
-    for (i = 0; i < s->num_irq; i++) {
-        s->irq_target[i] = qemu_get_be32(f);
-        s->irq_state[i].enabled = qemu_get_byte(f);
-        s->irq_state[i].pending = qemu_get_byte(f);
-        s->irq_state[i].active = qemu_get_byte(f);
-        s->irq_state[i].level = qemu_get_byte(f);
-        s->irq_state[i].model = qemu_get_byte(f);
-        s->irq_state[i].trigger = qemu_get_byte(f);
-    }
 
     if (c->post_load) {
         c->post_load(s);
     }
-
     return 0;
 }
 
+static const VMStateDescription vmstate_gic_irq_state = {
+    .name = "arm_gic_irq_state",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(enabled, gic_irq_state),
+        VMSTATE_UINT8(pending, gic_irq_state),
+        VMSTATE_UINT8(active, gic_irq_state),
+        VMSTATE_UINT8(level, gic_irq_state),
+        VMSTATE_BOOL(model, gic_irq_state),
+        VMSTATE_BOOL(trigger, gic_irq_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_gic = {
+    .name = "arm_gic",
+    .version_id = 4,
+    .minimum_version_id = 4,
+    .pre_save = gic_pre_save,
+    .post_load = gic_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_BOOL(enabled, GICState),
+        VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, NCPU),
+        VMSTATE_STRUCT_ARRAY(irq_state, GICState, GIC_MAXIRQ, 1,
+                             vmstate_gic_irq_state, gic_irq_state),
+        VMSTATE_UINT8_ARRAY(irq_target, GICState, GIC_MAXIRQ),
+        VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, NCPU),
+        VMSTATE_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL),
+        VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, NCPU),
+        VMSTATE_UINT16_ARRAY(priority_mask, GICState, NCPU),
+        VMSTATE_UINT16_ARRAY(running_irq, GICState, NCPU),
+        VMSTATE_UINT16_ARRAY(running_priority, GICState, NCPU),
+        VMSTATE_UINT16_ARRAY(current_pending, GICState, NCPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static void arm_gic_common_realize(DeviceState *dev, Error **errp)
 {
     GICState *s = ARM_GIC_COMMON(dev);
@@ -131,8 +106,6 @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp)
                    num_irq);
         return;
     }
-
-    register_savevm(NULL, "arm_gic", -1, 3, gic_save, gic_load, s);
 }
 
 static void arm_gic_common_reset(DeviceState *dev)
@@ -182,6 +155,7 @@ static void arm_gic_common_class_init(ObjectClass *klass, void *data)
     dc->reset = arm_gic_common_reset;
     dc->realize = arm_gic_common_realize;
     dc->props = arm_gic_common_properties;
+    dc->vmsd = &vmstate_gic;
     dc->no_user = 1;
 }
 
commit c3037774be5329e584d4d709b9df7e1799bba215
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 5 16:17:59 2013 +0100

    arm_gic: Fix sizes of state fields in preparation for vmstate support
    
    In preparation for switching to vmstate for migration support, fix
    the sizes of various GIC state fields. In particular, we replace all
    the bitfields (which VMState can't deal with) with straightforward
    uint8_t values which we do bit operations on. (The bitfields made
    more sense when NCPU was set differently in different situations,
    but we now always model at the architectural limit of 8.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Igor Mitsyanko <i.mitsyanko at gmail.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1363975375-3166-3-git-send-email-peter.maydell at linaro.org

diff --git a/hw/arm_gic_common.c b/hw/arm_gic_common.c
index f2dc8bf..f95bec3 100644
--- a/hw/arm_gic_common.c
+++ b/hw/arm_gic_common.c
@@ -149,7 +149,7 @@ static void arm_gic_common_reset(DeviceState *dev)
         s->current_pending[i] = 1023;
         s->running_irq[i] = 1023;
         s->running_priority[i] = 0x100;
-        s->cpu_enabled[i] = 0;
+        s->cpu_enabled[i] = false;
     }
     for (i = 0; i < 16; i++) {
         GIC_SET_ENABLED(i, ALL_CPU_MASK);
@@ -161,7 +161,7 @@ static void arm_gic_common_reset(DeviceState *dev)
             s->irq_target[i] = 1;
         }
     }
-    s->enabled = 0;
+    s->enabled = false;
 }
 
 static Property arm_gic_common_properties[] = {
diff --git a/hw/arm_gic_internal.h b/hw/arm_gic_internal.h
index 3e1928b..99a3bc3 100644
--- a/hw/arm_gic_internal.h
+++ b/hw/arm_gic_internal.h
@@ -45,14 +45,14 @@
 #define GIC_SET_ACTIVE(irq, cm) s->irq_state[irq].active |= (cm)
 #define GIC_CLEAR_ACTIVE(irq, cm) s->irq_state[irq].active &= ~(cm)
 #define GIC_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0)
-#define GIC_SET_MODEL(irq) s->irq_state[irq].model = 1
-#define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = 0
+#define GIC_SET_MODEL(irq) s->irq_state[irq].model = true
+#define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = false
 #define GIC_TEST_MODEL(irq) s->irq_state[irq].model
 #define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level = (cm)
 #define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
 #define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
-#define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1
-#define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
+#define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = true
+#define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = false
 #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
 #define GIC_GET_PRIORITY(irq, cpu) (((irq) < GIC_INTERNAL) ?            \
                                     s->priority1[irq][cpu] :            \
@@ -61,30 +61,30 @@
 
 typedef struct gic_irq_state {
     /* The enable bits are only banked for per-cpu interrupts.  */
-    unsigned enabled:NCPU;
-    unsigned pending:NCPU;
-    unsigned active:NCPU;
-    unsigned level:NCPU;
-    unsigned model:1; /* 0 = N:N, 1 = 1:N */
-    unsigned trigger:1; /* nonzero = edge triggered.  */
+    uint8_t enabled;
+    uint8_t pending;
+    uint8_t active;
+    uint8_t level;
+    bool model; /* 0 = N:N, 1 = 1:N */
+    bool trigger; /* nonzero = edge triggered.  */
 } gic_irq_state;
 
 typedef struct GICState {
     SysBusDevice busdev;
     qemu_irq parent_irq[NCPU];
-    int enabled;
-    int cpu_enabled[NCPU];
+    bool enabled;
+    bool cpu_enabled[NCPU];
 
     gic_irq_state irq_state[GIC_MAXIRQ];
-    int irq_target[GIC_MAXIRQ];
-    int priority1[GIC_INTERNAL][NCPU];
-    int priority2[GIC_MAXIRQ - GIC_INTERNAL];
-    int last_active[GIC_MAXIRQ][NCPU];
-
-    int priority_mask[NCPU];
-    int running_irq[NCPU];
-    int running_priority[NCPU];
-    int current_pending[NCPU];
+    uint8_t irq_target[GIC_MAXIRQ];
+    uint8_t priority1[GIC_INTERNAL][NCPU];
+    uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL];
+    uint16_t last_active[GIC_MAXIRQ][NCPU];
+
+    uint16_t priority_mask[NCPU];
+    uint16_t running_irq[NCPU];
+    uint16_t running_priority[NCPU];
+    uint16_t current_pending[NCPU];
 
     uint32_t num_cpu;
 
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index d198cfd..2351200 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -458,10 +458,10 @@ static void armv7m_nvic_reset(DeviceState *dev)
      * as enabled by default, and with a priority mask which allows
      * all interrupts through.
      */
-    s->gic.cpu_enabled[0] = 1;
+    s->gic.cpu_enabled[0] = true;
     s->gic.priority_mask[0] = 0x100;
     /* The NVIC as a whole is always enabled. */
-    s->gic.enabled = 1;
+    s->gic.enabled = true;
     systick_reset(s);
 }
 
commit bd7f92e59e7f40ddaeda40e55f7818c8121ecf1a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 5 16:17:59 2013 +0100

    vmstate: Add support for two dimensional arrays
    
    Add support for migrating two dimensional arrays, by defining
    a set of new macros VMSTATE_*_2DARRAY paralleling the existing
    VMSTATE_*_ARRAY macros. 2D arrays are handled the same for actual
    state serialization; the only difference is that the type check
    has to change for a 2D array.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Igor Mitsyanko <i.mitsyanko at gmail.com>
    Message-id: 1363975375-3166-2-git-send-email-peter.maydell at linaro.org

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 8184123..ebc4d09 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -164,6 +164,7 @@ extern const VMStateInfo vmstate_info_buffer;
 extern const VMStateInfo vmstate_info_unused_buffer;
 extern const VMStateInfo vmstate_info_bitmap;
 
+#define type_check_2darray(t1,t2,n,m) ((t1(*)[n][m])0 - (t2*)0)
 #define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0)
 #define type_check_pointer(t1,t2) ((t1**)0 - (t2*)0)
 
@@ -179,6 +180,10 @@ extern const VMStateInfo vmstate_info_bitmap;
     (offsetof(_state, _field) +                                      \
      type_check_array(_type, typeof_field(_state, _field), _num))
 
+#define vmstate_offset_2darray(_state, _field, _type, _n1, _n2)      \
+    (offsetof(_state, _field) +                                      \
+     type_check_2darray(_type, typeof_field(_state, _field), _n1, _n2))
+
 #define vmstate_offset_sub_array(_state, _field, _type, _start)      \
     (offsetof(_state, _field[_start]))
 
@@ -224,6 +229,16 @@ extern const VMStateInfo vmstate_info_bitmap;
     .offset     = vmstate_offset_array(_state, _field, _type, _num), \
 }
 
+#define VMSTATE_2DARRAY(_field, _state, _n1, _n2, _version, _info, _type) { \
+    .name       = (stringify(_field)),                                      \
+    .version_id = (_version),                                               \
+    .num        = (_n1) * (_n2),                                            \
+    .info       = &(_info),                                                 \
+    .size       = sizeof(_type),                                            \
+    .flags      = VMS_ARRAY,                                                \
+    .offset     = vmstate_offset_2darray(_state, _field, _type, _n1, _n2),  \
+}
+
 #define VMSTATE_ARRAY_TEST(_field, _state, _num, _test, _info, _type) {\
     .name         = (stringify(_field)),                              \
     .field_exists = (_test),                                          \
@@ -592,15 +607,27 @@ extern const VMStateInfo vmstate_info_bitmap;
 #define VMSTATE_UINT16_ARRAY_V(_f, _s, _n, _v)                         \
     VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint16, uint16_t)
 
+#define VMSTATE_UINT16_2DARRAY_V(_f, _s, _n1, _n2, _v)                \
+    VMSTATE_2DARRAY(_f, _s, _n1, _n2, _v, vmstate_info_uint16, uint16_t)
+
 #define VMSTATE_UINT16_ARRAY(_f, _s, _n)                               \
     VMSTATE_UINT16_ARRAY_V(_f, _s, _n, 0)
 
+#define VMSTATE_UINT16_2DARRAY(_f, _s, _n1, _n2)                      \
+    VMSTATE_UINT16_2DARRAY_V(_f, _s, _n1, _n2, 0)
+
+#define VMSTATE_UINT8_2DARRAY_V(_f, _s, _n1, _n2, _v)                 \
+    VMSTATE_2DARRAY(_f, _s, _n1, _n2, _v, vmstate_info_uint8, uint8_t)
+
 #define VMSTATE_UINT8_ARRAY_V(_f, _s, _n, _v)                         \
     VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint8, uint8_t)
 
 #define VMSTATE_UINT8_ARRAY(_f, _s, _n)                               \
     VMSTATE_UINT8_ARRAY_V(_f, _s, _n, 0)
 
+#define VMSTATE_UINT8_2DARRAY(_f, _s, _n1, _n2)                       \
+    VMSTATE_UINT8_2DARRAY_V(_f, _s, _n1, _n2, 0)
+
 #define VMSTATE_UINT32_ARRAY_V(_f, _s, _n, _v)                        \
     VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint32, uint32_t)
 
commit b79269b78d0182fa7f4e23b779010145d0b4eaea
Author: Igor Mitsyanko <i.mitsyanko at gmail.com>
Date:   Fri Apr 5 16:17:59 2013 +0100

    hw/onenand.c: fix migration of dynamically allocated buffer "otp"
    
    VMSTATE_BUFFER_UNSAFE should be used for buffers inlined in device state, not
    for buffers allocated dynamically. Change to VMSTATE_BUFFER_POINTER_UNSAFE macro,
    which will do migration right.
    
    Signed-off-by: Igor Mitsyanko <i.mitsyanko at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1362923278-4080-4-git-send-email-i.mitsyanko at gmail.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/onenand.c b/hw/onenand.c
index ddba366..57a346d 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -185,7 +185,8 @@ static const VMStateDescription vmstate_onenand = {
         VMSTATE_UINT8(ecc.cp, OneNANDState),
         VMSTATE_UINT16_ARRAY(ecc.lp, OneNANDState, 2),
         VMSTATE_UINT16(ecc.count, OneNANDState),
-        VMSTATE_BUFFER_UNSAFE(otp, OneNANDState, 0, ((64 + 2) << PAGE_SHIFT)),
+        VMSTATE_BUFFER_POINTER_UNSAFE(otp, OneNANDState, 0,
+            ((64 + 2) << PAGE_SHIFT)),
         VMSTATE_END_OF_LIST()
     }
 };
commit 5f00679ee98b1643ff652bbf982dffe1b432596e
Author: Igor Mitsyanko <i.mitsyanko at gmail.com>
Date:   Fri Apr 5 16:17:59 2013 +0100

    hw/sd.c: fix migration of dynamically allocated buffer "buf"
    
    VMSTATE_BUFFER_UNSAFE should be used for buffers inlined in device state, not
    for buffers allocated dynamically. Change to VMSTATE_BUFFER_POINTER_UNSAFE macro,
    which will do migration right.
    
    Signed-off-by: Igor Mitsyanko <i.mitsyanko at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Michael Walle <michael at walle.cc>
    Message-id: 1362923278-4080-3-git-send-email-i.mitsyanko at gmail.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/sd.c b/hw/sd.c
index a895123..66c4014 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -478,7 +478,7 @@ static const VMStateDescription sd_vmstate = {
         VMSTATE_UINT64(data_start, SDState),
         VMSTATE_UINT32(data_offset, SDState),
         VMSTATE_UINT8_ARRAY(data, SDState, 512),
-        VMSTATE_BUFFER_UNSAFE(buf, SDState, 1, 512),
+        VMSTATE_BUFFER_POINTER_UNSAFE(buf, SDState, 1, 512),
         VMSTATE_BOOL(enable, SDState),
         VMSTATE_END_OF_LIST()
     }
commit 8070568b9aa8d93b3729ab7e9ca0ef8a6351d2bd
Author: Igor Mitsyanko <i.mitsyanko at gmail.com>
Date:   Fri Apr 5 16:17:58 2013 +0100

    vmstate.h: introduce VMSTATE_BUFFER_POINTER_UNSAFE macro
    
    Macro could be used to migrate a dynamically allocated buffer of known size.
    
    Signed-off-by: Igor Mitsyanko <i.mitsyanko at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1362923278-4080-2-git-send-email-i.mitsyanko at gmail.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 65918a9..8184123 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -436,6 +436,15 @@ extern const VMStateInfo vmstate_info_bitmap;
     .offset     = offsetof(_state, _field),                          \
 }
 
+#define VMSTATE_BUFFER_POINTER_UNSAFE(_field, _state, _version, _size) { \
+    .name       = (stringify(_field)),                               \
+    .version_id = (_version),                                        \
+    .size       = (_size),                                           \
+    .info       = &vmstate_info_buffer,                              \
+    .flags      = VMS_BUFFER|VMS_POINTER,                            \
+    .offset     = offsetof(_state, _field),                          \
+}
+
 #define VMSTATE_UNUSED_BUFFER(_test, _version, _size) {              \
     .name         = "unused",                                        \
     .field_exists = (_test),                                         \
commit 28092a23e6e2cb8298c1381f4f046842ffd376eb
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 5 16:17:58 2013 +0100

    hw/arm_mptimer: Save the timer state
    
    Add a missing VMSTATE_TIMER() entry to the arm_mptimer vmstate
    description; this omission meant that we would probably hang on reload
    when the timer failed to fire.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 1363967348-3044-1-git-send-email-peter.maydell at linaro.org

diff --git a/hw/arm_mptimer.c b/hw/arm_mptimer.c
index f59a9f1..317f5e4 100644
--- a/hw/arm_mptimer.c
+++ b/hw/arm_mptimer.c
@@ -253,14 +253,15 @@ static int arm_mptimer_init(SysBusDevice *dev)
 
 static const VMStateDescription vmstate_timerblock = {
     .name = "arm_mptimer_timerblock",
-    .version_id = 1,
-    .minimum_version_id = 1,
+    .version_id = 2,
+    .minimum_version_id = 2,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(count, TimerBlock),
         VMSTATE_UINT32(load, TimerBlock),
         VMSTATE_UINT32(control, TimerBlock),
         VMSTATE_UINT32(status, TimerBlock),
         VMSTATE_INT64(tick, TimerBlock),
+        VMSTATE_TIMER(timer, TimerBlock),
         VMSTATE_END_OF_LIST()
     }
 };
commit e8945b4f2a65fc2872cc31a5141e136fd27d0af8
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 5 16:17:58 2013 +0100

    pl050: Don't send always-constant is_mouse field
    
    The is_mouse field of the pl050 state structure is constant (it tracks
    whether this is a 'pl050_keyboard' or 'pl050_mouse'), so there's
    no need to include it in the VMState structure.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1363628480-29306-1-git-send-email-peter.maydell at linaro.org

diff --git a/hw/pl050.c b/hw/pl050.c
index bc31ab6..76735a0 100644
--- a/hw/pl050.c
+++ b/hw/pl050.c
@@ -24,14 +24,13 @@ typedef struct {
 
 static const VMStateDescription vmstate_pl050 = {
     .name = "pl050",
-    .version_id = 1,
-    .minimum_version_id = 1,
+    .version_id = 2,
+    .minimum_version_id = 2,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(cr, pl050_state),
         VMSTATE_UINT32(clk, pl050_state),
         VMSTATE_UINT32(last, pl050_state),
         VMSTATE_INT32(pending, pl050_state),
-        VMSTATE_INT32(is_mouse, pl050_state),
         VMSTATE_END_OF_LIST()
     }
 };
commit 591f73f642a5f3c822c3efaae8d83a174371a4f5
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 5 16:17:58 2013 +0100

    hw/arm/nseries: don't print to stdout or stderr
    
    Remove various bits of printing to stdout or stderr from the
    nseries code, replacing it with a qemu log message where there's
    an appropriate log category, and just dropping the output for
    some of the more debug-like printing.
    
    In particular, this will get rid of the 'mipid_reset' message
    you currently get from 'make check'.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1363368565-24546-1-git-send-email-peter.maydell at linaro.org

diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
index 6747c1c..b28e7d3 100644
--- a/hw/arm/nseries.c
+++ b/hw/arm/nseries.c
@@ -129,8 +129,6 @@ static void n800_mmc_cs_cb(void *opaque, int line, int level)
     /* TODO: this seems to actually be connected to the menelaus, to
      * which also both MMC slots connect.  */
     omap_mmc_enable((struct omap_mmc_s *) opaque, !level);
-
-    printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);
 }
 
 static void n8x0_gpio_setup(struct n800_s *s)
@@ -428,9 +426,6 @@ struct mipid_s {
 
 static void mipid_reset(struct mipid_s *s)
 {
-    if (!s->sleep)
-        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
-
     s->pm = 0;
     s->cmd = 0;
 
@@ -578,11 +573,9 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
 
     case 0x28:	/* DISPOFF */
         s->onoff = 0;
-        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
         break;
     case 0x29:	/* DISPON */
         s->onoff = 1;
-        fprintf(stderr, "%s: Display on\n", __FUNCTION__);
         break;
 
     case 0x2a:	/* CASET */
@@ -669,7 +662,8 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
 
     default:
     bad_cmd:
-        fprintf(stderr, "%s: unknown command %02x\n", __FUNCTION__, s->cmd);
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: unknown command %02x\n", __func__, s->cmd);
         break;
     }
 
@@ -1347,7 +1341,6 @@ static void n8x0_init(QEMUMachineInitArgs *args,
 
     if (option_rom[0].name &&
         (args->boot_device[0] == 'n' || !args->kernel_filename)) {
-        int rom_size;
         uint8_t nolo_tags[0x10000];
         /* No, wait, better start at the ROM.  */
         s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
@@ -1361,10 +1354,9 @@ static void n8x0_init(QEMUMachineInitArgs *args,
          *
          * The code above is for loading the `zImage' file from Nokia
          * images.  */
-        rom_size = load_image_targphys(option_rom[0].name,
-                                       OMAP2_Q2_BASE + 0x400000,
-                                       sdram_size - 0x400000);
-        printf("%i bytes of image loaded\n", rom_size);
+        load_image_targphys(option_rom[0].name,
+                            OMAP2_Q2_BASE + 0x400000,
+                            sdram_size - 0x400000);
 
         n800_setup_nolo_tags(nolo_tags);
         cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000);
commit 150a470b64c548b7539ea47526f345f15ebac355
Merge: d05ef16 4bf0bb8
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Apr 5 08:55:14 2013 -0500

    Merge remote-tracking branch 'luiz/queue/qmp' into staging
    
    # By Luiz Capitulino
    # Via Luiz Capitulino
    * luiz/queue/qmp:
      chardev: drop the Memory chardev driver
      hmp: human-monitor-command: stop using the Memory chardev driver
      Monitor: Make output buffer dynamic
      qstring: add qstring_get_length()

commit f1922e36e267eae0c9d70e8660830e081878bdfc
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Apr 4 11:04:12 2013 +1000

    xilinx_zynq: Cleanup ssi_create_slave
    
    With the recent m25p80 cleanup there is no need to use
    ssi_create_slave_no_init() anymore. Just use ssi_create_slave().
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 6f36286..5b9257a 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -86,8 +86,7 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
         spi = (SSIBus *)qdev_get_child_bus(dev, bus_name);
 
         for (j = 0; j < num_ss; ++j) {
-            flash_dev = ssi_create_slave_no_init(spi, "n25q128");
-            qdev_init_nofail(flash_dev);
+            flash_dev = ssi_create_slave(spi, "n25q128");
 
             cs_line = qdev_get_gpio_in(flash_dev, 0);
             sysbus_connect_irq(busdev, i * num_ss + j + 1, cs_line);
commit e641080fdc1e81290564e1e9ec4fe7637011fa82
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Apr 4 11:04:11 2013 +1000

    petalogix_ml605_mmu: Cleanup ssi_create_slave()
    
    With the recent m25p80 cleanup there is no need to use
    ssi_create_slave_no_init() anymore. Just use ssi_create_slave().
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index cfc0220..07dc808 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -158,8 +158,7 @@ petalogix_ml605_init(QEMUMachineInitArgs *args)
         for (i = 0; i < NUM_SPI_FLASHES; i++) {
             qemu_irq cs_line;
 
-            dev = ssi_create_slave_no_init(spi, "n25q128");
-            qdev_init_nofail(dev);
+            dev = ssi_create_slave(spi, "n25q128");
             cs_line = qdev_get_gpio_in(dev, 0);
             sysbus_connect_irq(busdev, i+1, cs_line);
         }
commit 5b90a86629dcc075be294524696e6199266f72ad
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Mar 30 10:03:25 2013 -0700

    target-s390: Fix SRNMT
    
    Fallthough into abort = oops.
    
    Cc: qemu-trivial at nongnu.org
    Cc: Alexander Graf <agraf at suse.de>
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index a4f2194..0c3cf68 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -3088,6 +3088,7 @@ static ExitStatus op_srnm(DisasContext *s, DisasOps *o)
         break;
     case 0xb9: /* SRNMT */
         pos = 4, len = 3;
+        break;
     default:
         tcg_abort();
     }
commit 4bf0bb8014ac2ac61b1004f5d92b2a4594d48017
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Tue Apr 2 15:29:29 2013 -0400

    chardev: drop the Memory chardev driver
    
    It's not used anymore since the last commit.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/qemu-char.c b/qemu-char.c
index e5eb8dd..0f7f32d 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2796,70 +2796,6 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     return NULL;
 }
 
-/***********************************************************/
-/* Memory chardev */
-typedef struct {
-    size_t outbuf_size;
-    size_t outbuf_capacity;
-    uint8_t *outbuf;
-} MemoryDriver;
-
-static int mem_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
-{
-    MemoryDriver *d = chr->opaque;
-
-    /* TODO: the QString implementation has the same code, we should
-     * introduce a generic way to do this in cutils.c */
-    if (d->outbuf_capacity < d->outbuf_size + len) {
-        /* grow outbuf */
-        d->outbuf_capacity += len;
-        d->outbuf_capacity *= 2;
-        d->outbuf = g_realloc(d->outbuf, d->outbuf_capacity);
-    }
-
-    memcpy(d->outbuf + d->outbuf_size, buf, len);
-    d->outbuf_size += len;
-
-    return len;
-}
-
-void qemu_chr_init_mem(CharDriverState *chr)
-{
-    MemoryDriver *d;
-
-    d = g_malloc(sizeof(*d));
-    d->outbuf_size = 0;
-    d->outbuf_capacity = 4096;
-    d->outbuf = g_malloc0(d->outbuf_capacity);
-
-    memset(chr, 0, sizeof(*chr));
-    chr->opaque = d;
-    chr->chr_write = mem_chr_write;
-}
-
-QString *qemu_chr_mem_to_qs(CharDriverState *chr)
-{
-    MemoryDriver *d = chr->opaque;
-    return qstring_from_substr((char *) d->outbuf, 0, d->outbuf_size - 1);
-}
-
-/* NOTE: this driver can not be closed with qemu_chr_delete()! */
-void qemu_chr_close_mem(CharDriverState *chr)
-{
-    MemoryDriver *d = chr->opaque;
-
-    g_free(d->outbuf);
-    g_free(chr->opaque);
-    chr->opaque = NULL;
-    chr->chr_write = NULL;
-}
-
-size_t qemu_chr_mem_osize(const CharDriverState *chr)
-{
-    const MemoryDriver *d = chr->opaque;
-    return d->outbuf_size;
-}
-
 /*********************************************************/
 /* Ring buffer chardev */
 
commit 48c043d0d1835c64b571c484a9f229fe6d220287
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Tue Apr 2 15:07:33 2013 -0400

    hmp: human-monitor-command: stop using the Memory chardev driver
    
    The Memory chardev driver was added because, as the Monitor's output
    buffer was static, we needed a way to accumulate the output of an
    HMP commmand when ran by human-monitor-command.
    
    However, the Monitor's output buffer is now dynamic, so it's possible
    for the human-monitor-command to use it instead of the Memory chardev
    driver.
    
    This commit does that change, but there are two important
    observations about it:
    
     1. We need a way to signal to the Monitor that it shouldn't call
        chardev functions when flushing its output. This is done
        by adding a new flag to the Monitor object called skip_flush
    	(which is set to true by qmp_human_monitor_command())
    
     2. The current code has buffered semantics: QMP clients will
        only see a command's output if it flushes its output with
    	a new-line character. This commit changes this to unbuffered,
    	which means that QMP clients will see a command's output
    	whenever the command prints anything.
    
    	I don't think this will matter in practice though, as I believe
    	all HMP commands print the new-line character anyway.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/monitor.c b/monitor.c
index 8712c53..b4bda77 100644
--- a/monitor.c
+++ b/monitor.c
@@ -188,6 +188,7 @@ struct Monitor {
     int reset_seen;
     int flags;
     int suspend_cnt;
+    bool skip_flush;
     QString *outbuf;
     ReadLineState *rs;
     MonitorControl *mc;
@@ -273,6 +274,10 @@ void monitor_flush(Monitor *mon)
     size_t len;
     const char *buf;
 
+    if (mon->skip_flush) {
+        return;
+    }
+
     buf = qstring_get_str(mon->outbuf);
     len = qstring_get_length(mon->outbuf);
 
@@ -675,13 +680,10 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
 {
     char *output = NULL;
     Monitor *old_mon, hmp;
-    CharDriverState mchar;
 
     memset(&hmp, 0, sizeof(hmp));
     hmp.outbuf = qstring_new();
-
-    qemu_chr_init_mem(&mchar);
-    hmp.chr = &mchar;
+    hmp.skip_flush = true;
 
     old_mon = cur_mon;
     cur_mon = &hmp;
@@ -699,17 +701,14 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
     handle_user_command(&hmp, command_line);
     cur_mon = old_mon;
 
-    if (qemu_chr_mem_osize(hmp.chr) > 0) {
-        QString *str = qemu_chr_mem_to_qs(hmp.chr);
-        output = g_strdup(qstring_get_str(str));
-        QDECREF(str);
+    if (qstring_get_length(hmp.outbuf) > 0) {
+        output = g_strdup(qstring_get_str(hmp.outbuf));
     } else {
         output = g_strdup("");
     }
 
 out:
     QDECREF(hmp.outbuf);
-    qemu_chr_close_mem(hmp.chr);
     return output;
 }
 
commit e1f2641b5926d20f63d36f0de45206be774da8da
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon Mar 25 13:52:26 2013 -0400

    Monitor: Make output buffer dynamic
    
    Commit f628926bb423fa8a7e0b114511400ea9df38b76a changed monitor_flush()
    to retry on qemu_chr_fe_write() errors. However, the Monitor's output
    buffer can keep growing while the retry is not issued and this can
    cause the buffer to overflow.
    
    To reproduce this issue, just start qemu and type on the Monitor:
    
    (qemu) ?
    
    This will cause an assertion to trig.
    
    To fix this problem this commit makes the Monitor buffer dynamic,
    which means that it can grow as much as needed.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/monitor.c b/monitor.c
index 4ec1db9..8712c53 100644
--- a/monitor.c
+++ b/monitor.c
@@ -188,8 +188,7 @@ struct Monitor {
     int reset_seen;
     int flags;
     int suspend_cnt;
-    uint8_t outbuf[1024];
-    int outbuf_index;
+    QString *outbuf;
     ReadLineState *rs;
     MonitorControl *mc;
     CPUArchState *mon_cpu;
@@ -271,45 +270,52 @@ static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond,
 void monitor_flush(Monitor *mon)
 {
     int rc;
+    size_t len;
+    const char *buf;
+
+    buf = qstring_get_str(mon->outbuf);
+    len = qstring_get_length(mon->outbuf);
 
-    if (mon && mon->outbuf_index != 0 && !mon->mux_out) {
-        rc = qemu_chr_fe_write(mon->chr, mon->outbuf, mon->outbuf_index);
-        if (rc == mon->outbuf_index) {
+    if (mon && len && !mon->mux_out) {
+        rc = qemu_chr_fe_write(mon->chr, (const uint8_t *) buf, len);
+        if (rc == len) {
             /* all flushed */
-            mon->outbuf_index = 0;
+            QDECREF(mon->outbuf);
+            mon->outbuf = qstring_new();
             return;
         }
         if (rc > 0) {
             /* partinal write */
-            memmove(mon->outbuf, mon->outbuf + rc, mon->outbuf_index - rc);
-            mon->outbuf_index -= rc;
+            QString *tmp = qstring_from_str(buf + rc);
+            QDECREF(mon->outbuf);
+            mon->outbuf = tmp;
         }
         qemu_chr_fe_add_watch(mon->chr, G_IO_OUT, monitor_unblocked, mon);
     }
 }
 
-/* flush at every end of line or if the buffer is full */
+/* flush at every end of line */
 static void monitor_puts(Monitor *mon, const char *str)
 {
     char c;
 
     for(;;) {
-        assert(mon->outbuf_index < sizeof(mon->outbuf) - 1);
         c = *str++;
         if (c == '\0')
             break;
-        if (c == '\n')
-            mon->outbuf[mon->outbuf_index++] = '\r';
-        mon->outbuf[mon->outbuf_index++] = c;
-        if (mon->outbuf_index >= (sizeof(mon->outbuf) - 1)
-            || c == '\n')
+        if (c == '\n') {
+            qstring_append_chr(mon->outbuf, '\r');
+        }
+        qstring_append_chr(mon->outbuf, c);
+        if (c == '\n') {
             monitor_flush(mon);
+        }
     }
 }
 
 void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
 {
-    char buf[4096];
+    char *buf;
 
     if (!mon)
         return;
@@ -318,8 +324,9 @@ void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
         return;
     }
 
-    vsnprintf(buf, sizeof(buf), fmt, ap);
+    buf = g_strdup_vprintf(fmt, ap);
     monitor_puts(mon, buf);
+    g_free(buf);
 }
 
 void monitor_printf(Monitor *mon, const char *fmt, ...)
@@ -671,6 +678,8 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
     CharDriverState mchar;
 
     memset(&hmp, 0, sizeof(hmp));
+    hmp.outbuf = qstring_new();
+
     qemu_chr_init_mem(&mchar);
     hmp.chr = &mchar;
 
@@ -699,6 +708,7 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
     }
 
 out:
+    QDECREF(hmp.outbuf);
     qemu_chr_close_mem(hmp.chr);
     return output;
 }
@@ -4749,6 +4759,7 @@ void monitor_init(CharDriverState *chr, int flags)
     }
 
     mon = g_malloc0(sizeof(*mon));
+    mon->outbuf = qstring_new();
 
     mon->chr = chr;
     mon->flags = flags;
commit 54d49ac99227aff646ac940abfab3417f5cb1693
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon Mar 25 13:46:37 2013 -0400

    qstring: add qstring_get_length()
    
    Long overdue.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/include/qapi/qmp/qstring.h b/include/qapi/qmp/qstring.h
index 0e690f4..1bc3666 100644
--- a/include/qapi/qmp/qstring.h
+++ b/include/qapi/qmp/qstring.h
@@ -26,6 +26,7 @@ typedef struct QString {
 QString *qstring_new(void);
 QString *qstring_from_str(const char *str);
 QString *qstring_from_substr(const char *str, int start, int end);
+size_t qstring_get_length(const QString *qstring);
 const char *qstring_get_str(const QString *qstring);
 void qstring_append_int(QString *qstring, int64_t value);
 void qstring_append(QString *qstring, const char *str);
diff --git a/qobject/qstring.c b/qobject/qstring.c
index 5f7376c..607b7a1 100644
--- a/qobject/qstring.c
+++ b/qobject/qstring.c
@@ -32,6 +32,14 @@ QString *qstring_new(void)
 }
 
 /**
+ * qstring_get_length(): Get the length of a QString
+ */
+size_t qstring_get_length(const QString *qstring)
+{
+    return qstring->length;
+}
+
+/**
  * qstring_from_substr(): Create a new QString from a C string substring
  *
  * Return string reference
commit abe20840166e6f04d3ab60f8d53a2ff5907bd942
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Mar 28 14:33:24 2013 +0000

    linux-user: Don't omit comma for strace of rt_sigaction()
    
    Pass the 'last' parameter of print_signal() through to
    print_raw_param(); this fixes a problem where we weren't printing
    the comma separator for strace of rt_sigaction() when the signal
    was an unnamed (ie realtime) one:
      6856 rt_sigaction(230xf6fff870,0xf6fff8fc) = 0
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 0fbae3c..ea6c1d2 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -143,7 +143,7 @@ print_signal(abi_ulong arg, int last)
     case TARGET_SIGTTOU: signal_name = "SIGTTOU"; break;
     }
     if (signal_name == NULL) {
-        print_raw_param("%ld", arg, 1);
+        print_raw_param("%ld", arg, last);
         return;
     }
     gemu_log("%s%s", signal_name, get_comma(last));
commit 2bd01ac1e238c76e201ba21f314cec46437d2c5a
Author: Stefan Berger <stefanb at linux.vnet.ibm.com>
Date:   Thu Mar 28 11:18:40 2013 -0400

    test-visitor-serialization: Fix some memory leaks
    
    This patch fixes some of the memory leaks in test-visitor-serialization but not all of them.
    
    Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c
index 3c6b8df..e84926f 100644
--- a/tests/test-visitor-serialization.c
+++ b/tests/test-visitor-serialization.c
@@ -258,6 +258,7 @@ static void test_primitives(gconstpointer opaque)
     g_assert(pt_copy != NULL);
     if (pt->type == PTYPE_STRING) {
         g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
+        g_free((char *)pt_copy->value.string);
     } else if (pt->type == PTYPE_NUMBER) {
         /* we serialize with %f for our reference visitors, so rather than fuzzy
          * floating math to test "equality", just compare the formatted values
@@ -275,6 +276,7 @@ static void test_primitives(gconstpointer opaque)
 
     ops->cleanup(serialize_data);
     g_free(args);
+    g_free(pt_copy);
 }
 
 static void test_struct(gconstpointer opaque)
@@ -660,6 +662,7 @@ static void qmp_deserialize(void **native_out, void *datap,
 
     QDECREF(output_json);
     d->qiv = qmp_input_visitor_new(obj);
+    qobject_decref(obj);
     visit(qmp_input_get_visitor(d->qiv), native_out, errp);
 }
 
@@ -668,9 +671,12 @@ static void qmp_cleanup(void *datap)
     QmpSerializeData *d = datap;
     qmp_output_visitor_cleanup(d->qov);
     qmp_input_visitor_cleanup(d->qiv);
+
+    g_free(d);
 }
 
 typedef struct StringSerializeData {
+    char *string;
     StringOutputVisitor *sov;
     StringInputVisitor *siv;
 } StringSerializeData;
@@ -690,15 +696,19 @@ static void string_deserialize(void **native_out, void *datap,
 {
     StringSerializeData *d = datap;
 
-    d->siv = string_input_visitor_new(string_output_get_string(d->sov));
+    d->string = string_output_get_string(d->sov);
+    d->siv = string_input_visitor_new(d->string);
     visit(string_input_get_visitor(d->siv), native_out, errp);
 }
 
 static void string_cleanup(void *datap)
 {
     StringSerializeData *d = datap;
+
     string_output_visitor_cleanup(d->sov);
     string_input_visitor_cleanup(d->siv);
+    g_free(d->string);
+    g_free(d);
 }
 
 /* visitor registration, test harness */
commit d05ef160453e98546a4197496dc8a3cb2defac53
Author: Brad Smith <brad at comstyle.com>
Date:   Thu Apr 4 20:37:53 2013 -0400

    Allow clock_gettime() monotonic clock to be utilized on more OS's
    
    Allow the clock_gettime() code using monotonic clock to be utilized on
    more POSIX compliannt OS's. This started as a fix for OpenBSD which was
    listed in one function as part of the previous hard coded list of OS's
    for the functions to support but not in the other.
    
    Signed-off-by: Brad Smith <brad at comstyle.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 20130405003748.GH884 at rox.home.comstyle.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 1766b2d..c363190 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -117,8 +117,7 @@ extern int use_rt_clock;
 
 static inline int64_t get_clock(void)
 {
-#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \
-    || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+#ifdef CLOCK_MONOTONIC
     if (use_rt_clock) {
         struct timespec ts;
         clock_gettime(CLOCK_MONOTONIC, &ts);
diff --git a/util/qemu-timer-common.c b/util/qemu-timer-common.c
index 16f5e75..95e0847 100644
--- a/util/qemu-timer-common.c
+++ b/util/qemu-timer-common.c
@@ -49,9 +49,7 @@ int use_rt_clock;
 static void __attribute__((constructor)) init_get_clock(void)
 {
     use_rt_clock = 0;
-#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \
-    || defined(__DragonFly__) || defined(__FreeBSD_kernel__) \
-    || defined(__OpenBSD__)
+#ifdef CLOCK_MONOTONIC
     {
         struct timespec ts;
         if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
commit c5a98cf333997616147a161ef4e4cf71bb9bd00a
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:22 2013 +0100

    pc_acpi_init(): don't bail as soon as failing to find default DSDT
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-11-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 09d44fc..ebbf059 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -891,9 +891,7 @@ void pc_cpus_init(const char *cpu_model)
 
 void pc_acpi_init(const char *default_dsdt)
 {
-    char *filename = NULL, *arg = NULL;
-    QemuOpts *opts;
-    Error *err = NULL;
+    char *filename;
 
     if (acpi_tables != NULL) {
         /* manually set via -acpitable, leave it alone */
@@ -903,23 +901,26 @@ void pc_acpi_init(const char *default_dsdt)
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, default_dsdt);
     if (filename == NULL) {
         fprintf(stderr, "WARNING: failed to find %s\n", default_dsdt);
-        return;
-    }
+    } else {
+        char *arg;
+        QemuOpts *opts;
+        Error *err = NULL;
 
-    arg = g_strdup_printf("file=%s", filename);
+        arg = g_strdup_printf("file=%s", filename);
 
-    /* creates a deep copy of "arg" */
-    opts = qemu_opts_parse(qemu_find_opts("acpi"), arg, 0);
-    g_assert(opts != NULL);
+        /* creates a deep copy of "arg" */
+        opts = qemu_opts_parse(qemu_find_opts("acpi"), arg, 0);
+        g_assert(opts != NULL);
 
-    acpi_table_add(opts, &err);
-    if (err) {
-        fprintf(stderr, "WARNING: failed to load %s: %s\n", filename,
-                error_get_pretty(err));
-        error_free(err);
+        acpi_table_add(opts, &err);
+        if (err) {
+            fprintf(stderr, "WARNING: failed to load %s: %s\n", filename,
+                    error_get_pretty(err));
+            error_free(err);
+        }
+        g_free(arg);
+        g_free(filename);
     }
-    g_free(arg);
-    g_free(filename);
 }
 
 void *pc_memory_init(MemoryRegion *system_memory,
commit 3a4a4697aacdd58b77f8bca6f2c0ce307b213506
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:21 2013 +0100

    Introduce IO_APIC_DEFAULT_ADDRESS for 0xfec00000
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-10-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 2e915ec..09d44fc 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -72,6 +72,8 @@
 #define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3)
 #define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4)
 
+#define IO_APIC_DEFAULT_ADDRESS 0xfec00000
+
 #define E820_NR_ENTRIES		16
 
 struct e820_entry {
@@ -1169,7 +1171,7 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name)
     }
     qdev_init_nofail(dev);
     d = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(d, 0, 0xfec00000);
+    sysbus_mmio_map(d, 0, IO_APIC_DEFAULT_ADDRESS);
 
     for (i = 0; i < IOAPIC_NUM_PINS; i++) {
         gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i);
commit dab8623430926a8c55a149c22b2b8e2edb786ae3
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:20 2013 +0100

    extract/unify the constant 0xfee00000 as APIC_DEFAULT_ADDRESS
    
    A common dependency of the constant's current users:
    - hw/apic_common.c
    - hw/i386/kvmvapic.c
    - target-i386/cpu.c
    is "target-i386/cpu.h".
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-9-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/apic_common.c b/hw/apic_common.c
index d0c2616..3798509 100644
--- a/hw/apic_common.c
+++ b/hw/apic_common.c
@@ -218,7 +218,7 @@ static void apic_reset_common(DeviceState *d)
     bool bsp;
 
     bsp = cpu_is_bsp(s->cpu);
-    s->apicbase = 0xfee00000 |
+    s->apicbase = APIC_DEFAULT_ADDRESS |
         (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE;
 
     s->vapic_paddr = 0;
diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
index c151c95..cc95e5c 100644
--- a/hw/i386/kvmvapic.c
+++ b/hw/i386/kvmvapic.c
@@ -13,8 +13,6 @@
 #include "sysemu/kvm.h"
 #include "hw/apic_internal.h"
 
-#define APIC_DEFAULT_ADDRESS    0xfee00000
-
 #define VAPIC_IO_PORT           0x7e
 
 #define VAPIC_CPU_SHIFT         7
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index bf717d5..69c3570 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2049,8 +2049,6 @@ static void mce_init(X86CPU *cpu)
     }
 }
 
-#define MSI_ADDR_BASE 0xfee00000
-
 #ifndef CONFIG_USER_ONLY
 static void x86_cpu_apic_init(X86CPU *cpu, Error **errp)
 {
@@ -2090,7 +2088,7 @@ static void x86_cpu_apic_init(X86CPU *cpu, Error **errp)
            on the global memory bus. */
         /* XXX: what if the base changes? */
         sysbus_mmio_map_overlap(SYS_BUS_DEVICE(env->apic_state), 0,
-                                MSI_ADDR_BASE, 0x1000);
+                                APIC_DEFAULT_ADDRESS, 0x1000);
         apic_mapped = 1;
     }
 }
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 5284ebc..069a2e2 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -1267,4 +1267,6 @@ const char *get_register_name_32(unsigned int reg);
 uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index);
 void enable_compat_apic_id_mode(void);
 
+#define APIC_DEFAULT_ADDRESS 0xfee00000
+
 #endif /* CPU_I386_H */
commit 23084327dc5c2f42e8a1c3e39ec565e344c7f52e
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:19 2013 +0100

    like acpi_table_install(), acpi_table_add() should propagate Errors
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-8-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/arch_init.c b/arch_init.c
index 0373a58..c2cbc71 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -1106,8 +1106,13 @@ int qemu_uuid_parse(const char *str, uint8_t *uuid)
 void do_acpitable_option(const QemuOpts *opts)
 {
 #ifdef TARGET_I386
-    if (acpi_table_add(opts) < 0) {
-        fprintf(stderr, "Wrong acpi table provided\n");
+    Error *err = NULL;
+
+    acpi_table_add(opts, &err);
+    if (err) {
+        fprintf(stderr, "Wrong acpi table provided: %s\n",
+                error_get_pretty(err));
+        error_free(err);
         exit(1);
     }
 #endif
diff --git a/hw/acpi.c b/hw/acpi.c
index ec1ade7..856da81 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -229,7 +229,7 @@ static void acpi_table_install(const char unsigned *blob, size_t bloblen,
                                       ACPI_TABLE_PFX_SIZE, acpi_payload_size);
 }
 
-int acpi_table_add(const QemuOpts *opts)
+void acpi_table_add(const QemuOpts *opts, Error **errp)
 {
     AcpiTableOptions *hdrs = NULL;
     Error *err = NULL;
@@ -306,12 +306,7 @@ out:
         qapi_dealloc_visitor_cleanup(dv);
     }
 
-    if (err) {
-        fprintf(stderr, "%s\n", error_get_pretty(err));
-        error_free(err);
-        return -1;
-    }
-    return 0;
+    error_propagate(errp, err);
 }
 
 static void acpi_notify_wakeup(Notifier *notifier, void *data)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index d1bc0de..2e915ec 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -891,6 +891,7 @@ void pc_acpi_init(const char *default_dsdt)
 {
     char *filename = NULL, *arg = NULL;
     QemuOpts *opts;
+    Error *err = NULL;
 
     if (acpi_tables != NULL) {
         /* manually set via -acpitable, leave it alone */
@@ -909,8 +910,11 @@ void pc_acpi_init(const char *default_dsdt)
     opts = qemu_opts_parse(qemu_find_opts("acpi"), arg, 0);
     g_assert(opts != NULL);
 
-    if (acpi_table_add(opts) != 0) {
-        fprintf(stderr, "WARNING: failed to load %s\n", filename);
+    acpi_table_add(opts, &err);
+    if (err) {
+        fprintf(stderr, "WARNING: failed to load %s: %s\n", filename,
+                error_get_pretty(err));
+        error_free(err);
     }
     g_free(arg);
     g_free(filename);
diff --git a/hw/pc.h b/hw/pc.h
index 613520d..55964ce 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -113,7 +113,7 @@ extern char unsigned *acpi_tables;
 extern size_t acpi_tables_len;
 
 void acpi_bios_init(void);
-int acpi_table_add(const QemuOpts *opts);
+void acpi_table_add(const QemuOpts *opts, Error **errp);
 
 /* acpi_piix.c */
 
commit e980f2bf0a39cb524259bb70084e0f75b92c8f39
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:18 2013 +0100

    acpi_table_add(): extract and reimplement internals
    
    The new function acpi_table_install() installs any blob the caller passes
    in. In the next patches this function will be promoted from helper role to
    extern.
    
    Reimplementing the logic should make it easier to understand. It also
    removes a buffer overflow when
    
        has_header &&
        cumulative_file_size < ACPI_TABLE_HDR_SIZE - ACPI_TABLE_PFX_SIZE
    
    (In that case the g_realloc() call in the read() loop used to shrink the
    "acpi_tables" array, causing an out-of-bounds read access when copying the
    header out of "acpi_tables".)
    
    The new code isn't more daring alignment-wise than its predecessor:
    "acpi_table_header" is packed, and the uint32_t fields are at offsets 6,
    26, and 34.
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-7-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/acpi.c b/hw/acpi.c
index 1aca458..ec1ade7 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -30,7 +30,7 @@
 
 struct acpi_table_header {
     uint16_t _length;         /* our length, not actual part of the hdr */
-                              /* XXX why we have 2 length fields here? */
+                              /* allows easier parsing for fw_cfg clients */
     char sig[4];              /* ACPI signature (4 ASCII characters) */
     uint32_t length;          /* Length of table, in bytes, including header */
     uint8_t revision;         /* ACPI Specification minor version # */
@@ -45,8 +45,7 @@ struct acpi_table_header {
 #define ACPI_TABLE_HDR_SIZE sizeof(struct acpi_table_header)
 #define ACPI_TABLE_PFX_SIZE sizeof(uint16_t)  /* size of the extra prefix */
 
-static const char unsigned dfl_hdr[ACPI_TABLE_HDR_SIZE] =
-    "\0\0"                   /* fake _length (2) */
+static const char unsigned dfl_hdr[ACPI_TABLE_HDR_SIZE - ACPI_TABLE_PFX_SIZE] =
     "QEMU\0\0\0\0\1\0"       /* sig (4), len(4), revno (1), csum (1) */
     "QEMUQEQEMUQEMU\1\0\0\0" /* OEM id (6), table (8), revno (4) */
     "QEMU\1\0\0\0"           /* ASL compiler ID (4), version (4) */
@@ -79,19 +78,165 @@ static int acpi_checksum(const uint8_t *data, int len)
     return (-sum) & 0xff;
 }
 
+
+/* Install a copy of the ACPI table specified in @blob.
+ *
+ * If @has_header is set, @blob starts with the System Description Table Header
+ * structure. Otherwise, "dfl_hdr" is prepended. In any case, each header field
+ * is optionally overwritten from @hdrs.
+ *
+ * It is valid to call this function with
+ * (@blob == NULL && bloblen == 0 && !has_header).
+ *
+ * @hdrs->file and @hdrs->data are ignored.
+ *
+ * SIZE_MAX is considered "infinity" in this function.
+ *
+ * The number of tables that can be installed is not limited, but the 16-bit
+ * counter at the beginning of "acpi_tables" wraps around after UINT16_MAX.
+ */
+static void acpi_table_install(const char unsigned *blob, size_t bloblen,
+                               bool has_header,
+                               const struct AcpiTableOptions *hdrs,
+                               Error **errp)
+{
+    size_t body_start;
+    const char unsigned *hdr_src;
+    size_t body_size, acpi_payload_size;
+    struct acpi_table_header *ext_hdr;
+    unsigned changed_fields;
+
+    /* Calculate where the ACPI table body starts within the blob, plus where
+     * to copy the ACPI table header from.
+     */
+    if (has_header) {
+        /*   _length             | ACPI header in blob | blob body
+         *   ^^^^^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^^^   ^^^^^^^^^
+         *   ACPI_TABLE_PFX_SIZE     sizeof dfl_hdr      body_size
+         *                           == body_start
+         *
+         *                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+         *                           acpi_payload_size == bloblen
+         */
+        body_start = sizeof dfl_hdr;
+
+        if (bloblen < body_start) {
+            error_setg(errp, "ACPI table claiming to have header is too "
+                       "short, available: %zu, expected: %zu", bloblen,
+                       body_start);
+            return;
+        }
+        hdr_src = blob;
+    } else {
+        /*   _length             | ACPI header in template | blob body
+         *   ^^^^^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^^^^^^^   ^^^^^^^^^^
+         *   ACPI_TABLE_PFX_SIZE       sizeof dfl_hdr        body_size
+         *                                                   == bloblen
+         *
+         *                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+         *                                  acpi_payload_size
+         */
+        body_start = 0;
+        hdr_src = dfl_hdr;
+    }
+    body_size = bloblen - body_start;
+    acpi_payload_size = sizeof dfl_hdr + body_size;
+
+    if (acpi_payload_size > UINT16_MAX) {
+        error_setg(errp, "ACPI table too big, requested: %zu, max: %u",
+                   acpi_payload_size, (unsigned)UINT16_MAX);
+        return;
+    }
+
+    /* We won't fail from here on. Initialize / extend the globals. */
+    if (acpi_tables == NULL) {
+        acpi_tables_len = sizeof(uint16_t);
+        acpi_tables = g_malloc0(acpi_tables_len);
+    }
+
+    acpi_tables = g_realloc(acpi_tables, acpi_tables_len +
+                                         ACPI_TABLE_PFX_SIZE +
+                                         sizeof dfl_hdr + body_size);
+
+    ext_hdr = (struct acpi_table_header *)(acpi_tables + acpi_tables_len);
+    acpi_tables_len += ACPI_TABLE_PFX_SIZE;
+
+    memcpy(acpi_tables + acpi_tables_len, hdr_src, sizeof dfl_hdr);
+    acpi_tables_len += sizeof dfl_hdr;
+
+    if (blob != NULL) {
+        memcpy(acpi_tables + acpi_tables_len, blob + body_start, body_size);
+        acpi_tables_len += body_size;
+    }
+
+    /* increase number of tables */
+    cpu_to_le16wu((uint16_t *)acpi_tables,
+                  le16_to_cpupu((uint16_t *)acpi_tables) + 1u);
+
+    /* Update the header fields. The strings need not be NUL-terminated. */
+    changed_fields = 0;
+    ext_hdr->_length = cpu_to_le16(acpi_payload_size);
+
+    if (hdrs->has_sig) {
+        strncpy(ext_hdr->sig, hdrs->sig, sizeof ext_hdr->sig);
+        ++changed_fields;
+    }
+
+    if (has_header && le32_to_cpu(ext_hdr->length) != acpi_payload_size) {
+        fprintf(stderr,
+                "warning: ACPI table has wrong length, header says "
+                "%" PRIu32 ", actual size %zu bytes\n",
+                le32_to_cpu(ext_hdr->length), acpi_payload_size);
+    }
+    ext_hdr->length = cpu_to_le32(acpi_payload_size);
+
+    if (hdrs->has_rev) {
+        ext_hdr->revision = hdrs->rev;
+        ++changed_fields;
+    }
+
+    ext_hdr->checksum = 0;
+
+    if (hdrs->has_oem_id) {
+        strncpy(ext_hdr->oem_id, hdrs->oem_id, sizeof ext_hdr->oem_id);
+        ++changed_fields;
+    }
+    if (hdrs->has_oem_table_id) {
+        strncpy(ext_hdr->oem_table_id, hdrs->oem_table_id,
+                sizeof ext_hdr->oem_table_id);
+        ++changed_fields;
+    }
+    if (hdrs->has_oem_rev) {
+        ext_hdr->oem_revision = cpu_to_le32(hdrs->oem_rev);
+        ++changed_fields;
+    }
+    if (hdrs->has_asl_compiler_id) {
+        strncpy(ext_hdr->asl_compiler_id, hdrs->asl_compiler_id,
+                sizeof ext_hdr->asl_compiler_id);
+        ++changed_fields;
+    }
+    if (hdrs->has_asl_compiler_rev) {
+        ext_hdr->asl_compiler_revision = cpu_to_le32(hdrs->asl_compiler_rev);
+        ++changed_fields;
+    }
+
+    if (!has_header && changed_fields == 0) {
+        fprintf(stderr, "warning: ACPI table: no headers are specified\n");
+    }
+
+    /* recalculate checksum */
+    ext_hdr->checksum = acpi_checksum((const char unsigned *)ext_hdr +
+                                      ACPI_TABLE_PFX_SIZE, acpi_payload_size);
+}
+
 int acpi_table_add(const QemuOpts *opts)
 {
     AcpiTableOptions *hdrs = NULL;
     Error *err = NULL;
     char **pathnames = NULL;
     char **cur;
-
-    size_t len, start, allen;
-    bool has_header;
-    int changed;
-    int r;
-    struct acpi_table_header hdr;
-    char unsigned *table_start;
+    size_t bloblen = 0;
+    char unsigned *blob = NULL;
 
     {
         OptsVisitor *ov;
@@ -108,7 +253,6 @@ int acpi_table_add(const QemuOpts *opts)
         error_setg(&err, "'-acpitable' requires one of 'data' or 'file'");
         goto out;
     }
-    has_header = hdrs->has_file;
 
     pathnames = g_strsplit(hdrs->has_file ? hdrs->file : hdrs->data, ":", 0);
     if (pathnames == NULL || pathnames[0] == NULL) {
@@ -116,19 +260,7 @@ int acpi_table_add(const QemuOpts *opts)
         goto out;
     }
 
-    if (!acpi_tables) {
-        allen = sizeof(uint16_t);
-        acpi_tables = g_malloc0(allen);
-    } else {
-        allen = acpi_tables_len;
-    }
-
-    start = allen;
-    acpi_tables = g_realloc(acpi_tables, start + ACPI_TABLE_HDR_SIZE);
-    allen += has_header ? ACPI_TABLE_PFX_SIZE : ACPI_TABLE_HDR_SIZE;
-
     /* now read in the data files, reallocating buffer as needed */
-
     for (cur = pathnames; *cur; ++cur) {
         int fd = open(*cur, O_RDONLY | O_BINARY);
 
@@ -139,13 +271,15 @@ int acpi_table_add(const QemuOpts *opts)
 
         for (;;) {
             char unsigned data[8192];
-            r = read(fd, data, sizeof(data));
+            ssize_t r;
+
+            r = read(fd, data, sizeof data);
             if (r == 0) {
                 break;
             } else if (r > 0) {
-                acpi_tables = g_realloc(acpi_tables, allen + r);
-                memcpy(acpi_tables + allen, data, r);
-                allen += r;
+                blob = g_realloc(blob, bloblen + r);
+                memcpy(blob + bloblen, data, r);
+                bloblen += r;
             } else if (errno != EINTR) {
                 error_setg(&err, "can't read file %s: %s",
                            *cur, strerror(errno));
@@ -157,102 +291,10 @@ int acpi_table_add(const QemuOpts *opts)
         close(fd);
     }
 
-    /* now fill in the header fields */
-
-    table_start = acpi_tables + start;   /* start of the table */
-    changed = 0;
-
-    /* copy the header to temp place to align the fields */
-    memcpy(&hdr, has_header ? table_start : dfl_hdr, ACPI_TABLE_HDR_SIZE);
-
-    /* length of the table minus our prefix */
-    len = allen - start - ACPI_TABLE_PFX_SIZE;
-
-    hdr._length = cpu_to_le16(len);
-
-    if (hdrs->has_sig) {
-        /* strncpy is justified: the field need not be NUL-terminated. */
-        strncpy(hdr.sig, hdrs->sig, sizeof(hdr.sig));
-        ++changed;
-    }
-
-    /* length of the table including header, in bytes */
-    if (has_header) {
-        unsigned long val;
-
-        /* check if actual length is correct */
-        val = le32_to_cpu(hdr.length);
-        if (val != len) {
-            fprintf(stderr,
-                "warning: acpitable has wrong length,"
-                " header says %lu, actual size %zu bytes\n",
-                val, len);
-            ++changed;
-        }
-    }
-    /* we may avoid putting length here if has_header is true */
-    hdr.length = cpu_to_le32(len);
-
-    if (hdrs->has_rev) {
-        hdr.revision = hdrs->rev;
-        ++changed;
-    }
-
-    if (hdrs->has_oem_id) {
-        /* strncpy is justified: the field need not be NUL-terminated. */
-        strncpy(hdr.oem_id, hdrs->oem_id, sizeof(hdr.oem_id));
-        ++changed;
-    }
-
-    if (hdrs->has_oem_table_id) {
-        /* strncpy is justified: the field need not be NUL-terminated. */
-        strncpy(hdr.oem_table_id, hdrs->oem_table_id,
-                sizeof(hdr.oem_table_id));
-        ++changed;
-    }
-
-    if (hdrs->has_oem_rev) {
-        hdr.oem_revision = cpu_to_le32(hdrs->oem_rev);
-        ++changed;
-    }
-
-    if (hdrs->has_asl_compiler_id) {
-        /* strncpy is justified: the field need not be NUL-terminated. */
-        strncpy(hdr.asl_compiler_id, hdrs->asl_compiler_id,
-                sizeof(hdr.asl_compiler_id));
-        ++changed;
-    }
-
-    if (hdrs->has_asl_compiler_rev) {
-        hdr.asl_compiler_revision = cpu_to_le32(hdrs->asl_compiler_rev);
-        ++changed;
-    }
-
-    if (!has_header && !changed) {
-        fprintf(stderr, "warning: acpitable: no table headers are specified\n");
-    }
-
-
-    /* now calculate checksum of the table, complete with the header */
-    /* we may as well leave checksum intact if has_header is true */
-    /* alternatively there may be a way to set cksum to a given value */
-    hdr.checksum = 0;    /* for checksum calculation */
-
-    /* put header back */
-    memcpy(table_start, &hdr, sizeof(hdr));
-
-    if (changed || !has_header || 1) {
-        ((struct acpi_table_header *)table_start)->checksum =
-            acpi_checksum((uint8_t *)table_start + ACPI_TABLE_PFX_SIZE, len);
-    }
-
-    /* increase number of tables */
-    (*(uint16_t *)acpi_tables) =
-        cpu_to_le32(le32_to_cpu(*(uint16_t *)acpi_tables) + 1);
-
-    acpi_tables_len = allen;
+    acpi_table_install(blob, bloblen, hdrs->has_file, hdrs, &err);
 
 out:
+    g_free(blob);
     g_strfreev(pathnames);
 
     if (hdrs != NULL) {
commit 0c764a9dfc0d480c21f325480aa2e69581841858
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:17 2013 +0100

    acpi_table_add(): accept QemuOpts and parse it with OptsVisitor
    
    As one consequence, strtok() -- which modifies its argument -- is replaced
    with g_strsplit().
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-6-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/arch_init.c b/arch_init.c
index 2ed12fa..0373a58 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -1103,10 +1103,10 @@ int qemu_uuid_parse(const char *str, uint8_t *uuid)
     return 0;
 }
 
-void do_acpitable_option(const char *optarg)
+void do_acpitable_option(const QemuOpts *opts)
 {
 #ifdef TARGET_I386
-    if (acpi_table_add(optarg) < 0) {
+    if (acpi_table_add(opts) < 0) {
         fprintf(stderr, "Wrong acpi table provided\n");
         exit(1);
     }
diff --git a/hw/acpi.c b/hw/acpi.c
index 1d1916b..1aca458 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -23,6 +23,10 @@
 #include "hw/pc.h"
 #include "hw/acpi.h"
 #include "monitor/monitor.h"
+#include "qemu/config-file.h"
+#include "qapi/opts-visitor.h"
+#include "qapi/dealloc-visitor.h"
+#include "qapi-visit.h"
 
 struct acpi_table_header {
     uint16_t _length;         /* our length, not actual part of the hdr */
@@ -51,6 +55,20 @@ static const char unsigned dfl_hdr[ACPI_TABLE_HDR_SIZE] =
 char unsigned *acpi_tables;
 size_t acpi_tables_len;
 
+static QemuOptsList qemu_acpi_opts = {
+    .name = "acpi",
+    .implied_opt_name = "data",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_acpi_opts.head),
+    .desc = { { 0 } } /* validated with OptsVisitor */
+};
+
+static void acpi_register_config(void)
+{
+    qemu_add_opts(&qemu_acpi_opts);
+}
+
+machine_init(acpi_register_config);
+
 static int acpi_checksum(const uint8_t *data, int len)
 {
     int sum, i;
@@ -61,12 +79,13 @@ static int acpi_checksum(const uint8_t *data, int len)
     return (-sum) & 0xff;
 }
 
-/* XXX fixme: this function uses obsolete argument parsing interface */
-int acpi_table_add(const char *t)
+int acpi_table_add(const QemuOpts *opts)
 {
+    AcpiTableOptions *hdrs = NULL;
     Error *err = NULL;
-    char buf[1024], *p, *f;
-    unsigned long val;
+    char **pathnames = NULL;
+    char **cur;
+
     size_t len, start, allen;
     bool has_header;
     int changed;
@@ -74,21 +93,26 @@ int acpi_table_add(const char *t)
     struct acpi_table_header hdr;
     char unsigned *table_start;
 
-    r = 0;
-    r |= get_param_value(buf, sizeof(buf), "data", t) ? 1 : 0;
-    r |= get_param_value(buf, sizeof(buf), "file", t) ? 2 : 0;
-    switch (r) {
-    case 0:
-        buf[0] = '\0';
-        /* fallthrough for default behavior */
-    case 1:
-        has_header = false;
-        break;
-    case 2:
-        has_header = true;
-        break;
-    default:
-        error_setg(&err, "acpitable: both data and file are specified");
+    {
+        OptsVisitor *ov;
+
+        ov = opts_visitor_new(opts);
+        visit_type_AcpiTableOptions(opts_get_visitor(ov), &hdrs, NULL, &err);
+        opts_visitor_cleanup(ov);
+    }
+
+    if (err) {
+        goto out;
+    }
+    if (hdrs->has_file == hdrs->has_data) {
+        error_setg(&err, "'-acpitable' requires one of 'data' or 'file'");
+        goto out;
+    }
+    has_header = hdrs->has_file;
+
+    pathnames = g_strsplit(hdrs->has_file ? hdrs->file : hdrs->data, ":", 0);
+    if (pathnames == NULL || pathnames[0] == NULL) {
+        error_setg(&err, "'-acpitable' requires at least one pathname");
         goto out;
     }
 
@@ -105,11 +129,11 @@ int acpi_table_add(const char *t)
 
     /* now read in the data files, reallocating buffer as needed */
 
-    for (f = strtok(buf, ":"); f; f = strtok(NULL, ":")) {
-        int fd = open(f, O_RDONLY | O_BINARY);
+    for (cur = pathnames; *cur; ++cur) {
+        int fd = open(*cur, O_RDONLY | O_BINARY);
 
         if (fd < 0) {
-            error_setg(&err, "can't open file %s: %s", f, strerror(errno));
+            error_setg(&err, "can't open file %s: %s", *cur, strerror(errno));
             goto out;
         }
 
@@ -124,7 +148,7 @@ int acpi_table_add(const char *t)
                 allen += r;
             } else if (errno != EINTR) {
                 error_setg(&err, "can't read file %s: %s",
-                           f, strerror(errno));
+                           *cur, strerror(errno));
                 close(fd);
                 goto out;
             }
@@ -146,14 +170,16 @@ int acpi_table_add(const char *t)
 
     hdr._length = cpu_to_le16(len);
 
-    if (get_param_value(buf, sizeof(buf), "sig", t)) {
+    if (hdrs->has_sig) {
         /* strncpy is justified: the field need not be NUL-terminated. */
-        strncpy(hdr.sig, buf, sizeof(hdr.sig));
+        strncpy(hdr.sig, hdrs->sig, sizeof(hdr.sig));
         ++changed;
     }
 
     /* length of the table including header, in bytes */
     if (has_header) {
+        unsigned long val;
+
         /* check if actual length is correct */
         val = le32_to_cpu(hdr.length);
         if (val != len) {
@@ -167,52 +193,38 @@ int acpi_table_add(const char *t)
     /* we may avoid putting length here if has_header is true */
     hdr.length = cpu_to_le32(len);
 
-    if (get_param_value(buf, sizeof(buf), "rev", t)) {
-        val = strtoul(buf, &p, 0);
-        if (val > 255 || *p) {
-            error_setg(&err, "acpitable: \"rev=%s\" is invalid", buf);
-            goto out;
-        }
-        hdr.revision = (uint8_t)val;
+    if (hdrs->has_rev) {
+        hdr.revision = hdrs->rev;
         ++changed;
     }
 
-    if (get_param_value(buf, sizeof(buf), "oem_id", t)) {
+    if (hdrs->has_oem_id) {
         /* strncpy is justified: the field need not be NUL-terminated. */
-        strncpy(hdr.oem_id, buf, sizeof(hdr.oem_id));
+        strncpy(hdr.oem_id, hdrs->oem_id, sizeof(hdr.oem_id));
         ++changed;
     }
 
-    if (get_param_value(buf, sizeof(buf), "oem_table_id", t)) {
+    if (hdrs->has_oem_table_id) {
         /* strncpy is justified: the field need not be NUL-terminated. */
-        strncpy(hdr.oem_table_id, buf, sizeof(hdr.oem_table_id));
+        strncpy(hdr.oem_table_id, hdrs->oem_table_id,
+                sizeof(hdr.oem_table_id));
         ++changed;
     }
 
-    if (get_param_value(buf, sizeof(buf), "oem_rev", t)) {
-        val = strtol(buf, &p, 0);
-        if (*p) {
-            error_setg(&err, "acpitable: \"oem_rev=%s\" is invalid", buf);
-            goto out;
-        }
-        hdr.oem_revision = cpu_to_le32(val);
+    if (hdrs->has_oem_rev) {
+        hdr.oem_revision = cpu_to_le32(hdrs->oem_rev);
         ++changed;
     }
 
-    if (get_param_value(buf, sizeof(buf), "asl_compiler_id", t)) {
+    if (hdrs->has_asl_compiler_id) {
         /* strncpy is justified: the field need not be NUL-terminated. */
-        strncpy(hdr.asl_compiler_id, buf, sizeof(hdr.asl_compiler_id));
+        strncpy(hdr.asl_compiler_id, hdrs->asl_compiler_id,
+                sizeof(hdr.asl_compiler_id));
         ++changed;
     }
 
-    if (get_param_value(buf, sizeof(buf), "asl_compiler_rev", t)) {
-        val = strtol(buf, &p, 0);
-        if (*p) {
-            error_setg(&err, "acpitable: \"%s=%s\" is invalid",
-                       "asl_compiler_rev", buf);
-            goto out;
-        }
-        hdr.asl_compiler_revision = cpu_to_le32(val);
+    if (hdrs->has_asl_compiler_rev) {
+        hdr.asl_compiler_revision = cpu_to_le32(hdrs->asl_compiler_rev);
         ++changed;
     }
 
@@ -239,12 +251,25 @@ int acpi_table_add(const char *t)
         cpu_to_le32(le32_to_cpu(*(uint16_t *)acpi_tables) + 1);
 
     acpi_tables_len = allen;
-    return 0;
 
 out:
-    fprintf(stderr, "%s\n", error_get_pretty(err));
-    error_free(err);
-    return -1;
+    g_strfreev(pathnames);
+
+    if (hdrs != NULL) {
+        QapiDeallocVisitor *dv;
+
+        dv = qapi_dealloc_visitor_new();
+        visit_type_AcpiTableOptions(qapi_dealloc_get_visitor(dv), &hdrs, NULL,
+                                    NULL);
+        qapi_dealloc_visitor_cleanup(dv);
+    }
+
+    if (err) {
+        fprintf(stderr, "%s\n", error_get_pretty(err));
+        error_free(err);
+        return -1;
+    }
+    return 0;
 }
 
 static void acpi_notify_wakeup(Notifier *notifier, void *data)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index b1e06fa..d1bc0de 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -51,6 +51,7 @@
 #include "exec/address-spaces.h"
 #include "sysemu/arch_init.h"
 #include "qemu/bitmap.h"
+#include "qemu/config-file.h"
 
 /* debug PC/ISA interrupts */
 //#define DEBUG_IRQ
@@ -889,6 +890,7 @@ void pc_cpus_init(const char *cpu_model)
 void pc_acpi_init(const char *default_dsdt)
 {
     char *filename = NULL, *arg = NULL;
+    QemuOpts *opts;
 
     if (acpi_tables != NULL) {
         /* manually set via -acpitable, leave it alone */
@@ -902,7 +904,12 @@ void pc_acpi_init(const char *default_dsdt)
     }
 
     arg = g_strdup_printf("file=%s", filename);
-    if (acpi_table_add(arg) != 0) {
+
+    /* creates a deep copy of "arg" */
+    opts = qemu_opts_parse(qemu_find_opts("acpi"), arg, 0);
+    g_assert(opts != NULL);
+
+    if (acpi_table_add(opts) != 0) {
         fprintf(stderr, "WARNING: failed to load %s\n", filename);
     }
     g_free(arg);
diff --git a/hw/pc.h b/hw/pc.h
index c967e9f..613520d 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -113,7 +113,7 @@ extern char unsigned *acpi_tables;
 extern size_t acpi_tables_len;
 
 void acpi_bios_init(void);
-int acpi_table_add(const char *table_desc);
+int acpi_table_add(const QemuOpts *opts);
 
 /* acpi_piix.c */
 
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index 8c8d78e..aed3d1d 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -2,6 +2,7 @@
 #define QEMU_ARCH_INIT_H
 
 #include "qmp-commands.h"
+#include "qemu/option.h"
 
 enum {
     QEMU_ARCH_ALL = -1,
@@ -26,7 +27,7 @@ enum {
 extern const uint32_t arch_type;
 
 void select_soundhw(const char *optarg);
-void do_acpitable_option(const char *optarg);
+void do_acpitable_option(const QemuOpts *opts);
 void do_smbios_option(const char *optarg);
 void cpudef_init(void);
 int audio_available(void);
diff --git a/vl.c b/vl.c
index 0ac9c00..a8bba04 100644
--- a/vl.c
+++ b/vl.c
@@ -3587,7 +3587,9 @@ int main(int argc, char **argv, char **envp)
                 break;
             }
             case QEMU_OPTION_acpitable:
-                do_acpitable_option(optarg);
+                opts = qemu_opts_parse(qemu_find_opts("acpi"), optarg, 1);
+                g_assert(opts != NULL);
+                do_acpitable_option(opts);
                 break;
             case QEMU_OPTION_smbios:
                 do_smbios_option(optarg);
commit 8ccbad5c7b61c46c1b69b8089b8965cd69c0a8de
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:16 2013 +0100

    qapi schema: add AcpiTableOptions
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-5-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qapi-schema.json b/qapi-schema.json
index bfd7a8a..db542f6 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3455,3 +3455,61 @@
 # Since: 1.5
 ##
 { 'command': 'query-tpm', 'returns': ['TPMInfo'] }
+
+##
+# @AcpiTableOptions
+#
+# Specify an ACPI table on the command line to load.
+#
+# At most one of @file and @data can be specified. The list of files specified
+# by any one of them is loaded and concatenated in order. If both are omitted,
+# @data is implied.
+#
+# Other fields / optargs can be used to override fields of the generic ACPI
+# table header; refer to the ACPI specification 5.0, section 5.2.6 System
+# Description Table Header. If a header field is not overridden, then the
+# corresponding value from the concatenated blob is used (in case of @file), or
+# it is filled in with a hard-coded value (in case of @data).
+#
+# String fields are copied into the matching ACPI member from lowest address
+# upwards, and silently truncated / NUL-padded to length.
+#
+# @sig: #optional table signature / identifier (4 bytes)
+#
+# @rev: #optional table revision number (dependent on signature, 1 byte)
+#
+# @oem_id: #optional OEM identifier (6 bytes)
+#
+# @oem_table_id: #optional OEM table identifier (8 bytes)
+#
+# @oem_rev: #optional OEM-supplied revision number (4 bytes)
+#
+# @asl_compiler_id: #optional identifier of the utility that created the table
+#                   (4 bytes)
+#
+# @asl_compiler_rev: #optional revision number of the utility that created the
+#                    table (4 bytes)
+#
+# @file: #optional colon (:) separated list of pathnames to load and
+#        concatenate as table data. The resultant binary blob is expected to
+#        have an ACPI table header. At least one file is required. This field
+#        excludes @data.
+#
+# @data: #optional colon (:) separated list of pathnames to load and
+#        concatenate as table data. The resultant binary blob must not have an
+#        ACPI table header. At least one file is required. This field excludes
+#        @file.
+#
+# Since 1.5
+##
+{ 'type': 'AcpiTableOptions',
+  'data': {
+    '*sig':               'str',
+    '*rev':               'uint8',
+    '*oem_id':            'str',
+    '*oem_table_id':      'str',
+    '*oem_rev':           'uint32',
+    '*asl_compiler_id':   'str',
+    '*asl_compiler_rev':  'uint32',
+    '*file':              'str',
+    '*data':              'str' }}
commit 445d9cae371960671c1d762330d0d498c352dd3c
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:15 2013 +0100

    acpi_table_add(): report fatal errors through an internal Error object
    
    The upcoming changes will need a cleanup section at the end of the
    function, plus OptsVisitor reports errors via Error. For now keep
    channeling any Errors to stderr.
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-4-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/acpi.c b/hw/acpi.c
index d9cf4da..1d1916b 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -64,6 +64,7 @@ static int acpi_checksum(const uint8_t *data, int len)
 /* XXX fixme: this function uses obsolete argument parsing interface */
 int acpi_table_add(const char *t)
 {
+    Error *err = NULL;
     char buf[1024], *p, *f;
     unsigned long val;
     size_t len, start, allen;
@@ -87,8 +88,8 @@ int acpi_table_add(const char *t)
         has_header = true;
         break;
     default:
-        fprintf(stderr, "acpitable: both data and file are specified\n");
-        return -1;
+        error_setg(&err, "acpitable: both data and file are specified");
+        goto out;
     }
 
     if (!acpi_tables) {
@@ -108,8 +109,8 @@ int acpi_table_add(const char *t)
         int fd = open(f, O_RDONLY | O_BINARY);
 
         if (fd < 0) {
-            fprintf(stderr, "can't open file %s: %s\n", f, strerror(errno));
-            return -1;
+            error_setg(&err, "can't open file %s: %s", f, strerror(errno));
+            goto out;
         }
 
         for (;;) {
@@ -122,10 +123,10 @@ int acpi_table_add(const char *t)
                 memcpy(acpi_tables + allen, data, r);
                 allen += r;
             } else if (errno != EINTR) {
-                fprintf(stderr, "can't read file %s: %s\n",
-                        f, strerror(errno));
+                error_setg(&err, "can't read file %s: %s",
+                           f, strerror(errno));
                 close(fd);
-                return -1;
+                goto out;
             }
         }
 
@@ -169,8 +170,8 @@ int acpi_table_add(const char *t)
     if (get_param_value(buf, sizeof(buf), "rev", t)) {
         val = strtoul(buf, &p, 0);
         if (val > 255 || *p) {
-            fprintf(stderr, "acpitable: \"rev=%s\" is invalid\n", buf);
-            return -1;
+            error_setg(&err, "acpitable: \"rev=%s\" is invalid", buf);
+            goto out;
         }
         hdr.revision = (uint8_t)val;
         ++changed;
@@ -191,8 +192,8 @@ int acpi_table_add(const char *t)
     if (get_param_value(buf, sizeof(buf), "oem_rev", t)) {
         val = strtol(buf, &p, 0);
         if (*p) {
-            fprintf(stderr, "acpitable: \"oem_rev=%s\" is invalid\n", buf);
-            return -1;
+            error_setg(&err, "acpitable: \"oem_rev=%s\" is invalid", buf);
+            goto out;
         }
         hdr.oem_revision = cpu_to_le32(val);
         ++changed;
@@ -207,9 +208,9 @@ int acpi_table_add(const char *t)
     if (get_param_value(buf, sizeof(buf), "asl_compiler_rev", t)) {
         val = strtol(buf, &p, 0);
         if (*p) {
-            fprintf(stderr, "acpitable: \"%s=%s\" is invalid\n",
-                    "asl_compiler_rev", buf);
-            return -1;
+            error_setg(&err, "acpitable: \"%s=%s\" is invalid",
+                       "asl_compiler_rev", buf);
+            goto out;
         }
         hdr.asl_compiler_revision = cpu_to_le32(val);
         ++changed;
@@ -240,6 +241,10 @@ int acpi_table_add(const char *t)
     acpi_tables_len = allen;
     return 0;
 
+out:
+    fprintf(stderr, "%s\n", error_get_pretty(err));
+    error_free(err);
+    return -1;
 }
 
 static void acpi_notify_wakeup(Notifier *notifier, void *data)
commit cb88a4ea79193cdbfb9b27bf9deb36c88ec9b6dc
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:14 2013 +0100

    change element type from "char" to "unsigned char" in ACPI table data
    
    The data is binary, not textual.
    
    Also, acpi_table_add() abuses the "char *f" pointer -- which normally
    points to file names to load -- to poke into the table. Introduce "char
    unsigned *table_start" for that purpose.
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-3-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/acpi.c b/hw/acpi.c
index e9b73cf..d9cf4da 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -41,14 +41,14 @@ struct acpi_table_header {
 #define ACPI_TABLE_HDR_SIZE sizeof(struct acpi_table_header)
 #define ACPI_TABLE_PFX_SIZE sizeof(uint16_t)  /* size of the extra prefix */
 
-static const char dfl_hdr[ACPI_TABLE_HDR_SIZE] =
+static const char unsigned dfl_hdr[ACPI_TABLE_HDR_SIZE] =
     "\0\0"                   /* fake _length (2) */
     "QEMU\0\0\0\0\1\0"       /* sig (4), len(4), revno (1), csum (1) */
     "QEMUQEQEMUQEMU\1\0\0\0" /* OEM id (6), table (8), revno (4) */
     "QEMU\1\0\0\0"           /* ASL compiler ID (4), version (4) */
     ;
 
-char *acpi_tables;
+char unsigned *acpi_tables;
 size_t acpi_tables_len;
 
 static int acpi_checksum(const uint8_t *data, int len)
@@ -71,6 +71,7 @@ int acpi_table_add(const char *t)
     int changed;
     int r;
     struct acpi_table_header hdr;
+    char unsigned *table_start;
 
     r = 0;
     r |= get_param_value(buf, sizeof(buf), "data", t) ? 1 : 0;
@@ -112,7 +113,7 @@ int acpi_table_add(const char *t)
         }
 
         for (;;) {
-            char data[8192];
+            char unsigned data[8192];
             r = read(fd, data, sizeof(data));
             if (r == 0) {
                 break;
@@ -133,11 +134,11 @@ int acpi_table_add(const char *t)
 
     /* now fill in the header fields */
 
-    f = acpi_tables + start;   /* start of the table */
+    table_start = acpi_tables + start;   /* start of the table */
     changed = 0;
 
     /* copy the header to temp place to align the fields */
-    memcpy(&hdr, has_header ? f : dfl_hdr, ACPI_TABLE_HDR_SIZE);
+    memcpy(&hdr, has_header ? table_start : dfl_hdr, ACPI_TABLE_HDR_SIZE);
 
     /* length of the table minus our prefix */
     len = allen - start - ACPI_TABLE_PFX_SIZE;
@@ -225,11 +226,11 @@ int acpi_table_add(const char *t)
     hdr.checksum = 0;    /* for checksum calculation */
 
     /* put header back */
-    memcpy(f, &hdr, sizeof(hdr));
+    memcpy(table_start, &hdr, sizeof(hdr));
 
     if (changed || !has_header || 1) {
-        ((struct acpi_table_header *)f)->checksum =
-            acpi_checksum((uint8_t *)f + ACPI_TABLE_PFX_SIZE, len);
+        ((struct acpi_table_header *)table_start)->checksum =
+            acpi_checksum((uint8_t *)table_start + ACPI_TABLE_PFX_SIZE, len);
     }
 
     /* increase number of tables */
diff --git a/hw/pc.h b/hw/pc.h
index 8e1dd4c..c967e9f 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -109,7 +109,7 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name);
 
 /* acpi.c */
 extern int acpi_enabled;
-extern char *acpi_tables;
+extern char unsigned *acpi_tables;
 extern size_t acpi_tables_len;
 
 void acpi_bios_init(void);
commit 4d8b3c6302fe50e9192854d8affda883e078fd4d
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:13 2013 +0100

    strip some whitespace
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-2-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/arch_init.c b/arch_init.c
index 4ef5a15..2ed12fa 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -142,7 +142,7 @@ int qemu_read_default_config_files(bool userconfig)
             return ret;
         }
     }
-    
+
     return 0;
 }
 
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 48f41ca..5284ebc 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -185,7 +185,7 @@
 #define HF2_VINTR_SHIFT      3 /* value of V_INTR_MASKING bit */
 
 #define HF2_GIF_MASK          (1 << HF2_GIF_SHIFT)
-#define HF2_HIF_MASK          (1 << HF2_HIF_SHIFT) 
+#define HF2_HIF_MASK          (1 << HF2_HIF_SHIFT)
 #define HF2_NMI_MASK          (1 << HF2_NMI_SHIFT)
 #define HF2_VINTR_MASK        (1 << HF2_VINTR_SHIFT)
 
diff --git a/vl.c b/vl.c
index 33f30b6..0ac9c00 100644
--- a/vl.c
+++ b/vl.c
@@ -2546,7 +2546,7 @@ static int virtcon_parse(const char *devname)
         qemu_opt_set(bus_opts, "driver", "virtio-serial-s390");
     } else {
         qemu_opt_set(bus_opts, "driver", "virtio-serial-pci");
-    } 
+    }
 
     dev_opts = qemu_opts_create_nofail(device);
     qemu_opt_set(dev_opts, "driver", "virtconsole");
@@ -2598,7 +2598,7 @@ static int sclp_parse(const char *devname)
 }
 
 static int debugcon_parse(const char *devname)
-{   
+{
     QemuOpts *opts;
 
     if (!qemu_chr_new("debugcon", devname, NULL)) {
@@ -3735,8 +3735,8 @@ int main(int argc, char **argv, char **envp)
 			}
 			p += 8;
 			os_set_proc_name(p);
-		     }	
-		 }	
+		     }
+		 }
                 break;
             case QEMU_OPTION_prom_env:
                 if (nb_prom_envs >= MAX_PROM_ENVS) {
commit b9936159ff601562a7bb16b5b9c7713e6cec9559
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Mar 27 20:29:41 2013 +0100

    ipoctal232: Convert to use chardev properties directly
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Alberto Garcia <agarcia at igalia.com>
    Message-id: 1364412581-3672-4-git-send-email-hdegoede at redhat.com
    Cc: Alberto Garcia <agarcia at igalia.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ipoctal232.c b/hw/ipoctal232.c
index 345efae..685fee2 100644
--- a/hw/ipoctal232.c
+++ b/hw/ipoctal232.c
@@ -93,7 +93,6 @@ typedef struct SCC2698Block SCC2698Block;
 struct SCC2698Channel {
     IPOctalState *ipoctal;
     CharDriverState *dev;
-    char *devpath;
     bool rx_enabled;
     uint8_t mr[2];
     uint8_t mr_idx;
@@ -545,26 +544,12 @@ static int ipoctal_init(IPackDevice *ip)
         ch->ipoctal = s;
 
         /* Redirect IP-Octal channels to host character devices */
-        if (ch->devpath) {
-            const char chr_name[] = "ipoctal";
-            char label[ARRAY_SIZE(chr_name) + 2];
-            static int index;
-
-            snprintf(label, sizeof(label), "%s%d", chr_name, index);
-
-            ch->dev = qemu_chr_new(label, ch->devpath, NULL);
-
-            if (ch->dev) {
-                index++;
-                qemu_chr_fe_claim_no_fail(ch->dev);
-                qemu_chr_add_handlers(ch->dev, hostdev_can_receive,
-                                      hostdev_receive, hostdev_event, ch);
-                DPRINTF("Redirecting channel %u to %s (%s)\n",
-                        i, ch->devpath, label);
-            } else {
-                DPRINTF("Could not redirect channel %u to %s\n",
-                        i, ch->devpath);
-            }
+        if (ch->dev) {
+            qemu_chr_add_handlers(ch->dev, hostdev_can_receive,
+                                  hostdev_receive, hostdev_event, ch);
+            DPRINTF("Redirecting channel %u to %s\n", i, ch->dev->label);
+        } else {
+            DPRINTF("Could not redirect channel %u, no chardev set\n", i);
         }
     }
 
@@ -572,14 +557,14 @@ static int ipoctal_init(IPackDevice *ip)
 }
 
 static Property ipoctal_properties[] = {
-    DEFINE_PROP_STRING("serial0", IPOctalState, ch[0].devpath),
-    DEFINE_PROP_STRING("serial1", IPOctalState, ch[1].devpath),
-    DEFINE_PROP_STRING("serial2", IPOctalState, ch[2].devpath),
-    DEFINE_PROP_STRING("serial3", IPOctalState, ch[3].devpath),
-    DEFINE_PROP_STRING("serial4", IPOctalState, ch[4].devpath),
-    DEFINE_PROP_STRING("serial5", IPOctalState, ch[5].devpath),
-    DEFINE_PROP_STRING("serial6", IPOctalState, ch[6].devpath),
-    DEFINE_PROP_STRING("serial7", IPOctalState, ch[7].devpath),
+    DEFINE_PROP_CHR("chardev0", IPOctalState, ch[0].dev),
+    DEFINE_PROP_CHR("chardev1", IPOctalState, ch[1].dev),
+    DEFINE_PROP_CHR("chardev2", IPOctalState, ch[2].dev),
+    DEFINE_PROP_CHR("chardev3", IPOctalState, ch[3].dev),
+    DEFINE_PROP_CHR("chardev4", IPOctalState, ch[4].dev),
+    DEFINE_PROP_CHR("chardev5", IPOctalState, ch[5].dev),
+    DEFINE_PROP_CHR("chardev6", IPOctalState, ch[6].dev),
+    DEFINE_PROP_CHR("chardev7", IPOctalState, ch[7].dev),
     DEFINE_PROP_END_OF_LIST(),
 };
 
commit 456d60692310e7ac25cf822cc1e98192ad636ece
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Mar 27 20:29:40 2013 +0100

    qemu-char: Call fe_claim / fe_release when not using qdev chr properties
    
    chardev-frontends need to explictly check, increase and decrement the
    avail_connections "property" of the chardev when they are not using a
    qdev-chardev-property for the chardev.
    
    This fixes things like:
    qemu-kvm -chardev stdio,id=foo -device isa-serial,chardev=foo \
      -mon chardev=foo
    
    Working, where they should fail. Most of the changes here are due to
    old hardware emulation code which is using serial_hds directly rather then
    a qdev-chardev-property.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364412581-3672-3-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/backends/rng-egd.c b/backends/rng-egd.c
index 5e012e9..cc6f5ee 100644
--- a/backends/rng-egd.c
+++ b/backends/rng-egd.c
@@ -149,6 +149,11 @@ static void rng_egd_opened(RngBackend *b, Error **errp)
         return;
     }
 
+    if (qemu_chr_fe_claim(s->chr) != 0) {
+        error_set(errp, QERR_DEVICE_IN_USE, s->chr_name);
+        return;
+    }
+
     /* FIXME we should resubmit pending requests when the CDS reconnects. */
     qemu_chr_add_handlers(s->chr, rng_egd_chr_can_read, rng_egd_chr_read,
                           NULL, s);
@@ -191,6 +196,7 @@ static void rng_egd_finalize(Object *obj)
 
     if (s->chr) {
         qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
+        qemu_chr_fe_release(s->chr);
     }
 
     g_free(s->chr_name);
diff --git a/gdbstub.c b/gdbstub.c
index a666cb5..a0288a7 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -3025,6 +3025,7 @@ int gdbserver_start(const char *device)
         if (!chr)
             return -1;
 
+        qemu_chr_fe_claim_no_fail(chr);
         qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
                               gdb_chr_event, NULL);
     }
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 7467cca..b7ca511 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -1981,9 +1981,11 @@ static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
     memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
-    if (chr)
+    if (chr) {
+        qemu_chr_fe_claim_no_fail(chr);
         qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
                         pxa2xx_fir_rx, pxa2xx_fir_event, s);
+    }
 
     register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
                     pxa2xx_fir_load, s);
diff --git a/hw/bt-hci-csr.c b/hw/bt-hci-csr.c
index e4ada3c..55c819b 100644
--- a/hw/bt-hci-csr.c
+++ b/hw/bt-hci-csr.c
@@ -439,6 +439,7 @@ CharDriverState *uart_hci_init(qemu_irq wakeup)
     s->chr.opaque = s;
     s->chr.chr_write = csrhci_write;
     s->chr.chr_ioctl = csrhci_ioctl;
+    s->chr.avail_connections = 1;
 
     s->hci = qemu_next_hci();
     s->hci->opaque = s;
diff --git a/hw/ipoctal232.c b/hw/ipoctal232.c
index 1da6a99..345efae 100644
--- a/hw/ipoctal232.c
+++ b/hw/ipoctal232.c
@@ -556,6 +556,7 @@ static int ipoctal_init(IPackDevice *ip)
 
             if (ch->dev) {
                 index++;
+                qemu_chr_fe_claim_no_fail(ch->dev);
                 qemu_chr_add_handlers(ch->dev, hostdev_can_receive,
                                       hostdev_receive, hostdev_event, ch);
                 DPRINTF("Redirecting channel %u to %s (%s)\n",
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index 68a2cf2..af2789e 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -292,6 +292,7 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier *
         fprintf(stderr, "creating eventfd for eventfd %d failed\n", eventfd);
         exit(-1);
     }
+    qemu_chr_fe_claim_no_fail(chr);
 
     /* if MSI is supported we need multiple interrupts */
     if (ivshmem_has_feature(s, IVSHMEM_MSI)) {
diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
index aacf0f0..e5de801 100644
--- a/hw/mcf_uart.c
+++ b/hw/mcf_uart.c
@@ -280,6 +280,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
     s->chr = chr;
     s->irq = irq;
     if (chr) {
+        qemu_chr_fe_claim_no_fail(chr);
         qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
                               mcf_uart_event, s);
     }
diff --git a/hw/sh_serial.c b/hw/sh_serial.c
index 40e797c..4629695 100644
--- a/hw/sh_serial.c
+++ b/hw/sh_serial.c
@@ -396,9 +396,11 @@ void sh_serial_init(MemoryRegion *sysmem,
 
     s->chr = chr;
 
-    if (chr)
+    if (chr) {
+        qemu_chr_fe_claim_no_fail(chr);
         qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
 			      sh_serial_event, s);
+    }
 
     s->eri = eri_source;
     s->rxi = rxi_source;
diff --git a/hw/xen_console.c b/hw/xen_console.c
index a8db6f8..c56ef47 100644
--- a/hw/xen_console.c
+++ b/hw/xen_console.c
@@ -241,9 +241,17 @@ static int con_initialise(struct XenDevice *xendev)
 	return -1;
 
     xen_be_bind_evtchn(&con->xendev);
-    if (con->chr)
-        qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive,
-                              NULL, con);
+    if (con->chr) {
+        if (qemu_chr_fe_claim(con->chr) == 0) {
+            qemu_chr_add_handlers(con->chr, xencons_can_receive,
+                                  xencons_receive, NULL, con);
+        } else {
+            xen_be_printf(xendev, 0,
+                          "xen_console_init error chardev %s already used\n",
+                          con->chr->label);
+            con->chr = NULL;
+        }
+    }
 
     xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
 		  con->ring_ref,
@@ -260,8 +268,10 @@ static void con_disconnect(struct XenDevice *xendev)
     if (!xendev->dev) {
         return;
     }
-    if (con->chr)
+    if (con->chr) {
         qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
+        qemu_chr_fe_release(con->chr);
+    }
     xen_be_unbind_evtchn(&con->xendev);
 
     if (con->sring) {
diff --git a/net/slirp.c b/net/slirp.c
index 4df550f..eabfee6 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -660,6 +660,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
         fwd->port = port;
         fwd->slirp = s->slirp;
 
+        qemu_chr_fe_claim_no_fail(fwd->hd);
         qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
                               NULL, fwd);
     }
diff --git a/qemu-char.c b/qemu-char.c
index 100f9a9..e5eb8dd 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3411,6 +3411,7 @@ CharDriverState *qemu_chr_new(const char *label, const char *filename, void (*in
         error_free(err);
     }
     if (chr && qemu_opt_get_bool(opts, "mux", 0)) {
+        qemu_chr_fe_claim_no_fail(chr);
         monitor_init(chr, MONITOR_USE_READLINE);
     }
     return chr;
@@ -3523,9 +3524,16 @@ CharDriverState *qemu_chr_find(const char *name)
 CharDriverState *qemu_char_get_next_serial(void)
 {
     static int next_serial;
+    CharDriverState *chr;
 
     /* FIXME: This function needs to go away: use chardev properties!  */
-    return serial_hds[next_serial++];
+
+    while (next_serial < MAX_SERIAL_PORTS && serial_hds[next_serial]) {
+        chr = serial_hds[next_serial++];
+        qemu_chr_fe_claim_no_fail(chr);
+        return chr;
+    }
+    return NULL;
 }
 
 QemuOptsList qemu_chardev_opts = {
diff --git a/vl.c b/vl.c
index e2c9706..33f30b6 100644
--- a/vl.c
+++ b/vl.c
@@ -2396,6 +2396,7 @@ static int mon_init_func(QemuOpts *opts, void *opaque)
         exit(1);
     }
 
+    qemu_chr_fe_claim_no_fail(chr);
     monitor_init(chr, flags);
     return 0;
 }
commit 44c473decd4de5559487430f876de53c607b1e9d
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Mar 27 20:29:39 2013 +0100

    qemu-char: Add qemu_chr_fe_claim / _release helper functions
    
    Add qemu_chr_fe_claim / _release helper functions for properly dealing with
    avail_connections.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364412581-3672-2-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c
index d9934b5..a22b155 100644
--- a/hw/qdev-properties-system.c
+++ b/hw/qdev-properties-system.c
@@ -123,11 +123,10 @@ static int parse_chr(DeviceState *dev, const char *str, void **ptr)
     if (chr == NULL) {
         return -ENOENT;
     }
-    if (chr->avail_connections < 1) {
+    if (qemu_chr_fe_claim(chr) != 0) {
         return -EEXIST;
     }
     *ptr = chr;
-    --chr->avail_connections;
     return 0;
 }
 
@@ -140,7 +139,7 @@ static void release_chr(Object *obj, const char *name, void *opaque)
 
     if (chr) {
         qemu_chr_add_handlers(chr, NULL, NULL, NULL, NULL);
-        ++chr->avail_connections;
+        qemu_chr_fe_release(chr);
     }
 }
 
diff --git a/include/char/char.h b/include/char/char.h
index 32c9999..9d1ea46 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -203,6 +203,35 @@ int qemu_chr_fe_ioctl(CharDriverState *s, int cmd, void *arg);
 int qemu_chr_fe_get_msgfd(CharDriverState *s);
 
 /**
+ * @qemu_chr_fe_claim:
+ *
+ * Claim a backend before using it, should be called before calling
+ * qemu_chr_add_handlers(). 
+ *
+ * Returns: -1 if the backend is already in use by another frontend, 0 on
+ *          success.
+ */
+int qemu_chr_fe_claim(CharDriverState *s);
+
+/**
+ * @qemu_chr_fe_claim_no_fail:
+ *
+ * Like qemu_chr_fe_claim, but will exit qemu with an error when the
+ * backend is already in use.
+ */
+void qemu_chr_fe_claim_no_fail(CharDriverState *s);
+
+/**
+ * @qemu_chr_fe_claim:
+ *
+ * Release a backend for use by another frontend.
+ *
+ * Returns: -1 if the backend is already in use by another frontend, 0 on
+ *          success.
+ */
+void qemu_chr_fe_release(CharDriverState *s);
+
+/**
  * @qemu_chr_be_can_write:
  *
  * Determine how much data the front end can currently accept.  This function
diff --git a/qemu-char.c b/qemu-char.c
index 505a773..100f9a9 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3452,6 +3452,29 @@ int qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
     return tag;
 }
 
+int qemu_chr_fe_claim(CharDriverState *s)
+{
+    if (s->avail_connections < 1) {
+        return -1;
+    }
+    s->avail_connections--;
+    return 0;
+}
+
+void qemu_chr_fe_claim_no_fail(CharDriverState *s)
+{
+    if (qemu_chr_fe_claim(s) != 0) {
+        fprintf(stderr, "%s: error chardev \"%s\" already used\n",
+                __func__, s->label);
+        exit(1);
+    }
+}
+
+void qemu_chr_fe_release(CharDriverState *s)
+{
+    s->avail_connections++;
+}
+
 void qemu_chr_delete(CharDriverState *chr)
 {
     QTAILQ_REMOVE(&chardevs, chr, next);
commit 4dbb9ed3263e0f48282a2fc3d05099ba63e5b0e2
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Wed Apr 3 14:04:09 2013 +1000

    xilinx_axienet: pump events as appropriate
    
    When the conditions blocking receiving are cleared, check for buffered rx
    packets.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index 5785290..07c4bad 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -516,6 +516,8 @@ static void enet_write(void *opaque, hwaddr addr,
             s->rcw[addr & 1] = value;
             if ((addr & 1) && value & RCW1_RST) {
                 axienet_rx_reset(s);
+            } else {
+                qemu_flush_queued_packets(qemu_get_queue(s->nic));
             }
             break;
 
commit bd4a47330ed5b9661205dd4ac2023e452b856bf9
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Apr 2 11:28:25 2013 +0200

    po: Update German translation
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/po/de_DE.po b/po/de_DE.po
index 2566674..92c5df5 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -18,27 +18,27 @@ msgstr ""
 
 #: ../ui/gtk.c:213
 msgid " - Press Ctrl+Alt+G to release grab"
-msgstr ""
+msgstr "- Strg+Alt+G drücken, um Eingabegeräte freizugeben"
 
 #: ../ui/gtk.c:217
 msgid " [Paused]"
-msgstr ""
+msgstr "[Angehalten]"
 
 #: ../ui/gtk.c:1250
 msgid "_Machine"
-msgstr ""
+msgstr "_Maschine"
 
 #: ../ui/gtk.c:1252
 msgid "_Pause"
-msgstr ""
+msgstr "_Angehalten"
 
 #: ../ui/gtk.c:1258
 msgid "_Reset"
-msgstr ""
+msgstr "_Reset"
 
 #: ../ui/gtk.c:1261
 msgid "Power _Down"
-msgstr ""
+msgstr "_Herunterfahren"
 
 #: ../ui/gtk.c:1276
 msgid "_View"
commit a23da65924fffc6390f74e75afd33f5300091b4e
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Apr 2 11:28:24 2013 +0200

    po/Makefile: Fix dependency for %.mo
    
    Otherwise make will refuse to build updated .po files.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/po/Makefile b/po/Makefile
index 8297ab5..60ccd7d 100644
--- a/po/Makefile
+++ b/po/Makefile
@@ -30,7 +30,7 @@ install: $(OBJS)
 	    $(INSTALL) -m644 $$obj $(DESTDIR)$(prefix)/share/locale/$$base/LC_MESSAGES/qemu.mo; \
 	done
 
-%.mo:
+%.mo: %.po
 	@msgfmt -o $@ $(SRC_PATH)/po/`basename $@ .mo`.po
 
 messages.po: $(SRC_PATH)/ui/gtk.c
commit ec3960148f95dd90e94511a6a64838bc3f474bcc
Author: Jason Wang <jasowang at redhat.com>
Date:   Fri Feb 22 22:57:52 2013 +0800

    help: add docs for missing 'queues' option of tap
    
    Cc: Markus Armbruster <armbru at redhat.com>
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Message-id: 1361545072-30426-1-git-send-email-jasowang at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qapi-schema.json b/qapi-schema.json
index f629a24..bfd7a8a 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2591,6 +2591,8 @@
 #
 # @vhostforce: #optional vhost on for non-MSIX virtio guests
 #
+# @queues: #optional number of queues to be created for multiqueue capable tap
+#
 # Since 1.2
 ##
 { 'type': 'NetdevTapOptions',
diff --git a/qemu-options.hx b/qemu-options.hx
index c40ba55..7cd6002 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1360,7 +1360,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
     "-net tap[,vlan=n][,name=str],ifname=name\n"
     "                connect the host TAP network interface to VLAN 'n'\n"
 #else
-    "-net tap[,vlan=n][,name=str][,fd=h][,fds=x:y:...:z][,ifname=name][,script=file][,downscript=dfile][,helper=helper][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostfds=x:y:...:z][,vhostforce=on|off]\n"
+    "-net tap[,vlan=n][,name=str][,fd=h][,fds=x:y:...:z][,ifname=name][,script=file][,downscript=dfile][,helper=helper][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostfds=x:y:...:z][,vhostforce=on|off][,queues=n]\n"
     "                connect the host TAP network interface to VLAN 'n'\n"
     "                use network scripts 'file' (default=" DEFAULT_NETWORK_SCRIPT ")\n"
     "                to configure it and 'dfile' (default=" DEFAULT_NETWORK_DOWN_SCRIPT ")\n"
@@ -1379,6 +1379,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
     "                use vhostforce=on to force vhost on for non-MSIX virtio guests\n"
     "                use 'vhostfd=h' to connect to an already opened vhost net device\n"
     "                use 'vhostfds=x:y:...:z to connect to multiple already opened vhost net devices\n"
+    "                use 'queues=n' to specify the number of queues to be created for multiqueue TAP\n"
     "-net bridge[,vlan=n][,name=str][,br=bridge][,helper=helper]\n"
     "                connects a host TAP network interface to a host bridge device 'br'\n"
     "                (default=" DEFAULT_BRIDGE_INTERFACE ") using the program 'helper'\n"
commit 560e63965232e37d1916a447125cf91c18a96930
Author: Bruce Rogers <brogers at suse.com>
Date:   Tue Apr 2 12:41:40 2013 -0600

    acpi: initialize s4_val used in s4 shutdown
    
    While investigating why a 32 bit Windows 2003 guest wasn't able to
    successfully perform a shutdown /h, it was discovered that commit
    afafe4bbe0cf7d3318e1ac7b40925561f86a6bd4 inadvertently dropped the
    initialization of the s4_val used to handle s4 shutdown.
    Initialize the value as before.
    
    Signed-off-by: Bruce Rogers <brogers at suse.com>
    Message-id: 1364928100-487-1-git-send-email-brogers at suse.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/acpi.c b/hw/acpi.c
index 53e47d5..e9b73cf 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -472,8 +472,9 @@ static const MemoryRegionOps acpi_pm_cnt_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
-void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent)
+void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, uint8_t s4_val)
 {
+    ar->pm1.cnt.s4_val = s4_val;
     ar->wakeup.notify = acpi_notify_wakeup;
     qemu_register_wakeup_notifier(&ar->wakeup);
     memory_region_init_io(&ar->pm1.cnt.io, &acpi_pm_cnt_ops, ar, "acpi-cnt", 2);
diff --git a/hw/acpi.h b/hw/acpi.h
index c3628d0..e18ef28 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -142,7 +142,7 @@ void acpi_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci,
                        MemoryRegion *parent);
 
 /* PM1a_CNT: piix and ich9 don't implement PM1b CNT. */
-void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent);
+void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, uint8_t s4_val);
 void acpi_pm1_cnt_update(ACPIREGS *ar,
                          bool sci_enable, bool sci_disable);
 void acpi_pm1_cnt_reset(ACPIREGS *ar);
diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index 29f84ff..7b34a03 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -212,7 +212,7 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
 
     acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
     acpi_pm1_evt_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
-    acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io);
+    acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io, 2);
 
     acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
     memory_region_init_io(&pm->io_gpe, &ich9_gpe_ops, pm, "apci-gpe0",
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 7a4b712..48a32b5 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -418,7 +418,7 @@ static int piix4_pm_initfn(PCIDevice *dev)
 
     acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
     acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
-    acpi_pm1_cnt_init(&s->ar, &s->io);
+    acpi_pm1_cnt_init(&s->ar, &s->io, s->s4_val);
     acpi_gpe_init(&s->ar, GPE_LEN);
 
     s->powerdown_notifier.notify = piix4_pm_powerdown_req;
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 4529508..9d9b64e 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -360,7 +360,7 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
 
     acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
     acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
-    acpi_pm1_cnt_init(&s->ar, &s->io);
+    acpi_pm1_cnt_init(&s->ar, &s->io, 2);
 
     return 0;
 }
commit a509d632c877f7b5fa07368879b8ae5919a6d345
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Tue Apr 2 17:48:12 2013 -0300

    target-i386: Check for host features before filter_features_for_kvm()
    
    commit 5ec01c2e96910e1588d1a0de8609b9dda7618c7f broke "-cpu ..,enforce",
    as it has moved kvm_check_features_against_host() after the
    filter_features_for_kvm() call. filter_features_for_kvm() removes all
    features not supported by the host, so this effectively made
    kvm_check_features_against_host() impossible to fail.
    
    This patch changes the call so we check for host feature support before
    filtering the feature bits.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Message-id: 1364935692-24004-1-git-send-email-ehabkost at redhat.com
    Cc: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 4b43759..bf717d5 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2131,14 +2131,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
         env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
         env->cpuid_svm_features &= TCG_SVM_FEATURES;
     } else {
-#ifdef CONFIG_KVM
-        filter_features_for_kvm(cpu);
-#endif
         if (check_cpuid && kvm_check_features_against_host(cpu)
             && enforce_cpuid) {
             error_setg(errp, "Host's CPU doesn't support requested features");
             return;
         }
+#ifdef CONFIG_KVM
+        filter_features_for_kvm(cpu);
+#endif
     }
 
 #ifndef CONFIG_USER_ONLY
commit 8243b0464b247ff460178a15f1fe306ef9c70b49
Author: Stefan Weil <sw at weilnetz.de>
Date:   Tue Apr 2 22:14:51 2013 +0200

    tpm: Fix several compiler warnings (redefined data types)
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Message-id: 1364933691-21197-1-git-send-email-sw at weilnetz.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/tpm/tpm_int.h b/tpm/tpm_int.h
index b4787ad..340bfd5 100644
--- a/tpm/tpm_int.h
+++ b/tpm/tpm_int.h
@@ -15,11 +15,8 @@
 #include "exec/memory.h"
 #include "tpm/tpm_tis.h"
 
-struct TPMDriverOps;
-typedef struct TPMDriverOps TPMDriverOps;
-
 /* overall state of the TPM interface */
-typedef struct TPMState {
+struct TPMState {
     ISADevice busdev;
     MemoryRegion mmio;
 
@@ -32,12 +29,10 @@ typedef struct TPMState {
 
     char *backend;
     TPMBackend *be_driver;
-} TPMState;
+};
 
 #define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS)
 
-typedef void (TPMRecvDataCB)(TPMState *, uint8_t locty);
-
 struct TPMDriverOps {
     enum TpmType type;
     /* get a descriptive text of the backend to display to the user */
diff --git a/tpm/tpm_tis.h b/tpm/tpm_tis.h
index 0c8df80..7f216e5 100644
--- a/tpm/tpm_tis.h
+++ b/tpm/tpm_tis.h
@@ -35,10 +35,10 @@
 #define TYPE_TPM_TIS                "tpm-tis"
 
 
-typedef struct TPMSizedBuffer {
+struct TPMSizedBuffer {
     uint32_t size;
     uint8_t  *buffer;
-} TPMSizedBuffer;
+};
 
 typedef enum {
     TPM_TIS_STATE_IDLE = 0,
commit eabb21aac9665097676b97fa3e053ae2982eba1e
Merge: 162cbbd 044d4e1
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Apr 3 15:05:52 2013 -0500

    Merge remote-tracking branch 'sstabellini/xen-2013-04-03' into staging
    
    # By Hanweidong (1) and Stefano Stabellini (1)
    # Via Stefano Stabellini
    * sstabellini/xen-2013-04-03:
      xen-mapcache: pass the right size argument to test_bits
      xen-mapcache: replace last_address_index with a last_entry pointer

commit 044d4e1aae539bd4214175bd9591b3de7986cf18
Author: Hanweidong <hanweidong at huawei.com>
Date:   Tue Apr 2 13:22:41 2013 +0000

    xen-mapcache: pass the right size argument to test_bits
    
    Compute the correct size for test_bits().
    qemu_get_ram_ptr() and qemu_safe_ram_ptr() will call xen_map_cache()
    with size is 0 if the requested address is in the RAM.  Then
    xen_map_cache() will pass the size 0 to test_bits() for checking if the
    corresponding pfn was mapped in cache. But test_bits() will always
    return 1 when size is 0 without any bit testing. Actually, for this
    case, test_bits should check one bit. So this patch introduced a
    __test_bit_size which is greater than 0 and a multiple of XC_PAGE_SIZE,
    then test_bits can work correctly with __test_bit_size
    >> XC_PAGE_SHIFT as its size.
    
    Signed-off-by: Zhenguo Wang <wangzhenguo at huawei.com>
    Signed-off-by: Weidong Han <hanweidong at huawei.com>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/xen-mapcache.c b/xen-mapcache.c
index a80cbdb..5a626cd 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -200,6 +200,7 @@ uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size,
     hwaddr address_index;
     hwaddr address_offset;
     hwaddr __size = size;
+    hwaddr __test_bit_size = size;
     bool translated = false;
 
 tryagain:
@@ -208,9 +209,23 @@ tryagain:
 
     trace_xen_map_cache(phys_addr);
 
+    /* __test_bit_size is always a multiple of XC_PAGE_SIZE */
+    if (size) {
+        __test_bit_size = size + (phys_addr & (XC_PAGE_SIZE - 1));
+
+        if (__test_bit_size % XC_PAGE_SIZE) {
+            __test_bit_size += XC_PAGE_SIZE - (__test_bit_size % XC_PAGE_SIZE);
+        }
+    } else {
+        __test_bit_size = XC_PAGE_SIZE;
+    }
+
     if (mapcache->last_entry != NULL &&
         mapcache->last_entry->paddr_index == address_index &&
-        !lock && !__size) {
+        !lock && !__size &&
+        test_bits(address_offset >> XC_PAGE_SHIFT,
+                  __test_bit_size >> XC_PAGE_SHIFT,
+                  mapcache->last_entry->valid_mapping)) {
         trace_xen_map_cache_return(mapcache->last_entry->vaddr_base + address_offset);
         return mapcache->last_entry->vaddr_base + address_offset;
     }
@@ -229,7 +244,8 @@ tryagain:
 
     while (entry && entry->lock && entry->vaddr_base &&
             (entry->paddr_index != address_index || entry->size != __size ||
-             !test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT,
+             !test_bits(address_offset >> XC_PAGE_SHIFT,
+                 __test_bit_size >> XC_PAGE_SHIFT,
                  entry->valid_mapping))) {
         pentry = entry;
         entry = entry->next;
@@ -241,13 +257,15 @@ tryagain:
     } else if (!entry->lock) {
         if (!entry->vaddr_base || entry->paddr_index != address_index ||
                 entry->size != __size ||
-                !test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT,
+                !test_bits(address_offset >> XC_PAGE_SHIFT,
+                    __test_bit_size >> XC_PAGE_SHIFT,
                     entry->valid_mapping)) {
             xen_remap_bucket(entry, __size, address_index);
         }
     }
 
-    if(!test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT,
+    if(!test_bits(address_offset >> XC_PAGE_SHIFT,
+                __test_bit_size >> XC_PAGE_SHIFT,
                 entry->valid_mapping)) {
         mapcache->last_entry = NULL;
         if (!translated && mapcache->phys_offset_to_gaddr) {
commit e2deee3ea6136b6189e8cfd26379420b9a398d96
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Tue Apr 2 13:23:40 2013 +0000

    xen-mapcache: replace last_address_index with a last_entry pointer
    
    Replace last_address_index and last_address_vaddr with a single pointer
    to the last MapCacheEntry used.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/xen-mapcache.c b/xen-mapcache.c
index dc6d1fa..a80cbdb 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -74,8 +74,7 @@ typedef struct MapCache {
     QTAILQ_HEAD(map_cache_head, MapCacheRev) locked_entries;
 
     /* For most cases (>99.9%), the page address is the same. */
-    hwaddr last_address_index;
-    uint8_t *last_address_vaddr;
+    MapCacheEntry *last_entry;
     unsigned long max_mcache_size;
     unsigned int mcache_bucket_shift;
 
@@ -105,7 +104,6 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
     mapcache->opaque = opaque;
 
     QTAILQ_INIT(&mapcache->locked_entries);
-    mapcache->last_address_index = -1;
 
     if (geteuid() == 0) {
         rlimit_as.rlim_cur = RLIM_INFINITY;
@@ -210,9 +208,11 @@ tryagain:
 
     trace_xen_map_cache(phys_addr);
 
-    if (address_index == mapcache->last_address_index && !lock && !__size) {
-        trace_xen_map_cache_return(mapcache->last_address_vaddr + address_offset);
-        return mapcache->last_address_vaddr + address_offset;
+    if (mapcache->last_entry != NULL &&
+        mapcache->last_entry->paddr_index == address_index &&
+        !lock && !__size) {
+        trace_xen_map_cache_return(mapcache->last_entry->vaddr_base + address_offset);
+        return mapcache->last_entry->vaddr_base + address_offset;
     }
 
     /* size is always a multiple of MCACHE_BUCKET_SIZE */
@@ -249,7 +249,7 @@ tryagain:
 
     if(!test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT,
                 entry->valid_mapping)) {
-        mapcache->last_address_index = -1;
+        mapcache->last_entry = NULL;
         if (!translated && mapcache->phys_offset_to_gaddr) {
             phys_addr = mapcache->phys_offset_to_gaddr(phys_addr, size, mapcache->opaque);
             translated = true;
@@ -259,19 +259,18 @@ tryagain:
         return NULL;
     }
 
-    mapcache->last_address_index = address_index;
-    mapcache->last_address_vaddr = entry->vaddr_base;
+    mapcache->last_entry = entry;
     if (lock) {
         MapCacheRev *reventry = g_malloc0(sizeof(MapCacheRev));
         entry->lock++;
-        reventry->vaddr_req = mapcache->last_address_vaddr + address_offset;
-        reventry->paddr_index = mapcache->last_address_index;
+        reventry->vaddr_req = mapcache->last_entry->vaddr_base + address_offset;
+        reventry->paddr_index = mapcache->last_entry->paddr_index;
         reventry->size = entry->size;
         QTAILQ_INSERT_HEAD(&mapcache->locked_entries, reventry, next);
     }
 
-    trace_xen_map_cache_return(mapcache->last_address_vaddr + address_offset);
-    return mapcache->last_address_vaddr + address_offset;
+    trace_xen_map_cache_return(mapcache->last_entry->vaddr_base + address_offset);
+    return mapcache->last_entry->vaddr_base + address_offset;
 }
 
 ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
@@ -338,9 +337,9 @@ void xen_invalidate_map_cache_entry(uint8_t *buffer)
     QTAILQ_REMOVE(&mapcache->locked_entries, reventry, next);
     g_free(reventry);
 
-    if (mapcache->last_address_index == paddr_index) {
-        mapcache->last_address_index = -1;
-        mapcache->last_address_vaddr = NULL;
+    if (mapcache->last_entry != NULL &&
+        mapcache->last_entry->paddr_index == paddr_index) {
+        mapcache->last_entry = NULL;
     }
 
     entry = &mapcache->entry[paddr_index % mapcache->nr_buckets];
@@ -404,8 +403,7 @@ void xen_invalidate_map_cache(void)
         entry->valid_mapping = NULL;
     }
 
-    mapcache->last_address_index = -1;
-    mapcache->last_address_vaddr = NULL;
+    mapcache->last_entry = NULL;
 
     mapcache_unlock();
 }
commit 162cbbd1736de2bca43fdefa7e98c54a361ee60d
Merge: 9d4563c 9b938c7
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Apr 2 14:07:35 2013 -0500

    Merge remote-tracking branch 'luiz/queue/qmp' into staging
    
    # By Stefan Hajnoczi
    # Via Luiz Capitulino
    * luiz/queue/qmp:
      chardev: clear O_NONBLOCK on SCM_RIGHTS file descriptors
      qemu-socket: set passed fd non-blocking in socket_connect()
      net: ensure "socket" backend uses non-blocking fds
      oslib-posix: rename socket_set_nonblock() to qemu_set_nonblock()

commit 9d4563c415683e4d06c84a46e8d178a680fdcb7b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Apr 2 17:57:56 2013 +0200

    configure: remove unset variables
    
    These variables have not been set for a long time.  Do not
    include them in config-host.mak.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1364918276-11866-1-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index fbea75e..d685275 100755
--- a/configure
+++ b/configure
@@ -3899,8 +3899,6 @@ else
   echo "AUTOCONF_HOST := "                             >> $config_host_mak
 fi
 echo "LDFLAGS=$LDFLAGS" >> $config_host_mak
-echo "ARLIBS_BEGIN=$arlibs_begin" >> $config_host_mak
-echo "ARLIBS_END=$arlibs_end" >> $config_host_mak
 echo "LIBS+=$LIBS" >> $config_host_mak
 echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
 echo "EXESUF=$EXESUF" >> $config_host_mak
commit 9b938c7262e403f5467110609cb20ef1ae6e9df2
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 27 10:10:46 2013 +0100

    chardev: clear O_NONBLOCK on SCM_RIGHTS file descriptors
    
    When we receive a file descriptor over a UNIX domain socket the
    O_NONBLOCK flag is preserved.  Clear the O_NONBLOCK flag and rely on
    QEMU file descriptor users like migration, SPICE, VNC, block layer, and
    others to set non-blocking only when necessary.
    
    This change ensures we don't accidentally expose O_NONBLOCK in the QMP
    API.  QMP clients should not need to get the non-blocking state
    "correct".
    
    A recent real-world example was when libvirt passed a non-blocking TCP
    socket for migration where we expected a blocking socket.  The source
    QEMU produced a corrupted migration stream since its code did not cope
    with non-blocking sockets.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qemu-char.c b/qemu-char.c
index 4d8c6ca..d825b60 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2440,6 +2440,9 @@ static void unix_process_msgfd(CharDriverState *chr, struct msghdr *msg)
         if (fd < 0)
             continue;
 
+        /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
+        qemu_set_block(fd);
+
 #ifndef MSG_CMSG_CLOEXEC
         qemu_set_cloexec(fd);
 #endif
commit 1a751ebfbb2d7a696b889d8208cb5ffc83c090b1
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 27 10:10:45 2013 +0100

    qemu-socket: set passed fd non-blocking in socket_connect()
    
    socket_connect() sets non-blocking on TCP or UNIX domain sockets if a
    callback function is passed.  Do the same for file descriptor passing,
    otherwise we could unexpectedly be using a blocking file descriptor.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index b632a74..94581aa 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -910,6 +910,7 @@ int socket_connect(SocketAddress *addr, Error **errp,
     case SOCKET_ADDRESS_KIND_FD:
         fd = monitor_get_fd(cur_mon, addr->fd->str, errp);
         if (callback) {
+            qemu_set_nonblock(fd);
             callback(fd, opaque);
         }
         break;
commit fc13fa00eaff6797c67abc9b0f748b346f238986
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 27 10:10:44 2013 +0100

    net: ensure "socket" backend uses non-blocking fds
    
    There are several code paths in net_init_socket() depending on how the
    socket is created: file descriptor passing, UDP multicast, TCP, or UDP.
    Some of these support both listen and connect.
    
    Not all code paths set the socket to non-blocking.  This patch addresses
    the file descriptor passing and UDP cases which were missing
    socket_set_nonblock(fd) calls.
    
    I considered moving socket_set_nonblock(fd) to a central location but it
    turns out the code paths are different enough to require non-blocking at
    different places.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/net/socket.c b/net/socket.c
index b5c8e65..87af1d3 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -674,6 +674,7 @@ static int net_socket_udp_init(NetClientState *peer,
         closesocket(fd);
         return -1;
     }
+    qemu_set_nonblock(fd);
 
     s = net_socket_fd_init(peer, model, name, fd, 0);
     if (!s) {
@@ -712,7 +713,11 @@ int net_init_socket(const NetClientOptions *opts, const char *name,
         int fd;
 
         fd = monitor_handle_fd_param(cur_mon, sock->fd);
-        if (fd == -1 || !net_socket_fd_init(peer, "socket", name, fd, 1)) {
+        if (fd == -1) {
+            return -1;
+        }
+        qemu_set_nonblock(fd);
+        if (!net_socket_fd_init(peer, "socket", name, fd, 1)) {
             return -1;
         }
         return 0;
commit f9e8cacc5557e4372401da74141f833fcacda038
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 27 10:10:43 2013 +0100

    oslib-posix: rename socket_set_nonblock() to qemu_set_nonblock()
    
    The fcntl(fd, F_SETFL, O_NONBLOCK) flag is not specific to sockets.
    Rename to qemu_set_nonblock() just like qemu_set_cloexec().
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/block/nbd.c b/block/nbd.c
index 3d711b2..eff683c 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -415,7 +415,7 @@ static int nbd_establish_connection(BlockDriverState *bs)
 
     /* Now that we're connected, set the socket to be non-blocking and
      * kick the reply mechanism.  */
-    socket_set_nonblock(sock);
+    qemu_set_nonblock(sock);
     qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL,
                             nbd_have_request, s);
 
diff --git a/block/sheepdog.c b/block/sheepdog.c
index bb67c4c..987018e 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -471,7 +471,7 @@ static int connect_to_sdog(BDRVSheepdogState *s)
         qerror_report_err(err);
         error_free(err);
     } else {
-        socket_set_nonblock(fd);
+        qemu_set_nonblock(fd);
     }
 
     return fd;
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index d225f6d..c5174d7 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -37,8 +37,8 @@ int qemu_socket(int domain, int type, int protocol);
 int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
 int socket_set_cork(int fd, int v);
 int socket_set_nodelay(int fd);
-void socket_set_block(int fd);
-void socket_set_nonblock(int fd);
+void qemu_set_block(int fd);
+void qemu_set_nonblock(int fd);
 int send_all(int fd, const void *buf, int len1);
 int recv_all(int fd, void *buf, int len1, bool single_read);
 
diff --git a/migration.c b/migration.c
index 7fb2147..3b4b467 100644
--- a/migration.c
+++ b/migration.c
@@ -121,7 +121,7 @@ void process_incoming_migration(QEMUFile *f)
     int fd = qemu_get_fd(f);
 
     assert(fd != -1);
-    socket_set_nonblock(fd);
+    qemu_set_nonblock(fd);
     qemu_coroutine_enter(co, f);
 }
 
diff --git a/nbd.c b/nbd.c
index d1a67ee..85187ff 100644
--- a/nbd.c
+++ b/nbd.c
@@ -386,7 +386,7 @@ static int nbd_send_negotiate(NBDClient *client)
         [28 .. 151]   reserved     (0)
      */
 
-    socket_set_block(csock);
+    qemu_set_block(csock);
     rc = -EINVAL;
 
     TRACE("Beginning negotiation.");
@@ -429,7 +429,7 @@ static int nbd_send_negotiate(NBDClient *client)
     TRACE("Negotiation succeeded.");
     rc = 0;
 fail:
-    socket_set_nonblock(csock);
+    qemu_set_nonblock(csock);
     return rc;
 }
 
@@ -443,7 +443,7 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
 
     TRACE("Receiving negotiation.");
 
-    socket_set_block(csock);
+    qemu_set_block(csock);
     rc = -EINVAL;
 
     if (read_sync(csock, buf, 8) != 8) {
@@ -558,7 +558,7 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
     rc = 0;
 
 fail:
-    socket_set_nonblock(csock);
+    qemu_set_nonblock(csock);
     return rc;
 }
 
diff --git a/net/socket.c b/net/socket.c
index 6c3752b..b5c8e65 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -308,7 +308,7 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
         }
     }
 
-    socket_set_nonblock(fd);
+    qemu_set_nonblock(fd);
     return fd;
 fail:
     if (fd >= 0)
@@ -519,7 +519,7 @@ static int net_socket_listen_init(NetClientState *peer,
         perror("socket");
         return -1;
     }
-    socket_set_nonblock(fd);
+    qemu_set_nonblock(fd);
 
     /* allow fast reuse */
     val = 1;
@@ -565,7 +565,7 @@ static int net_socket_connect_init(NetClientState *peer,
         perror("socket");
         return -1;
     }
-    socket_set_nonblock(fd);
+    qemu_set_nonblock(fd);
 
     connected = 0;
     for(;;) {
diff --git a/qemu-char.c b/qemu-char.c
index dee623e..4d8c6ca 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2570,7 +2570,7 @@ static int tcp_chr_add_client(CharDriverState *chr, int fd)
     if (s->fd != -1)
 	return -1;
 
-    socket_set_nonblock(fd);
+    qemu_set_nonblock(fd);
     if (s->do_nodelay)
         socket_set_nodelay(fd);
     s->fd = fd;
@@ -2722,7 +2722,7 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
         printf("QEMU waiting for connection on: %s\n",
                chr->filename);
         tcp_chr_accept(s->listen_chan, G_IO_IN, chr);
-        socket_set_nonblock(s->listen_fd);
+        qemu_set_nonblock(s->listen_fd);
     }
     return chr;
 }
@@ -2764,7 +2764,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     }
 
     if (!is_waitconnect)
-        socket_set_nonblock(fd);
+        qemu_set_nonblock(fd);
 
     chr = qemu_chr_open_socket_fd(fd, do_nodelay, is_listen, is_telnet,
                                   is_waitconnect, &local_err);
@@ -3653,7 +3653,7 @@ static CharDriverState *qmp_chardev_open_serial(ChardevHostdev *serial,
     if (error_is_set(errp)) {
         return NULL;
     }
-    socket_set_nonblock(fd);
+    qemu_set_nonblock(fd);
     return qemu_chr_open_tty_fd(fd);
 #else
     error_setg(errp, "character device backend type 'serial' not supported");
diff --git a/savevm.c b/savevm.c
index 406caa9..b1d8988 100644
--- a/savevm.c
+++ b/savevm.c
@@ -422,7 +422,7 @@ QEMUFile *qemu_fopen_socket(int fd, const char *mode)
 
     s->fd = fd;
     if (mode[0] == 'w') {
-        socket_set_block(s->fd);
+        qemu_set_block(s->fd);
         s->file = qemu_fopen_ops(s, &socket_write_ops);
     } else {
         s->file = qemu_fopen_ops(s, &socket_read_ops);
diff --git a/slirp/misc.c b/slirp/misc.c
index 6b9c2c4..8ecced5 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -215,7 +215,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
                 qemu_setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
                 opt = 1;
                 qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
-		socket_set_nonblock(so->s);
+		qemu_set_nonblock(so->s);
 
 		/* Append the telnet options now */
                 if (so->so_m != NULL && do_pty == 1)  {
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 84a6bb5..e98ce1a 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -336,7 +336,7 @@ int tcp_fconnect(struct socket *so)
     int opt, s=so->s;
     struct sockaddr_in addr;
 
-    socket_set_nonblock(s);
+    qemu_set_nonblock(s);
     opt = 1;
     qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
     opt = 1;
@@ -425,7 +425,7 @@ void tcp_connect(struct socket *inso)
         tcp_close(sototcpcb(so)); /* This will sofree() as well */
         return;
     }
-    socket_set_nonblock(s);
+    qemu_set_nonblock(s);
     opt = 1;
     qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
     opt = 1;
diff --git a/ui/vnc.c b/ui/vnc.c
index bbe1e0f..5ddb696 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2732,7 +2732,7 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth, bool websocket)
 
     VNC_DEBUG("New client on socket %d\n", csock);
     vd->dcl.idle = 0;
-    socket_set_nonblock(vs->csock);
+    qemu_set_nonblock(vs->csock);
 #ifdef CONFIG_VNC_WS
     if (websocket) {
         vs->websocket = 1;
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 433dd68..4e4b819 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -134,14 +134,14 @@ void qemu_vfree(void *ptr)
     free(ptr);
 }
 
-void socket_set_block(int fd)
+void qemu_set_block(int fd)
 {
     int f;
     f = fcntl(fd, F_GETFL);
     fcntl(fd, F_SETFL, f & ~O_NONBLOCK);
 }
 
-void socket_set_nonblock(int fd)
+void qemu_set_nonblock(int fd)
 {
     int f;
     f = fcntl(fd, F_GETFL);
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index 640194c..dcfa0c2 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -100,14 +100,14 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
     return p;
 }
 
-void socket_set_block(int fd)
+void qemu_set_block(int fd)
 {
     unsigned long opt = 0;
     WSAEventSelect(fd, NULL, 0);
     ioctlsocket(fd, FIONBIO, &opt);
 }
 
-void socket_set_nonblock(int fd)
+void qemu_set_nonblock(int fd)
 {
     unsigned long opt = 1;
     ioctlsocket(fd, FIONBIO, &opt);
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index b6b78f5..b632a74 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -277,7 +277,7 @@ static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
     }
     qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
     if (connect_state != NULL) {
-        socket_set_nonblock(sock);
+        qemu_set_nonblock(sock);
     }
     /* connect to peer */
     do {
@@ -737,7 +737,7 @@ int unix_connect_opts(QemuOpts *opts, Error **errp,
         connect_state = g_malloc0(sizeof(*connect_state));
         connect_state->callback = callback;
         connect_state->opaque = opaque;
-        socket_set_nonblock(sock);
+        qemu_set_nonblock(sock);
     }
 
     memset(&un, 0, sizeof(un));
commit c707582b78d01d81fe4e470fd812334be145882d
Author: Wenchao Xia <xiawenc at linux.vnet.ibm.com>
Date:   Tue Mar 26 10:24:06 2013 +0800

    VMXNET3: initialize rx_ridx to eliminate compile warning
    
      Gcc report "hw/vmxnet3.c:972: error: ‘rx_ridx’ may be used
    uninitialized in this function", so fix it.
    
    Signed-off-by: Wenchao Xia <xiawenc at linux.vnet.ibm.com>
    Message-id: 1364264646-27542-1-git-send-email-xiawenc at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/vmxnet3.c b/hw/vmxnet3.c
index 925be80..bdd256e 100644
--- a/hw/vmxnet3.c
+++ b/hw/vmxnet3.c
@@ -969,7 +969,7 @@ vmxnet3_indicate_packet(VMXNET3State *s)
     struct Vmxnet3_RxDesc rxd;
     bool is_head = true;
     uint32_t rxd_idx;
-    uint32_t rx_ridx;
+    uint32_t rx_ridx = 0;
 
     struct Vmxnet3_RxCompDesc rxcd;
     uint32_t new_rxcd_gen = VMXNET3_INIT_GEN;
commit b1ee58290d7cc2c6b1231fd701987c1753ad9ae3
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Mar 27 11:36:14 2013 -0500

    qdev: only send deleted event if device was realized
    
    Reported-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1364402174-16580-1-git-send-email-aliguori at us.ibm.com

diff --git a/hw/qdev.c b/hw/qdev.c
index 9b0f652..e2bb37d 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -767,7 +767,7 @@ static void device_unparent(Object *obj)
     DeviceClass *dc = DEVICE_GET_CLASS(dev);
     BusState *bus;
     QObject *event_data;
-    gchar *path = object_get_canonical_path(obj);
+    bool have_realized = dev->realized;
 
     while (dev->num_child_bus) {
         bus = QLIST_FIRST(&dev->child_bus);
@@ -787,15 +787,20 @@ static void device_unparent(Object *obj)
         dev->parent_bus = NULL;
     }
 
-    if (dev->id) {
-        event_data = qobject_from_jsonf("{ 'device': %s, 'path': %s }",
-                                        dev->id, path);
-    } else {
-        event_data = qobject_from_jsonf("{ 'path': %s }", path);
+    /* Only send event if the device had been completely realized */
+    if (have_realized) {
+        gchar *path = object_get_canonical_path(OBJECT(dev));
+
+        if (dev->id) {
+            event_data = qobject_from_jsonf("{ 'device': %s, 'path': %s }",
+                                            dev->id, path);
+        } else {
+            event_data = qobject_from_jsonf("{ 'path': %s }", path);
+        }
+        monitor_protocol_event(QEVENT_DEVICE_DELETED, event_data);
+        qobject_decref(event_data);
+        g_free(path);
     }
-    monitor_protocol_event(QEVENT_DEVICE_DELETED, event_data);
-    qobject_decref(event_data);
-    g_free(path);
 }
 
 static void device_class_init(ObjectClass *class, void *data)
commit 8f0605cc9caacbcc647a6df9ae541ed2da4b9bb0
Author: Stefan Berger <stefanb at linux.vnet.ibm.com>
Date:   Thu Mar 28 07:26:21 2013 -0400

    QOM-ify the TPM support
    
    QOM-ified the TPM support with much code borrowed from the rng implementation.
    
    All other TPM related code moves will be provided in a subsequent patch.
    
    Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
    Message-id: 1364469981.24703.1.camel at d941e-10
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index 464bc3e..42557d5 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -4,3 +4,5 @@ common-obj-$(CONFIG_POSIX) += rng-random.o
 common-obj-y += msmouse.o
 common-obj-$(CONFIG_BRLAPI) += baum.o
 $(obj)/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS) 
+
+common-obj-$(CONFIG_TPM) += tpm.o
diff --git a/backends/tpm.c b/backends/tpm.c
new file mode 100644
index 0000000..28148c2
--- /dev/null
+++ b/backends/tpm.c
@@ -0,0 +1,154 @@
+/*
+ * QEMU TPM Backend
+ *
+ * Copyright IBM, Corp. 2013
+ *
+ * Authors:
+ *  Stefan Berger   <stefanb 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.
+ *
+ * Based on backends/rng.c by Anthony Liguori
+ */
+
+#include "backends/tpm.h"
+#include "tpm/tpm_int.h"
+#include "qapi/qmp/qerror.h"
+
+enum TpmType tpm_backend_get_type(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->type;
+}
+
+const char *tpm_backend_get_desc(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->desc();
+}
+
+void tpm_backend_destroy(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->destroy(s);
+}
+
+int tpm_backend_init(TPMBackend *s, TPMState *state,
+                     TPMRecvDataCB *datacb)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->init(s, state, datacb);
+}
+
+int tpm_backend_startup_tpm(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->startup_tpm(s);
+}
+
+bool tpm_backend_had_startup_error(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->had_startup_error(s);
+}
+
+size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->realloc_buffer(sb);
+}
+
+void tpm_backend_deliver_request(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    k->ops->deliver_request(s);
+}
+
+void tpm_backend_reset(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    k->ops->reset(s);
+}
+
+void tpm_backend_cancel_cmd(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    k->ops->cancel_cmd(s);
+}
+
+bool tpm_backend_get_tpm_established_flag(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->get_tpm_established_flag(s);
+}
+
+static bool tpm_backend_prop_get_opened(Object *obj, Error **errp)
+{
+    TPMBackend *s = TPM_BACKEND(obj);
+
+    return s->opened;
+}
+
+void tpm_backend_open(TPMBackend *s, Error **errp)
+{
+    object_property_set_bool(OBJECT(s), true, "opened", errp);
+}
+
+static void tpm_backend_prop_set_opened(Object *obj, bool value, Error **errp)
+{
+    TPMBackend *s = TPM_BACKEND(obj);
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    if (value == s->opened) {
+        return;
+    }
+
+    if (!value && s->opened) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    if (k->opened) {
+        k->opened(s, errp);
+    }
+
+    if (!error_is_set(errp)) {
+        s->opened = value;
+    }
+}
+
+static void tpm_backend_instance_init(Object *obj)
+{
+    object_property_add_bool(obj, "opened",
+                             tpm_backend_prop_get_opened,
+                             tpm_backend_prop_set_opened,
+                             NULL);
+}
+
+static const TypeInfo tpm_backend_info = {
+    .name = TYPE_TPM_BACKEND,
+    .parent = TYPE_OBJECT,
+    .instance_size = sizeof(TPMBackend),
+    .instance_init = tpm_backend_instance_init,
+    .class_size = sizeof(TPMBackendClass),
+    .abstract = true,
+};
+
+static void register_types(void)
+{
+    type_register_static(&tpm_backend_info);
+}
+
+type_init(register_types);
diff --git a/include/backends/tpm.h b/include/backends/tpm.h
new file mode 100644
index 0000000..9e93cc5
--- /dev/null
+++ b/include/backends/tpm.h
@@ -0,0 +1,170 @@
+/*
+ * QEMU TPM Backend
+ *
+ * Copyright IBM, Corp. 2013
+ *
+ * Authors:
+ *  Stefan Berger  <stefanb 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 _QEMU_TPM_H
+#define _QEMU_TPM_H
+
+#include "qom/object.h"
+#include "qemu-common.h"
+#include "qapi/error.h"
+#include "qapi-types.h"
+#include "qemu/option.h"
+#include "tpm/tpm.h"
+
+#define TYPE_TPM_BACKEND "tpm-backend"
+#define TPM_BACKEND(obj) \
+    OBJECT_CHECK(TPMBackend, (obj), TYPE_TPM_BACKEND)
+#define TPM_BACKEND_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(TPMBackendClass, (obj), TYPE_TPM_BACKEND)
+#define TPM_BACKEND_CLASS(klass) \
+    OBJECT_CLASS_CHECK(TPMBackendClass, (klass), TYPE_TPM_BACKEND)
+
+typedef struct TPMBackendClass TPMBackendClass;
+typedef struct TPMBackend TPMBackend;
+
+typedef struct TPMDriverOps TPMDriverOps;
+
+struct TPMBackendClass {
+    ObjectClass parent_class;
+
+    const TPMDriverOps *ops;
+
+    void (*opened)(TPMBackend *s, Error **errp);
+};
+
+struct TPMBackend {
+    Object parent;
+
+    /*< protected >*/
+    bool opened;
+
+    char *id;
+    enum TpmModel fe_model;
+    char *path;
+    char *cancel_path;
+    const TPMDriverOps *ops;
+
+    QLIST_ENTRY(TPMBackend) list;
+};
+
+
+/**
+ * tpm_backend_get_type:
+ * @s: the backend
+ *
+ * Returns the TpmType of the backend.
+ */
+enum TpmType tpm_backend_get_type(TPMBackend *s);
+
+/**
+ * tpm_backend_get_desc:
+ * @s: the backend
+ *
+ * Returns a human readable description of the backend.
+ */
+const char *tpm_backend_get_desc(TPMBackend *s);
+
+/**
+ * tpm_backend_destroy:
+ * @s: the backend to destroy
+ */
+void tpm_backend_destroy(TPMBackend *s);
+
+/**
+ * tpm_backend_init:
+ * @s: the backend to initialized
+ * @state: TPMState
+ * @datacb: callback for sending data to frontend
+ *
+ * Initialize the backend with the given variables.
+ *
+ * Returns 0 on success.
+ */
+int tpm_backend_init(TPMBackend *s, TPMState *state,
+                     TPMRecvDataCB *datacb);
+
+/**
+ * tpm_backend_startup_tpm:
+ * @s: the backend whose TPM support is to be started
+ *
+ * Returns 0 on success.
+ */
+int tpm_backend_startup_tpm(TPMBackend *s);
+
+/**
+ * tpm_backend_had_startup_error:
+ * @s: the backend to query for a statup error
+ *
+ * Check whether the backend had an error during startup. Returns
+ * false if no error occurred and the backend can be used, true
+ * otherwise.
+ */
+bool tpm_backend_had_startup_error(TPMBackend *s);
+
+/**
+ * tpm_backend_realloc_buffer:
+ * @s: the backend
+ * @sb: the TPMSizedBuffer to re-allocated to the size suitable for the
+ *      backend.
+ *
+ * This function returns the size of the allocated buffer
+ */
+size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb);
+
+/**
+ * tpm_backend_deliver_request:
+ * @s: the backend to send the request to
+ *
+ * Send a request to the backend. The backend will then send the request
+ * to the TPM implementation.
+ */
+void tpm_backend_deliver_request(TPMBackend *s);
+
+/**
+ * tpm_backend_reset:
+ * @s: the backend to reset
+ *
+ * Reset the backend into a well defined state with all previous errors
+ * reset.
+ */
+void tpm_backend_reset(TPMBackend *s);
+
+/**
+ * tpm_backend_cancel_cmd:
+ * @s: the backend
+ *
+ * Cancel any ongoing command being processed by the TPM implementation
+ * on behalf of the QEMU guest.
+ */
+void tpm_backend_cancel_cmd(TPMBackend *s);
+
+/**
+ * tpm_backend_get_tpm_established_flag:
+ * @s: the backend
+ *
+ * Get the TPM establishment flag. This function may be called very
+ * frequently by the frontend since for example in the TIS implementation
+ * this flag is part of a register.
+ */
+bool tpm_backend_get_tpm_established_flag(TPMBackend *s);
+
+/**
+ * tpm_backend_open:
+ * @s: the backend to open
+ * @errp: a pointer to return the #Error object if an error occurs.
+ *
+ * This function will open the backend if it is not already open.  Calling this
+ * function on an already opened backend will not result in an error.
+ */
+void tpm_backend_open(TPMBackend *s, Error **errp);
+
+#endif
diff --git a/include/tpm/tpm.h b/include/tpm/tpm.h
index cc8f20e..2d457c4 100644
--- a/include/tpm/tpm.h
+++ b/include/tpm/tpm.h
@@ -14,6 +14,10 @@
 
 #include "qemu/option.h"
 
+typedef struct TPMState TPMState;
+typedef struct TPMSizedBuffer TPMSizedBuffer;
+typedef void (TPMRecvDataCB)(TPMState *, uint8_t locty);
+
 int tpm_config_parse(QemuOptsList *opts_list, const char *optarg);
 int tpm_init(void);
 void tpm_cleanup(void);
diff --git a/tpm/tpm.c b/tpm/tpm.c
index ae00eae..1f4ac8d 100644
--- a/tpm/tpm.c
+++ b/tpm/tpm.c
@@ -15,6 +15,7 @@
 
 #include "monitor/monitor.h"
 #include "qapi/qmp/qerror.h"
+#include "backends/tpm.h"
 #include "tpm_int.h"
 #include "tpm/tpm.h"
 #include "qemu/config-file.h"
@@ -145,6 +146,7 @@ static int configure_tpm(QemuOpts *opts)
     const char *id;
     const TPMDriverOps *be;
     TPMBackend *drv;
+    Error *local_err = NULL;
 
     if (!QLIST_EMPTY(&tpm_backends)) {
         error_report("Only one TPM is allowed.\n");
@@ -177,6 +179,13 @@ static int configure_tpm(QemuOpts *opts)
         return 1;
     }
 
+    tpm_backend_open(drv, &local_err);
+    if (local_err) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return 1;
+    }
+
     QLIST_INSERT_HEAD(&tpm_backends, drv, list);
 
     return 0;
@@ -197,7 +206,7 @@ void tpm_cleanup(void)
 
     QLIST_FOREACH_SAFE(drv, &tpm_backends, list, next) {
         QLIST_REMOVE(drv, list);
-        drv->ops->destroy(drv);
+        tpm_backend_destroy(drv);
     }
 }
 
diff --git a/tpm/tpm_int.h b/tpm/tpm_int.h
index f705643..b4787ad 100644
--- a/tpm/tpm_int.h
+++ b/tpm/tpm_int.h
@@ -18,22 +18,6 @@
 struct TPMDriverOps;
 typedef struct TPMDriverOps TPMDriverOps;
 
-typedef struct TPMPassthruState TPMPassthruState;
-
-typedef struct TPMBackend {
-    char *id;
-    enum TpmModel fe_model;
-    char *path;
-    char *cancel_path;
-    const TPMDriverOps *ops;
-
-    union {
-        TPMPassthruState *tpm_pt;
-    } s;
-
-    QLIST_ENTRY(TPMBackend) list;
-} TPMBackend;
-
 /* overall state of the TPM interface */
 typedef struct TPMState {
     ISADevice busdev;
diff --git a/tpm/tpm_passthrough.c b/tpm/tpm_passthrough.c
index 24aff4d..80a48d6 100644
--- a/tpm/tpm_passthrough.c
+++ b/tpm/tpm_passthrough.c
@@ -27,6 +27,7 @@
 #include "qemu-common.h"
 #include "qapi/error.h"
 #include "qemu/sockets.h"
+#include "backends/tpm.h"
 #include "tpm_int.h"
 #include "hw/hw.h"
 #include "hw/pc.h"
@@ -43,8 +44,11 @@
     do { } while (0)
 #endif
 
-/* data structures */
+#define TYPE_TPM_PASSTHROUGH "tpm-passthrough"
+#define TPM_PASSTHROUGH(obj) \
+    OBJECT_CHECK(TPMPassthruState, (obj), TYPE_TPM_PASSTHROUGH)
 
+/* data structures */
 typedef struct TPMPassthruThreadParams {
     TPMState *tpm_state;
 
@@ -53,6 +57,8 @@ typedef struct TPMPassthruThreadParams {
 } TPMPassthruThreadParams;
 
 struct TPMPassthruState {
+    TPMBackend parent;
+
     TPMBackendThread tbt;
 
     TPMPassthruThreadParams tpm_thread_params;
@@ -65,6 +71,8 @@ struct TPMPassthruState {
     bool had_startup_error;
 };
 
+typedef struct TPMPassthruState TPMPassthruState;
+
 #define TPM_PASSTHROUGH_DEFAULT_DEVICE "/dev/tpm0"
 
 /* functions */
@@ -149,7 +157,7 @@ static void tpm_passthrough_worker_thread(gpointer data,
                                           gpointer user_data)
 {
     TPMPassthruThreadParams *thr_parms = user_data;
-    TPMPassthruState *tpm_pt = thr_parms->tb->s.tpm_pt;
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(thr_parms->tb);
     TPMBackendCmd cmd = (TPMBackendCmd)data;
 
     DPRINTF("tpm_passthrough: processing command type %d\n", cmd);
@@ -176,21 +184,21 @@ static void tpm_passthrough_worker_thread(gpointer data,
  */
 static int tpm_passthrough_startup_tpm(TPMBackend *tb)
 {
-    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 
     /* terminate a running TPM */
     tpm_backend_thread_end(&tpm_pt->tbt);
 
     tpm_backend_thread_create(&tpm_pt->tbt,
                               tpm_passthrough_worker_thread,
-                              &tb->s.tpm_pt->tpm_thread_params);
+                              &tpm_pt->tpm_thread_params);
 
     return 0;
 }
 
 static void tpm_passthrough_reset(TPMBackend *tb)
 {
-    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 
     DPRINTF("tpm_passthrough: CALL TO TPM_RESET!\n");
 
@@ -204,7 +212,7 @@ static void tpm_passthrough_reset(TPMBackend *tb)
 static int tpm_passthrough_init(TPMBackend *tb, TPMState *s,
                                 TPMRecvDataCB *recv_data_cb)
 {
-    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 
     tpm_pt->tpm_thread_params.tpm_state = s;
     tpm_pt->tpm_thread_params.recv_data_callback = recv_data_cb;
@@ -220,7 +228,7 @@ static bool tpm_passthrough_get_tpm_established_flag(TPMBackend *tb)
 
 static bool tpm_passthrough_get_startup_error(TPMBackend *tb)
 {
-    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 
     return tpm_pt->had_startup_error;
 }
@@ -238,14 +246,14 @@ static size_t tpm_passthrough_realloc_buffer(TPMSizedBuffer *sb)
 
 static void tpm_passthrough_deliver_request(TPMBackend *tb)
 {
-    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 
     tpm_backend_thread_deliver_request(&tpm_pt->tbt);
 }
 
 static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
 {
-    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
     int n;
 
     /*
@@ -412,6 +420,7 @@ static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb)
 
 static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
 {
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
     const char *value;
 
     value = qemu_opt_get(opts, "cancel-path");
@@ -424,45 +433,45 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
         value = TPM_PASSTHROUGH_DEFAULT_DEVICE;
     }
 
-    tb->s.tpm_pt->tpm_dev = g_strdup(value);
+    tpm_pt->tpm_dev = g_strdup(value);
 
-    tb->path = g_strdup(tb->s.tpm_pt->tpm_dev);
+    tb->path = g_strdup(tpm_pt->tpm_dev);
 
-    tb->s.tpm_pt->tpm_fd = qemu_open(tb->s.tpm_pt->tpm_dev, O_RDWR);
-    if (tb->s.tpm_pt->tpm_fd < 0) {
+    tpm_pt->tpm_fd = qemu_open(tpm_pt->tpm_dev, O_RDWR);
+    if (tpm_pt->tpm_fd < 0) {
         error_report("Cannot access TPM device using '%s': %s\n",
-                     tb->s.tpm_pt->tpm_dev, strerror(errno));
+                     tpm_pt->tpm_dev, strerror(errno));
         goto err_free_parameters;
     }
 
-    if (tpm_passthrough_test_tpmdev(tb->s.tpm_pt->tpm_fd)) {
+    if (tpm_passthrough_test_tpmdev(tpm_pt->tpm_fd)) {
         error_report("'%s' is not a TPM device.\n",
-                     tb->s.tpm_pt->tpm_dev);
+                     tpm_pt->tpm_dev);
         goto err_close_tpmdev;
     }
 
     return 0;
 
  err_close_tpmdev:
-    qemu_close(tb->s.tpm_pt->tpm_fd);
-    tb->s.tpm_pt->tpm_fd = -1;
+    qemu_close(tpm_pt->tpm_fd);
+    tpm_pt->tpm_fd = -1;
 
  err_free_parameters:
     g_free(tb->path);
     tb->path = NULL;
 
-    g_free(tb->s.tpm_pt->tpm_dev);
-    tb->s.tpm_pt->tpm_dev = NULL;
+    g_free(tpm_pt->tpm_dev);
+    tpm_pt->tpm_dev = NULL;
 
     return 1;
 }
 
 static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
 {
-    TPMBackend *tb;
+    Object *obj = object_new(TYPE_TPM_PASSTHROUGH);
+    TPMBackend *tb = TPM_BACKEND(obj);
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 
-    tb = g_new0(TPMBackend, 1);
-    tb->s.tpm_pt = g_new0(TPMPassthruState, 1);
     tb->id = g_strdup(id);
     /* let frontend set the fe_model to proper value */
     tb->fe_model = -1;
@@ -473,8 +482,8 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
         goto err_exit;
     }
 
-    tb->s.tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tb);
-    if (tb->s.tpm_pt->cancel_fd < 0) {
+    tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tb);
+    if (tpm_pt->cancel_fd < 0) {
         goto err_exit;
     }
 
@@ -482,29 +491,25 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
 
 err_exit:
     g_free(tb->id);
-    g_free(tb->s.tpm_pt);
-    g_free(tb);
 
     return NULL;
 }
 
 static void tpm_passthrough_destroy(TPMBackend *tb)
 {
-    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 
     tpm_passthrough_cancel_cmd(tb);
 
     tpm_backend_thread_end(&tpm_pt->tbt);
 
     qemu_close(tpm_pt->tpm_fd);
-    qemu_close(tb->s.tpm_pt->cancel_fd);
+    qemu_close(tpm_pt->cancel_fd);
 
     g_free(tb->id);
     g_free(tb->path);
     g_free(tb->cancel_path);
-    g_free(tb->s.tpm_pt->tpm_dev);
-    g_free(tb->s.tpm_pt);
-    g_free(tb);
+    g_free(tpm_pt->tpm_dev);
 }
 
 const TPMDriverOps tpm_passthrough_driver = {
@@ -522,8 +527,33 @@ const TPMDriverOps tpm_passthrough_driver = {
     .get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag,
 };
 
+static void tpm_passthrough_inst_init(Object *obj)
+{
+}
+
+static void tpm_passthrough_inst_finalize(Object *obj)
+{
+}
+
+static void tpm_passthrough_class_init(ObjectClass *klass, void *data)
+{
+    TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
+
+    tbc->ops = &tpm_passthrough_driver;
+}
+
+static const TypeInfo tpm_passthrough_info = {
+    .name = TYPE_TPM_PASSTHROUGH,
+    .parent = TYPE_TPM_BACKEND,
+    .instance_size = sizeof(TPMPassthruState),
+    .class_init = tpm_passthrough_class_init,
+    .instance_init = tpm_passthrough_inst_init,
+    .instance_finalize = tpm_passthrough_inst_finalize,
+};
+
 static void tpm_passthrough_register(void)
 {
+    type_register_static(&tpm_passthrough_info);
     tpm_register_driver(&tpm_passthrough_driver);
 }
 
diff --git a/tpm/tpm_tis.c b/tpm/tpm_tis.c
index e93825e..367f734 100644
--- a/tpm/tpm_tis.c
+++ b/tpm/tpm_tis.c
@@ -19,6 +19,7 @@
  * specification.
  */
 
+#include "backends/tpm.h"
 #include "tpm_int.h"
 #include "block/block.h"
 #include "exec/address-spaces.h"
@@ -160,7 +161,7 @@ static void tpm_tis_tpm_send(TPMState *s, uint8_t locty)
      */
     tis->loc[locty].state = TPM_TIS_STATE_EXECUTION;
 
-    s->be_driver->ops->deliver_request(s->be_driver);
+    tpm_backend_deliver_request(s->be_driver);
 }
 
 /* raise an interrupt if allowed */
@@ -284,7 +285,7 @@ static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty)
              * request the backend to cancel. Some backends may not
              * support it
              */
-            s->be_driver->ops->cancel_cmd(s->be_driver);
+            tpm_backend_cancel_cmd(s->be_driver);
             return;
         }
     }
@@ -426,7 +427,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
     uint8_t locty = tpm_tis_locality_from_addr(addr);
     uint32_t avail;
 
-    if (s->be_driver->ops->had_startup_error(s->be_driver)) {
+    if (tpm_backend_had_startup_error(s->be_driver)) {
         return val;
     }
 
@@ -438,7 +439,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
         if (tpm_tis_check_request_use_except(s, locty)) {
             val |= TPM_TIS_ACCESS_PENDING_REQUEST;
         }
-        val |= !s->be_driver->ops->get_tpm_established_flag(s->be_driver);
+        val |= !tpm_backend_get_tpm_established_flag(s->be_driver);
         break;
     case TPM_TIS_REG_INT_ENABLE:
         val = tis->loc[locty].inte;
@@ -529,7 +530,7 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
         return;
     }
 
-    if (s->be_driver->ops->had_startup_error(s->be_driver)) {
+    if (tpm_backend_had_startup_error(s->be_driver)) {
         return;
     }
 
@@ -804,7 +805,7 @@ static const MemoryRegionOps tpm_tis_memory_ops = {
 
 static int tpm_tis_do_startup_tpm(TPMState *s)
 {
-    return s->be_driver->ops->startup_tpm(s->be_driver);
+    return tpm_backend_startup_tpm(s->be_driver);
 }
 
 /*
@@ -817,7 +818,7 @@ static void tpm_tis_reset(DeviceState *dev)
     TPMTISEmuState *tis = &s->s.tis;
     int c;
 
-    s->be_driver->ops->reset(s->be_driver);
+    tpm_backend_reset(s->be_driver);
 
     tis->active_locty = TPM_TIS_NO_LOCALITY;
     tis->next_locty = TPM_TIS_NO_LOCALITY;
@@ -831,9 +832,9 @@ static void tpm_tis_reset(DeviceState *dev)
         tis->loc[c].state = TPM_TIS_STATE_IDLE;
 
         tis->loc[c].w_offset = 0;
-        s->be_driver->ops->realloc_buffer(&tis->loc[c].w_buffer);
+        tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].w_buffer);
         tis->loc[c].r_offset = 0;
-        s->be_driver->ops->realloc_buffer(&tis->loc[c].r_buffer);
+        tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].r_buffer);
     }
 
     tpm_tis_do_startup_tpm(s);
@@ -865,7 +866,7 @@ static void tpm_tis_realizefn(DeviceState *dev, Error **errp)
 
     s->be_driver->fe_model = TPM_MODEL_TPM_TIS;
 
-    if (s->be_driver->ops->init(s->be_driver, s, tpm_tis_receive_cb)) {
+    if (tpm_backend_init(s->be_driver, s, tpm_tis_receive_cb)) {
         error_setg(errp, "tpm_tis: backend driver with id %s could not be "
                    "initialized", s->backend);
         return;
commit 684a096eafbe37ab6c9a1fdb5e0185f04098b166
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Mar 29 11:39:50 2013 -0500

    qemu-char: rewrite io_channel_send_all and drop the '_all' suffix
    
    The current code is oddly written and have equally odd semantics.
    Despite the '_all' suffix, upon EAGAIN the result will be a partial
    write but instead of returning the partial write, we return EAGAIN.
    
    Change the behavior to write as much as we can until we get an EAGAIN
    returning a partial write if we do.
    
    Reported-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1364575190-731-1-git-send-email-aliguori at us.ibm.com

diff --git a/qemu-char.c b/qemu-char.c
index dee623e..7acbf53 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -727,33 +727,37 @@ static GIOChannel *io_channel_from_socket(int fd)
     return chan;
 }
 
-static int io_channel_send_all(GIOChannel *fd, const void *_buf, int len1)
+static int io_channel_send(GIOChannel *fd, const void *buf, size_t len)
 {
     GIOStatus status;
-    gsize bytes_written;
-    int len;
-    const uint8_t *buf = _buf;
+    size_t offset;
 
-    len = len1;
-    while (len > 0) {
-        status = g_io_channel_write_chars(fd, (const gchar *)buf, len,
+    offset = 0;
+    while (offset < len) {
+        gsize bytes_written;
+
+        status = g_io_channel_write_chars(fd, buf + offset, len - offset,
                                           &bytes_written, NULL);
         if (status != G_IO_STATUS_NORMAL) {
             if (status == G_IO_STATUS_AGAIN) {
+                /* If we've written any data, return a partial write. */
+                if (offset) {
+                    break;
+                }
                 errno = EAGAIN;
-                return -1;
             } else {
                 errno = EINVAL;
-                return -1;
             }
+
+            return -1;
         } else if (status == G_IO_STATUS_EOF) {
             break;
-        } else {
-            buf += bytes_written;
-            len -= bytes_written;
         }
+
+        offset += bytes_written;
     }
-    return len1 - len;
+
+    return offset;
 }
 
 #ifndef _WIN32
@@ -770,7 +774,7 @@ static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     FDCharDriver *s = chr->opaque;
     
-    return io_channel_send_all(s->fd_out, buf, len);
+    return io_channel_send(s->fd_out, buf, len);
 }
 
 static gboolean fd_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
@@ -1088,7 +1092,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
         pty_chr_update_read_handler(chr);
         return 0;
     }
-    return io_channel_send_all(s->fd, buf, len);
+    return io_channel_send(s->fd, buf, len);
 }
 
 static GSource *pty_chr_add_watch(CharDriverState *chr, GIOCondition cond)
@@ -2347,7 +2351,7 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     TCPCharDriver *s = chr->opaque;
     if (s->connected) {
-        return io_channel_send_all(s->chan, buf, len);
+        return io_channel_send(s->chan, buf, len);
     } else {
         /* XXX: indicate an error ? */
         return len;
commit d819cdccffe08f6e12b4c2dec8f4aa381f0cd687
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Mar 30 15:21:40 2013 +0100

    ui/gtk: Set QEMU window icon
    
    The QEMU icon which is already used for SDL
    is now also loaded by GTK.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Message-id: 1364653300-26813-1-git-send-email-sw at weilnetz.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/gtk.c b/ui/gtk.c
index 9692c56..1a6bee6 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1363,6 +1363,7 @@ static const DisplayChangeListenerOps dcl_ops = {
 void gtk_display_init(DisplayState *ds)
 {
     GtkDisplayState *s = g_malloc0(sizeof(*s));
+    char *filename;
 
     gtk_init(NULL, NULL);
 
@@ -1394,6 +1395,18 @@ void gtk_display_init(DisplayState *ds)
 
     gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), s->drawing_area, gtk_label_new("VGA"));
 
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "qemu-icon.bmp");
+    if (filename) {
+        GError *error = NULL;
+        GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(filename, &error);
+        if (pixbuf) {
+            gtk_window_set_icon(GTK_WINDOW(s->window), pixbuf);
+        } else {
+            g_error_free(error);
+        }
+        g_free(filename);
+    }
+
     gd_create_menus(s);
 
     gd_connect_signals(s);
commit 77cfd14c9f5742136e7968aee5c305e50b8891ac
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Apr 1 19:12:06 2013 +0200

    po: add French translation
    
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1364836326-8707-6-git-send-email-aurelien at aurel32.net
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/po/fr_FR.po b/po/fr_FR.po
new file mode 100644
index 0000000..27d8636
--- /dev/null
+++ b/po/fr_FR.po
@@ -0,0 +1,62 @@
+# French translation for QEMU.
+# This file is put in the public domain.
+#
+# Aurelien Jarno <aurelien at aurel32.net>, 2013.
+msgid ""
+msgstr ""
+"Project-Id-Version: QEMU 1.4.50\n"
+"Report-Msgid-Bugs-To: qemu-devel at nongnu.org\n"
+"POT-Creation-Date: 2013-03-31 20:42+0200\n"
+"PO-Revision-Date: 2013-03-31 19:39+0200\n"
+"Last-Translator: Aurelien Jarno <aurelien at aurel32.net>\n"
+"Language-Team: French <FR at li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Lokalize 1.4\n"
+
+#: ../ui/gtk.c:213
+msgid " - Press Ctrl+Alt+G to release grab"
+msgstr "- Appuyer sur Ctrl+Alt+G pour arrêter la capture"
+
+#: ../ui/gtk.c:217
+msgid " [Paused]"
+msgstr " [En pause]"
+
+#: ../ui/gtk.c:1250
+msgid "_Machine"
+msgstr "_Machine"
+
+#: ../ui/gtk.c:1252
+msgid "_Pause"
+msgstr "_Pause"
+
+#: ../ui/gtk.c:1258
+msgid "_Reset"
+msgstr "_Réinitialiser"
+
+#: ../ui/gtk.c:1261
+msgid "Power _Down"
+msgstr "_Éteindre"
+
+#: ../ui/gtk.c:1276
+msgid "_View"
+msgstr "_Vue"
+
+#: ../ui/gtk.c:1306
+msgid "Zoom To _Fit"
+msgstr "Zoomer pour _ajuster"
+
+#: ../ui/gtk.c:1312
+msgid "Grab On _Hover"
+msgstr "Capturer en _survolant"
+
+#: ../ui/gtk.c:1315
+msgid "_Grab Input"
+msgstr "_Capturer les entrées"
+
+#: ../ui/gtk.c:1341
+msgid "Show _Tabs"
+msgstr "Montrer les _onglets"
commit 9b6926e4e3cc102fb434fd16917a1044119eadd3
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Apr 1 19:12:05 2013 +0200

    po: update existing translation files
    
    Cc: Paolo Bonzini <pbonzini at redhat.com>
    Cc: Kevin Wolf <kwolf at redhat.com>
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1364836326-8707-5-git-send-email-aurelien at aurel32.net
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/po/de_DE.po b/po/de_DE.po
index 8755783..2566674 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: QEMU 1.4.50\n"
 "Report-Msgid-Bugs-To: qemu-devel at nongnu.org\n"
-"POT-Creation-Date: 2013-02-08 09:21-0600\n"
+"POT-Creation-Date: 2013-03-31 20:42+0200\n"
 "PO-Revision-Date: 2012-02-28 16:00+0100\n"
 "Last-Translator: Kevin Wolf <kwolf at redhat.com>\n"
 "Language-Team: Deutsch <de at li.org>\n"
@@ -16,26 +16,49 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n!=1);\n"
 
-#: ../ui/gtk.c:990
-msgid "_File"
-msgstr "_Datei"
+#: ../ui/gtk.c:213
+msgid " - Press Ctrl+Alt+G to release grab"
+msgstr ""
+
+#: ../ui/gtk.c:217
+msgid " [Paused]"
+msgstr ""
+
+#: ../ui/gtk.c:1250
+msgid "_Machine"
+msgstr ""
+
+#: ../ui/gtk.c:1252
+msgid "_Pause"
+msgstr ""
+
+#: ../ui/gtk.c:1258
+msgid "_Reset"
+msgstr ""
 
-#: ../ui/gtk.c:1000
+#: ../ui/gtk.c:1261
+msgid "Power _Down"
+msgstr ""
+
+#: ../ui/gtk.c:1276
 msgid "_View"
 msgstr "_Ansicht"
 
-#: ../ui/gtk.c:1029
+#: ../ui/gtk.c:1306
 msgid "Zoom To _Fit"
 msgstr "Auf _Fenstergröße skalieren"
 
-#: ../ui/gtk.c:1035
+#: ../ui/gtk.c:1312
 msgid "Grab On _Hover"
 msgstr "Tastatur _automatisch einfangen"
 
-#: ../ui/gtk.c:1038
+#: ../ui/gtk.c:1315
 msgid "_Grab Input"
 msgstr "_Eingabegeräte einfangen"
 
-#: ../ui/gtk.c:1064
+#: ../ui/gtk.c:1341
 msgid "Show _Tabs"
 msgstr "_Tableiste anzeigen"
+
+#~ msgid "_File"
+#~ msgstr "_Datei"
diff --git a/po/it.po b/po/it.po
index 7d77fff..2ace3b0 100644
--- a/po/it.po
+++ b/po/it.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: QEMU 1.4.50\n"
 "Report-Msgid-Bugs-To: qemu-devel at nongnu.org\n"
-"POT-Creation-Date: 2013-02-08 09:21-0600\n"
+"POT-Creation-Date: 2013-03-31 20:42+0200\n"
 "PO-Revision-Date: 2012-02-27 08:23+0100\n"
 "Last-Translator: Paolo Bonzini <pbonzini at redhat.com>\n"
 "Language-Team: Italian <it at li.org>\n"
@@ -16,26 +16,49 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
 
-#: ../ui/gtk.c:990
-msgid "_File"
-msgstr "_File"
+#: ../ui/gtk.c:213
+msgid " - Press Ctrl+Alt+G to release grab"
+msgstr ""
+
+#: ../ui/gtk.c:217
+msgid " [Paused]"
+msgstr ""
+
+#: ../ui/gtk.c:1250
+msgid "_Machine"
+msgstr ""
+
+#: ../ui/gtk.c:1252
+msgid "_Pause"
+msgstr ""
+
+#: ../ui/gtk.c:1258
+msgid "_Reset"
+msgstr ""
 
-#: ../ui/gtk.c:1000
+#: ../ui/gtk.c:1261
+msgid "Power _Down"
+msgstr ""
+
+#: ../ui/gtk.c:1276
 msgid "_View"
 msgstr "_Visualizza"
 
-#: ../ui/gtk.c:1029
+#: ../ui/gtk.c:1306
 msgid "Zoom To _Fit"
 msgstr "Adatta alla _finestra"
 
-#: ../ui/gtk.c:1035
+#: ../ui/gtk.c:1312
 msgid "Grab On _Hover"
 msgstr "Cattura _automatica input"
 
-#: ../ui/gtk.c:1038
+#: ../ui/gtk.c:1315
 msgid "_Grab Input"
 msgstr "_Cattura input"
 
-#: ../ui/gtk.c:1064
+#: ../ui/gtk.c:1341
 msgid "Show _Tabs"
 msgstr "Mostra _tab"
+
+#~ msgid "_File"
+#~ msgstr "_File"
diff --git a/po/messages.po b/po/messages.po
index 191e81c..42a3eac 100644
--- a/po/messages.po
+++ b/po/messages.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: QEMU 1.4.50\n"
 "Report-Msgid-Bugs-To: qemu-devel at nongnu.org\n"
-"POT-Creation-Date: 2013-02-08 09:21-0600\n"
+"POT-Creation-Date: 2013-03-31 20:42+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
 "Language-Team: LANGUAGE <LL at li.org>\n"
@@ -16,26 +16,46 @@ msgstr ""
 "Content-Type: text/plain; charset=CHARSET\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: ../ui/gtk.c:990
-msgid "_File"
+#: ../ui/gtk.c:213
+msgid " - Press Ctrl+Alt+G to release grab"
 msgstr ""
 
-#: ../ui/gtk.c:1000
+#: ../ui/gtk.c:217
+msgid " [Paused]"
+msgstr ""
+
+#: ../ui/gtk.c:1250
+msgid "_Machine"
+msgstr ""
+
+#: ../ui/gtk.c:1252
+msgid "_Pause"
+msgstr ""
+
+#: ../ui/gtk.c:1258
+msgid "_Reset"
+msgstr ""
+
+#: ../ui/gtk.c:1261
+msgid "Power _Down"
+msgstr ""
+
+#: ../ui/gtk.c:1276
 msgid "_View"
 msgstr ""
 
-#: ../ui/gtk.c:1029
+#: ../ui/gtk.c:1306
 msgid "Zoom To _Fit"
 msgstr ""
 
-#: ../ui/gtk.c:1035
+#: ../ui/gtk.c:1312
 msgid "Grab On _Hover"
 msgstr ""
 
-#: ../ui/gtk.c:1038
+#: ../ui/gtk.c:1315
 msgid "_Grab Input"
 msgstr ""
 
-#: ../ui/gtk.c:1064
+#: ../ui/gtk.c:1341
 msgid "Show _Tabs"
 msgstr ""
commit 1b33b354b43c8a3cc176bd4d7a021a1eac423ebc
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Apr 1 19:12:04 2013 +0200

    po/Makefile: correctly pass QEMU version
    
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1364836326-8707-4-git-send-email-aurelien at aurel32.net
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/po/Makefile b/po/Makefile
index 2c0193e..8297ab5 100644
--- a/po/Makefile
+++ b/po/Makefile
@@ -34,7 +34,7 @@ install: $(OBJS)
 	@msgfmt -o $@ $(SRC_PATH)/po/`basename $@ .mo`.po
 
 messages.po: $(SRC_PATH)/ui/gtk.c
-	@xgettext -o $@ --foreign-user --package-name=QEMU --package-version=1.0.50 --msgid-bugs-address=qemu-devel at nongnu.org -k_ -C $<
+	@xgettext -o $@ --foreign-user --package-name=QEMU --package-version=$(VERSION) --msgid-bugs-address=qemu-devel at nongnu.org -k_ -C $<
 
 %.po: messages.po
 	@msgmerge $@ $< > $@.bak && mv $@.bak $@
commit f84756554e32d97db3aa949db1dd58c7eea62375
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Apr 1 19:12:03 2013 +0200

    po/Makefile: simplify
    
    In the hope we get more translations, we should not have to modify
    po/Makefile for each of them.
    
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1364836326-8707-3-git-send-email-aurelien at aurel32.net
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/po/Makefile b/po/Makefile
index 2b4420f..2c0193e 100644
--- a/po/Makefile
+++ b/po/Makefile
@@ -2,9 +2,8 @@
 # process and also within the source tree to update the translation files.
 
 VERSION=$(shell cat ../VERSION)
-TRANSLATIONS=de_DE it
-SRCS=$(addsuffix .po, $(TRANSLATIONS))
-OBJS=$(addsuffix .mo, $(TRANSLATIONS))
+SRCS=$(filter-out messages.po,$(wildcard *.po))
+OBJS=$(patsubst %.po,%.mo,$(SRCS))
 
 SRC_PATH=..
 
@@ -37,10 +36,7 @@ install: $(OBJS)
 messages.po: $(SRC_PATH)/ui/gtk.c
 	@xgettext -o $@ --foreign-user --package-name=QEMU --package-version=1.0.50 --msgid-bugs-address=qemu-devel at nongnu.org -k_ -C $<
 
-de_DE.po: messages.po $(SRC_PATH)/ui/gtk.c
+%.po: messages.po
 	@msgmerge $@ $< > $@.bak && mv $@.bak $@
 
-it.po: messages.po $(SRC_PATH)/ui/gtk.c
-	@msgmerge $@ $< > $@.bak && mv $@.bak $@
-
-.PHONY: $(SRCS) clean all
+.PHONY: clean all
commit d8da9ee847799b8d7de4679d4de17d66d4dedb56
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Apr 1 19:12:02 2013 +0200

    gtk: make more messages translatable
    
    Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1364836326-8707-2-git-send-email-aurelien at aurel32.net
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/gtk.c b/ui/gtk.c
index a5a8156..9692c56 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -210,11 +210,11 @@ static void gd_update_caption(GtkDisplayState *s)
     bool is_paused = !runstate_is_running();
 
     if (gd_is_grab_active(s)) {
-        grab = " - Press Ctrl+Alt+G to release grab";
+        grab = _(" - Press Ctrl+Alt+G to release grab");
     }
 
     if (is_paused) {
-        status = " [Paused]";
+        status = _(" [Paused]");
     }
     s->external_pause_update = true;
     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->pause_item),
commit 4690579e9bafa0a2a49d7b12dae905279a552cd6
Author: Amos Kong <akong at redhat.com>
Date:   Wed Mar 20 18:16:34 2013 +0800

    append the terminating '\0' to bootorder string
    
    Problem was introduced in commit c8a6ae8b. The last terminating
    '\0' was lost, use the right length 5 ("HALT\0").
    
    Reported-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Amos Kong <akong at redhat.com>
    Message-id: 1363774594-21001-1-git-send-email-akong at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index 52eacca..e2c9706 100644
--- a/vl.c
+++ b/vl.c
@@ -1278,9 +1278,9 @@ char *get_boot_devices_list(size_t *size)
 
     if (boot_strict && *size > 0) {
         list[total-1] = '\n';
-        list = g_realloc(list, total + 4);
-        memcpy(&list[total], "HALT", 4);
-        *size = total + 4;
+        list = g_realloc(list, total + 5);
+        memcpy(&list[total], "HALT", 5);
+        *size = total + 5;
     }
     return list;
 }
commit a130c6b2b1b9c45836a51e90c847baedcb3125d3
Merge: 5d45de9 6dcfdba
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Apr 2 08:12:16 2013 -0500

    Merge remote-tracking branch 'awilliam/tags/vfio-pci-for-qemu-20130401.0' into staging
    
    vfio-pci pull request 20130401
    
    # gpg: Signature made Mon 01 Apr 2013 02:40:45 PM CDT using RSA key ID 3BB08B22
    # gpg: Can't check signature: public key not found
    
    # By Alex Williamson
    # Via Alex Williamson
    * awilliam/tags/vfio-pci-for-qemu-20130401.0:
      vfio: cleanup includes
      vfio: Add bootindex support
      vfio-pci: Move devices to D0 on reset
      vfio-pci: Add extra debugging
      qemu vfio-pci: Graphics device quirks
      qemu vfio-pci: Add support for VGA MMIO and I/O port access
      vfio-pci: Add PCIe capability mangling based on bus type
      vfio-pci: Generalize PCI config mangling
      linux-headers: Update to v3.9-rc2

commit 5d45de9796539f95eb6b1201588362981f8cb2d4
Author: Edgar E. Iglesias <edgar.iglesias at xilinx.com>
Date:   Thu Mar 28 22:59:03 2013 +0100

    microblaze: Add support for the sleep insn
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at xilinx.com>

diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index a74da8e..06d2346 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1317,6 +1317,23 @@ static void dec_br(DisasContext *dc)
     /* Memory barrier.  */
     mbar = (dc->ir >> 16) & 31;
     if (mbar == 2 && dc->imm == 4) {
+        /* mbar IMM & 16 decodes to sleep.  */
+        if (dc->rd & 16) {
+            TCGv_i32 tmp_hlt = tcg_const_i32(EXCP_HLT);
+            TCGv_i32 tmp_1 = tcg_const_i32(1);
+
+            LOG_DIS("sleep\n");
+
+            t_sync_flags(dc);
+            tcg_gen_st_i32(tmp_1, cpu_env,
+                           -offsetof(MicroBlazeCPU, env)
+                           +offsetof(CPUState, halted));
+            tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc + 4);
+            gen_helper_raise_exception(cpu_env, tmp_hlt);
+            tcg_temp_free_i32(tmp_hlt);
+            tcg_temp_free_i32(tmp_1);
+            return;
+        }
         LOG_DIS("mbar %d\n", dc->rd);
         /* Break the TB.  */
         dc->cpustate_changed = 1;
commit 6dcfdbad69aa510bc87b4a2585a597e028ca4eaa
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 13:35:40 2013 -0600

    vfio: cleanup includes
    
    Starting to get messy, put the back in alphabetical order.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index 0d2a445..693a9ff 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -19,26 +19,26 @@
  */
 
 #include <dirent.h>
-#include <unistd.h>
+#include <linux/vfio.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <linux/vfio.h>
+#include <unistd.h>
 
 #include "config.h"
-#include "qemu/event_notifier.h"
 #include "exec/address-spaces.h"
-#include "sysemu/kvm.h"
-#include "sysemu/sysemu.h"
 #include "exec/memory.h"
 #include "hw/pci/msi.h"
 #include "hw/pci/msix.h"
 #include "hw/pci/pci.h"
 #include "qemu-common.h"
 #include "qemu/error-report.h"
+#include "qemu/event_notifier.h"
 #include "qemu/queue.h"
 #include "qemu/range.h"
+#include "sysemu/kvm.h"
+#include "sysemu/sysemu.h"
 
 /* #define DEBUG_VFIO */
 #ifdef DEBUG_VFIO
commit c29029dd8829827ef8af3a6fb18f9df929ffc6b7
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 13:35:24 2013 -0600

    vfio: Add bootindex support
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index d310730..0d2a445 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -30,6 +30,7 @@
 #include "qemu/event_notifier.h"
 #include "exec/address-spaces.h"
 #include "sysemu/kvm.h"
+#include "sysemu/sysemu.h"
 #include "exec/memory.h"
 #include "hw/pci/msi.h"
 #include "hw/pci/msix.h"
@@ -160,6 +161,7 @@ typedef struct VFIODevice {
     uint32_t features;
 #define VFIO_FEATURE_ENABLE_VGA_BIT 0
 #define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT)
+    int32_t bootindex;
     uint8_t pm_cap;
     bool reset_works;
     bool has_vga;
@@ -3070,6 +3072,8 @@ static int vfio_initfn(PCIDevice *pdev)
         }
     }
 
+    add_boot_device_path(vdev->bootindex, &pdev->qdev, NULL);
+
     return 0;
 
 out_teardown:
@@ -3157,6 +3161,7 @@ static Property vfio_pci_dev_properties[] = {
                        intx.mmap_timeout, 1100),
     DEFINE_PROP_BIT("x-vga", VFIODevice, features,
                     VFIO_FEATURE_ENABLE_VGA_BIT, false),
+    DEFINE_PROP_INT32("bootindex", VFIODevice, bootindex, -1),
     /*
      * TODO - support passed fds... is this necessary?
      * DEFINE_PROP_STRING("vfiofd", VFIODevice, vfiofd_name),
commit ba66181828a5e5b0bbc117c4e999ca559a87456e
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 13:35:08 2013 -0600

    vfio-pci: Move devices to D0 on reset
    
    Guests may leave devices in a low power state at reboot, but we expect
    devices to be woken up for the next boot.  Make this happen.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index b913ec0..d310730 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -160,6 +160,7 @@ typedef struct VFIODevice {
     uint32_t features;
 #define VFIO_FEATURE_ENABLE_VGA_BIT 0
 #define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT)
+    uint8_t pm_cap;
     bool reset_works;
     bool has_vga;
 } VFIODevice;
@@ -2534,6 +2535,8 @@ static int vfio_add_std_cap(VFIODevice *vdev, uint8_t pos)
     case PCI_CAP_ID_MSIX:
         ret = vfio_setup_msix(vdev, pos);
         break;
+    case PCI_CAP_ID_PM:
+        vdev->pm_cap = pos;
     default:
         ret = pci_add_capability(pdev, cap_id, pos, size);
         break;
@@ -3108,6 +3111,26 @@ static void vfio_pci_reset(DeviceState *dev)
 
     vfio_disable_interrupts(vdev);
 
+    /* Make sure the device is in D0 */
+    if (vdev->pm_cap) {
+        uint16_t pmcsr;
+        uint8_t state;
+
+        pmcsr = vfio_pci_read_config(pdev, vdev->pm_cap + PCI_PM_CTRL, 2);
+        state = pmcsr & PCI_PM_CTRL_STATE_MASK;
+        if (state) {
+            pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+            vfio_pci_write_config(pdev, vdev->pm_cap + PCI_PM_CTRL, pmcsr, 2);
+            /* vfio handles the necessary delay here */
+            pmcsr = vfio_pci_read_config(pdev, vdev->pm_cap + PCI_PM_CTRL, 2);
+            state = pmcsr & PCI_PM_CTRL_STATE_MASK;
+            if (state) {
+                error_report("vfio: Unable to power on device, stuck in D%d\n",
+                             state);
+            }
+        }
+    }
+
     /*
      * Stop any ongoing DMA by disconecting I/O, MMIO, and bus master.
      * Also put INTx Disable in known state.
commit 82ca891283a08cddd659b534592fe00f2159bc74
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 13:34:56 2013 -0600

    vfio-pci: Add extra debugging
    
    Often when debugging it's useful to be able to disable bypass paths
    so no interactions with the device are missed.  Add some extra debug
    options to do this.  Also add device info on read/write BAR accesses,
    which is useful when debugging more than one assigned device.  A
    couple DPRINTFs also had redundant "vfio:" prefixes.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index e96f141..b913ec0 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -48,6 +48,10 @@
     do { } while (0)
 #endif
 
+/* Extra debugging, trap acceleration paths for more logging */
+#define VFIO_ALLOW_MMAP 1
+#define VFIO_ALLOW_KVM_INTX 1
+
 struct VFIODevice;
 
 typedef struct VFIOQuirk {
@@ -305,7 +309,7 @@ static void vfio_enable_intx_kvm(VFIODevice *vdev)
     int ret, argsz;
     int32_t *pfd;
 
-    if (!kvm_irqfds_enabled() ||
+    if (!VFIO_ALLOW_KVM_INTX || !kvm_irqfds_enabled() ||
         vdev->intx.route.mode != PCI_INTX_ENABLED ||
         !kvm_check_extension(kvm_state, KVM_CAP_IRQFD_RESAMPLE)) {
         return;
@@ -925,8 +929,16 @@ static void vfio_bar_write(void *opaque, hwaddr addr,
                      __func__, addr, data, size);
     }
 
-    DPRINTF("%s(BAR%d+0x%"HWADDR_PRIx", 0x%"PRIx64", %d)\n",
-            __func__, bar->nr, addr, data, size);
+#ifdef DEBUG_VFIO
+    {
+        VFIODevice *vdev = container_of(bar, VFIODevice, bars[bar->nr]);
+
+        DPRINTF("%s(%04x:%02x:%02x.%x:BAR%d+0x%"HWADDR_PRIx", 0x%"PRIx64
+                ", %d)\n", __func__, vdev->host.domain, vdev->host.bus,
+                vdev->host.slot, vdev->host.function, bar->nr, addr,
+                data, size);
+    }
+#endif
 
     /*
      * A read or write to a BAR always signals an INTx EOI.  This will
@@ -972,8 +984,16 @@ static uint64_t vfio_bar_read(void *opaque,
         break;
     }
 
-    DPRINTF("%s(BAR%d+0x%"HWADDR_PRIx", %d) = 0x%"PRIx64"\n",
-            __func__, bar->nr, addr, size, data);
+#ifdef DEBUG_VFIO
+    {
+        VFIODevice *vdev = container_of(bar, VFIODevice, bars[bar->nr]);
+
+        DPRINTF("%s(%04x:%02x:%02x.%x:BAR%d+0x%"HWADDR_PRIx
+                ", %d) = 0x%"PRIx64"\n", __func__, vdev->host.domain,
+                vdev->host.bus, vdev->host.slot, vdev->host.function,
+                bar->nr, addr, size, data);
+    }
+#endif
 
     /* Same as write above */
     vfio_eoi(container_of(bar, VFIODevice, bars[bar->nr]));
@@ -1917,7 +1937,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
     int ret;
 
     if (vfio_listener_skipped_section(section)) {
-        DPRINTF("vfio: SKIPPING region_add %"HWADDR_PRIx" - %"PRIx64"\n",
+        DPRINTF("SKIPPING region_add %"HWADDR_PRIx" - %"PRIx64"\n",
                 section->offset_within_address_space,
                 section->offset_within_address_space + section->size - 1);
         return;
@@ -1941,7 +1961,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
             section->offset_within_region +
             (iova - section->offset_within_address_space);
 
-    DPRINTF("vfio: region_add %"HWADDR_PRIx" - %"HWADDR_PRIx" [%p]\n",
+    DPRINTF("region_add %"HWADDR_PRIx" - %"HWADDR_PRIx" [%p]\n",
             iova, end - 1, vaddr);
 
     ret = vfio_dma_map(container, iova, end - iova, vaddr, section->readonly);
@@ -1961,7 +1981,7 @@ static void vfio_listener_region_del(MemoryListener *listener,
     int ret;
 
     if (vfio_listener_skipped_section(section)) {
-        DPRINTF("vfio: SKIPPING region_del %"HWADDR_PRIx" - %"PRIx64"\n",
+        DPRINTF("SKIPPING region_del %"HWADDR_PRIx" - %"PRIx64"\n",
                 section->offset_within_address_space,
                 section->offset_within_address_space + section->size - 1);
         return;
@@ -1981,7 +2001,7 @@ static void vfio_listener_region_del(MemoryListener *listener,
         return;
     }
 
-    DPRINTF("vfio: region_del %"HWADDR_PRIx" - %"HWADDR_PRIx"\n",
+    DPRINTF("region_del %"HWADDR_PRIx" - %"HWADDR_PRIx"\n",
             iova, end - 1);
 
     ret = vfio_dma_unmap(container, iova, end - iova);
@@ -2184,7 +2204,7 @@ static int vfio_mmap_bar(VFIOBAR *bar, MemoryRegion *mem, MemoryRegion *submem,
 {
     int ret = 0;
 
-    if (size && bar->flags & VFIO_REGION_INFO_FLAG_MMAP) {
+    if (VFIO_ALLOW_MMAP && size && bar->flags & VFIO_REGION_INFO_FLAG_MMAP) {
         int prot = 0;
 
         if (bar->flags & VFIO_REGION_INFO_FLAG_READ) {
commit 7076eabcbf38d514ecd47c8190d3d162573ceacc
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 13:34:40 2013 -0600

    qemu vfio-pci: Graphics device quirks
    
    Graphics cards have a number of different backdoors.  Some of these
    are alternative ways to get PCI BAR addresses, some of them are
    complete mirrors of PCI config space available through MMIO and
    I/O port access.  These quirks cover a number of ATI Radeon and
    Nvidia devices.  On the ATI/AMD side, this should enable HD5450
    and HD7850 and hopefully a host of devices around those generations.
    For Nvidia, my card selection is much more dated.  A 8400gs works
    well with both the Window shipped driver and the Nvidia downloaded
    driver.  A 7300le works as well, with the caveat that generating
    the Window experience index with the Nvidia driver causes the card
    to reset several times before generating a BSOD.  An NVS 290 card
    seems to run well with the shipped Windows driver, but generates
    a BSOD with the Nvidia driver.  All of the Nvidia devices work with
    the Linux Nvidia proprietary driver and nouveau, the HD5450 works
    with either radeon or fglrx, HD7850 works with vesa and fglrx (not
    supported by radeon).  Extremely limited 3D testing.
    
    Device reset is also an issue with graphics.  It's unfortunately
    very common that the devices offer no means to reset the card or
    doesn't seem effective.  Nvidia devices are pretty good about being
    able to get the device to a working state through the VGA BIOS init,
    Radeon devices less so, and often require a host reboot.  Work
    remains to be done here.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index ff415a6..e96f141 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -48,6 +48,16 @@
     do { } while (0)
 #endif
 
+struct VFIODevice;
+
+typedef struct VFIOQuirk {
+    MemoryRegion mem;
+    struct VFIODevice *vdev;
+    QLIST_ENTRY(VFIOQuirk) next;
+    uint32_t data;
+    uint32_t data2;
+} VFIOQuirk;
+
 typedef struct VFIOBAR {
     off_t fd_offset; /* offset of BAR within device fd */
     int fd; /* device fd, allows us to pass VFIOBAR as opaque data */
@@ -57,12 +67,14 @@ typedef struct VFIOBAR {
     size_t size;
     uint32_t flags; /* VFIO region flags (rd/wr/mmap) */
     uint8_t nr; /* cache the BAR number for debug */
+    QLIST_HEAD(, VFIOQuirk) quirks;
 } VFIOBAR;
 
 typedef struct VFIOVGARegion {
     MemoryRegion mem;
     off_t offset;
     int nr;
+    QLIST_HEAD(, VFIOQuirk) quirks;
 } VFIOVGARegion;
 
 typedef struct VFIOVGA {
@@ -82,8 +94,6 @@ typedef struct VFIOINTx {
     QEMUTimer *mmap_timer; /* enable mmaps after periods w/o interrupts */
 } VFIOINTx;
 
-struct VFIODevice;
-
 typedef struct VFIOMSIVector {
     EventNotifier interrupt; /* eventfd triggered on interrupt */
     struct VFIODevice *vdev; /* back pointer to device */
@@ -169,6 +179,8 @@ static QLIST_HEAD(, VFIOGroup)
 
 static void vfio_disable_interrupts(VFIODevice *vdev);
 static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len);
+static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
+                                  uint32_t val, int len);
 static void vfio_mmap_set_enabled(VFIODevice *vdev, bool enabled);
 
 /*
@@ -1059,6 +1071,700 @@ static const MemoryRegionOps vfio_vga_ops = {
 };
 
 /*
+ * Device specific quirks
+ */
+
+#define PCI_VENDOR_ID_ATI               0x1002
+
+/*
+ * Device 1002:68f9 (Advanced Micro Devices [AMD] nee ATI Cedar PRO [Radeon
+ * HD 5450/6350]) reports the upper byte of the physical address of the
+ * I/O port BAR4 through VGA register 0x3c3.  The BAR is 256 bytes, so the
+ * lower byte is known to be zero.  Probing for this quirk reads 0xff from
+ * port 0x3c3 on some devices so we store the physical address and replace
+ * reads with the virtual address any time it matches.  XXX Research when
+ * to enable quirk.
+ */
+static uint64_t vfio_ati_3c3_quirk_read(void *opaque,
+                                        hwaddr addr, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    PCIDevice *pdev = &vdev->pdev;
+    uint64_t data = vfio_vga_read(&vdev->vga.region[QEMU_PCI_VGA_IO_HI],
+                                  addr + 0x3, size);
+
+    if (data == quirk->data) {
+        data = pci_get_byte(pdev->config + PCI_BASE_ADDRESS_4 + 1);
+        DPRINTF("%s(0x3c3, 1) = 0x%"PRIx64"\n", __func__, data);
+    }
+
+    return data;
+}
+
+static const MemoryRegionOps vfio_ati_3c3_quirk = {
+    .read = vfio_ati_3c3_quirk_read,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void vfio_vga_probe_ati_3c3_quirk(VFIODevice *vdev)
+{
+    PCIDevice *pdev = &vdev->pdev;
+    off_t physoffset = vdev->config_offset + PCI_BASE_ADDRESS_4;
+    uint32_t physbar;
+    VFIOQuirk *quirk;
+
+    if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI ||
+        vdev->bars[4].size < 256) {
+        return;
+    }
+
+    /* Get I/O port BAR physical address */
+    if (pread(vdev->fd, &physbar, 4, physoffset) != 4) {
+        error_report("vfio: probe failed for ATI/AMD 0x3c3 quirk on device "
+                     "%04x:%02x:%02x.%x", vdev->host.domain,
+                     vdev->host.bus, vdev->host.slot, vdev->host.function);
+        return;
+    }
+
+    quirk = g_malloc0(sizeof(*quirk));
+    quirk->vdev = vdev;
+    quirk->data = (physbar >> 8) & 0xff;
+
+    memory_region_init_io(&quirk->mem, &vfio_ati_3c3_quirk, quirk,
+                          "vfio-ati-3c3-quirk", 1);
+    memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, 3,
+                                &quirk->mem);
+
+    QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks,
+                      quirk, next);
+
+    DPRINTF("Enabled ATI/AMD quirk 0x3c3 for device %04x:%02x:%02x.%x\n",
+            vdev->host.domain, vdev->host.bus, vdev->host.slot,
+            vdev->host.function);
+}
+
+/*
+ * Device 1002:68f9 (Advanced Micro Devices [AMD] nee ATI Cedar PRO [Radeon
+ * HD 5450/6350]) reports the physical address of MMIO BAR0 through a
+ * write/read operation on I/O port BAR4.  When uint32_t 0x4010 is written
+ * to offset 0x0, the subsequent read from offset 0x4 returns the contents
+ * of BAR0.  Test for this quirk on all ATI/AMD devices.  XXX - Note that
+ * 0x10 is the offset of BAR0 in config sapce, is this a window to all of
+ * config space?
+ */
+static uint64_t vfio_ati_4010_quirk_read(void *opaque,
+                                         hwaddr addr, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    PCIDevice *pdev = &vdev->pdev;
+    uint64_t data = vfio_bar_read(&vdev->bars[4], addr, size);
+
+    if (addr == 4 && size == 4 && quirk->data) {
+        data = pci_get_long(pdev->config + PCI_BASE_ADDRESS_0);
+        DPRINTF("%s(BAR4+0x4) = 0x%"PRIx64"\n", __func__, data);
+    }
+
+    quirk->data = 0;
+
+    return data;
+}
+
+static void vfio_ati_4010_quirk_write(void *opaque, hwaddr addr,
+                                      uint64_t data, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+
+    vfio_bar_write(&vdev->bars[4], addr, data, size);
+
+    quirk->data = (addr == 0 && size == 4 && data == 0x4010) ? 1 : 0;
+}
+
+static const MemoryRegionOps vfio_ati_4010_quirk = {
+    .read = vfio_ati_4010_quirk_read,
+    .write = vfio_ati_4010_quirk_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void vfio_probe_ati_4010_quirk(VFIODevice *vdev, int nr)
+{
+    PCIDevice *pdev = &vdev->pdev;
+    off_t physoffset = vdev->config_offset + PCI_BASE_ADDRESS_0;
+    uint32_t physbar0;
+    uint64_t data;
+    VFIOQuirk *quirk;
+
+    if (!vdev->has_vga || nr != 4 || !vdev->bars[0].size ||
+        pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) {
+        return;
+    }
+
+    /* Get I/O port BAR physical address */
+    if (pread(vdev->fd, &physbar0, 4, physoffset) != 4) {
+        error_report("vfio: probe failed for ATI/AMD 0x4010 quirk on device "
+                     "%04x:%02x:%02x.%x", vdev->host.domain,
+                     vdev->host.bus, vdev->host.slot, vdev->host.function);
+        return;
+    }
+
+    /* Write 0x4010 to I/O port BAR offset 0 */
+    vfio_bar_write(&vdev->bars[4], 0, 0x4010, 4);
+    /* Read back result */
+    data = vfio_bar_read(&vdev->bars[4], 4, 4);
+
+    /* If the register matches the physical address of BAR0, we need a quirk */
+    if (data != physbar0) {
+        return;
+    }
+
+    quirk = g_malloc0(sizeof(*quirk));
+    quirk->vdev = vdev;
+
+    memory_region_init_io(&quirk->mem, &vfio_ati_4010_quirk, quirk,
+                          "vfio-ati-4010-quirk", 8);
+    memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1);
+
+    QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
+
+    DPRINTF("Enabled ATI/AMD quirk 0x4010 for device %04x:%02x:%02x.%x\n",
+            vdev->host.domain, vdev->host.bus, vdev->host.slot,
+            vdev->host.function);
+}
+
+/*
+ * Device 1002:5b63 (Advanced Micro Devices [AMD] nee ATI RV370 [Radeon X550])
+ * retrieves the upper half of the MMIO BAR0 physical address by writing
+ * 0xf10 to I/O port BAR1 offset 0 and reading the result from offset 6.
+ * XXX - 0x10 is the offset of BAR0 in PCI config space, this could provide
+ * full access to config space.  Config space is little endian, so the data
+ * register probably starts at 0x4.
+ */
+static uint64_t vfio_ati_f10_quirk_read(void *opaque,
+                                        hwaddr addr, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    PCIDevice *pdev = &vdev->pdev;
+    uint64_t data = vfio_bar_read(&vdev->bars[1], addr, size);
+
+    if (addr == 6 && size == 2 && quirk->data) {
+        data = pci_get_word(pdev->config + PCI_BASE_ADDRESS_0 + 2);
+        DPRINTF("%s(BAR1+0x6) = 0x%"PRIx64"\n", __func__, data);
+    }
+
+    quirk->data = 0;
+
+    return data;
+}
+
+static void vfio_ati_f10_quirk_write(void *opaque, hwaddr addr,
+                                     uint64_t data, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+
+    vfio_bar_write(&vdev->bars[1], addr, data, size);
+
+    quirk->data = (addr == 0 && size == 4 && data == 0xf10) ? 1 : 0;
+}
+
+static const MemoryRegionOps vfio_ati_f10_quirk = {
+    .read = vfio_ati_f10_quirk_read,
+    .write = vfio_ati_f10_quirk_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void vfio_probe_ati_f10_quirk(VFIODevice *vdev, int nr)
+{
+    PCIDevice *pdev = &vdev->pdev;
+    off_t physoffset = vdev->config_offset + PCI_BASE_ADDRESS_0;
+    uint32_t physbar0;
+    uint64_t data;
+    VFIOQuirk *quirk;
+
+    if (!vdev->has_vga || nr != 1 || !vdev->bars[0].size ||
+        pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) {
+        return;
+    }
+
+    /* Get I/O port BAR physical address */
+    if (pread(vdev->fd, &physbar0, 4, physoffset) != 4) {
+        error_report("vfio: probe failed for ATI/AMD 0xf10 quirk on device "
+                     "%04x:%02x:%02x.%x", vdev->host.domain,
+                     vdev->host.bus, vdev->host.slot, vdev->host.function);
+        return;
+    }
+
+    vfio_bar_write(&vdev->bars[1], 0, 0xf10, 4);
+    data = vfio_bar_read(&vdev->bars[1], 0x6, 2);
+
+    /* If the register matches the physical address of BAR0, we need a quirk */
+    if (data != (le32_to_cpu(physbar0) >> 16)) {
+        return;
+    }
+
+    quirk = g_malloc0(sizeof(*quirk));
+    quirk->vdev = vdev;
+
+    memory_region_init_io(&quirk->mem, &vfio_ati_f10_quirk, quirk,
+                          "vfio-ati-f10-quirk", 8);
+    memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1);
+
+    QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
+
+    DPRINTF("Enabled ATI/AMD quirk 0xf10 for device %04x:%02x:%02x.%x\n",
+            vdev->host.domain, vdev->host.bus, vdev->host.slot,
+            vdev->host.function);
+}
+
+#define PCI_VENDOR_ID_NVIDIA                    0x10de
+
+/*
+ * Nvidia has several different methods to get to config space, the
+ * nouveu project has several of these documented here:
+ * https://github.com/pathscale/envytools/tree/master/hwdocs
+ *
+ * The first quirk is actually not documented in envytools and is found
+ * on 10de:01d1 (NVIDIA Corporation G72 [GeForce 7300 LE]).  This is an
+ * NV46 chipset.  The backdoor uses the legacy VGA I/O ports to access
+ * the mirror of PCI config space found at BAR0 offset 0x1800.  The access
+ * sequence first writes 0x338 to I/O port 0x3d4.  The target offset is
+ * then written to 0x3d0.  Finally 0x538 is written for a read and 0x738
+ * is written for a write to 0x3d4.  The BAR0 offset is then accessible
+ * through 0x3d0.  This quirk doesn't seem to be necessary on newer cards
+ * that use the I/O port BAR5 window but it doesn't hurt to leave it.
+ */
+enum {
+    NV_3D0_NONE,
+    NV_3D0_SELECT,
+    NV_3D0_WINDOW,
+    NV_3D0_READ,
+    NV_3D0_WRITE,
+};
+
+static uint64_t vfio_nvidia_3d0_quirk_read(void *opaque,
+                                           hwaddr addr, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    PCIDevice *pdev = &vdev->pdev;
+    uint64_t data = vfio_vga_read(&vdev->vga.region[QEMU_PCI_VGA_IO_HI],
+                                  addr + 0x10, size);
+
+    if (quirk->data == NV_3D0_READ && addr == 0) {
+        data = vfio_pci_read_config(pdev, quirk->data2, size);
+        DPRINTF("%s(0x3d0, %d) = 0x%"PRIx64"\n", __func__, size, data);
+    }
+
+    quirk->data = NV_3D0_NONE;
+
+    return data;
+}
+
+static void vfio_nvidia_3d0_quirk_write(void *opaque, hwaddr addr,
+                                        uint64_t data, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    PCIDevice *pdev = &vdev->pdev;
+
+    switch (quirk->data) {
+    case NV_3D0_NONE:
+        if (addr == 4 && data == 0x338) {
+            quirk->data = NV_3D0_SELECT;
+        }
+        break;
+    case NV_3D0_SELECT:
+        quirk->data = NV_3D0_NONE;
+        if (addr == 0 && (data & ~0xff) == 0x1800) {
+            quirk->data = NV_3D0_WINDOW;
+            quirk->data2 = data & 0xff;
+        }
+        break;
+    case NV_3D0_WINDOW:
+        quirk->data = NV_3D0_NONE;
+        if (addr == 4) {
+            if (data == 0x538) {
+                quirk->data = NV_3D0_READ;
+            } else if (data == 0x738) {
+                quirk->data = NV_3D0_WRITE;
+            }
+        }
+        break;
+    case NV_3D0_WRITE:
+        quirk->data = NV_3D0_NONE;
+        if (addr == 0) {
+            vfio_pci_write_config(pdev, quirk->data2, data, size);
+            DPRINTF("%s(0x3d0, 0x%"PRIx64", %d)\n", __func__, data, size);
+            return;
+        }
+        break;
+    default:
+        quirk->data = NV_3D0_NONE;
+    }
+
+    vfio_vga_write(&vdev->vga.region[QEMU_PCI_VGA_IO_HI],
+                   addr + 0x10, data, size);
+}
+
+static const MemoryRegionOps vfio_nvidia_3d0_quirk = {
+    .read = vfio_nvidia_3d0_quirk_read,
+    .write = vfio_nvidia_3d0_quirk_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void vfio_vga_probe_nvidia_3d0_quirk(VFIODevice *vdev)
+{
+    PCIDevice *pdev = &vdev->pdev;
+    VFIOQuirk *quirk;
+
+    if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA ||
+        !vdev->bars[1].size) {
+        return;
+    }
+
+    quirk = g_malloc0(sizeof(*quirk));
+    quirk->vdev = vdev;
+
+    memory_region_init_io(&quirk->mem, &vfio_nvidia_3d0_quirk, quirk,
+                          "vfio-nvidia-3d0-quirk", 6);
+    memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem,
+                                0x10, &quirk->mem);
+
+    QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks,
+                      quirk, next);
+
+    DPRINTF("Enabled NVIDIA VGA 0x3d0 quirk for device %04x:%02x:%02x.%x\n",
+            vdev->host.domain, vdev->host.bus, vdev->host.slot,
+            vdev->host.function);
+}
+
+/*
+ * The second quirk is documented in envytools.  The I/O port BAR5 is just
+ * a set of address/data ports to the MMIO BARs.  The BAR we care about is
+ * again BAR0.  This backdoor is apparently a bit newer than the one above
+ * so we need to not only trap 256 bytes @0x1800, but all of PCI config
+ * space, including extended space is available at the 4k @0x88000.
+ */
+enum {
+    NV_BAR5_ADDRESS = 0x1,
+    NV_BAR5_ENABLE = 0x2,
+    NV_BAR5_MASTER = 0x4,
+    NV_BAR5_VALID = 0x7,
+};
+
+static uint64_t vfio_nvidia_bar5_window_quirk_read(void *opaque,
+                                                   hwaddr addr, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    uint64_t data = vfio_bar_read(&vdev->bars[5], addr, size);
+
+    if (addr == 0xc && quirk->data == NV_BAR5_VALID) {
+        data = vfio_pci_read_config(&vdev->pdev, quirk->data2, size);
+        DPRINTF("%s(%04x:%02x:%02x.%x:BAR5+0x%"HWADDR_PRIx", %d) = 0x%"
+                PRIx64"\n", __func__, vdev->host.domain, vdev->host.bus,
+                vdev->host.slot, vdev->host.function, addr, size, data);
+    }
+
+    return data;
+}
+
+static void vfio_nvidia_bar5_window_quirk_write(void *opaque, hwaddr addr,
+                                                uint64_t data, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+
+    /*
+     * Use quirk->data to track enables and quirk->data2 for the offset
+     */
+    switch (addr) {
+    case 0x0:
+        if (data & 0x1) {
+            quirk->data |= NV_BAR5_MASTER;
+        } else {
+            quirk->data &= ~NV_BAR5_MASTER;
+        }
+        break;
+    case 0x4:
+        if (data & 0x1) {
+            quirk->data |= NV_BAR5_ENABLE;
+        } else {
+            quirk->data &= ~NV_BAR5_ENABLE;
+        }
+        break;
+    case 0x8:
+        if (quirk->data & NV_BAR5_MASTER) {
+            if ((data & ~0xfff) == 0x88000) {
+                quirk->data |= NV_BAR5_ADDRESS;
+                quirk->data2 = data & 0xfff;
+            } else if ((data & ~0xff) == 0x1800) {
+                quirk->data |= NV_BAR5_ADDRESS;
+                quirk->data2 = data & 0xff;
+            } else {
+                quirk->data &= ~NV_BAR5_ADDRESS;
+            }
+        }
+        break;
+    case 0xc:
+        if (quirk->data == NV_BAR5_VALID) {
+            vfio_pci_write_config(&vdev->pdev, quirk->data2, data, size);
+            DPRINTF("%s(%04x:%02x:%02x.%x:BAR5+0x%"HWADDR_PRIx", 0x%"
+                    PRIx64", %d)\n", __func__, vdev->host.domain,
+                    vdev->host.bus, vdev->host.slot, vdev->host.function,
+                    addr, data, size);
+            return;
+        }
+    }
+
+    vfio_bar_write(&vdev->bars[5], addr, data, size);
+}
+
+static const MemoryRegionOps vfio_nvidia_bar5_window_quirk = {
+    .read = vfio_nvidia_bar5_window_quirk_read,
+    .write = vfio_nvidia_bar5_window_quirk_write,
+    .valid.min_access_size = 4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void vfio_probe_nvidia_bar5_window_quirk(VFIODevice *vdev, int nr)
+{
+    PCIDevice *pdev = &vdev->pdev;
+    VFIOQuirk *quirk;
+
+    if (!vdev->has_vga || nr != 5 ||
+        pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA) {
+        return;
+    }
+
+    quirk = g_malloc0(sizeof(*quirk));
+    quirk->vdev = vdev;
+
+    memory_region_init_io(&quirk->mem, &vfio_nvidia_bar5_window_quirk, quirk,
+                          "vfio-nvidia-bar5-window-quirk", 16);
+    memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1);
+
+    QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
+
+    DPRINTF("Enabled NVIDIA BAR5 window quirk for device %04x:%02x:%02x.%x\n",
+            vdev->host.domain, vdev->host.bus, vdev->host.slot,
+            vdev->host.function);
+}
+
+/*
+ * Finally, BAR0 itself.  We want to redirect any accesses to either
+ * 0x1800 or 0x88000 through the PCI config space access functions.
+ *
+ * NB - quirk at a page granularity or else they don't seem to work when
+ *      BARs are mmap'd
+ *
+ * Here's offset 0x88000...
+ */
+static uint64_t vfio_nvidia_bar0_88000_quirk_read(void *opaque,
+                                                  hwaddr addr, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    hwaddr base = 0x88000 & TARGET_PAGE_MASK;
+    hwaddr offset = 0x88000 & ~TARGET_PAGE_MASK;
+    uint64_t data = vfio_bar_read(&vdev->bars[0], addr + base, size);
+
+    if (ranges_overlap(addr, size, offset, PCI_CONFIG_SPACE_SIZE)) {
+        data = vfio_pci_read_config(&vdev->pdev, addr - offset, size);
+
+        DPRINTF("%s(%04x:%02x:%02x.%x:BAR0+0x%"HWADDR_PRIx", %d) = 0x%"
+                PRIx64"\n", __func__, vdev->host.domain, vdev->host.bus,
+                vdev->host.slot, vdev->host.function, addr + base, size, data);
+    }
+
+    return data;
+}
+
+static void vfio_nvidia_bar0_88000_quirk_write(void *opaque, hwaddr addr,
+                                               uint64_t data, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    hwaddr base = 0x88000 & TARGET_PAGE_MASK;
+    hwaddr offset = 0x88000 & ~TARGET_PAGE_MASK;
+
+    if (ranges_overlap(addr, size, offset, PCI_CONFIG_SPACE_SIZE)) {
+        vfio_pci_write_config(&vdev->pdev, addr - offset, data, size);
+
+        DPRINTF("%s(%04x:%02x:%02x.%x:BAR0+0x%"HWADDR_PRIx", 0x%"
+                PRIx64", %d)\n", __func__, vdev->host.domain, vdev->host.bus,
+                vdev->host.slot, vdev->host.function, addr + base, data, size);
+    } else {
+        vfio_bar_write(&vdev->bars[0], addr + base, data, size);
+    }
+}
+
+static const MemoryRegionOps vfio_nvidia_bar0_88000_quirk = {
+    .read = vfio_nvidia_bar0_88000_quirk_read,
+    .write = vfio_nvidia_bar0_88000_quirk_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void vfio_probe_nvidia_bar0_88000_quirk(VFIODevice *vdev, int nr)
+{
+    PCIDevice *pdev = &vdev->pdev;
+    VFIOQuirk *quirk;
+
+    if (!vdev->has_vga || nr != 0 ||
+        pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA) {
+        return;
+    }
+
+    quirk = g_malloc0(sizeof(*quirk));
+    quirk->vdev = vdev;
+
+    memory_region_init_io(&quirk->mem, &vfio_nvidia_bar0_88000_quirk, quirk,
+                          "vfio-nvidia-bar0-88000-quirk",
+                          TARGET_PAGE_ALIGN(PCIE_CONFIG_SPACE_SIZE));
+    memory_region_add_subregion_overlap(&vdev->bars[nr].mem,
+                                        0x88000 & TARGET_PAGE_MASK,
+                                        &quirk->mem, 1);
+
+    QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
+
+    DPRINTF("Enabled NVIDIA BAR0 0x88000 quirk for device %04x:%02x:%02x.%x\n",
+            vdev->host.domain, vdev->host.bus, vdev->host.slot,
+            vdev->host.function);
+}
+
+/*
+ * And here's the same for BAR0 offset 0x1800...
+ */
+static uint64_t vfio_nvidia_bar0_1800_quirk_read(void *opaque,
+                                                 hwaddr addr, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    hwaddr base = 0x1800 & TARGET_PAGE_MASK;
+    hwaddr offset = 0x1800 & ~TARGET_PAGE_MASK;
+    uint64_t data = vfio_bar_read(&vdev->bars[0], addr + base, size);
+
+    if (ranges_overlap(addr, size, offset, PCI_CONFIG_SPACE_SIZE)) {
+        data = vfio_pci_read_config(&vdev->pdev, addr - offset, size);
+
+        DPRINTF("%s(%04x:%02x:%02x.%x:BAR0+0x%"HWADDR_PRIx", %d) = 0x%"
+                PRIx64"\n", __func__, vdev->host.domain, vdev->host.bus,
+                vdev->host.slot, vdev->host.function, addr + base, size, data);
+    }
+
+    return data;
+}
+
+static void vfio_nvidia_bar0_1800_quirk_write(void *opaque, hwaddr addr,
+                                              uint64_t data, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    hwaddr base = 0x1800 & TARGET_PAGE_MASK;
+    hwaddr offset = 0x1800 & ~TARGET_PAGE_MASK;
+
+    if (ranges_overlap(addr, size, offset, PCI_CONFIG_SPACE_SIZE)) {
+        vfio_pci_write_config(&vdev->pdev, addr - offset, data, size);
+
+        DPRINTF("%s(%04x:%02x:%02x.%x:BAR0+0x%"HWADDR_PRIx", 0x%"
+                PRIx64", %d)\n", __func__, vdev->host.domain, vdev->host.bus,
+                vdev->host.slot, vdev->host.function, addr + base, data, size);
+    } else {
+        vfio_bar_write(&vdev->bars[0], addr + base, data, size);
+    }
+}
+
+static const MemoryRegionOps vfio_nvidia_bar0_1800_quirk = {
+    .read = vfio_nvidia_bar0_1800_quirk_read,
+    .write = vfio_nvidia_bar0_1800_quirk_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void vfio_probe_nvidia_bar0_1800_quirk(VFIODevice *vdev, int nr)
+{
+    PCIDevice *pdev = &vdev->pdev;
+    VFIOQuirk *quirk;
+
+    if (!vdev->has_vga || nr != 0 ||
+        pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA) {
+        return;
+    }
+
+    /* Log the chipset ID */
+    DPRINTF("Nvidia NV%02x\n",
+            (unsigned int)(vfio_bar_read(&vdev->bars[0], 0, 4) >> 20) & 0xff);
+
+    quirk = g_malloc0(sizeof(*quirk));
+    quirk->vdev = vdev;
+
+    memory_region_init_io(&quirk->mem, &vfio_nvidia_bar0_1800_quirk, quirk,
+                          "vfio-nvidia-bar0-1800-quirk",
+                          TARGET_PAGE_ALIGN(PCI_CONFIG_SPACE_SIZE));
+    memory_region_add_subregion_overlap(&vdev->bars[nr].mem,
+                                        0x1800 & TARGET_PAGE_MASK,
+                                        &quirk->mem, 1);
+
+    QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
+
+    DPRINTF("Enabled NVIDIA BAR0 0x1800 quirk for device %04x:%02x:%02x.%x\n",
+            vdev->host.domain, vdev->host.bus, vdev->host.slot,
+            vdev->host.function);
+}
+
+/*
+ * TODO - Some Nvidia devices provide config access to their companion HDA
+ * device and even to their parent bridge via these config space mirrors.
+ * Add quirks for those regions.
+ */
+
+/*
+ * Common quirk probe entry points.
+ */
+static void vfio_vga_quirk_setup(VFIODevice *vdev)
+{
+    vfio_vga_probe_ati_3c3_quirk(vdev);
+    vfio_vga_probe_nvidia_3d0_quirk(vdev);
+}
+
+static void vfio_vga_quirk_teardown(VFIODevice *vdev)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(vdev->vga.region); i++) {
+        while (!QLIST_EMPTY(&vdev->vga.region[i].quirks)) {
+            VFIOQuirk *quirk = QLIST_FIRST(&vdev->vga.region[i].quirks);
+            memory_region_del_subregion(&vdev->vga.region[i].mem, &quirk->mem);
+            QLIST_REMOVE(quirk, next);
+            g_free(quirk);
+        }
+    }
+}
+
+static void vfio_bar_quirk_setup(VFIODevice *vdev, int nr)
+{
+    vfio_probe_ati_4010_quirk(vdev, nr);
+    vfio_probe_ati_f10_quirk(vdev, nr);
+    vfio_probe_nvidia_bar5_window_quirk(vdev, nr);
+    vfio_probe_nvidia_bar0_88000_quirk(vdev, nr);
+    vfio_probe_nvidia_bar0_1800_quirk(vdev, nr);
+}
+
+static void vfio_bar_quirk_teardown(VFIODevice *vdev, int nr)
+{
+    VFIOBAR *bar = &vdev->bars[nr];
+
+    while (!QLIST_EMPTY(&bar->quirks)) {
+        VFIOQuirk *quirk = QLIST_FIRST(&bar->quirks);
+        memory_region_del_subregion(&bar->mem, &quirk->mem);
+        QLIST_REMOVE(quirk, next);
+        g_free(quirk);
+    }
+}
+
+/*
  * PCI config space
  */
 static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len)
@@ -1459,6 +2165,8 @@ static void vfio_unmap_bar(VFIODevice *vdev, int nr)
         return;
     }
 
+    vfio_bar_quirk_teardown(vdev, nr);
+
     memory_region_del_subregion(&bar->mem, &bar->mmap_mem);
     munmap(bar->mmap, memory_region_size(&bar->mmap_mem));
 
@@ -1569,6 +2277,8 @@ static void vfio_map_bar(VFIODevice *vdev, int nr)
             error_report("%s unsupported. Performance may be slow", name);
         }
     }
+
+    vfio_bar_quirk_setup(vdev, nr);
 }
 
 static void vfio_map_bars(VFIODevice *vdev)
@@ -1599,6 +2309,7 @@ static void vfio_map_bars(VFIODevice *vdev)
         pci_register_vga(&vdev->pdev, &vdev->vga.region[QEMU_PCI_VGA_MEM].mem,
                          &vdev->vga.region[QEMU_PCI_VGA_IO_LO].mem,
                          &vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem);
+        vfio_vga_quirk_setup(vdev);
     }
 }
 
@@ -1611,6 +2322,7 @@ static void vfio_unmap_bars(VFIODevice *vdev)
     }
 
     if (vdev->has_vga) {
+        vfio_vga_quirk_teardown(vdev);
         pci_unregister_vga(&vdev->pdev);
         memory_region_destroy(&vdev->vga.region[QEMU_PCI_VGA_MEM].mem);
         memory_region_destroy(&vdev->vga.region[QEMU_PCI_VGA_IO_LO].mem);
@@ -2104,6 +2816,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev)
         vdev->bars[i].fd_offset = reg_info.offset;
         vdev->bars[i].fd = vdev->fd;
         vdev->bars[i].nr = i;
+        QLIST_INIT(&vdev->bars[i].quirks);
     }
 
     reg_info.index = VFIO_PCI_ROM_REGION_INDEX;
@@ -2169,12 +2882,15 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev)
 
         vdev->vga.region[QEMU_PCI_VGA_MEM].offset = QEMU_PCI_VGA_MEM_BASE;
         vdev->vga.region[QEMU_PCI_VGA_MEM].nr = QEMU_PCI_VGA_MEM;
+        QLIST_INIT(&vdev->vga.region[QEMU_PCI_VGA_MEM].quirks);
 
         vdev->vga.region[QEMU_PCI_VGA_IO_LO].offset = QEMU_PCI_VGA_IO_LO_BASE;
         vdev->vga.region[QEMU_PCI_VGA_IO_LO].nr = QEMU_PCI_VGA_IO_LO;
+        QLIST_INIT(&vdev->vga.region[QEMU_PCI_VGA_IO_LO].quirks);
 
         vdev->vga.region[QEMU_PCI_VGA_IO_HI].offset = QEMU_PCI_VGA_IO_HI_BASE;
         vdev->vga.region[QEMU_PCI_VGA_IO_HI].nr = QEMU_PCI_VGA_IO_HI;
+        QLIST_INIT(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks);
 
         vdev->has_vga = true;
     }
commit f15689c7e4422d5453ae45628df5b83a53e518ed
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 13:33:44 2013 -0600

    qemu vfio-pci: Add support for VGA MMIO and I/O port access
    
    Most VGA cards need some kind of quirk to fully operate since they
    hide backdoors to get to other registers outside of PCI config space
    within the registers, but this provides the base infrastructure.  If
    we could identity map PCI resources for assigned devices we would need
    a lot fewer quirks.
    
    To enable this, use a kernel side vfio-pci driver that incorporates
    VGA support (v3.9), and use the -vga none option and add the x-vga=on
    option for the vfio-pci device.  The "x-" denotes this as an
    experimental feature.  You may also need to use a cached copy of the
    VGA BIOS for your device, passing it to vfio-pci using the romfile=
    option.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index 0f74dbb..ff415a6 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -59,6 +59,18 @@ typedef struct VFIOBAR {
     uint8_t nr; /* cache the BAR number for debug */
 } VFIOBAR;
 
+typedef struct VFIOVGARegion {
+    MemoryRegion mem;
+    off_t offset;
+    int nr;
+} VFIOVGARegion;
+
+typedef struct VFIOVGA {
+    off_t fd_offset;
+    int fd;
+    VFIOVGARegion region[QEMU_PCI_VGA_NUM_REGIONS];
+} VFIOVGA;
+
 typedef struct VFIOINTx {
     bool pending; /* interrupt pending */
     bool kvm_accel; /* set when QEMU bypass through KVM enabled */
@@ -127,10 +139,15 @@ typedef struct VFIODevice {
     int nr_vectors; /* Number of MSI/MSIX vectors currently in use */
     int interrupt; /* Current interrupt type */
     VFIOBAR bars[PCI_NUM_REGIONS - 1]; /* No ROM */
+    VFIOVGA vga; /* 0xa0000, 0x3b0, 0x3c0 */
     PCIHostDeviceAddress host;
     QLIST_ENTRY(VFIODevice) next;
     struct VFIOGroup *group;
+    uint32_t features;
+#define VFIO_FEATURE_ENABLE_VGA_BIT 0
+#define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT)
     bool reset_works;
+    bool has_vga;
 } VFIODevice;
 
 typedef struct VFIOGroup {
@@ -958,6 +975,89 @@ static const MemoryRegionOps vfio_bar_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
+static void vfio_vga_write(void *opaque, hwaddr addr,
+                           uint64_t data, unsigned size)
+{
+    VFIOVGARegion *region = opaque;
+    VFIOVGA *vga = container_of(region, VFIOVGA, region[region->nr]);
+    union {
+        uint8_t byte;
+        uint16_t word;
+        uint32_t dword;
+        uint64_t qword;
+    } buf;
+    off_t offset = vga->fd_offset + region->offset + addr;
+
+    switch (size) {
+    case 1:
+        buf.byte = data;
+        break;
+    case 2:
+        buf.word = cpu_to_le16(data);
+        break;
+    case 4:
+        buf.dword = cpu_to_le32(data);
+        break;
+    default:
+        hw_error("vfio: unsupported write size, %d bytes\n", size);
+        break;
+    }
+
+    if (pwrite(vga->fd, &buf, size, offset) != size) {
+        error_report("%s(,0x%"HWADDR_PRIx", 0x%"PRIx64", %d) failed: %m",
+                     __func__, region->offset + addr, data, size);
+    }
+
+    DPRINTF("%s(0x%"HWADDR_PRIx", 0x%"PRIx64", %d)\n",
+            __func__, region->offset + addr, data, size);
+}
+
+static uint64_t vfio_vga_read(void *opaque, hwaddr addr, unsigned size)
+{
+    VFIOVGARegion *region = opaque;
+    VFIOVGA *vga = container_of(region, VFIOVGA, region[region->nr]);
+    union {
+        uint8_t byte;
+        uint16_t word;
+        uint32_t dword;
+        uint64_t qword;
+    } buf;
+    uint64_t data = 0;
+    off_t offset = vga->fd_offset + region->offset + addr;
+
+    if (pread(vga->fd, &buf, size, offset) != size) {
+        error_report("%s(,0x%"HWADDR_PRIx", %d) failed: %m",
+                     __func__, region->offset + addr, size);
+        return (uint64_t)-1;
+    }
+
+    switch (size) {
+    case 1:
+        data = buf.byte;
+        break;
+    case 2:
+        data = le16_to_cpu(buf.word);
+        break;
+    case 4:
+        data = le32_to_cpu(buf.dword);
+        break;
+    default:
+        hw_error("vfio: unsupported read size, %d bytes\n", size);
+        break;
+    }
+
+    DPRINTF("%s(0x%"HWADDR_PRIx", %d) = 0x%"PRIx64"\n",
+            __func__, region->offset + addr, size, data);
+
+    return data;
+}
+
+static const MemoryRegionOps vfio_vga_ops = {
+    .read = vfio_vga_read,
+    .write = vfio_vga_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 /*
  * PCI config space
  */
@@ -1478,6 +1578,28 @@ static void vfio_map_bars(VFIODevice *vdev)
     for (i = 0; i < PCI_ROM_SLOT; i++) {
         vfio_map_bar(vdev, i);
     }
+
+    if (vdev->has_vga) {
+        memory_region_init_io(&vdev->vga.region[QEMU_PCI_VGA_MEM].mem,
+                              &vfio_vga_ops,
+                              &vdev->vga.region[QEMU_PCI_VGA_MEM],
+                              "vfio-vga-mmio at 0xa0000",
+                              QEMU_PCI_VGA_MEM_SIZE);
+        memory_region_init_io(&vdev->vga.region[QEMU_PCI_VGA_IO_LO].mem,
+                              &vfio_vga_ops,
+                              &vdev->vga.region[QEMU_PCI_VGA_IO_LO],
+                              "vfio-vga-io at 0x3b0",
+                              QEMU_PCI_VGA_IO_LO_SIZE);
+        memory_region_init_io(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem,
+                              &vfio_vga_ops,
+                              &vdev->vga.region[QEMU_PCI_VGA_IO_HI],
+                              "vfio-vga-io at 0x3c0",
+                              QEMU_PCI_VGA_IO_HI_SIZE);
+
+        pci_register_vga(&vdev->pdev, &vdev->vga.region[QEMU_PCI_VGA_MEM].mem,
+                         &vdev->vga.region[QEMU_PCI_VGA_IO_LO].mem,
+                         &vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem);
+    }
 }
 
 static void vfio_unmap_bars(VFIODevice *vdev)
@@ -1487,6 +1609,13 @@ static void vfio_unmap_bars(VFIODevice *vdev)
     for (i = 0; i < PCI_ROM_SLOT; i++) {
         vfio_unmap_bar(vdev, i);
     }
+
+    if (vdev->has_vga) {
+        pci_unregister_vga(&vdev->pdev);
+        memory_region_destroy(&vdev->vga.region[QEMU_PCI_VGA_MEM].mem);
+        memory_region_destroy(&vdev->vga.region[QEMU_PCI_VGA_IO_LO].mem);
+        memory_region_destroy(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem);
+    }
 }
 
 /*
@@ -2012,6 +2141,44 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev)
     }
     vdev->config_offset = reg_info.offset;
 
+    if ((vdev->features & VFIO_FEATURE_ENABLE_VGA) &&
+        dev_info.num_regions > VFIO_PCI_VGA_REGION_INDEX) {
+        struct vfio_region_info vga_info = {
+            .argsz = sizeof(vga_info),
+            .index = VFIO_PCI_VGA_REGION_INDEX,
+         };
+
+        ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, &vga_info);
+        if (ret) {
+            error_report(
+                "vfio: Device does not support requested feature x-vga");
+            goto error;
+        }
+
+        if (!(vga_info.flags & VFIO_REGION_INFO_FLAG_READ) ||
+            !(vga_info.flags & VFIO_REGION_INFO_FLAG_WRITE) ||
+            vga_info.size < 0xbffff + 1) {
+            error_report("vfio: Unexpected VGA info, flags 0x%lx, size 0x%lx",
+                         (unsigned long)vga_info.flags,
+                         (unsigned long)vga_info.size);
+            goto error;
+        }
+
+        vdev->vga.fd_offset = vga_info.offset;
+        vdev->vga.fd = vdev->fd;
+
+        vdev->vga.region[QEMU_PCI_VGA_MEM].offset = QEMU_PCI_VGA_MEM_BASE;
+        vdev->vga.region[QEMU_PCI_VGA_MEM].nr = QEMU_PCI_VGA_MEM;
+
+        vdev->vga.region[QEMU_PCI_VGA_IO_LO].offset = QEMU_PCI_VGA_IO_LO_BASE;
+        vdev->vga.region[QEMU_PCI_VGA_IO_LO].nr = QEMU_PCI_VGA_IO_LO;
+
+        vdev->vga.region[QEMU_PCI_VGA_IO_HI].offset = QEMU_PCI_VGA_IO_HI_BASE;
+        vdev->vga.region[QEMU_PCI_VGA_IO_HI].nr = QEMU_PCI_VGA_IO_HI;
+
+        vdev->has_vga = true;
+    }
+
 error:
     if (ret) {
         QLIST_REMOVE(vdev, next);
@@ -2229,6 +2396,8 @@ static Property vfio_pci_dev_properties[] = {
     DEFINE_PROP_PCI_HOST_DEVADDR("host", VFIODevice, host),
     DEFINE_PROP_UINT32("x-intx-mmap-timeout-ms", VFIODevice,
                        intx.mmap_timeout, 1100),
+    DEFINE_PROP_BIT("x-vga", VFIODevice, features,
+                    VFIO_FEATURE_ENABLE_VGA_BIT, false),
     /*
      * TODO - support passed fds... is this necessary?
      * DEFINE_PROP_STRING("vfiofd", VFIODevice, vfiofd_name),
commit 96adc5c7c2178d02f0db2db368ba3e4aacef931a
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 11:50:04 2013 -0600

    vfio-pci: Add PCIe capability mangling based on bus type
    
    Windows seems to pay particular interest to the PCIe header type of
    devices and will fail to load drivers if we attach Endpoint devices or
    Legacy Endpoint devices to the Root Complex.  We can use
    pci_bus_is_express and pci_bus_is_root to determine the bus type and
    mangle the type appropriately:
    
    * Legacy PCI
      * No change, capability is unmodified for compatibility.
    * PCI Express
      * Integrated Root Complex Endpoint -> Endpoint
    * PCI Express Root Complex
      * Endpoint -> Integrated Root Complex Endpoint
      * Legacy Endpoint -> none, capability hidden
    
    We also take this opportunity to explicitly limit supported devices
    to Endpoints, Legacy Endpoints, and Root Complex Integrated Endpoints.
    We don't currently have support for other types and users often cause
    themselves problems by assigning them.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index a3bae7b..0f74dbb 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -1506,6 +1506,124 @@ static uint8_t vfio_std_cap_max_size(PCIDevice *pdev, uint8_t pos)
     return next - pos;
 }
 
+static void vfio_set_word_bits(uint8_t *buf, uint16_t val, uint16_t mask)
+{
+    pci_set_word(buf, (pci_get_word(buf) & ~mask) | val);
+}
+
+static void vfio_add_emulated_word(VFIODevice *vdev, int pos,
+                                   uint16_t val, uint16_t mask)
+{
+    vfio_set_word_bits(vdev->pdev.config + pos, val, mask);
+    vfio_set_word_bits(vdev->pdev.wmask + pos, ~mask, mask);
+    vfio_set_word_bits(vdev->emulated_config_bits + pos, mask, mask);
+}
+
+static void vfio_set_long_bits(uint8_t *buf, uint32_t val, uint32_t mask)
+{
+    pci_set_long(buf, (pci_get_long(buf) & ~mask) | val);
+}
+
+static void vfio_add_emulated_long(VFIODevice *vdev, int pos,
+                                   uint32_t val, uint32_t mask)
+{
+    vfio_set_long_bits(vdev->pdev.config + pos, val, mask);
+    vfio_set_long_bits(vdev->pdev.wmask + pos, ~mask, mask);
+    vfio_set_long_bits(vdev->emulated_config_bits + pos, mask, mask);
+}
+
+static int vfio_setup_pcie_cap(VFIODevice *vdev, int pos, uint8_t size)
+{
+    uint16_t flags;
+    uint8_t type;
+
+    flags = pci_get_word(vdev->pdev.config + pos + PCI_CAP_FLAGS);
+    type = (flags & PCI_EXP_FLAGS_TYPE) >> 4;
+
+    if (type != PCI_EXP_TYPE_ENDPOINT &&
+        type != PCI_EXP_TYPE_LEG_END &&
+        type != PCI_EXP_TYPE_RC_END) {
+
+        error_report("vfio: Assignment of PCIe type 0x%x "
+                     "devices is not currently supported", type);
+        return -EINVAL;
+    }
+
+    if (!pci_bus_is_express(vdev->pdev.bus)) {
+        /*
+         * Use express capability as-is on PCI bus.  It doesn't make much
+         * sense to even expose, but some drivers (ex. tg3) depend on it
+         * and guests don't seem to be particular about it.  We'll need
+         * to revist this or force express devices to express buses if we
+         * ever expose an IOMMU to the guest.
+         */
+    } else if (pci_bus_is_root(vdev->pdev.bus)) {
+        /*
+         * On a Root Complex bus Endpoints become Root Complex Integrated
+         * Endpoints, which changes the type and clears the LNK & LNK2 fields.
+         */
+        if (type == PCI_EXP_TYPE_ENDPOINT) {
+            vfio_add_emulated_word(vdev, pos + PCI_CAP_FLAGS,
+                                   PCI_EXP_TYPE_RC_END << 4,
+                                   PCI_EXP_FLAGS_TYPE);
+
+            /* Link Capabilities, Status, and Control goes away */
+            if (size > PCI_EXP_LNKCTL) {
+                vfio_add_emulated_long(vdev, pos + PCI_EXP_LNKCAP, 0, ~0);
+                vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKCTL, 0, ~0);
+                vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKSTA, 0, ~0);
+
+#ifndef PCI_EXP_LNKCAP2
+#define PCI_EXP_LNKCAP2 44
+#endif
+#ifndef PCI_EXP_LNKSTA2
+#define PCI_EXP_LNKSTA2 50
+#endif
+                /* Link 2 Capabilities, Status, and Control goes away */
+                if (size > PCI_EXP_LNKCAP2) {
+                    vfio_add_emulated_long(vdev, pos + PCI_EXP_LNKCAP2, 0, ~0);
+                    vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKCTL2, 0, ~0);
+                    vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKSTA2, 0, ~0);
+                }
+            }
+
+        } else if (type == PCI_EXP_TYPE_LEG_END) {
+            /*
+             * Legacy endpoints don't belong on the root complex.  Windows
+             * seems to be happier with devices if we skip the capability.
+             */
+            return 0;
+        }
+
+    } else {
+        /*
+         * Convert Root Complex Integrated Endpoints to regular endpoints.
+         * These devices don't support LNK/LNK2 capabilities, so make them up.
+         */
+        if (type == PCI_EXP_TYPE_RC_END) {
+            vfio_add_emulated_word(vdev, pos + PCI_CAP_FLAGS,
+                                   PCI_EXP_TYPE_ENDPOINT << 4,
+                                   PCI_EXP_FLAGS_TYPE);
+            vfio_add_emulated_long(vdev, pos + PCI_EXP_LNKCAP,
+                                   PCI_EXP_LNK_MLW_1 | PCI_EXP_LNK_LS_25, ~0);
+            vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKCTL, 0, ~0);
+        }
+
+        /* Mark the Link Status bits as emulated to allow virtual negotiation */
+        vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKSTA,
+                               pci_get_word(vdev->pdev.config + pos +
+                                            PCI_EXP_LNKSTA),
+                               PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS);
+    }
+
+    pos = pci_add_capability(&vdev->pdev, PCI_CAP_ID_EXP, pos, size);
+    if (pos >= 0) {
+        vdev->pdev.exp.exp_cap = pos;
+    }
+
+    return pos;
+}
+
 static int vfio_add_std_cap(VFIODevice *vdev, uint8_t pos)
 {
     PCIDevice *pdev = &vdev->pdev;
@@ -1536,13 +1654,22 @@ static int vfio_add_std_cap(VFIODevice *vdev, uint8_t pos)
             return ret;
         }
     } else {
-        pdev->config[PCI_CAPABILITY_LIST] = 0; /* Begin the rebuild */
+        /* Begin the rebuild, use QEMU emulated list bits */
+        pdev->config[PCI_CAPABILITY_LIST] = 0;
+        vdev->emulated_config_bits[PCI_CAPABILITY_LIST] = 0xff;
+        vdev->emulated_config_bits[PCI_STATUS] |= PCI_STATUS_CAP_LIST;
     }
 
+    /* Use emulated next pointer to allow dropping caps */
+    pci_set_byte(vdev->emulated_config_bits + pos + 1, 0xff);
+
     switch (cap_id) {
     case PCI_CAP_ID_MSI:
         ret = vfio_setup_msi(vdev, pos);
         break;
+    case PCI_CAP_ID_EXP:
+        ret = vfio_setup_pcie_cap(vdev, pos, size);
+        break;
     case PCI_CAP_ID_MSIX:
         ret = vfio_setup_msix(vdev, pos);
         break;
commit 4b5d5e87c7ab2e979a2cad6c8e01bcae55b85f1c
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 11:50:04 2013 -0600

    vfio-pci: Generalize PCI config mangling
    
    Kernel-side vfio virtualizes all of config space, but some parts are
    unique to Qemu.  For instance we may or may not expose the ROM BAR,
    Qemu manages MSI/MSIX, and Qemu manages the multi-function bit so that
    single function devices can appear as multi-function and vica versa.
    Generalize this into a bitmap of Qemu emulated bits.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index 288361d..a3bae7b 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -117,6 +117,7 @@ typedef struct VFIODevice {
     int fd;
     VFIOINTx intx;
     unsigned int config_size;
+    uint8_t *emulated_config_bits; /* QEMU emulated bits, little-endian */
     off_t config_offset; /* Offset of config space region within device fd */
     unsigned int rom_size;
     off_t rom_offset; /* Offset of ROM region within device fd */
@@ -963,44 +964,29 @@ static const MemoryRegionOps vfio_bar_ops = {
 static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len)
 {
     VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev);
-    uint32_t val = 0;
+    uint32_t emu_bits = 0, emu_val = 0, phys_val = 0, val;
 
-    /*
-     * We only need QEMU PCI config support for the ROM BAR, the MSI and MSIX
-     * capabilities, and the multifunction bit below.  We let VFIO handle
-     * virtualizing everything else.  Performance is not a concern here.
-     */
-    if (ranges_overlap(addr, len, PCI_ROM_ADDRESS, 4) ||
-        (pdev->cap_present & QEMU_PCI_CAP_MSIX &&
-         ranges_overlap(addr, len, pdev->msix_cap, MSIX_CAP_LENGTH)) ||
-        (pdev->cap_present & QEMU_PCI_CAP_MSI &&
-         ranges_overlap(addr, len, pdev->msi_cap, vdev->msi_cap_size))) {
+    memcpy(&emu_bits, vdev->emulated_config_bits + addr, len);
+    emu_bits = le32_to_cpu(emu_bits);
 
-        val = pci_default_read_config(pdev, addr, len);
-    } else {
-        if (pread(vdev->fd, &val, len, vdev->config_offset + addr) != len) {
+    if (emu_bits) {
+        emu_val = pci_default_read_config(pdev, addr, len);
+    }
+
+    if (~emu_bits & (0xffffffffU >> (32 - len * 8))) {
+        ssize_t ret;
+
+        ret = pread(vdev->fd, &phys_val, len, vdev->config_offset + addr);
+        if (ret != len) {
             error_report("%s(%04x:%02x:%02x.%x, 0x%x, 0x%x) failed: %m",
                          __func__, vdev->host.domain, vdev->host.bus,
                          vdev->host.slot, vdev->host.function, addr, len);
             return -errno;
         }
-        val = le32_to_cpu(val);
+        phys_val = le32_to_cpu(phys_val);
     }
 
-    /* Multifunction bit is virualized in QEMU */
-    if (unlikely(ranges_overlap(addr, len, PCI_HEADER_TYPE, 1))) {
-        uint32_t mask = PCI_HEADER_TYPE_MULTI_FUNCTION;
-
-        if (len == 4) {
-            mask <<= 16;
-        }
-
-        if (pdev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) {
-            val |= mask;
-        } else {
-            val &= ~mask;
-        }
-    }
+    val = (emu_val & emu_bits) | (phys_val & ~emu_bits);
 
     DPRINTF("%s(%04x:%02x:%02x.%x, @0x%x, len=0x%x) %x\n", __func__,
             vdev->host.domain, vdev->host.bus, vdev->host.slot,
@@ -1026,12 +1012,6 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
                      vdev->host.slot, vdev->host.function, addr, val, len);
     }
 
-    /* Write standard header bits to emulation */
-    if (addr < PCI_CONFIG_HEADER_SIZE) {
-        pci_default_write_config(pdev, addr, val, len);
-        return;
-    }
-
     /* MSI/MSI-X Enabling/Disabling */
     if (pdev->cap_present & QEMU_PCI_CAP_MSI &&
         ranges_overlap(addr, len, pdev->msi_cap, vdev->msi_cap_size)) {
@@ -1046,9 +1026,7 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
         } else if (was_enabled && !is_enabled) {
             vfio_disable_msi(vdev);
         }
-    }
-
-    if (pdev->cap_present & QEMU_PCI_CAP_MSIX &&
+    } else if (pdev->cap_present & QEMU_PCI_CAP_MSIX &&
         ranges_overlap(addr, len, pdev->msix_cap, MSIX_CAP_LENGTH)) {
         int is_enabled, was_enabled = msix_enabled(pdev);
 
@@ -1061,6 +1039,9 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
         } else if (was_enabled && !is_enabled) {
             vfio_disable_msix(vdev);
         }
+    } else {
+        /* Write everything to QEMU to keep emulated bits correct */
+        pci_default_write_config(pdev, addr, val, len);
     }
 }
 
@@ -2003,6 +1984,16 @@ static int vfio_initfn(PCIDevice *pdev)
         goto out_put;
     }
 
+    /* vfio emulates a lot for us, but some bits need extra love */
+    vdev->emulated_config_bits = g_malloc0(vdev->config_size);
+
+    /* QEMU can choose to expose the ROM or not */
+    memset(vdev->emulated_config_bits + PCI_ROM_ADDRESS, 0xff, 4);
+
+    /* QEMU can change multi-function devices to single function, or reverse */
+    vdev->emulated_config_bits[PCI_HEADER_TYPE] =
+                                              PCI_HEADER_TYPE_MULTI_FUNCTION;
+
     /*
      * Clear host resource mapping info.  If we choose not to register a
      * BAR, such as might be the case with the option ROM, we can get
@@ -2025,6 +2016,17 @@ static int vfio_initfn(PCIDevice *pdev)
         goto out_teardown;
     }
 
+    /* QEMU emulates all of MSI & MSIX */
+    if (pdev->cap_present & QEMU_PCI_CAP_MSIX) {
+        memset(vdev->emulated_config_bits + pdev->msix_cap, 0xff,
+               MSIX_CAP_LENGTH);
+    }
+
+    if (pdev->cap_present & QEMU_PCI_CAP_MSI) {
+        memset(vdev->emulated_config_bits + pdev->msi_cap, 0xff,
+               vdev->msi_cap_size);
+    }
+
     if (vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1)) {
         vdev->intx.mmap_timer = qemu_new_timer_ms(vm_clock,
                                                   vfio_intx_mmap_enable, vdev);
@@ -2042,6 +2044,7 @@ out_teardown:
     vfio_teardown_msi(vdev);
     vfio_unmap_bars(vdev);
 out_put:
+    g_free(vdev->emulated_config_bits);
     vfio_put_device(vdev);
     vfio_put_group(group);
     return ret;
@@ -2059,6 +2062,7 @@ static void vfio_exitfn(PCIDevice *pdev)
     }
     vfio_teardown_msi(vdev);
     vfio_unmap_bars(vdev);
+    g_free(vdev->emulated_config_bits);
     vfio_put_device(vdev);
     vfio_put_group(group);
 }
commit 010ca0b3fb9bebd6ad53c1db0266dd7b39f700c7
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 11:50:04 2013 -0600

    linux-headers: Update to v3.9-rc2
    
    Unedited scripts/update-linux-headers.sh run against v3.9-rc2 tag
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
index f787b72..e094121 100644
--- a/linux-headers/linux/vfio.h
+++ b/linux-headers/linux/vfio.h
@@ -303,6 +303,15 @@ enum {
 	VFIO_PCI_BAR5_REGION_INDEX,
 	VFIO_PCI_ROM_REGION_INDEX,
 	VFIO_PCI_CONFIG_REGION_INDEX,
+	/*
+	 * Expose VGA regions defined for PCI base class 03, subclass 00.
+	 * This includes I/O port ranges 0x3b0 to 0x3bb and 0x3c0 to 0x3df
+	 * as well as the MMIO range 0xa0000 to 0xbffff.  Each implemented
+	 * range is found at it's identity mapped offset from the region
+	 * offset, for example 0x3b0 is region_info.offset + 0x3b0.  Areas
+	 * between described ranges are unimplemented.
+	 */
+	VFIO_PCI_VGA_REGION_INDEX,
 	VFIO_PCI_NUM_REGIONS
 };
 
commit 174d4d215fb49b4d43196e62f22c2533431b260e
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sun Mar 24 01:52:07 2013 +0100

    tcg/mips: Implement muls2_i32
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index bd8c858..373c364 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -1413,6 +1413,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
 #endif
         break;
+    case INDEX_op_muls2_i32:
+        tcg_out_opc_reg(s, OPC_MULT, 0, args[2], args[3]);
+        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
+        tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
+        break;
     case INDEX_op_mulu2_i32:
         tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
         tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
@@ -1595,6 +1600,7 @@ static const TCGTargetOpDef mips_op_defs[] = {
 
     { INDEX_op_add_i32, { "r", "rZ", "rJ" } },
     { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
+    { INDEX_op_muls2_i32, { "r", "r", "rZ", "rZ" } },
     { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
     { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
     { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 0384bd3..6155327 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -87,7 +87,7 @@ typedef enum {
 #define TCG_TARGET_HAS_orc_i32          0
 #define TCG_TARGET_HAS_eqv_i32          0
 #define TCG_TARGET_HAS_nand_i32         0
-#define TCG_TARGET_HAS_muls2_i32        0
+#define TCG_TARGET_HAS_muls2_i32        1
 
 /* optional instructions only implemented on MIPS4, MIPS32 and Loongson 2 */
 #if (defined(__mips_isa_rev) && (__mips_isa_rev >= 1)) || \
commit c334a3880c02d1d8299ed54057e3fffd99ad2048
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:02 2013 +0100

    target-i386: SSE4.2: use clz32/ctz32 instead of reinventing the wheel
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/fpu_helper.c b/target-i386/fpu_helper.c
index 44f3d27..29a8fb6 100644
--- a/target-i386/fpu_helper.c
+++ b/target-i386/fpu_helper.c
@@ -20,6 +20,7 @@
 #include <math.h>
 #include "cpu.h"
 #include "helper.h"
+#include "qemu/host-utils.h"
 
 #if !defined(CONFIG_USER_ONLY)
 #include "exec/softmmu_exec.h"
diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index a0bac07..a11dba1 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -2064,34 +2064,6 @@ static inline unsigned pcmpxstrx(CPUX86State *env, Reg *d, Reg *s,
     return res;
 }
 
-static inline int rffs1(unsigned int val)
-{
-    int ret = 1, hi;
-
-    for (hi = sizeof(val) * 4; hi; hi /= 2) {
-        if (val >> hi) {
-            val >>= hi;
-            ret += hi;
-        }
-    }
-
-    return ret;
-}
-
-static inline int ffs1(unsigned int val)
-{
-    int ret = 1, hi;
-
-    for (hi = sizeof(val) * 4; hi; hi /= 2) {
-        if (val << hi) {
-            val <<= hi;
-            ret += hi;
-        }
-    }
-
-    return ret;
-}
-
 void glue(helper_pcmpestri, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
                                     uint32_t ctrl)
 {
@@ -2100,7 +2072,7 @@ void glue(helper_pcmpestri, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
                                  pcmp_elen(env, R_EAX, ctrl));
 
     if (res) {
-        env->regs[R_ECX] = (ctrl & (1 << 6)) ? rffs1(res) - 1 : 32 - ffs1(res);
+        env->regs[R_ECX] = (ctrl & (1 << 6)) ? 31 - clz32(res) : ctz32(res);
     } else {
         env->regs[R_ECX] = 16 >> (ctrl & (1 << 0));
     }
@@ -2138,7 +2110,7 @@ void glue(helper_pcmpistri, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
                                  pcmp_ilen(d, ctrl));
 
     if (res) {
-        env->regs[R_ECX] = (ctrl & (1 << 6)) ? rffs1(res) - 1 : 32 - ffs1(res);
+        env->regs[R_ECX] = (ctrl & (1 << 6)) ? 31 - clz32(res) : ctz32(res);
     } else {
         env->regs[R_ECX] = 16 >> (ctrl & (1 << 0));
     }
commit 83f7dc28ca7cb422f88caf3923bf078abb4e4dea
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:02 2013 +0100

    target-i386: enable SSE4.1 and SSE4.2 in TCG mode
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index a0640db..4b43759 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -388,16 +388,17 @@ typedef struct x86_def_t {
           /* missing:
           CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */
 #define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | \
-          CPUID_EXT_SSSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT | \
-          CPUID_EXT_MOVBE | CPUID_EXT_HYPERVISOR)
+          CPUID_EXT_SSSE3 | CPUID_EXT_CX16 | CPUID_EXT_SSE41 | \
+          CPUID_EXT_SSE42 | CPUID_EXT_POPCNT | CPUID_EXT_MOVBE | \
+          CPUID_EXT_HYPERVISOR)
           /* missing:
           CPUID_EXT_PCLMULQDQ, CPUID_EXT_DTES64, CPUID_EXT_DSCPL,
           CPUID_EXT_VMX, CPUID_EXT_SMX, CPUID_EXT_EST, CPUID_EXT_TM2,
           CPUID_EXT_CID, CPUID_EXT_FMA, CPUID_EXT_XTPR, CPUID_EXT_PDCM,
-          CPUID_EXT_PCID, CPUID_EXT_DCA, CPUID_EXT_SSE41, CPUID_EXT_SSE42,
-          CPUID_EXT_X2APIC, CPUID_EXT_TSC_DEADLINE_TIMER, CPUID_EXT_AES,
-          CPUID_EXT_XSAVE, CPUID_EXT_OSXSAVE, CPUID_EXT_AVX,
-          CPUID_EXT_F16C, CPUID_EXT_RDRAND */
+          CPUID_EXT_PCID, CPUID_EXT_DCA, CPUID_EXT_X2APIC,
+          CPUID_EXT_TSC_DEADLINE_TIMER, CPUID_EXT_AES, CPUID_EXT_XSAVE,
+          CPUID_EXT_OSXSAVE, CPUID_EXT_AVX, CPUID_EXT_F16C,
+          CPUID_EXT_RDRAND */
 #define TCG_EXT2_FEATURES ((TCG_FEATURES & CPUID_EXT2_AMD_ALIASES) | \
           CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
           CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT)
commit e4eba27e29114842978234a44c92b2a945a6b46d
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:02 2013 +0100

    target-i386: SSE4.2: fix pcmpXstrX instructions with "Masked(-)" polarity
    
    valids can equals to -1 if the reg/mem string is empty. Change the
    expression to have an empty xor mask in that case.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 77ab410..a0bac07 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -2050,7 +2050,7 @@ static inline unsigned pcmpxstrx(CPUX86State *env, Reg *d, Reg *s,
         res ^= (2 << upper) - 1;
         break;
     case 3:
-        res ^= (2 << valids) - 1;
+        res ^= (1 << (valids + 1)) - 1;
         break;
     }
 
commit 75c9527e190231fbc2fd8470e132f360e70206be
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:02 2013 +0100

    target-i386: SSE4.2: fix pcmpXstrX instructions in "Equal ordered" mode
    
    The inner loop should only change the current bit of the result, instead
    of the whole result.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 2fc5fdd..77ab410 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -2036,10 +2036,11 @@ static inline unsigned pcmpxstrx(CPUX86State *env, Reg *d, Reg *s,
     case 3:
         for (j = valids - validd; j >= 0; j--) {
             res <<= 1;
-            res |= 1;
+            v = 1;
             for (i = MIN(upper - j, validd); i >= 0; i--) {
-                res &= (pcmp_val(s, ctrl, i + j) == pcmp_val(d, ctrl, i));
+                v &= (pcmp_val(s, ctrl, i + j) == pcmp_val(d, ctrl, i));
             }
+            res |= v;
         }
         break;
     }
commit b27a6cacb73ca006c6995ca5c3db7347333ba7f4
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:01 2013 +0100

    target-i386: SSE4.2: fix pcmpXstrX instructions in "Equal each" mode
    
    pcmpXstrX instructions in "Equal each" mode force both invalid element
    pair to true. It means (upper - MAX(valids, validd)) bits should be set
    to 1, not (upper - MAX(valids, validd) + 1).
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 51c5fc9..2fc5fdd 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -2025,7 +2025,7 @@ static inline unsigned pcmpxstrx(CPUX86State *env, Reg *d, Reg *s,
         }
         break;
     case 2:
-        res = (2 << (upper - MAX(valids, validd))) - 1;
+        res = (1 << (upper - MAX(valids, validd))) - 1;
         res <<= MAX(valids, validd) - MIN(valids, validd);
         for (i = MIN(valids, validd); i >= 0; i--) {
             res <<= 1;
commit 649ad05ed4133d3a48d43881aa9351c024d9cdc1
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:01 2013 +0100

    target-i386: SSE4.2: fix pcmpXstrX instructions in "Ranges" mode
    
    Fix the order of the of the comparisons to match the "Intel 64 and
    IA-32 Architectures Software Developer's Manual".
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 4a95f41..51c5fc9 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -2019,8 +2019,8 @@ static inline unsigned pcmpxstrx(CPUX86State *env, Reg *d, Reg *s,
             res <<= 1;
             v = pcmp_val(s, ctrl, j);
             for (i = ((validd - 1) | 1); i >= 0; i -= 2) {
-                res |= (pcmp_val(d, ctrl, i - 0) <= v &&
-                        pcmp_val(d, ctrl, i - 1) >= v);
+                res |= (pcmp_val(d, ctrl, i - 0) >= v &&
+                        pcmp_val(d, ctrl, i - 1) <= v);
             }
         }
         break;
commit 2b8d7e9d728fe2b7c8ffb9859368fb2b5c0bf833
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:01 2013 +0100

    target-i386: SSE4.2: fix pcmpXstrm instructions
    
    pcmpXstrm instructions returns their result in the XMM0 register and
    not in the first operand.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 0667c87..4a95f41 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -2116,16 +2116,16 @@ void glue(helper_pcmpestrm, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
     if ((ctrl >> 6) & 1) {
         if (ctrl & 1) {
             for (i = 0; i < 8; i++, res >>= 1) {
-                d->W(i) = (res & 1) ? ~0 : 0;
+                env->xmm_regs[0].W(i) = (res & 1) ? ~0 : 0;
             }
         } else {
             for (i = 0; i < 16; i++, res >>= 1) {
-                d->B(i) = (res & 1) ? ~0 : 0;
+                env->xmm_regs[0].B(i) = (res & 1) ? ~0 : 0;
             }
         }
     } else {
-        d->Q(1) = 0;
-        d->Q(0) = res;
+        env->xmm_regs[0].Q(1) = 0;
+        env->xmm_regs[0].Q(0) = res;
     }
 }
 
@@ -2154,16 +2154,16 @@ void glue(helper_pcmpistrm, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
     if ((ctrl >> 6) & 1) {
         if (ctrl & 1) {
             for (i = 0; i < 8; i++, res >>= 1) {
-                d->W(i) = (res & 1) ? ~0 : 0;
+                env->xmm_regs[0].W(i) = (res & 1) ? ~0 : 0;
             }
         } else {
             for (i = 0; i < 16; i++, res >>= 1) {
-                d->B(i) = (res & 1) ? ~0 : 0;
+                env->xmm_regs[0].B(i) = (res & 1) ? ~0 : 0;
             }
         }
     } else {
-        d->Q(1) = 0;
-        d->Q(0) = res;
+        env->xmm_regs[0].Q(1) = 0;
+        env->xmm_regs[0].Q(0) = res;
     }
 }
 
commit 93e3c0ae69ae73d7f04ac378c5df6e98c7faa6dd
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:01 2013 +0100

    target-i386: SSE4.2: fix pcmpXstri instructions
    
    ffs1 returns the first bit set to one starting counting from the most
    significant bit.
    
    pcmpXstri returns the most significant bit set to one, starting counting
    from the least significant bit.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 0136df9..0667c87 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -2099,7 +2099,7 @@ void glue(helper_pcmpestri, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
                                  pcmp_elen(env, R_EAX, ctrl));
 
     if (res) {
-        env->regs[R_ECX] = ((ctrl & (1 << 6)) ? rffs1 : ffs1)(res) - 1;
+        env->regs[R_ECX] = (ctrl & (1 << 6)) ? rffs1(res) - 1 : 32 - ffs1(res);
     } else {
         env->regs[R_ECX] = 16 >> (ctrl & (1 << 0));
     }
@@ -2137,7 +2137,7 @@ void glue(helper_pcmpistri, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
                                  pcmp_ilen(d, ctrl));
 
     if (res) {
-        env->regs[R_ECX] = ((ctrl & (1 << 6)) ? rffs1 : ffs1)(res) - 1;
+        env->regs[R_ECX] = (ctrl & (1 << 6)) ? rffs1(res) - 1 : 32 - ffs1(res);
     } else {
         env->regs[R_ECX] = 16 >> (ctrl & (1 << 0));
     }
commit da5156cd9a62274839d6fa685cc52614886cc722
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:01 2013 +0100

    target-i386: SSE4.2: fix pcmpgtq instruction
    
    The "Intel 64 and IA-32 Architectures Software Developer's Manual" (at
    least recent versions) clearly says that the comparison is signed.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index cad9d75..0136df9 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -1933,8 +1933,7 @@ void glue(helper_mpsadbw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
 }
 
 /* SSE4.2 op helpers */
-/* it's unclear whether signed or unsigned */
-#define FCMPGTQ(d, s) (d > s ? -1 : 0)
+#define FCMPGTQ(d, s) ((int64_t)d > (int64_t)s ? -1 : 0)
 SSE_HELPER_Q(helper_pcmpgtq, FCMPGTQ)
 
 static inline int pcmp_elen(CPUX86State *env, int reg, uint32_t ctrl)
commit 34c6addd4b22583e7b408c0d1452eab753cbfb62
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:01 2013 +0100

    target-i386: SSE4.1: fix pinsrb instruction
    
    gen_op_mov_TN_reg() loads the value in cpu_T[0], so this temporary should
    be used instead of cpu_tmp0.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 7239696..7596a90 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -4404,9 +4404,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     if (mod == 3)
                         gen_op_mov_TN_reg(OT_LONG, 0, rm);
                     else
-                        tcg_gen_qemu_ld8u(cpu_tmp0, cpu_A0,
+                        tcg_gen_qemu_ld8u(cpu_T[0], cpu_A0,
                                         (s->mem_index >> 2) - 1);
-                    tcg_gen_st8_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State,
+                    tcg_gen_st8_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
                                             xmm_regs[reg].XMM_B(val & 15)));
                     break;
                 case 0x21: /* insertps */
commit c7b4c36714a442ae5abd26de293cb5e967be6e12
Merge: e63d28d b0d62a3
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Apr 1 10:36:09 2013 -0500

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging
    
    # By Dunrong Huang (1) and others
    # Via Stefan Hajnoczi
    * stefanha/trivial-patches:
      hw/tcx: Remove unused 'addr' field and the property that sets it
      hw/i386/pc: format load_linux function
      configure: show debug-info option in --help output

commit e63d28d7dbfcec81214aecc9ff0aaee46e87aa44
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 14:34:23 2013 +0000

    sysbus: Remove sysbus_add_memory and sysbus_del_memory
    
    Remove the sysbus_add_memory and sysbus_del_memory functions. These
    are trivial wrappers for mapping a memory region into the system
    memory space, and have no users now.  Sysbus devices should never map
    their own memory regions anyway; the correct API for mapping an mmio
    region is for the creator of the device to use sysbus_mmio_map.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1363358063-23973-6-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/sysbus.c b/hw/sysbus.c
index 9a19468..9004d8c 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -236,24 +236,6 @@ static char *sysbus_get_fw_dev_path(DeviceState *dev)
     return g_strdup(path);
 }
 
-void sysbus_add_memory(SysBusDevice *dev, hwaddr addr,
-                       MemoryRegion *mem)
-{
-    memory_region_add_subregion(get_system_memory(), addr, mem);
-}
-
-void sysbus_add_memory_overlap(SysBusDevice *dev, hwaddr addr,
-                               MemoryRegion *mem, unsigned priority)
-{
-    memory_region_add_subregion_overlap(get_system_memory(), addr, mem,
-                                        priority);
-}
-
-void sysbus_del_memory(SysBusDevice *dev, MemoryRegion *mem)
-{
-    memory_region_del_subregion(get_system_memory(), mem);
-}
-
 void sysbus_add_io(SysBusDevice *dev, hwaddr addr,
                        MemoryRegion *mem)
 {
diff --git a/hw/sysbus.h b/hw/sysbus.h
index 5d90a52..7c2e316 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -58,11 +58,6 @@ void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq);
 void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr);
 void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr,
                              unsigned priority);
-void sysbus_add_memory(SysBusDevice *dev, hwaddr addr,
-                       MemoryRegion *mem);
-void sysbus_add_memory_overlap(SysBusDevice *dev, hwaddr addr,
-                               MemoryRegion *mem, unsigned priority);
-void sysbus_del_memory(SysBusDevice *dev, MemoryRegion *mem);
 void sysbus_add_io(SysBusDevice *dev, hwaddr addr,
                    MemoryRegion *mem);
 void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem);
commit c31bc98e3bcf52fe1cd4b9b7a70869330eae80ea
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Mar 28 18:43:04 2013 +0000

    hw/milkymist-softusb: set buffer in softusb_read_{dmem, pmem} error path
    
    Make sure we set the buffer to something in the softusb_read_{dmem,pmem}
    error paths, since the caller will use the buffer unconditionally.
    (Newer gcc is smart enough to spot this and complain about 'may be
    used uninitialized'.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1364496184-11994-1-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c
index b279d4e..90a0ae5 100644
--- a/hw/milkymist-softusb.c
+++ b/hw/milkymist-softusb.c
@@ -132,6 +132,7 @@ static inline void softusb_read_dmem(MilkymistSoftUsbState *s,
     if (offset + len >= s->dmem_size) {
         error_report("milkymist_softusb: read dmem out of bounds "
                 "at offset 0x%x, len %d", offset, len);
+        memset(buf, 0, len);
         return;
     }
 
@@ -156,6 +157,7 @@ static inline void softusb_read_pmem(MilkymistSoftUsbState *s,
     if (offset + len >= s->pmem_size) {
         error_report("milkymist_softusb: read pmem out of bounds "
                 "at offset 0x%x, len %d", offset, len);
+        memset(buf, 0, len);
         return;
     }
 
commit c34e120554c31d45bdfbac08a5c1d9ef92a62020
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 14:34:22 2013 +0000

    milkymist-softusb: Don't map RAM memory regions in the device itself
    
    Don't map the pmem and dmem RAM memory regions in the milkymist-softusb
    device itself. Instead just expose them as sysbus mmio regions which
    the device creator can map appropriately. This allows us to drop the
    pmem_base and dmem_base properties. Instead of going via
    cpu_physical_memory_read/_write when the device wants to access the
    RAMs, we just keep a host pointer to the memory and use that.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Michael Walle <michael at walle.cc>
    Message-id: 1363358063-23973-5-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/milkymist-hw.h b/hw/milkymist-hw.h
index 8e6c01e..4e86c4e 100644
--- a/hw/milkymist-hw.h
+++ b/hw/milkymist-hw.h
@@ -194,12 +194,12 @@ static inline DeviceState *milkymist_softusb_create(hwaddr base,
     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(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, pmem_base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, dmem_base);
     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
 
     return dev;
diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c
index d911686..b279d4e 100644
--- a/hw/milkymist-softusb.c
+++ b/hw/milkymist-softusb.c
@@ -54,10 +54,11 @@ struct MilkymistSoftUsbState {
     MemoryRegion dmem;
     qemu_irq irq;
 
+    void *pmem_ptr;
+    void *dmem_ptr;
+
     /* device properties */
-    uint32_t pmem_base;
     uint32_t pmem_size;
-    uint32_t dmem_base;
     uint32_t dmem_size;
 
     /* device registers */
@@ -134,7 +135,7 @@ static inline void softusb_read_dmem(MilkymistSoftUsbState *s,
         return;
     }
 
-    cpu_physical_memory_read(s->dmem_base + offset, buf, len);
+    memcpy(buf, s->dmem_ptr + offset, len);
 }
 
 static inline void softusb_write_dmem(MilkymistSoftUsbState *s,
@@ -146,7 +147,7 @@ static inline void softusb_write_dmem(MilkymistSoftUsbState *s,
         return;
     }
 
-    cpu_physical_memory_write(s->dmem_base + offset, buf, len);
+    memcpy(s->dmem_ptr + offset, buf, len);
 }
 
 static inline void softusb_read_pmem(MilkymistSoftUsbState *s,
@@ -158,7 +159,7 @@ static inline void softusb_read_pmem(MilkymistSoftUsbState *s,
         return;
     }
 
-    cpu_physical_memory_read(s->pmem_base + offset, buf, len);
+    memcpy(buf, s->pmem_ptr + offset, len);
 }
 
 static inline void softusb_write_pmem(MilkymistSoftUsbState *s,
@@ -170,7 +171,7 @@ static inline void softusb_write_pmem(MilkymistSoftUsbState *s,
         return;
     }
 
-    cpu_physical_memory_write(s->pmem_base + offset, buf, len);
+    memcpy(s->pmem_ptr + offset, buf, len);
 }
 
 static void softusb_mouse_changed(MilkymistSoftUsbState *s)
@@ -270,11 +271,13 @@ static int milkymist_softusb_init(SysBusDevice *dev)
     memory_region_init_ram(&s->pmem, "milkymist-softusb.pmem",
                            s->pmem_size);
     vmstate_register_ram_global(&s->pmem);
-    sysbus_add_memory(dev, s->pmem_base, &s->pmem);
+    s->pmem_ptr = memory_region_get_ram_ptr(&s->pmem);
+    sysbus_init_mmio(dev, &s->pmem);
     memory_region_init_ram(&s->dmem, "milkymist-softusb.dmem",
                            s->dmem_size);
     vmstate_register_ram_global(&s->dmem);
-    sysbus_add_memory(dev, s->dmem_base, &s->dmem);
+    s->dmem_ptr = memory_region_get_ram_ptr(&s->dmem);
+    sysbus_init_mmio(dev, &s->dmem);
 
     hid_init(&s->hid_kbd, HID_KEYBOARD, softusb_kbd_hid_datain);
     hid_init(&s->hid_mouse, HID_MOUSE, softusb_mouse_hid_datain);
@@ -298,9 +301,7 @@ static const VMStateDescription vmstate_milkymist_softusb = {
 };
 
 static Property milkymist_softusb_properties[] = {
-    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(),
 };
commit 20cf850c6ac5bf1ef13de1da93a5c8b5ea28b304
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 14:34:21 2013 +0000

    milkymist-minimac2: Just expose buffers as a sysbus mmio region
    
    Just expose the register buffers memory as a standard sysbus mmio
    region which the creator of the device can map, rather than
    providing a qdev property which the creator has to set to the
    base address and then doing the mapping in the device's own
    init function.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Michael Walle <michael at walle.cc>
    Message-id: 1363358063-23973-4-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/milkymist-hw.h b/hw/milkymist-hw.h
index c047a70..8e6c01e 100644
--- a/hw/milkymist-hw.h
+++ b/hw/milkymist-hw.h
@@ -177,10 +177,10 @@ static inline DeviceState *milkymist_minimac2_create(hwaddr base,
 
     qemu_check_nic_model(&nd_table[0], "minimac2");
     dev = qdev_create(NULL, "milkymist-minimac2");
-    qdev_prop_set_taddr(dev, "buffers_base", buffers_base);
     qdev_set_nic_properties(dev, &nd_table[0]);
     qdev_init_nofail(dev);
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, buffers_base);
     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, rx_irq);
     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, tx_irq);
 
diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c
index c20ff90..29618e8 100644
--- a/hw/milkymist-minimac2.c
+++ b/hw/milkymist-minimac2.c
@@ -96,7 +96,6 @@ struct MilkymistMinimac2State {
     NICState *nic;
     NICConf conf;
     char *phy_model;
-    hwaddr buffers_base;
     MemoryRegion buffers;
     MemoryRegion regs_region;
 
@@ -475,7 +474,7 @@ static int milkymist_minimac2_init(SysBusDevice *dev)
     s->rx1_buf = s->rx0_buf + MINIMAC2_BUFFER_SIZE;
     s->tx_buf = s->rx1_buf + MINIMAC2_BUFFER_SIZE;
 
-    sysbus_add_memory(dev, s->buffers_base, &s->buffers);
+    sysbus_init_mmio(dev, &s->buffers);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     s->nic = qemu_new_nic(&net_milkymist_minimac2_info, &s->conf,
@@ -517,8 +516,6 @@ static const VMStateDescription vmstate_milkymist_minimac2 = {
 };
 
 static Property milkymist_minimac2_properties[] = {
-    DEFINE_PROP_TADDR("buffers_base", MilkymistMinimac2State,
-    buffers_base, 0),
     DEFINE_NIC_PROPERTIES(MilkymistMinimac2State, conf),
     DEFINE_PROP_STRING("phy_model", MilkymistMinimac2State, phy_model),
     DEFINE_PROP_END_OF_LIST(),
commit a86f200aeb66a4f402b22241a5d8360f02bfc090
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 14:34:20 2013 +0000

    musicpal: qdevify musicpal-misc
    
    Make musicpal-misc into its own (trivial) qdev device, so we
    can get rid of the abuse of sysbus_add_memory().
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1363358063-23973-3-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index edd5282..ea8473d 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -1033,6 +1033,15 @@ static const TypeInfo mv88w8618_flashcfg_info = {
 
 #define MP_BOARD_REVISION       0x31
 
+typedef struct {
+    SysBusDevice parent_obj;
+    MemoryRegion iomem;
+} MusicPalMiscState;
+
+#define TYPE_MUSICPAL_MISC "musicpal-misc"
+#define MUSICPAL_MISC(obj) \
+     OBJECT_CHECK(MusicPalMiscState, (obj), TYPE_MUSICPAL_MISC)
+
 static uint64_t musicpal_misc_read(void *opaque, hwaddr offset,
                                    unsigned size)
 {
@@ -1056,15 +1065,23 @@ static const MemoryRegionOps musicpal_misc_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void musicpal_misc_init(SysBusDevice *dev)
+static void musicpal_misc_init(Object *obj)
 {
-    MemoryRegion *iomem = g_new(MemoryRegion, 1);
+    SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+    MusicPalMiscState *s = MUSICPAL_MISC(obj);
 
-    memory_region_init_io(iomem, &musicpal_misc_ops, NULL,
+    memory_region_init_io(&s->iomem, &musicpal_misc_ops, NULL,
                           "musicpal-misc", MP_MISC_SIZE);
-    sysbus_add_memory(dev, MP_MISC_BASE, iomem);
+    sysbus_init_mmio(sd, &s->iomem);
 }
 
+static const TypeInfo musicpal_misc_info = {
+    .name = TYPE_MUSICPAL_MISC,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_init = musicpal_misc_init,
+    .instance_size = sizeof(MusicPalMiscState),
+};
+
 /* WLAN register offsets */
 #define MP_WLAN_MAGIC1          0x11c
 #define MP_WLAN_MAGIC2          0x124
@@ -1614,7 +1631,7 @@ static void musicpal_init(QEMUMachineInitArgs *args)
 
     sysbus_create_simple("mv88w8618_wlan", MP_WLAN_BASE, NULL);
 
-    musicpal_misc_init(SYS_BUS_DEVICE(dev));
+    sysbus_create_simple(TYPE_MUSICPAL_MISC, MP_MISC_BASE, NULL);
 
     dev = sysbus_create_simple("musicpal_gpio", MP_GPIO_BASE, pic[MP_GPIO_IRQ]);
     i2c_dev = sysbus_create_simple("gpio_i2c", -1, NULL);
@@ -1694,6 +1711,7 @@ static void musicpal_register_types(void)
     type_register_static(&musicpal_lcd_info);
     type_register_static(&musicpal_gpio_info);
     type_register_static(&musicpal_key_info);
+    type_register_static(&musicpal_misc_info);
 }
 
 type_init(musicpal_register_types)
commit 4ce5dae88ecf2bafa0cd663de7e923728b1b3672
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 14:34:19 2013 +0000

    sysbus: make SysBusDeviceClass::init optional
    
    Make the SysBusDeviceClass::init optional, for devices which
    genuinely don't need to do anything here. In particular, simple
    devices which can do all their initialization in their
    instance_init method don't need either a DeviceClass::realize
    or SysBusDeviceClass::init method.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Acked-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 1363358063-23973-2-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/sysbus.c b/hw/sysbus.c
index 702fc72..9a19468 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -137,6 +137,9 @@ static int sysbus_device_init(DeviceState *dev)
     SysBusDevice *sd = SYS_BUS_DEVICE(dev);
     SysBusDeviceClass *sbc = SYS_BUS_DEVICE_GET_CLASS(sd);
 
+    if (!sbc->init) {
+        return 0;
+    }
     return sbc->init(sd);
 }
 
commit 5357406415571b3f03d05b60a143afdea2b9b1b9
Author: Dunrong Huang <huangdr at cloud-times.com>
Date:   Sun Mar 31 09:35:53 2013 +0800

    target-moxie: set do_interrupt to a target-specific helper function
    
    The value of "do_interrupt" member of CPUClass shoule be set to a
    target-specific function, or it will lead to a segfault like below:
    
    $ moxie-softmmu/qemu-system-moxie -M moxiesim
    Segmentation fault
    
    Cc: Anthony Green <green at moxielogic.com>
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Cc: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Dunrong Huang <huangdr at cloud-times.com>
    Signed-of-by: Anthony Green <green at moxielogic.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-moxie/cpu.c b/target-moxie/cpu.c
index c17d3f0..c0855f0 100644
--- a/target-moxie/cpu.c
+++ b/target-moxie/cpu.c
@@ -98,6 +98,7 @@ static void moxie_cpu_class_init(ObjectClass *oc, void *data)
     cc->class_by_name = moxie_cpu_class_by_name;
 
     dc->vmsd = &vmstate_moxie_cpu;
+    cc->do_interrupt = moxie_cpu_do_interrupt;
 }
 
 static void moxielite_initfn(Object *obj)
diff --git a/target-moxie/cpu.h b/target-moxie/cpu.h
index b96236f..988729a 100644
--- a/target-moxie/cpu.h
+++ b/target-moxie/cpu.h
@@ -117,7 +117,7 @@ static inline MoxieCPU *moxie_env_get_cpu(CPUMoxieState *env)
 
 MoxieCPU *cpu_moxie_init(const char *cpu_model);
 int cpu_moxie_exec(CPUMoxieState *s);
-void do_interrupt(CPUMoxieState *env);
+void moxie_cpu_do_interrupt(CPUState *cs);
 void moxie_translate_init(void);
 int cpu_moxie_signal_handler(int host_signum, void *pinfo,
                              void *puc);
diff --git a/target-moxie/helper.c b/target-moxie/helper.c
index 8604ce8..6e0ac2a 100644
--- a/target-moxie/helper.c
+++ b/target-moxie/helper.c
@@ -102,7 +102,7 @@ void helper_debug(CPUMoxieState *env)
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt(CPUState *env)
+void moxie_cpu_do_interrupt(CPUState *env)
 {
     env->exception_index = -1;
 }
@@ -147,8 +147,11 @@ int cpu_moxie_handle_mmu_fault(CPUMoxieState *env, target_ulong address,
 }
 
 
-void do_interrupt(CPUMoxieState *env)
+void moxie_cpu_do_interrupt(CPUState *cs)
 {
+    MoxieCPU *cpu = MOXIE_CPU(cs);
+    CPUMoxieState *env = &cpu->env;
+
     switch (env->exception_index) {
     case MOXIE_EX_BREAK:
         break;
commit 5e3a0f418c4d57399778cee0b55aebfb663b6425
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Mar 29 18:20:20 2013 +0100

    w32: Fix build with older gcc (unresolved symbol)
    
    The cross i586-mingw32msvc-gcc 4.4.4 from Debian Squeeze does not support
    __sync_val_compare_and_swap by default.
    
    Using -march=i686 fixes that and should also result in better code.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/configure b/configure
index f2af714..70c2219 100755
--- a/configure
+++ b/configure
@@ -562,6 +562,11 @@ 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"
+  if test "$cpu" = "i386"; then
+    # We need something better than i386 for __sync_val_compare_and_swap
+    # and can expect that QEMU will only run on i686 or later.
+    QEMU_CFLAGS="-march=i686 $QEMU_CFLAGS"
+  fi
   LIBS="-lwinmm -lws2_32 -liphlpapi $LIBS"
 cat > $TMPC << EOF
 int main(void) { return 0; }
commit e06335b9515f0508f33846e58b2028dfa4fc9983
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Mar 24 09:04:48 2013 +0100

    target-moxie: Fix pointer-to-integer conversion (MinGW-w64)
    
    The type cast must use tcg_target_long instead of long.
    This makes a difference for hosts where sizeof(long) != sizeof(void *).
    
    Cc: Anthony Green <green at moxielogic.com>
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Anthony Green <green at moxielogic.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-moxie/translate.c b/target-moxie/translate.c
index 34f166e..cc02bd3 100644
--- a/target-moxie/translate.c
+++ b/target-moxie/translate.c
@@ -133,7 +133,7 @@ static inline void gen_goto_tb(CPUMoxieState *env, DisasContext *ctx,
         !ctx->singlestep_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) {
commit c9721215126a8ef46abd2e762efd6aa5ff6b92b9
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Sat Feb 23 00:40:39 2013 +0000

    piix_pci: Fix C99 comments
    
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Tested-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Laszlo Ersek <lersek at redhat.com>
    Message-id: 1361580039-4459-4-git-send-email-dwmw2 at infradead.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 1e05d49..83fcfa4 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -425,10 +425,10 @@ static void piix3_reset(void *opaque)
     PIIX3State *d = opaque;
     uint8_t *pci_conf = d->dev.config;
 
-    pci_conf[0x04] = 0x07; // master, memory and I/O
+    pci_conf[0x04] = 0x07; /* master, memory and I/O */
     pci_conf[0x05] = 0x00;
     pci_conf[0x06] = 0x00;
-    pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
+    pci_conf[0x07] = 0x02; /* PCI_status_devsel_medium */
     pci_conf[0x4c] = 0x4d;
     pci_conf[0x4e] = 0x03;
     pci_conf[0x4f] = 0x00;
@@ -569,7 +569,8 @@ static void piix3_class_init(ObjectClass *klass, void *data)
     k->init         = piix3_initfn;
     k->config_write = piix3_write_config;
     k->vendor_id    = PCI_VENDOR_ID_INTEL;
-    k->device_id    = PCI_DEVICE_ID_INTEL_82371SB_0; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
+    /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */
+    k->device_id    = PCI_DEVICE_ID_INTEL_82371SB_0;
     k->class_id     = PCI_CLASS_BRIDGE_ISA;
 }
 
@@ -592,7 +593,8 @@ static void piix3_xen_class_init(ObjectClass *klass, void *data)
     k->init         = piix3_initfn;
     k->config_write = piix3_write_config_xen;
     k->vendor_id    = PCI_VENDOR_ID_INTEL;
-    k->device_id    = PCI_DEVICE_ID_INTEL_82371SB_0; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
+    /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */
+    k->device_id    = PCI_DEVICE_ID_INTEL_82371SB_0;
     k->class_id     = PCI_CLASS_BRIDGE_ISA;
 };
 
commit d93a8a435cbd7f874ef71d4da5677c5f88d8435a
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Sat Feb 23 00:40:38 2013 +0000

    piix_pci: Use DEVICE() and ISA_BUS()
    
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Tested-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Laszlo Ersek <lersek at redhat.com>
    Message-id: 1361580039-4459-3-git-send-email-dwmw2 at infradead.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index c29eee0..1e05d49 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -300,8 +300,7 @@ static PCIBus *i440fx_common_init(const char *device_name,
         pci_bus_set_route_irq_fn(b, piix3_route_intx_pin_to_irq);
     }
     piix3->pic = pic;
-    *isa_bus = DO_UPCAST(ISABus, qbus,
-                         qdev_get_child_bus(&piix3->dev.qdev, "isa.0"));
+    *isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0"));
 
     *piix3_devfn = piix3->dev.devfn;
 
@@ -548,7 +547,7 @@ static int piix3_initfn(PCIDevice *dev)
 {
     PIIX3State *d = DO_UPCAST(PIIX3State, dev, dev);
 
-    isa_bus_new(&d->dev.qdev, pci_address_space_io(dev));
+    isa_bus_new(DEVICE(d), pci_address_space_io(dev));
 
     memory_region_init_io(&d->rcr_mem, &rcr_ops, d, "piix3-reset-control", 1);
     memory_region_add_subregion_overlap(pci_address_space_io(dev), RCR_IOPORT,
commit 57a0f0c651a63d3e1e02d74e5c59d2648037b087
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Sat Feb 23 00:40:37 2013 +0000

    piix_pci: Clean up i440FX object handling
    
    Define and use I440FX_PCI_DEVICE() instead of using DO_UPCAST().
    
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Tested-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Laszlo Ersek <lersek at redhat.com>
    Message-id: 1361580039-4459-2-git-send-email-dwmw2 at infradead.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index ce39779..c29eee0 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -82,6 +82,10 @@ typedef struct PIIX3State {
     MemoryRegion rcr_mem;
 } PIIX3State;
 
+#define TYPE_I440FX_PCI_DEVICE "i440FX"
+#define I440FX_PCI_DEVICE(obj) \
+    OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE)
+
 struct PCII440FXState {
     PCIDevice dev;
     MemoryRegion *system_memory;
@@ -141,7 +145,7 @@ static void i440fx_set_smm(int val, void *arg)
 static void i440fx_write_config(PCIDevice *dev,
                                 uint32_t address, uint32_t val, int len)
 {
-    PCII440FXState *d = DO_UPCAST(PCII440FXState, dev, dev);
+    PCII440FXState *d = I440FX_PCI_DEVICE(dev);
 
     /* XXX: implement SMRAM.D_LOCK */
     pci_default_write_config(dev, address, val, len);
@@ -212,7 +216,7 @@ static int i440fx_pcihost_initfn(SysBusDevice *dev)
 
 static int i440fx_initfn(PCIDevice *dev)
 {
-    PCII440FXState *d = DO_UPCAST(PCII440FXState, dev, dev);
+    PCII440FXState *d = I440FX_PCI_DEVICE(dev);
 
     d->dev.config[I440FX_SMRAM] = 0x02;
 
@@ -251,7 +255,7 @@ static PCIBus *i440fx_common_init(const char *device_name,
     qdev_init_nofail(dev);
 
     d = pci_create_simple(b, 0, device_name);
-    *pi440fx_state = DO_UPCAST(PCII440FXState, dev, d);
+    *pi440fx_state = I440FX_PCI_DEVICE(d);
     f = *pi440fx_state;
     f->system_memory = address_space_mem;
     f->pci_address_space = pci_address_space;
@@ -325,7 +329,8 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
 {
     PCIBus *b;
 
-    b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, isa_bus, pic,
+    b = i440fx_common_init(TYPE_I440FX_PCI_DEVICE, pi440fx_state,
+                           piix3_devfn, isa_bus, pic,
                            address_space_mem, address_space_io, ram_size,
                            pci_hole_start, pci_hole_size,
                            pci_hole64_start, pci_hole64_size,
@@ -617,7 +622,7 @@ static void i440fx_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo i440fx_info = {
-    .name          = "i440FX",
+    .name          = TYPE_I440FX_PCI_DEVICE,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCII440FXState),
     .class_init    = i440fx_class_init,
commit 226ecabfbd410c7b2041385ea4b6f083a09ce8a2
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 22 17:57:48 2013 +0100

    qemu-bridge-helper: force usage of a very high MAC address for the bridge
    
    Linux uses the lowest enslaved MAC address as the MAC address of
    the bridge.  Set MAC address to a high value so that it does not
    affect the MAC address of the bridge.
    
    Changing the MAC address of the bridge could cause a few seconds
    of network downtime.
    
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1363971468-21154-1-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-bridge-helper.c b/qemu-bridge-helper.c
index 287bfd5..6a0974e 100644
--- a/qemu-bridge-helper.c
+++ b/qemu-bridge-helper.c
@@ -367,6 +367,24 @@ int main(int argc, char **argv)
         goto cleanup;
     }
 
+    /* Linux uses the lowest enslaved MAC address as the MAC address of
+     * the bridge.  Set MAC address to a high value so that it doesn't
+     * affect the MAC address of the bridge.
+     */
+    if (ioctl(ctlfd, SIOCGIFHWADDR, &ifr) < 0) {
+        fprintf(stderr, "failed to get MAC address of device `%s': %s\n",
+                iface, strerror(errno));
+        ret = EXIT_FAILURE;
+        goto cleanup;
+    }
+    ifr.ifr_hwaddr.sa_data[0] = 0xFE;
+    if (ioctl(ctlfd, SIOCSIFHWADDR, &ifr) < 0) {
+        fprintf(stderr, "failed to set MAC address of device `%s': %s\n",
+                iface, strerror(errno));
+        ret = EXIT_FAILURE;
+        goto cleanup;
+    }
+
     /* add the interface to the bridge */
     prep_ifreq(&ifr, bridge);
     ifindex = if_nametoindex(iface);
commit 2900af5969c8d54d48872cd707a4a0e71e6fa57e
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Mar 27 10:49:15 2013 +0100

    virtio-balloon: cleanup: remove qdev field.
    
    The qdev field is no longer needed, just drop it.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1364377755-15508-7-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index 38d2ee3..b382bd4 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -360,7 +360,6 @@ static int virtio_balloon_device_init(VirtIODevice *vdev)
     s->dvq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output);
     s->svq = virtio_add_queue(vdev, 128, virtio_balloon_receive_stats);
 
-    s->qdev = qdev;
     register_savevm(qdev, "virtio-balloon", -1, 1,
                     virtio_balloon_save, virtio_balloon_load, s);
 
diff --git a/hw/virtio-balloon.h b/hw/virtio-balloon.h
index 5f8fe02..d898315 100644
--- a/hw/virtio-balloon.h
+++ b/hw/virtio-balloon.h
@@ -67,7 +67,6 @@ typedef struct VirtIOBalloon {
     QEMUTimer *stats_timer;
     int64_t stats_last_update;
     int64_t stats_poll_interval;
-    DeviceState *qdev;
 } VirtIOBalloon;
 
 #endif
commit c96caced3ffd9e5a078f3f5b5d373a40faf7dc3a
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Mar 27 10:49:14 2013 +0100

    virtio-balloon: cleanup: QOM casts.
    
    As the virtio-balloon-pci is switched to the new API, we can use QOM
    casts.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1364377755-15508-6-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index 87278f5..38d2ee3 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -31,14 +31,6 @@
 
 #include "hw/virtio-bus.h"
 
-/*
- * Will be modified later in the serie.
- */
-static VirtIOBalloon *to_virtio_balloon(VirtIODevice *vdev)
-{
-    return (VirtIOBalloon *)vdev;
-}
-
 static void balloon_page(void *addr, int deflate)
 {
 #if defined(__linux__)
@@ -74,7 +66,8 @@ static inline void reset_stats(VirtIOBalloon *dev)
 
 static bool balloon_stats_supported(const VirtIOBalloon *s)
 {
-    return s->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ);
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
+    return vdev->guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ);
 }
 
 static bool balloon_stats_enabled(const VirtIOBalloon *s)
@@ -100,6 +93,7 @@ static void balloon_stats_change_timer(VirtIOBalloon *s, int secs)
 static void balloon_stats_poll_cb(void *opaque)
 {
     VirtIOBalloon *s = opaque;
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
 
     if (!balloon_stats_supported(s)) {
         /* re-schedule */
@@ -108,7 +102,7 @@ static void balloon_stats_poll_cb(void *opaque)
     }
 
     virtqueue_push(s->svq, &s->stats_vq_elem, s->stats_vq_offset);
-    virtio_notify(&s->vdev, s->svq);
+    virtio_notify(vdev, s->svq);
 }
 
 static void balloon_stats_get_all(Object *obj, struct Visitor *v,
@@ -186,7 +180,7 @@ static void balloon_stats_set_poll_interval(Object *obj, struct Visitor *v,
 
 static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
 {
-    VirtIOBalloon *s = to_virtio_balloon(vdev);
+    VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
     VirtQueueElement elem;
     MemoryRegionSection section;
 
@@ -220,7 +214,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
 
 static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
 {
-    VirtIOBalloon *s = DO_UPCAST(VirtIOBalloon, vdev, vdev);
+    VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
     VirtQueueElement *elem = &s->stats_vq_elem;
     VirtIOBalloonStat stat;
     size_t offset = 0;
@@ -262,7 +256,7 @@ out:
 
 static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
 {
-    VirtIOBalloon *dev = to_virtio_balloon(vdev);
+    VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
     struct virtio_balloon_config config;
 
     config.num_pages = cpu_to_le32(dev->num_pages);
@@ -274,7 +268,7 @@ static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
 static void virtio_balloon_set_config(VirtIODevice *vdev,
                                       const uint8_t *config_data)
 {
-    VirtIOBalloon *dev = to_virtio_balloon(vdev);
+    VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
     struct virtio_balloon_config config;
     uint32_t oldactual = dev->actual;
     memcpy(&config, config_data, 8);
@@ -300,22 +294,24 @@ static void virtio_balloon_stat(void *opaque, BalloonInfo *info)
 
 static void virtio_balloon_to_target(void *opaque, ram_addr_t target)
 {
-    VirtIOBalloon *dev = opaque;
+    VirtIOBalloon *dev = VIRTIO_BALLOON(opaque);
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
 
     if (target > ram_size) {
         target = ram_size;
     }
     if (target) {
         dev->num_pages = (ram_size - target) >> VIRTIO_BALLOON_PFN_SHIFT;
-        virtio_notify_config(&dev->vdev);
+        virtio_notify_config(vdev);
     }
 }
 
 static void virtio_balloon_save(QEMUFile *f, void *opaque)
 {
-    VirtIOBalloon *s = opaque;
+    VirtIOBalloon *s = VIRTIO_BALLOON(opaque);
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
 
-    virtio_save(&s->vdev, f);
+    virtio_save(vdev, f);
 
     qemu_put_be32(f, s->num_pages);
     qemu_put_be32(f, s->actual);
@@ -323,13 +319,14 @@ static void virtio_balloon_save(QEMUFile *f, void *opaque)
 
 static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id)
 {
-    VirtIOBalloon *s = opaque;
+    VirtIOBalloon *s = VIRTIO_BALLOON(opaque);
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
     int ret;
 
     if (version_id != 1)
         return -EINVAL;
 
-    ret = virtio_load(&s->vdev, f);
+    ret = virtio_load(vdev, f);
     if (ret) {
         return ret;
     }
@@ -347,9 +344,9 @@ static int virtio_balloon_device_init(VirtIODevice *vdev)
 
     virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON, 8);
 
-    s->vdev.get_config = virtio_balloon_get_config;
-    s->vdev.set_config = virtio_balloon_set_config;
-    s->vdev.get_features = virtio_balloon_get_features;
+    vdev->get_config = virtio_balloon_get_config;
+    vdev->set_config = virtio_balloon_set_config;
+    vdev->get_features = virtio_balloon_get_features;
 
     ret = qemu_add_balloon_handler(virtio_balloon_to_target,
                                    virtio_balloon_stat, s);
diff --git a/hw/virtio-balloon.h b/hw/virtio-balloon.h
index 139eac3..5f8fe02 100644
--- a/hw/virtio-balloon.h
+++ b/hw/virtio-balloon.h
@@ -57,7 +57,7 @@ typedef struct VirtIOBalloonStat {
 } QEMU_PACKED VirtIOBalloonStat;
 
 typedef struct VirtIOBalloon {
-    VirtIODevice vdev;
+    VirtIODevice parent_obj;
     VirtQueue *ivq, *dvq, *svq;
     uint32_t num_pages;
     uint32_t actual;
commit 5c7d0962f60498c3f11d402e1c857cb9d5d8568d
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Mar 27 10:49:13 2013 +0100

    virtio-balloon: cleanup: init and exit function.
    
    This remove old init and exit function as they are no longer needed.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1364377755-15508-5-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index 7519971..87278f5 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -339,27 +339,13 @@ static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static VirtIODevice *virtio_balloon_common_init(DeviceState *dev,
-                                                VirtIOBalloon **ps)
+static int virtio_balloon_device_init(VirtIODevice *vdev)
 {
-    VirtIOBalloon *s = *ps;
+    DeviceState *qdev = DEVICE(vdev);
+    VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
     int ret;
 
-    /*
-     * We have two cases here: the old virtio-balloon-x device, and the
-     * refactored virtio-balloon.
-     * This will disappear later in the serie.
-     */
-    int old_device = (s == NULL);
-    if (s == NULL) {
-        /* old virtio-balloon-pci or virtio-balloon-s390, no memory allocated */
-        s = (VirtIOBalloon *)virtio_common_init("virtio-balloon",
-                                                VIRTIO_ID_BALLOON,
-                                                8, sizeof(VirtIOBalloon));
-    } else {
-        /* new API virtio-balloon. (memory allocated by qdev) */
-        virtio_init(VIRTIO_DEVICE(s), "virtio-balloon", VIRTIO_ID_BALLOON, 8);
-    }
+    virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON, 8);
 
     s->vdev.get_config = virtio_balloon_get_config;
     s->vdev.set_config = virtio_balloon_set_config;
@@ -367,60 +353,27 @@ static VirtIODevice *virtio_balloon_common_init(DeviceState *dev,
 
     ret = qemu_add_balloon_handler(virtio_balloon_to_target,
                                    virtio_balloon_stat, s);
-    if ((ret < 0) && (old_device)) {
-        virtio_cleanup(&s->vdev);
-        return NULL;
-    }
+
     if (ret < 0) {
         virtio_common_cleanup(VIRTIO_DEVICE(s));
-        return NULL;
+        return -1;
     }
 
-    s->ivq = virtio_add_queue(&s->vdev, 128, virtio_balloon_handle_output);
-    s->dvq = virtio_add_queue(&s->vdev, 128, virtio_balloon_handle_output);
-    s->svq = virtio_add_queue(&s->vdev, 128, virtio_balloon_receive_stats);
+    s->ivq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output);
+    s->dvq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output);
+    s->svq = virtio_add_queue(vdev, 128, virtio_balloon_receive_stats);
 
-    s->qdev = dev;
-    register_savevm(dev, "virtio-balloon", -1, 1,
+    s->qdev = qdev;
+    register_savevm(qdev, "virtio-balloon", -1, 1,
                     virtio_balloon_save, virtio_balloon_load, s);
 
-    object_property_add(OBJECT(dev), "guest-stats", "guest statistics",
+    object_property_add(OBJECT(qdev), "guest-stats", "guest statistics",
                         balloon_stats_get_all, NULL, NULL, s, NULL);
 
-    object_property_add(OBJECT(dev), "guest-stats-polling-interval", "int",
+    object_property_add(OBJECT(qdev), "guest-stats-polling-interval", "int",
                         balloon_stats_get_poll_interval,
                         balloon_stats_set_poll_interval,
                         NULL, s, NULL);
-
-    return &s->vdev;
-}
-
-/*
- * This two functions will be removed later in the serie.
- */
-VirtIODevice *virtio_balloon_init(DeviceState *dev)
-{
-    VirtIOBalloon *s = NULL;
-    return virtio_balloon_common_init(dev, &s);
-}
-
-void virtio_balloon_exit(VirtIODevice *vdev)
-{
-    VirtIOBalloon *s = DO_UPCAST(VirtIOBalloon, vdev, vdev);
-
-    balloon_stats_destroy_timer(s);
-    qemu_remove_balloon_handler(s);
-    unregister_savevm(s->qdev, "virtio-balloon", s);
-    virtio_cleanup(vdev);
-}
-
-static int virtio_balloon_device_init(VirtIODevice *vdev)
-{
-    DeviceState *qdev = DEVICE(vdev);
-    VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
-    if (virtio_balloon_common_init(qdev, &s) == NULL) {
-        return -1;
-    }
     return 0;
 }
 
commit 30bff6a0f1d12742475a980708cfa82be56a881f
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Mar 27 10:49:12 2013 +0100

    virtio-balloon-ccw: switch to the new API.
    
    Here the virtio-balloon-ccw is modified for the new API. The device
    virtio-balloon-ccw extends virtio-ccw-device as before. It creates and
    connects a virtio-balloon during the init. The properties are not modified.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1364377755-15508-4-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 7e79c57..5dce791 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -608,22 +608,24 @@ static int virtio_ccw_serial_exit(VirtioCcwDevice *dev)
     return virtio_ccw_exit(dev);
 }
 
-static int virtio_ccw_balloon_init(VirtioCcwDevice *dev)
+static int virtio_ccw_balloon_init(VirtioCcwDevice *ccw_dev)
 {
-    VirtIODevice *vdev;
+    VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(ccw_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
 
-    vdev = virtio_balloon_init((DeviceState *)dev);
-    if (!vdev) {
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    if (qdev_init(vdev) < 0) {
         return -1;
     }
 
-    return virtio_ccw_device_init(dev, vdev);
+    return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
 }
 
-static int virtio_ccw_balloon_exit(VirtioCcwDevice *dev)
+static void virtio_ccw_balloon_instance_init(Object *obj)
 {
-    virtio_balloon_exit(dev->vdev);
-    return virtio_ccw_exit(dev);
+    VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_BALLOON);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 }
 
 static int virtio_ccw_scsi_init(VirtioCcwDevice *ccw_dev)
@@ -820,15 +822,16 @@ static void virtio_ccw_balloon_class_init(ObjectClass *klass, void *data)
     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
 
     k->init = virtio_ccw_balloon_init;
-    k->exit = virtio_ccw_balloon_exit;
+    k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
     dc->props = virtio_ccw_balloon_properties;
 }
 
 static const TypeInfo virtio_ccw_balloon = {
-    .name          = "virtio-balloon-ccw",
+    .name          = TYPE_VIRTIO_BALLOON_CCW,
     .parent        = TYPE_VIRTIO_CCW_DEVICE,
-    .instance_size = sizeof(VirtioCcwDevice),
+    .instance_size = sizeof(VirtIOBalloonCcw),
+    .instance_init = virtio_ccw_balloon_instance_init,
     .class_init    = virtio_ccw_balloon_class_init,
 };
 
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index d9f7399..d580510 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -16,6 +16,7 @@
 #include <hw/virtio-net.h>
 #include <hw/virtio-serial.h>
 #include <hw/virtio-scsi.h>
+#include "hw/virtio-balloon.h"
 #include <hw/virtio-rng.h>
 #include <hw/virtio-bus.h>
 
@@ -115,6 +116,16 @@ typedef struct VirtIOBlkCcw {
     VirtIOBlkConf blk;
 } VirtIOBlkCcw;
 
+/* virtio-balloon-ccw */
+
+#define TYPE_VIRTIO_BALLOON_CCW "virtio-balloon-ccw"
+#define VIRTIO_BALLOON_CCW(obj) \
+        OBJECT_CHECK(VirtIOBalloonCcw, (obj), TYPE_VIRTIO_BALLOON_CCW)
+
+typedef struct VirtIOBalloonCcw {
+    VirtioCcwDevice parent_obj;
+    VirtIOBalloon vdev;
+} VirtIOBalloonCcw;
 
 VirtualCssBus *virtual_css_bus_init(void);
 void virtio_ccw_device_update_status(SubchDev *sch);
commit e378e88dfc2dec2a60a856dd478a4edfbc88efd0
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Mar 27 10:49:11 2013 +0100

    virtio-balloon-pci: switch to the new API.
    
    Here the virtio-balloon-pci is modified for the new API. The device
    virtio-balloon-pci extends virtio-pci. It creates and connects a
    virtio-balloon during the init. The properties are not changed.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1364377755-15508-3-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 736a9bf..fb20722 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -22,6 +22,7 @@
 #include "hw/virtio-net.h"
 #include "hw/virtio-serial.h"
 #include "hw/virtio-scsi.h"
+#include "hw/virtio-balloon.h"
 #include "hw/pci/pci.h"
 #include "qemu/error-report.h"
 #include "hw/pci/msi.h"
@@ -1000,33 +1001,6 @@ static void virtio_net_exit_pci(PCIDevice *pci_dev)
     virtio_exit_pci(pci_dev);
 }
 
-static int virtio_balloon_init_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-    VirtIODevice *vdev;
-
-    if (proxy->class_code != PCI_CLASS_OTHERS &&
-        proxy->class_code != PCI_CLASS_MEMORY_RAM) { /* qemu < 1.1 */
-        proxy->class_code = PCI_CLASS_OTHERS;
-    }
-
-    vdev = virtio_balloon_init(&pci_dev->qdev);
-    if (!vdev) {
-        return -1;
-    }
-    virtio_init_pci(proxy, vdev);
-    return 0;
-}
-
-static void virtio_balloon_exit_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-
-    virtio_pci_stop_ioeventfd(proxy);
-    virtio_balloon_exit(proxy->vdev);
-    virtio_exit_pci(pci_dev);
-}
-
 static int virtio_rng_init_pci(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
@@ -1127,34 +1101,6 @@ static const TypeInfo virtio_serial_info = {
     .class_init    = virtio_serial_class_init,
 };
 
-static Property virtio_balloon_properties[] = {
-    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
-    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void virtio_balloon_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = virtio_balloon_init_pci;
-    k->exit = virtio_balloon_exit_pci;
-    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
-    k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON;
-    k->revision = VIRTIO_PCI_ABI_VERSION;
-    k->class_id = PCI_CLASS_OTHERS;
-    dc->reset = virtio_pci_reset;
-    dc->props = virtio_balloon_properties;
-}
-
-static const TypeInfo virtio_balloon_info = {
-    .name          = "virtio-balloon-pci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(VirtIOPCIProxy),
-    .class_init    = virtio_balloon_class_init,
-};
-
 static void virtio_rng_initfn(Object *obj)
 {
     PCIDevice *pci_dev = PCI_DEVICE(obj);
@@ -1461,6 +1407,59 @@ static const TypeInfo virtio_scsi_pci_info = {
     .class_init    = virtio_scsi_pci_class_init,
 };
 
+/* virtio-balloon-pci */
+
+static Property virtio_balloon_pci_properties[] = {
+    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static int virtio_balloon_pci_init(VirtIOPCIProxy *vpci_dev)
+{
+    VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(vpci_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
+
+    if (vpci_dev->class_code != PCI_CLASS_OTHERS &&
+        vpci_dev->class_code != PCI_CLASS_MEMORY_RAM) { /* qemu < 1.1 */
+        vpci_dev->class_code = PCI_CLASS_OTHERS;
+    }
+
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    if (qdev_init(vdev) < 0) {
+        return -1;
+    }
+    return 0;
+}
+
+static void virtio_balloon_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
+    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+    k->init = virtio_balloon_pci_init;
+    dc->props = virtio_balloon_pci_properties;
+    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON;
+    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
+    pcidev_k->class_id = PCI_CLASS_OTHERS;
+}
+
+static void virtio_balloon_pci_instance_init(Object *obj)
+{
+    VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_BALLOON);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+}
+
+static const TypeInfo virtio_balloon_pci_info = {
+    .name          = TYPE_VIRTIO_BALLOON_PCI,
+    .parent        = TYPE_VIRTIO_PCI,
+    .instance_size = sizeof(VirtIOBalloonPCI),
+    .instance_init = virtio_balloon_pci_instance_init,
+    .class_init    = virtio_balloon_pci_class_init,
+};
+
 /* virtio-pci-bus */
 
 void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev)
@@ -1501,7 +1500,6 @@ static void virtio_pci_register_types(void)
 {
     type_register_static(&virtio_net_info);
     type_register_static(&virtio_serial_info);
-    type_register_static(&virtio_balloon_info);
     type_register_static(&virtio_rng_info);
     type_register_static(&virtio_pci_bus_info);
     type_register_static(&virtio_pci_info);
@@ -1510,6 +1508,7 @@ static void virtio_pci_register_types(void)
 #endif
     type_register_static(&virtio_blk_pci_info);
     type_register_static(&virtio_scsi_pci_info);
+    type_register_static(&virtio_balloon_pci_info);
 }
 
 type_init(virtio_pci_register_types)
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index bfe7a8e..f99f2eb 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -21,12 +21,14 @@
 #include "hw/virtio-rng.h"
 #include "hw/virtio-serial.h"
 #include "hw/virtio-scsi.h"
+#include "hw/virtio-balloon.h"
 #include "hw/virtio-bus.h"
 #include "hw/9pfs/virtio-9p-device.h"
 
 typedef struct VirtIOPCIProxy VirtIOPCIProxy;
 typedef struct VirtIOBlkPCI VirtIOBlkPCI;
 typedef struct VirtIOSCSIPCI VirtIOSCSIPCI;
+typedef struct VirtIOBalloonPCI VirtIOBalloonPCI;
 
 /* virtio-pci-bus */
 
@@ -116,6 +118,18 @@ struct VirtIOBlkPCI {
     VirtIOBlkConf blk;
 };
 
+/*
+ * virtio-balloon-pci: This extends VirtioPCIProxy.
+ */
+#define TYPE_VIRTIO_BALLOON_PCI "virtio-balloon-pci"
+#define VIRTIO_BALLOON_PCI(obj) \
+        OBJECT_CHECK(VirtIOBalloonPCI, (obj), TYPE_VIRTIO_BALLOON_PCI)
+
+struct VirtIOBalloonPCI {
+    VirtIOPCIProxy parent_obj;
+    VirtIOBalloon vdev;
+};
+
 void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
 void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev);
 
commit 1ab461b534b34838d1b21c056ab37413f54fefa6
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Mar 27 10:49:10 2013 +0100

    virtio-balloon: add the virtio-balloon device.
    
    Create virtio-balloon which extends virtio-device, so it can be connected on
    virtio-bus.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1364377755-15508-2-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index 54a4372..7519971 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -29,6 +29,11 @@
 #include <sys/mman.h>
 #endif
 
+#include "hw/virtio-bus.h"
+
+/*
+ * Will be modified later in the serie.
+ */
 static VirtIOBalloon *to_virtio_balloon(VirtIODevice *vdev)
 {
     return (VirtIOBalloon *)vdev;
@@ -334,14 +339,27 @@ static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-VirtIODevice *virtio_balloon_init(DeviceState *dev)
+static VirtIODevice *virtio_balloon_common_init(DeviceState *dev,
+                                                VirtIOBalloon **ps)
 {
-    VirtIOBalloon *s;
+    VirtIOBalloon *s = *ps;
     int ret;
 
-    s = (VirtIOBalloon *)virtio_common_init("virtio-balloon",
-                                            VIRTIO_ID_BALLOON,
-                                            8, sizeof(VirtIOBalloon));
+    /*
+     * We have two cases here: the old virtio-balloon-x device, and the
+     * refactored virtio-balloon.
+     * This will disappear later in the serie.
+     */
+    int old_device = (s == NULL);
+    if (s == NULL) {
+        /* old virtio-balloon-pci or virtio-balloon-s390, no memory allocated */
+        s = (VirtIOBalloon *)virtio_common_init("virtio-balloon",
+                                                VIRTIO_ID_BALLOON,
+                                                8, sizeof(VirtIOBalloon));
+    } else {
+        /* new API virtio-balloon. (memory allocated by qdev) */
+        virtio_init(VIRTIO_DEVICE(s), "virtio-balloon", VIRTIO_ID_BALLOON, 8);
+    }
 
     s->vdev.get_config = virtio_balloon_get_config;
     s->vdev.set_config = virtio_balloon_set_config;
@@ -349,10 +367,14 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev)
 
     ret = qemu_add_balloon_handler(virtio_balloon_to_target,
                                    virtio_balloon_stat, s);
-    if (ret < 0) {
+    if ((ret < 0) && (old_device)) {
         virtio_cleanup(&s->vdev);
         return NULL;
     }
+    if (ret < 0) {
+        virtio_common_cleanup(VIRTIO_DEVICE(s));
+        return NULL;
+    }
 
     s->ivq = virtio_add_queue(&s->vdev, 128, virtio_balloon_handle_output);
     s->dvq = virtio_add_queue(&s->vdev, 128, virtio_balloon_handle_output);
@@ -373,6 +395,15 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev)
     return &s->vdev;
 }
 
+/*
+ * This two functions will be removed later in the serie.
+ */
+VirtIODevice *virtio_balloon_init(DeviceState *dev)
+{
+    VirtIOBalloon *s = NULL;
+    return virtio_balloon_common_init(dev, &s);
+}
+
 void virtio_balloon_exit(VirtIODevice *vdev)
 {
     VirtIOBalloon *s = DO_UPCAST(VirtIOBalloon, vdev, vdev);
@@ -382,3 +413,55 @@ void virtio_balloon_exit(VirtIODevice *vdev)
     unregister_savevm(s->qdev, "virtio-balloon", s);
     virtio_cleanup(vdev);
 }
+
+static int virtio_balloon_device_init(VirtIODevice *vdev)
+{
+    DeviceState *qdev = DEVICE(vdev);
+    VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
+    if (virtio_balloon_common_init(qdev, &s) == NULL) {
+        return -1;
+    }
+    return 0;
+}
+
+static int virtio_balloon_device_exit(DeviceState *qdev)
+{
+    VirtIOBalloon *s = VIRTIO_BALLOON(qdev);
+    VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+
+    balloon_stats_destroy_timer(s);
+    qemu_remove_balloon_handler(s);
+    unregister_savevm(qdev, "virtio-balloon", s);
+    virtio_common_cleanup(vdev);
+    return 0;
+}
+
+static Property virtio_balloon_properties[] = {
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_balloon_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+    dc->exit = virtio_balloon_device_exit;
+    dc->props = virtio_balloon_properties;
+    vdc->init = virtio_balloon_device_init;
+    vdc->get_config = virtio_balloon_get_config;
+    vdc->set_config = virtio_balloon_set_config;
+    vdc->get_features = virtio_balloon_get_features;
+}
+
+static const TypeInfo virtio_balloon_info = {
+    .name = TYPE_VIRTIO_BALLOON,
+    .parent = TYPE_VIRTIO_DEVICE,
+    .instance_size = sizeof(VirtIOBalloon),
+    .class_init = virtio_balloon_class_init,
+};
+
+static void virtio_register_types(void)
+{
+    type_register_static(&virtio_balloon_info);
+}
+
+type_init(virtio_register_types)
diff --git a/hw/virtio-balloon.h b/hw/virtio-balloon.h
index b007042..139eac3 100644
--- a/hw/virtio-balloon.h
+++ b/hw/virtio-balloon.h
@@ -18,6 +18,10 @@
 #include "hw/virtio.h"
 #include "hw/pci/pci.h"
 
+#define TYPE_VIRTIO_BALLOON "virtio-balloon"
+#define VIRTIO_BALLOON(obj) \
+        OBJECT_CHECK(VirtIOBalloon, (obj), TYPE_VIRTIO_BALLOON)
+
 /* from Linux's linux/virtio_balloon.h */
 
 /* The ID for virtio_balloon */
commit fde245ca7ea790495db370cd260259595dbdf874
Merge: 837df37 5d186eb
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Mar 28 12:57:37 2013 -0500

    Merge remote-tracking branch 'stefanha/block' into staging
    
    # By Kevin Wolf (22) and Peter Lieven (1)
    # Via Stefan Hajnoczi
    * stefanha/block: (23 commits)
      block: Fix direct use of protocols as driver for bdrv_open()
      qcow2: Gather clusters in a looping loop
      qcow2: Move cluster gathering to a non-looping loop
      qcow2: Allow requests with multiple l2metas
      qcow2: Use byte granularity in qcow2_alloc_cluster_offset()
      qcow2: Prepare handle_alloc/copied() for byte granularity
      qcow2: handle_copied(): Implement non-zero host_offset
      qcow2: handle_copied(): Get rid of keep_clusters parameter
      qcow2: handle_copied(): Get rid of nb_clusters parameter
      qcow2: Factor out handle_copied()
      qcow2: Clean up handle_alloc()
      qcow2: Finalise interface of handle_alloc()
      qcow2: handle_alloc(): Get rid of keep_clusters parameter
      qcow2: handle_alloc(): Get rid of nb_clusters parameter
      qcow2: Factor out handle_alloc()
      qcow2: Decouple cluster allocation from cluster reuse code
      qcow2: Change handle_dependency to byte granularity
      qcow2: Improve check for overlapping allocations
      qcow2: Handle dependencies earlier
      qcow2: Remove bogus unlock of s->lock
      ...

commit 837df37e881e14ffdb05c2b912b2ad30b851c9d3
Merge: e280ff5 7e86600
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Mar 28 12:57:32 2013 -0500

    Merge remote-tracking branch 'stefanha/tracing' into staging
    
    # By Lluís Vilanova (7) and others
    # Via Stefan Hajnoczi
    * stefanha/tracing:
      vl: add runstate_set tracepoint
      .gitignore: rename trace/generated-tracers.dtrace
      .gitignore: add trace/generated-events.[ch]
      trace: rebuild generated-events.o when configuration changes
      trace: [stderr] Port to generic event information and new control interface
      trace: [simple] Port to generic event information and new control interface
      trace: [default] Port to generic event information and new control interface
      trace: [monitor] Use new event control interface
      trace: Provide a detailed event control interface
      trace: Provide a generic tracing event descriptor
      trace: [tracetool] Explicitly identify public backends

commit 7e8660032cd21c1bdc4160b8fab7deec62e1aa12
Author: Kazuya Saito <saito.kazuya at jp.fujitsu.com>
Date:   Fri Mar 22 17:26:59 2013 +0900

    vl: add runstate_set tracepoint
    
    This patch enables us to know RunState transition. It will be userful
    for investigation when the trouble occured in special event such like
    live migration, shutdown, suspend, and so on.
    
    Signed-off-by: Kazuya Saito <saito.kazuya at jp.fujitsu.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/trace-events b/trace-events
index 406fe5f..85dd49c 100644
--- a/trace-events
+++ b/trace-events
@@ -474,6 +474,7 @@ scsi_request_sense(int target, int lun, int tag) "target %d lun %d tag %d"
 # vl.c
 vm_state_notify(int running, int reason) "running %d reason %d"
 load_file(const char *name, const char *path) "name %s location %s"
+runstate_set(int new_state) "new state %d"
 
 # block/qcow2.c
 qcow2_writev_start_req(void *co, int64_t sector, int nb_sectors) "co %p sector %" PRIx64 " nb_sectors %d"
diff --git a/vl.c b/vl.c
index 7643f16..770cb7f 100644
--- a/vl.c
+++ b/vl.c
@@ -642,7 +642,7 @@ void runstate_set(RunState new_state)
                 RunState_lookup[new_state]);
         abort();
     }
-
+    trace_runstate_set(new_state);
     current_run_state = new_state;
 }
 
commit a46b24fd5dfd6814bafa65e51d8da86ce8eef7f5
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Mar 8 16:10:12 2013 +0100

    .gitignore: rename trace/generated-tracers.dtrace
    
    For a while the file was called trace/generated-tracers-dtrace.dtrace
    but today it's called trace/generated-tracers.dtrace.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/.gitignore b/.gitignore
index c0238aa..487813a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,7 +6,7 @@ config-target.*
 trace/generated-tracers.h
 trace/generated-tracers.c
 trace/generated-tracers-dtrace.h
-trace/generated-tracers-dtrace.dtrace
+trace/generated-tracers.dtrace
 trace/generated-events.h
 trace/generated-events.c
 libcacard/trace/generated-tracers.c
commit 878e63e6c568d4eb147d1adde297325f3aa28c51
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Mar 8 16:10:11 2013 +0100

    .gitignore: add trace/generated-events.[ch]
    
    Don't display autogenerated files in git-status(1).
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/.gitignore b/.gitignore
index 9c234a3..c0238aa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,8 @@ trace/generated-tracers.h
 trace/generated-tracers.c
 trace/generated-tracers-dtrace.h
 trace/generated-tracers-dtrace.dtrace
+trace/generated-events.h
+trace/generated-events.c
 libcacard/trace/generated-tracers.c
 *-timestamp
 *-softmmu
commit a7373b1f61d106ef5c9710eb56e942f513dc512d
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Mar 8 15:52:15 2013 +0100

    trace: rebuild generated-events.o when configuration changes
    
    Make sure to rebuild generated-events.o when ./configure options change.
    This prevents linker errors when a stale generated-events.o gets linked
    with code compiled against fresh headers.  For example, try building
    with ./configure --enable-trace-backend=stderr followed by ./configure
    --enable-trace-backend=dtrace.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/trace/Makefile.objs b/trace/Makefile.objs
index 156aa25..a043072 100644
--- a/trace/Makefile.objs
+++ b/trace/Makefile.objs
@@ -11,7 +11,7 @@ $(obj)/generated-events.h-timestamp: $(SRC_PATH)/trace-events
 		< $< > $@,"  GEN   $(patsubst %-timestamp,%,$@)")
 	@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
 
-$(obj)/generated-events.c: $(obj)/generated-events.c-timestamp
+$(obj)/generated-events.c: $(obj)/generated-events.c-timestamp $(BUILD_DIR)/config-host.mak
 $(obj)/generated-events.c-timestamp: $(SRC_PATH)/trace-events
 	$(call quiet-command,$(TRACETOOL) \
 		--format=events-c \
commit c6f18b9195b4251f32b6ac8e149b449354c1c93b
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Tue Mar 5 14:48:00 2013 +0100

    trace: [stderr] Port to generic event information and new control interface
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/scripts/tracetool/backend/stderr.py b/scripts/tracetool/backend/stderr.py
index a10fbb8..6f93dbd 100644
--- a/scripts/tracetool/backend/stderr.py
+++ b/scripts/tracetool/backend/stderr.py
@@ -20,40 +20,29 @@ PUBLIC = True
 
 
 def c(events):
-    out('#include "trace.h"',
-        '',
-        'TraceEvent trace_list[] = {')
-
-    for e in events:
-        out('{.tp_name = "%(name)s", .state=0},',
-            name = e.name,
-            )
-
-    out('};')
+    pass
 
 def h(events):
     out('#include <stdio.h>',
-        '#include "trace/stderr.h"',
+        '#include "trace/control.h"',
         '',
-        'extern TraceEvent trace_list[];')
+        )
 
-    for num, e in enumerate(events):
+    for e in events:
         argnames = ", ".join(e.args.names())
         if len(e.args) > 0:
             argnames = ", " + argnames
 
         out('static inline void trace_%(name)s(%(args)s)',
             '{',
-            '    if (trace_list[%(event_num)s].state != 0) {',
+            '    bool _state = trace_event_get_state(%(event_id)s);',
+            '    if (_state) {',
             '        fprintf(stderr, "%(name)s " %(fmt)s "\\n" %(argnames)s);',
             '    }',
             '}',
             name = e.name,
             args = e.args,
-            event_num = num,
-            fmt = e.fmt,
+            event_id = "TRACE_" + e.name.upper(),
+            fmt = e.fmt.rstrip("\n"),
             argnames = argnames,
             )
-
-    out('',
-        '#define NR_TRACE_EVENTS %d' % len(events))
diff --git a/trace/stderr.c b/trace/stderr.c
index 0810d6f..e212efd 100644
--- a/trace/stderr.c
+++ b/trace/stderr.c
@@ -4,40 +4,18 @@
 
 void trace_print_events(FILE *stream, fprintf_function stream_printf)
 {
-    unsigned int i;
+    TraceEventID i;
 
-    for (i = 0; i < NR_TRACE_EVENTS; i++) {
+    for (i = 0; i < trace_event_count(); i++) {
+        TraceEvent *ev = trace_event_id(i);
         stream_printf(stream, "%s [Event ID %u] : state %u\n",
-                      trace_list[i].tp_name, i, trace_list[i].state);
+                      trace_event_get_name(ev), i, trace_event_get_state_dynamic(ev));
     }
 }
 
-bool trace_event_set_state(const char *name, bool state)
+void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state)
 {
-    unsigned int i;
-    unsigned int len;
-    bool wildcard = false;
-    bool matched = false;
-
-    len = strlen(name);
-    if (len > 0 && name[len - 1] == '*') {
-        wildcard = true;
-        len -= 1;
-    }
-    for (i = 0; i < NR_TRACE_EVENTS; i++) {
-        if (wildcard) {
-            if (!strncmp(trace_list[i].tp_name, name, len)) {
-                trace_list[i].state = state;
-                matched = true;
-            }
-            continue;
-        }
-        if (!strcmp(trace_list[i].tp_name, name)) {
-            trace_list[i].state = state;
-            return true;
-        }
-    }
-    return matched;
+    ev->dstate = state;
 }
 
 bool trace_backend_init(const char *events, const char *file)
diff --git a/trace/stderr.h b/trace/stderr.h
deleted file mode 100644
index d575b61..0000000
--- a/trace/stderr.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef TRACE_STDERR_H
-#define TRACE_STDERR_H
-
-typedef uint64_t TraceEventID;
-
-typedef struct {
-    const char *tp_name;
-    bool state;
-} TraceEvent;
-
-#endif /* ! TRACE_STDERR_H */
commit 60481e210d1f5f9e97d4d5db82b9afb8d3df7acf
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Tue Mar 5 14:47:55 2013 +0100

    trace: [simple] Port to generic event information and new control interface
    
    The backend is forced to dump event numbers using 64 bits, as TraceEventID is
    an enum.
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/scripts/tracetool/backend/simple.py b/scripts/tracetool/backend/simple.py
index ac864f3..37ef599 100644
--- a/scripts/tracetool/backend/simple.py
+++ b/scripts/tracetool/backend/simple.py
@@ -28,17 +28,10 @@ def is_string(arg):
 
 def c(events):
     out('#include "trace.h"',
+        '#include "trace/control.h"',
         '#include "trace/simple.h"',
         '',
-        'TraceEvent trace_list[] = {')
-
-    for e in events:
-        out('{.tp_name = "%(name)s", .state=0},',
-            name = e.name,
-            )
-
-    out('};',
-        '')
+        )
 
     for num, event in enumerate(events):
         out('void trace_%(name)s(%(args)s)',
@@ -63,7 +56,9 @@ def c(events):
 
 
         out('',
-            '    if (!trace_list[%(event_id)s].state) {',
+            '    TraceEvent *eventp = trace_event_id(%(event_id)s);',
+            '    bool _state = trace_event_get_state_dynamic(eventp);',
+            '    if (!_state) {',
             '        return;',
             '    }',
             '',
@@ -106,6 +101,3 @@ def h(events):
             name = event.name,
             args = event.args,
             )
-    out('')
-    out('#define NR_TRACE_EVENTS %d' % len(events))
-    out('extern TraceEvent trace_list[NR_TRACE_EVENTS];')
diff --git a/trace/simple.c b/trace/simple.c
index 375d98f..1e3f691 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -218,6 +218,7 @@ int trace_record_start(TraceBufferRecord *rec, TraceEventID event, size_t datasi
 {
     unsigned int idx, rec_off, old_idx, new_idx;
     uint32_t rec_len = sizeof(TraceRecord) + datasize;
+    uint64_t event_u64 = event;
     uint64_t timestamp_ns = get_clock();
 
     do {
@@ -235,7 +236,7 @@ int trace_record_start(TraceBufferRecord *rec, TraceEventID event, size_t datasi
     idx = old_idx % TRACE_BUF_LEN;
 
     rec_off = idx;
-    rec_off = write_to_buffer(rec_off, &event, sizeof(event));
+    rec_off = write_to_buffer(rec_off, &event_u64, sizeof(event_u64));
     rec_off = write_to_buffer(rec_off, &timestamp_ns, sizeof(timestamp_ns));
     rec_off = write_to_buffer(rec_off, &rec_len, sizeof(rec_len));
 
@@ -359,38 +360,16 @@ void trace_print_events(FILE *stream, fprintf_function stream_printf)
 {
     unsigned int i;
 
-    for (i = 0; i < NR_TRACE_EVENTS; i++) {
+    for (i = 0; i < trace_event_count(); i++) {
+        TraceEvent *ev = trace_event_id(i);
         stream_printf(stream, "%s [Event ID %u] : state %u\n",
-                      trace_list[i].tp_name, i, trace_list[i].state);
+                      trace_event_get_name(ev), i, trace_event_get_state_dynamic(ev));
     }
 }
 
-bool trace_event_set_state(const char *name, bool state)
+void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state)
 {
-    unsigned int i;
-    unsigned int len;
-    bool wildcard = false;
-    bool matched = false;
-
-    len = strlen(name);
-    if (len > 0 && name[len - 1] == '*') {
-        wildcard = true;
-        len -= 1;
-    }
-    for (i = 0; i < NR_TRACE_EVENTS; i++) {
-        if (wildcard) {
-            if (!strncmp(trace_list[i].tp_name, name, len)) {
-                trace_list[i].state = state;
-                matched = true;
-            }
-            continue;
-        }
-        if (!strcmp(trace_list[i].tp_name, name)) {
-            trace_list[i].state = state;
-            return true;
-        }
-    }
-    return matched;
+    ev->dstate = state;
 }
 
 /* Helper function to create a thread with signals blocked.  Use glib's
diff --git a/trace/simple.h b/trace/simple.h
index 2ab96a8..5260d9a 100644
--- a/trace/simple.h
+++ b/trace/simple.h
@@ -15,12 +15,8 @@
 #include <stdbool.h>
 #include <stdio.h>
 
-typedef uint64_t TraceEventID;
+#include "trace/generated-events.h"
 
-typedef struct {
-    const char *tp_name;
-    bool state;
-} TraceEvent;
 
 void st_print_trace_file_status(FILE *stream, fprintf_function stream_printf);
 void st_set_trace_file_enabled(bool enable);
commit fd068a953ccb54a00e7b1cf2d8961498c7d74bd4
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Tue Mar 5 14:47:49 2013 +0100

    trace: [default] Port to generic event information and new control interface
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/trace/default.c b/trace/default.c
index c9b27a2..6e07a47 100644
--- a/trace/default.c
+++ b/trace/default.c
@@ -1,7 +1,7 @@
 /*
  * Default implementation for backend initialization from commandline.
  *
- * Copyright (C) 2011 Lluís Vilanova <vilanova at ac.upc.edu>
+ * Copyright (C) 2011-2012 Lluís Vilanova <vilanova at ac.upc.edu>
  *
  * This work is licensed under the terms of the GNU GPL, version 2.  See
  * the COPYING file in the top-level directory.
@@ -18,11 +18,10 @@ void trace_print_events(FILE *stream, fprintf_function stream_printf)
                   "operation not supported with the current backend\n");
 }
 
-bool trace_event_set_state(const char *name, bool state)
+void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state)
 {
     fprintf(stderr, "warning: "
             "cannot set the state of a trace event with the current backend\n");
-    return false;
 }
 
 bool trace_backend_init(const char *events, const char *file)
commit ca285c3fca7c3d2b77b133e82f7a3592ccc7f5d3
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Tue Mar 5 14:47:43 2013 +0100

    trace: [monitor] Use new event control interface
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/monitor.c b/monitor.c
index 5dfae2a..4ec1db9 100644
--- a/monitor.c
+++ b/monitor.c
@@ -761,9 +761,18 @@ static void do_trace_event_set_state(Monitor *mon, const QDict *qdict)
 {
     const char *tp_name = qdict_get_str(qdict, "name");
     bool new_state = qdict_get_bool(qdict, "option");
-    int ret = trace_event_set_state(tp_name, new_state);
 
-    if (!ret) {
+    bool found = false;
+    TraceEvent *ev = NULL;
+    while ((ev = trace_event_pattern(tp_name, ev)) != NULL) {
+        found = true;
+        if (!trace_event_get_state_static(ev)) {
+            monitor_printf(mon, "event \"%s\" is not traceable\n", tp_name);
+        } else {
+            trace_event_set_state_dynamic(ev, new_state);
+        }
+    }
+    if (!trace_event_is_pattern(tp_name) && !found) {
         monitor_printf(mon, "unknown event name \"%s\"\n", tp_name);
     }
 }
commit b1bae816c4c0743e37ee9e797a503610c34e3073
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Tue Mar 5 14:47:38 2013 +0100

    trace: Provide a detailed event control interface
    
    This interface decouples event obtaining from interaction.
    
    Events can be obtained through three different methods:
    
    * identifier
    * name
    * simple wildcard pattern
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/docs/tracing.txt b/docs/tracing.txt
index 14db3bf..cf53c17 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -100,49 +100,37 @@ respectively.  This ensures portability between 32- and 64-bit platforms.
 
 == Generic interface and monitor commands ==
 
-You can programmatically query and control the dynamic state of trace events
-through a backend-agnostic interface:
+You can programmatically query and control the state of trace events through a
+backend-agnostic interface provided by the header "trace/control.h".
 
-* trace_print_events
+Note that some of the backends do not provide an implementation for some parts
+of this interface, in which case QEMU will just print a warning (please refer to
+header "trace/control.h" to see which routines are backend-dependent).
 
-* trace_event_set_state
-  Enables or disables trace events at runtime inside QEMU.
-  The function returns "true" if the state of the event has been successfully
-  changed, or "false" otherwise:
-
-    #include "trace/control.h"
-    
-    trace_event_set_state("virtio_irq", true); /* enable */
-    [...]
-    trace_event_set_state("virtio_irq", false); /* disable */
-
-Note that some of the backends do not provide an implementation for this
-interface, in which case QEMU will just print a warning.
-
-This functionality is also provided through monitor commands:
+The state of events can also be queried and modified through monitor commands:
 
 * info trace-events
   View available trace events and their state.  State 1 means enabled, state 0
   means disabled.
 
 * trace-event NAME on|off
-  Enable/disable a given trace event or a group of events having common prefix
-  through wildcard.
+  Enable/disable a given trace event or a group of events (using wildcards).
 
 The "-trace events=<file>" command line argument can be used to enable the
 events listed in <file> from the very beginning of the program. This file must
 contain one event name per line.
 
-A basic wildcard matching is supported in both the monitor command "trace
--event" and the events list file. That means you can enable/disable the events
-having a common prefix in a batch. For example, virtio-blk trace events could
-be enabled using:
-  trace-event virtio_blk_* on
-
 If a line in the "-trace events=<file>" file begins with a '-', the trace event
 will be disabled instead of enabled.  This is useful when a wildcard was used
 to enable an entire family of events but one noisy event needs to be disabled.
 
+Wildcard matching is supported in both the monitor command "trace-event" and the
+events list file. That means you can enable/disable the events having a common
+prefix in a batch. For example, virtio-blk trace events could be enabled using
+the following monitor command:
+
+    trace-event virtio_blk_* on
+
 == Trace backends ==
 
 The "tracetool" script automates tedious trace event code generation and also
@@ -263,3 +251,7 @@ guard such computations and avoid its compilation when the event is disabled:
         }
         return ptr;
     }
+
+You can check both if the event has been disabled and is dynamically enabled at
+the same time using the 'trace_event_get_state' routine (see header
+"trace/control.h" for more information).
diff --git a/trace/control-internal.h b/trace/control-internal.h
new file mode 100644
index 0000000..cce2da4
--- /dev/null
+++ b/trace/control-internal.h
@@ -0,0 +1,67 @@
+/*
+ * Interface for configuring and controlling the state of tracing events.
+ *
+ * Copyright (C) 2011-2012 Lluís Vilanova <vilanova at ac.upc.edu>
+ *
+ * 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 TRACE__CONTROL_INTERNAL_H
+#define TRACE__CONTROL_INTERNAL_H
+
+#include <string.h>
+
+
+extern TraceEvent trace_events[];
+
+
+static inline TraceEvent *trace_event_id(TraceEventID id)
+{
+    assert(id < trace_event_count());
+    return &trace_events[id];
+}
+
+static inline TraceEventID trace_event_count(void)
+{
+    return TRACE_EVENT_COUNT;
+}
+
+static inline bool trace_event_is_pattern(const char *str)
+{
+    assert(str != NULL);
+    return strchr(str, '*') != NULL;
+}
+
+static inline TraceEventID trace_event_get_id(TraceEvent *ev)
+{
+    assert(ev != NULL);
+    return ev->id;
+}
+
+static inline const char * trace_event_get_name(TraceEvent *ev)
+{
+    assert(ev != NULL);
+    return ev->name;
+}
+
+static inline bool trace_event_get_state_static(TraceEvent *ev)
+{
+    assert(ev != NULL);
+    return ev->sstate;
+}
+
+static inline bool trace_event_get_state_dynamic(TraceEvent *ev)
+{
+    assert(ev != NULL);
+    return ev->dstate;
+}
+
+static inline void trace_event_set_state_dynamic(TraceEvent *ev, bool state)
+{
+    assert(ev != NULL);
+    assert(trace_event_get_state_static(ev));
+    return trace_event_set_state_dynamic_backend(ev, state);
+}
+
+#endif  /* TRACE__CONTROL_INTERNAL_H */
diff --git a/trace/control.c b/trace/control.c
index be05efb..49f61e1 100644
--- a/trace/control.c
+++ b/trace/control.c
@@ -1,19 +1,86 @@
 /*
  * Interface for configuring and controlling the state of tracing events.
  *
- * Copyright (C) 2011 Lluís Vilanova <vilanova at ac.upc.edu>
+ * Copyright (C) 2011-2012 Lluís Vilanova <vilanova at ac.upc.edu>
  *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
+ * 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 "trace/control.h"
 
 
-void trace_backend_init_events(const char *fname)
+TraceEvent *trace_event_name(const char *name)
+{
+    assert(name != NULL);
+
+    TraceEventID i;
+    for (i = 0; i < trace_event_count(); i++) {
+        TraceEvent *ev = trace_event_id(i);
+        if (strcmp(trace_event_get_name(ev), name) == 0) {
+            return ev;
+        }
+    }
+    return NULL;
+}
+
+static bool pattern_glob(const char *pat, const char *ev)
+{
+    while (*pat != '\0' && *ev != '\0') {
+        if (*pat == *ev) {
+            pat++;
+            ev++;
+        }
+        else if (*pat == '*') {
+            if (pattern_glob(pat, ev+1)) {
+                return true;
+            } else if (pattern_glob(pat+1, ev)) {
+                return true;
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    while (*pat == '*') {
+        pat++;
+    }
+
+    if (*pat == '\0' && *ev == '\0') {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev)
 {
-    int ret;
+    assert(pat != NULL);
 
+    TraceEventID i;
+
+    if (ev == NULL) {
+        i = -1;
+    } else {
+        i = trace_event_get_id(ev);
+    }
+    i++;
+
+    while (i < trace_event_count()) {
+        TraceEvent *res = trace_event_id(i);
+        if (pattern_glob(pat, trace_event_get_name(res))) {
+            return res;
+        }
+        i++;
+    }
+
+    return NULL;
+}
+
+void trace_backend_init_events(const char *fname)
+{
     if (fname == NULL) {
         return;
     }
@@ -32,15 +99,28 @@ void trace_backend_init_events(const char *fname)
             if ('#' == line_buf[0]) { /* skip commented lines */
                 continue;
             }
-            if ('-' == line_buf[0]) {
-                ret = trace_event_set_state(line_buf+1, false);
+            const bool enable = ('-' != line_buf[0]);
+            char *line_ptr = enable ? line_buf : line_buf + 1;
+            if (trace_event_is_pattern(line_ptr)) {
+                TraceEvent *ev = NULL;
+                while ((ev = trace_event_pattern(line_ptr, ev)) != NULL) {
+                    if (trace_event_get_state_static(ev)) {
+                        trace_event_set_state_dynamic(ev, enable);
+                    }
+                }
             } else {
-                ret = trace_event_set_state(line_buf, true);
-            }
-            if (!ret) {
-                fprintf(stderr,
-                        "error: trace event '%s' does not exist\n", line_buf);
-                exit(1);
+                TraceEvent *ev = trace_event_name(line_ptr);
+                if (ev == NULL) {
+                    fprintf(stderr,
+                            "error: trace event '%s' does not exist\n", line_ptr);
+                    exit(1);
+                }
+                if (!trace_event_get_state_static(ev)) {
+                    fprintf(stderr,
+                            "error: trace event '%s' is not traceable\n", line_ptr);
+                    exit(1);
+                }
+                trace_event_set_state_dynamic(ev, enable);
             }
         }
     }
diff --git a/trace/control.h b/trace/control.h
index 2acaa42..cde8260 100644
--- a/trace/control.h
+++ b/trace/control.h
@@ -1,41 +1,193 @@
 /*
  * Interface for configuring and controlling the state of tracing events.
  *
- * Copyright (C) 2011 Lluís Vilanova <vilanova at ac.upc.edu>
+ * Copyright (C) 2011-2012 Lluís Vilanova <vilanova at ac.upc.edu>
  *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
+ * 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 TRACE_CONTROL_H
-#define TRACE_CONTROL_H
+#ifndef TRACE__CONTROL_H
+#define TRACE__CONTROL_H
 
 #include "qemu-common.h"
+#include "trace/generated-events.h"
 
 
-/** Print the state of all events. */
-void trace_print_events(FILE *stream, fprintf_function stream_printf);
-/** Set the state of an event.
+/**
+ * TraceEventID:
+ *
+ * Unique tracing event identifier.
+ *
+ * These are named as 'TRACE_${EVENT_NAME}'.
+ *
+ * See also: "trace/generated-events.h"
+ */
+enum TraceEventID;
+
+/**
+ * trace_event_id:
+ * @id: Event identifier.
+ *
+ * Get an event by its identifier.
+ *
+ * This routine has a constant cost, as opposed to trace_event_name and
+ * trace_event_pattern.
+ *
+ * Pre-conditions: The identifier is valid.
+ *
+ * Returns: pointer to #TraceEvent.
+ *
+ */
+static TraceEvent *trace_event_id(TraceEventID id);
+
+/**
+ * trace_event_name:
+ * @id: Event name.
+ *
+ * Search an event by its name.
+ *
+ * Returns: pointer to #TraceEvent or NULL if not found.
+ */
+TraceEvent *trace_event_name(const char *name);
+
+/**
+ * trace_event_pattern:
+ * @pat: Event name pattern.
+ * @ev: Event to start searching from (not included).
+ *
+ * Get all events with a given name pattern.
+ *
+ * Returns: pointer to #TraceEvent or NULL if not found.
+ */
+TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev);
+
+/**
+ * trace_event_is_pattern:
+ *
+ * Whether the given string is an event name pattern.
+ */
+static bool trace_event_is_pattern(const char *str);
+
+/**
+ * trace_event_count:
+ *
+ * Return the number of events.
+ */
+static TraceEventID trace_event_count(void);
+
+
+
+/**
+ * trace_event_get_id:
+ *
+ * Get the identifier of an event.
+ */
+static TraceEventID trace_event_get_id(TraceEvent *ev);
+
+/**
+ * trace_event_get_name:
  *
- * @return Whether the state changed.
+ * Get the name of an event.
  */
-bool trace_event_set_state(const char *name, bool state);
+static const char * trace_event_get_name(TraceEvent *ev);
 
+/**
+ * trace_event_get_state:
+ * @id: Event identifier.
+ *
+ * Get the tracing state of an event (both static and dynamic).
+ *
+ * If the event has the disabled property, the check will have no performance
+ * impact.
+ *
+ * As a down side, you must always use an immediate #TraceEventID value.
+ */
+#define trace_event_get_state(id)                       \
+    ((id ##_ENABLED) && trace_event_get_state_dynamic(trace_event_id(id)))
+
+/**
+ * trace_event_get_state_static:
+ * @id: Event identifier.
+ *
+ * Get the static tracing state of an event.
+ *
+ * Use the define 'TRACE_${EVENT_NAME}_ENABLED' for compile-time checks (it will
+ * be set to 1 or 0 according to the presence of the disabled property).
+ */
+static bool trace_event_get_state_static(TraceEvent *ev);
+
+/**
+ * trace_event_get_state_dynamic:
+ *
+ * Get the dynamic tracing state of an event.
+ */
+static bool trace_event_get_state_dynamic(TraceEvent *ev);
+
+/**
+ * trace_event_set_state:
+ *
+ * Set the tracing state of an event (only if possible).
+ */
+#define trace_event_set_state(id, state)                \
+    do {                                                \
+        if ((id ##_ENABLED)) {                          \
+            TraceEvent *_e = trace_event_id(id);        \
+            trace_event_set_state_dynamic(_e, state);   \
+        }                                               \
+    } while (0)
+
+/**
+ * trace_event_set_state_dynamic:
+ *
+ * Set the dynamic tracing state of an event.
+ *
+ * Pre-condition: trace_event_get_state_static(ev) == true
+ */
+static void trace_event_set_state_dynamic(TraceEvent *ev, bool state);
+
+/**
+ * trace_event_set_state_dynamic_backend:
+ *
+ * Warning: This function must be implemented by each tracing backend.
+ */
+void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state);
+
+
+
+/**
+ * trace_print_events:
+ *
+ * Print the state of all events.
+ *
+ * Warning: This function must be implemented by each tracing backend.
+ */
+void trace_print_events(FILE *stream, fprintf_function stream_printf);
 
-/** Initialize the tracing backend.
+/**
+ * trace_backend_init:
+ * @events: Name of file with events to be enabled at startup; may be NULL.
+ *          Corresponds to commandline option "-trace events=...".
+ * @file:   Name of trace output file; may be NULL.
+ *          Corresponds to commandline option "-trace file=...".
  *
- * @events Name of file with events to be enabled at startup; may be NULL.
- *         Corresponds to commandline option "-trace events=...".
- * @file   Name of trace output file; may be NULL.
- *         Corresponds to commandline option "-trace file=...".
- * @return Whether the backend could be successfully initialized.
+ * Initialize the tracing backend.
+ *
+ * Warning: This function must be implemented by each tracing backend.
+ *
+ * Returns: Whether the backend could be successfully initialized.
  */
 bool trace_backend_init(const char *events, const char *file);
 
-/** Generic function to initialize the state of events.
+/**
+ * trace_backend_init_events:
+ * @fname: Name of file with events to enable; may be NULL.
  *
- * @fname Name of file with events to enable; may be NULL.
+ * Generic function to initialize the state of events.
  */
 void trace_backend_init_events(const char *fname);
 
-#endif  /* TRACE_CONTROL_H */
+
+#include "trace/control-internal.h"
+
+#endif  /* TRACE__CONTROL_H */
commit 45be2f5d0dcdd314cd0c70a11220e5e09a44d654
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Tue Mar 5 14:47:32 2013 +0100

    trace: Provide a generic tracing event descriptor
    
    Uses tracetool to generate a backend-independent tracing event description
    (struct TraceEvent).
    
    The values for such structure are generated with the non-public "events"
    backend ("events-c" frontend).
    
    The generation of the defines to check if an event is statically enabled is also
    moved to the "events" backend ("events-h" frontend).
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/Makefile b/Makefile
index 6915178..80344d9 100644
--- a/Makefile
+++ b/Makefile
@@ -35,6 +35,9 @@ GENERATED_HEADERS = config-host.h qemu-options.def
 GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
 GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c
 
+GENERATED_HEADERS += trace/generated-events.h
+GENERATED_SOURCES += trace/generated-events.c
+
 GENERATED_HEADERS += trace/generated-tracers.h
 ifeq ($(TRACE_BACKEND),dtrace)
 GENERATED_HEADERS += trace/generated-tracers-dtrace.h
diff --git a/scripts/tracetool/backend/events.py b/scripts/tracetool/backend/events.py
new file mode 100644
index 0000000..5afce3e
--- /dev/null
+++ b/scripts/tracetool/backend/events.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generic event description.
+
+This is a dummy backend to establish appropriate frontend/backend compatibility
+checks.
+"""
+
+__author__     = "Lluís Vilanova <vilanova at ac.upc.edu>"
+__copyright__  = "Copyright 2012, Lluís Vilanova <vilanova at ac.upc.edu>"
+__license__    = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__      = "stefanha at linux.vnet.ibm.com"
+
+
+def events_h(events):
+    pass
+
+def events_c(events):
+    pass
diff --git a/scripts/tracetool/format/events_c.py b/scripts/tracetool/format/events_c.py
new file mode 100644
index 0000000..d670ec8
--- /dev/null
+++ b/scripts/tracetool/format/events_c.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate .c for event description.
+"""
+
+__author__     = "Lluís Vilanova <vilanova at ac.upc.edu>"
+__copyright__  = "Copyright 2012, Lluís Vilanova <vilanova at ac.upc.edu>"
+__license__    = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__      = "stefanha at linux.vnet.ibm.com"
+
+
+from tracetool import out
+
+
+def begin(events):
+    out('/* This file is autogenerated by tracetool, do not edit. */',
+        '',
+        '#include "trace.h"',
+        '#include "trace/generated-events.h"',
+        '#include "trace/control.h"',
+        '',
+        )
+
+    out('TraceEvent trace_events[TRACE_EVENT_COUNT] = {')
+
+    for e in events:
+        out('    { .id = %(id)s, .name = \"%(name)s\", .sstate = %(sstate)s, .dstate = 0 },',
+            id = "TRACE_" + e.name.upper(),
+            name = e.name,
+            sstate = "TRACE_%s_ENABLED" % e.name.upper(),
+            )
+
+    out('};',
+        '',
+        )
diff --git a/scripts/tracetool/format/events_h.py b/scripts/tracetool/format/events_h.py
new file mode 100644
index 0000000..d30ccea
--- /dev/null
+++ b/scripts/tracetool/format/events_h.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate .h for event description.
+"""
+
+__author__     = "Lluís Vilanova <vilanova at ac.upc.edu>"
+__copyright__  = "Copyright 2012, Lluís Vilanova <vilanova at ac.upc.edu>"
+__license__    = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__      = "stefanha at linux.vnet.ibm.com"
+
+
+from tracetool import out
+
+
+def begin(events):
+    out('/* This file is autogenerated by tracetool, do not edit. */',
+        '',
+        '#ifndef TRACE__GENERATED_EVENTS_H',
+        '#define TRACE__GENERATED_EVENTS_H',
+        '',
+        '#include <stdbool.h>',
+        ''
+        )
+
+    # event identifiers
+    out('typedef enum {')
+
+    for e in events:
+        out('    TRACE_%s,' % e.name.upper())
+
+    out('    TRACE_EVENT_COUNT',
+        '} TraceEventID;',
+        )
+
+    # static state
+    for e in events:
+        if 'disable' in e.properties:
+            enabled = 0
+        else:
+            enabled = 1
+        out('#define TRACE_%s_ENABLED %d' % (e.name.upper(), enabled))
+
+    out('#include "trace/event-internal.h"',
+        '',
+        '#endif  /* TRACE__GENERATED_EVENTS_H */',
+        )
diff --git a/scripts/tracetool/format/h.py b/scripts/tracetool/format/h.py
index 9a58de1..93132fc 100644
--- a/scripts/tracetool/format/h.py
+++ b/scripts/tracetool/format/h.py
@@ -25,14 +25,7 @@ def begin(events):
         '#include "qemu-common.h"')
 
 def end(events):
-    for e in events:
-        if "disable" in e.properties:
-            enabled = 0
-        else:
-            enabled = 1
-        out('#define TRACE_%s_ENABLED %d' % (e.name.upper(), enabled))
-    out('',
-        '#endif /* TRACE__GENERATED_TRACERS_H */')
+    out('#endif /* TRACE__GENERATED_TRACERS_H */')
 
 def nop(events):
     for e in events:
diff --git a/trace/Makefile.objs b/trace/Makefile.objs
index dde9d57..156aa25 100644
--- a/trace/Makefile.objs
+++ b/trace/Makefile.objs
@@ -1,7 +1,29 @@
 # -*- mode: makefile -*-
 
 ######################################################################
-# Auto-generated header for tracing routines
+# Auto-generated event descriptions
+
+$(obj)/generated-events.h: $(obj)/generated-events.h-timestamp
+$(obj)/generated-events.h-timestamp: $(SRC_PATH)/trace-events
+	$(call quiet-command,$(TRACETOOL) \
+		--format=events-h \
+		--backend=events \
+		< $< > $@,"  GEN   $(patsubst %-timestamp,%,$@)")
+	@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
+
+$(obj)/generated-events.c: $(obj)/generated-events.c-timestamp
+$(obj)/generated-events.c-timestamp: $(SRC_PATH)/trace-events
+	$(call quiet-command,$(TRACETOOL) \
+		--format=events-c \
+		--backend=events \
+		< $< > $@,"  GEN   $(patsubst %-timestamp,%,$@)")
+	@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
+
+util-obj-y += generated-events.o
+
+
+######################################################################
+# Auto-generated tracing routines
 
 $(obj)/generated-tracers.h: $(obj)/generated-tracers.h-timestamp
 	@cmp -s $< $@ || cp $< $@
diff --git a/trace/event-internal.h b/trace/event-internal.h
new file mode 100644
index 0000000..b2310d9
--- /dev/null
+++ b/trace/event-internal.h
@@ -0,0 +1,33 @@
+/*
+ * Interface for configuring and controlling the state of tracing events.
+ *
+ * Copyright (C) 2012 Lluís Vilanova <vilanova at ac.upc.edu>
+ *
+ * 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 TRACE__EVENT_INTERNAL_H
+#define TRACE__EVENT_INTERNAL_H
+
+#include "trace/generated-events.h"
+
+
+/**
+ * TraceEvent:
+ * @id: Unique event identifier.
+ * @name: Event name.
+ * @sstate: Static tracing state.
+ * @dstate: Dynamic tracing state.
+ *
+ * Opaque generic description of a tracing event.
+ */
+typedef struct TraceEvent {
+    TraceEventID id;
+    const char * name;
+    const bool sstate;
+    bool dstate;
+} TraceEvent;
+
+
+#endif  /* TRACE__EVENT_INTERNAL_H */
commit 93fba1618ddbbef8bedd8d684cf356586c94bbb1
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Tue Mar 5 14:47:26 2013 +0100

    trace: [tracetool] Explicitly identify public backends
    
    Public backends are those printed by "--list-backends" and thus considered valid
    by the configure script.
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/scripts/tracetool.py b/scripts/tracetool.py
index c003cf6..a79ec0f 100755
--- a/scripts/tracetool.py
+++ b/scripts/tracetool.py
@@ -90,8 +90,8 @@ def main(args):
             arg_format = arg
 
         elif opt == "--list-backends":
-            backends = tracetool.backend.get_list()
-            out(", ".join([ b for b,_ in backends ]))
+            public_backends = tracetool.backend.get_list(only_public = True)
+            out(", ".join([ b for b,_ in public_backends ]))
             sys.exit(0)
         elif opt == "--check-backend":
             check_backend = True
diff --git a/scripts/tracetool/backend/__init__.py b/scripts/tracetool/backend/__init__.py
index be43472..f0314ee 100644
--- a/scripts/tracetool/backend/__init__.py
+++ b/scripts/tracetool/backend/__init__.py
@@ -17,6 +17,16 @@ considered its short description.
 All backends must generate their contents through the 'tracetool.out' routine.
 
 
+Backend attributes
+------------------
+
+========= ====================================================================
+Attribute Description
+========= ====================================================================
+PUBLIC    If exists and is set to 'True', the backend is considered "public".
+========= ====================================================================
+
+
 Backend functions
 -----------------
 
@@ -42,7 +52,7 @@ import os
 import tracetool
 
 
-def get_list():
+def get_list(only_public = False):
     """Get a list of (name, description) pairs."""
     res = [("nop", "Tracing disabled.")]
     modnames = []
@@ -57,6 +67,10 @@ def get_list():
             continue
         module = module[1]
 
+        public = getattr(module, "PUBLIC", False)
+        if only_public and not public:
+            continue
+
         doc = module.__doc__
         if doc is None:
             doc = ""
diff --git a/scripts/tracetool/backend/dtrace.py b/scripts/tracetool/backend/dtrace.py
index ad5eb3b..e31bc79 100644
--- a/scripts/tracetool/backend/dtrace.py
+++ b/scripts/tracetool/backend/dtrace.py
@@ -16,6 +16,9 @@ __email__      = "stefanha at linux.vnet.ibm.com"
 from tracetool import out
 
 
+PUBLIC = True
+
+
 PROBEPREFIX = None
 
 def _probeprefix():
diff --git a/scripts/tracetool/backend/simple.py b/scripts/tracetool/backend/simple.py
index e4b4a7f..ac864f3 100644
--- a/scripts/tracetool/backend/simple.py
+++ b/scripts/tracetool/backend/simple.py
@@ -15,6 +15,10 @@ __email__      = "stefanha at linux.vnet.ibm.com"
 
 from tracetool import out
 
+
+PUBLIC = True
+
+
 def is_string(arg):
     strtype = ('const char*', 'char*', 'const char *', 'char *')
     if arg.lstrip().startswith(strtype):
diff --git a/scripts/tracetool/backend/stderr.py b/scripts/tracetool/backend/stderr.py
index 917fde7..a10fbb8 100644
--- a/scripts/tracetool/backend/stderr.py
+++ b/scripts/tracetool/backend/stderr.py
@@ -16,6 +16,9 @@ __email__      = "stefanha at linux.vnet.ibm.com"
 from tracetool import out
 
 
+PUBLIC = True
+
+
 def c(events):
     out('#include "trace.h"',
         '',
diff --git a/scripts/tracetool/backend/ust.py b/scripts/tracetool/backend/ust.py
index 31a2ff0..ea36995 100644
--- a/scripts/tracetool/backend/ust.py
+++ b/scripts/tracetool/backend/ust.py
@@ -16,6 +16,9 @@ __email__      = "stefanha at linux.vnet.ibm.com"
 from tracetool import out
 
 
+PUBLIC = True
+
+
 def c(events):
     out('#include <ust/marker.h>',
         '#undef mutex_lock',
commit 5d186eb03eb37b257e29a4731ca484362d5fc4e4
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 27 17:28:18 2013 +0100

    block: Fix direct use of protocols as driver for bdrv_open()
    
    bdrv_open_common() implements direct use of protocols by copying the
    pre-opened BlockDriverStates to bs using bdrv_swap(). It did however
    first set some fields in bs, which end up in file after the swap. When
    bdrv_open() destroys file, it appears to be open, and because it isn't,
    qemu could segfault while trying to close it.
    
    Reorder the operations to return immediately in such cases so that file
    is correctly detected as closed.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block.c b/block.c
index 16a92a4..0ae2e93 100644
--- a/block.c
+++ b/block.c
@@ -680,6 +680,18 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
 
     trace_bdrv_open_common(bs, filename, flags, drv->format_name);
 
+    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
+        return -ENOTSUP;
+    }
+
+    /* bdrv_open() with directly using a protocol as drv. This layer is already
+     * opened, so assign it to bs (while file becomes a closed BlockDriverState)
+     * and return immediately. */
+    if (file != NULL && drv->bdrv_file_open) {
+        bdrv_swap(file, bs);
+        return 0;
+    }
+
     bs->open_flags = flags;
     bs->buffer_alignment = 512;
 
@@ -694,10 +706,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
         bs->filename[0] = '\0';
     }
 
-    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
-        return -ENOTSUP;
-    }
-
     bs->drv = drv;
     bs->opaque = g_malloc0(drv->instance_size);
 
@@ -708,13 +716,9 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
 
     /* Open the image, either directly or using a protocol */
     if (drv->bdrv_file_open) {
-        if (file != NULL) {
-            bdrv_swap(file, bs);
-            ret = 0;
-        } else {
-            assert(drv->bdrv_parse_filename || filename != NULL);
-            ret = drv->bdrv_file_open(bs, filename, options, open_flags);
-        }
+        assert(file == NULL);
+        assert(drv->bdrv_parse_filename || filename != NULL);
+        ret = drv->bdrv_file_open(bs, filename, options, open_flags);
     } else {
         assert(file != NULL);
         bs->file = file;
commit ecdd5333ab9ed3f2b848066aaaef02c027b25e36
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 27 11:43:49 2013 +0100

    qcow2: Gather clusters in a looping loop
    
    Instead of just checking once in exactly this order if there are
    dependendies, non-COW clusters and new allocation, this starts looping
    around these. This way we can, for example, gather non-COW clusters after
    new allocations as long as the host cluster offsets stay contiguous.
    
    Once handle_dependencies() is extended so that COW areas of in-flight
    allocations can be overwritten, this allows to continue with gathering
    other clusters (we wouldn't be able to do that without this change
    because we would have missed a possible second dependency in one of the
    next clusters).
    
    This means that in the typical sequential write case, we can combine the
    COW overwrite of one cluster with the allocation of the next cluster as
    soon as something like Delayed COW gets actually implemented. It is only
    by avoiding splitting requests this way that Delayed COW actually starts
    improving performance noticably.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 960d446..c71470a 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -770,7 +770,7 @@ out:
  *           must start over anyway, so consider *cur_bytes undefined.
  */
 static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
-    uint64_t *cur_bytes)
+    uint64_t *cur_bytes, QCowL2Meta **m)
 {
     BDRVQcowState *s = bs->opaque;
     QCowL2Meta *old_alloc;
@@ -793,6 +793,15 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
                 bytes = 0;
             }
 
+            /* Stop if already an l2meta exists. After yielding, it wouldn't
+             * be valid any more, so we'd have to clean up the old L2Metas
+             * and deal with requests depending on them before starting to
+             * gather new ones. Not worth the trouble. */
+            if (bytes == 0 && *m) {
+                *cur_bytes = 0;
+                return 0;
+            }
+
             if (bytes == 0) {
                 /* Wait for the dependency to complete. We need to recheck
                  * the free/allocated clusters when we continue. */
@@ -1023,16 +1032,16 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
         nb_clusters = count_cow_clusters(s, nb_clusters, l2_table, l2_index);
     }
 
+    /* This function is only called when there were no non-COW clusters, so if
+     * we can't find any unallocated or COW clusters either, something is
+     * wrong with our code. */
+    assert(nb_clusters > 0);
+
     ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
     if (ret < 0) {
         return ret;
     }
 
-    if (nb_clusters == 0) {
-        *bytes = 0;
-        return 0;
-    }
-
     /* Allocate, if necessary at a given offset in the image file */
     alloc_cluster_offset = start_of_cluster(s, *host_offset);
     ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset,
@@ -1146,8 +1155,27 @@ again:
     remaining = (n_end - n_start) << BDRV_SECTOR_BITS;
     cluster_offset = 0;
     *host_offset = 0;
+    cur_bytes = 0;
+    *m = NULL;
 
     while (true) {
+
+        if (!*host_offset) {
+            *host_offset = start_of_cluster(s, cluster_offset);
+        }
+
+        assert(remaining >= cur_bytes);
+
+        start           += cur_bytes;
+        remaining       -= cur_bytes;
+        cluster_offset  += cur_bytes;
+
+        if (remaining == 0) {
+            break;
+        }
+
+        cur_bytes = remaining;
+
         /*
          * Now start gathering as many contiguous clusters as possible:
          *
@@ -1166,12 +1194,17 @@ again:
          *         the right synchronisation between the in-flight request and
          *         the new one.
          */
-        cur_bytes = remaining;
-        ret = handle_dependencies(bs, start, &cur_bytes);
+        ret = handle_dependencies(bs, start, &cur_bytes, m);
         if (ret == -EAGAIN) {
+            /* Currently handle_dependencies() doesn't yield if we already had
+             * an allocation. If it did, we would have to clean up the L2Meta
+             * structs before starting over. */
+            assert(*m == NULL);
             goto again;
         } else if (ret < 0) {
             return ret;
+        } else if (cur_bytes == 0) {
+            break;
         } else {
             /* handle_dependencies() may have decreased cur_bytes (shortened
              * the allocations below) so that the next dependency is processed
@@ -1185,24 +1218,11 @@ again:
         if (ret < 0) {
             return ret;
         } else if (ret) {
-            if (!*host_offset) {
-                *host_offset = start_of_cluster(s, cluster_offset);
-            }
-
-            start           += cur_bytes;
-            remaining       -= cur_bytes;
-            cluster_offset  += cur_bytes;
-
-            cur_bytes = remaining;
+            continue;
         } else if (cur_bytes == 0) {
             break;
         }
 
-        /* If there is something left to allocate, do that now */
-        if (remaining == 0) {
-            break;
-        }
-
         /*
          * 3. If the request still hasn't completed, allocate new clusters,
          *    considering any cluster_offset of steps 1c or 2.
@@ -1211,15 +1231,7 @@ again:
         if (ret < 0) {
             return ret;
         } else if (ret) {
-            if (!*host_offset) {
-                *host_offset = start_of_cluster(s, cluster_offset);
-            }
-
-            start           += cur_bytes;
-            remaining       -= cur_bytes;
-            cluster_offset  += cur_bytes;
-
-            break;
+            continue;
         } else {
             assert(cur_bytes == 0);
             break;
diff --git a/tests/qemu-iotests/044.out b/tests/qemu-iotests/044.out
index 34c25c7..5c5aa92 100644
--- a/tests/qemu-iotests/044.out
+++ b/tests/qemu-iotests/044.out
@@ -1,6 +1,6 @@
 No errors were found on the image.
 7292415/33554432 = 21.73% allocated, 0.00% fragmented, 0.00% compressed clusters
-Image end offset: 4296447488
+Image end offset: 4296448000
 .
 ----------------------------------------------------------------------
 Ran 1 tests
commit 2c3b32d25620c26e26fd590c198ec6d9cf91da57
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:12 2013 +0100

    qcow2: Move cluster gathering to a non-looping loop
    
    This patch is mainly to separate the indentation change from the
    semantic changes. All that really changes here is that everything moves
    into a while loop, all 'goto done' become 'break' and at the end of the
    loop a new 'break is inserted.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 6dc7f7f..960d446 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1147,79 +1147,85 @@ again:
     cluster_offset = 0;
     *host_offset = 0;
 
-    /*
-     * Now start gathering as many contiguous clusters as possible:
-     *
-     * 1. Check for overlaps with in-flight allocations
-     *
-     *      a) Overlap not in the first cluster -> shorten this request and let
-     *         the caller handle the rest in its next loop iteration.
-     *
-     *      b) Real overlaps of two requests. Yield and restart the search for
-     *         contiguous clusters (the situation could have changed while we
-     *         were sleeping)
-     *
-     *      c) TODO: Request starts in the same cluster as the in-flight
-     *         allocation ends. Shorten the COW of the in-fight allocation, set
-     *         cluster_offset to write to the same cluster and set up the right
-     *         synchronisation between the in-flight request and the new one.
-     */
-    cur_bytes = remaining;
-    ret = handle_dependencies(bs, start, &cur_bytes);
-    if (ret == -EAGAIN) {
-        goto again;
-    } else if (ret < 0) {
-        return ret;
-    } else {
-        /* handle_dependencies() may have decreased cur_bytes (shortened
-         * the allocations below) so that the next dependency is processed
-         * correctly during the next loop iteration. */
-    }
-
-    /*
-     * 2. Count contiguous COPIED clusters.
-     */
-    ret = handle_copied(bs, start, &cluster_offset, &cur_bytes, m);
-    if (ret < 0) {
-        return ret;
-    } else if (ret) {
-        if (!*host_offset) {
-            *host_offset = start_of_cluster(s, cluster_offset);
+    while (true) {
+        /*
+         * Now start gathering as many contiguous clusters as possible:
+         *
+         * 1. Check for overlaps with in-flight allocations
+         *
+         *      a) Overlap not in the first cluster -> shorten this request and
+         *         let the caller handle the rest in its next loop iteration.
+         *
+         *      b) Real overlaps of two requests. Yield and restart the search
+         *         for contiguous clusters (the situation could have changed
+         *         while we were sleeping)
+         *
+         *      c) TODO: Request starts in the same cluster as the in-flight
+         *         allocation ends. Shorten the COW of the in-fight allocation,
+         *         set cluster_offset to write to the same cluster and set up
+         *         the right synchronisation between the in-flight request and
+         *         the new one.
+         */
+        cur_bytes = remaining;
+        ret = handle_dependencies(bs, start, &cur_bytes);
+        if (ret == -EAGAIN) {
+            goto again;
+        } else if (ret < 0) {
+            return ret;
+        } else {
+            /* handle_dependencies() may have decreased cur_bytes (shortened
+             * the allocations below) so that the next dependency is processed
+             * correctly during the next loop iteration. */
         }
 
-        start           += cur_bytes;
-        remaining       -= cur_bytes;
-        cluster_offset  += cur_bytes;
+        /*
+         * 2. Count contiguous COPIED clusters.
+         */
+        ret = handle_copied(bs, start, &cluster_offset, &cur_bytes, m);
+        if (ret < 0) {
+            return ret;
+        } else if (ret) {
+            if (!*host_offset) {
+                *host_offset = start_of_cluster(s, cluster_offset);
+            }
 
-        cur_bytes = remaining;
-    } else if (cur_bytes == 0) {
-        goto done;
-    }
+            start           += cur_bytes;
+            remaining       -= cur_bytes;
+            cluster_offset  += cur_bytes;
 
-    /* If there is something left to allocate, do that now */
-    if (remaining == 0) {
-        goto done;
-    }
+            cur_bytes = remaining;
+        } else if (cur_bytes == 0) {
+            break;
+        }
 
-    /*
-     * 3. If the request still hasn't completed, allocate new clusters,
-     *    considering any cluster_offset of steps 1c or 2.
-     */
-    ret = handle_alloc(bs, start, &cluster_offset, &cur_bytes, m);
-    if (ret < 0) {
-        return ret;
-    } else if (ret) {
-        if (!*host_offset) {
-            *host_offset = start_of_cluster(s, cluster_offset);
+        /* If there is something left to allocate, do that now */
+        if (remaining == 0) {
+            break;
         }
 
-        start           += cur_bytes;
-        remaining       -= cur_bytes;
-        cluster_offset  += cur_bytes;
+        /*
+         * 3. If the request still hasn't completed, allocate new clusters,
+         *    considering any cluster_offset of steps 1c or 2.
+         */
+        ret = handle_alloc(bs, start, &cluster_offset, &cur_bytes, m);
+        if (ret < 0) {
+            return ret;
+        } else if (ret) {
+            if (!*host_offset) {
+                *host_offset = start_of_cluster(s, cluster_offset);
+            }
+
+            start           += cur_bytes;
+            remaining       -= cur_bytes;
+            cluster_offset  += cur_bytes;
+
+            break;
+        } else {
+            assert(cur_bytes == 0);
+            break;
+        }
     }
 
-    /* Some cleanup work */
-done:
     *num = (n_end - n_start) - (remaining >> BDRV_SECTOR_BITS);
     assert(*num > 0);
     assert(*host_offset != 0);
commit 88c6588c5165da1526f735ed850861c5b74670bd
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:11 2013 +0100

    qcow2: Allow requests with multiple l2metas
    
    Instead of expecting a single l2meta, have a list of them. This allows
    to still have a single I/O request for the guest data, even though
    multiple l2meta may be needed in order to describe both a COW overwrite
    and a new cluster allocation (typical sequential write case).
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 78e7db9..6dc7f7f 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1069,10 +1069,13 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
     int alloc_n_start = offset_into_cluster(s, guest_offset)
                         >> BDRV_SECTOR_BITS;
     int nb_sectors = MIN(requested_sectors, avail_sectors);
+    QCowL2Meta *old_m = *m;
 
     *m = g_malloc0(sizeof(**m));
 
     **m = (QCowL2Meta) {
+        .next           = old_m,
+
         .alloc_offset   = alloc_cluster_offset,
         .offset         = start_of_cluster(s, guest_offset),
         .nb_clusters    = nb_clusters,
diff --git a/block/qcow2.c b/block/qcow2.c
index 3f7edf5..7e7d775 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -858,7 +858,9 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
             goto fail;
         }
 
-        if (l2meta != NULL) {
+        while (l2meta != NULL) {
+            QCowL2Meta *next;
+
             ret = qcow2_alloc_cluster_link_l2(bs, l2meta);
             if (ret < 0) {
                 goto fail;
@@ -871,8 +873,9 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
 
             qemu_co_queue_restart_all(&l2meta->dependent_requests);
 
+            next = l2meta->next;
             g_free(l2meta);
-            l2meta = NULL;
+            l2meta = next;
         }
 
         remaining_sectors -= cur_nr_sectors;
@@ -885,12 +888,17 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
 fail:
     qemu_co_mutex_unlock(&s->lock);
 
-    if (l2meta != NULL) {
+    while (l2meta != NULL) {
+        QCowL2Meta *next;
+
         if (l2meta->nb_clusters != 0) {
             QLIST_REMOVE(l2meta, next_in_flight);
         }
         qemu_co_queue_restart_all(&l2meta->dependent_requests);
+
+        next = l2meta->next;
         g_free(l2meta);
+        l2meta = next;
     }
 
     qemu_iovec_destroy(&hd_qiov);
diff --git a/block/qcow2.h b/block/qcow2.h
index 32806bd..bf8db2a 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -250,6 +250,9 @@ typedef struct QCowL2Meta
      */
     Qcow2COWRegion cow_end;
 
+    /** Pointer to next L2Meta of the same write request */
+    struct QCowL2Meta *next;
+
     QLIST_ENTRY(QCowL2Meta) next_in_flight;
 } QCowL2Meta;
 
commit 710c2496d8cecc92568d439a3cf9d5874b3a55e2
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:10 2013 +0100

    qcow2: Use byte granularity in qcow2_alloc_cluster_offset()
    
    This gets rid of the nb_clusters and keep_clusters and the associated
    complicated calculations. Just advance the number of bytes that have
    been processed and everything is fine.
    
    This patch advances the variables even after the last operation even
    though they aren't used any more afterwards to make things look more
    uniform. A later patch will turn the whole thing into a loop and then
    it actually starts making sense.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 4f43d41..78e7db9 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1127,28 +1127,24 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
     int n_start, int n_end, int *num, uint64_t *host_offset, QCowL2Meta **m)
 {
     BDRVQcowState *s = bs->opaque;
-    int l2_index, ret, sectors;
-    unsigned int nb_clusters, keep_clusters;
+    uint64_t start, remaining;
     uint64_t cluster_offset;
     uint64_t cur_bytes;
+    int ret;
 
     trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset,
                                       n_start, n_end);
 
+    assert(n_start * BDRV_SECTOR_SIZE == offset_into_cluster(s, offset));
+    offset = start_of_cluster(s, offset);
+
 again:
+    start = offset + (n_start << BDRV_SECTOR_BITS);
+    remaining = (n_end - n_start) << BDRV_SECTOR_BITS;
     cluster_offset = 0;
     *host_offset = 0;
 
     /*
-     * Calculate the number of clusters to look for. We stop at L2 table
-     * boundaries to keep things simple.
-     */
-    l2_index = offset_to_l2_index(s, offset);
-    nb_clusters = MIN(size_to_clusters(s, n_end << BDRV_SECTOR_BITS),
-                      s->l2_size - l2_index);
-    n_end = MIN(n_end, nb_clusters * s->cluster_sectors);
-
-    /*
      * Now start gathering as many contiguous clusters as possible:
      *
      * 1. Check for overlaps with in-flight allocations
@@ -1165,8 +1161,8 @@ again:
      *         cluster_offset to write to the same cluster and set up the right
      *         synchronisation between the in-flight request and the new one.
      */
-    cur_bytes = (n_end - n_start) * BDRV_SECTOR_SIZE;
-    ret = handle_dependencies(bs, offset, &cur_bytes);
+    cur_bytes = remaining;
+    ret = handle_dependencies(bs, start, &cur_bytes);
     if (ret == -EAGAIN) {
         goto again;
     } else if (ret < 0) {
@@ -1177,33 +1173,28 @@ again:
          * correctly during the next loop iteration. */
     }
 
-    nb_clusters = size_to_clusters(s, offset + cur_bytes)
-                - (offset >> s->cluster_bits);
-
     /*
      * 2. Count contiguous COPIED clusters.
      */
-    uint64_t tmp_bytes = cur_bytes;
-    ret = handle_copied(bs, offset, &cluster_offset, &tmp_bytes, m);
+    ret = handle_copied(bs, start, &cluster_offset, &cur_bytes, m);
     if (ret < 0) {
         return ret;
     } else if (ret) {
-        keep_clusters =
-            size_to_clusters(s, tmp_bytes + offset_into_cluster(s, offset));
-        nb_clusters -= keep_clusters;
-
         if (!*host_offset) {
             *host_offset = start_of_cluster(s, cluster_offset);
         }
+
+        start           += cur_bytes;
+        remaining       -= cur_bytes;
+        cluster_offset  += cur_bytes;
+
+        cur_bytes = remaining;
     } else if (cur_bytes == 0) {
-        keep_clusters = 0;
         goto done;
-    } else {
-        keep_clusters = 0;
     }
 
     /* If there is something left to allocate, do that now */
-    if (nb_clusters == 0) {
+    if (remaining == 0) {
         goto done;
     }
 
@@ -1211,43 +1202,24 @@ again:
      * 3. If the request still hasn't completed, allocate new clusters,
      *    considering any cluster_offset of steps 1c or 2.
      */
-    int alloc_n_start;
-    int alloc_n_end;
-
-    if (keep_clusters != 0) {
-        offset         = start_of_cluster(s, offset
-                                             + keep_clusters * s->cluster_size);
-        cluster_offset = start_of_cluster(s, cluster_offset
-                                             + keep_clusters * s->cluster_size);
-
-        alloc_n_start = 0;
-        alloc_n_end = n_end - keep_clusters * s->cluster_sectors;
-    } else {
-        alloc_n_start = n_start;
-        alloc_n_end = n_end;
-    }
-
-    cur_bytes = MIN(cur_bytes, ((alloc_n_end - alloc_n_start) << BDRV_SECTOR_BITS));
-
-    ret = handle_alloc(bs, offset, &cluster_offset, &cur_bytes, m);
+    ret = handle_alloc(bs, start, &cluster_offset, &cur_bytes, m);
     if (ret < 0) {
         return ret;
-    }
+    } else if (ret) {
+        if (!*host_offset) {
+            *host_offset = start_of_cluster(s, cluster_offset);
+        }
 
-    if (!*host_offset) {
-        *host_offset = start_of_cluster(s, cluster_offset);
+        start           += cur_bytes;
+        remaining       -= cur_bytes;
+        cluster_offset  += cur_bytes;
     }
-    nb_clusters = size_to_clusters(s, cur_bytes + offset_into_cluster(s, offset));
 
     /* Some cleanup work */
 done:
-    sectors = (keep_clusters + nb_clusters) << (s->cluster_bits - 9);
-    if (sectors > n_end) {
-        sectors = n_end;
-    }
-
-    assert(sectors > n_start);
-    *num = sectors - n_start;
+    *num = (n_end - n_start) - (remaining >> BDRV_SECTOR_BITS);
+    assert(*num > 0);
+    assert(*host_offset != 0);
 
     return 0;
 }
commit 411d62b04b4cd2d3a6cea310689dbafa2479bc28
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:09 2013 +0100

    qcow2: Prepare handle_alloc/copied() for byte granularity
    
    This makes handle_alloc() and handle_copied() return byte-granularity
    host offsets instead of returning always the cluster start. This is
    required so that qcow2_alloc_cluster_offset() can stop aligning
    everything to cluster boundaries.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 239a997..4f43d41 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -817,7 +817,9 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
  * *host_offset is not zero, only physically contiguous clusters beginning at
  * this host offset are counted.
  *
- * Note that guest_offset may not be cluster aligned.
+ * Note that guest_offset may not be cluster aligned. In this case, the
+ * returned *host_offset points to exact byte referenced by guest_offset and
+ * therefore isn't cluster aligned as well.
  *
  * Returns:
  *   0:     if no allocated clusters are available at the given offset.
@@ -845,6 +847,9 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
     trace_qcow2_handle_copied(qemu_coroutine_self(), guest_offset, *host_offset,
                               *bytes);
 
+    assert(*host_offset == 0 ||    offset_into_cluster(s, guest_offset)
+                                == offset_into_cluster(s, *host_offset));
+
     /*
      * Calculate the number of clusters to look for. We stop at L2 table
      * boundaries to keep things simple.
@@ -903,7 +908,8 @@ out:
     /* Only return a host offset if we actually made progress. Otherwise we
      * would make requirements for handle_alloc() that it can't fulfill */
     if (ret) {
-        *host_offset = cluster_offset & L2E_OFFSET_MASK;
+        *host_offset = (cluster_offset & L2E_OFFSET_MASK)
+                     + offset_into_cluster(s, guest_offset);
     }
 
     return ret;
@@ -961,7 +967,9 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
  * copy on write. If *host_offset is non-zero, clusters are only allocated if
  * the new allocation can match the specified host offset.
  *
- * Note that guest_offset may not be cluster aligned.
+ * Note that guest_offset may not be cluster aligned. In this case, the
+ * returned *host_offset points to exact byte referenced by guest_offset and
+ * therefore isn't cluster aligned as well.
  *
  * Returns:
  *   0:     if no clusters could be allocated. *bytes is set to 0,
@@ -1026,7 +1034,7 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
     }
 
     /* Allocate, if necessary at a given offset in the image file */
-    alloc_cluster_offset = *host_offset;
+    alloc_cluster_offset = start_of_cluster(s, *host_offset);
     ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset,
                                   &nb_clusters);
     if (ret < 0) {
@@ -1062,12 +1070,10 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
                         >> BDRV_SECTOR_BITS;
     int nb_sectors = MIN(requested_sectors, avail_sectors);
 
-    *host_offset = alloc_cluster_offset;
-
     *m = g_malloc0(sizeof(**m));
 
     **m = (QCowL2Meta) {
-        .alloc_offset   = *host_offset,
+        .alloc_offset   = alloc_cluster_offset,
         .offset         = start_of_cluster(s, guest_offset),
         .nb_clusters    = nb_clusters,
         .nb_available   = nb_sectors,
@@ -1084,6 +1090,7 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
     qemu_co_queue_init(&(*m)->dependent_requests);
     QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
 
+    *host_offset = alloc_cluster_offset + offset_into_cluster(s, guest_offset);
     *bytes = MIN(*bytes, (nb_sectors * BDRV_SECTOR_SIZE)
                          - offset_into_cluster(s, guest_offset));
     assert(*bytes != 0);
@@ -1186,7 +1193,7 @@ again:
         nb_clusters -= keep_clusters;
 
         if (!*host_offset) {
-            *host_offset = cluster_offset;
+            *host_offset = start_of_cluster(s, cluster_offset);
         }
     } else if (cur_bytes == 0) {
         keep_clusters = 0;
@@ -1228,7 +1235,7 @@ again:
     }
 
     if (!*host_offset) {
-        *host_offset = cluster_offset;
+        *host_offset = start_of_cluster(s, cluster_offset);
     }
     nb_clusters = size_to_clusters(s, cur_bytes + offset_into_cluster(s, offset));
 
commit e62daaf67958e8274547ddac87cb0a177a869216
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:08 2013 +0100

    qcow2: handle_copied(): Implement non-zero host_offset
    
    Look only for clusters that start at a given physical offset.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 5e5465d..239a997 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -830,8 +830,6 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
  *          the length of the area that can be written to.
  *
  *  -errno: in error cases
- *
- * TODO Make non-zero host_offset behave like describe above
  */
 static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
     uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
@@ -846,7 +844,6 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
 
     trace_qcow2_handle_copied(qemu_coroutine_self(), guest_offset, *host_offset,
                               *bytes);
-    assert(*host_offset == 0);
 
     /*
      * Calculate the number of clusters to look for. We stop at L2 table
@@ -870,6 +867,16 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
     if (qcow2_get_cluster_type(cluster_offset) == QCOW2_CLUSTER_NORMAL
         && (cluster_offset & QCOW_OFLAG_COPIED))
     {
+        /* If a specific host_offset is required, check it */
+        bool offset_matches =
+            (cluster_offset & L2E_OFFSET_MASK) == *host_offset;
+
+        if (*host_offset != 0 && !offset_matches) {
+            *bytes = 0;
+            ret = 0;
+            goto out;
+        }
+
         /* We keep all QCOW_OFLAG_COPIED clusters */
         keep_clusters =
             count_contiguous_clusters(nb_clusters, s->cluster_size,
@@ -883,19 +890,22 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
 
         ret = 1;
     } else {
-        cluster_offset = 0;
         ret = 0;
     }
 
-    cluster_offset &= L2E_OFFSET_MASK;
-    *host_offset = cluster_offset;
-
     /* Cleanup */
+out:
     pret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
     if (pret < 0) {
         return pret;
     }
 
+    /* Only return a host offset if we actually made progress. Otherwise we
+     * would make requirements for handle_alloc() that it can't fulfill */
+    if (ret) {
+        *host_offset = cluster_offset & L2E_OFFSET_MASK;
+    }
+
     return ret;
 }
 
@@ -1165,7 +1175,6 @@ again:
 
     /*
      * 2. Count contiguous COPIED clusters.
-     *    TODO: Consider cluster_offset if set in step 1c.
      */
     uint64_t tmp_bytes = cur_bytes;
     ret = handle_copied(bs, offset, &cluster_offset, &tmp_bytes, m);
@@ -1179,6 +1188,9 @@ again:
         if (!*host_offset) {
             *host_offset = cluster_offset;
         }
+    } else if (cur_bytes == 0) {
+        keep_clusters = 0;
+        goto done;
     } else {
         keep_clusters = 0;
     }
commit c53ede9f6d8f0de7939eea676c1398c4073ff35e
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:07 2013 +0100

    qcow2: handle_copied(): Get rid of keep_clusters parameter
    
    Now *bytes is used to return the length of the area that can be written
    to without performing an allocation or COW.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index d640328..5e5465d 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -831,19 +831,17 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
  *
  *  -errno: in error cases
  *
- * TODO Get rid of keep_clusters parameter
- * TODO Make bytes behave like described above
  * TODO Make non-zero host_offset behave like describe above
  */
 static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
-    uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m,
-    unsigned int *keep_clusters)
+    uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index;
     uint64_t cluster_offset;
     uint64_t *l2_table;
     unsigned int nb_clusters;
+    unsigned int keep_clusters;
     int ret, pret;
 
     trace_qcow2_handle_copied(qemu_coroutine_self(), guest_offset, *host_offset,
@@ -873,17 +871,19 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
         && (cluster_offset & QCOW_OFLAG_COPIED))
     {
         /* We keep all QCOW_OFLAG_COPIED clusters */
-        *keep_clusters =
+        keep_clusters =
             count_contiguous_clusters(nb_clusters, s->cluster_size,
                                       &l2_table[l2_index], 0,
                                       QCOW_OFLAG_COPIED | QCOW_OFLAG_ZERO);
-        assert(*keep_clusters <= nb_clusters);
+        assert(keep_clusters <= nb_clusters);
+
+        *bytes = MIN(*bytes,
+                 keep_clusters * s->cluster_size
+                 - offset_into_cluster(s, guest_offset));
 
         ret = 1;
     } else {
-        *keep_clusters = 0;
         cluster_offset = 0;
-
         ret = 0;
     }
 
@@ -1168,16 +1168,19 @@ again:
      *    TODO: Consider cluster_offset if set in step 1c.
      */
     uint64_t tmp_bytes = cur_bytes;
-    ret = handle_copied(bs, offset, &cluster_offset, &tmp_bytes, m,
-                        &keep_clusters);
+    ret = handle_copied(bs, offset, &cluster_offset, &tmp_bytes, m);
     if (ret < 0) {
         return ret;
     } else if (ret) {
+        keep_clusters =
+            size_to_clusters(s, tmp_bytes + offset_into_cluster(s, offset));
         nb_clusters -= keep_clusters;
 
         if (!*host_offset) {
             *host_offset = cluster_offset;
         }
+    } else {
+        keep_clusters = 0;
     }
 
     /* If there is something left to allocate, do that now */
commit acb0467f8df7e9dbc8bbcb9a2e1e8cfe17f79691
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:06 2013 +0100

    qcow2: handle_copied(): Get rid of nb_clusters parameter
    
    handle_copied() uses its bytes parameter now to determine how many
    clusters it should try to find.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 9036bd8..d640328 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -831,24 +831,35 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
  *
  *  -errno: in error cases
  *
- * TODO Get rid of keep_clusters, nb_clusters parameters
+ * TODO Get rid of keep_clusters parameter
  * TODO Make bytes behave like described above
  * TODO Make non-zero host_offset behave like describe above
  */
 static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
     uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m,
-    unsigned int *keep_clusters, unsigned int *nb_clusters)
+    unsigned int *keep_clusters)
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index;
     uint64_t cluster_offset;
     uint64_t *l2_table;
+    unsigned int nb_clusters;
     int ret, pret;
 
     trace_qcow2_handle_copied(qemu_coroutine_self(), guest_offset, *host_offset,
                               *bytes);
     assert(*host_offset == 0);
 
+    /*
+     * Calculate the number of clusters to look for. We stop at L2 table
+     * boundaries to keep things simple.
+     */
+    nb_clusters =
+        size_to_clusters(s, offset_into_cluster(s, guest_offset) + *bytes);
+
+    l2_index = offset_to_l2_index(s, guest_offset);
+    nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
+
     /* Find L2 entry for the first involved cluster */
     ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
     if (ret < 0) {
@@ -863,11 +874,10 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
     {
         /* We keep all QCOW_OFLAG_COPIED clusters */
         *keep_clusters =
-            count_contiguous_clusters(*nb_clusters, s->cluster_size,
+            count_contiguous_clusters(nb_clusters, s->cluster_size,
                                       &l2_table[l2_index], 0,
                                       QCOW_OFLAG_COPIED | QCOW_OFLAG_ZERO);
-        assert(*keep_clusters <= *nb_clusters);
-        *nb_clusters -= *keep_clusters;
+        assert(*keep_clusters <= nb_clusters);
 
         ret = 1;
     } else {
@@ -1159,10 +1169,12 @@ again:
      */
     uint64_t tmp_bytes = cur_bytes;
     ret = handle_copied(bs, offset, &cluster_offset, &tmp_bytes, m,
-                        &keep_clusters, &nb_clusters);
+                        &keep_clusters);
     if (ret < 0) {
         return ret;
     } else if (ret) {
+        nb_clusters -= keep_clusters;
+
         if (!*host_offset) {
             *host_offset = cluster_offset;
         }
commit 0af729ec007ea4d103a2e3f3fc5db522610a2290
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:05 2013 +0100

    qcow2: Factor out handle_copied()
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 1141483..9036bd8 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -812,6 +812,84 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
 }
 
 /*
+ * Checks how many already allocated clusters that don't require a copy on
+ * write there are at the given guest_offset (up to *bytes). If
+ * *host_offset is not zero, only physically contiguous clusters beginning at
+ * this host offset are counted.
+ *
+ * Note that guest_offset may not be cluster aligned.
+ *
+ * Returns:
+ *   0:     if no allocated clusters are available at the given offset.
+ *          *bytes is normally unchanged. It is set to 0 if the cluster
+ *          is allocated and doesn't need COW, but doesn't have the right
+ *          physical offset.
+ *
+ *   1:     if allocated clusters that don't require a COW are available at
+ *          the requested offset. *bytes may have decreased and describes
+ *          the length of the area that can be written to.
+ *
+ *  -errno: in error cases
+ *
+ * TODO Get rid of keep_clusters, nb_clusters parameters
+ * TODO Make bytes behave like described above
+ * TODO Make non-zero host_offset behave like describe above
+ */
+static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
+    uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m,
+    unsigned int *keep_clusters, unsigned int *nb_clusters)
+{
+    BDRVQcowState *s = bs->opaque;
+    int l2_index;
+    uint64_t cluster_offset;
+    uint64_t *l2_table;
+    int ret, pret;
+
+    trace_qcow2_handle_copied(qemu_coroutine_self(), guest_offset, *host_offset,
+                              *bytes);
+    assert(*host_offset == 0);
+
+    /* Find L2 entry for the first involved cluster */
+    ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
+    if (ret < 0) {
+        return ret;
+    }
+
+    cluster_offset = be64_to_cpu(l2_table[l2_index]);
+
+    /* Check how many clusters are already allocated and don't need COW */
+    if (qcow2_get_cluster_type(cluster_offset) == QCOW2_CLUSTER_NORMAL
+        && (cluster_offset & QCOW_OFLAG_COPIED))
+    {
+        /* We keep all QCOW_OFLAG_COPIED clusters */
+        *keep_clusters =
+            count_contiguous_clusters(*nb_clusters, s->cluster_size,
+                                      &l2_table[l2_index], 0,
+                                      QCOW_OFLAG_COPIED | QCOW_OFLAG_ZERO);
+        assert(*keep_clusters <= *nb_clusters);
+        *nb_clusters -= *keep_clusters;
+
+        ret = 1;
+    } else {
+        *keep_clusters = 0;
+        cluster_offset = 0;
+
+        ret = 0;
+    }
+
+    cluster_offset &= L2E_OFFSET_MASK;
+    *host_offset = cluster_offset;
+
+    /* Cleanup */
+    pret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
+    if (pret < 0) {
+        return pret;
+    }
+
+    return ret;
+}
+
+/*
  * Allocates new clusters for the given guest_offset.
  *
  * At most *nb_clusters are allocated, and on return *nb_clusters is updated to
@@ -1023,7 +1101,6 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index, ret, sectors;
-    uint64_t *l2_table;
     unsigned int nb_clusters, keep_clusters;
     uint64_t cluster_offset;
     uint64_t cur_bytes;
@@ -1032,6 +1109,9 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
                                       n_start, n_end);
 
 again:
+    cluster_offset = 0;
+    *host_offset = 0;
+
     /*
      * Calculate the number of clusters to look for. We stop at L2 table
      * boundaries to keep things simple.
@@ -1057,12 +1137,6 @@ again:
      *         allocation ends. Shorten the COW of the in-fight allocation, set
      *         cluster_offset to write to the same cluster and set up the right
      *         synchronisation between the in-flight request and the new one.
-     *
-     * 2. Count contiguous COPIED clusters.
-     *    TODO: Consider cluster_offset if set in step 1c.
-     *
-     * 3. If the request still hasn't completed, allocate new clusters,
-     *    considering any cluster_offset of steps 1c or 2.
      */
     cur_bytes = (n_end - n_start) * BDRV_SECTOR_SIZE;
     ret = handle_dependencies(bs, offset, &cur_bytes);
@@ -1079,43 +1153,19 @@ again:
     nb_clusters = size_to_clusters(s, offset + cur_bytes)
                 - (offset >> s->cluster_bits);
 
-    /* Find L2 entry for the first involved cluster */
-    ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
-    if (ret < 0) {
-        return ret;
-    }
-
-    cluster_offset = be64_to_cpu(l2_table[l2_index]);
-
-    /* Check how many clusters are already allocated and don't need COW */
-    if (qcow2_get_cluster_type(cluster_offset) == QCOW2_CLUSTER_NORMAL
-        && (cluster_offset & QCOW_OFLAG_COPIED))
-    {
-        /* We keep all QCOW_OFLAG_COPIED clusters */
-        keep_clusters =
-            count_contiguous_clusters(nb_clusters, s->cluster_size,
-                                      &l2_table[l2_index], 0,
-                                      QCOW_OFLAG_COPIED | QCOW_OFLAG_ZERO);
-        assert(keep_clusters <= nb_clusters);
-        nb_clusters -= keep_clusters;
-    } else {
-        keep_clusters = 0;
-        cluster_offset = 0;
-    }
-
-    cluster_offset &= L2E_OFFSET_MASK;
-    *host_offset = cluster_offset;
-
     /*
-     * The L2 table isn't used any more after this. As long as the cache works
-     * synchronously, it's important to release it before calling
-     * do_alloc_cluster_offset, which may yield if we need to wait for another
-     * request to complete. If we still had the reference, we could use up the
-     * whole cache with sleeping requests.
+     * 2. Count contiguous COPIED clusters.
+     *    TODO: Consider cluster_offset if set in step 1c.
      */
-    ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
+    uint64_t tmp_bytes = cur_bytes;
+    ret = handle_copied(bs, offset, &cluster_offset, &tmp_bytes, m,
+                        &keep_clusters, &nb_clusters);
     if (ret < 0) {
         return ret;
+    } else if (ret) {
+        if (!*host_offset) {
+            *host_offset = cluster_offset;
+        }
     }
 
     /* If there is something left to allocate, do that now */
@@ -1123,6 +1173,10 @@ again:
         goto done;
     }
 
+    /*
+     * 3. If the request still hasn't completed, allocate new clusters,
+     *    considering any cluster_offset of steps 1c or 2.
+     */
     int alloc_n_start;
     int alloc_n_end;
 
diff --git a/trace-events b/trace-events
index 9511a28..5a6ef4b 100644
--- a/trace-events
+++ b/trace-events
@@ -483,6 +483,7 @@ qcow2_writev_done_part(void *co, int cur_nr_sectors) "co %p cur_nr_sectors %d"
 qcow2_writev_data(void *co, uint64_t offset) "co %p offset %" PRIx64
 
 qcow2_alloc_clusters_offset(void *co, uint64_t offset, int n_start, int n_end) "co %p offet %" PRIx64 " n_start %d n_end %d"
+qcow2_handle_copied(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64
 qcow2_handle_alloc(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64
 qcow2_do_alloc_clusters_offset(void *co, uint64_t guest_offset, uint64_t host_offset, int nb_clusters) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " nb_clusters %d"
 qcow2_cluster_alloc_phys(void *co) "co %p"
commit 83baa9a4719b42bc28d525fa28af643523cc2bf3
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:04 2013 +0100

    qcow2: Clean up handle_alloc()
    
    Things can be simplified a bit now. No semantic changes.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 8ed1f7d..1141483 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -886,7 +886,6 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
     unsigned int nb_clusters;
     int ret;
 
-    uint64_t alloc_offset;
     uint64_t alloc_cluster_offset;
 
     trace_qcow2_handle_alloc(qemu_coroutine_self(), guest_offset, *host_offset,
@@ -928,72 +927,69 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
         return 0;
     }
 
-    /* Calculate start and size of allocation */
-    alloc_offset = guest_offset;
-    alloc_cluster_offset = *host_offset;
-
     /* Allocate, if necessary at a given offset in the image file */
-    ret = do_alloc_cluster_offset(bs, alloc_offset, &alloc_cluster_offset,
+    alloc_cluster_offset = *host_offset;
+    ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset,
                                   &nb_clusters);
     if (ret < 0) {
         goto fail;
     }
 
-    /* save info needed for meta data update */
-    if (nb_clusters > 0) {
-        /*
-         * requested_sectors: Number of sectors from the start of the first
-         * newly allocated cluster to the end of the (possibly shortened
-         * before) write request.
-         *
-         * avail_sectors: Number of sectors from the start of the first
-         * newly allocated to the end of the last newly allocated cluster.
-         *
-         * nb_sectors: The number of sectors from the start of the first
-         * newly allocated cluster to the end of the aread that the write
-         * request actually writes to (excluding COW at the end)
-         */
-        int requested_sectors =
-            (*bytes + offset_into_cluster(s, guest_offset))
-            >> BDRV_SECTOR_BITS;
-        int avail_sectors = nb_clusters
-                            << (s->cluster_bits - BDRV_SECTOR_BITS);
-        int alloc_n_start = offset_into_cluster(s, guest_offset)
-                            >> BDRV_SECTOR_BITS;
-        int nb_sectors = MIN(requested_sectors, avail_sectors);
-
-        if (*host_offset == 0) {
-            *host_offset = alloc_cluster_offset;
-        }
-
-        *m = g_malloc0(sizeof(**m));
-
-        **m = (QCowL2Meta) {
-            .alloc_offset   = alloc_cluster_offset,
-            .offset         = alloc_offset & ~(s->cluster_size - 1),
-            .nb_clusters    = nb_clusters,
-            .nb_available   = nb_sectors,
-
-            .cow_start = {
-                .offset     = 0,
-                .nb_sectors = alloc_n_start,
-            },
-            .cow_end = {
-                .offset     = nb_sectors * BDRV_SECTOR_SIZE,
-                .nb_sectors = avail_sectors - nb_sectors,
-            },
-        };
-        qemu_co_queue_init(&(*m)->dependent_requests);
-        QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
-
-        *bytes = MIN(*bytes, (nb_sectors * BDRV_SECTOR_SIZE)
-                             - offset_into_cluster(s, guest_offset));
-        assert(*bytes != 0);
-    } else {
+    /* Can't extend contiguous allocation */
+    if (nb_clusters == 0) {
         *bytes = 0;
         return 0;
     }
 
+    /*
+     * Save info needed for meta data update.
+     *
+     * requested_sectors: Number of sectors from the start of the first
+     * newly allocated cluster to the end of the (possibly shortened
+     * before) write request.
+     *
+     * avail_sectors: Number of sectors from the start of the first
+     * newly allocated to the end of the last newly allocated cluster.
+     *
+     * nb_sectors: The number of sectors from the start of the first
+     * newly allocated cluster to the end of the area that the write
+     * request actually writes to (excluding COW at the end)
+     */
+    int requested_sectors =
+        (*bytes + offset_into_cluster(s, guest_offset))
+        >> BDRV_SECTOR_BITS;
+    int avail_sectors = nb_clusters
+                        << (s->cluster_bits - BDRV_SECTOR_BITS);
+    int alloc_n_start = offset_into_cluster(s, guest_offset)
+                        >> BDRV_SECTOR_BITS;
+    int nb_sectors = MIN(requested_sectors, avail_sectors);
+
+    *host_offset = alloc_cluster_offset;
+
+    *m = g_malloc0(sizeof(**m));
+
+    **m = (QCowL2Meta) {
+        .alloc_offset   = *host_offset,
+        .offset         = start_of_cluster(s, guest_offset),
+        .nb_clusters    = nb_clusters,
+        .nb_available   = nb_sectors,
+
+        .cow_start = {
+            .offset     = 0,
+            .nb_sectors = alloc_n_start,
+        },
+        .cow_end = {
+            .offset     = nb_sectors * BDRV_SECTOR_SIZE,
+            .nb_sectors = avail_sectors - nb_sectors,
+        },
+    };
+    qemu_co_queue_init(&(*m)->dependent_requests);
+    QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
+
+    *bytes = MIN(*bytes, (nb_sectors * BDRV_SECTOR_SIZE)
+                         - offset_into_cluster(s, guest_offset));
+    assert(*bytes != 0);
+
     return 1;
 
 fail:
commit c37f4cd71d99b7658d238bd8399048fc6e506958
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:03 2013 +0100

    qcow2: Finalise interface of handle_alloc()
    
    The interface works completely on a byte granularity now and duplicated
    parameters are removed.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 8f4ef0d..8ed1f7d 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -875,13 +875,9 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
  *          newly allocated cluster.
  *
  *  -errno: in error cases
- *
- * TODO Get rid of n_start, n_end
- * TODO Make *bytes actually behave as specified above
  */
 static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
-    uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m,
-    int n_start, int n_end)
+    uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index;
@@ -901,8 +897,11 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
      * Calculate the number of clusters to look for. We stop at L2 table
      * boundaries to keep things simple.
      */
+    nb_clusters =
+        size_to_clusters(s, offset_into_cluster(s, guest_offset) + *bytes);
+
     l2_index = offset_to_l2_index(s, guest_offset);
-    nb_clusters = MIN(size_to_clusters(s, *bytes), s->l2_size - l2_index);
+    nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
 
     /* Find L2 entry for the first involved cluster */
     ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
@@ -954,10 +953,13 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
          * newly allocated cluster to the end of the aread that the write
          * request actually writes to (excluding COW at the end)
          */
-        int requested_sectors = n_end;
+        int requested_sectors =
+            (*bytes + offset_into_cluster(s, guest_offset))
+            >> BDRV_SECTOR_BITS;
         int avail_sectors = nb_clusters
                             << (s->cluster_bits - BDRV_SECTOR_BITS);
-        int alloc_n_start = *host_offset == 0 ? n_start : 0;
+        int alloc_n_start = offset_into_cluster(s, guest_offset)
+                            >> BDRV_SECTOR_BITS;
         int nb_sectors = MIN(requested_sectors, avail_sectors);
 
         if (*host_offset == 0) {
@@ -984,7 +986,9 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
         qemu_co_queue_init(&(*m)->dependent_requests);
         QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
 
-        *bytes = nb_clusters * s->cluster_size;
+        *bytes = MIN(*bytes, (nb_sectors * BDRV_SECTOR_SIZE)
+                             - offset_into_cluster(s, guest_offset));
+        assert(*bytes != 0);
     } else {
         *bytes = 0;
         return 0;
@@ -1139,10 +1143,9 @@ again:
         alloc_n_end = n_end;
     }
 
-    cur_bytes = nb_clusters * s->cluster_size;
+    cur_bytes = MIN(cur_bytes, ((alloc_n_end - alloc_n_start) << BDRV_SECTOR_BITS));
 
-    ret = handle_alloc(bs, offset, &cluster_offset, &cur_bytes, m,
-                       alloc_n_start, alloc_n_end);
+    ret = handle_alloc(bs, offset, &cluster_offset, &cur_bytes, m);
     if (ret < 0) {
         return ret;
     }
@@ -1150,7 +1153,7 @@ again:
     if (!*host_offset) {
         *host_offset = cluster_offset;
     }
-    nb_clusters = size_to_clusters(s, cur_bytes);
+    nb_clusters = size_to_clusters(s, cur_bytes + offset_into_cluster(s, offset));
 
     /* Some cleanup work */
 done:
diff --git a/block/qcow2.h b/block/qcow2.h
index c4eaf67..32806bd 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -271,6 +271,11 @@ static inline int64_t start_of_cluster(BDRVQcowState *s, int64_t offset)
     return offset & ~(s->cluster_size - 1);
 }
 
+static inline int64_t offset_into_cluster(BDRVQcowState *s, int64_t offset)
+{
+    return offset & (s->cluster_size - 1);
+}
+
 static inline int size_to_clusters(BDRVQcowState *s, int64_t size)
 {
     return (size + (s->cluster_size - 1)) >> s->cluster_bits;
commit 3b8e2e260c8cee63c9253718983a6682dc2771d7
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:02 2013 +0100

    qcow2: handle_alloc(): Get rid of keep_clusters parameter
    
    handle_alloc() is now called with the offset at which the actual new
    allocation starts instead of the offset at which the whole write request
    starts, part of which may already be processed.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 009f62a..8f4ef0d 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -876,12 +876,12 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
  *
  *  -errno: in error cases
  *
- * TODO Get rid of keep_clusters, n_start, n_end
+ * TODO Get rid of n_start, n_end
  * TODO Make *bytes actually behave as specified above
  */
 static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
     uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m,
-    int keep_clusters, int n_start, int n_end)
+    int n_start, int n_end)
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index;
@@ -892,7 +892,6 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
 
     uint64_t alloc_offset;
     uint64_t alloc_cluster_offset;
-    uint64_t keep_bytes = keep_clusters * s->cluster_size;
 
     trace_qcow2_handle_alloc(qemu_coroutine_self(), guest_offset, *host_offset,
                              *bytes);
@@ -911,14 +910,13 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
         return ret;
     }
 
-    entry = be64_to_cpu(l2_table[l2_index + keep_clusters]);
+    entry = be64_to_cpu(l2_table[l2_index]);
 
     /* For the moment, overwrite compressed clusters one by one */
     if (entry & QCOW_OFLAG_COMPRESSED) {
         nb_clusters = 1;
     } else {
-        nb_clusters = count_cow_clusters(s, nb_clusters, l2_table,
-                                         l2_index + keep_clusters);
+        nb_clusters = count_cow_clusters(s, nb_clusters, l2_table, l2_index);
     }
 
     ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
@@ -932,13 +930,8 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
     }
 
     /* Calculate start and size of allocation */
-    alloc_offset = guest_offset + keep_bytes;
-
-    if (keep_clusters == 0) {
-        alloc_cluster_offset = 0;
-    } else {
-        alloc_cluster_offset = *host_offset + keep_bytes;
-    }
+    alloc_offset = guest_offset;
+    alloc_cluster_offset = *host_offset;
 
     /* Allocate, if necessary at a given offset in the image file */
     ret = do_alloc_cluster_offset(bs, alloc_offset, &alloc_cluster_offset,
@@ -961,13 +954,13 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
          * newly allocated cluster to the end of the aread that the write
          * request actually writes to (excluding COW at the end)
          */
-        int requested_sectors = n_end - keep_clusters * s->cluster_sectors;
+        int requested_sectors = n_end;
         int avail_sectors = nb_clusters
                             << (s->cluster_bits - BDRV_SECTOR_BITS);
-        int alloc_n_start = keep_clusters == 0 ? n_start : 0;
+        int alloc_n_start = *host_offset == 0 ? n_start : 0;
         int nb_sectors = MIN(requested_sectors, avail_sectors);
 
-        if (keep_clusters == 0) {
+        if (*host_offset == 0) {
             *host_offset = alloc_cluster_offset;
         }
 
@@ -1130,9 +1123,26 @@ again:
         goto done;
     }
 
+    int alloc_n_start;
+    int alloc_n_end;
+
+    if (keep_clusters != 0) {
+        offset         = start_of_cluster(s, offset
+                                             + keep_clusters * s->cluster_size);
+        cluster_offset = start_of_cluster(s, cluster_offset
+                                             + keep_clusters * s->cluster_size);
+
+        alloc_n_start = 0;
+        alloc_n_end = n_end - keep_clusters * s->cluster_sectors;
+    } else {
+        alloc_n_start = n_start;
+        alloc_n_end = n_end;
+    }
+
     cur_bytes = nb_clusters * s->cluster_size;
+
     ret = handle_alloc(bs, offset, &cluster_offset, &cur_bytes, m,
-                       keep_clusters, n_start, n_end);
+                       alloc_n_start, alloc_n_end);
     if (ret < 0) {
         return ret;
     }
diff --git a/block/qcow2.h b/block/qcow2.h
index a99d51b..c4eaf67 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -266,6 +266,11 @@ enum {
 
 #define REFT_OFFSET_MASK 0xffffffffffffff00ULL
 
+static inline int64_t start_of_cluster(BDRVQcowState *s, int64_t offset)
+{
+    return offset & ~(s->cluster_size - 1);
+}
+
 static inline int size_to_clusters(BDRVQcowState *s, int64_t size)
 {
     return (size + (s->cluster_size - 1)) >> s->cluster_bits;
commit f5bc63509471299176066d5f63bb8ff2e15af279
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:01 2013 +0100

    qcow2: handle_alloc(): Get rid of nb_clusters parameter
    
    We already communicate the same information in *bytes.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 454a30c..009f62a 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -876,17 +876,18 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
  *
  *  -errno: in error cases
  *
- * TODO Get rid of nb_clusters, keep_clusters, n_start, n_end
+ * TODO Get rid of keep_clusters, n_start, n_end
  * TODO Make *bytes actually behave as specified above
  */
 static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
     uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m,
-    unsigned int nb_clusters, int keep_clusters, int n_start, int n_end)
+    int keep_clusters, int n_start, int n_end)
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index;
     uint64_t *l2_table;
     uint64_t entry;
+    unsigned int nb_clusters;
     int ret;
 
     uint64_t alloc_offset;
@@ -897,6 +898,13 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
                              *bytes);
     assert(*bytes > 0);
 
+    /*
+     * Calculate the number of clusters to look for. We stop at L2 table
+     * boundaries to keep things simple.
+     */
+    l2_index = offset_to_l2_index(s, guest_offset);
+    nb_clusters = MIN(size_to_clusters(s, *bytes), s->l2_size - l2_index);
+
     /* Find L2 entry for the first involved cluster */
     ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
     if (ret < 0) {
@@ -1103,6 +1111,7 @@ again:
     }
 
     cluster_offset &= L2E_OFFSET_MASK;
+    *host_offset = cluster_offset;
 
     /*
      * The L2 table isn't used any more after this. As long as the cache works
@@ -1123,11 +1132,14 @@ again:
 
     cur_bytes = nb_clusters * s->cluster_size;
     ret = handle_alloc(bs, offset, &cluster_offset, &cur_bytes, m,
-                       nb_clusters, keep_clusters, n_start, n_end);
+                       keep_clusters, n_start, n_end);
     if (ret < 0) {
         return ret;
     }
 
+    if (!*host_offset) {
+        *host_offset = cluster_offset;
+    }
     nb_clusters = size_to_clusters(s, cur_bytes);
 
     /* Some cleanup work */
@@ -1139,7 +1151,6 @@ done:
 
     assert(sectors > n_start);
     *num = sectors - n_start;
-    *host_offset = cluster_offset;
 
     return 0;
 }
commit 10f0ed8b2f0d3e9f0476b6f00868dd13b524066a
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:00 2013 +0100

    qcow2: Factor out handle_alloc()
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 9550927..454a30c 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -859,6 +859,146 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
 }
 
 /*
+ * Allocates new clusters for an area that either is yet unallocated or needs a
+ * copy on write. If *host_offset is non-zero, clusters are only allocated if
+ * the new allocation can match the specified host offset.
+ *
+ * Note that guest_offset may not be cluster aligned.
+ *
+ * Returns:
+ *   0:     if no clusters could be allocated. *bytes is set to 0,
+ *          *host_offset is left unchanged.
+ *
+ *   1:     if new clusters were allocated. *bytes may be decreased if the
+ *          new allocation doesn't cover all of the requested area.
+ *          *host_offset is updated to contain the host offset of the first
+ *          newly allocated cluster.
+ *
+ *  -errno: in error cases
+ *
+ * TODO Get rid of nb_clusters, keep_clusters, n_start, n_end
+ * TODO Make *bytes actually behave as specified above
+ */
+static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
+    uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m,
+    unsigned int nb_clusters, int keep_clusters, int n_start, int n_end)
+{
+    BDRVQcowState *s = bs->opaque;
+    int l2_index;
+    uint64_t *l2_table;
+    uint64_t entry;
+    int ret;
+
+    uint64_t alloc_offset;
+    uint64_t alloc_cluster_offset;
+    uint64_t keep_bytes = keep_clusters * s->cluster_size;
+
+    trace_qcow2_handle_alloc(qemu_coroutine_self(), guest_offset, *host_offset,
+                             *bytes);
+    assert(*bytes > 0);
+
+    /* Find L2 entry for the first involved cluster */
+    ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
+    if (ret < 0) {
+        return ret;
+    }
+
+    entry = be64_to_cpu(l2_table[l2_index + keep_clusters]);
+
+    /* For the moment, overwrite compressed clusters one by one */
+    if (entry & QCOW_OFLAG_COMPRESSED) {
+        nb_clusters = 1;
+    } else {
+        nb_clusters = count_cow_clusters(s, nb_clusters, l2_table,
+                                         l2_index + keep_clusters);
+    }
+
+    ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
+    if (ret < 0) {
+        return ret;
+    }
+
+    if (nb_clusters == 0) {
+        *bytes = 0;
+        return 0;
+    }
+
+    /* Calculate start and size of allocation */
+    alloc_offset = guest_offset + keep_bytes;
+
+    if (keep_clusters == 0) {
+        alloc_cluster_offset = 0;
+    } else {
+        alloc_cluster_offset = *host_offset + keep_bytes;
+    }
+
+    /* Allocate, if necessary at a given offset in the image file */
+    ret = do_alloc_cluster_offset(bs, alloc_offset, &alloc_cluster_offset,
+                                  &nb_clusters);
+    if (ret < 0) {
+        goto fail;
+    }
+
+    /* save info needed for meta data update */
+    if (nb_clusters > 0) {
+        /*
+         * requested_sectors: Number of sectors from the start of the first
+         * newly allocated cluster to the end of the (possibly shortened
+         * before) write request.
+         *
+         * avail_sectors: Number of sectors from the start of the first
+         * newly allocated to the end of the last newly allocated cluster.
+         *
+         * nb_sectors: The number of sectors from the start of the first
+         * newly allocated cluster to the end of the aread that the write
+         * request actually writes to (excluding COW at the end)
+         */
+        int requested_sectors = n_end - keep_clusters * s->cluster_sectors;
+        int avail_sectors = nb_clusters
+                            << (s->cluster_bits - BDRV_SECTOR_BITS);
+        int alloc_n_start = keep_clusters == 0 ? n_start : 0;
+        int nb_sectors = MIN(requested_sectors, avail_sectors);
+
+        if (keep_clusters == 0) {
+            *host_offset = alloc_cluster_offset;
+        }
+
+        *m = g_malloc0(sizeof(**m));
+
+        **m = (QCowL2Meta) {
+            .alloc_offset   = alloc_cluster_offset,
+            .offset         = alloc_offset & ~(s->cluster_size - 1),
+            .nb_clusters    = nb_clusters,
+            .nb_available   = nb_sectors,
+
+            .cow_start = {
+                .offset     = 0,
+                .nb_sectors = alloc_n_start,
+            },
+            .cow_end = {
+                .offset     = nb_sectors * BDRV_SECTOR_SIZE,
+                .nb_sectors = avail_sectors - nb_sectors,
+            },
+        };
+        qemu_co_queue_init(&(*m)->dependent_requests);
+        QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
+
+        *bytes = nb_clusters * s->cluster_size;
+    } else {
+        *bytes = 0;
+        return 0;
+    }
+
+    return 1;
+
+fail:
+    if (*m && (*m)->nb_clusters > 0) {
+        QLIST_REMOVE(*m, next_in_flight);
+    }
+    return ret;
+}
+
+/*
  * alloc_cluster_offset
  *
  * For a given offset on the virtual disk, find the cluster offset in qcow2
@@ -977,93 +1117,21 @@ again:
     }
 
     /* If there is something left to allocate, do that now */
-    if (nb_clusters > 0) {
-        uint64_t alloc_offset;
-        uint64_t alloc_cluster_offset;
-        uint64_t keep_bytes = keep_clusters * s->cluster_size;
-
-        ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
-        if (ret < 0) {
-            return ret;
-        }
-
-        /* For the moment, overwrite compressed clusters one by one */
-        uint64_t entry = be64_to_cpu(l2_table[l2_index + keep_clusters]);
-        if (entry & QCOW_OFLAG_COMPRESSED) {
-            nb_clusters = 1;
-        } else {
-            nb_clusters = count_cow_clusters(s, nb_clusters, l2_table,
-                                             l2_index + keep_clusters);
-        }
-
-        ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
-        if (ret < 0) {
-            return ret;
-        }
-
-        /* Calculate start and size of allocation */
-        alloc_offset = offset + keep_bytes;
-
-        if (keep_clusters == 0) {
-            alloc_cluster_offset = 0;
-        } else {
-            alloc_cluster_offset = cluster_offset + keep_bytes;
-        }
-
-        /* Allocate, if necessary at a given offset in the image file */
-        ret = do_alloc_cluster_offset(bs, alloc_offset, &alloc_cluster_offset,
-                                      &nb_clusters);
-        if (ret < 0) {
-            goto fail;
-        }
-
-        /* save info needed for meta data update */
-        if (nb_clusters > 0) {
-            /*
-             * requested_sectors: Number of sectors from the start of the first
-             * newly allocated cluster to the end of the (possibly shortened
-             * before) write request.
-             *
-             * avail_sectors: Number of sectors from the start of the first
-             * newly allocated to the end of the last newly allocated cluster.
-             *
-             * nb_sectors: The number of sectors from the start of the first
-             * newly allocated cluster to the end of the aread that the write
-             * request actually writes to (excluding COW at the end)
-             */
-            int requested_sectors = n_end - keep_clusters * s->cluster_sectors;
-            int avail_sectors = nb_clusters
-                                << (s->cluster_bits - BDRV_SECTOR_BITS);
-            int alloc_n_start = keep_clusters == 0 ? n_start : 0;
-            int nb_sectors = MIN(requested_sectors, avail_sectors);
-
-            if (keep_clusters == 0) {
-                cluster_offset = alloc_cluster_offset;
-            }
+    if (nb_clusters == 0) {
+        goto done;
+    }
 
-            *m = g_malloc0(sizeof(**m));
-
-            **m = (QCowL2Meta) {
-                .alloc_offset   = alloc_cluster_offset,
-                .offset         = alloc_offset & ~(s->cluster_size - 1),
-                .nb_clusters    = nb_clusters,
-                .nb_available   = nb_sectors,
-
-                .cow_start = {
-                    .offset     = 0,
-                    .nb_sectors = alloc_n_start,
-                },
-                .cow_end = {
-                    .offset     = nb_sectors * BDRV_SECTOR_SIZE,
-                    .nb_sectors = avail_sectors - nb_sectors,
-                },
-            };
-            qemu_co_queue_init(&(*m)->dependent_requests);
-            QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
-        }
+    cur_bytes = nb_clusters * s->cluster_size;
+    ret = handle_alloc(bs, offset, &cluster_offset, &cur_bytes, m,
+                       nb_clusters, keep_clusters, n_start, n_end);
+    if (ret < 0) {
+        return ret;
     }
 
+    nb_clusters = size_to_clusters(s, cur_bytes);
+
     /* Some cleanup work */
+done:
     sectors = (keep_clusters + nb_clusters) << (s->cluster_bits - 9);
     if (sectors > n_end) {
         sectors = n_end;
@@ -1074,12 +1142,6 @@ again:
     *host_offset = cluster_offset;
 
     return 0;
-
-fail:
-    if (*m && (*m)->nb_clusters > 0) {
-        QLIST_REMOVE(*m, next_in_flight);
-    }
-    return ret;
 }
 
 static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
diff --git a/trace-events b/trace-events
index 406fe5f..9511a28 100644
--- a/trace-events
+++ b/trace-events
@@ -483,6 +483,7 @@ qcow2_writev_done_part(void *co, int cur_nr_sectors) "co %p cur_nr_sectors %d"
 qcow2_writev_data(void *co, uint64_t offset) "co %p offset %" PRIx64
 
 qcow2_alloc_clusters_offset(void *co, uint64_t offset, int n_start, int n_end) "co %p offet %" PRIx64 " n_start %d n_end %d"
+qcow2_handle_alloc(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64
 qcow2_do_alloc_clusters_offset(void *co, uint64_t guest_offset, uint64_t host_offset, int nb_clusters) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " nb_clusters %d"
 qcow2_cluster_alloc_phys(void *co) "co %p"
 qcow2_cluster_link_l2(void *co, int nb_clusters) "co %p nb_clusters %d"
commit 037689d8969c493d39153fd920ad81e161b0d55c
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:49:59 2013 +0100

    qcow2: Decouple cluster allocation from cluster reuse code
    
    This moves some code that prepares the allocation of new clusters to
    where the actual allocation happens. This is the minimum required to be
    able to move it to a separate function in the next patch.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 202adb4..9550927 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -946,10 +946,7 @@ again:
 
     cluster_offset = be64_to_cpu(l2_table[l2_index]);
 
-    /*
-     * Check how many clusters are already allocated and don't need COW, and how
-     * many need a new allocation.
-     */
+    /* Check how many clusters are already allocated and don't need COW */
     if (qcow2_get_cluster_type(cluster_offset) == QCOW2_CLUSTER_NORMAL
         && (cluster_offset & QCOW_OFLAG_COPIED))
     {
@@ -965,17 +962,6 @@ again:
         cluster_offset = 0;
     }
 
-    if (nb_clusters > 0) {
-        /* For the moment, overwrite compressed clusters one by one */
-        uint64_t entry = be64_to_cpu(l2_table[l2_index + keep_clusters]);
-        if (entry & QCOW_OFLAG_COMPRESSED) {
-            nb_clusters = 1;
-        } else {
-            nb_clusters = count_cow_clusters(s, nb_clusters, l2_table,
-                                             l2_index + keep_clusters);
-        }
-    }
-
     cluster_offset &= L2E_OFFSET_MASK;
 
     /*
@@ -996,6 +982,25 @@ again:
         uint64_t alloc_cluster_offset;
         uint64_t keep_bytes = keep_clusters * s->cluster_size;
 
+        ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
+        if (ret < 0) {
+            return ret;
+        }
+
+        /* For the moment, overwrite compressed clusters one by one */
+        uint64_t entry = be64_to_cpu(l2_table[l2_index + keep_clusters]);
+        if (entry & QCOW_OFLAG_COMPRESSED) {
+            nb_clusters = 1;
+        } else {
+            nb_clusters = count_cow_clusters(s, nb_clusters, l2_table,
+                                             l2_index + keep_clusters);
+        }
+
+        ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
+        if (ret < 0) {
+            return ret;
+        }
+
         /* Calculate start and size of allocation */
         alloc_offset = offset + keep_bytes;
 
commit 65eb2e35c07632eb5d26f15a57461e321bacb883
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:49:58 2013 +0100

    qcow2: Change handle_dependency to byte granularity
    
    This is a more precise description of what really constitutes a
    dependency. The behaviour doesn't change at this point because the COW
    area of the old request is still aligned to cluster boundaries and
    therefore an overlap is detected wheneven the requests touch any part of
    the same cluster.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 7f4f73e..202adb4 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -759,31 +759,41 @@ out:
  * Check if there already is an AIO write request in flight which allocates
  * the same cluster. In this case we need to wait until the previous
  * request has completed and updated the L2 table accordingly.
+ *
+ * Returns:
+ *   0       if there was no dependency. *cur_bytes indicates the number of
+ *           bytes from guest_offset that can be read before the next
+ *           dependency must be processed (or the request is complete)
+ *
+ *   -EAGAIN if we had to wait for another request, previously gathered
+ *           information on cluster allocation may be invalid now. The caller
+ *           must start over anyway, so consider *cur_bytes undefined.
  */
 static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
-    unsigned int *nb_clusters)
+    uint64_t *cur_bytes)
 {
     BDRVQcowState *s = bs->opaque;
     QCowL2Meta *old_alloc;
+    uint64_t bytes = *cur_bytes;
 
     QLIST_FOREACH(old_alloc, &s->cluster_allocs, next_in_flight) {
 
-        uint64_t start = guest_offset >> s->cluster_bits;
-        uint64_t end = start + *nb_clusters;
-        uint64_t old_start = old_alloc->offset >> s->cluster_bits;
-        uint64_t old_end = old_start + old_alloc->nb_clusters;
+        uint64_t start = guest_offset;
+        uint64_t end = start + bytes;
+        uint64_t old_start = l2meta_cow_start(old_alloc);
+        uint64_t old_end = l2meta_cow_end(old_alloc);
 
         if (end <= old_start || start >= old_end) {
             /* No intersection */
         } else {
             if (start < old_start) {
                 /* Stop at the start of a running allocation */
-                *nb_clusters = old_start - start;
+                bytes = old_start - start;
             } else {
-                *nb_clusters = 0;
+                bytes = 0;
             }
 
-            if (*nb_clusters == 0) {
+            if (bytes == 0) {
                 /* Wait for the dependency to complete. We need to recheck
                  * the free/allocated clusters when we continue. */
                 qemu_co_mutex_unlock(&s->lock);
@@ -794,9 +804,9 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
         }
     }
 
-    if (!*nb_clusters) {
-        abort();
-    }
+    /* Make sure that existing clusters and new allocations are only used up to
+     * the next dependency if we shortened the request above */
+    *cur_bytes = bytes;
 
     return 0;
 }
@@ -875,6 +885,7 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
     uint64_t *l2_table;
     unsigned int nb_clusters, keep_clusters;
     uint64_t cluster_offset;
+    uint64_t cur_bytes;
 
     trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset,
                                       n_start, n_end);
@@ -887,6 +898,7 @@ again:
     l2_index = offset_to_l2_index(s, offset);
     nb_clusters = MIN(size_to_clusters(s, n_end << BDRV_SECTOR_BITS),
                       s->l2_size - l2_index);
+    n_end = MIN(n_end, nb_clusters * s->cluster_sectors);
 
     /*
      * Now start gathering as many contiguous clusters as possible:
@@ -911,7 +923,8 @@ again:
      * 3. If the request still hasn't completed, allocate new clusters,
      *    considering any cluster_offset of steps 1c or 2.
      */
-    ret = handle_dependencies(bs, offset, &nb_clusters);
+    cur_bytes = (n_end - n_start) * BDRV_SECTOR_SIZE;
+    ret = handle_dependencies(bs, offset, &cur_bytes);
     if (ret == -EAGAIN) {
         goto again;
     } else if (ret < 0) {
@@ -922,6 +935,9 @@ again:
          * correctly during the next loop iteration. */
     }
 
+    nb_clusters = size_to_clusters(s, offset + cur_bytes)
+                - (offset >> s->cluster_bits);
+
     /* Find L2 entry for the first involved cluster */
     ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
     if (ret < 0) {
diff --git a/block/qcow2.h b/block/qcow2.h
index 0940b1b..a99d51b 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -307,6 +307,17 @@ static inline bool qcow2_need_accurate_refcounts(BDRVQcowState *s)
     return !(s->incompatible_features & QCOW2_INCOMPAT_DIRTY);
 }
 
+static inline uint64_t l2meta_cow_start(QCowL2Meta *m)
+{
+    return m->offset + m->cow_start.offset;
+}
+
+static inline uint64_t l2meta_cow_end(QCowL2Meta *m)
+{
+    return m->offset + m->cow_end.offset
+        + (m->cow_end.nb_sectors << BDRV_SECTOR_BITS);
+}
+
 // FIXME Need qcow2_ prefix to global functions
 
 /* qcow2.c functions */
commit d9d74f4177af59bec23baa480d640709f56df0aa
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:49:57 2013 +0100

    qcow2: Improve check for overlapping allocations
    
    The old code detected an overlapping allocation even when the
    allocations didn't actually overlap, but were only adjacent.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 71e027a..7f4f73e 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -773,7 +773,7 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
         uint64_t old_start = old_alloc->offset >> s->cluster_bits;
         uint64_t old_end = old_start + old_alloc->nb_clusters;
 
-        if (end < old_start || start > old_end) {
+        if (end <= old_start || start >= old_end) {
             /* No intersection */
         } else {
             if (start < old_start) {
diff --git a/tests/qemu-iotests/038.out b/tests/qemu-iotests/038.out
index acc7629..9cd0cd8 100644
--- a/tests/qemu-iotests/038.out
+++ b/tests/qemu-iotests/038.out
@@ -517,9 +517,7 @@ qemu-io> wrote 65536/65536 bytes at offset 16711680
 qemu-io> Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' 
 
 == Some concurrent requests touching the same cluster ==
-qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> wrote 81920/81920 bytes at offset XXX
-80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-wrote 65536/65536 bytes at offset XXX
+qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -579,6 +577,8 @@ wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset XXX
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 65536/65536 bytes at offset XXX
@@ -645,6 +645,8 @@ wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset XXX
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 65536/65536 bytes at offset XXX
@@ -703,8 +705,6 @@ wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-wrote 81920/81920 bytes at offset XXX
-80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
 == Verify image content ==
 qemu-io> read 4096/4096 bytes at offset 2064384
commit 17a71e58238138c3f02be7e9f5dc8de5d72a9a9d
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:49:56 2013 +0100

    qcow2: Handle dependencies earlier
    
    Handling overlapping allocations isn't just a detail of cluster
    allocation. It is rather one of three ways to get the host cluster
    offset for a write request:
    
    1. If a request overlaps an in-flight allocations, the cluster offset
       can be taken from there (this is what handle_dependencies will evolve
       into) or the request must just wait until the allocation has
       completed. Accessing the L2 is not valid in this case, it has
       outdated information.
    
    2. Outside overlapping areas, check the clusters that can be written to
       as they are, with no COW involved.
    
    3. If a COW is required, allocate new clusters
    
    Changing the code to reflect this doesn't change the behaviour because
    overlaps cannot exist for clusters that are kept in step 2. It does
    however make it easier for later patches to work on clusters that belong
    to an allocation that is still in flight.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index d72d063..71e027a 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -824,16 +824,10 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
     uint64_t *host_offset, unsigned int *nb_clusters)
 {
     BDRVQcowState *s = bs->opaque;
-    int ret;
 
     trace_qcow2_do_alloc_clusters_offset(qemu_coroutine_self(), guest_offset,
                                          *host_offset, *nb_clusters);
 
-    ret = handle_dependencies(bs, guest_offset, nb_clusters);
-    if (ret < 0) {
-        return ret;
-    }
-
     /* Allocate new clusters */
     trace_qcow2_cluster_alloc_phys(qemu_coroutine_self());
     if (*host_offset == 0) {
@@ -845,7 +839,7 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
         *host_offset = cluster_offset;
         return 0;
     } else {
-        ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters);
+        int ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters);
         if (ret < 0) {
             return ret;
         }
@@ -885,20 +879,55 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
     trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset,
                                       n_start, n_end);
 
-    /* Find L2 entry for the first involved cluster */
 again:
-    ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
-    if (ret < 0) {
-        return ret;
-    }
-
     /*
      * Calculate the number of clusters to look for. We stop at L2 table
      * boundaries to keep things simple.
      */
+    l2_index = offset_to_l2_index(s, offset);
     nb_clusters = MIN(size_to_clusters(s, n_end << BDRV_SECTOR_BITS),
                       s->l2_size - l2_index);
 
+    /*
+     * Now start gathering as many contiguous clusters as possible:
+     *
+     * 1. Check for overlaps with in-flight allocations
+     *
+     *      a) Overlap not in the first cluster -> shorten this request and let
+     *         the caller handle the rest in its next loop iteration.
+     *
+     *      b) Real overlaps of two requests. Yield and restart the search for
+     *         contiguous clusters (the situation could have changed while we
+     *         were sleeping)
+     *
+     *      c) TODO: Request starts in the same cluster as the in-flight
+     *         allocation ends. Shorten the COW of the in-fight allocation, set
+     *         cluster_offset to write to the same cluster and set up the right
+     *         synchronisation between the in-flight request and the new one.
+     *
+     * 2. Count contiguous COPIED clusters.
+     *    TODO: Consider cluster_offset if set in step 1c.
+     *
+     * 3. If the request still hasn't completed, allocate new clusters,
+     *    considering any cluster_offset of steps 1c or 2.
+     */
+    ret = handle_dependencies(bs, offset, &nb_clusters);
+    if (ret == -EAGAIN) {
+        goto again;
+    } else if (ret < 0) {
+        return ret;
+    } else {
+        /* handle_dependencies() may have decreased cur_bytes (shortened
+         * the allocations below) so that the next dependency is processed
+         * correctly during the next loop iteration. */
+    }
+
+    /* Find L2 entry for the first involved cluster */
+    ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
+    if (ret < 0) {
+        return ret;
+    }
+
     cluster_offset = be64_to_cpu(l2_table[l2_index]);
 
     /*
@@ -963,9 +992,7 @@ again:
         /* Allocate, if necessary at a given offset in the image file */
         ret = do_alloc_cluster_offset(bs, alloc_offset, &alloc_cluster_offset,
                                       &nb_clusters);
-        if (ret == -EAGAIN) {
-            goto again;
-        } else if (ret < 0) {
+        if (ret < 0) {
             goto fail;
         }
 
diff --git a/block/qcow2.h b/block/qcow2.h
index e4b5e11..0940b1b 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -277,6 +277,11 @@ static inline int size_to_l1(BDRVQcowState *s, int64_t size)
     return (size + (1ULL << shift) - 1) >> shift;
 }
 
+static inline int offset_to_l2_index(BDRVQcowState *s, int64_t offset)
+{
+    return (offset >> s->cluster_bits) & (s->l2_size - 1);
+}
+
 static inline int64_t align_offset(int64_t offset, int n)
 {
     offset = (offset + n - 1) & ~(n - 1);
commit 9ee6439e27d15c528fde6d9da1e4c238a23b6b7a
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:49:55 2013 +0100

    qcow2: Remove bogus unlock of s->lock
    
    The unlock wakes up the next coroutine, but the currently running
    coroutine will lock it again before it yields, so this doesn't make a
    lot of sense.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 8ea696a..3f7edf5 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -869,9 +869,7 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
                 QLIST_REMOVE(l2meta, next_in_flight);
             }
 
-            qemu_co_mutex_unlock(&s->lock);
             qemu_co_queue_restart_all(&l2meta->dependent_requests);
-            qemu_co_mutex_lock(&s->lock);
 
             g_free(l2meta);
             l2meta = NULL;
commit c349ca4bb2dbca53c15147d283ea9f6c94376c6c
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:49:54 2013 +0100

    qcow2: Fix "total clusters" number in bdrv_check
    
    This should be based on the virtual disk size, not on the size of the
    image.
    
    Interesting observation: With some VM state stored in the image file,
    percentages higher than 100% are possible, even though snapshots
    themselves are ignored. This is a qcow2 bug to be fixed another day: The
    VM state should be discarded in the active L2 tables after completing
    the snapshot creation.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 9bfb390..c38e970 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1152,9 +1152,11 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
 
     size = bdrv_getlength(bs->file);
     nb_clusters = size_to_clusters(s, size);
-    res->bfi.total_clusters = nb_clusters;
     refcount_table = g_malloc0(nb_clusters * sizeof(uint16_t));
 
+    res->bfi.total_clusters =
+        size_to_clusters(s, bs->total_sectors * BDRV_SECTOR_SIZE);
+
     /* header */
     inc_refcounts(bs, res, refcount_table, nb_clusters,
         0, s->cluster_size);
diff --git a/tests/qemu-iotests/044.out b/tests/qemu-iotests/044.out
index 5eed3f8..34c25c7 100644
--- a/tests/qemu-iotests/044.out
+++ b/tests/qemu-iotests/044.out
@@ -1,5 +1,5 @@
 No errors were found on the image.
-7292415/8391499= 86.90% allocated, 0.00% fragmented, 0.00% compressed clusters
+7292415/33554432 = 21.73% allocated, 0.00% fragmented, 0.00% compressed clusters
 Image end offset: 4296447488
 .
 ----------------------------------------------------------------------
commit 6f74928192e8e8a16f64b6208171eb13af890bbc
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:49:53 2013 +0100

    qemu-iotests: More concurrent allocation scenarios
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/tests/qemu-iotests/046 b/tests/qemu-iotests/046
index e0176f4..987bfff 100755
--- a/tests/qemu-iotests/046
+++ b/tests/qemu-iotests/046
@@ -66,7 +66,7 @@ function backing_io()
     done
 }
 
-backing_io 0 16 write | $QEMU_IO $TEST_IMG | _filter_qemu_io
+backing_io 0 32 write | $QEMU_IO $TEST_IMG | _filter_qemu_io
 
 mv $TEST_IMG $TEST_IMG.base
 
@@ -153,6 +153,36 @@ aio_write -P 101 0xaa000 0xe000
 resume A
 aio_flush
 EOF
+
+# Reverse sequential write
+cat  <<EOF
+break write_aio A
+aio_write -P 121 0xdc000 0x2000
+wait_break A
+aio_write -P 120 0xc4000 0x18000
+resume A
+aio_flush
+EOF
+
+# Reverse sequential write with a gap
+cat  <<EOF
+break write_aio A
+aio_write -P 141 0xfc000 0x2000
+wait_break A
+aio_write -P 140 0xe4000 0x14000
+resume A
+aio_flush
+EOF
+
+# Allocate an area in the middle and then overwrite with a larger request
+cat  <<EOF
+break write_aio A
+aio_write -P 161 0x10c000 0x8000
+wait_break A
+aio_write -P 160 0x104000 0x18000
+resume A
+aio_flush
+EOF
 }
 
 overlay_io | $QEMU_IO blkdebug::$TEST_IMG | _filter_qemu_io |\
@@ -203,6 +233,23 @@ function verify_io()
     echo read -P 10  0xa8000 0x2000
     echo read -P 101 0xaa000 0xe000
     echo read -P 110 0xb8000 0x8000
+
+    echo read -P 12  0xc0000 0x4000
+    echo read -P 120 0xc4000 0x18000
+    echo read -P 121 0xdc000 0x2000
+    echo read -P 13  0xde000 0x2000
+
+    echo read -P 14  0xe0000 0x4000
+    echo read -P 140 0xe4000 0x14000
+    echo read -P 15  0xf8000 0x4000
+    echo read -P 141 0xfc000 0x2000
+    echo read -P 15  0xfe000 0x2000
+
+    echo read -P 16  0x100000 0x4000
+    echo read -P 160 0x104000 0x8000
+    # Undefined content for 0x10c000 0x8000
+    echo read -P 160 0x114000 0x8000
+    echo read -P 17  0x11c000 0x4000
 }
 
 verify_io | $QEMU_IO $TEST_IMG | _filter_qemu_io
diff --git a/tests/qemu-iotests/046.out b/tests/qemu-iotests/046.out
index 565360f..4b50a17e 100644
--- a/tests/qemu-iotests/046.out
+++ b/tests/qemu-iotests/046.out
@@ -34,6 +34,38 @@ qemu-io> wrote 65536/65536 bytes at offset 917504
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 qemu-io> wrote 65536/65536 bytes at offset 983040
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1048576
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1114112
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1179648
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1245184
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1310720
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1376256
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1441792
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1507328
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1572864
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1638400
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1703936
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1769472
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1835008
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1900544
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1966080
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 2031616
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 qemu-io> Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' 
 
 == Some concurrent requests touching the same cluster ==
@@ -89,6 +121,24 @@ qemu-io> wrote 8192/8192 bytes at offset XXX
 8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 57344/57344 bytes at offset XXX
 56 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> qemu-io> blkdebug: Suspended request 'A'
+qemu-io> qemu-io> qemu-io> blkdebug: Resuming request 'A'
+qemu-io> wrote 8192/8192 bytes at offset XXX
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 98304/98304 bytes at offset XXX
+96 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> qemu-io> blkdebug: Suspended request 'A'
+qemu-io> qemu-io> qemu-io> blkdebug: Resuming request 'A'
+qemu-io> wrote 8192/8192 bytes at offset XXX
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset XXX
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> qemu-io> blkdebug: Suspended request 'A'
+qemu-io> qemu-io> qemu-io> blkdebug: Resuming request 'A'
+qemu-io> wrote 32768/32768 bytes at offset XXX
+32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 98304/98304 bytes at offset XXX
+96 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 qemu-io> 
 == Verify image content ==
 qemu-io> read 65536/65536 bytes at offset 0
@@ -159,5 +209,31 @@ qemu-io> read 57344/57344 bytes at offset 696320
 56 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 qemu-io> read 32768/32768 bytes at offset 753664
 32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 16384/16384 bytes at offset 786432
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 98304/98304 bytes at offset 802816
+96 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 901120
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 909312
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 16384/16384 bytes at offset 917504
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 81920/81920 bytes at offset 933888
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 16384/16384 bytes at offset 1015808
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 1032192
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 1040384
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 16384/16384 bytes at offset 1048576
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 32768/32768 bytes at offset 1064960
+32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 32768/32768 bytes at offset 1130496
+32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 16384/16384 bytes at offset 1163264
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 qemu-io> No errors were found on the image.
 *** done
commit 142c6b1a89c3af769fbab6a22f51eefa7a3b0330
Author: Peter Lieven <pl at kamp.de>
Date:   Thu Mar 21 13:07:10 2013 +0100

    vl.c: call bdrv_init_with_whitelist() before cmdline parsing
    
    commit 4d454574 "qemu-option: move standard option definitions
    out of qemu-config.c" broke support for commandline option
    groups that where registered during bdrv_init(). In particular
    support for -iscsi options was broken since that commit.
    
    Fix by moving the bdrv_init_with_whitelist() before command
    line argument parsing.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/vl.c b/vl.c
index 7643f16..7f86a40 100644
--- a/vl.c
+++ b/vl.c
@@ -2941,6 +2941,8 @@ int main(int argc, char **argv, char **envp)
     nb_numa_nodes = 0;
     nb_nics = 0;
 
+    bdrv_init_with_whitelist();
+
     autostart= 1;
 
     /* first pass of option parsing */
@@ -4199,8 +4201,6 @@ int main(int argc, char **argv, char **envp)
 
     cpu_exec_init_all();
 
-    bdrv_init_with_whitelist();
-
     blk_mig_init();
 
     /* open the virtual block devices */
commit b0d62a3d8e1ea9eccd246829a03e2d23f0982431
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 26 12:35:09 2013 +0000

    hw/tcx: Remove unused 'addr' field and the property that sets it
    
    Remove the 'addr' field from TCXState (since it is completely unused),
    also the qdev property which sets it. This seems to be a relic from
    many years past; devices don't need to know where they are mapped.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 2f214da..9ebda02 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -575,7 +575,6 @@ static void tcx_init(hwaddr addr, int vram_size, int width,
     SysBusDevice *s;
 
     dev = qdev_create(NULL, "SUNW,tcx");
-    qdev_prop_set_taddr(dev, "addr", addr);
     qdev_prop_set_uint32(dev, "vram_size", vram_size);
     qdev_prop_set_uint16(dev, "width", width);
     qdev_prop_set_uint16(dev, "height", height);
diff --git a/hw/tcx.c b/hw/tcx.c
index f1edffd..c44068e 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -37,7 +37,6 @@
 
 typedef struct TCXState {
     SysBusDevice busdev;
-    hwaddr addr;
     QemuConsole *con;
     uint8_t *vram;
     uint32_t *vram24, *cplane;
@@ -707,7 +706,6 @@ write_err:
 }
 
 static Property tcx_properties[] = {
-    DEFINE_PROP_TADDR("addr",      TCXState, addr,      -1),
     DEFINE_PROP_HEX32("vram_size", TCXState, vram_size, -1),
     DEFINE_PROP_UINT16("width",    TCXState, width,     -1),
     DEFINE_PROP_UINT16("height",   TCXState, height,    -1),
commit 0f9d76e5a9a396a2209761265ba6d98ce89b6a32
Author: liguang <lig.fnst at cn.fujitsu.com>
Date:   Tue Mar 26 16:43:19 2013 +0800

    hw/i386/pc: format load_linux function
    
    Signed-off-by: liguang <lig.fnst at cn.fujitsu.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index ed7d9ba..b1e06fa 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -646,8 +646,8 @@ static long get_file_size(FILE *f)
 
 static void load_linux(void *fw_cfg,
                        const char *kernel_filename,
-		       const char *initrd_filename,
-		       const char *kernel_cmdline,
+                       const char *initrd_filename,
+                       const char *kernel_cmdline,
                        hwaddr max_ram_size)
 {
     uint16_t protocol;
@@ -664,60 +664,62 @@ static void load_linux(void *fw_cfg,
     /* load the kernel header */
     f = fopen(kernel_filename, "rb");
     if (!f || !(kernel_size = get_file_size(f)) ||
-	fread(header, 1, MIN(ARRAY_SIZE(header), kernel_size), f) !=
-	MIN(ARRAY_SIZE(header), kernel_size)) {
-	fprintf(stderr, "qemu: could not load kernel '%s': %s\n",
-		kernel_filename, strerror(errno));
-	exit(1);
+        fread(header, 1, MIN(ARRAY_SIZE(header), kernel_size), f) !=
+        MIN(ARRAY_SIZE(header), kernel_size)) {
+        fprintf(stderr, "qemu: could not load kernel '%s': %s\n",
+                kernel_filename, strerror(errno));
+        exit(1);
     }
 
     /* kernel protocol version */
 #if 0
     fprintf(stderr, "header magic: %#x\n", ldl_p(header+0x202));
 #endif
-    if (ldl_p(header+0x202) == 0x53726448)
-	protocol = lduw_p(header+0x206);
-    else {
-	/* This looks like a multiboot kernel. If it is, let's stop
-	   treating it like a Linux kernel. */
+    if (ldl_p(header+0x202) == 0x53726448) {
+        protocol = lduw_p(header+0x206);
+    } else {
+        /* This looks like a multiboot kernel. If it is, let's stop
+           treating it like a Linux kernel. */
         if (load_multiboot(fw_cfg, f, kernel_filename, initrd_filename,
-                           kernel_cmdline, kernel_size, header))
+                           kernel_cmdline, kernel_size, header)) {
             return;
-	protocol = 0;
+        }
+        protocol = 0;
     }
 
     if (protocol < 0x200 || !(header[0x211] & 0x01)) {
-	/* Low kernel */
-	real_addr    = 0x90000;
-	cmdline_addr = 0x9a000 - cmdline_size;
-	prot_addr    = 0x10000;
+        /* Low kernel */
+        real_addr    = 0x90000;
+        cmdline_addr = 0x9a000 - cmdline_size;
+        prot_addr    = 0x10000;
     } else if (protocol < 0x202) {
-	/* High but ancient kernel */
-	real_addr    = 0x90000;
-	cmdline_addr = 0x9a000 - cmdline_size;
-	prot_addr    = 0x100000;
+        /* High but ancient kernel */
+        real_addr    = 0x90000;
+        cmdline_addr = 0x9a000 - cmdline_size;
+        prot_addr    = 0x100000;
     } else {
-	/* High and recent kernel */
-	real_addr    = 0x10000;
-	cmdline_addr = 0x20000;
-	prot_addr    = 0x100000;
+        /* High and recent kernel */
+        real_addr    = 0x10000;
+        cmdline_addr = 0x20000;
+        prot_addr    = 0x100000;
     }
 
 #if 0
     fprintf(stderr,
-	    "qemu: real_addr     = 0x" TARGET_FMT_plx "\n"
-	    "qemu: cmdline_addr  = 0x" TARGET_FMT_plx "\n"
-	    "qemu: prot_addr     = 0x" TARGET_FMT_plx "\n",
-	    real_addr,
-	    cmdline_addr,
-	    prot_addr);
+            "qemu: real_addr     = 0x" TARGET_FMT_plx "\n"
+            "qemu: cmdline_addr  = 0x" TARGET_FMT_plx "\n"
+            "qemu: prot_addr     = 0x" TARGET_FMT_plx "\n",
+            real_addr,
+            cmdline_addr,
+            prot_addr);
 #endif
 
     /* highest address for loading the initrd */
-    if (protocol >= 0x203)
-	initrd_max = ldl_p(header+0x22c);
-    else
-	initrd_max = 0x37ffffff;
+    if (protocol >= 0x203) {
+        initrd_max = ldl_p(header+0x22c);
+    } else {
+        initrd_max = 0x37ffffff;
+    }
 
     if (initrd_max >= max_ram_size-ACPI_DATA_SIZE)
     	initrd_max = max_ram_size-ACPI_DATA_SIZE-1;
@@ -727,10 +729,10 @@ static void load_linux(void *fw_cfg,
     fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
 
     if (protocol >= 0x202) {
-	stl_p(header+0x228, cmdline_addr);
+        stl_p(header+0x228, cmdline_addr);
     } else {
-	stw_p(header+0x20, 0xA33F);
-	stw_p(header+0x22, cmdline_addr-real_addr);
+        stw_p(header+0x20, 0xA33F);
+        stw_p(header+0x22, cmdline_addr-real_addr);
     }
 
     /* handle vga= parameter */
@@ -755,23 +757,23 @@ static void load_linux(void *fw_cfg,
     /* High nybble = B reserved for QEMU; low nybble is revision number.
        If this code is substantially changed, you may want to consider
        incrementing the revision. */
-    if (protocol >= 0x200)
-	header[0x210] = 0xB0;
-
+    if (protocol >= 0x200) {
+        header[0x210] = 0xB0;
+    }
     /* heap */
     if (protocol >= 0x201) {
-	header[0x211] |= 0x80;	/* CAN_USE_HEAP */
-	stw_p(header+0x224, cmdline_addr-real_addr-0x200);
+        header[0x211] |= 0x80;	/* CAN_USE_HEAP */
+        stw_p(header+0x224, cmdline_addr-real_addr-0x200);
     }
 
     /* load initrd */
     if (initrd_filename) {
-	if (protocol < 0x200) {
-	    fprintf(stderr, "qemu: linux kernel too old to load a ram disk\n");
-	    exit(1);
-	}
+        if (protocol < 0x200) {
+            fprintf(stderr, "qemu: linux kernel too old to load a ram disk\n");
+            exit(1);
+        }
 
-	initrd_size = get_image_size(initrd_filename);
+        initrd_size = get_image_size(initrd_filename);
         if (initrd_size < 0) {
             fprintf(stderr, "qemu: error reading initrd %s\n",
                     initrd_filename);
@@ -787,14 +789,15 @@ static void load_linux(void *fw_cfg,
         fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
         fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data, initrd_size);
 
-	stl_p(header+0x218, initrd_addr);
-	stl_p(header+0x21c, initrd_size);
+        stl_p(header+0x218, initrd_addr);
+        stl_p(header+0x21c, initrd_size);
     }
 
     /* load kernel and setup */
     setup_size = header[0x1f1];
-    if (setup_size == 0)
-	setup_size = 4;
+    if (setup_size == 0) {
+        setup_size = 4;
+    }
     setup_size = (setup_size+1)*512;
     kernel_size -= setup_size;
 
commit 9941afdef4fc898ed1588468095d1e36574427a1
Author: Dunrong Huang <huangdr at cloud-times.com>
Date:   Sun Mar 24 15:05:27 2013 +0800

    configure: show debug-info option in --help output
    
    "--enable-debug-info" and "--disable-debug-info" were not shown
    in --help output.
    
    Signed-off-by: Dunrong Huang <huangdr at cloud-times.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/configure b/configure
index f2af714..61e71fa 100755
--- a/configure
+++ b/configure
@@ -1057,6 +1057,8 @@ echo "  --localstatedir=PATH     install local state in PATH"
 echo "  --with-confsuffix=SUFFIX suffix for QEMU data inside datadir and sysconfdir [$confsuffix]"
 echo "  --enable-debug-tcg       enable TCG debugging"
 echo "  --disable-debug-tcg      disable TCG debugging (default)"
+echo "  --enable-debug-info       enable debugging information (default)"
+echo "  --disable-debug-info      disable debugging information"
 echo "  --enable-debug           enable common debug build options"
 echo "  --enable-sparse          enable sparse checker"
 echo "  --disable-sparse         disable sparse checker (default)"
commit e280ff5e9159ed227a117339c1157143627cab96
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:08:03 2013 +0100

    spice-qemu-char: Drop hackish vmc_register on spice_chr_write
    
    Now that the core takes care of fe_open tracking we no longer need this hack.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-12-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index d249829..535f955 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -149,7 +149,6 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     SpiceCharDriver *s = chr->opaque;
 
-    vmc_register_interface(s);
     assert(s->datalen == 0);
     if (s->bufsize < len) {
         s->bufsize = len;
commit bc6b815d9e34778aa7fbe785ecfa0b216c96f576
Author: Alon Levy <alevy at redhat.com>
Date:   Tue Mar 26 11:08:02 2013 +0100

    virtio-serial: propagate guest_connected to the port on post_load
    
    When migrating a host with with a spice agent running the mouse becomes
    non operational after the migration due to the agent state being
    inconsistent between the guest and the client.
    
    After migration the spicevmc backend on the destination has never been notified
    of the (non 0) guest_connected state. Virtio-serial holds this state
    information and migrates it, this patch properly propagates this information
    to virtio-console and through that to interested chardev backends.
    
    rhbz #725965
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-11-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index eb7af21..a9cb114 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -579,6 +579,7 @@ static void virtio_serial_post_load_timer_cb(void *opaque)
     VirtIOSerial *s = opaque;
     VirtIOSerialPort *port;
     uint8_t host_connected;
+    VirtIOSerialPortClass *vsc;
 
     if (!s->post_load) {
         return;
@@ -594,6 +595,10 @@ static void virtio_serial_post_load_timer_cb(void *opaque)
             send_control_event(s, port->id, VIRTIO_CONSOLE_PORT_OPEN,
                                port->host_connected);
         }
+        vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
+        if (vsc->set_guest_connected) {
+            vsc->set_guest_connected(port, port->guest_connected);
+        }
     }
     g_free(s->post_load->connected);
     qemu_free_timer(s->post_load->timer);
commit b2c1394af13b46a72cd27ff580cdd1d9bb1e8934
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:08:01 2013 +0100

    virtio-serial: Consolidate guest_open/guest_close into set_guest_connected
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-10-git-send-email-hdegoede 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 7c89990..284180f 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -66,26 +66,15 @@ static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
     return ret;
 }
 
-/* Callback function that's called when the guest opens the port */
-static void guest_open(VirtIOSerialPort *port)
+/* Callback function that's called when the guest opens/closes the port */
+static void set_guest_connected(VirtIOSerialPort *port, int guest_connected)
 {
     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
 
     if (!vcon->chr) {
         return;
     }
-    qemu_chr_fe_set_open(vcon->chr, 1);
-}
-
-/* Callback function that's called when the guest closes the port */
-static void guest_close(VirtIOSerialPort *port)
-{
-    VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
-
-    if (!vcon->chr) {
-        return;
-    }
-    qemu_chr_fe_set_open(vcon->chr, 0);
+    qemu_chr_fe_set_open(vcon->chr, guest_connected);
 }
 
 /* Readiness of the guest to accept data on a port */
@@ -152,8 +141,7 @@ static void virtconsole_class_init(ObjectClass *klass, void *data)
     k->is_console = true;
     k->init = virtconsole_initfn;
     k->have_data = flush_buf;
-    k->guest_open = guest_open;
-    k->guest_close = guest_close;
+    k->set_guest_connected = set_guest_connected;
     dc->props = virtconsole_properties;
 }
 
@@ -176,8 +164,7 @@ static void virtserialport_class_init(ObjectClass *klass, void *data)
 
     k->init = virtconsole_initfn;
     k->have_data = flush_buf;
-    k->guest_open = guest_open;
-    k->guest_close = guest_close;
+    k->set_guest_connected = set_guest_connected;
     dc->props = virtserialport_properties;
 }
 
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index ab7168e..eb7af21 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -372,14 +372,9 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
 
     case VIRTIO_CONSOLE_PORT_OPEN:
         port->guest_connected = cpkt.value;
-        if (cpkt.value && vsc->guest_open) {
+        if (vsc->set_guest_connected) {
             /* Send the guest opened notification if an app is interested */
-            vsc->guest_open(port);
-        }
-
-        if (!cpkt.value && vsc->guest_close) {
-            /* Send the guest closed notification if an app is interested */
-            vsc->guest_close(port);
+            vsc->set_guest_connected(port, cpkt.value);
         }
         break;
     }
@@ -484,9 +479,9 @@ static void guest_reset(VirtIOSerial *vser)
         vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
         if (port->guest_connected) {
             port->guest_connected = false;
-
-            if (vsc->guest_close)
-                vsc->guest_close(port);
+            if (vsc->set_guest_connected) {
+                vsc->set_guest_connected(port, false);
+            }
         }
     }
 }
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
index 484dcfe..516400f 100644
--- a/hw/virtio-serial.h
+++ b/hw/virtio-serial.h
@@ -92,10 +92,8 @@ typedef struct VirtIOSerialPortClass {
     int (*exit)(VirtIOSerialPort *port);
 
     /* Callbacks for guest events */
-        /* Guest opened device. */
-    void (*guest_open)(VirtIOSerialPort *port);
-        /* Guest closed device. */
-    void (*guest_close)(VirtIOSerialPort *port);
+        /* Guest opened/closed device. */
+    void (*set_guest_connected)(VirtIOSerialPort *port, int guest_connected);
 
         /* Guest is now ready to accept data (virtqueues set up). */
     void (*guest_ready)(VirtIOSerialPort *port);
commit a59bcd31c91397f8c67b6902e7716d626c5070e6
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:08:00 2013 +0100

    qemu-char: add_handlers: Don't re-send the be_open event on unregister
    
    Resending the be_open event only is useful when a frontend is registering, not
    when it is unregistering.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-9-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index ca9381b..dee623e 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -241,7 +241,7 @@ void qemu_chr_add_handlers(CharDriverState *s,
 
     /* We're connecting to an already opened device, so let's make sure we
        also get the open event */
-    if (s->be_open) {
+    if (fe_open && s->be_open) {
         qemu_chr_be_generic_open(s);
     }
 }
commit 85d91e3295f3af21e4d4a19f1f6691c0bf2ed10c
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:07:59 2013 +0100

    qemu-char: Move incrementing of avail_connections to qdev-properties-system
    
    The decrement of avail_connections is done in qdev-properties-system move
    the increment there too for proper balancing of the calls.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-8-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c
index 28813d3..d9934b5 100644
--- a/hw/qdev-properties-system.c
+++ b/hw/qdev-properties-system.c
@@ -136,9 +136,11 @@ static void release_chr(Object *obj, const char *name, void *opaque)
     DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
     CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
+    CharDriverState *chr = *ptr;
 
-    if (*ptr) {
-        qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
+    if (chr) {
+        qemu_chr_add_handlers(chr, NULL, NULL, NULL, NULL);
+        ++chr->avail_connections;
     }
 }
 
diff --git a/qemu-char.c b/qemu-char.c
index bab2eb7..ca9381b 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -224,8 +224,6 @@ void qemu_chr_add_handlers(CharDriverState *s,
     int fe_open;
 
     if (!opaque && !fd_can_read && !fd_read && !fd_event) {
-        /* chr driver being released. */
-        ++s->avail_connections;
         fe_open = 0;
     } else {
         fe_open = 1;
commit 574b711a92db094a2d4e7ca707f3b34437a64246
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:07:58 2013 +0100

    qemu-char: Consolidate guest_close/guest_open into a set_fe_open callback
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-7-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/char/char.h b/include/char/char.h
index a726ddc..32c9999 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -68,8 +68,7 @@ struct CharDriverState {
     void (*chr_close)(struct CharDriverState *chr);
     void (*chr_accept_input)(struct CharDriverState *chr);
     void (*chr_set_echo)(struct CharDriverState *chr, bool echo);
-    void (*chr_guest_open)(struct CharDriverState *chr);
-    void (*chr_guest_close)(struct CharDriverState *chr);
+    void (*chr_set_fe_open)(struct CharDriverState *chr, int fe_open);
     void *opaque;
     int idle_tag;
     char *label;
diff --git a/qemu-char.c b/qemu-char.c
index 29a2462..bab2eb7 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -514,8 +514,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
     chr->chr_update_read_handler = mux_chr_update_read_handler;
     chr->chr_accept_input = mux_chr_accept_input;
     /* Frontend guest-open / -close notification is not support with muxes */
-    chr->chr_guest_open = NULL;
-    chr->chr_guest_close = NULL;
+    chr->chr_set_fe_open = NULL;
 
     /* Muxes are always open on creation */
     qemu_chr_be_generic_open(chr);
@@ -3425,11 +3424,8 @@ void qemu_chr_fe_set_open(struct CharDriverState *chr, int fe_open)
         return;
     }
     chr->fe_open = fe_open;
-    if (fe_open && chr->chr_guest_open) {
-        chr->chr_guest_open(chr);
-    }
-    if (!fe_open && chr->chr_guest_close) {
-        chr->chr_guest_close(chr);
+    if (chr->chr_set_fe_open) {
+        chr->chr_set_fe_open(chr, fe_open);
     }
 }
 
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index c39095b..d249829 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -176,16 +176,14 @@ static void spice_chr_close(struct CharDriverState *chr)
     g_free(s);
 }
 
-static void spice_chr_guest_open(struct CharDriverState *chr)
+static void spice_chr_set_fe_open(struct CharDriverState *chr, int fe_open)
 {
     SpiceCharDriver *s = chr->opaque;
-    vmc_register_interface(s);
-}
-
-static void spice_chr_guest_close(struct CharDriverState *chr)
-{
-    SpiceCharDriver *s = chr->opaque;
-    vmc_unregister_interface(s);
+    if (fe_open) {
+        vmc_register_interface(s);
+    } else {
+        vmc_unregister_interface(s);
+    }
 }
 
 static void print_allowed_subtypes(void)
@@ -218,8 +216,7 @@ static CharDriverState *chr_open(const char *subtype)
     chr->opaque = s;
     chr->chr_write = spice_chr_write;
     chr->chr_close = spice_chr_close;
-    chr->chr_guest_open = spice_chr_guest_open;
-    chr->chr_guest_close = spice_chr_guest_close;
+    chr->chr_set_fe_open = spice_chr_set_fe_open;
 
     QLIST_INSERT_HEAD(&spice_chars, s, next);
 
commit 8e25daa87ac98c9070365b42dcfc070e47fca934
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:07:57 2013 +0100

    qemu-char: Cleanup: consolidate fe_open/fe_close into fe_set_open
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-6-git-send-email-hdegoede 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 2f7c3df..7c89990 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -74,7 +74,7 @@ static void guest_open(VirtIOSerialPort *port)
     if (!vcon->chr) {
         return;
     }
-    qemu_chr_fe_open(vcon->chr);
+    qemu_chr_fe_set_open(vcon->chr, 1);
 }
 
 /* Callback function that's called when the guest closes the port */
@@ -85,7 +85,7 @@ static void guest_close(VirtIOSerialPort *port)
     if (!vcon->chr) {
         return;
     }
-    qemu_chr_fe_close(vcon->chr);
+    qemu_chr_fe_set_open(vcon->chr, 0);
 }
 
 /* Readiness of the guest to accept data on a port */
diff --git a/include/char/char.h b/include/char/char.h
index 3cd2aef..a726ddc 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -129,21 +129,12 @@ void qemu_chr_delete(CharDriverState *chr);
 void qemu_chr_fe_set_echo(struct CharDriverState *chr, bool echo);
 
 /**
- * @qemu_chr_fe_open:
+ * @qemu_chr_fe_set_open:
  *
- * Open a character backend.  This function call is an indication that the
- * front end is ready to begin doing I/O.
+ * Set character frontend open status.  This is an indication that the
+ * front end is ready (or not) to begin doing I/O.
  */
-void qemu_chr_fe_open(struct CharDriverState *chr);
-
-/**
- * @qemu_chr_fe_close:
- *
- * Close a character backend.  This function call indicates that the front end
- * no longer is able to process I/O.  To process I/O again, the front end will
- * call @qemu_chr_fe_open.
- */
-void qemu_chr_fe_close(struct CharDriverState *chr);
+void qemu_chr_fe_set_open(struct CharDriverState *chr, int fe_open);
 
 /**
  * @qemu_chr_fe_printf:
diff --git a/qemu-char.c b/qemu-char.c
index 947541a..29a2462 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -238,11 +238,7 @@ void qemu_chr_add_handlers(CharDriverState *s,
         s->chr_update_read_handler(s);
 
     if (!s->explicit_fe_open) {
-        if (fe_open) {
-            qemu_chr_fe_open(s);
-        } else {
-            qemu_chr_fe_close(s);
-        }
+        qemu_chr_fe_set_open(s, fe_open);
     }
 
     /* We're connecting to an already opened device, so let's make sure we
@@ -3423,24 +3419,16 @@ void qemu_chr_fe_set_echo(struct CharDriverState *chr, bool echo)
     }
 }
 
-void qemu_chr_fe_open(struct CharDriverState *chr)
+void qemu_chr_fe_set_open(struct CharDriverState *chr, int fe_open)
 {
-    if (chr->fe_open) {
+    if (chr->fe_open == fe_open) {
         return;
     }
-    chr->fe_open = 1;
-    if (chr->chr_guest_open) {
+    chr->fe_open = fe_open;
+    if (fe_open && chr->chr_guest_open) {
         chr->chr_guest_open(chr);
     }
-}
-
-void qemu_chr_fe_close(struct CharDriverState *chr)
-{
-    if (!chr->fe_open) {
-        return;
-    }
-    chr->fe_open = 0;
-    if (chr->chr_guest_close) {
+    if (!fe_open && chr->chr_guest_close) {
         chr->chr_guest_close(chr);
     }
 }
commit 190832289fe670f764fb277e4dcaf00f94ca6553
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:07:56 2013 +0100

    qemu-char: Automatically do fe_open / fe_close on qemu_chr_add_handlers
    
    Most frontends can't really determine if the guest actually has the frontend
    side open. So lets automatically generate fe_open / fe_close as soon as a
    frontend becomes ready (as signalled by calling qemu_chr_add_handlers) /
    becomes non ready (as signalled by setting all handlers to NULL).
    
    And allow frontends which can actually determine if the guest is listening to
    opt-out of this.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-5-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 9734e42..d02a7b9 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1282,7 +1282,6 @@ static int usbredir_initfn(USBDevice *udev)
     dev->compatible_speedmask = USB_SPEED_MASK_FULL | USB_SPEED_MASK_HIGH;
 
     /* Let the backend know we are ready */
-    qemu_chr_fe_open(dev->cs);
     qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
                           usbredir_chardev_read, usbredir_chardev_event, dev);
 
@@ -1306,7 +1305,6 @@ static void usbredir_handle_destroy(USBDevice *udev)
 {
     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
 
-    qemu_chr_fe_close(dev->cs);
     qemu_chr_delete(dev->cs);
     /* Note must be done after qemu_chr_close, as that causes a close event */
     qemu_bh_delete(dev->chardev_close_bh);
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index e2d1c58..2f7c3df 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -131,6 +131,7 @@ static int virtconsole_initfn(VirtIOSerialPort *port)
     }
 
     if (vcon->chr) {
+        vcon->chr->explicit_fe_open = 1;
         qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
                               vcon);
     }
diff --git a/include/char/char.h b/include/char/char.h
index dbb1b89..3cd2aef 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -76,6 +76,7 @@ struct CharDriverState {
     char *filename;
     int be_open;
     int fe_open;
+    int explicit_fe_open;
     int avail_connections;
     QemuOpts *opts;
     QTAILQ_ENTRY(CharDriverState) next;
diff --git a/qemu-char.c b/qemu-char.c
index c9890ad..947541a 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -221,9 +221,14 @@ void qemu_chr_add_handlers(CharDriverState *s,
                            IOEventHandler *fd_event,
                            void *opaque)
 {
+    int fe_open;
+
     if (!opaque && !fd_can_read && !fd_read && !fd_event) {
         /* chr driver being released. */
         ++s->avail_connections;
+        fe_open = 0;
+    } else {
+        fe_open = 1;
     }
     s->chr_can_read = fd_can_read;
     s->chr_read = fd_read;
@@ -232,6 +237,14 @@ void qemu_chr_add_handlers(CharDriverState *s,
     if (s->chr_update_read_handler)
         s->chr_update_read_handler(s);
 
+    if (!s->explicit_fe_open) {
+        if (fe_open) {
+            qemu_chr_fe_open(s);
+        } else {
+            qemu_chr_fe_close(s);
+        }
+    }
+
     /* We're connecting to an already opened device, so let's make sure we
        also get the open event */
     if (s->be_open) {
commit c0c4bd2cfae0fb83696000f1bfc355f22e2b41cb
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:07:55 2013 +0100

    qemu-char: Add fe_open tracking
    
    Add tracking of the fe_open state to struct CharDriverState.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-4-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/char/char.h b/include/char/char.h
index e9d2c10..dbb1b89 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -75,6 +75,7 @@ struct CharDriverState {
     char *label;
     char *filename;
     int be_open;
+    int fe_open;
     int avail_connections;
     QemuOpts *opts;
     QTAILQ_ENTRY(CharDriverState) next;
diff --git a/qemu-char.c b/qemu-char.c
index 345fd67..c9890ad 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3412,6 +3412,10 @@ void qemu_chr_fe_set_echo(struct CharDriverState *chr, bool echo)
 
 void qemu_chr_fe_open(struct CharDriverState *chr)
 {
+    if (chr->fe_open) {
+        return;
+    }
+    chr->fe_open = 1;
     if (chr->chr_guest_open) {
         chr->chr_guest_open(chr);
     }
@@ -3419,6 +3423,10 @@ void qemu_chr_fe_open(struct CharDriverState *chr)
 
 void qemu_chr_fe_close(struct CharDriverState *chr)
 {
+    if (!chr->fe_open) {
+        return;
+    }
+    chr->fe_open = 0;
     if (chr->chr_guest_close) {
         chr->chr_guest_close(chr);
     }
commit fee204fd46016c168ca4d404d04e2c06b8b34770
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:07:54 2013 +0100

    qemu-char: Rename qemu_chr_generic_open to qemu_chr_be_generic_open
    
    To better reflect that it is for handling a backend being opened.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-3-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/backends/baum.c b/backends/baum.c
index d7d658c..ea9ffe8 100644
--- a/backends/baum.c
+++ b/backends/baum.c
@@ -611,7 +611,7 @@ CharDriverState *chr_baum_init(void)
 
     qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
 
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
 
     return chr;
 
diff --git a/include/char/char.h b/include/char/char.h
index 90443fc..e9d2c10 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -250,7 +250,7 @@ void qemu_chr_add_handlers(CharDriverState *s,
                            IOEventHandler *fd_event,
                            void *opaque);
 
-void qemu_chr_generic_open(CharDriverState *s);
+void qemu_chr_be_generic_open(CharDriverState *s);
 void qemu_chr_accept_input(CharDriverState *s);
 int qemu_chr_add_client(CharDriverState *s, int fd);
 void qemu_chr_info_print(Monitor *mon, const QObject *ret_data);
diff --git a/qemu-char.c b/qemu-char.c
index 4419817..345fd67 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -120,7 +120,7 @@ void qemu_chr_be_event(CharDriverState *s, int event)
     s->chr_event(s->handler_opaque, event);
 }
 
-static gboolean qemu_chr_generic_open_bh(gpointer opaque)
+static gboolean qemu_chr_be_generic_open_bh(gpointer opaque)
 {
     CharDriverState *s = opaque;
     qemu_chr_be_event(s, CHR_EVENT_OPENED);
@@ -128,10 +128,10 @@ static gboolean qemu_chr_generic_open_bh(gpointer opaque)
     return FALSE;
 }
 
-void qemu_chr_generic_open(CharDriverState *s)
+void qemu_chr_be_generic_open(CharDriverState *s)
 {
     if (s->idle_tag == 0) {
-        s->idle_tag = g_idle_add(qemu_chr_generic_open_bh, s);
+        s->idle_tag = g_idle_add(qemu_chr_be_generic_open_bh, s);
     }
 }
 
@@ -235,7 +235,7 @@ void qemu_chr_add_handlers(CharDriverState *s,
     /* We're connecting to an already opened device, so let's make sure we
        also get the open event */
     if (s->be_open) {
-        qemu_chr_generic_open(s);
+        qemu_chr_be_generic_open(s);
     }
 }
 
@@ -509,7 +509,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
     chr->chr_guest_close = NULL;
 
     /* Muxes are always open on creation */
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
 
     return chr;
 }
@@ -863,7 +863,7 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
     chr->chr_update_read_handler = fd_chr_update_read_handler;
     chr->chr_close = fd_chr_close;
 
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
 
     return chr;
 }
@@ -1160,7 +1160,7 @@ static void pty_chr_state(CharDriverState *chr, int connected)
         pty_chr_rearm_timer(chr, 1000);
     } else {
         if (!s->connected)
-            qemu_chr_generic_open(chr);
+            qemu_chr_be_generic_open(chr);
         s->connected = 1;
     }
 }
@@ -1576,7 +1576,7 @@ static CharDriverState *qemu_chr_open_pp_fd(int fd)
     chr->chr_close = pp_close;
     chr->opaque = drv;
 
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
 
     return chr;
 }
@@ -1861,7 +1861,7 @@ static CharDriverState *qemu_chr_open_win_path(const char *filename)
         g_free(chr);
         return NULL;
     }
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
     return chr;
 }
 
@@ -1961,7 +1961,7 @@ static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts)
         g_free(chr);
         return NULL;
     }
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
     return chr;
 }
 
@@ -1975,7 +1975,7 @@ static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
     s->hcom = fd_out;
     chr->opaque = s;
     chr->chr_write = win_chr_write;
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
     return chr;
 }
 
@@ -2540,7 +2540,7 @@ static void tcp_chr_connect(void *opaque)
     if (s->chan) {
         s->tag = io_add_watch_poll(s->chan, tcp_chr_read_poll, tcp_chr_read, chr);
     }
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
 }
 
 #define IACSET(x,a,b,c) x[0] = a; x[1] = b; x[2] = c;
diff --git a/ui/console.c b/ui/console.c
index eb7a2bc..e84ba8b 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1600,7 +1600,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
         s->t_attrib = s->t_attrib_default;
     }
 
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
     if (chr->init)
         chr->init(chr);
 }
diff --git a/ui/gtk.c b/ui/gtk.c
index 1edfaca..a5a8156 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1163,7 +1163,7 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
 
     gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), vc->menu_item);
 
-    qemu_chr_generic_open(vc->chr);
+    qemu_chr_be_generic_open(vc->chr);
     if (vc->chr->init) {
         vc->chr->init(vc->chr);
     }
commit 16665b943b23e953220df257e7e04e669aa384d5
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:07:53 2013 +0100

    qemu-char: Rename opened to be_open
    
    Rename the opened variable to be_open to reflect that it contains the
    opened state of the backend.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-2-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index 47ac8c9..7c314dc 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -495,7 +495,7 @@ static int usb_serial_initfn(USBDevice *dev)
                           usb_serial_event, s);
     usb_serial_handle_reset(dev);
 
-    if (s->cs->opened && !dev->attached) {
+    if (s->cs->be_open && !dev->attached) {
         usb_device_attach(dev);
     }
     return 0;
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index c519b9b..9734e42 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -258,7 +258,7 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
 {
     USBRedirDevice *dev = priv;
 
-    if (!dev->cs->opened) {
+    if (!dev->cs->be_open) {
         return 0;
     }
 
diff --git a/include/char/char.h b/include/char/char.h
index 5c3a7a5..90443fc 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -74,7 +74,7 @@ struct CharDriverState {
     int idle_tag;
     char *label;
     char *filename;
-    int opened;
+    int be_open;
     int avail_connections;
     QemuOpts *opts;
     QTAILQ_ENTRY(CharDriverState) next;
diff --git a/qemu-char.c b/qemu-char.c
index 936150f..4419817 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -108,10 +108,10 @@ void qemu_chr_be_event(CharDriverState *s, int event)
     /* Keep track if the char device is open */
     switch (event) {
         case CHR_EVENT_OPENED:
-            s->opened = 1;
+            s->be_open = 1;
             break;
         case CHR_EVENT_CLOSED:
-            s->opened = 0;
+            s->be_open = 0;
             break;
     }
 
@@ -234,7 +234,7 @@ void qemu_chr_add_handlers(CharDriverState *s,
 
     /* We're connecting to an already opened device, so let's make sure we
        also get the open event */
-    if (s->opened) {
+    if (s->be_open) {
         qemu_chr_generic_open(s);
     }
 }
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index 8a9236d..c39095b 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -100,8 +100,8 @@ static void vmc_state(SpiceCharDeviceInstance *sin, int connected)
     }
 #endif
 
-    if ((scd->chr->opened && connected) ||
-        (!scd->chr->opened && !connected)) {
+    if ((scd->chr->be_open && connected) ||
+        (!scd->chr->be_open && !connected)) {
         return;
     }
 
commit 99835e00849369bab726a4dc4ceed1f6f9ed967c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Mar 27 14:34:32 2013 +0100

    compiler: fix warning with GCC 4.8.0
    
    GCC 4.8.0 introduces a new warning:
    
        block/qcow2-snapshot.c: In function 'qcow2_write_snapshots’:
        block/qcow2-snapshot.c:252:18: error: typedef 'qemu_build_bug_on__253'
                  locally defined but not used [-Werror=unused-local-typedefs]
             QEMU_BUILD_BUG_ON(offsetof(QCowHeader, snapshots_offset) !=
                      ^
        cc1: all warnings being treated as errors
    
    (Caret diagnostics aren't perfect yet with macros... :)) Work around it
    with __attribute__((unused)).
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1364391272-1128-1-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
index 2f7998b..6175c24 100644
--- a/include/qemu/compiler.h
+++ b/include/qemu/compiler.h
@@ -33,7 +33,7 @@
 #define cat(x,y) x ## y
 #define cat2(x,y) cat(x,y)
 #define QEMU_BUILD_BUG_ON(x) \
-    typedef char cat2(qemu_build_bug_on__,__LINE__)[(x)?-1:1];
+    typedef char cat2(qemu_build_bug_on__,__LINE__)[(x)?-1:1] __attribute__((unused));
 
 #if defined __GNUC__
 # if !QEMU_GNUC_PREREQ(4, 4)
commit 404e7a4f4af753bd2aef649adf79e7434fb6dc31
Merge: 18501ae 6214e73
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 26 16:16:43 2013 -0500

    Merge remote-tracking branch 'mst/tags/for_anthony' into staging
    
    virtio,pci,qom
    
    Work by Alex to support VGA assignment,
    pci and virtio fixes by Stefan, Jason and myself, and a
    new qmp event for hotplug support by myself.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    
    # gpg: Signature made Tue 26 Mar 2013 02:02:24 PM CDT using RSA key ID D28D5469
    # gpg: Can't check signature: public key not found
    
    # By Alex Williamson (13) and others
    # Via Michael S. Tsirkin
    * mst/tags/for_anthony: (23 commits)
      pcie: Add endpoint capability initialization wrapper
      roms: switch oldnoconfig to olddefconfig
      pcie: Mangle types to match topology
      pci: Create and use API to determine root buses
      pci: Create pci_bus_is_express helper
      pci: Q35, Root Ports, and Switches create PCI Express buses
      pci: Allow PCI bus creation interfaces to specify the type of bus
      pci: Move PCI and PCIE type defines
      pci: Create and register a new PCI Express TypeInfo
      exec: assert that RAMBlock size is non-zero
      pci: refuse empty ROM files
      pci_bridge: Remove duplicate IRQ swizzle function
      pci_bridge: Use a default map_irq function
      pci: Fix INTx routing notifier recursion
      pci_bridge: drop formatting from source
      pci_bridge: factor out common code
      pci: Teach PCI Bridges about VGA routing
      pci: Add PCI VGA helpers
      virtio-pci: guest notifier mask without non-irqfd
      virtio-net: remove layout assumptions for mq ctrl
      ...

diff --cc hw/spapr_pci.c
index 42c8b61,20b9015..3e0d8d1
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@@ -619,29 -621,10 +619,29 @@@ static int spapr_phb_init(SysBusDevice 
                                      &sphb->msiwindow);
      }
  
 -    bus = pci_register_bus(DEVICE(s), sphb->busname,
 +    /*
 +     * Selecting a busname is more complex than you'd think, due to
 +     * interacting constraints.  If the user has specified an id
 +     * explicitly for the phb , then we want to use the qdev default
 +     * of naming the bus based on the bridge device (so the user can
 +     * then assign devices to it in the way they expect).  For the
 +     * first / default PCI bus (index=0) we want to use just "pci"
 +     * because libvirt expects there to be a bus called, simply,
 +     * "pci".  Otherwise, we use the same name as in the device tree,
 +     * since it's unique by construction, and makes the guest visible
 +     * BUID clear.
 +     */
 +    if (s->qdev.id) {
 +        busname = NULL;
 +    } else if (sphb->index == 0) {
 +        busname = "pci";
 +    } else {
 +        busname = sphb->dtbusname;
 +    }
 +    bus = pci_register_bus(DEVICE(s), busname,
                             pci_spapr_set_irq, pci_spapr_map_irq, sphb,
                             &sphb->memspace, &sphb->iospace,
-                            PCI_DEVFN(0, 0), PCI_NUM_PINS);
+                            PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS);
      phb->bus = bus;
  
      sphb->dma_window_start = 0;
commit 6214e73cc5b75a4f8d89a70d71727edfa47a81b3
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Tue Mar 19 12:11:24 2013 -0600

    pcie: Add endpoint capability initialization wrapper
    
    Fix the awkward API of mangling the caller specified PCIe type and
    just provide an interface to initialize an endpoint device.  This
    will pick either a regular endpoint or integrated endpoint based on
    the bus and return pcie_cap_init to doing exactly what is asked.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index bcfbae4..62bd0b8 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -48,19 +48,6 @@ int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port)
 
     assert(pci_is_express(dev));
 
-    /*
-     * Mangle type to convert Endpoints to Root Complex Integrated Endpoints.
-     * Windows will report Code 10 (device cannot start) for regular Endpoints
-     * on the Root Complex.
-     */
-    if (pci_bus_is_express(dev->bus) && pci_bus_is_root(dev->bus)) {
-        switch (type) {
-        case PCI_EXP_TYPE_ENDPOINT:
-            type = PCI_EXP_TYPE_RC_END;
-            break;
-        }
-    }
-
     pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset,
                                  PCI_EXP_VER2_SIZEOF);
     if (pos < 0) {
@@ -100,6 +87,22 @@ int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port)
     return pos;
 }
 
+int pcie_endpoint_cap_init(PCIDevice *dev, uint8_t offset)
+{
+    uint8_t type = PCI_EXP_TYPE_ENDPOINT;
+
+    /*
+     * Windows guests will report Code 10, device cannot start, if
+     * a regular Endpoint type is exposed on a root complex.  These
+     * should instead be Root Complex Integrated Endpoints.
+     */
+    if (pci_bus_is_express(dev->bus) && pci_bus_is_root(dev->bus)) {
+        type = PCI_EXP_TYPE_RC_END;
+    }
+
+    return pcie_cap_init(dev, offset, type, 0);
+}
+
 void pcie_cap_exit(PCIDevice *dev)
 {
     pci_del_capability(dev, PCI_CAP_ID_EXP, PCI_EXP_VER2_SIZEOF);
diff --git a/hw/pci/pcie.h b/hw/pci/pcie.h
index 31604e2..c010007 100644
--- a/hw/pci/pcie.h
+++ b/hw/pci/pcie.h
@@ -95,6 +95,7 @@ struct PCIExpressDevice {
 
 /* PCI express capability helper functions */
 int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port);
+int pcie_endpoint_cap_init(PCIDevice *dev, uint8_t offset);
 void pcie_cap_exit(PCIDevice *dev);
 uint8_t pcie_cap_get_type(const PCIDevice *dev);
 void pcie_cap_flags_set_vector(PCIDevice *dev, uint8_t vector);
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 07afdee..5aa342b 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -3332,7 +3332,7 @@ static int usb_xhci_initfn(struct PCIDevice *dev)
                      PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64,
                      &xhci->mem);
 
-    ret = pcie_cap_init(&xhci->pci_dev, 0xa0, PCI_EXP_TYPE_ENDPOINT, 0);
+    ret = pcie_endpoint_cap_init(&xhci->pci_dev, 0xa0);
     assert(ret >= 0);
 
     if (xhci->flags & (1 << XHCI_FLAG_USE_MSI)) {
commit a5519b42cfd6c00e9f8b31c5aad7682e7a9f1181
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Thu Mar 21 14:04:21 2013 +0200

    roms: switch oldnoconfig to olddefconfig
    
    When a new option is added that qemu does not know
    about, the prudent thing is to use the default not
    force it to "no".
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/roms/configure-seabios.sh b/roms/configure-seabios.sh
index 98f59a2..4bb6c2b 100755
--- a/roms/configure-seabios.sh
+++ b/roms/configure-seabios.sh
@@ -2,4 +2,4 @@
 config="$1"
 make -C seabios clean distclean
 cp "$config" seabios/.config
-make -C seabios oldnoconfig
+make -C seabios olddefconfig
commit eb28cb1bb0cb156aef7e613395af403bba0e7f30
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 14 16:01:35 2013 -0600

    pcie: Mangle types to match topology
    
    Windows will fail to start drivers for devices with an Endpoint type
    PCIe capability attached to a Root Complex (code 10 - Device cannot
    start).  The proper type for such a device is Root Complex Integrated
    Endpoint.  Devices don't care which they are, so do this conversion
    automatically.
    
    This allows the Windows driver to load for nec-usb-xhci when attached
    to pcie.0 of a q35 machine.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 485c94c..bcfbae4 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -48,6 +48,19 @@ int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port)
 
     assert(pci_is_express(dev));
 
+    /*
+     * Mangle type to convert Endpoints to Root Complex Integrated Endpoints.
+     * Windows will report Code 10 (device cannot start) for regular Endpoints
+     * on the Root Complex.
+     */
+    if (pci_bus_is_express(dev->bus) && pci_bus_is_root(dev->bus)) {
+        switch (type) {
+        case PCI_EXP_TYPE_ENDPOINT:
+            type = PCI_EXP_TYPE_RC_END;
+            break;
+        }
+    }
+
     pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset,
                                  PCI_EXP_VER2_SIZEOF);
     if (pos < 0) {
commit 0889464a5050c25611d08ca33d8447796c88c7f7
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 14 16:01:29 2013 -0600

    pci: Create and use API to determine root buses
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 7f28101..d5257ed 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -302,6 +302,11 @@ bool pci_bus_is_express(PCIBus *bus)
     return object_dynamic_cast(OBJECT(bus), TYPE_PCIE_BUS);
 }
 
+bool pci_bus_is_root(PCIBus *bus)
+{
+    return !bus->parent_dev;
+}
+
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name,
                          MemoryRegion *address_space_mem,
@@ -360,7 +365,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
 
 int pci_bus_num(PCIBus *s)
 {
-    if (!s->parent_dev)
+    if (pci_bus_is_root(s))
         return 0;       /* pci host bridge */
     return s->parent_dev->config[PCI_SECONDARY_BUS];
 }
@@ -1186,7 +1191,7 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
 /* Special hooks used by device assignment */
 void pci_bus_set_route_irq_fn(PCIBus *bus, pci_route_irq_fn route_intx_to_irq)
 {
-    assert(!bus->parent_dev);
+    assert(pci_bus_is_root(bus));
     bus->route_intx_to_irq = route_intx_to_irq;
 }
 
@@ -1651,7 +1656,7 @@ static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num)
     }
 
     /* Consider all bus numbers in range for the host pci bridge. */
-    if (bus->parent_dev &&
+    if (!pci_bus_is_root(bus) &&
         !pci_secondary_bus_in_range(bus->parent_dev, bus_num)) {
         return NULL;
     }
@@ -1659,7 +1664,7 @@ static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num)
     /* try child bus */
     for (; bus; bus = sec) {
         QLIST_FOREACH(sec, &bus->child, sibling) {
-            assert(sec->parent_dev);
+            assert(!pci_bus_is_root(sec));
             if (sec->parent_dev->config[PCI_SECONDARY_BUS] == bus_num) {
                 return sec;
             }
diff --git a/hw/pci/pci.h b/hw/pci/pci.h
index d715e6f..774369c 100644
--- a/hw/pci/pci.h
+++ b/hw/pci/pci.h
@@ -345,6 +345,7 @@ typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
 #define TYPE_PCIE_BUS "PCIE"
 
 bool pci_bus_is_express(PCIBus *bus);
+bool pci_bus_is_root(PCIBus *bus);
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name,
                          MemoryRegion *address_space_mem,
commit 8c0bf9e24242c89c1abbd708c714dd2a89febbd2
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 14 16:01:23 2013 -0600

    pci: Create pci_bus_is_express helper
    
    For testing the bus type.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 7c5f2e2..7f28101 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -297,6 +297,11 @@ static void pci_bus_init(PCIBus *bus, DeviceState *parent,
     vmstate_register(NULL, -1, &vmstate_pcibus, bus);
 }
 
+bool pci_bus_is_express(PCIBus *bus)
+{
+    return object_dynamic_cast(OBJECT(bus), TYPE_PCIE_BUS);
+}
+
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name,
                          MemoryRegion *address_space_mem,
diff --git a/hw/pci/pci.h b/hw/pci/pci.h
index 10aeaf0..d715e6f 100644
--- a/hw/pci/pci.h
+++ b/hw/pci/pci.h
@@ -344,6 +344,7 @@ typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
 #define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
 #define TYPE_PCIE_BUS "PCIE"
 
+bool pci_bus_is_express(PCIBus *bus);
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name,
                          MemoryRegion *address_space_mem,
commit afb661eb902f4ad1456d57b31cdd02f0b4aac33f
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 14 16:01:17 2013 -0600

    pci: Q35, Root Ports, and Switches create PCI Express buses
    
    Convert q35, ioh3420, xio3130_upstream, and xio3130_downstream to
    use the new TYPE_PCIE_BUS.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/ioh3420.c b/hw/ioh3420.c
index 74d84d4..5cff61e 100644
--- a/hw/ioh3420.c
+++ b/hw/ioh3420.c
@@ -97,7 +97,7 @@ static int ioh3420_initfn(PCIDevice *d)
     PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
     int rc;
 
-    rc = pci_bridge_initfn(d, TYPE_PCI_BUS);
+    rc = pci_bridge_initfn(d, TYPE_PCIE_BUS);
     if (rc < 0) {
         return rc;
     }
diff --git a/hw/q35.c b/hw/q35.c
index 37592bc..6ea081a 100644
--- a/hw/q35.c
+++ b/hw/q35.c
@@ -55,7 +55,7 @@ static int q35_host_init(SysBusDevice *dev)
     }
     b = pci_bus_new(&s->host.pci.busdev.qdev, "pcie.0",
                     s->mch.pci_address_space, s->mch.address_space_io,
-                    0, TYPE_PCI_BUS);
+                    0, TYPE_PCIE_BUS);
     s->host.pci.bus = b;
     qdev_set_parent_bus(DEVICE(&s->mch), BUS(b));
     qdev_init_nofail(DEVICE(&s->mch));
diff --git a/hw/xio3130_downstream.c b/hw/xio3130_downstream.c
index a76d89b..b868f56 100644
--- a/hw/xio3130_downstream.c
+++ b/hw/xio3130_downstream.c
@@ -61,7 +61,7 @@ static int xio3130_downstream_initfn(PCIDevice *d)
     PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
     int rc;
 
-    rc = pci_bridge_initfn(d, TYPE_PCI_BUS);
+    rc = pci_bridge_initfn(d, TYPE_PCIE_BUS);
     if (rc < 0) {
         return rc;
     }
diff --git a/hw/xio3130_upstream.c b/hw/xio3130_upstream.c
index d8fd19e..cd5d97d 100644
--- a/hw/xio3130_upstream.c
+++ b/hw/xio3130_upstream.c
@@ -57,7 +57,7 @@ static int xio3130_upstream_initfn(PCIDevice *d)
     PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
     int rc;
 
-    rc = pci_bridge_initfn(d, TYPE_PCI_BUS);
+    rc = pci_bridge_initfn(d, TYPE_PCIE_BUS);
     if (rc < 0) {
         return rc;
     }
commit 60a0e44320cc2601236450fbe95d952830192a1d
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 14 16:01:11 2013 -0600

    pci: Allow PCI bus creation interfaces to specify the type of bus
    
    No change to any types.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index 770dc8c..b1e0044 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -775,7 +775,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
 
     b = pci_register_bus(dev, "pci",
                          typhoon_set_irq, sys_map_irq, s,
-                         &s->pchip.reg_mem, addr_space_io, 0, 64);
+                         &s->pchip.reg_mem, addr_space_io, 0, 64, TYPE_PCI_BUS);
     phb->bus = b;
 
     /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB.  */
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 7992d6f..754ca6c 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -329,7 +329,7 @@ static int apb_pci_bridge_initfn(PCIDevice *dev)
 {
     int rc;
 
-    rc = pci_bridge_initfn(dev);
+    rc = pci_bridge_initfn(dev, TYPE_PCI_BUS);
     if (rc < 0) {
         return rc;
     }
@@ -381,7 +381,7 @@ PCIBus *pci_apb_init(hwaddr special_base,
                               pci_apb_set_irq, pci_pbm_map_irq, d,
                               &d->pci_mmio,
                               get_system_io(),
-                              0, 32);
+                              0, 32, TYPE_PCI_BUS);
 
     *pbm_irqs = d->pbm_irqs;
     d->ivec_irqs = ivec_irqs;
diff --git a/hw/bonito.c b/hw/bonito.c
index 3456e78..e58655a 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -707,7 +707,7 @@ static int bonito_pcihost_initfn(SysBusDevice *dev)
     phb->bus = pci_register_bus(DEVICE(dev), "pci",
                                 pci_bonito_set_irq, pci_bonito_map_irq, dev,
                                 get_system_memory(), get_system_io(),
-                                0x28, 32);
+                                0x28, 32, TYPE_PCI_BUS);
 
     return 0;
 }
diff --git a/hw/dec_pci.c b/hw/dec_pci.c
index 64a5092..6ec3d22 100644
--- a/hw/dec_pci.c
+++ b/hw/dec_pci.c
@@ -51,12 +51,17 @@ static int dec_map_irq(PCIDevice *pci_dev, int irq_num)
     return irq_num;
 }
 
+static int dec_pci_bridge_initfn(PCIDevice *pci_dev)
+{
+    return pci_bridge_initfn(pci_dev, TYPE_PCI_BUS);
+}
+
 static void dec_21154_pci_bridge_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = pci_bridge_initfn;
+    k->init = dec_pci_bridge_initfn;
     k->exit = pci_bridge_exitfn;
     k->vendor_id = PCI_VENDOR_ID_DEC;
     k->device_id = PCI_DEVICE_ID_DEC_21154;
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index 11e47d5..69344d9 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -88,7 +88,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
                                 pic,
                                 &d->pci_mmio,
                                 address_space_io,
-                                0, 4);
+                                0, 4, TYPE_PCI_BUS);
 
     pci_create_simple(phb->bus, 0, "grackle");
 
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index c73a58a..37be9c2 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -1107,7 +1107,7 @@ PCIBus *gt64120_register(qemu_irq *pic)
                                 pic,
                                 get_system_memory(),
                                 get_system_io(),
-                                PCI_DEVFN(18, 0), 4);
+                                PCI_DEVFN(18, 0), 4, TYPE_PCI_BUS);
     memory_region_init_io(&d->ISD_mem, &isd_mem_ops, d, "isd-mem", 0x1000);
 
     pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "gt64120_pci");
diff --git a/hw/i82801b11.c b/hw/i82801b11.c
index 992095c..8b4a9c6 100644
--- a/hw/i82801b11.c
+++ b/hw/i82801b11.c
@@ -59,7 +59,7 @@ static int i82801b11_bridge_initfn(PCIDevice *d)
 {
     int rc;
 
-    rc = pci_bridge_initfn(d);
+    rc = pci_bridge_initfn(d, TYPE_PCI_BUS);
     if (rc < 0) {
         return rc;
     }
diff --git a/hw/ioh3420.c b/hw/ioh3420.c
index 43f8554..74d84d4 100644
--- a/hw/ioh3420.c
+++ b/hw/ioh3420.c
@@ -97,7 +97,7 @@ static int ioh3420_initfn(PCIDevice *d)
     PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
     int rc;
 
-    rc = pci_bridge_initfn(d);
+    rc = pci_bridge_initfn(d, TYPE_PCI_BUS);
     if (rc < 0) {
         return rc;
     }
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 74f449d..7c5f2e2 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -301,9 +301,9 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
-                         uint8_t devfn_min)
+                         uint8_t devfn_min, const char *typename)
 {
-    qbus_create_inplace(bus, TYPE_PCI_BUS, parent, name);
+    qbus_create_inplace(bus, typename, parent, name);
     pci_bus_init(bus, parent, name, address_space_mem,
                  address_space_io, devfn_min);
 }
@@ -311,11 +311,11 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
 PCIBus *pci_bus_new(DeviceState *parent, const char *name,
                     MemoryRegion *address_space_mem,
                     MemoryRegion *address_space_io,
-                    uint8_t devfn_min)
+                    uint8_t devfn_min, const char *typename)
 {
     PCIBus *bus;
 
-    bus = PCI_BUS(qbus_create(TYPE_PCI_BUS, parent, name));
+    bus = PCI_BUS(qbus_create(typename, parent, name));
     pci_bus_init(bus, parent, name, address_space_mem,
                  address_space_io, devfn_min);
     return bus;
@@ -343,12 +343,12 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          void *irq_opaque,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
-                         uint8_t devfn_min, int nirq)
+                         uint8_t devfn_min, int nirq, const char *typename)
 {
     PCIBus *bus;
 
     bus = pci_bus_new(parent, name, address_space_mem,
-                      address_space_io, devfn_min);
+                      address_space_io, devfn_min, typename);
     pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq);
     return bus;
 }
diff --git a/hw/pci/pci.h b/hw/pci/pci.h
index 37fb522..10aeaf0 100644
--- a/hw/pci/pci.h
+++ b/hw/pci/pci.h
@@ -348,11 +348,11 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
-                         uint8_t devfn_min);
+                         uint8_t devfn_min, const char *typename);
 PCIBus *pci_bus_new(DeviceState *parent, const char *name,
                     MemoryRegion *address_space_mem,
                     MemoryRegion *address_space_io,
-                    uint8_t devfn_min);
+                    uint8_t devfn_min, const char *typename);
 void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                   void *irq_opaque, int nirq);
 int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
@@ -364,7 +364,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          void *irq_opaque,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
-                         uint8_t devfn_min, int nirq);
+                         uint8_t devfn_min, int nirq, const char *typename);
 void pci_bus_set_route_irq_fn(PCIBus *, pci_route_irq_fn);
 PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
 bool pci_intx_route_changed(PCIINTxRoute *old, PCIINTxRoute *new);
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index bf93ac6..24be6c5 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -328,7 +328,7 @@ void pci_bridge_reset(DeviceState *qdev)
 }
 
 /* default qdev initialization function for PCI-to-PCI bridge */
-int pci_bridge_initfn(PCIDevice *dev)
+int pci_bridge_initfn(PCIDevice *dev, const char *typename)
 {
     PCIBus *parent = dev->bus;
     PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
@@ -363,8 +363,7 @@ int pci_bridge_initfn(PCIDevice *dev)
 	    br->bus_name = dev->qdev.id;
     }
 
-    qbus_create_inplace(&sec_bus->qbus, TYPE_PCI_BUS, &dev->qdev,
-                        br->bus_name);
+    qbus_create_inplace(&sec_bus->qbus, typename, &dev->qdev, br->bus_name);
     sec_bus->parent_dev = dev;
     sec_bus->map_irq = br->map_irq ? br->map_irq : pci_swizzle_map_irq_fn;
     sec_bus->address_space_mem = &br->address_space_mem;
diff --git a/hw/pci/pci_bridge.h b/hw/pci/pci_bridge.h
index e549b78..1868f7a 100644
--- a/hw/pci/pci_bridge.h
+++ b/hw/pci/pci_bridge.h
@@ -43,7 +43,7 @@ void pci_bridge_disable_base_limit(PCIDevice *dev);
 void pci_bridge_reset_reg(PCIDevice *dev);
 void pci_bridge_reset(DeviceState *qdev);
 
-int pci_bridge_initfn(PCIDevice *pci_dev);
+int pci_bridge_initfn(PCIDevice *pci_dev, const char *typename);
 void pci_bridge_exitfn(PCIDevice *pci_dev);
 
 
diff --git a/hw/pci_bridge_dev.c b/hw/pci_bridge_dev.c
index 840ef43..971b432 100644
--- a/hw/pci_bridge_dev.c
+++ b/hw/pci_bridge_dev.c
@@ -42,7 +42,7 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
     PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br);
     int err;
 
-    err = pci_bridge_initfn(dev);
+    err = pci_bridge_initfn(dev, TYPE_PCI_BUS);
     if (err) {
         goto bridge_error;
     }
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index e10bc1c..ce39779 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -245,7 +245,7 @@ static PCIBus *i440fx_common_init(const char *device_name,
     dev = qdev_create(NULL, "i440FX-pcihost");
     s = PCI_HOST_BRIDGE(dev);
     b = pci_bus_new(dev, NULL, pci_address_space,
-                    address_space_io, 0);
+                    address_space_io, 0, TYPE_PCI_BUS);
     s->bus = b;
     object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL);
     qdev_init_nofail(dev);
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index f3bbe88..854e170 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -349,7 +349,7 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev)
 
     b = pci_register_bus(DEVICE(dev), NULL, ppc4xx_pci_set_irq,
                          ppc4xx_pci_map_irq, s->irq, get_system_memory(),
-                         get_system_io(), 0, 4);
+                         get_system_io(), 0, 4, TYPE_PCI_BUS);
     h->bus = b;
 
     pci_create_simple(b, 0, "ppc4xx-host-bridge");
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 310ae1c..abc7ebe 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -356,7 +356,7 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
 
     b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq,
                          mpc85xx_pci_map_irq, s->irq, address_space_mem,
-                         &s->pio, PCI_DEVFN(s->first_slot, 0), 4);
+                         &s->pio, PCI_DEVFN(s->first_slot, 0), 4, TYPE_PCI_BUS);
     h->bus = b;
 
     pci_create_simple(b, 0, "e500-host-bridge");
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index d21e876..58df245 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -154,7 +154,7 @@ static void raven_pcihost_initfn(Object *obj)
     DeviceState *pci_dev;
 
     pci_bus_new_inplace(&s->pci_bus, DEVICE(obj), NULL,
-                        address_space_mem, address_space_io, 0);
+                        address_space_mem, address_space_io, 0, TYPE_PCI_BUS);
     h->bus = &s->pci_bus;
 
     object_initialize(&s->pci_dev, TYPE_RAVEN_PCI_DEVICE);
diff --git a/hw/q35.c b/hw/q35.c
index 0a25b8b..37592bc 100644
--- a/hw/q35.c
+++ b/hw/q35.c
@@ -54,7 +54,8 @@ static int q35_host_init(SysBusDevice *dev)
         return -1;
     }
     b = pci_bus_new(&s->host.pci.busdev.qdev, "pcie.0",
-                    s->mch.pci_address_space, s->mch.address_space_io, 0);
+                    s->mch.pci_address_space, s->mch.address_space_io,
+                    0, TYPE_PCI_BUS);
     s->host.pci.bus = b;
     qdev_set_parent_bus(DEVICE(&s->mch), BUS(b));
     qdev_init_nofail(DEVICE(&s->mch));
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index 96535db..e3e7550 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -124,7 +124,7 @@ static int sh_pci_device_init(SysBusDevice *dev)
                               s->irq,
                               get_system_memory(),
                               get_system_io(),
-                              PCI_DEVFN(0, 0), 4);
+                              PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
     memory_region_init_io(&s->memconfig_p4, &sh_pci_reg_ops, s,
                           "sh_pci", 0x224);
     memory_region_init_alias(&s->memconfig_a7, "sh_pci.2", &s->memconfig_p4,
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 36adbc5..20b9015 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -624,7 +624,7 @@ static int spapr_phb_init(SysBusDevice *s)
     bus = pci_register_bus(DEVICE(s), sphb->busname,
                            pci_spapr_set_irq, pci_spapr_map_irq, sphb,
                            &sphb->memspace, &sphb->iospace,
-                           PCI_DEVFN(0, 0), PCI_NUM_PINS);
+                           PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS);
     phb->bus = bus;
 
     sphb->dma_window_start = 0;
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index cb95ad1..fff235d 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -239,7 +239,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic,
                               pic,
                               &d->pci_mmio,
                               address_space_io,
-                              PCI_DEVFN(11, 0), 4);
+                              PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
 
 #if 0
     pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north");
@@ -305,7 +305,7 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic,
                               pic,
                               &d->pci_mmio,
                               address_space_io,
-                              PCI_DEVFN(11, 0), 4);
+                              PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
 
     sysbus_mmio_map(s, 0, 0xf0800000);
     sysbus_mmio_map(s, 1, 0xf0c00000);
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index 0b97a40..d67ca79 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -70,7 +70,7 @@ static int pci_vpb_init(SysBusDevice *dev)
     bus = pci_register_bus(&dev->qdev, "pci",
                            pci_vpb_set_irq, pci_vpb_map_irq, s->irq,
                            get_system_memory(), get_system_io(),
-                           PCI_DEVFN(11, 0), 4);
+                           PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
 
     /* ??? Register memory space.  */
 
diff --git a/hw/xio3130_downstream.c b/hw/xio3130_downstream.c
index 4bccd0d..a76d89b 100644
--- a/hw/xio3130_downstream.c
+++ b/hw/xio3130_downstream.c
@@ -61,7 +61,7 @@ static int xio3130_downstream_initfn(PCIDevice *d)
     PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
     int rc;
 
-    rc = pci_bridge_initfn(d);
+    rc = pci_bridge_initfn(d, TYPE_PCI_BUS);
     if (rc < 0) {
         return rc;
     }
diff --git a/hw/xio3130_upstream.c b/hw/xio3130_upstream.c
index 82556aa..d8fd19e 100644
--- a/hw/xio3130_upstream.c
+++ b/hw/xio3130_upstream.c
@@ -57,7 +57,7 @@ static int xio3130_upstream_initfn(PCIDevice *d)
     PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
     int rc;
 
-    rc = pci_bridge_initfn(d);
+    rc = pci_bridge_initfn(d, TYPE_PCI_BUS);
     if (rc < 0) {
         return rc;
     }
commit cf09458d644934976aa64e88bb41ef9a4cc2766a
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 14 16:01:05 2013 -0600

    pci: Move PCI and PCIE type defines
    
    Move these so that we can reference them from a more common header
    instead of including pci_bus.h everywhere.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.h b/hw/pci/pci.h
index d837a65..37fb522 100644
--- a/hw/pci/pci.h
+++ b/hw/pci/pci.h
@@ -339,6 +339,11 @@ typedef enum {
 
 typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
                               PCIHotplugState state);
+
+#define TYPE_PCI_BUS "PCI"
+#define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
+#define TYPE_PCIE_BUS "PCIE"
+
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name,
                          MemoryRegion *address_space_mem,
diff --git a/hw/pci/pci_bus.h b/hw/pci/pci_bus.h
index 6d3155f..6ee443c 100644
--- a/hw/pci/pci_bus.h
+++ b/hw/pci/pci_bus.h
@@ -8,10 +8,6 @@
  * use accessor functions in pci.h, pci_bridge.h
  */
 
-#define TYPE_PCI_BUS "PCI"
-#define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
-#define TYPE_PCIE_BUS "PCIE"
-
 struct PCIBus {
     BusState qbus;
     PCIDMAContextFunc dma_context_fn;
commit 3a861c466cee46fed042d76100fa0fd9644f3091
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 14 16:00:59 2013 -0600

    pci: Create and register a new PCI Express TypeInfo
    
    This will allow us to differentiate Express and Legacy buses.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 81028cb..74f449d 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -75,6 +75,11 @@ static const TypeInfo pci_bus_info = {
     .class_init = pci_bus_class_init,
 };
 
+static const TypeInfo pcie_bus_info = {
+    .name = TYPE_PCIE_BUS,
+    .parent = TYPE_PCI_BUS,
+};
+
 static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
 static void pci_update_mappings(PCIDevice *d);
 static void pci_set_irq(void *opaque, int irq_num, int level);
@@ -2236,6 +2241,7 @@ static const TypeInfo pci_device_type_info = {
 static void pci_register_types(void)
 {
     type_register_static(&pci_bus_info);
+    type_register_static(&pcie_bus_info);
     type_register_static(&pci_device_type_info);
 }
 
diff --git a/hw/pci/pci_bus.h b/hw/pci/pci_bus.h
index aef559a..6d3155f 100644
--- a/hw/pci/pci_bus.h
+++ b/hw/pci/pci_bus.h
@@ -10,6 +10,7 @@
 
 #define TYPE_PCI_BUS "PCI"
 #define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
+#define TYPE_PCIE_BUS "PCIE"
 
 struct PCIBus {
     BusState qbus;
commit 49cd9ac6a1929467e2df5783a5183fc7708ec3ff
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Mon Mar 11 10:20:21 2013 +0100

    exec: assert that RAMBlock size is non-zero
    
    find_ram_offset() does not handle size=0 gracefully.  It hands out the
    same RAMBlock offset multiple times, leading to obscure failures later
    on.
    
    Add an assert to warn early if something is incorrectly allocating a
    zero size RAMBlock.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/exec.c b/exec.c
index 8a6aac3..786987a 100644
--- a/exec.c
+++ b/exec.c
@@ -925,6 +925,8 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
     RAMBlock *block, *next_block;
     ram_addr_t offset = RAM_ADDR_MAX, mingap = RAM_ADDR_MAX;
 
+    assert(size != 0); /* it would hand out same offset multiple times */
+
     if (QTAILQ_EMPTY(&ram_list.blocks))
         return 0;
 
commit 8c7f3dd05e4f1ee90000c89e428e69ae2e6bd691
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Mon Mar 11 10:20:20 2013 +0100

    pci: refuse empty ROM files
    
    A zero size ROM file is invalid and should produce a warning.
    Attempting to use a zero size file ends up hitting an assertion
    qemu_ram_set_idstr() because RAMBlocks with duplicate addresses are
    allocated - due to zero size the allocator doesn't increment the next
    available RAMBlock offset.
    
    Also convert __FUNCTION__ to __func__ while we're touching this code.
    There are no other __FUNCTION__ instances in pci.c anymore.
    
    Reported-by: Milos Ivanovic <milosivanovic at orcon.net.nz>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index f24c389..81028cb 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1912,7 +1912,12 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
     size = get_image_size(path);
     if (size < 0) {
         error_report("%s: failed to find romfile \"%s\"",
-                     __FUNCTION__, pdev->romfile);
+                     __func__, pdev->romfile);
+        g_free(path);
+        return -1;
+    } else if (size == 0) {
+        error_report("%s: ignoring empty romfile \"%s\"",
+                     __func__, pdev->romfile);
         g_free(path);
         return -1;
     }
commit ea7cfed68bb4f26fc65b078ab735a4097e9b4fe2
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 7 16:17:00 2013 -0700

    pci_bridge: Remove duplicate IRQ swizzle function
    
    pci_bridge_dev_map_irq_fn() is identical to pci_swizzle_map_irq_fn(),
    which is now the default for all PCI bridges.  We can therefore remove
    this function and the pci_bridge_map_irq() call that used it.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci_bridge_dev.c b/hw/pci_bridge_dev.c
index 9cc6a40..840ef43 100644
--- a/hw/pci_bridge_dev.c
+++ b/hw/pci_bridge_dev.c
@@ -36,21 +36,12 @@ struct PCIBridgeDev {
 };
 typedef struct PCIBridgeDev PCIBridgeDev;
 
-/* Mapping mandated by PCI-to-PCI Bridge architecture specification,
- * revision 1.2 */
-/* Table 9-1: Interrupt Binding for Devices Behind a Bridge */
-static int pci_bridge_dev_map_irq_fn(PCIDevice *dev, int irq_num)
-{
-    return (irq_num + PCI_SLOT(dev->devfn)) % PCI_NUM_PINS;
-}
-
 static int pci_bridge_dev_initfn(PCIDevice *dev)
 {
     PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
     PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br);
     int err;
 
-    pci_bridge_map_irq(br, NULL, pci_bridge_dev_map_irq_fn);
     err = pci_bridge_initfn(dev);
     if (err) {
         goto bridge_error;
commit 659fefeed36a4b58191595cebab2dbc003788d90
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 7 16:16:54 2013 -0700

    pci_bridge: Use a default map_irq function
    
    The PCI bridge spec defines a default swizzle for translating INTx
    IRQs from secondary bus to primary.  Use this by default for any
    bridge that doesn't set a function.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index edb8c8d..bf93ac6 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -366,7 +366,7 @@ int pci_bridge_initfn(PCIDevice *dev)
     qbus_create_inplace(&sec_bus->qbus, TYPE_PCI_BUS, &dev->qdev,
                         br->bus_name);
     sec_bus->parent_dev = dev;
-    sec_bus->map_irq = br->map_irq;
+    sec_bus->map_irq = br->map_irq ? br->map_irq : pci_swizzle_map_irq_fn;
     sec_bus->address_space_mem = &br->address_space_mem;
     memory_region_init(&br->address_space_mem, "pci_bridge_pci", INT64_MAX);
     sec_bus->address_space_io = &br->address_space_io;
commit e5368f0da75c1c668e85398aa930be2f4273e684
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 7 11:29:19 2013 -0700

    pci: Fix INTx routing notifier recursion
    
    For some reason we recurse to fire the INTx routing notifier for each
    child of a bus, for each possible device of a bus.  That means that if
    we add a root port, the notifier gets called for that bridge 256
    times.  If we add an upstream switch behind that root port, 256^2.  But
    of course we need a downstream switch, 256^3.  This starts to be
    noticeable.  Stop the insanity.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 8772707..f24c389 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1215,9 +1215,10 @@ void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
         if (dev && dev->intx_routing_notifier) {
             dev->intx_routing_notifier(dev);
         }
-        QLIST_FOREACH(sec, &bus->child, sibling) {
-            pci_bus_fire_intx_routing_notifier(sec);
-        }
+    }
+
+    QLIST_FOREACH(sec, &bus->child, sibling) {
+        pci_bus_fire_intx_routing_notifier(sec);
     }
 }
 
commit 600d05b9aa4b4d23775fc17968dd6b581928001d
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Mar 4 11:31:21 2013 +0200

    pci_bridge: drop formatting from source
    
    We use the same formatting for all files, it
    doesn't make sense to have formatting directives only
    in pci bridge header.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci_bridge.h b/hw/pci/pci_bridge.h
index 9d25c1b..e549b78 100644
--- a/hw/pci/pci_bridge.h
+++ b/hw/pci/pci_bridge.h
@@ -63,11 +63,3 @@ void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
 #define  PCI_BRIDGE_CTL_DISCARD_SERR	0x800	/* Discard timer SERR# enable */
 
 #endif  /* QEMU_PCI_BRIDGE_H */
-/*
- * Local variables:
- *  c-indent-level: 4
- *  c-basic-offset: 4
- *  tab-width: 8
- *  indent-tab-mode: nil
- * End:
- */
commit 45eb768c706d3a5fbe55224c589e8b4e252781d9
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Mar 4 11:23:49 2013 +0200

    pci_bridge: factor out common code
    
    Reuse common code in pcie_port, override the hardwired-to-0
    bits per PCI Express spec.
    No functional change but makes the code easier to follow.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index a881602..8772707 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -668,16 +668,10 @@ static void pci_init_mask_bridge(PCIDevice *d)
     pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_LIMIT,
                                PCI_PREF_RANGE_TYPE_64);
 
-/* TODO: add this define to pci_regs.h in linux and then in qemu. */
-#define  PCI_BRIDGE_CTL_VGA_16BIT	0x10	/* VGA 16-bit decode */
-#define  PCI_BRIDGE_CTL_DISCARD		0x100	/* Primary discard timer */
-#define  PCI_BRIDGE_CTL_SEC_DISCARD	0x200	/* Secondary discard timer */
-#define  PCI_BRIDGE_CTL_DISCARD_STATUS	0x400	/* Discard timer status */
-#define  PCI_BRIDGE_CTL_DISCARD_SERR	0x800	/* Discard timer SERR# enable */
-/*
- * TODO: Bridges default to 10-bit VGA decoding but we currently only
- * implement 16-bit decoding (no alias support).
- */
+    /*
+     * TODO: Bridges default to 10-bit VGA decoding but we currently only
+     * implement 16-bit decoding (no alias support).
+     */
     pci_set_word(d->wmask + PCI_BRIDGE_CONTROL,
                  PCI_BRIDGE_CTL_PARITY |
                  PCI_BRIDGE_CTL_SERR |
diff --git a/hw/pci/pci_bridge.h b/hw/pci/pci_bridge.h
index 455cb66..9d25c1b 100644
--- a/hw/pci/pci_bridge.h
+++ b/hw/pci/pci_bridge.h
@@ -55,6 +55,13 @@ void pci_bridge_exitfn(PCIDevice *pci_dev);
 void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
                         pci_map_irq_fn map_irq);
 
+/* TODO: add this define to pci_regs.h in linux and then in qemu. */
+#define  PCI_BRIDGE_CTL_VGA_16BIT	0x10	/* VGA 16-bit decode */
+#define  PCI_BRIDGE_CTL_DISCARD		0x100	/* Primary discard timer */
+#define  PCI_BRIDGE_CTL_SEC_DISCARD	0x200	/* Secondary discard timer */
+#define  PCI_BRIDGE_CTL_DISCARD_STATUS	0x400	/* Discard timer status */
+#define  PCI_BRIDGE_CTL_DISCARD_SERR	0x800	/* Discard timer SERR# enable */
+
 #endif  /* QEMU_PCI_BRIDGE_H */
 /*
  * Local variables:
diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c
index 1be107b..91b53a0 100644
--- a/hw/pci/pcie_port.c
+++ b/hw/pci/pcie_port.c
@@ -27,15 +27,17 @@ void pcie_port_init_reg(PCIDevice *d)
     pci_set_word(d->config + PCI_STATUS, 0);
     pci_set_word(d->config + PCI_SEC_STATUS, 0);
 
-    /* Unlike conventional pci bridge, some bits are hardwired to 0. */
-#define  PCI_BRIDGE_CTL_VGA_16BIT       0x10    /* VGA 16-bit decode */
-    pci_set_word(d->wmask + PCI_BRIDGE_CONTROL,
-                 PCI_BRIDGE_CTL_PARITY |
-                 PCI_BRIDGE_CTL_ISA |
-                 PCI_BRIDGE_CTL_VGA |
-                 PCI_BRIDGE_CTL_VGA_16BIT | /* Req, but no alias support yet */
-                 PCI_BRIDGE_CTL_SERR |
-                 PCI_BRIDGE_CTL_BUS_RESET);
+    /*
+     * Unlike conventional pci bridge, for some bits the spec states:
+     * Does not apply to PCI Express and must be hardwired to 0.
+     */
+    pci_word_test_and_clear_mask(d->wmask + PCI_BRIDGE_CONTROL,
+                                 PCI_BRIDGE_CTL_MASTER_ABORT |
+                                 PCI_BRIDGE_CTL_FAST_BACK |
+                                 PCI_BRIDGE_CTL_DISCARD |
+                                 PCI_BRIDGE_CTL_SEC_DISCARD |
+                                 PCI_BRIDGE_CTL_DISCARD_STATUS |
+                                 PCI_BRIDGE_CTL_DISCARD_SERR);
 }
 
 /**************************************************************************
commit ba7d8515c1e929baccea9f53d06d131fd2b007a1
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Sun Mar 3 10:21:32 2013 -0700

    pci: Teach PCI Bridges about VGA routing
    
    Each PCI Bridge has a set of implied VGA regions that are enabled when
    the VGA bit is set in the bridge control register.  This allows VGA
    devices behind bridges.  Unfortunately with VGA Enable, which we
    formerly allowed but didn't back, comes along some required VGA
    baggage.  VGA Palette Snooping is required, along with VGA 16-bit
    decoding.  We don't yet have support for palette snooping.
    We also don't have support for 10-bit VGA aliases, the default mode, but
    we enable the register, even on root ports, to avoid confusing guests.
    Fortunately there's likely nothing from this century that requires these
    features, so the missing bits are noted with TODOs.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index ed43111..a881602 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -674,6 +674,10 @@ static void pci_init_mask_bridge(PCIDevice *d)
 #define  PCI_BRIDGE_CTL_SEC_DISCARD	0x200	/* Secondary discard timer */
 #define  PCI_BRIDGE_CTL_DISCARD_STATUS	0x400	/* Discard timer status */
 #define  PCI_BRIDGE_CTL_DISCARD_SERR	0x800	/* Discard timer SERR# enable */
+/*
+ * TODO: Bridges default to 10-bit VGA decoding but we currently only
+ * implement 16-bit decoding (no alias support).
+ */
     pci_set_word(d->wmask + PCI_BRIDGE_CONTROL,
                  PCI_BRIDGE_CTL_PARITY |
                  PCI_BRIDGE_CTL_SERR |
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 995842a..edb8c8d 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -151,6 +151,28 @@ static void pci_bridge_init_alias(PCIBridge *bridge, MemoryRegion *alias,
     memory_region_add_subregion_overlap(parent_space, base, alias, 1);
 }
 
+static void pci_bridge_init_vga_aliases(PCIBridge *br, PCIBus *parent,
+                                        MemoryRegion *alias_vga)
+{
+    uint16_t brctl = pci_get_word(br->dev.config + PCI_BRIDGE_CONTROL);
+
+    memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_LO],
+                             "pci_bridge_vga_io_lo", &br->address_space_io,
+                             QEMU_PCI_VGA_IO_LO_BASE, QEMU_PCI_VGA_IO_LO_SIZE);
+    memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_HI],
+                             "pci_bridge_vga_io_hi", &br->address_space_io,
+                             QEMU_PCI_VGA_IO_HI_BASE, QEMU_PCI_VGA_IO_HI_SIZE);
+    memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_MEM],
+                             "pci_bridge_vga_mem", &br->address_space_mem,
+                             QEMU_PCI_VGA_MEM_BASE, QEMU_PCI_VGA_MEM_SIZE);
+
+    if (brctl & PCI_BRIDGE_CTL_VGA) {
+        pci_register_vga(&br->dev, &alias_vga[QEMU_PCI_VGA_MEM],
+                         &alias_vga[QEMU_PCI_VGA_IO_LO],
+                         &alias_vga[QEMU_PCI_VGA_IO_HI]);
+    }
+}
+
 static PCIBridgeWindows *pci_bridge_region_init(PCIBridge *br)
 {
     PCIBus *parent = br->dev.bus;
@@ -175,7 +197,8 @@ static PCIBridgeWindows *pci_bridge_region_init(PCIBridge *br)
                           &br->address_space_io,
                           parent->address_space_io,
                           cmd & PCI_COMMAND_IO);
-   /* TODO: optinal VGA and VGA palette snooping support. */
+
+    pci_bridge_init_vga_aliases(br, parent, w->alias_vga);
 
     return w;
 }
@@ -187,6 +210,7 @@ static void pci_bridge_region_del(PCIBridge *br, PCIBridgeWindows *w)
     memory_region_del_subregion(parent->address_space_io, &w->alias_io);
     memory_region_del_subregion(parent->address_space_mem, &w->alias_mem);
     memory_region_del_subregion(parent->address_space_mem, &w->alias_pref_mem);
+    pci_unregister_vga(&br->dev);
 }
 
 static void pci_bridge_region_cleanup(PCIBridge *br, PCIBridgeWindows *w)
@@ -194,6 +218,9 @@ static void pci_bridge_region_cleanup(PCIBridge *br, PCIBridgeWindows *w)
     memory_region_destroy(&w->alias_io);
     memory_region_destroy(&w->alias_mem);
     memory_region_destroy(&w->alias_pref_mem);
+    memory_region_destroy(&w->alias_vga[QEMU_PCI_VGA_IO_LO]);
+    memory_region_destroy(&w->alias_vga[QEMU_PCI_VGA_IO_HI]);
+    memory_region_destroy(&w->alias_vga[QEMU_PCI_VGA_MEM]);
     g_free(w);
 }
 
@@ -227,7 +254,10 @@ void pci_bridge_write_config(PCIDevice *d,
 
         /* memory base/limit, prefetchable base/limit and
            io base/limit upper 16 */
-        ranges_overlap(address, len, PCI_MEMORY_BASE, 20)) {
+        ranges_overlap(address, len, PCI_MEMORY_BASE, 20) ||
+
+        /* vga enable */
+        ranges_overlap(address, len, PCI_BRIDGE_CONTROL, 2)) {
         pci_bridge_update_mappings(s);
     }
 
@@ -306,6 +336,16 @@ int pci_bridge_initfn(PCIDevice *dev)
 
     pci_word_test_and_set_mask(dev->config + PCI_STATUS,
                                PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
+
+    /*
+     * TODO: We implement VGA Enable in the Bridge Control Register
+     * therefore per the PCI to PCI bridge spec we must also implement
+     * VGA Palette Snooping.  When done, set this bit writable:
+     *
+     * pci_word_test_and_set_mask(dev->wmask + PCI_COMMAND,
+     *                            PCI_COMMAND_VGA_PALETTE);
+     */
+
     pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_PCI);
     dev->config[PCI_HEADER_TYPE] =
         (dev->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) |
diff --git a/hw/pci/pci_bus.h b/hw/pci/pci_bus.h
index f905b9e..aef559a 100644
--- a/hw/pci/pci_bus.h
+++ b/hw/pci/pci_bus.h
@@ -47,6 +47,13 @@ struct PCIBridgeWindows {
     MemoryRegion alias_pref_mem;
     MemoryRegion alias_mem;
     MemoryRegion alias_io;
+    /*
+     * When bridge control VGA forwarding is enabled, bridges will
+     * provide positive decode on the PCI VGA defined I/O port and
+     * MMIO ranges.  When enabled forwarding is only qualified on the
+     * I/O and memory enable bits in the bridge command register.
+     */
+    MemoryRegion alias_vga[QEMU_PCI_VGA_NUM_REGIONS];
 };
 
 struct PCIBridge {
diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c
index 33a6b0a..1be107b 100644
--- a/hw/pci/pcie_port.c
+++ b/hw/pci/pcie_port.c
@@ -28,10 +28,12 @@ void pcie_port_init_reg(PCIDevice *d)
     pci_set_word(d->config + PCI_SEC_STATUS, 0);
 
     /* Unlike conventional pci bridge, some bits are hardwired to 0. */
+#define  PCI_BRIDGE_CTL_VGA_16BIT       0x10    /* VGA 16-bit decode */
     pci_set_word(d->wmask + PCI_BRIDGE_CONTROL,
                  PCI_BRIDGE_CTL_PARITY |
                  PCI_BRIDGE_CTL_ISA |
                  PCI_BRIDGE_CTL_VGA |
+                 PCI_BRIDGE_CTL_VGA_16BIT | /* Req, but no alias support yet */
                  PCI_BRIDGE_CTL_SERR |
                  PCI_BRIDGE_CTL_BUS_RESET);
 }
commit e01fd687185444944b0b5b0f8c739ae4b33eb029
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Sun Mar 3 10:21:26 2013 -0700

    pci: Add PCI VGA helpers
    
    Allow devices to register VGA memory regions for handling PCI spec
    defined VGA I/O port and MMIO areas.  PCI will attach these to the
    bus address spaces and enable them according to the device command
    register value.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 2f45c8f..ed43111 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -875,6 +875,8 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
             continue;
         memory_region_del_subregion(r->address_space, r->memory);
     }
+
+    pci_unregister_vga(pci_dev);
 }
 
 static int pci_unregister_device(DeviceState *dev)
@@ -937,6 +939,63 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
         : pci_dev->bus->address_space_mem;
 }
 
+static void pci_update_vga(PCIDevice *pci_dev)
+{
+    uint16_t cmd;
+
+    if (!pci_dev->has_vga) {
+        return;
+    }
+
+    cmd = pci_get_word(pci_dev->config + PCI_COMMAND);
+
+    memory_region_set_enabled(pci_dev->vga_regions[QEMU_PCI_VGA_MEM],
+                              cmd & PCI_COMMAND_MEMORY);
+    memory_region_set_enabled(pci_dev->vga_regions[QEMU_PCI_VGA_IO_LO],
+                              cmd & PCI_COMMAND_IO);
+    memory_region_set_enabled(pci_dev->vga_regions[QEMU_PCI_VGA_IO_HI],
+                              cmd & PCI_COMMAND_IO);
+}
+
+void pci_register_vga(PCIDevice *pci_dev, MemoryRegion *mem,
+                      MemoryRegion *io_lo, MemoryRegion *io_hi)
+{
+    assert(!pci_dev->has_vga);
+
+    assert(memory_region_size(mem) == QEMU_PCI_VGA_MEM_SIZE);
+    pci_dev->vga_regions[QEMU_PCI_VGA_MEM] = mem;
+    memory_region_add_subregion_overlap(pci_dev->bus->address_space_mem,
+                                        QEMU_PCI_VGA_MEM_BASE, mem, 1);
+
+    assert(memory_region_size(io_lo) == QEMU_PCI_VGA_IO_LO_SIZE);
+    pci_dev->vga_regions[QEMU_PCI_VGA_IO_LO] = io_lo;
+    memory_region_add_subregion_overlap(pci_dev->bus->address_space_io,
+                                        QEMU_PCI_VGA_IO_LO_BASE, io_lo, 1);
+
+    assert(memory_region_size(io_hi) == QEMU_PCI_VGA_IO_HI_SIZE);
+    pci_dev->vga_regions[QEMU_PCI_VGA_IO_HI] = io_hi;
+    memory_region_add_subregion_overlap(pci_dev->bus->address_space_io,
+                                        QEMU_PCI_VGA_IO_HI_BASE, io_hi, 1);
+    pci_dev->has_vga = true;
+
+    pci_update_vga(pci_dev);
+}
+
+void pci_unregister_vga(PCIDevice *pci_dev)
+{
+    if (!pci_dev->has_vga) {
+        return;
+    }
+
+    memory_region_del_subregion(pci_dev->bus->address_space_mem,
+                                pci_dev->vga_regions[QEMU_PCI_VGA_MEM]);
+    memory_region_del_subregion(pci_dev->bus->address_space_io,
+                                pci_dev->vga_regions[QEMU_PCI_VGA_IO_LO]);
+    memory_region_del_subregion(pci_dev->bus->address_space_io,
+                                pci_dev->vga_regions[QEMU_PCI_VGA_IO_HI]);
+    pci_dev->has_vga = false;
+}
+
 pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num)
 {
     return pci_dev->io_regions[region_num].addr;
@@ -1036,6 +1095,8 @@ static void pci_update_mappings(PCIDevice *d)
                                                 r->addr, r->memory, 1);
         }
     }
+
+    pci_update_vga(d);
 }
 
 static inline int pci_irq_disabled(PCIDevice *d)
diff --git a/hw/pci/pci.h b/hw/pci/pci.h
index f340fe5..d837a65 100644
--- a/hw/pci/pci.h
+++ b/hw/pci/pci.h
@@ -108,6 +108,20 @@ typedef struct PCIIORegion {
 #define PCI_ROM_SLOT 6
 #define PCI_NUM_REGIONS 7
 
+enum {
+    QEMU_PCI_VGA_MEM,
+    QEMU_PCI_VGA_IO_LO,
+    QEMU_PCI_VGA_IO_HI,
+    QEMU_PCI_VGA_NUM_REGIONS,
+};
+
+#define QEMU_PCI_VGA_MEM_BASE 0xa0000
+#define QEMU_PCI_VGA_MEM_SIZE 0x20000
+#define QEMU_PCI_VGA_IO_LO_BASE 0x3b0
+#define QEMU_PCI_VGA_IO_LO_SIZE 0xc
+#define QEMU_PCI_VGA_IO_HI_BASE 0x3c0
+#define QEMU_PCI_VGA_IO_HI_SIZE 0x20
+
 #include "hw/pci/pci_regs.h"
 
 /* PCI HEADER_TYPE */
@@ -234,6 +248,10 @@ struct PCIDevice {
     /* IRQ objects for the INTA-INTD pins.  */
     qemu_irq *irq;
 
+    /* Legacy PCI VGA regions */
+    MemoryRegion *vga_regions[QEMU_PCI_VGA_NUM_REGIONS];
+    bool has_vga;
+
     /* Current IRQ levels.  Used internally by the generic PCI code.  */
     uint8_t irq_state;
 
@@ -287,6 +305,9 @@ struct PCIDevice {
 
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
                       uint8_t attr, MemoryRegion *memory);
+void pci_register_vga(PCIDevice *pci_dev, MemoryRegion *mem,
+                      MemoryRegion *io_lo, MemoryRegion *io_hi);
+void pci_unregister_vga(PCIDevice *pci_dev);
 pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num);
 
 int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
commit a38b2c49bfd3f1cfc2aadd08cd049af16a342b1e
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Mar 13 21:37:08 2013 +0200

    virtio-pci: guest notifier mask without non-irqfd
    
    non-irqfd setups are currently broken with vhost:
    we start up masked and nothing unmasks the interrupts.
    Fix by using mask notifiers, same as the irqfd path.
    
    Sharing irqchip/non irqchip code is always a good thing,
    in this case it will help non irqchip benefit
    from backend masking optimization.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 39c1966..19965e5 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -609,20 +609,23 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs)
     }
 }
 
-static int kvm_virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
-                                        unsigned int queue_no,
-                                        unsigned int vector,
-                                        MSIMessage msg)
+static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
+                                       unsigned int queue_no,
+                                       unsigned int vector,
+                                       MSIMessage msg)
 {
     VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
     EventNotifier *n = virtio_queue_get_guest_notifier(vq);
-    VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
+    VirtIOIRQFD *irqfd;
     int ret = 0;
 
-    if (irqfd->msg.data != msg.data || irqfd->msg.address != msg.address) {
-        ret = kvm_irqchip_update_msi_route(kvm_state, irqfd->virq, msg);
-        if (ret < 0) {
-            return ret;
+    if (proxy->vector_irqfd) {
+        irqfd = &proxy->vector_irqfd[vector];
+        if (irqfd->msg.data != msg.data || irqfd->msg.address != msg.address) {
+            ret = kvm_irqchip_update_msi_route(kvm_state, irqfd->virq, msg);
+            if (ret < 0) {
+                return ret;
+            }
         }
     }
 
@@ -642,7 +645,7 @@ static int kvm_virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
     return ret;
 }
 
-static void kvm_virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy,
+static void virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy,
                                              unsigned int queue_no,
                                              unsigned int vector)
 {
@@ -656,8 +659,8 @@ static void kvm_virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy,
     }
 }
 
-static int kvm_virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector,
-                                     MSIMessage msg)
+static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector,
+                                    MSIMessage msg)
 {
     VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
     VirtIODevice *vdev = proxy->vdev;
@@ -670,7 +673,7 @@ static int kvm_virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector,
         if (virtio_queue_vector(vdev, queue_no) != vector) {
             continue;
         }
-        ret = kvm_virtio_pci_vq_vector_unmask(proxy, queue_no, vector, msg);
+        ret = virtio_pci_vq_vector_unmask(proxy, queue_no, vector, msg);
         if (ret < 0) {
             goto undo;
         }
@@ -682,12 +685,12 @@ undo:
         if (virtio_queue_vector(vdev, queue_no) != vector) {
             continue;
         }
-        kvm_virtio_pci_vq_vector_mask(proxy, queue_no, vector);
+        virtio_pci_vq_vector_mask(proxy, queue_no, vector);
     }
     return ret;
 }
 
-static void kvm_virtio_pci_vector_mask(PCIDevice *dev, unsigned vector)
+static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector)
 {
     VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
     VirtIODevice *vdev = proxy->vdev;
@@ -700,13 +703,13 @@ static void kvm_virtio_pci_vector_mask(PCIDevice *dev, unsigned vector)
         if (virtio_queue_vector(vdev, queue_no) != vector) {
             continue;
         }
-        kvm_virtio_pci_vq_vector_mask(proxy, queue_no, vector);
+        virtio_pci_vq_vector_mask(proxy, queue_no, vector);
     }
 }
 
-static void kvm_virtio_pci_vector_poll(PCIDevice *dev,
-                                       unsigned int vector_start,
-                                       unsigned int vector_end)
+static void virtio_pci_vector_poll(PCIDevice *dev,
+                                   unsigned int vector_start,
+                                   unsigned int vector_end)
 {
     VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
     VirtIODevice *vdev = proxy->vdev;
@@ -781,11 +784,13 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign)
     proxy->nvqs_with_notifiers = nvqs;
 
     /* Must unset vector notifier while guest notifier is still assigned */
-    if (proxy->vector_irqfd && !assign) {
+    if ((proxy->vector_irqfd || vdev->guest_notifier_mask) && !assign) {
         msix_unset_vector_notifiers(&proxy->pci_dev);
-        kvm_virtio_pci_vector_release(proxy, nvqs);
-        g_free(proxy->vector_irqfd);
-        proxy->vector_irqfd = NULL;
+        if (proxy->vector_irqfd) {
+            kvm_virtio_pci_vector_release(proxy, nvqs);
+            g_free(proxy->vector_irqfd);
+            proxy->vector_irqfd = NULL;
+        }
     }
 
     for (n = 0; n < nvqs; n++) {
@@ -801,18 +806,20 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign)
     }
 
     /* Must set vector notifier after guest notifier has been assigned */
-    if (with_irqfd && assign) {
-        proxy->vector_irqfd =
-            g_malloc0(sizeof(*proxy->vector_irqfd) *
-                      msix_nr_vectors_allocated(&proxy->pci_dev));
-        r = kvm_virtio_pci_vector_use(proxy, nvqs);
-        if (r < 0) {
-            goto assign_error;
+    if ((with_irqfd || vdev->guest_notifier_mask) && assign) {
+        if (with_irqfd) {
+            proxy->vector_irqfd =
+                g_malloc0(sizeof(*proxy->vector_irqfd) *
+                          msix_nr_vectors_allocated(&proxy->pci_dev));
+            r = kvm_virtio_pci_vector_use(proxy, nvqs);
+            if (r < 0) {
+                goto assign_error;
+            }
         }
         r = msix_set_vector_notifiers(&proxy->pci_dev,
-                                      kvm_virtio_pci_vector_unmask,
-                                      kvm_virtio_pci_vector_mask,
-                                      kvm_virtio_pci_vector_poll);
+                                      virtio_pci_vector_unmask,
+                                      virtio_pci_vector_mask,
+                                      virtio_pci_vector_poll);
         if (r < 0) {
             goto notifiers_error;
         }
@@ -821,8 +828,10 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign)
     return 0;
 
 notifiers_error:
-    assert(assign);
-    kvm_virtio_pci_vector_release(proxy, nvqs);
+    if (with_irqfd) {
+        assert(assign);
+        kvm_virtio_pci_vector_release(proxy, nvqs);
+    }
 
 assign_error:
     /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
commit f8f7c533e20d1681feeb665109301151bdb739b4
Author: Jason Wang <jasowang at redhat.com>
Date:   Wed Mar 6 13:50:27 2013 +0800

    virtio-net: remove layout assumptions for mq ctrl
    
    Following commit 921ac5d0f3a0df869db5ce4edf752f51d8b1596a (virtio-net:
    remove layout assumptions for ctrl vq), this patch makes multiqueue ctrl
    handling not rely on the layout of descriptors.
    
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 8c9d871..4590557 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -578,13 +578,14 @@ static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd,
 }
 
 static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd,
-                                VirtQueueElement *elem)
+                                struct iovec *iov, unsigned int iov_cnt)
 {
-    struct virtio_net_ctrl_mq s;
+    struct virtio_net_ctrl_mq mq;
+    size_t s;
+    uint16_t queues;
 
-    if (elem->out_num != 2 ||
-        elem->out_sg[1].iov_len != sizeof(struct virtio_net_ctrl_mq)) {
-        error_report("virtio-net ctrl invalid steering command");
+    s = iov_to_buf(iov, iov_cnt, 0, &mq, sizeof(mq));
+    if (s != sizeof(mq)) {
         return VIRTIO_NET_ERR;
     }
 
@@ -592,16 +593,16 @@ static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd,
         return VIRTIO_NET_ERR;
     }
 
-    memcpy(&s, elem->out_sg[1].iov_base, sizeof(struct virtio_net_ctrl_mq));
+    queues = lduw_p(&mq.virtqueue_pairs);
 
-    if (s.virtqueue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN ||
-        s.virtqueue_pairs > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX ||
-        s.virtqueue_pairs > n->max_queues ||
+    if (queues < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN ||
+        queues > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX ||
+        queues > n->max_queues ||
         !n->multiqueue) {
         return VIRTIO_NET_ERR;
     }
 
-    n->curr_queues = s.virtqueue_pairs;
+    n->curr_queues = queues;
     /* stop the backend before changing the number of queues to avoid handling a
      * disabled queue */
     virtio_net_set_status(&n->vdev, n->vdev.status);
@@ -639,7 +640,7 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
         } else if (ctrl.class == VIRTIO_NET_CTRL_VLAN) {
             status = virtio_net_handle_vlan_table(n, ctrl.cmd, iov, iov_cnt);
         } else if (ctrl.class == VIRTIO_NET_CTRL_MQ) {
-            status = virtio_net_handle_mq(n, ctrl.cmd, &elem);
+            status = virtio_net_handle_mq(n, ctrl.cmd, iov, iov_cnt);
         }
 
         s = iov_from_buf(elem.in_sg, elem.in_num, 0, &status, sizeof(status));
commit 15054fce2df8592dec70bba23faf126f0f372f81
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Mar 11 15:11:04 2013 +0200

    qmp: add path to device_deleted event
    
    Add QOM path to device deleted event.  It now becomes useful to report
    it for devices which don't have an ID assigned.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt
index 24cf3e8..dcc826d 100644
--- a/QMP/qmp-events.txt
+++ b/QMP/qmp-events.txt
@@ -147,9 +147,11 @@ Device removal can be initiated by the guest or by HMP/QMP commands.
 Data:
 
 - "device": device name (json-string, optional)
+- "path": device path (json-string)
 
 { "event": "DEVICE_DELETED",
-  "data": { "device": "virtio-net-pci-0" },
+  "data": { "device": "virtio-net-pci-0",
+            "path": "/machine/peripheral/virtio-net-pci-0" },
   "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
 
 DEVICE_TRAY_MOVED
diff --git a/hw/qdev.c b/hw/qdev.c
index 5e8a89c..0cdf568 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -764,6 +764,7 @@ static void device_unparent(Object *obj)
     DeviceClass *dc = DEVICE_GET_CLASS(dev);
     BusState *bus;
     QObject *event_data;
+    gchar *path = object_get_canonical_path(obj);
 
     while (dev->num_child_bus) {
         bus = QLIST_FIRST(&dev->child_bus);
@@ -784,12 +785,14 @@ static void device_unparent(Object *obj)
     }
 
     if (dev->id) {
-        event_data = qobject_from_jsonf("{ 'device': %s }", dev->id);
+        event_data = qobject_from_jsonf("{ 'device': %s, 'path': %s }",
+                                        dev->id, path);
     } else {
-        event_data = qobject_from_jsonf("{ }");
+        event_data = qobject_from_jsonf("{ 'path': %s }", path);
     }
     monitor_protocol_event(QEVENT_DEVICE_DELETED, event_data);
     qobject_decref(event_data);
+    g_free(path);
 }
 
 static void device_class_init(ObjectClass *class, void *data)
commit e998fa8df828ef68ea540a12917d10b4d335c1dd
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Mar 18 21:01:37 2013 +0200

    qom: call class destructor before unparent
    
    It seems more logical to have destruction flow start with the subclass
    and move up to the base class.  This ensures object has a valid
    canonical path when destructor is called.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/qom/object.c b/qom/object.c
index 3d638ff..a0e3cbe 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -363,12 +363,12 @@ static void object_property_del_child(Object *obj, Object *child, Error **errp)
 void object_unparent(Object *obj)
 {
     object_ref(obj);
-    if (obj->parent) {
-        object_property_del_child(obj->parent, obj, NULL);
-    }
     if (obj->class->unparent) {
         (obj->class->unparent)(obj);
     }
+    if (obj->parent) {
+        object_property_del_child(obj->parent, obj, NULL);
+    }
     object_unref(obj);
 }
 
commit 18501ae6e825d8da72369fd091018ef71071bd87
Merge: fad5593 500f006
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 26 13:38:00 2013 -0500

    Merge remote-tracking branch 'quintela/migration.next' into staging
    
    # By Peter Lieven (9) and others
    # Via Juan Quintela
    * quintela/migration.next: (22 commits)
      Use qemu_put_buffer_async for guest memory pages
      Add qemu_put_buffer_async
      Use writev ops if available
      Store the data to send also in iovec
      Update bytes_xfer in qemu_put_byte
      Add socket_writev_buffer function
      Add QemuFileWritevBuffer QemuFileOps
      migration: use XBZRLE only after bulk stage
      migration: do not search dirty pages in bulk stage
      migration: do not sent zero pages in bulk stage
      migration: add an indicator for bulk state of ram migration
      migration: search for zero instead of dup pages
      bitops: unroll while loop in find_next_bit()
      buffer_is_zero: use vector optimizations if possible
      cutils: add a function to find non-zero content in a buffer
      move vector definitions to qemu-common.h
      savevm: Fix bugs in the VMSTATE_VBUFFER_MULTIPLY definition
      savevm: Add VMSTATE_STRUCT_VARRAY_POINTER_UINT32
      savevm: Add VMSTATE_FLOAT64 helpers
      savevm: Add VMSTATE_UINTTL_EQUAL helper
      ...

commit fad5593ca646010d3cb83f7926d78dd30c20c610
Merge: 0fbf01f b57ed9b
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 26 13:34:38 2013 -0500

    Merge remote-tracking branch 'cohuck/virtio-ccw-upstr' into staging
    
    # By Cornelia Huck
    # Via Cornelia Huck
    * cohuck/virtio-ccw-upstr:
      virtio-ccw: Queue sanity check for notify hypercall.

commit b57ed9bf075e33cdd2f9eb545ff555301dd57221
Author: Cornelia Huck <cornelia.huck at de.ibm.com>
Date:   Tue Mar 26 17:32:44 2013 +0100

    virtio-ccw: Queue sanity check for notify hypercall.
    
    Verify that the virtio-ccw notify hypercall passed a reasonable
    value for queue.
    
    Cc: qemu-stable at nongnu.org
    Reported-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com>

diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index d436414..76b63e2 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -31,6 +31,9 @@ static int virtio_ccw_hcall_notify(const uint64_t *args)
     if (!sch || !css_subch_visible(sch)) {
         return -EINVAL;
     }
+    if (queue >= VIRTIO_PCI_QUEUE_MAX) {
+        return -EINVAL;
+    }
     virtio_queue_notify(virtio_ccw_get_vdev(sch), queue);
     return 0;
 
commit 0fbf01fe911e84c588be41636570f46f597113d6
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 26 10:04:43 2013 -0500

    qtest: use synchronous I/O for char device
    
    Peter reported that rtc-test would periodically hang.  It turns out
    this was due to an EAGAIN occurring on qemu_chr_fe_write.
    
    Instead of heavily refactoring qtest, just use a synchronous version
    of the write operation for qemu_chr_fe_write to address this problem.
    
    Reported-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qtest.c b/qtest.c
index 5e0e9ec..b03b68a 100644
--- a/qtest.c
+++ b/qtest.c
@@ -191,7 +191,7 @@ static void GCC_FMT_ATTR(2, 3) qtest_send(CharDriverState *chr,
     len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
     va_end(ap);
 
-    qemu_chr_fe_write(chr, (uint8_t *)buffer, len);
+    qemu_chr_fe_write_all(chr, (uint8_t *)buffer, len);
     if (qtest_log_fp && qtest_opened) {
         fprintf(qtest_log_fp, "%s", buffer);
     }
commit cd18720a294bd7244ffda719677dd9c737317b67
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 26 10:04:17 2013 -0500

    char: introduce a blocking version of qemu_chr_fe_write
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/char/char.h b/include/char/char.h
index 0326b2a..5c3a7a5 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -170,6 +170,21 @@ int qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
 int qemu_chr_fe_write(CharDriverState *s, const uint8_t *buf, int len);
 
 /**
+ * @qemu_chr_fe_write_all:
+ *
+ * Write data to a character backend from the front end.  This function will
+ * send data from the front end to the back end.  Unlike @qemu_chr_fe_write,
+ * this function will block if the back end cannot consume all of the data
+ * attempted to be written.
+ *
+ * @buf the data
+ * @len the number of bytes to send
+ *
+ * Returns: the number of bytes consumed
+ */
+int qemu_chr_fe_write_all(CharDriverState *s, const uint8_t *buf, int len);
+
+/**
  * @qemu_chr_fe_ioctl:
  *
  * Issue a device specific ioctl to a backend.
diff --git a/qemu-char.c b/qemu-char.c
index 4e011df..936150f 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -140,6 +140,33 @@ int qemu_chr_fe_write(CharDriverState *s, const uint8_t *buf, int len)
     return s->chr_write(s, buf, len);
 }
 
+int qemu_chr_fe_write_all(CharDriverState *s, const uint8_t *buf, int len)
+{
+    int offset = 0;
+    int res;
+
+    while (offset < len) {
+        do {
+            res = s->chr_write(s, buf + offset, len - offset);
+            if (res == -1 && errno == EAGAIN) {
+                g_usleep(100);
+            }
+        } while (res == -1 && errno == EAGAIN);
+
+        if (res == 0) {
+            break;
+        }
+
+        if (res < 0) {
+            return res;
+        }
+
+        offset += res;
+    }
+
+    return offset;
+}
+
 int qemu_chr_fe_ioctl(CharDriverState *s, int cmd, void *arg)
 {
     if (!s->chr_ioctl)
commit e769bdc26ded6d7681cddd9f67c5f87a4b5ba53c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Mar 25 13:15:14 2013 +0000

    hw/qdev: Abort rather than ignoring errors adding device properties
    
    Instead of ignoring any errors that occur when adding properties
    to a new device in device_initfn(), check for them and abort if any
    occur. The most likely cause is accidentally adding a duplicate
    property, which is a programming error by the device author.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1364217314-7400-3-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 04ec456..6b1947e 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -710,6 +710,7 @@ static void device_initfn(Object *obj)
     DeviceState *dev = DEVICE(obj);
     ObjectClass *class;
     Property *prop;
+    Error *err = NULL;
 
     if (qdev_hotplug) {
         dev->hotplugged = 1;
@@ -725,15 +726,18 @@ static void device_initfn(Object *obj)
     class = object_get_class(OBJECT(dev));
     do {
         for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) {
-            qdev_property_add_legacy(dev, prop, NULL);
-            qdev_property_add_static(dev, prop, NULL);
+            qdev_property_add_legacy(dev, prop, &err);
+            assert_no_error(err);
+            qdev_property_add_static(dev, prop, &err);
+            assert_no_error(err);
         }
         class = object_class_get_parent(class);
     } while (class != object_class_by_name(TYPE_DEVICE));
     qdev_prop_set_globals(dev);
 
     object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
-                             (Object **)&dev->parent_bus, NULL);
+                             (Object **)&dev->parent_bus, &err);
+    assert_no_error(err);
 }
 
 /* Unlink device from bus and free the structure.  */
commit 54852b03711f06c5f24af72de583346922176947
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Mar 25 13:15:13 2013 +0000

    qom: Detect attempts to add a property that already exists
    
    Detect attempts to add a property to an object if one of
    that name already exists, and report them as errors.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1364217314-7400-2-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qom/object.c b/qom/object.c
index 3d638ff..3f77968 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -629,7 +629,18 @@ void object_property_add(Object *obj, const char *name, const char *type,
                          ObjectPropertyRelease *release,
                          void *opaque, Error **errp)
 {
-    ObjectProperty *prop = g_malloc0(sizeof(*prop));
+    ObjectProperty *prop;
+
+    QTAILQ_FOREACH(prop, &obj->properties, node) {
+        if (strcmp(prop->name, name) == 0) {
+            error_setg(errp, "attempt to add duplicate property '%s'"
+                       " to object (type '%s')", name,
+                       object_get_typename(obj));
+            return;
+        }
+    }
+
+    prop = g_malloc0(sizeof(*prop));
 
     prop->name = g_strdup(name);
     prop->type = g_strdup(type);
commit b000dfbd42e8aac9af66ae0ed787ef1021bea29f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Mar 25 13:40:44 2013 +0000

    hw/qdev-properties.c: Improve diagnostic for setting property after realize
    
    Now we have error_setg() we can improve the error message emitted if
    you attempt to set a property of a device after the device is realized
    (the previous message was "permission denied" which was not very
    informative).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1364218844-7509-1-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev-addr.c b/hw/qdev-addr.c
index 2398b4a..80a38bb 100644
--- a/hw/qdev-addr.c
+++ b/hw/qdev-addr.c
@@ -42,7 +42,7 @@ static void set_taddr(Object *obj, Visitor *v, void *opaque,
     int64_t value;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c
index 8795144..28813d3 100644
--- a/hw/qdev-properties-system.c
+++ b/hw/qdev-properties-system.c
@@ -43,7 +43,7 @@ static void set_pointer(Object *obj, Visitor *v, Property *prop,
     int ret;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -287,7 +287,7 @@ static void set_vlan(Object *obj, Visitor *v, void *opaque,
     NetClientState *hubport;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 247ca6c..168c466 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -7,6 +7,20 @@
 #include "qapi/visitor.h"
 #include "char/char.h"
 
+void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
+                                  Error **errp)
+{
+    if (dev->id) {
+        error_setg(errp, "Attempt to set property '%s' on device '%s' "
+                   "(type '%s') after it was realized", name, dev->id,
+                   object_get_typename(OBJECT(dev)));
+    } else {
+        error_setg(errp, "Attempt to set property '%s' on anonymous device "
+                   "(type '%s') after it was realized", name,
+                   object_get_typename(OBJECT(dev)));
+    }
+}
+
 void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
 {
     void *ptr = dev;
@@ -33,7 +47,7 @@ static void set_enum(Object *obj, Visitor *v, void *opaque,
     int *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -86,7 +100,7 @@ static void set_bit(Object *obj, Visitor *v, void *opaque,
     bool value;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -126,7 +140,7 @@ static void set_uint8(Object *obj, Visitor *v, void *opaque,
     uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -193,7 +207,7 @@ static void set_uint16(Object *obj, Visitor *v, void *opaque,
     uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -226,7 +240,7 @@ static void set_uint32(Object *obj, Visitor *v, void *opaque,
     uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -251,7 +265,7 @@ static void set_int32(Object *obj, Visitor *v, void *opaque,
     int32_t *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -324,7 +338,7 @@ static void set_uint64(Object *obj, Visitor *v, void *opaque,
     uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -414,7 +428,7 @@ static void set_string(Object *obj, Visitor *v, void *opaque,
     char *str;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -478,7 +492,7 @@ static void set_mac(Object *obj, Visitor *v, void *opaque,
     char *str, *p;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -570,7 +584,7 @@ static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
     char *str;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -641,7 +655,7 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque,
     const int64_t max = 32768;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -709,7 +723,7 @@ static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
     unsigned int slot = 0, func = 0;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -824,7 +838,7 @@ static void set_prop_arraylen(Object *obj, Visitor *v, void *opaque,
     int i;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
     if (*alenptr) {
diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h
index c9bb246..a379339 100644
--- a/hw/qdev-properties.h
+++ b/hw/qdev-properties.h
@@ -167,4 +167,16 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
  */
 void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp);
 
+/**
+ * @qdev_prop_set_after_realize:
+ * @dev: device
+ * @name: name of property
+ * @errp: indirect pointer to Error to be set
+ * Set the Error object to report that an attempt was made to set a property
+ * on a device after it has already been realized. This is a utility function
+ * which allows property-setter functions to easily report the error in
+ * a friendly format identifying both the device and the property.
+ */
+void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
+                                 Error **errp);
 #endif
diff --git a/hw/qdev.c b/hw/qdev.c
index 708a058..04ec456 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -562,7 +562,7 @@ static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque,
     int ret;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
commit c19f806e01ba5c4a4d4fac80b76841512ed4a11e
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:20 2013 +0100

    virtio-scsi: cleanup: remove qdev field.
    
    The qdev field is no longer needed. Just drop it.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-11-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 96e3688..06a58a6 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -704,8 +704,6 @@ static int virtio_scsi_device_init(VirtIODevice *vdev)
 
     s->cmd_vqs = g_malloc0(s->conf.num_queues * sizeof(VirtQueue *));
 
-    s->qdev = qdev;
-
     /* TODO set up vdev function pointers */
     vdev->get_config = virtio_scsi_get_config;
     vdev->set_config = virtio_scsi_set_config;
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
index fe2c7d6..31e97bb 100644
--- a/hw/virtio-scsi.h
+++ b/hw/virtio-scsi.h
@@ -39,7 +39,6 @@ struct VirtIOSCSIConf {
 
 typedef struct VirtIOSCSI {
     VirtIODevice parent_obj;
-    DeviceState *qdev;
     VirtIOSCSIConf conf;
 
     SCSIBus bus;
commit 763684befd34461371c2d2188655b69e4d93a5db
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:19 2013 +0100

    virtio-scsi: cleanup: init and exit functions.
    
    This remove old init and exit function as they are no longer needed.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-10-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index c341d24..96e3688 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -692,35 +692,19 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = {
     .load_request = virtio_scsi_load_request,
 };
 
-static VirtIODevice *virtio_scsi_common_init(DeviceState *dev,
-                                             VirtIOSCSIConf *proxyconf,
-                                             VirtIOSCSI **ps)
+static int virtio_scsi_device_init(VirtIODevice *vdev)
 {
-    VirtIOSCSI *s = *ps;
-    VirtIODevice *vdev = VIRTIO_DEVICE(s);
+    DeviceState *qdev = DEVICE(vdev);
+    VirtIOSCSI *s = VIRTIO_SCSI(vdev);
     static int virtio_scsi_id;
     int i;
 
-    /*
-     * We have two cases here: the old virtio-scsi-pci device, and the
-     * refactored virtio-scsi.
-     */
+    virtio_init(VIRTIO_DEVICE(s), "virtio-scsi", VIRTIO_ID_SCSI,
+                sizeof(VirtIOSCSIConfig));
 
-    if (s == NULL) {
-        /* virtio-scsi-pci */
-        s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
-                                             sizeof(VirtIOSCSIConfig),
-                                             sizeof(VirtIOSCSI));
-    } else {
-        /* virtio-scsi */
-        virtio_init(VIRTIO_DEVICE(s), "virtio-scsi", VIRTIO_ID_SCSI,
-                    sizeof(VirtIOSCSIConfig));
-    }
+    s->cmd_vqs = g_malloc0(s->conf.num_queues * sizeof(VirtQueue *));
 
-    s->cmd_vqs = g_malloc0(proxyconf->num_queues * sizeof(VirtQueue *));
-
-    s->qdev = dev;
-    s->conf = *proxyconf;
+    s->qdev = qdev;
 
     /* TODO set up vdev function pointers */
     vdev->get_config = virtio_scsi_get_config;
@@ -737,38 +721,14 @@ static VirtIODevice *virtio_scsi_common_init(DeviceState *dev,
                                          virtio_scsi_handle_cmd);
     }
 
-    scsi_bus_new(&s->bus, dev, &virtio_scsi_scsi_info);
-    if (!dev->hotplugged) {
+    scsi_bus_new(&s->bus, qdev, &virtio_scsi_scsi_info);
+    if (!qdev->hotplugged) {
         scsi_bus_legacy_handle_cmdline(&s->bus);
     }
 
-    register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1,
+    register_savevm(qdev, "virtio-scsi", virtio_scsi_id++, 1,
                     virtio_scsi_save, virtio_scsi_load, s);
 
-    return vdev;
-}
-
-VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
-{
-    VirtIOSCSI *s = NULL;
-    return virtio_scsi_common_init(dev, proxyconf, &s);
-}
-
-void virtio_scsi_exit(VirtIODevice *vdev)
-{
-    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
-    unregister_savevm(s->qdev, "virtio-scsi", s);
-    g_free(s->cmd_vqs);
-    virtio_cleanup(vdev);
-}
-
-static int virtio_scsi_device_init(VirtIODevice *vdev)
-{
-    DeviceState *qdev = DEVICE(vdev);
-    VirtIOSCSI *s = VIRTIO_SCSI(vdev);
-    if (virtio_scsi_common_init(qdev, &(s->conf), &s) == NULL) {
-        return -1;
-    }
     return 0;
 }
 
commit 0ac8e139274245320b1c56f6e9ec9318c2da963a
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:18 2013 +0100

    virtio-scsi: cleanup: use QOM casts.
    
    As the virtio-scsi-pci and virtio-scsi-s390 are switched to the new API,
    we can use QOM casts.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-9-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 56d1b27..c341d24 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -172,6 +172,7 @@ static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
 {
     VirtIOSCSI *s = req->dev;
     VirtQueue *vq = req->vq;
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
     virtqueue_push(vq, &req->elem, req->qsgl.size + req->elem.in_sg[0].iov_len);
     qemu_sglist_destroy(&req->qsgl);
     if (req->sreq) {
@@ -179,7 +180,7 @@ static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
         scsi_req_unref(req->sreq);
     }
     g_free(req);
-    virtio_notify(&s->vdev, vq);
+    virtio_notify(vdev, vq);
 }
 
 static void virtio_scsi_bad_req(void)
@@ -566,16 +567,16 @@ static void virtio_scsi_reset(VirtIODevice *vdev)
  */
 static void virtio_scsi_save(QEMUFile *f, void *opaque)
 {
-    VirtIOSCSI *s = opaque;
-    virtio_save(&s->vdev, f);
+    VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
+    virtio_save(vdev, f);
 }
 
 static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id)
 {
-    VirtIOSCSI *s = opaque;
+    VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
     int ret;
 
-    ret = virtio_load(&s->vdev, f);
+    ret = virtio_load(vdev, f);
     if (ret) {
         return ret;
     }
@@ -587,9 +588,10 @@ static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
 {
     VirtIOSCSIReq *req = virtio_scsi_pop_req(s, s->event_vq);
     VirtIOSCSIEvent *evt;
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
     int in_size;
 
-    if (!(s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+    if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
         return;
     }
 
@@ -633,7 +635,7 @@ static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
 
 static void virtio_scsi_handle_event(VirtIODevice *vdev, VirtQueue *vq)
 {
-    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
+    VirtIOSCSI *s = VIRTIO_SCSI(vdev);
 
     if (s->events_dropped) {
         virtio_scsi_push_event(s, NULL, VIRTIO_SCSI_T_NO_EVENT, 0);
@@ -643,8 +645,9 @@ static void virtio_scsi_handle_event(VirtIODevice *vdev, VirtQueue *vq)
 static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
 {
     VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
 
-    if (((s->vdev.guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) &&
+    if (((vdev->guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) &&
         dev->type != TYPE_ROM) {
         virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE,
                                sense.asc | (sense.ascq << 8));
@@ -654,8 +657,9 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
 static void virtio_scsi_hotplug(SCSIBus *bus, SCSIDevice *dev)
 {
     VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
 
-    if ((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
+    if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
         virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET,
                                VIRTIO_SCSI_EVT_RESET_RESCAN);
     }
@@ -664,8 +668,9 @@ static void virtio_scsi_hotplug(SCSIBus *bus, SCSIDevice *dev)
 static void virtio_scsi_hot_unplug(SCSIBus *bus, SCSIDevice *dev)
 {
     VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
 
-    if ((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
+    if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
         virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET,
                                VIRTIO_SCSI_EVT_RESET_REMOVED);
     }
@@ -692,6 +697,7 @@ static VirtIODevice *virtio_scsi_common_init(DeviceState *dev,
                                              VirtIOSCSI **ps)
 {
     VirtIOSCSI *s = *ps;
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
     static int virtio_scsi_id;
     int i;
 
@@ -717,17 +723,17 @@ static VirtIODevice *virtio_scsi_common_init(DeviceState *dev,
     s->conf = *proxyconf;
 
     /* TODO set up vdev function pointers */
-    s->vdev.get_config = virtio_scsi_get_config;
-    s->vdev.set_config = virtio_scsi_set_config;
-    s->vdev.get_features = virtio_scsi_get_features;
-    s->vdev.reset = virtio_scsi_reset;
-
-    s->ctrl_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
-                                   virtio_scsi_handle_ctrl);
-    s->event_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
+    vdev->get_config = virtio_scsi_get_config;
+    vdev->set_config = virtio_scsi_set_config;
+    vdev->get_features = virtio_scsi_get_features;
+    vdev->reset = virtio_scsi_reset;
+
+    s->ctrl_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
+                                  virtio_scsi_handle_ctrl);
+    s->event_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
                                    virtio_scsi_handle_event);
     for (i = 0; i < s->conf.num_queues; i++) {
-        s->cmd_vqs[i] = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
+        s->cmd_vqs[i] = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
                                          virtio_scsi_handle_cmd);
     }
 
@@ -739,7 +745,7 @@ static VirtIODevice *virtio_scsi_common_init(DeviceState *dev,
     register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1,
                     virtio_scsi_save, virtio_scsi_load, s);
 
-    return &s->vdev;
+    return vdev;
 }
 
 VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
index 758c29b..fe2c7d6 100644
--- a/hw/virtio-scsi.h
+++ b/hw/virtio-scsi.h
@@ -38,7 +38,7 @@ struct VirtIOSCSIConf {
 };
 
 typedef struct VirtIOSCSI {
-    VirtIODevice vdev;
+    VirtIODevice parent_obj;
     DeviceState *qdev;
     VirtIOSCSIConf conf;
 
commit c908ea1052f8c6391c2d321693220130846f703c
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:17 2013 +0100

    virtio-scsi-ccw: switch to new API
    
    Here the virtio-scsi-ccw is modified for the new API. The device
    virtio-scsi-ccw extends virtio-ccw-device as before. It creates and
    connects a virtio-scsi during the init. The properties are not modified.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-8-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index a2f9f52..7e79c57 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -626,22 +626,24 @@ static int virtio_ccw_balloon_exit(VirtioCcwDevice *dev)
     return virtio_ccw_exit(dev);
 }
 
-static int virtio_ccw_scsi_init(VirtioCcwDevice *dev)
+static int virtio_ccw_scsi_init(VirtioCcwDevice *ccw_dev)
 {
-    VirtIODevice *vdev;
+    VirtIOSCSICcw *dev = VIRTIO_SCSI_CCW(ccw_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
 
-    vdev = virtio_scsi_init((DeviceState *)dev, &dev->scsi);
-    if (!vdev) {
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    if (qdev_init(vdev) < 0) {
         return -1;
     }
 
-    return virtio_ccw_device_init(dev, vdev);
+    return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
 }
 
-static int virtio_ccw_scsi_exit(VirtioCcwDevice *dev)
+static void virtio_ccw_scsi_instance_init(Object *obj)
 {
-    virtio_scsi_exit(dev->vdev);
-    return virtio_ccw_exit(dev);
+    VirtIOSCSICcw *dev = VIRTIO_SCSI_CCW(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SCSI);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 }
 
 static int virtio_ccw_rng_init(VirtioCcwDevice *dev)
@@ -832,7 +834,7 @@ static const TypeInfo virtio_ccw_balloon = {
 
 static Property virtio_ccw_scsi_properties[] = {
     DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
-    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtioCcwDevice, scsi),
+    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSICcw, vdev.conf),
     DEFINE_VIRTIO_SCSI_FEATURES(VirtioCcwDevice, host_features[0]),
     DEFINE_PROP_END_OF_LIST(),
 };
@@ -843,15 +845,16 @@ static void virtio_ccw_scsi_class_init(ObjectClass *klass, void *data)
     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
 
     k->init = virtio_ccw_scsi_init;
-    k->exit = virtio_ccw_scsi_exit;
+    k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
     dc->props = virtio_ccw_scsi_properties;
 }
 
 static const TypeInfo virtio_ccw_scsi = {
-    .name          = "virtio-scsi-ccw",
+    .name          = TYPE_VIRTIO_SCSI_CCW,
     .parent        = TYPE_VIRTIO_CCW_DEVICE,
-    .instance_size = sizeof(VirtioCcwDevice),
+    .instance_size = sizeof(VirtIOSCSICcw),
+    .instance_init = virtio_ccw_scsi_instance_init,
     .class_init    = virtio_ccw_scsi_class_init,
 };
 
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 3993bc5..d9f7399 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -76,7 +76,6 @@ struct VirtioCcwDevice {
     uint32_t host_features[VIRTIO_CCW_FEATURE_SIZE];
     virtio_serial_conf serial;
     virtio_net_conf net;
-    VirtIOSCSIConf scsi;
     VirtIORNGConf rng;
     VirtioBusState bus;
     /* Guest provided values: */
@@ -93,6 +92,17 @@ typedef struct VirtualCssBus {
 #define VIRTUAL_CSS_BUS(obj) \
      OBJECT_CHECK(VirtualCssBus, (obj), TYPE_VIRTUAL_CSS_BUS)
 
+/* virtio-scsi-ccw */
+
+#define TYPE_VIRTIO_SCSI_CCW "virtio-scsi-ccw"
+#define VIRTIO_SCSI_CCW(obj) \
+        OBJECT_CHECK(VirtIOSCSICcw, (obj), TYPE_VIRTIO_SCSI_CCW)
+
+typedef struct VirtIOSCSICcw {
+    VirtioCcwDevice parent_obj;
+    VirtIOSCSI vdev;
+} VirtIOSCSICcw;
+
 /* virtio-blk-ccw */
 
 #define TYPE_VIRTIO_BLK_CCW "virtio-blk-ccw"
commit 9ef13d8f1956b086f4bcb1d70cd5ff96e5faa2cb
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:16 2013 +0100

    virtio-scsi-s390: switch to the new API.
    
    Here the virtio-scsi-s390 is modified for the new API. The device
    virtio-scsi-s390 extends virtio-s390-device as before. It creates and
    connects a virtio-scsi during the init. The properties are not modified.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-7-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index 89441f8..8c529c1 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -202,16 +202,24 @@ static int s390_virtio_serial_init(VirtIOS390Device *dev)
     return r;
 }
 
-static int s390_virtio_scsi_init(VirtIOS390Device *dev)
+static int s390_virtio_scsi_init(VirtIOS390Device *s390_dev)
 {
-    VirtIODevice *vdev;
+    VirtIOSCSIS390 *dev = VIRTIO_SCSI_S390(s390_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
 
-    vdev = virtio_scsi_init((DeviceState *)dev, &dev->scsi);
-    if (!vdev) {
+    qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
+    if (qdev_init(vdev) < 0) {
         return -1;
     }
 
-    return s390_virtio_device_init(dev, vdev);
+    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
+}
+
+static void s390_virtio_scsi_instance_init(Object *obj)
+{
+    VirtIOSCSIS390 *dev = VIRTIO_SCSI_S390(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SCSI);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 }
 
 static int s390_virtio_rng_init(VirtIOS390Device *dev)
@@ -538,7 +546,7 @@ static const TypeInfo virtio_s390_device_info = {
 };
 
 static Property s390_virtio_scsi_properties[] = {
-    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOS390Device, scsi),
+    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSIS390, vdev.conf),
     DEFINE_VIRTIO_SCSI_FEATURES(VirtIOS390Device, host_features),
     DEFINE_PROP_END_OF_LIST(),
 };
@@ -553,9 +561,10 @@ static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo s390_virtio_scsi = {
-    .name          = "virtio-scsi-s390",
+    .name          = TYPE_VIRTIO_SCSI_S390,
     .parent        = TYPE_VIRTIO_S390_DEVICE,
-    .instance_size = sizeof(VirtIOS390Device),
+    .instance_size = sizeof(VirtIOSCSIS390),
+    .instance_init = s390_virtio_scsi_instance_init,
     .class_init    = s390_virtio_scsi_class_init,
 };
 
diff --git a/hw/s390x/s390-virtio-bus.h b/hw/s390x/s390-virtio-bus.h
index 1a63411..ebe8794 100644
--- a/hw/s390x/s390-virtio-bus.h
+++ b/hw/s390x/s390-virtio-bus.h
@@ -93,7 +93,6 @@ struct VirtIOS390Device {
     uint32_t host_features;
     virtio_serial_conf serial;
     virtio_net_conf net;
-    VirtIOSCSIConf scsi;
     VirtIORNGConf rng;
     VirtioBusState bus;
 };
@@ -131,5 +130,15 @@ typedef struct VirtIOBlkS390 {
     VirtIOBlkConf blk;
 } VirtIOBlkS390;
 
+/* virtio-scsi-s390 */
+
+#define TYPE_VIRTIO_SCSI_S390 "virtio-scsi-s390"
+#define VIRTIO_SCSI_S390(obj) \
+        OBJECT_CHECK(VirtIOSCSIS390, (obj), TYPE_VIRTIO_SCSI_S390)
+
+typedef struct VirtIOSCSIS390 {
+    VirtIOS390Device parent_obj;
+    VirtIOSCSI vdev;
+} VirtIOSCSIS390;
 
 #endif
commit bc7b90a010719612344c4a78be7819841e76b7ec
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:15 2013 +0100

    virtio-scsi-pci: switch to new API.
    
    Here the virtio-scsi-pci is modified for the new API. The device virtio-scsi-pci
    extends virtio-pci. It creates and connects a virtio-scsi during the init.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-6-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 0cf8b2e..668060d 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -1190,64 +1190,6 @@ static const TypeInfo virtio_rng_info = {
     .class_init    = virtio_rng_class_init,
 };
 
-static int virtio_scsi_init_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-    VirtIODevice *vdev;
-
-    vdev = virtio_scsi_init(&pci_dev->qdev, &proxy->scsi);
-    if (!vdev) {
-        return -EINVAL;
-    }
-
-    vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED
-                                        ? proxy->scsi.num_queues + 3
-                                        : proxy->nvectors;
-    virtio_init_pci(proxy, vdev);
-
-    /* make the actual value visible */
-    proxy->nvectors = vdev->nvectors;
-    return 0;
-}
-
-static void virtio_scsi_exit_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-
-    virtio_scsi_exit(proxy->vdev);
-    virtio_exit_pci(pci_dev);
-}
-
-static Property virtio_scsi_properties[] = {
-    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
-    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEV_NVECTORS_UNSPECIFIED),
-    DEFINE_VIRTIO_SCSI_FEATURES(VirtIOPCIProxy, host_features),
-    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOPCIProxy, scsi),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void virtio_scsi_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = virtio_scsi_init_pci;
-    k->exit = virtio_scsi_exit_pci;
-    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
-    k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI;
-    k->revision = 0x00;
-    k->class_id = PCI_CLASS_STORAGE_SCSI;
-    dc->reset = virtio_pci_reset;
-    dc->props = virtio_scsi_properties;
-}
-
-static const TypeInfo virtio_scsi_info = {
-    .name          = "virtio-scsi-pci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(VirtIOPCIProxy),
-    .class_init    = virtio_scsi_class_init,
-};
-
 #ifdef CONFIG_VIRTFS
 static int virtio_9p_init_pci(PCIDevice *pci_dev)
 {
@@ -1454,6 +1396,62 @@ static const TypeInfo virtio_blk_pci_info = {
     .class_init    = virtio_blk_pci_class_init,
 };
 
+/* virtio-scsi-pci */
+
+static Property virtio_scsi_pci_properties[] = {
+    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
+                    VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
+    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
+                       DEV_NVECTORS_UNSPECIFIED),
+    DEFINE_VIRTIO_SCSI_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSIPCI, vdev.conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static int virtio_scsi_pci_init_pci(VirtIOPCIProxy *vpci_dev)
+{
+    VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(vpci_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
+
+    if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
+        vpci_dev->nvectors = dev->vdev.conf.num_queues + 3;
+    }
+
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    if (qdev_init(vdev) < 0) {
+        return -1;
+    }
+    return 0;
+}
+
+static void virtio_scsi_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
+    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+    k->init = virtio_scsi_pci_init_pci;
+    dc->props = virtio_scsi_pci_properties;
+    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI;
+    pcidev_k->revision = 0x00;
+    pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI;
+}
+
+static void virtio_scsi_pci_instance_init(Object *obj)
+{
+    VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SCSI);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+}
+
+static const TypeInfo virtio_scsi_pci_info = {
+    .name          = TYPE_VIRTIO_SCSI_PCI,
+    .parent        = TYPE_VIRTIO_PCI,
+    .instance_size = sizeof(VirtIOSCSIPCI),
+    .instance_init = virtio_scsi_pci_instance_init,
+    .class_init    = virtio_scsi_pci_class_init,
+};
+
 /* virtio-pci-bus */
 
 void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev)
@@ -1495,7 +1493,6 @@ static void virtio_pci_register_types(void)
     type_register_static(&virtio_net_info);
     type_register_static(&virtio_serial_info);
     type_register_static(&virtio_balloon_info);
-    type_register_static(&virtio_scsi_info);
     type_register_static(&virtio_rng_info);
     type_register_static(&virtio_pci_bus_info);
     type_register_static(&virtio_pci_info);
@@ -1503,6 +1500,7 @@ static void virtio_pci_register_types(void)
     type_register_static(&virtio_9p_info);
 #endif
     type_register_static(&virtio_blk_pci_info);
+    type_register_static(&virtio_scsi_pci_info);
 }
 
 type_init(virtio_pci_register_types)
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index a9dbfff..bfe7a8e 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -26,6 +26,7 @@
 
 typedef struct VirtIOPCIProxy VirtIOPCIProxy;
 typedef struct VirtIOBlkPCI VirtIOBlkPCI;
+typedef struct VirtIOSCSIPCI VirtIOSCSIPCI;
 
 /* virtio-pci-bus */
 
@@ -81,7 +82,6 @@ struct VirtIOPCIProxy {
 #endif
     virtio_serial_conf serial;
     virtio_net_conf net;
-    VirtIOSCSIConf scsi;
     VirtIORNGConf rng;
     bool ioeventfd_disabled;
     bool ioeventfd_started;
@@ -90,6 +90,19 @@ struct VirtIOPCIProxy {
     VirtioBusState bus;
 };
 
+
+/*
+ * virtio-scsi-pci: This extends VirtioPCIProxy.
+ */
+#define TYPE_VIRTIO_SCSI_PCI "virtio-scsi-pci"
+#define VIRTIO_SCSI_PCI(obj) \
+        OBJECT_CHECK(VirtIOSCSIPCI, (obj), TYPE_VIRTIO_SCSI_PCI)
+
+struct VirtIOSCSIPCI {
+    VirtIOPCIProxy parent_obj;
+    VirtIOSCSI vdev;
+};
+
 /*
  * virtio-blk-pci: This extends VirtioPCIProxy.
  */
commit 3ab1dfdd50a7c852e4921935250c22f486c5b8a4
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:14 2013 +0100

    virtio-scsi: add the virtio-scsi device.
    
    Create virtio-scsi which extends virtio-device, so it can be connected on
    virtio-bus.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-5-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 08fcb80..56d1b27 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -17,6 +17,7 @@
 #include "qemu/error-report.h"
 #include <hw/scsi.h>
 #include <hw/scsi-defs.h>
+#include "hw/virtio-bus.h"
 
 #define VIRTIO_SCSI_VQ_SIZE     128
 #define VIRTIO_SCSI_CDB_SIZE    32
@@ -686,15 +687,30 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = {
     .load_request = virtio_scsi_load_request,
 };
 
-VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
+static VirtIODevice *virtio_scsi_common_init(DeviceState *dev,
+                                             VirtIOSCSIConf *proxyconf,
+                                             VirtIOSCSI **ps)
 {
-    VirtIOSCSI *s;
+    VirtIOSCSI *s = *ps;
     static int virtio_scsi_id;
     int i;
 
-    s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
-                                         sizeof(VirtIOSCSIConfig),
-                                         sizeof(VirtIOSCSI));
+    /*
+     * We have two cases here: the old virtio-scsi-pci device, and the
+     * refactored virtio-scsi.
+     */
+
+    if (s == NULL) {
+        /* virtio-scsi-pci */
+        s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
+                                             sizeof(VirtIOSCSIConfig),
+                                             sizeof(VirtIOSCSI));
+    } else {
+        /* virtio-scsi */
+        virtio_init(VIRTIO_DEVICE(s), "virtio-scsi", VIRTIO_ID_SCSI,
+                    sizeof(VirtIOSCSIConfig));
+    }
+
     s->cmd_vqs = g_malloc0(proxyconf->num_queues * sizeof(VirtQueue *));
 
     s->qdev = dev;
@@ -726,6 +742,12 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
     return &s->vdev;
 }
 
+VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
+{
+    VirtIOSCSI *s = NULL;
+    return virtio_scsi_common_init(dev, proxyconf, &s);
+}
+
 void virtio_scsi_exit(VirtIODevice *vdev)
 {
     VirtIOSCSI *s = (VirtIOSCSI *)vdev;
@@ -733,3 +755,56 @@ void virtio_scsi_exit(VirtIODevice *vdev)
     g_free(s->cmd_vqs);
     virtio_cleanup(vdev);
 }
+
+static int virtio_scsi_device_init(VirtIODevice *vdev)
+{
+    DeviceState *qdev = DEVICE(vdev);
+    VirtIOSCSI *s = VIRTIO_SCSI(vdev);
+    if (virtio_scsi_common_init(qdev, &(s->conf), &s) == NULL) {
+        return -1;
+    }
+    return 0;
+}
+
+static int virtio_scsi_device_exit(DeviceState *qdev)
+{
+    VirtIOSCSI *s = VIRTIO_SCSI(qdev);
+    VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+
+    unregister_savevm(qdev, "virtio-scsi", s);
+    g_free(s->cmd_vqs);
+    virtio_common_cleanup(vdev);
+    return 0;
+}
+
+static Property virtio_scsi_properties[] = {
+    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSI, conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_scsi_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+    dc->exit = virtio_scsi_device_exit;
+    dc->props = virtio_scsi_properties;
+    vdc->init = virtio_scsi_device_init;
+    vdc->get_config = virtio_scsi_get_config;
+    vdc->set_config = virtio_scsi_set_config;
+    vdc->get_features = virtio_scsi_get_features;
+    vdc->reset = virtio_scsi_reset;
+}
+
+static const TypeInfo virtio_scsi_info = {
+    .name = TYPE_VIRTIO_SCSI,
+    .parent = TYPE_VIRTIO_DEVICE,
+    .instance_size = sizeof(VirtIOSCSI),
+    .class_init = virtio_scsi_class_init,
+};
+
+static void virtio_register_types(void)
+{
+    type_register_static(&virtio_scsi_info);
+}
+
+type_init(virtio_register_types)
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
index da02f08..758c29b 100644
--- a/hw/virtio-scsi.h
+++ b/hw/virtio-scsi.h
@@ -18,6 +18,11 @@
 #include "hw/pci/pci.h"
 #include "hw/scsi.h"
 
+#define TYPE_VIRTIO_SCSI "virtio-scsi"
+#define VIRTIO_SCSI(obj) \
+        OBJECT_CHECK(VirtIOSCSI, (obj), TYPE_VIRTIO_SCSI)
+
+
 /* The ID for virtio_scsi */
 #define VIRTIO_ID_SCSI  8
 
commit 4bfeb18a454bd71c406683fb473375e02c724b00
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:13 2013 +0100

    virtio-scsi: moving host_features from properties to transport properties.
    
    host_features field is part of the transport device. So move all the
    host_features related properties into transport device.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-4-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index c5d5456..89441f8 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -538,7 +538,8 @@ static const TypeInfo virtio_s390_device_info = {
 };
 
 static Property s390_virtio_scsi_properties[] = {
-    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOS390Device, host_features, scsi),
+    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOS390Device, scsi),
+    DEFINE_VIRTIO_SCSI_FEATURES(VirtIOS390Device, host_features),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 4c44b7e..a2f9f52 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -832,7 +832,8 @@ static const TypeInfo virtio_ccw_balloon = {
 
 static Property virtio_ccw_scsi_properties[] = {
     DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
-    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtioCcwDevice, host_features[0], scsi),
+    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtioCcwDevice, scsi),
+    DEFINE_VIRTIO_SCSI_FEATURES(VirtioCcwDevice, host_features[0]),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index f3ece78..0cf8b2e 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -1221,7 +1221,8 @@ static void virtio_scsi_exit_pci(PCIDevice *pci_dev)
 static Property virtio_scsi_properties[] = {
     DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
     DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEV_NVECTORS_UNSPECIFIED),
-    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOPCIProxy, host_features, scsi),
+    DEFINE_VIRTIO_SCSI_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOPCIProxy, scsi),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
index fb83b67..da02f08 100644
--- a/hw/virtio-scsi.h
+++ b/hw/virtio-scsi.h
@@ -47,12 +47,16 @@ typedef struct VirtIOSCSI {
     VirtQueue **cmd_vqs;
 } VirtIOSCSI;
 
-#define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _features_field, _conf_field) \
-    DEFINE_VIRTIO_COMMON_FEATURES(_state, _features_field), \
-    DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \
-    DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF), \
-    DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128), \
-    DEFINE_PROP_BIT("hotplug", _state, _features_field, VIRTIO_SCSI_F_HOTPLUG, true), \
-    DEFINE_PROP_BIT("param_change", _state, _features_field, VIRTIO_SCSI_F_CHANGE, true)
+#define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _conf_field)                     \
+    DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1),       \
+    DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF),\
+    DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128)
+
+#define DEFINE_VIRTIO_SCSI_FEATURES(_state, _feature_field)                    \
+    DEFINE_VIRTIO_COMMON_FEATURES(_state, _feature_field),                     \
+    DEFINE_PROP_BIT("hotplug", _state, _feature_field, VIRTIO_SCSI_F_HOTPLUG,  \
+                                                       true),                  \
+    DEFINE_PROP_BIT("param_change", _state, _feature_field,                    \
+                                            VIRTIO_SCSI_F_CHANGE, true)
 
 #endif /* _QEMU_VIRTIO_SCSI_H */
commit 22219527f4272f5199a581bbd3950e9ba96bbc75
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:12 2013 +0100

    virtio-scsi: allocate cmd_vqs array separately.
    
    Allocate/Free the cmd_vqs array separately to have a fixed size device.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-3-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 55191c5..08fcb80 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -690,12 +690,12 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
 {
     VirtIOSCSI *s;
     static int virtio_scsi_id;
-    size_t sz;
     int i;
 
-    sz = sizeof(VirtIOSCSI) + proxyconf->num_queues * sizeof(VirtQueue *);
     s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
-                                         sizeof(VirtIOSCSIConfig), sz);
+                                         sizeof(VirtIOSCSIConfig),
+                                         sizeof(VirtIOSCSI));
+    s->cmd_vqs = g_malloc0(proxyconf->num_queues * sizeof(VirtQueue *));
 
     s->qdev = dev;
     s->conf = *proxyconf;
@@ -730,5 +730,6 @@ void virtio_scsi_exit(VirtIODevice *vdev)
 {
     VirtIOSCSI *s = (VirtIOSCSI *)vdev;
     unregister_savevm(s->qdev, "virtio-scsi", s);
+    g_free(s->cmd_vqs);
     virtio_cleanup(vdev);
 }
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
index 6a0a95e..fb83b67 100644
--- a/hw/virtio-scsi.h
+++ b/hw/virtio-scsi.h
@@ -44,7 +44,7 @@ typedef struct VirtIOSCSI {
     bool events_dropped;
     VirtQueue *ctrl_vq;
     VirtQueue *event_vq;
-    VirtQueue *cmd_vqs[0];
+    VirtQueue **cmd_vqs;
 } VirtIOSCSI;
 
 #define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _features_field, _conf_field) \
commit 394e2e4c59294f2c5da58d2970693667218c7cf3
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:11 2013 +0100

    virtio-scsi: don't use pointer for configuration.
    
    The configuration field must not be a pointer as it will be used for virtio-scsi
    properties. So *conf is replaced by conf.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-2-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 8620712..55191c5 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -237,7 +237,7 @@ static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq)
     VirtIOSCSIReq *req = sreq->hba_private;
     uint32_t n = virtio_queue_get_id(req->vq) - 2;
 
-    assert(n < req->dev->conf->num_queues);
+    assert(n < req->dev->conf.num_queues);
     qemu_put_be32s(f, &n);
     qemu_put_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
 }
@@ -251,7 +251,7 @@ static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq)
 
     req = g_malloc(sizeof(*req));
     qemu_get_be32s(f, &n);
-    assert(n < s->conf->num_queues);
+    assert(n < s->conf.num_queues);
     qemu_get_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
     virtio_scsi_parse_req(s, s->cmd_vqs[n], req);
 
@@ -513,10 +513,10 @@ static void virtio_scsi_get_config(VirtIODevice *vdev,
     VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
     VirtIOSCSI *s = (VirtIOSCSI *)vdev;
 
-    stl_raw(&scsiconf->num_queues, s->conf->num_queues);
+    stl_raw(&scsiconf->num_queues, s->conf.num_queues);
     stl_raw(&scsiconf->seg_max, 128 - 2);
-    stl_raw(&scsiconf->max_sectors, s->conf->max_sectors);
-    stl_raw(&scsiconf->cmd_per_lun, s->conf->cmd_per_lun);
+    stl_raw(&scsiconf->max_sectors, s->conf.max_sectors);
+    stl_raw(&scsiconf->cmd_per_lun, s->conf.cmd_per_lun);
     stl_raw(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
     stl_raw(&scsiconf->sense_size, s->sense_size);
     stl_raw(&scsiconf->cdb_size, s->cdb_size);
@@ -698,7 +698,7 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
                                          sizeof(VirtIOSCSIConfig), sz);
 
     s->qdev = dev;
-    s->conf = proxyconf;
+    s->conf = *proxyconf;
 
     /* TODO set up vdev function pointers */
     s->vdev.get_config = virtio_scsi_get_config;
@@ -710,7 +710,7 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
                                    virtio_scsi_handle_ctrl);
     s->event_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
                                    virtio_scsi_handle_event);
-    for (i = 0; i < s->conf->num_queues; i++) {
+    for (i = 0; i < s->conf.num_queues; i++) {
         s->cmd_vqs[i] = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
                                          virtio_scsi_handle_cmd);
     }
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
index ccf1e42..6a0a95e 100644
--- a/hw/virtio-scsi.h
+++ b/hw/virtio-scsi.h
@@ -35,7 +35,7 @@ struct VirtIOSCSIConf {
 typedef struct VirtIOSCSI {
     VirtIODevice vdev;
     DeviceState *qdev;
-    VirtIOSCSIConf *conf;
+    VirtIOSCSIConf conf;
 
     SCSIBus bus;
     uint32_t sense_size;
commit 2fd1a053e3696738d7499733df0feb1efd0d97e0
Merge: dcadaa9 4d70043
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 26 09:25:45 2013 -0500

    Merge remote-tracking branch 'luiz/queue/qmp' into staging
    
    # By Corey Bryant (2) and others
    # Via Luiz Capitulino
    * luiz/queue/qmp:
      New QMP command query-cpu-max and HMP command cpu_max
      qmp: fix handling of boolean values in qmp-shell
      QMP: TPM QMP and man page documentation updates
      QMP: Remove duplicate TPM type from query-tpm

commit 500f0061d628b52220038939728f0d7aee634468
Author: Orit Wasserman <owasserm at redhat.com>
Date:   Fri Mar 22 16:48:03 2013 +0200

    Use qemu_put_buffer_async for guest memory pages
    
    This will remove an unneeded copy of guest memory pages.
    For the page header and device state we still copy the data to the
    static buffer the other option is to allocate the memory on demand
    which is more expensive.
    
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index e1af898..4ef5a15 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -478,7 +478,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
             /* XBZRLE overflow or normal page */
             if (bytes_sent == -1) {
                 bytes_sent = save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_PAGE);
-                qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
+                qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
                 bytes_sent += TARGET_PAGE_SIZE;
                 acct_info.norm_pages++;
             }
commit 6181ec245529e0d40ac669fe3044eef3a9e19610
Author: Orit Wasserman <owasserm at redhat.com>
Date:   Fri Mar 22 16:48:02 2013 +0200

    Add qemu_put_buffer_async
    
    This allows us to add a buffer to the iovec to send without copying it
    into the static buffer, the buffer will be sent later when qemu_fflush is called.
    
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 8b8070f..623c434 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -75,6 +75,11 @@ int qemu_fclose(QEMUFile *f);
 int64_t qemu_ftell(QEMUFile *f);
 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
 void qemu_put_byte(QEMUFile *f, int v);
+/*
+ * put_buffer without copying the buffer.
+ * The buffer should be available till it is sent asynchronously.
+ */
+void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, int size);
 
 static inline void qemu_put_ubyte(QEMUFile *f, unsigned int v)
 {
diff --git a/savevm.c b/savevm.c
index 1d92987..406caa9 100644
--- a/savevm.c
+++ b/savevm.c
@@ -633,6 +633,28 @@ static void add_to_iovec(QEMUFile *f, const uint8_t *buf, int size)
     }
 }
 
+void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, int size)
+{
+    if (f->last_error) {
+        return;
+    }
+
+    if (f->is_write == 0 && f->buf_index > 0) {
+        fprintf(stderr,
+                "Attempted to write to buffer while read buffer is not empty\n");
+        abort();
+    }
+
+    add_to_iovec(f, buf, size);
+
+    f->is_write = 1;
+    f->bytes_xfer += size;
+
+    if (f->buf_index >= IO_BUF_SIZE || f->iovcnt >= MAX_IOV_SIZE) {
+        qemu_fflush(f);
+    }
+}
+
 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
 {
     int l;
@@ -652,18 +674,14 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
         if (l > size)
             l = size;
         memcpy(f->buf + f->buf_index, buf, l);
-        add_to_iovec(f, f->buf + f->buf_index, l);
         f->is_write = 1;
         f->buf_index += l;
-        f->bytes_xfer += l;
+        qemu_put_buffer_async(f, f->buf + (f->buf_index - l), l);
+        if (qemu_file_get_error(f)) {
+            break;
+        }
         buf += l;
         size -= l;
-        if (f->buf_index >= IO_BUF_SIZE || f->iovcnt >= MAX_IOV_SIZE) {
-            qemu_fflush(f);
-            if (qemu_file_get_error(f)) {
-                break;
-            }
-        }
     }
 }
 
commit cb88aa88d7e96cd12328915b33bf4a1bc054aa3f
Author: Orit Wasserman <owasserm at redhat.com>
Date:   Fri Mar 22 16:48:01 2013 +0200

    Use writev ops if available
    
    Update qemu_fflush and stdio_close to use writev ops if they are available
    Use the buffers stored in the iovec.
    
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index aaaf39a..1d92987 100644
--- a/savevm.c
+++ b/savevm.c
@@ -293,7 +293,7 @@ static int stdio_fclose(void *opaque)
     QEMUFileStdio *s = opaque;
     int ret = 0;
 
-    if (s->file->ops->put_buffer) {
+    if (s->file->ops->put_buffer || s->file->ops->writev_buffer) {
         int fd = fileno(s->stdio_file);
         struct stat st;
 
@@ -516,20 +516,35 @@ static void qemu_file_set_error(QEMUFile *f, int ret)
     }
 }
 
-/** Flushes QEMUFile buffer
+/**
+ * Flushes QEMUFile buffer
  *
+ * If there is writev_buffer QEMUFileOps it uses it otherwise uses
+ * put_buffer ops.
  */
 static void qemu_fflush(QEMUFile *f)
 {
-    int ret = 0;
+    ssize_t ret = 0;
+    int i = 0;
 
-    if (!f->ops->put_buffer) {
+    if (!f->ops->writev_buffer && !f->ops->put_buffer) {
         return;
     }
-    if (f->is_write && f->buf_index > 0) {
-        ret = f->ops->put_buffer(f->opaque, f->buf, f->pos, f->buf_index);
-        if (ret >= 0) {
-            f->pos += f->buf_index;
+
+    if (f->is_write && f->iovcnt > 0) {
+        if (f->ops->writev_buffer) {
+            ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt);
+            if (ret >= 0) {
+                f->pos += ret;
+            }
+        } else {
+            for (i = 0; i < f->iovcnt && ret >= 0; i++) {
+                ret = f->ops->put_buffer(f->opaque, f->iov[i].iov_base, f->pos,
+                                         f->iov[i].iov_len);
+                if (ret >= 0) {
+                    f->pos += ret;
+                }
+            }
         }
         f->buf_index = 0;
         f->iovcnt = 0;
commit b3ea2bdb792f6d961ba3adf45cf1f0c63c61e09d
Author: Orit Wasserman <owasserm at redhat.com>
Date:   Fri Mar 22 16:48:00 2013 +0200

    Store the data to send also in iovec
    
    All data is still copied into the static buffer.
    Adjacent iovecs are coalesced so we send one big buffer
    instead of many small buffers.
    
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index 5ab256c..aaaf39a 100644
--- a/savevm.c
+++ b/savevm.c
@@ -114,6 +114,7 @@ void qemu_announce_self(void)
 /* savevm/loadvm support */
 
 #define IO_BUF_SIZE 32768
+#define MAX_IOV_SIZE MIN(IOV_MAX, 64)
 
 struct QEMUFile {
     const QEMUFileOps *ops;
@@ -129,6 +130,9 @@ struct QEMUFile {
     int buf_size; /* 0 when writing */
     uint8_t buf[IO_BUF_SIZE];
 
+    struct iovec iov[MAX_IOV_SIZE];
+    unsigned int iovcnt;
+
     int last_error;
 };
 
@@ -528,6 +532,7 @@ static void qemu_fflush(QEMUFile *f)
             f->pos += f->buf_index;
         }
         f->buf_index = 0;
+        f->iovcnt = 0;
     }
     if (ret < 0) {
         qemu_file_set_error(f, ret);
@@ -601,6 +606,18 @@ int qemu_fclose(QEMUFile *f)
     return ret;
 }
 
+static void add_to_iovec(QEMUFile *f, const uint8_t *buf, int size)
+{
+    /* check for adjacent buffer and coalesce them */
+    if (f->iovcnt > 0 && buf == f->iov[f->iovcnt - 1].iov_base +
+        f->iov[f->iovcnt - 1].iov_len) {
+        f->iov[f->iovcnt - 1].iov_len += size;
+    } else {
+        f->iov[f->iovcnt].iov_base = (uint8_t *)buf;
+        f->iov[f->iovcnt++].iov_len = size;
+    }
+}
+
 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
 {
     int l;
@@ -620,12 +637,13 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
         if (l > size)
             l = size;
         memcpy(f->buf + f->buf_index, buf, l);
+        add_to_iovec(f, f->buf + f->buf_index, l);
         f->is_write = 1;
         f->buf_index += l;
         f->bytes_xfer += l;
         buf += l;
         size -= l;
-        if (f->buf_index >= IO_BUF_SIZE) {
+        if (f->buf_index >= IO_BUF_SIZE || f->iovcnt >= MAX_IOV_SIZE) {
             qemu_fflush(f);
             if (qemu_file_get_error(f)) {
                 break;
@@ -650,7 +668,9 @@ void qemu_put_byte(QEMUFile *f, int v)
     f->is_write = 1;
     f->bytes_xfer++;
 
-    if (f->buf_index >= IO_BUF_SIZE) {
+    add_to_iovec(f, f->buf + (f->buf_index - 1), 1);
+
+    if (f->buf_index >= IO_BUF_SIZE || f->iovcnt >= MAX_IOV_SIZE) {
         qemu_fflush(f);
     }
 }
commit 7d8a30bb98e89c203b3d2289ab0638c38bbeb7c1
Author: Orit Wasserman <owasserm at redhat.com>
Date:   Fri Mar 22 16:47:59 2013 +0200

    Update bytes_xfer in qemu_put_byte
    
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index 3466ef4..5ab256c 100644
--- a/savevm.c
+++ b/savevm.c
@@ -648,6 +648,8 @@ void qemu_put_byte(QEMUFile *f, int v)
 
     f->buf[f->buf_index++] = v;
     f->is_write = 1;
+    f->bytes_xfer++;
+
     if (f->buf_index >= IO_BUF_SIZE) {
         qemu_fflush(f);
     }
commit 28085f7b4d06970efa004257fcef013caf495a08
Author: Orit Wasserman <owasserm at redhat.com>
Date:   Fri Mar 22 16:47:58 2013 +0200

    Add socket_writev_buffer function
    
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index 8f1344a..3466ef4 100644
--- a/savevm.c
+++ b/savevm.c
@@ -39,6 +39,7 @@
 #include "qmp-commands.h"
 #include "trace.h"
 #include "qemu/bitops.h"
+#include "qemu/iov.h"
 
 #define SELF_ANNOUNCE_ROUNDS 5
 
@@ -171,6 +172,19 @@ static void coroutine_fn yield_until_fd_readable(int fd)
     qemu_coroutine_yield();
 }
 
+static ssize_t socket_writev_buffer(void *opaque, struct iovec *iov, int iovcnt)
+{
+    QEMUFileSocket *s = opaque;
+    ssize_t len;
+    ssize_t size = iov_size(iov, iovcnt);
+
+    len = iov_send(s->fd, iov, iovcnt, 0, size);
+    if (len < size) {
+        len = -socket_error();
+    }
+    return len;
+}
+
 static int socket_get_fd(void *opaque)
 {
     QEMUFileSocket *s = opaque;
@@ -387,6 +401,7 @@ static const QEMUFileOps socket_read_ops = {
 static const QEMUFileOps socket_write_ops = {
     .get_fd =     socket_get_fd,
     .put_buffer = socket_put_buffer,
+    .writev_buffer = socket_writev_buffer,
     .close =      socket_close
 };
 
commit d913829f0fd8451abcb1fd9d6dfce5586d9d7e10
Author: Orit Wasserman <owasserm at redhat.com>
Date:   Fri Mar 22 16:47:57 2013 +0200

    Add QemuFileWritevBuffer QemuFileOps
    
    This will allow us to write an iovec
    
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index df81261..8b8070f 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -51,11 +51,18 @@ typedef int (QEMUFileCloseFunc)(void *opaque);
  */
 typedef int (QEMUFileGetFD)(void *opaque);
 
+/*
+ * This function writes an iovec to file.
+ */
+typedef ssize_t (QEMUFileWritevBufferFunc)(void *opaque, struct iovec *iov,
+                                           int iovcnt);
+
 typedef struct QEMUFileOps {
     QEMUFilePutBufferFunc *put_buffer;
     QEMUFileGetBufferFunc *get_buffer;
     QEMUFileCloseFunc *close;
     QEMUFileGetFD *get_fd;
+    QEMUFileWritevBufferFunc *writev_buffer;
 } QEMUFileOps;
 
 QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops);
commit 5cc11c46cf187c7d5306b68e730ec0d372cd7ef0
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:39 2013 +0100

    migration: use XBZRLE only after bulk stage
    
    at the beginning of migration all pages are marked dirty and
    in the first round a bulk migration of all pages is performed.
    
    currently all these pages are copied to the page cache regardless
    of whether they are frequently updated or not. this doesn't make sense
    since most of these pages are never transferred again.
    
    this patch changes the XBZRLE transfer to only be used after
    the bulk stage has been completed. that means a page is added
    to the page cache the second time it is transferred and XBZRLE
    can benefit from the third time of transfer.
    
    since the page cache is likely smaller than the number of pages
    it's also likely that in the second round the page is missing in the
    cache due to collisions in the bulk phase.
    
    on the other hand a lot of unnecessary mallocs, memdups and frees
    are saved.
    
    the following results have been taken earlier while executing
    the test program from docs/xbzrle.txt. (+) with the patch and (-)
    without. (thanks to Eric Blake for reformatting and comments)
    
    + total time: 22185 milliseconds
    - total time: 22410 milliseconds
    
    Shaved 0.3 seconds, better than 1%!
    
    + downtime: 29 milliseconds
    - downtime: 21 milliseconds
    
    Not sure why downtime seemed worse, but probably not the end of the world.
    
    + transferred ram: 706034 kbytes
    - transferred ram: 721318 kbytes
    
    Fewer bytes sent - good.
    
    + remaining ram: 0 kbytes
    - remaining ram: 0 kbytes
    + total ram: 1057216 kbytes
    - total ram: 1057216 kbytes
    + duplicate: 108556 pages
    - duplicate: 105553 pages
    + normal: 175146 pages
    - normal: 179589 pages
    + normal bytes: 700584 kbytes
    - normal bytes: 718356 kbytes
    
    Fewer normal bytes...
    
    + cache size: 67108864 bytes
    - cache size: 67108864 bytes
    + xbzrle transferred: 3127 kbytes
    - xbzrle transferred: 630 kbytes
    
    ...and more compressed pages sent - good.
    
    + xbzrle pages: 117811 pages
    - xbzrle pages: 21527 pages
    + xbzrle cache miss: 18750
    - xbzrle cache miss: 179589
    
    And very good improvement on the cache miss rate.
    
    + xbzrle overflow : 0
    - xbzrle overflow : 0
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index a522735..e1af898 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -466,7 +466,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
                     acct_info.skipped_pages++;
                     bytes_sent = 0;
                 }
-            } else if (migrate_use_xbzrle()) {
+            } else if (!ram_bulk_stage && migrate_use_xbzrle()) {
                 current_addr = block->offset + offset;
                 bytes_sent = save_xbzrle_page(f, p, current_addr, block,
                                               offset, cont, last_stage);
commit 70c8652bf3c1fea79b7b68864e86926715c49261
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:38 2013 +0100

    migration: do not search dirty pages in bulk stage
    
    avoid searching for dirty pages just increment the
    page offset. all pages are dirty anyway.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 3a0d02e..a522735 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -340,7 +340,13 @@ ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr,
     unsigned long nr = base + (start >> TARGET_PAGE_BITS);
     unsigned long size = base + (int128_get64(mr->size) >> TARGET_PAGE_BITS);
 
-    unsigned long next = find_next_bit(migration_bitmap, size, nr);
+    unsigned long next;
+
+    if (ram_bulk_stage && nr > base) {
+        next = nr + 1;
+    } else {
+        next = find_next_bit(migration_bitmap, size, nr);
+    }
 
     if (next < size) {
         clear_bit(next, migration_bitmap);
commit f1c72795af573b24a7da5eb52375c9aba8a37972
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:37 2013 +0100

    migration: do not sent zero pages in bulk stage
    
    during bulk stage of ram migration if a page is a
    zero page do not send it at all.
    the memory at the destination reads as zero anyway.
    
    even if there is an madvise with QEMU_MADV_DONTNEED
    at the target upon receipt of a zero page I have observed
    that the target starts swapping if the memory is overcommitted.
    it seems that the pages are dropped asynchronously.
    
    this patch also updates QMP to return the number of
    skipped pages in MigrationStats.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 1291bd2..3a0d02e 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -183,6 +183,7 @@ int64_t xbzrle_cache_resize(int64_t new_size)
 /* accounting for migration statistics */
 typedef struct AccountingInfo {
     uint64_t dup_pages;
+    uint64_t skipped_pages;
     uint64_t norm_pages;
     uint64_t iterations;
     uint64_t xbzrle_bytes;
@@ -208,6 +209,16 @@ uint64_t dup_mig_pages_transferred(void)
     return acct_info.dup_pages;
 }
 
+uint64_t skipped_mig_bytes_transferred(void)
+{
+    return acct_info.skipped_pages * TARGET_PAGE_SIZE;
+}
+
+uint64_t skipped_mig_pages_transferred(void)
+{
+    return acct_info.skipped_pages;
+}
+
 uint64_t norm_mig_bytes_transferred(void)
 {
     return acct_info.norm_pages * TARGET_PAGE_SIZE;
@@ -440,10 +451,15 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
             bytes_sent = -1;
             if (is_zero_page(p)) {
                 acct_info.dup_pages++;
-                bytes_sent = save_block_hdr(f, block, offset, cont,
-                                            RAM_SAVE_FLAG_COMPRESS);
-                qemu_put_byte(f, 0);
-                bytes_sent++;
+                if (!ram_bulk_stage) {
+                    bytes_sent = save_block_hdr(f, block, offset, cont,
+                                                RAM_SAVE_FLAG_COMPRESS);
+                    qemu_put_byte(f, 0);
+                    bytes_sent++;
+                } else {
+                    acct_info.skipped_pages++;
+                    bytes_sent = 0;
+                }
             } else if (migrate_use_xbzrle()) {
                 current_addr = block->offset + offset;
                 bytes_sent = save_xbzrle_page(f, p, current_addr, block,
diff --git a/hmp.c b/hmp.c
index b0a861c..e3e833e 100644
--- a/hmp.c
+++ b/hmp.c
@@ -173,6 +173,8 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
                        info->ram->total >> 10);
         monitor_printf(mon, "duplicate: %" PRIu64 " pages\n",
                        info->ram->duplicate);
+        monitor_printf(mon, "skipped: %" PRIu64 " pages\n",
+                       info->ram->skipped);
         monitor_printf(mon, "normal: %" PRIu64 " pages\n",
                        info->ram->normal);
         monitor_printf(mon, "normal bytes: %" PRIu64 " kbytes\n",
diff --git a/include/migration/migration.h b/include/migration/migration.h
index bb617fd..e2acec6 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -96,6 +96,8 @@ extern SaveVMHandlers savevm_ram_handlers;
 
 uint64_t dup_mig_bytes_transferred(void);
 uint64_t dup_mig_pages_transferred(void);
+uint64_t skipped_mig_bytes_transferred(void);
+uint64_t skipped_mig_pages_transferred(void);
 uint64_t norm_mig_bytes_transferred(void);
 uint64_t norm_mig_pages_transferred(void);
 uint64_t xbzrle_mig_bytes_transferred(void);
diff --git a/migration.c b/migration.c
index 185d112..7fb2147 100644
--- a/migration.c
+++ b/migration.c
@@ -197,11 +197,11 @@ MigrationInfo *qmp_query_migrate(Error **errp)
         info->ram->remaining = ram_bytes_remaining();
         info->ram->total = ram_bytes_total();
         info->ram->duplicate = dup_mig_pages_transferred();
+        info->ram->skipped = skipped_mig_pages_transferred();
         info->ram->normal = norm_mig_pages_transferred();
         info->ram->normal_bytes = norm_mig_bytes_transferred();
         info->ram->dirty_pages_rate = s->dirty_pages_rate;
 
-
         if (blk_mig_active()) {
             info->has_disk = true;
             info->disk = g_malloc0(sizeof(*info->disk));
@@ -227,6 +227,7 @@ MigrationInfo *qmp_query_migrate(Error **errp)
         info->ram->remaining = 0;
         info->ram->total = ram_bytes_total();
         info->ram->duplicate = dup_mig_pages_transferred();
+        info->ram->skipped = skipped_mig_pages_transferred();
         info->ram->normal = norm_mig_pages_transferred();
         info->ram->normal_bytes = norm_mig_bytes_transferred();
         break;
diff --git a/qapi-schema.json b/qapi-schema.json
index 088f4e1..6c4966b 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -496,7 +496,9 @@
 #
 # @total: total amount of bytes involved in the migration process
 #
-# @duplicate: number of duplicate pages (since 1.2)
+# @duplicate: number of duplicate (zero) pages (since 1.2)
+#
+# @skipped: number of skipped zero pages (since 1.5)
 #
 # @normal : number of normal pages (since 1.2)
 #
@@ -509,8 +511,8 @@
 ##
 { 'type': 'MigrationStats',
   'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' ,
-           'duplicate': 'int', 'normal': 'int', 'normal-bytes': 'int',
-           'dirty-pages-rate' : 'int' } }
+           'duplicate': 'int', 'skipped': 'int', 'normal': 'int',
+           'normal-bytes': 'int', 'dirty-pages-rate' : 'int' } }
 
 ##
 # @XBZRLECacheStats
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 5e847b1..fdc4048 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2445,6 +2445,7 @@ The main json-object contains the following:
          - "duplicate": number of pages filled entirely with the same
             byte (json-int)
             These are sent over the wire much more efficiently.
+         - "skipped": number of skipped zero pages (json-int)
          - "normal" : number of whole pages transfered.  I.e. they
             were not sent as duplicate or xbzrle pages (json-int)
          - "normal-bytes" : number of bytes transferred in whole
commit 78d07ae7ac74bcc7f79aeefbaff17fb142f44b4d
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:36 2013 +0100

    migration: add an indicator for bulk state of ram migration
    
    the first round of ram transfer is special since all pages
    are dirty and thus all memory pages are transferred to
    the target. this patch adds a boolean variable to track
    this stage.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index dd5deff..1291bd2 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -319,6 +319,7 @@ static ram_addr_t last_offset;
 static unsigned long *migration_bitmap;
 static uint64_t migration_dirty_pages;
 static uint32_t last_version;
+static bool ram_bulk_stage;
 
 static inline
 ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr,
@@ -426,6 +427,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
             if (!block) {
                 block = QTAILQ_FIRST(&ram_list.blocks);
                 complete_round = true;
+                ram_bulk_stage = false;
             }
         } else {
             uint8_t *p;
@@ -529,6 +531,7 @@ static void reset_ram_globals(void)
     last_sent_block = NULL;
     last_offset = 0;
     last_version = ram_list.version;
+    ram_bulk_stage = true;
 }
 
 #define MAX_WAIT 50 /* ms, half buffered_file limit */
commit 3edcd7e6ebae3ef0ac178eed5f4225803159562d
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:35 2013 +0100

    migration: search for zero instead of dup pages
    
    virtually all dup pages are zero pages. remove
    the special is_dup_page() function and use the
    optimized buffer_find_nonzero_offset() function
    instead.
    
    here buffer_find_nonzero_offset() is used directly
    to avoid the unnecssary additional checks in
    buffer_is_zero().
    
    raw performace gain checking 1 GByte zeroed memory
    over is_dup_page() is approx. 10-12% with SSE2
    and 8-10% with unsigned long arithmedtic.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 35974c2..dd5deff 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -146,19 +146,10 @@ int qemu_read_default_config_files(bool userconfig)
     return 0;
 }
 
-static int is_dup_page(uint8_t *page)
+static inline bool is_zero_page(uint8_t *p)
 {
-    VECTYPE *p = (VECTYPE *)page;
-    VECTYPE val = SPLAT(page);
-    int i;
-
-    for (i = 0; i < TARGET_PAGE_SIZE / sizeof(VECTYPE); i++) {
-        if (!ALL_EQ(val, p[i])) {
-            return 0;
-        }
-    }
-
-    return 1;
+    return buffer_find_nonzero_offset(p, TARGET_PAGE_SIZE) ==
+        TARGET_PAGE_SIZE;
 }
 
 /* struct contains XBZRLE cache and a static page
@@ -445,12 +436,12 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
 
             /* In doubt sent page as normal */
             bytes_sent = -1;
-            if (is_dup_page(p)) {
+            if (is_zero_page(p)) {
                 acct_info.dup_pages++;
                 bytes_sent = save_block_hdr(f, block, offset, cont,
                                             RAM_SAVE_FLAG_COMPRESS);
-                qemu_put_byte(f, *p);
-                bytes_sent += 1;
+                qemu_put_byte(f, 0);
+                bytes_sent++;
             } else if (migrate_use_xbzrle()) {
                 current_addr = block->offset + offset;
                 bytes_sent = save_xbzrle_page(f, p, current_addr, block,
commit 49f676a00ab540fac1d2008be26434cf85607722
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:34 2013 +0100

    bitops: unroll while loop in find_next_bit()
    
    this patch adopts the loop unrolling idea of bitmap_is_zero() to
    speed up the skipping of large areas with zeros in find_next_bit().
    
    this routine is extensively used to find dirty pages in
    live migration.
    
    testing only the find_next_bit performance on a zeroed bitfield
    the loop onrolling decreased executing time by approx. 50% on x86_64.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/util/bitops.c b/util/bitops.c
index e72237a..227c38b 100644
--- a/util/bitops.c
+++ b/util/bitops.c
@@ -42,7 +42,23 @@ unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
         size -= BITS_PER_LONG;
         result += BITS_PER_LONG;
     }
-    while (size & ~(BITS_PER_LONG-1)) {
+    while (size >= 4*BITS_PER_LONG) {
+        unsigned long d1, d2, d3;
+        tmp = *p;
+        d1 = *(p+1);
+        d2 = *(p+2);
+        d3 = *(p+3);
+        if (tmp) {
+            goto found_middle;
+        }
+        if (d1 | d2 | d3) {
+            break;
+        }
+        p += 4;
+        result += 4*BITS_PER_LONG;
+        size -= 4*BITS_PER_LONG;
+    }
+    while (size >= BITS_PER_LONG) {
         if ((tmp = *(p++))) {
             goto found_middle;
         }
commit 56ded708ec38e4cb75a7c7357480ca34c0dc6875
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:33 2013 +0100

    buffer_is_zero: use vector optimizations if possible
    
    performance gain on SSE2 is approx. 20-25%. altivec
    is not tested. performance for unsigned long arithmetic
    is unchanged.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/util/cutils.c b/util/cutils.c
index 0696a3b..5024253 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -215,6 +215,11 @@ bool buffer_is_zero(const void *buf, size_t len)
     long d0, d1, d2, d3;
     const long * const data = buf;
 
+    /* use vector optimized zero check if possible */
+    if (can_use_buffer_find_nonzero_offset(buf, len)) {
+        return buffer_find_nonzero_offset(buf, len) == len;
+    }
+
     assert(len % (4 * sizeof(long)) == 0);
     len /= sizeof(long);
 
commit 41a259bd2b1796ddabdae600ee539269a7ddb6a5
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:32 2013 +0100

    cutils: add a function to find non-zero content in a buffer
    
    this adds buffer_find_nonzero_offset() which is a SSE2/Altivec
    optimized function that searches for non-zero content in a
    buffer.
    
    the function starts full unrolling only after the first few chunks have
    been checked one by one. analyzing real memory page data has revealed
    that non-zero pages are non-zero within the first 256-512 bits in
    most cases. as this function is also heavily used to check for zero memory
    pages this tweak has been made to avoid the high setup costs of the fully
    unrolled check for non-zero pages.
    
    due to the optimizations used in the function there are restrictions
    on buffer address and search length. the function
    can_use_buffer_find_nonzero_content() can be used to check if
    the function can be used safely.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/qemu-common.h b/include/qemu-common.h
index d7ad3a7..31fff22 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -469,4 +469,14 @@ void hexdump(const char *buf, FILE *fp, const char *prefix, size_t size);
 #define ALL_EQ(v1, v2) ((v1) == (v2))
 #endif
 
+#define BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR 8
+static inline bool
+can_use_buffer_find_nonzero_offset(const void *buf, size_t len)
+{
+    return (len % (BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR
+                   * sizeof(VECTYPE)) == 0
+            && ((uintptr_t) buf) % sizeof(VECTYPE) == 0);
+}
+size_t buffer_find_nonzero_offset(const void *buf, size_t len);
+
 #endif
diff --git a/util/cutils.c b/util/cutils.c
index 1439da4..0696a3b 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -143,6 +143,61 @@ int qemu_fdatasync(int fd)
 }
 
 /*
+ * Searches for an area with non-zero content in a buffer
+ *
+ * Attention! The len must be a multiple of
+ * BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR * sizeof(VECTYPE)
+ * and addr must be a multiple of sizeof(VECTYPE) due to
+ * restriction of optimizations in this function.
+ *
+ * can_use_buffer_find_nonzero_offset() can be used to check
+ * these requirements.
+ *
+ * The return value is the offset of the non-zero area rounded
+ * down to a multiple of sizeof(VECTYPE) for the first
+ * BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR chunks and down to
+ * BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR * sizeof(VECTYPE)
+ * afterwards.
+ *
+ * If the buffer is all zero the return value is equal to len.
+ */
+
+size_t buffer_find_nonzero_offset(const void *buf, size_t len)
+{
+    const VECTYPE *p = buf;
+    const VECTYPE zero = (VECTYPE){0};
+    size_t i;
+
+    assert(can_use_buffer_find_nonzero_offset(buf, len));
+
+    if (!len) {
+        return 0;
+    }
+
+    for (i = 0; i < BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR; i++) {
+        if (!ALL_EQ(p[i], zero)) {
+            return i * sizeof(VECTYPE);
+        }
+    }
+
+    for (i = BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR;
+         i < len / sizeof(VECTYPE);
+         i += BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR) {
+        VECTYPE tmp0 = p[i + 0] | p[i + 1];
+        VECTYPE tmp1 = p[i + 2] | p[i + 3];
+        VECTYPE tmp2 = p[i + 4] | p[i + 5];
+        VECTYPE tmp3 = p[i + 6] | p[i + 7];
+        VECTYPE tmp01 = tmp0 | tmp1;
+        VECTYPE tmp23 = tmp2 | tmp3;
+        if (!ALL_EQ(tmp01 | tmp23, zero)) {
+            break;
+        }
+    }
+
+    return i * sizeof(VECTYPE);
+}
+
+/*
  * Checks if a buffer is all zeroes
  *
  * Attention! The len must be a multiple of 4 * sizeof(long) due to
commit c61ca00ada744eb24825be2ba4d6ba8fe3a870a4
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:30 2013 +0100

    move vector definitions to qemu-common.h
    
    vector optimizations will now be used at various places
    not just in is_dup_page() in arch_init.c
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index e8ade9e..35974c2 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -116,26 +116,6 @@ const uint32_t arch_type = QEMU_ARCH;
 #define RAM_SAVE_FLAG_CONTINUE 0x20
 #define RAM_SAVE_FLAG_XBZRLE   0x40
 
-#ifdef __ALTIVEC__
-#include <altivec.h>
-#define VECTYPE        vector unsigned char
-#define SPLAT(p)       vec_splat(vec_ld(0, p), 0)
-#define ALL_EQ(v1, v2) vec_all_eq(v1, v2)
-/* altivec.h may redefine the bool macro as vector type.
- * Reset it to POSIX semantics. */
-#undef bool
-#define bool _Bool
-#elif defined __SSE2__
-#include <emmintrin.h>
-#define VECTYPE        __m128i
-#define SPLAT(p)       _mm_set1_epi8(*(p))
-#define ALL_EQ(v1, v2) (_mm_movemask_epi8(_mm_cmpeq_epi8(v1, v2)) == 0xFFFF)
-#else
-#define VECTYPE        unsigned long
-#define SPLAT(p)       (*(p) * (~0UL / 255))
-#define ALL_EQ(v1, v2) ((v1) == (v2))
-#endif
-
 
 static struct defconfig_file {
     const char *filename;
diff --git a/include/qemu-common.h b/include/qemu-common.h
index 2371132..d7ad3a7 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -448,4 +448,25 @@ int uleb128_decode_small(const uint8_t *in, uint32_t *n);
 
 void hexdump(const char *buf, FILE *fp, const char *prefix, size_t size);
 
+/* vector definitions */
+#ifdef __ALTIVEC__
+#include <altivec.h>
+#define VECTYPE        vector unsigned char
+#define SPLAT(p)       vec_splat(vec_ld(0, p), 0)
+#define ALL_EQ(v1, v2) vec_all_eq(v1, v2)
+/* altivec.h may redefine the bool macro as vector type.
+ * Reset it to POSIX semantics. */
+#undef bool
+#define bool _Bool
+#elif defined __SSE2__
+#include <emmintrin.h>
+#define VECTYPE        __m128i
+#define SPLAT(p)       _mm_set1_epi8(*(p))
+#define ALL_EQ(v1, v2) (_mm_movemask_epi8(_mm_cmpeq_epi8(v1, v2)) == 0xFFFF)
+#else
+#define VECTYPE        unsigned long
+#define SPLAT(p)       (*(p) * (~0UL / 255))
+#define ALL_EQ(v1, v2) ((v1) == (v2))
+#endif
+
 #endif
commit 377e2cb96b76c2b0023c1acc7230bf3a9e9f9f40
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 14:06:04 2013 +1100

    savevm: Fix bugs in the VMSTATE_VBUFFER_MULTIPLY definition
    
    The VMSTATE_BUFFER_MULTIPLY macro is misnamed - it actually specifies
    a variably sized buffer with VMS_VBUFFER, so should be named
    VMSTATE_VBUFFER_MULTIPLY.  This patch fixes this (the macro had no current
    users under either name).
    
    In addition, unlike the other VMSTATE_VBUFFER variants, this macro did not
    specify VMS_POINTER.  This patch fixes this bug as well.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index d8af9f2..65918a9 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -393,14 +393,14 @@ extern const VMStateInfo vmstate_info_bitmap;
     .offset       = vmstate_offset_buffer(_state, _field) + _start,  \
 }
 
-#define VMSTATE_BUFFER_MULTIPLY(_field, _state, _version, _test, _start, _field_size, _multiply) { \
+#define VMSTATE_VBUFFER_MULTIPLY(_field, _state, _version, _test, _start, _field_size, _multiply) { \
     .name         = (stringify(_field)),                             \
     .version_id   = (_version),                                      \
     .field_exists = (_test),                                         \
     .size_offset  = vmstate_offset_value(_state, _field_size, uint32_t),\
     .size         = (_multiply),                                      \
     .info         = &vmstate_info_buffer,                            \
-    .flags        = VMS_VBUFFER|VMS_MULTIPLY,                        \
+    .flags        = VMS_VBUFFER|VMS_POINTER|VMS_MULTIPLY,            \
     .offset       = offsetof(_state, _field),                        \
     .start        = (_start),                                        \
 }
commit 8474a9dd6757be064bf4b35f422b4640d1cca0a5
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 14:06:03 2013 +1100

    savevm: Add VMSTATE_STRUCT_VARRAY_POINTER_UINT32
    
    Currently the savevm code contains a VMSTATE_STRUCT_VARRAY_POINTER_INT32
    helper (a variably sized array with the number of elements in an int32_t),
    but not VMSTATE_STRUCT_VARRAY_POINTER_UINT32 (... with the number of
    elements in a uint32_t).  This patch (trivially) fixes the deficiency.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 5c31ff1..d8af9f2 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -343,6 +343,16 @@ extern const VMStateInfo vmstate_info_bitmap;
     .offset     = vmstate_offset_pointer(_state, _field, _type),     \
 }
 
+#define VMSTATE_STRUCT_VARRAY_POINTER_UINT32(_field, _state, _field_num, _vmsd, _type) { \
+    .name       = (stringify(_field)),                               \
+    .version_id = 0,                                                 \
+    .num_offset = vmstate_offset_value(_state, _field_num, uint32_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,                                                 \
commit 213945e4d753b5f214468ff746d65fa76e21dbd1
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 14:06:02 2013 +1100

    savevm: Add VMSTATE_FLOAT64 helpers
    
    The current savevm code includes VMSTATE helpers for a number of commonly
    used data types, but not for the float64 type used by the internal floating
    point emulation code.  This patch fixes the deficiency.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 294d455..5c31ff1 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -157,6 +157,8 @@ extern const VMStateInfo vmstate_info_uint16;
 extern const VMStateInfo vmstate_info_uint32;
 extern const VMStateInfo vmstate_info_uint64;
 
+extern const VMStateInfo vmstate_info_float64;
+
 extern const VMStateInfo vmstate_info_timer;
 extern const VMStateInfo vmstate_info_buffer;
 extern const VMStateInfo vmstate_info_unused_buffer;
@@ -543,6 +545,13 @@ extern const VMStateInfo vmstate_info_bitmap;
 #define VMSTATE_UINT32_TEST(_f, _s, _t)                                  \
     VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_uint32, uint32_t)
 
+
+#define VMSTATE_FLOAT64_V(_f, _s, _v)                                 \
+    VMSTATE_SINGLE(_f, _s, _v, vmstate_info_float64, float64)
+
+#define VMSTATE_FLOAT64(_f, _s)                                       \
+    VMSTATE_FLOAT64_V(_f, _s, 0)
+
 #define VMSTATE_TIMER_TEST(_f, _s, _test)                             \
     VMSTATE_POINTER_TEST(_f, _s, _test, vmstate_info_timer, QEMUTimer *)
 
@@ -609,6 +618,12 @@ extern const VMStateInfo vmstate_info_bitmap;
 #define VMSTATE_INT64_ARRAY(_f, _s, _n)                               \
     VMSTATE_INT64_ARRAY_V(_f, _s, _n, 0)
 
+#define VMSTATE_FLOAT64_ARRAY_V(_f, _s, _n, _v)                       \
+    VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_float64, float64)
+
+#define VMSTATE_FLOAT64_ARRAY(_f, _s, _n)                             \
+    VMSTATE_FLOAT64_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)))
 
diff --git a/savevm.c b/savevm.c
index cd98b0d..8f1344a 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1133,6 +1133,29 @@ const VMStateInfo vmstate_info_uint16_equal = {
     .put  = put_uint16,
 };
 
+/* floating point */
+
+static int get_float64(QEMUFile *f, void *pv, size_t size)
+{
+    float64 *v = pv;
+
+    *v = make_float64(qemu_get_be64(f));
+    return 0;
+}
+
+static void put_float64(QEMUFile *f, void *pv, size_t size)
+{
+    uint64_t *v = pv;
+
+    qemu_put_be64(f, float64_val(*v));
+}
+
+const VMStateInfo vmstate_info_float64 = {
+    .name = "float64",
+    .get  = get_float64,
+    .put  = put_float64,
+};
+
 /* timers  */
 
 static int get_timer(QEMUFile *f, void *pv, size_t size)
commit d58f5598342ffebe6c6278d8b90792060fca4792
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 14:06:01 2013 +1100

    savevm: Add VMSTATE_UINTTL_EQUAL helper
    
    This adds an _EQUAL VMSTATE helper for target_ulongs, defined in terms of
    VMSTATE_UINT32_EQUAL or VMSTATE_UINT64_EQUAL as appropriate.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/hw.h b/hw/hw.h
index 1553e54..1fb9afa 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -52,16 +52,22 @@ int qemu_boot_set(const char *boot_devices);
 #if TARGET_LONG_BITS == 64
 #define VMSTATE_UINTTL_V(_f, _s, _v)                                  \
     VMSTATE_UINT64_V(_f, _s, _v)
+#define VMSTATE_UINTTL_EQUAL_V(_f, _s, _v)                            \
+    VMSTATE_UINT64_EQUAL_V(_f, _s, _v)
 #define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v)                        \
     VMSTATE_UINT64_ARRAY_V(_f, _s, _n, _v)
 #else
 #define VMSTATE_UINTTL_V(_f, _s, _v)                                  \
     VMSTATE_UINT32_V(_f, _s, _v)
+#define VMSTATE_UINTTL_EQUAL_V(_f, _s, _v)                            \
+    VMSTATE_UINT32_EQUAL_V(_f, _s, _v)
 #define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v)                        \
     VMSTATE_UINT32_ARRAY_V(_f, _s, _n, _v)
 #endif
 #define VMSTATE_UINTTL(_f, _s)                                        \
     VMSTATE_UINTTL_V(_f, _s, 0)
+#define VMSTATE_UINTTL_EQUAL(_f, _s)                                  \
+    VMSTATE_UINTTL_EQUAL_V(_f, _s, 0)
 #define VMSTATE_UINTTL_ARRAY(_f, _s, _n)                              \
     VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, 0)
 
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index f12ad79..294d455 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -519,8 +519,11 @@ extern const VMStateInfo vmstate_info_bitmap;
 #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_UINT32_EQUAL_V(_f, _s, _v)                            \
+    VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint32_equal, uint32_t)
+
+#define VMSTATE_UINT32_EQUAL(_f, _s)                                  \
+    VMSTATE_UINT32_EQUAL_V(_f, _s, 0)
 
 #define VMSTATE_UINT64_EQUAL_V(_f, _s, _v)                            \
     VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint64_equal, uint64_t)
commit e344b8a16de429ada3d9126f26e2a96d71348356
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 14:06:00 2013 +1100

    savevm: Add VMSTATE_UINT64_EQUAL helpers
    
    The savevm code already includes a number of *_EQUAL helpers which act as
    sanity checks verifying that the configuration of the saved state matches
    that of the machine we're loading into to work.  Variants already exist
    for 8 bit 16 bit and 32 bit integers, but not 64 bit integers.  This patch
    fills that hole, adding a UINT64 version.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 6666d27..f12ad79 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -149,6 +149,7 @@ 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_uint64_equal;
 extern const VMStateInfo vmstate_info_int32_le;
 
 extern const VMStateInfo vmstate_info_uint8;
@@ -521,6 +522,12 @@ extern const VMStateInfo vmstate_info_bitmap;
 #define VMSTATE_UINT32_EQUAL(_f, _s)                                   \
     VMSTATE_SINGLE(_f, _s, 0, vmstate_info_uint32_equal, uint32_t)
 
+#define VMSTATE_UINT64_EQUAL_V(_f, _s, _v)                            \
+    VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint64_equal, uint64_t)
+
+#define VMSTATE_UINT64_EQUAL(_f, _s)                                  \
+    VMSTATE_UINT64_EQUAL_V(_f, _s, 0)
+
 #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 35c8d1e..cd98b0d 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1072,6 +1072,27 @@ const VMStateInfo vmstate_info_uint64 = {
     .put  = put_uint64,
 };
 
+/* 64 bit unsigned int. See that the received value is the same than the one
+   in the field */
+
+static int get_uint64_equal(QEMUFile *f, void *pv, size_t size)
+{
+    uint64_t *v = pv;
+    uint64_t v2;
+    qemu_get_be64s(f, &v2);
+
+    if (*v == v2) {
+        return 0;
+    }
+    return -EINVAL;
+}
+
+const VMStateInfo vmstate_info_uint64_equal = {
+    .name = "int64 equal",
+    .get  = get_uint64_equal,
+    .put  = put_uint64,
+};
+
 /* 8 bit int. See that the received value is the same than the one
    in the field */
 
commit 817c60457f41e8643b612d451b3737433e9c7e0a
Author: Juan Quintela <quintela at redhat.com>
Date:   Mon Feb 11 15:11:10 2013 +0100

    migration: Improve QMP documentation
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/qmp-commands.hx b/qmp-commands.hx
index b370060..5e847b1 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -644,7 +644,7 @@ EQMP
 
 SQMP
 migrate-set-cache-size
----------------------
+----------------------
 
 Set cache size to be used by XBZRLE migration, the cache size will be rounded
 down to the nearest power of 2
@@ -667,7 +667,7 @@ EQMP
 
 SQMP
 query-migrate-cache-size
----------------------
+------------------------
 
 Show cache size to be used by XBZRLE migration
 
@@ -2431,32 +2431,42 @@ The main json-object contains the following:
      - Possible values: "active", "completed", "failed", "cancelled"
 - "total-time": total amount of ms since migration started.  If
                 migration has ended, it returns the total migration
-		 time (json-int)
+                time (json-int)
 - "downtime": only present when migration has finished correctly
               total amount in ms for downtime that happened (json-int)
 - "expected-downtime": only present while migration is active
                 total amount in ms for downtime that was calculated on
-		the last bitmap round (json-int)
+                the last bitmap round (json-int)
 - "ram": only present if "status" is "active", it is a json-object with the
-  following RAM information (in bytes):
-         - "transferred": amount transferred (json-int)
-         - "remaining": amount remaining (json-int)
-         - "total": total (json-int)
-         - "duplicate": number of duplicated pages (json-int)
-         - "normal" : number of normal pages transferred (json-int)
-         - "normal-bytes" : number of normal bytes transferred (json-int)
+  following RAM information:
+         - "transferred": amount transferred in bytes (json-int)
+         - "remaining": amount remaining to transfer in bytes (json-int)
+         - "total": total amount of memory in bytes (json-int)
+         - "duplicate": number of pages filled entirely with the same
+            byte (json-int)
+            These are sent over the wire much more efficiently.
+         - "normal" : number of whole pages transfered.  I.e. they
+            were not sent as duplicate or xbzrle pages (json-int)
+         - "normal-bytes" : number of bytes transferred in whole
+            pages. This is just normal pages times size of one page,
+            but this way upper levels don't need to care about page
+            size (json-int)
 - "disk": only present if "status" is "active" and it is a block migration,
-  it is a json-object with the following disk information (in bytes):
-         - "transferred": amount transferred (json-int)
-         - "remaining": amount remaining (json-int)
-         - "total": total (json-int)
+  it is a json-object with the following disk information:
+         - "transferred": amount transferred in bytes (json-int)
+         - "remaining": amount remaining to transfer in bytes json-int)
+         - "total": total disk size in bytes (json-int)
 - "xbzrle-cache": only present if XBZRLE is active.
   It is a json-object with the following XBZRLE information:
-         - "cache-size": XBZRLE cache size
-         - "bytes": total XBZRLE bytes transferred
+         - "cache-size": XBZRLE cache size in bytes
+         - "bytes": number of bytes transferred for XBZRLE compressed pages
          - "pages": number of XBZRLE compressed pages
-         - "cache-miss": number of cache misses
-         - "overflow": number of XBZRLE overflows
+         - "cache-miss": number of XBRZRLE page cache misses
+         - "overflow": number of times XBZRLE overflows.  This means
+           that the XBZRLE encoding was bigger than just sent the
+           whole page, and then we sent the whole page instead (as as
+           normal page).
+
 Examples:
 
 1. Before the first migration
@@ -2567,11 +2577,11 @@ EQMP
 
 SQMP
 migrate-set-capabilities
--------
+------------------------
 
 Enable/Disable migration capabilities
 
-- "xbzrle": xbzrle support
+- "xbzrle": XBZRLE support
 
 Arguments:
 
@@ -2590,7 +2600,7 @@ EQMP
     },
 SQMP
 query-migrate-capabilities
--------
+--------------------------
 
 Query current migration capabilities
 
commit 4d700430a20b3d53b7b15bc5f6666f7e570e3f2c
Author: Michal Novotny <minovotn at redhat.com>
Date:   Mon Mar 25 17:31:33 2013 +0100

    New QMP command query-cpu-max and HMP command cpu_max
    
    These commands return the maximum number of CPUs supported by the
    currently running emulator instance, as defined in its QEMUMachine
    struct.
    
    Signed-off-by: Michal Novotny <minovotn at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index df44906..3d98604 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1643,6 +1643,8 @@ show qdev device model list
 show roms
 @item info tpm
 show the TPM device
+ at item info cpu_max
+show the number of CPUs supported by the machine being emulated.
 @end table
 ETEXI
 
diff --git a/hmp.c b/hmp.c
index d319897..c12c495 100644
--- a/hmp.c
+++ b/hmp.c
@@ -748,6 +748,14 @@ void hmp_ringbuf_read(Monitor *mon, const QDict *qdict)
     g_free(data);
 }
 
+void hmp_query_cpu_max(Monitor *mon, const QDict *qdict)
+{
+    int cpu_max;
+
+    cpu_max = qmp_query_cpu_max(NULL);
+    monitor_printf(mon, "Maximum number of CPUs is %d\n", cpu_max);
+}
+
 static void hmp_cont_cb(void *opaque, int err)
 {
     if (!err) {
diff --git a/hmp.h b/hmp.h
index 95fe76e..80e8b41 100644
--- a/hmp.h
+++ b/hmp.h
@@ -42,6 +42,7 @@ void hmp_stop(Monitor *mon, const QDict *qdict);
 void hmp_system_reset(Monitor *mon, const QDict *qdict);
 void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
 void hmp_cpu(Monitor *mon, const QDict *qdict);
+void hmp_query_cpu_max(Monitor *mon, const QDict *qdict);
 void hmp_memsave(Monitor *mon, const QDict *qdict);
 void hmp_pmemsave(Monitor *mon, const QDict *qdict);
 void hmp_ringbuf_write(Monitor *mon, const QDict *qdict);
diff --git a/monitor.c b/monitor.c
index 2d9e887..e450919 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2746,6 +2746,13 @@ static mon_cmd_t info_cmds[] = {
         .mhandler.cmd = hmp_info_tpm,
     },
     {
+        .name       = "cpu_max",
+        .args_type  = "",
+        .params     = "",
+        .help       = "Get maximum number of VCPUs supported by machine",
+        .mhandler.cmd = hmp_query_cpu_max,
+    },
+    {
         .name       = NULL,
     },
 };
diff --git a/qapi-schema.json b/qapi-schema.json
index 0d16d14..af499bd 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1832,6 +1832,17 @@
 { 'command': 'query-migrate-cache-size', 'returns': 'int' }
 
 ##
+## @query-cpu-max
+##
+## query maximum number of CPUs supported by machine
+##
+## Returns: number of CPUs
+##
+## Since: 1.5
+###
+{ 'command': 'query-cpu-max', 'returns': 'int' }
+
+##
 # @ObjectPropertyInfo:
 #
 # @name: the name of the property
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 3aa6bd1..2051fcb 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -385,6 +385,28 @@ Note: CPUs' indexes are obtained with the 'query-cpus' command.
 EQMP
 
     {
+        .name       = "query-cpu-max",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_cpu_max,
+    },
+
+SQMP
+query-cpu-max
+-------------
+
+Get the maximum CPUs supported by the machine being currently
+emulated.
+
+Returns json-int.
+
+Example:
+
+-> { "execute": "query-cpu-max" }
+<- { "return": 255 }
+
+EQMP
+
+    {
         .name       = "memsave",
         .args_type  = "val:l,size:i,filename:s,cpu:i?",
         .mhandler.cmd_new = qmp_marshal_input_memsave,
diff --git a/vl.c b/vl.c
index aeed7f4..7643f16 100644
--- a/vl.c
+++ b/vl.c
@@ -662,6 +662,11 @@ StatusInfo *qmp_query_status(Error **errp)
     return info;
 }
 
+int64_t qmp_query_cpu_max(Error **errp)
+{
+    return current_machine->max_cpus;
+}
+
 /***********************************************************/
 /* real time host monotonic timer */
 
commit e5ecec7bad7b679aa11ab788424bc0e1705be15b
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Mon Mar 25 15:48:46 2013 +0100

    qmp: fix handling of boolean values in qmp-shell
    
    qmp-shell converts only integer arguments and the rest
    is assumed to be strings which are faithfully sent as
    quoted strings by json. But QEMU refuses to accept qmp
    command with boolean argument whose value is escaped
    as string.
    
    Fix it by special-casing true/false keywords and store
    value as corresponding boolean.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/QMP/qmp-shell b/QMP/qmp-shell
index 24b665c..d126e63 100755
--- a/QMP/qmp-shell
+++ b/QMP/qmp-shell
@@ -101,7 +101,12 @@ class QMPShell(qmp.QEMUMonitorProtocol):
             try:
                 value = int(opt[1])
             except ValueError:
-                value = opt[1]
+                if opt[1] == 'true':
+                    value = True
+                elif opt[1] == 'false':
+                    value = False
+                else:
+                    value = opt[1]
             qmpcmd['arguments'][opt[0]] = value
         return qmpcmd
 
commit 28c4fa32bd76268320d44db5d82e0d18fbc7c864
Author: Corey Bryant <coreyb at linux.vnet.ibm.com>
Date:   Wed Mar 20 12:34:49 2013 -0400

    QMP: TPM QMP and man page documentation updates
    
    Signed-off-by: Corey Bryant <coreyb at linux.vnet.ibm.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index d7afeab..c40ba55 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2241,7 +2241,8 @@ Backend type must be:
 @option{passthrough}.
 
 The specific backend type will determine the applicable options.
-The @code{-tpmdev} option requires a @code{-device} option.
+The @code{-tpmdev} option creates the TPM backend and requires a
+ at code{-device} option that specifies the TPM frontend interface model.
 
 Options to each backend are described below.
 
diff --git a/qmp-commands.hx b/qmp-commands.hx
index b370060..3aa6bd1 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2721,18 +2721,76 @@ EQMP
         .mhandler.cmd_new = qmp_marshal_input_query_tpm,
     },
 
+SQMP
+query-tpm
+---------
+
+Return information about the TPM device.
+
+Arguments: None
+
+Example:
+
+-> { "execute": "query-tpm" }
+<- { "return":
+     [
+       { "model": "tpm-tis",
+         "options":
+           { "type": "passthrough",
+             "data":
+               { "cancel-path": "/sys/class/misc/tpm0/device/cancel",
+                 "path": "/dev/tpm0"
+               }
+           },
+         "id": "tpm0"
+       }
+     ]
+   }
+
+EQMP
+
     {
         .name       = "query-tpm-models",
         .args_type  = "",
         .mhandler.cmd_new = qmp_marshal_input_query_tpm_models,
     },
 
+SQMP
+query-tpm-models
+----------------
+
+Return a list of supported TPM models.
+
+Arguments: None
+
+Example:
+
+-> { "execute": "query-tpm-models" }
+<- { "return": [ "tpm-tis" ] }
+
+EQMP
+
     {
         .name       = "query-tpm-types",
         .args_type  = "",
         .mhandler.cmd_new = qmp_marshal_input_query_tpm_types,
     },
 
+SQMP
+query-tpm-types
+---------------
+
+Return a list of supported TPM types.
+
+Arguments: None
+
+Example:
+
+-> { "execute": "query-tpm-types" }
+<- { "return": [ "passthrough" ] }
+
+EQMP
+
     {
         .name       = "chardev-add",
         .args_type  = "id:s,backend:q",
commit 88ca7bcff1806594c80782ad19ba50db47086b23
Author: Corey Bryant <coreyb at linux.vnet.ibm.com>
Date:   Wed Mar 20 12:34:48 2013 -0400

    QMP: Remove duplicate TPM type from query-tpm
    
    Signed-off-by: Corey Bryant <coreyb at linux.vnet.ibm.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hmp.c b/hmp.c
index b0a861c..d319897 100644
--- a/hmp.c
+++ b/hmp.c
@@ -631,11 +631,11 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
                        c, TpmModel_lookup[ti->model]);
 
         monitor_printf(mon, "  \\ %s: type=%s",
-                       ti->id, TpmType_lookup[ti->type]);
+                       ti->id, TpmTypeOptionsKind_lookup[ti->options->kind]);
 
-        switch (ti->tpm_options->kind) {
-        case TPM_TYPE_OPTIONS_KIND_TPM_PASSTHROUGH_OPTIONS:
-            tpo = ti->tpm_options->tpm_passthrough_options;
+        switch (ti->options->kind) {
+        case TPM_TYPE_OPTIONS_KIND_PASSTHROUGH:
+            tpo = ti->options->passthrough;
             monitor_printf(mon, "%s%s%s%s",
                            tpo->has_path ? ",path=" : "",
                            tpo->has_path ? tpo->path : "",
diff --git a/qapi-schema.json b/qapi-schema.json
index 088f4e1..0d16d14 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3403,13 +3403,12 @@
 #
 # A union referencing different TPM backend types' configuration options
 #
-# @tpm-passthough-options: TPMPassthroughOptions describing the TPM
-#                          passthrough configuration options
+# @passthrough: The configuration options for the TPM passthrough type
 #
 # Since: 1.5
 ##
 { 'union': 'TpmTypeOptions',
-   'data': { 'tpm-passthrough-options' : 'TPMPassthroughOptions' } }
+   'data': { 'passthrough' : 'TPMPassthroughOptions' } }
 
 ##
 # @TpmInfo:
@@ -3420,17 +3419,14 @@
 #
 # @model: The TPM frontend model
 #
-# @type: The TPM (backend) type being used
-#
-# @tpm-options: The TPM (backend) type configuration options
+# @options: The TPM (backend) type configuration options
 #
 # Since: 1.5
 ##
 { 'type': 'TPMInfo',
   'data': {'id': 'str',
            'model': 'TpmModel',
-           'type': 'TpmType',
-           'tpm-options': 'TpmTypeOptions' } }
+           'options': 'TpmTypeOptions' } }
 
 ##
 # @query-tpm:
diff --git a/tpm/tpm.c b/tpm/tpm.c
index ffd2495..ae00eae 100644
--- a/tpm/tpm.c
+++ b/tpm/tpm.c
@@ -257,14 +257,13 @@ static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv)
 
     res->id = g_strdup(drv->id);
     res->model = drv->fe_model;
-    res->type = drv->ops->type;
-    res->tpm_options = g_new0(TpmTypeOptions, 1);
+    res->options = g_new0(TpmTypeOptions, 1);
 
-    switch (res->type) {
+    switch (drv->ops->type) {
     case TPM_TYPE_PASSTHROUGH:
-        res->tpm_options->kind = TPM_TYPE_OPTIONS_KIND_TPM_PASSTHROUGH_OPTIONS;
+        res->options->kind = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;
         tpo = g_new0(TPMPassthroughOptions, 1);
-        res->tpm_options->tpm_passthrough_options = tpo;
+        res->options->passthrough = tpo;
         if (drv->path) {
             tpo->path = g_strdup(drv->path);
             tpo->has_path = true;
commit dcadaa9b40d6019ac18d6fd7763d43048ef79218
Merge: 4b5805d d32fcad
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 25 13:14:26 2013 -0500

    Merge remote-tracking branch 'stefanha/net' into staging
    
    # By Dmitry Fleytman (5) and others
    # Via Stefan Hajnoczi
    * stefanha/net:
      net: increase buffer size to accommodate Jumbo frame pkts
      VMXNET3 device implementation
      Packet abstraction for VMWARE network devices
      Common definitions for VMWARE devices
      net: iovec checksum calculator
      Checksum-related utility functions
      net: use socket_set_nodelay() for -netdev socket

commit 4b5805de49edec5a81fe810bb612317de6545a38
Merge: d2f38a0 ea804ca
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 25 13:14:20 2013 -0500

    Merge remote-tracking branch 'stefanha/block' into staging
    
    # By Liu Yuan (1) and Stefan Weil (1)
    # Via Stefan Hajnoczi
    * stefanha/block:
      block: Add options QDict to bdrv_file_open() prototypes (fix MinGW build)
      rbd: fix compile error

commit d2f38a0acb0a1c5b7ab7621a32d603d08d513bea
Merge: d63c947 0099cd4
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 25 13:13:53 2013 -0500

    Merge remote-tracking branch 'kraxel/ipxe.3' into staging
    
    # By Gerd Hoffmann
    # Via Gerd Hoffmann
    * kraxel/ipxe.3:
      ipxe: update binaries
      ipxe: disable two second timeout

commit d63c9477e0cc303492325880dc9977f4096d895d
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 25 10:23:56 2013 -0500

    glib: add a compatibility interface for g_timeout_add_seconds
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/glib-compat.h b/include/glib-compat.h
new file mode 100644
index 0000000..8aa77af
--- /dev/null
+++ b/include/glib-compat.h
@@ -0,0 +1,27 @@
+/*
+ * GLIB Compatibility Functions
+ *
+ * Copyright IBM, Corp. 2013
+ *
+ * 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 QEMU_GLIB_COMPAT_H
+#define QEMU_GLIB_COMPAT_H
+
+#include <glib.h>
+
+#if !GLIB_CHECK_VERSION(2, 14, 0)
+static inline guint g_timeout_add_seconds(guint interval, GSourceFunc function,
+                                          gpointer data)
+{
+    return g_timeout_add(interval * 1000, function, data);
+}
+#endif
+
+#endif
diff --git a/include/qemu-common.h b/include/qemu-common.h
index 7754ee2..2371132 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -40,7 +40,7 @@
 #include <sys/time.h>
 #include <assert.h>
 #include <signal.h>
-#include <glib.h>
+#include "glib-compat.h"
 
 #ifdef _WIN32
 #include "sysemu/os-win32.h"
commit 6db253caf84203c9fb106b539072699fdd4730fe
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Mar 24 19:10:02 2013 +0100

    gtk: Release modifier when graphic console loses keyboard focus
    
    This solves, e.g., sticky ALT when selecting a GTK menu, switching to a
    different window or selecting a different virtual console.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Message-id: 514F417A.6010908 at web.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/gtk.c b/ui/gtk.c
index 305940d..1edfaca 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -98,6 +98,11 @@ static inline void gdk_drawable_get_size(GdkWindow *w, gint *ww, gint *wh)
 #define GDK_KEY_minus GDK_minus
 #endif
 
+static const int modifier_keycode[] = {
+    /* shift, control, alt keys, meta keys, both left & right */
+    0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8, 0xdb, 0xdd,
+};
+
 typedef struct VirtualConsole
 {
     GtkWidget *menu_item;
@@ -157,6 +162,8 @@ typedef struct GtkDisplayState
     gboolean free_scale;
 
     bool external_pause_update;
+
+    bool modifier_pressed[ARRAY_SIZE(modifier_keycode)];
 } GtkDisplayState;
 
 static GtkDisplayState *global_state;
@@ -263,6 +270,26 @@ static void gd_update_full_redraw(GtkDisplayState *s)
     gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh);
 }
 
+static void gtk_release_modifiers(GtkDisplayState *s)
+{
+    int i, keycode;
+
+    if (!gd_on_vga(s)) {
+        return;
+    }
+    for (i = 0; i < ARRAY_SIZE(modifier_keycode); i++) {
+        keycode = modifier_keycode[i];
+        if (!s->modifier_pressed[i]) {
+            continue;
+        }
+        if (keycode & SCANCODE_GREY) {
+            kbd_put_keycode(SCANCODE_EMUL0);
+        }
+        kbd_put_keycode(keycode | SCANCODE_UP);
+        s->modifier_pressed[i] = false;
+    }
+}
+
 /** DisplayState Callbacks **/
 
 static void gd_update(DisplayChangeListener *dcl,
@@ -393,8 +420,9 @@ static gboolean gd_window_key_event(GtkWidget *widget, GdkEventKey *key, void *o
     if (!handled && propagate_accel) {
         handled = gtk_window_activate_key(GTK_WINDOW(widget), key);
     }
-
-    if (!handled) {
+    if (handled) {
+        gtk_release_modifiers(s);
+    } else {
         handled = gtk_window_propagate_key_event(GTK_WINDOW(widget), key);
     }
 
@@ -624,8 +652,10 @@ static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button,
 
 static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
 {
+    GtkDisplayState *s = opaque;
     int gdk_keycode;
     int qemu_keycode;
+    int i;
 
     gdk_keycode = key->hardware_keycode;
 
@@ -647,6 +677,12 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
             gdk_keycode, qemu_keycode,
             (key->type == GDK_KEY_PRESS) ? "down" : "up");
 
+    for (i = 0; i < ARRAY_SIZE(modifier_keycode); i++) {
+        if (qemu_keycode == modifier_keycode[i]) {
+            s->modifier_pressed[i] = (key->type == GDK_KEY_PRESS);
+        }
+    }
+
     if (qemu_keycode & SCANCODE_GREY) {
         kbd_put_keycode(SCANCODE_EMUL0);
     }
@@ -702,6 +738,7 @@ static void gd_menu_switch_vc(GtkMenuItem *item, void *opaque)
     } else {
         int i;
 
+        gtk_release_modifiers(s);
         for (i = 0; i < s->nb_vcs; i++) {
             if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->vc[i].menu_item))) {
                 gtk_notebook_set_current_page(GTK_NOTEBOOK(s->notebook), i + 1);
@@ -1002,6 +1039,16 @@ static gboolean gd_leave_event(GtkWidget *widget, GdkEventCrossing *crossing, gp
     return TRUE;
 }
 
+static gboolean gd_focus_out_event(GtkWidget *widget,
+                                   GdkEventCrossing *crossing, gpointer data)
+{
+    GtkDisplayState *s = data;
+
+    gtk_release_modifiers(s);
+
+    return TRUE;
+}
+
 /** Virtual Console Callbacks **/
 
 static int gd_vc_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
@@ -1185,6 +1232,8 @@ static void gd_connect_signals(GtkDisplayState *s)
                      G_CALLBACK(gd_enter_event), s);
     g_signal_connect(s->drawing_area, "leave-notify-event",
                      G_CALLBACK(gd_leave_event), s);
+    g_signal_connect(s->drawing_area, "focus-out-event",
+                     G_CALLBACK(gd_focus_out_event), s);
 }
 
 static void gd_create_menus(GtkDisplayState *s)
commit d32fcad366e5f45d33dab2ee4de0e5729439680b
Author: Scott Feldman <sfeldma at cumulusnetworks.com>
Date:   Mon Mar 18 11:43:44 2013 -0700

    net: increase buffer size to accommodate Jumbo frame pkts
    
    Socket buffer sizes were hard-coded to 4K for VDE and socket netdevs.  Bump this
    up to 68K (ala tap netdev) to handle maximum GSO packet size (64k) plus plenty
    of room for the ethernet and virtio_net headers.
    
    Originally, ran into this limitation when using -netdev UDP sockets to connect
    VM-to-VM, where VM interface is configure with MTU=9000.  (Using virtio_net
    NIC model).  Test is simple: ping -M do -s 8500 <target>.  This test will
    attempt to ping with unfragmented packet of given size.  Without patch, size
    is limited to < 4K (minus protocol hdrs).  With patch, ping test works with pkt
    size up to 9000 (again, minus protocol hdrs).
    
    v2: per Stefan, increase buf size to (4096+65536) as done in tap and apply
        to vde and socket netdevs.
    v1: increase buf size to 12K just for -netdev UDP sockets
    
    Signed-off-by: Scott Feldman <sfeldma at cumulusnetworks.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/include/net/net.h b/include/net/net.h
index cb049a1..43d85a1 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -11,6 +11,11 @@
 
 #define MAX_QUEUE_NUM 1024
 
+/* Maximum GSO packet size (64k) plus plenty of room for
+ * the ethernet and virtio_net headers
+ */
+#define NET_BUFSIZE (4096 + 65536)
+
 struct MACAddr {
     uint8_t a[6];
 };
diff --git a/net/net.c b/net/net.c
index f3d67f8..7869161 100644
--- a/net/net.c
+++ b/net/net.c
@@ -497,7 +497,7 @@ ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
 static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
                                int iovcnt)
 {
-    uint8_t buffer[4096];
+    uint8_t buffer[NET_BUFSIZE];
     size_t offset;
 
     offset = iov_to_buf(iov, iovcnt, 0, buffer, sizeof(buffer));
diff --git a/net/socket.c b/net/socket.c
index b0c83e0..6c3752b 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -40,7 +40,7 @@ typedef struct NetSocketState {
     unsigned int index;
     unsigned int packet_len;
     unsigned int send_index;      /* number of bytes sent (only SOCK_STREAM) */
-    uint8_t buf[4096];
+    uint8_t buf[NET_BUFSIZE];
     struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */
     IOHandler *send_fn;           /* differs between SOCK_STREAM/SOCK_DGRAM */
     bool read_poll;               /* waiting to receive data? */
@@ -146,7 +146,7 @@ static void net_socket_send(void *opaque)
     NetSocketState *s = opaque;
     int size, err;
     unsigned l;
-    uint8_t buf1[4096];
+    uint8_t buf1[NET_BUFSIZE];
     const uint8_t *buf;
 
     size = qemu_recv(s->fd, buf1, sizeof(buf1), 0);
diff --git a/net/tap.c b/net/tap.c
index ce79699..e7c8481 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -44,17 +44,12 @@
 
 #include "hw/vhost_net.h"
 
-/* Maximum GSO packet size (64k) plus plenty of room for
- * the ethernet and virtio_net headers
- */
-#define TAP_BUFSIZE (4096 + 65536)
-
 typedef struct TAPState {
     NetClientState nc;
     int fd;
     char down_script[1024];
     char down_script_arg[128];
-    uint8_t buf[TAP_BUFSIZE];
+    uint8_t buf[NET_BUFSIZE];
     bool read_poll;
     bool write_poll;
     bool using_vnet_hdr;
diff --git a/net/vde.c b/net/vde.c
index 4dea32d..2a619fb 100644
--- a/net/vde.c
+++ b/net/vde.c
@@ -39,7 +39,7 @@ typedef struct VDEState {
 static void vde_to_qemu(void *opaque)
 {
     VDEState *s = opaque;
-    uint8_t buf[4096];
+    uint8_t buf[NET_BUFSIZE];
     int size;
 
     size = vde_recv(s->vde, (char *)buf, sizeof(buf), 0);
commit 786fd2b0f87baded8c9e55307b99719eea3e016e
Author: Dmitry Fleytman <dmitry at daynix.com>
Date:   Sat Mar 9 11:21:06 2013 +0200

    VMXNET3 device implementation
    
    Signed-off-by: Dmitry Fleytman <dmitry at daynix.com>
    Signed-off-by: Yan Vugenfirer <yan at daynix.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/default-configs/pci.mak b/default-configs/pci.mak
index ee2d18d..ce56d58 100644
--- a/default-configs/pci.mak
+++ b/default-configs/pci.mak
@@ -13,6 +13,7 @@ CONFIG_LSI_SCSI_PCI=y
 CONFIG_MEGASAS_SCSI_PCI=y
 CONFIG_RTL8139_PCI=y
 CONFIG_E1000_PCI=y
+CONFIG_VMXNET3_PCI=y
 CONFIG_IDE_CORE=y
 CONFIG_IDE_QDEV=y
 CONFIG_IDE_PCI=y
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 1a988ca..d0b2ecb 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -120,6 +120,7 @@ common-obj-$(CONFIG_PCNET_COMMON) += pcnet.o
 common-obj-$(CONFIG_E1000_PCI) += e1000.o
 common-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
 common-obj-$(CONFIG_VMXNET3_PCI) += vmxnet_tx_pkt.o vmxnet_rx_pkt.o
+common-obj-$(CONFIG_VMXNET3_PCI) += vmxnet3.o
 
 common-obj-$(CONFIG_SMC91C111) += smc91c111.o
 common-obj-$(CONFIG_LAN9118) += lan9118.o
diff --git a/hw/pci/pci.h b/hw/pci/pci.h
index f340fe5..3beb70b 100644
--- a/hw/pci/pci.h
+++ b/hw/pci/pci.h
@@ -60,6 +60,7 @@
 #define PCI_DEVICE_ID_VMWARE_NET         0x0720
 #define PCI_DEVICE_ID_VMWARE_SCSI        0x0730
 #define PCI_DEVICE_ID_VMWARE_IDE         0x1729
+#define PCI_DEVICE_ID_VMWARE_VMXNET3     0x07B0
 
 /* Intel (0x8086) */
 #define PCI_DEVICE_ID_INTEL_82551IT      0x1209
diff --git a/hw/vmxnet3.c b/hw/vmxnet3.c
new file mode 100644
index 0000000..925be80
--- /dev/null
+++ b/hw/vmxnet3.c
@@ -0,0 +1,2461 @@
+/*
+ * QEMU VMWARE VMXNET3 paravirtual NIC
+ *
+ * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
+ *
+ * Developed by Daynix Computing LTD (http://www.daynix.com)
+ *
+ * Authors:
+ * Dmitry Fleytman <dmitry at daynix.com>
+ * Tamir Shomer <tamirs at daynix.com>
+ * Yan Vugenfirer <yan at daynix.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "hw.h"
+#include "pci/pci.h"
+#include "net/net.h"
+#include "virtio-net.h"
+#include "net/tap.h"
+#include "net/checksum.h"
+#include "sysemu/sysemu.h"
+#include "qemu-common.h"
+#include "qemu/bswap.h"
+#include "pci/msix.h"
+#include "pci/msi.h"
+
+#include "vmxnet3.h"
+#include "vmxnet_debug.h"
+#include "vmware_utils.h"
+#include "vmxnet_tx_pkt.h"
+#include "vmxnet_rx_pkt.h"
+
+#define PCI_DEVICE_ID_VMWARE_VMXNET3_REVISION 0x1
+#define VMXNET3_MSIX_BAR_SIZE 0x2000
+
+#define VMXNET3_BAR0_IDX      (0)
+#define VMXNET3_BAR1_IDX      (1)
+#define VMXNET3_MSIX_BAR_IDX  (2)
+
+#define VMXNET3_OFF_MSIX_TABLE (0x000)
+#define VMXNET3_OFF_MSIX_PBA   (0x800)
+
+/* Link speed in Mbps should be shifted by 16 */
+#define VMXNET3_LINK_SPEED      (1000 << 16)
+
+/* Link status: 1 - up, 0 - down. */
+#define VMXNET3_LINK_STATUS_UP  0x1
+
+/* Least significant bit should be set for revision and version */
+#define VMXNET3_DEVICE_VERSION    0x1
+#define VMXNET3_DEVICE_REVISION   0x1
+
+/* Macros for rings descriptors access */
+#define VMXNET3_READ_TX_QUEUE_DESCR8(dpa, field) \
+    (vmw_shmem_ld8(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
+
+#define VMXNET3_WRITE_TX_QUEUE_DESCR8(dpa, field, value) \
+    (vmw_shmem_st8(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field, value)))
+
+#define VMXNET3_READ_TX_QUEUE_DESCR32(dpa, field) \
+    (vmw_shmem_ld32(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
+
+#define VMXNET3_WRITE_TX_QUEUE_DESCR32(dpa, field, value) \
+    (vmw_shmem_st32(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field), value))
+
+#define VMXNET3_READ_TX_QUEUE_DESCR64(dpa, field) \
+    (vmw_shmem_ld64(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
+
+#define VMXNET3_WRITE_TX_QUEUE_DESCR64(dpa, field, value) \
+    (vmw_shmem_st64(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field), value))
+
+#define VMXNET3_READ_RX_QUEUE_DESCR64(dpa, field) \
+    (vmw_shmem_ld64(dpa + offsetof(struct Vmxnet3_RxQueueDesc, field)))
+
+#define VMXNET3_READ_RX_QUEUE_DESCR32(dpa, field) \
+    (vmw_shmem_ld32(dpa + offsetof(struct Vmxnet3_RxQueueDesc, field)))
+
+#define VMXNET3_WRITE_RX_QUEUE_DESCR64(dpa, field, value) \
+    (vmw_shmem_st64(dpa + offsetof(struct Vmxnet3_RxQueueDesc, field), value))
+
+#define VMXNET3_WRITE_RX_QUEUE_DESCR8(dpa, field, value) \
+    (vmw_shmem_st8(dpa + offsetof(struct Vmxnet3_RxQueueDesc, field), value))
+
+/* Macros for guest driver shared area access */
+#define VMXNET3_READ_DRV_SHARED64(shpa, field) \
+    (vmw_shmem_ld64(shpa + offsetof(struct Vmxnet3_DriverShared, field)))
+
+#define VMXNET3_READ_DRV_SHARED32(shpa, field) \
+    (vmw_shmem_ld32(shpa + offsetof(struct Vmxnet3_DriverShared, field)))
+
+#define VMXNET3_WRITE_DRV_SHARED32(shpa, field, val) \
+    (vmw_shmem_st32(shpa + offsetof(struct Vmxnet3_DriverShared, field), val))
+
+#define VMXNET3_READ_DRV_SHARED16(shpa, field) \
+    (vmw_shmem_ld16(shpa + offsetof(struct Vmxnet3_DriverShared, field)))
+
+#define VMXNET3_READ_DRV_SHARED8(shpa, field) \
+    (vmw_shmem_ld8(shpa + offsetof(struct Vmxnet3_DriverShared, field)))
+
+#define VMXNET3_READ_DRV_SHARED(shpa, field, b, l) \
+    (vmw_shmem_read(shpa + offsetof(struct Vmxnet3_DriverShared, field), b, l))
+
+#define VMXNET_FLAG_IS_SET(field, flag) (((field) & (flag)) == (flag))
+
+#define TYPE_VMXNET3 "vmxnet3"
+#define VMXNET3(obj) OBJECT_CHECK(VMXNET3State, (obj), TYPE_VMXNET3)
+
+/* Cyclic ring abstraction */
+typedef struct {
+    hwaddr pa;
+    size_t size;
+    size_t cell_size;
+    size_t next;
+    uint8_t gen;
+} Vmxnet3Ring;
+
+static inline void vmxnet3_ring_init(Vmxnet3Ring *ring,
+                                     hwaddr pa,
+                                     size_t size,
+                                     size_t cell_size,
+                                     bool zero_region)
+{
+    ring->pa = pa;
+    ring->size = size;
+    ring->cell_size = cell_size;
+    ring->gen = VMXNET3_INIT_GEN;
+    ring->next = 0;
+
+    if (zero_region) {
+        vmw_shmem_set(pa, 0, size * cell_size);
+    }
+}
+
+#define VMXNET3_RING_DUMP(macro, ring_name, ridx, r)                         \
+    macro("%s#%d: base %" PRIx64 " size %lu cell_size %lu gen %d next %lu",  \
+          (ring_name), (ridx),                                               \
+          (r)->pa, (r)->size, (r)->cell_size, (r)->gen, (r)->next)
+
+static inline void vmxnet3_ring_inc(Vmxnet3Ring *ring)
+{
+    if (++ring->next >= ring->size) {
+        ring->next = 0;
+        ring->gen ^= 1;
+    }
+}
+
+static inline void vmxnet3_ring_dec(Vmxnet3Ring *ring)
+{
+    if (ring->next-- == 0) {
+        ring->next = ring->size - 1;
+        ring->gen ^= 1;
+    }
+}
+
+static inline hwaddr vmxnet3_ring_curr_cell_pa(Vmxnet3Ring *ring)
+{
+    return ring->pa + ring->next * ring->cell_size;
+}
+
+static inline void vmxnet3_ring_read_curr_cell(Vmxnet3Ring *ring, void *buff)
+{
+    vmw_shmem_read(vmxnet3_ring_curr_cell_pa(ring), buff, ring->cell_size);
+}
+
+static inline void vmxnet3_ring_write_curr_cell(Vmxnet3Ring *ring, void *buff)
+{
+    vmw_shmem_write(vmxnet3_ring_curr_cell_pa(ring), buff, ring->cell_size);
+}
+
+static inline size_t vmxnet3_ring_curr_cell_idx(Vmxnet3Ring *ring)
+{
+    return ring->next;
+}
+
+static inline uint8_t vmxnet3_ring_curr_gen(Vmxnet3Ring *ring)
+{
+    return ring->gen;
+}
+
+/* Debug trace-related functions */
+static inline void
+vmxnet3_dump_tx_descr(struct Vmxnet3_TxDesc *descr)
+{
+    VMW_PKPRN("TX DESCR: "
+              "addr %" PRIx64 ", len: %d, gen: %d, rsvd: %d, "
+              "dtype: %d, ext1: %d, msscof: %d, hlen: %d, om: %d, "
+              "eop: %d, cq: %d, ext2: %d, ti: %d, tci: %d",
+              le64_to_cpu(descr->addr), descr->len, descr->gen, descr->rsvd,
+              descr->dtype, descr->ext1, descr->msscof, descr->hlen, descr->om,
+              descr->eop, descr->cq, descr->ext2, descr->ti, descr->tci);
+}
+
+static inline void
+vmxnet3_dump_virt_hdr(struct virtio_net_hdr *vhdr)
+{
+    VMW_PKPRN("VHDR: flags 0x%x, gso_type: 0x%x, hdr_len: %d, gso_size: %d, "
+              "csum_start: %d, csum_offset: %d",
+              vhdr->flags, vhdr->gso_type, vhdr->hdr_len, vhdr->gso_size,
+              vhdr->csum_start, vhdr->csum_offset);
+}
+
+static inline void
+vmxnet3_dump_rx_descr(struct Vmxnet3_RxDesc *descr)
+{
+    VMW_PKPRN("RX DESCR: addr %" PRIx64 ", len: %d, gen: %d, rsvd: %d, "
+              "dtype: %d, ext1: %d, btype: %d",
+              le64_to_cpu(descr->addr), descr->len, descr->gen,
+              descr->rsvd, descr->dtype, descr->ext1, descr->btype);
+}
+
+/* Device state and helper functions */
+#define VMXNET3_RX_RINGS_PER_QUEUE (2)
+
+typedef struct {
+    Vmxnet3Ring tx_ring;
+    Vmxnet3Ring comp_ring;
+
+    uint8_t intr_idx;
+    hwaddr tx_stats_pa;
+    struct UPT1_TxStats txq_stats;
+} Vmxnet3TxqDescr;
+
+typedef struct {
+    Vmxnet3Ring rx_ring[VMXNET3_RX_RINGS_PER_QUEUE];
+    Vmxnet3Ring comp_ring;
+    uint8_t intr_idx;
+    hwaddr rx_stats_pa;
+    struct UPT1_RxStats rxq_stats;
+} Vmxnet3RxqDescr;
+
+typedef struct {
+    bool is_masked;
+    bool is_pending;
+    bool is_asserted;
+} Vmxnet3IntState;
+
+typedef struct {
+        PCIDevice parent_obj;
+        NICState *nic;
+        NICConf conf;
+        MemoryRegion bar0;
+        MemoryRegion bar1;
+        MemoryRegion msix_bar;
+
+        Vmxnet3RxqDescr rxq_descr[VMXNET3_DEVICE_MAX_RX_QUEUES];
+        Vmxnet3TxqDescr txq_descr[VMXNET3_DEVICE_MAX_TX_QUEUES];
+
+        /* Whether MSI-X support was installed successfully */
+        bool msix_used;
+        /* Whether MSI support was installed successfully */
+        bool msi_used;
+        hwaddr drv_shmem;
+        hwaddr temp_shared_guest_driver_memory;
+
+        uint8_t txq_num;
+
+        /* This boolean tells whether RX packet being indicated has to */
+        /* be split into head and body chunks from different RX rings  */
+        bool rx_packets_compound;
+
+        bool rx_vlan_stripping;
+        bool lro_supported;
+
+        uint8_t rxq_num;
+
+        /* Network MTU */
+        uint32_t mtu;
+
+        /* Maximum number of fragments for indicated TX packets */
+        uint32_t max_tx_frags;
+
+        /* Maximum number of fragments for indicated RX packets */
+        uint16_t max_rx_frags;
+
+        /* Index for events interrupt */
+        uint8_t event_int_idx;
+
+        /* Whether automatic interrupts masking enabled */
+        bool auto_int_masking;
+
+        bool peer_has_vhdr;
+
+        /* TX packets to QEMU interface */
+        struct VmxnetTxPkt *tx_pkt;
+        uint32_t offload_mode;
+        uint32_t cso_or_gso_size;
+        uint16_t tci;
+        bool needs_vlan;
+
+        struct VmxnetRxPkt *rx_pkt;
+
+        bool tx_sop;
+        bool skip_current_tx_pkt;
+
+        uint32_t device_active;
+        uint32_t last_command;
+
+        uint32_t link_status_and_speed;
+
+        Vmxnet3IntState interrupt_states[VMXNET3_MAX_INTRS];
+
+        uint32_t temp_mac;   /* To store the low part first */
+
+        MACAddr perm_mac;
+        uint32_t vlan_table[VMXNET3_VFT_SIZE];
+        uint32_t rx_mode;
+        MACAddr *mcast_list;
+        uint32_t mcast_list_len;
+        uint32_t mcast_list_buff_size; /* needed for live migration. */
+} VMXNET3State;
+
+/* Interrupt management */
+
+/*
+ *This function returns sign whether interrupt line is in asserted state
+ * This depends on the type of interrupt used. For INTX interrupt line will
+ * be asserted until explicit deassertion, for MSI(X) interrupt line will
+ * be deasserted automatically due to notification semantics of the MSI(X)
+ * interrupts
+ */
+static bool _vmxnet3_assert_interrupt_line(VMXNET3State *s, uint32_t int_idx)
+{
+    PCIDevice *d = PCI_DEVICE(s);
+
+    if (s->msix_used && msix_enabled(d)) {
+        VMW_IRPRN("Sending MSI-X notification for vector %u", int_idx);
+        msix_notify(d, int_idx);
+        return false;
+    }
+    if (s->msi_used && msi_enabled(d)) {
+        VMW_IRPRN("Sending MSI notification for vector %u", int_idx);
+        msi_notify(d, int_idx);
+        return false;
+    }
+
+    VMW_IRPRN("Asserting line for interrupt %u", int_idx);
+    qemu_set_irq(d->irq[int_idx], 1);
+    return true;
+}
+
+static void _vmxnet3_deassert_interrupt_line(VMXNET3State *s, int lidx)
+{
+    PCIDevice *d = PCI_DEVICE(s);
+
+    /*
+     * This function should never be called for MSI(X) interrupts
+     * because deassertion never required for message interrupts
+     */
+    assert(!s->msix_used || !msix_enabled(d));
+    /*
+     * This function should never be called for MSI(X) interrupts
+     * because deassertion never required for message interrupts
+     */
+    assert(!s->msi_used || !msi_enabled(d));
+
+    VMW_IRPRN("Deasserting line for interrupt %u", lidx);
+    qemu_set_irq(d->irq[lidx], 0);
+}
+
+static void vmxnet3_update_interrupt_line_state(VMXNET3State *s, int lidx)
+{
+    if (!s->interrupt_states[lidx].is_pending &&
+       s->interrupt_states[lidx].is_asserted) {
+        VMW_IRPRN("New interrupt line state for index %d is DOWN", lidx);
+        _vmxnet3_deassert_interrupt_line(s, lidx);
+        s->interrupt_states[lidx].is_asserted = false;
+        return;
+    }
+
+    if (s->interrupt_states[lidx].is_pending &&
+       !s->interrupt_states[lidx].is_masked &&
+       !s->interrupt_states[lidx].is_asserted) {
+        VMW_IRPRN("New interrupt line state for index %d is UP", lidx);
+        s->interrupt_states[lidx].is_asserted =
+            _vmxnet3_assert_interrupt_line(s, lidx);
+        s->interrupt_states[lidx].is_pending = false;
+        return;
+    }
+}
+
+static void vmxnet3_trigger_interrupt(VMXNET3State *s, int lidx)
+{
+    PCIDevice *d = PCI_DEVICE(s);
+    s->interrupt_states[lidx].is_pending = true;
+    vmxnet3_update_interrupt_line_state(s, lidx);
+
+    if (s->msix_used && msix_enabled(d) && s->auto_int_masking) {
+        goto do_automask;
+    }
+
+    if (s->msi_used && msi_enabled(d) && s->auto_int_masking) {
+        goto do_automask;
+    }
+
+    return;
+
+do_automask:
+    s->interrupt_states[lidx].is_masked = true;
+    vmxnet3_update_interrupt_line_state(s, lidx);
+}
+
+static bool vmxnet3_interrupt_asserted(VMXNET3State *s, int lidx)
+{
+    return s->interrupt_states[lidx].is_asserted;
+}
+
+static void vmxnet3_clear_interrupt(VMXNET3State *s, int int_idx)
+{
+    s->interrupt_states[int_idx].is_pending = false;
+    if (s->auto_int_masking) {
+        s->interrupt_states[int_idx].is_masked = true;
+    }
+    vmxnet3_update_interrupt_line_state(s, int_idx);
+}
+
+static void
+vmxnet3_on_interrupt_mask_changed(VMXNET3State *s, int lidx, bool is_masked)
+{
+    s->interrupt_states[lidx].is_masked = is_masked;
+    vmxnet3_update_interrupt_line_state(s, lidx);
+}
+
+static bool vmxnet3_verify_driver_magic(hwaddr dshmem)
+{
+    return (VMXNET3_READ_DRV_SHARED32(dshmem, magic) == VMXNET3_REV1_MAGIC);
+}
+
+#define VMXNET3_GET_BYTE(x, byte_num) (((x) >> (byte_num)*8) & 0xFF)
+#define VMXNET3_MAKE_BYTE(byte_num, val) \
+    (((uint32_t)((val) & 0xFF)) << (byte_num)*8)
+
+static void vmxnet3_set_variable_mac(VMXNET3State *s, uint32_t h, uint32_t l)
+{
+    s->conf.macaddr.a[0] = VMXNET3_GET_BYTE(l,  0);
+    s->conf.macaddr.a[1] = VMXNET3_GET_BYTE(l,  1);
+    s->conf.macaddr.a[2] = VMXNET3_GET_BYTE(l,  2);
+    s->conf.macaddr.a[3] = VMXNET3_GET_BYTE(l,  3);
+    s->conf.macaddr.a[4] = VMXNET3_GET_BYTE(h, 0);
+    s->conf.macaddr.a[5] = VMXNET3_GET_BYTE(h, 1);
+
+    VMW_CFPRN("Variable MAC: " VMXNET_MF, VMXNET_MA(s->conf.macaddr.a));
+
+    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+}
+
+static uint64_t vmxnet3_get_mac_low(MACAddr *addr)
+{
+    return VMXNET3_MAKE_BYTE(0, addr->a[0]) |
+           VMXNET3_MAKE_BYTE(1, addr->a[1]) |
+           VMXNET3_MAKE_BYTE(2, addr->a[2]) |
+           VMXNET3_MAKE_BYTE(3, addr->a[3]);
+}
+
+static uint64_t vmxnet3_get_mac_high(MACAddr *addr)
+{
+    return VMXNET3_MAKE_BYTE(0, addr->a[4]) |
+           VMXNET3_MAKE_BYTE(1, addr->a[5]);
+}
+
+static void
+vmxnet3_inc_tx_consumption_counter(VMXNET3State *s, int qidx)
+{
+    vmxnet3_ring_inc(&s->txq_descr[qidx].tx_ring);
+}
+
+static inline void
+vmxnet3_inc_rx_consumption_counter(VMXNET3State *s, int qidx, int ridx)
+{
+    vmxnet3_ring_inc(&s->rxq_descr[qidx].rx_ring[ridx]);
+}
+
+static inline void
+vmxnet3_inc_tx_completion_counter(VMXNET3State *s, int qidx)
+{
+    vmxnet3_ring_inc(&s->txq_descr[qidx].comp_ring);
+}
+
+static void
+vmxnet3_inc_rx_completion_counter(VMXNET3State *s, int qidx)
+{
+    vmxnet3_ring_inc(&s->rxq_descr[qidx].comp_ring);
+}
+
+static void
+vmxnet3_dec_rx_completion_counter(VMXNET3State *s, int qidx)
+{
+    vmxnet3_ring_dec(&s->rxq_descr[qidx].comp_ring);
+}
+
+static void vmxnet3_complete_packet(VMXNET3State *s, int qidx, uint32 tx_ridx)
+{
+    struct Vmxnet3_TxCompDesc txcq_descr;
+
+    VMXNET3_RING_DUMP(VMW_RIPRN, "TXC", qidx, &s->txq_descr[qidx].comp_ring);
+
+    txcq_descr.txdIdx = tx_ridx;
+    txcq_descr.gen = vmxnet3_ring_curr_gen(&s->txq_descr[qidx].comp_ring);
+
+    vmxnet3_ring_write_curr_cell(&s->txq_descr[qidx].comp_ring, &txcq_descr);
+
+    /* Flush changes in TX descriptor before changing the counter value */
+    smp_wmb();
+
+    vmxnet3_inc_tx_completion_counter(s, qidx);
+    vmxnet3_trigger_interrupt(s, s->txq_descr[qidx].intr_idx);
+}
+
+static bool
+vmxnet3_setup_tx_offloads(VMXNET3State *s)
+{
+    switch (s->offload_mode) {
+    case VMXNET3_OM_NONE:
+        vmxnet_tx_pkt_build_vheader(s->tx_pkt, false, false, 0);
+        break;
+
+    case VMXNET3_OM_CSUM:
+        vmxnet_tx_pkt_build_vheader(s->tx_pkt, false, true, 0);
+        VMW_PKPRN("L4 CSO requested\n");
+        break;
+
+    case VMXNET3_OM_TSO:
+        vmxnet_tx_pkt_build_vheader(s->tx_pkt, true, true,
+            s->cso_or_gso_size);
+        vmxnet_tx_pkt_update_ip_checksums(s->tx_pkt);
+        VMW_PKPRN("GSO offload requested.");
+        break;
+
+    default:
+        assert(false);
+        return false;
+    }
+
+    return true;
+}
+
+static void
+vmxnet3_tx_retrieve_metadata(VMXNET3State *s,
+                             const struct Vmxnet3_TxDesc *txd)
+{
+    s->offload_mode = txd->om;
+    s->cso_or_gso_size = txd->msscof;
+    s->tci = txd->tci;
+    s->needs_vlan = txd->ti;
+}
+
+typedef enum {
+    VMXNET3_PKT_STATUS_OK,
+    VMXNET3_PKT_STATUS_ERROR,
+    VMXNET3_PKT_STATUS_DISCARD,/* only for tx */
+    VMXNET3_PKT_STATUS_OUT_OF_BUF /* only for rx */
+} Vmxnet3PktStatus;
+
+static void
+vmxnet3_on_tx_done_update_stats(VMXNET3State *s, int qidx,
+    Vmxnet3PktStatus status)
+{
+    size_t tot_len = vmxnet_tx_pkt_get_total_len(s->tx_pkt);
+    struct UPT1_TxStats *stats = &s->txq_descr[qidx].txq_stats;
+
+    switch (status) {
+    case VMXNET3_PKT_STATUS_OK:
+        switch (vmxnet_tx_pkt_get_packet_type(s->tx_pkt)) {
+        case ETH_PKT_BCAST:
+            stats->bcastPktsTxOK++;
+            stats->bcastBytesTxOK += tot_len;
+            break;
+        case ETH_PKT_MCAST:
+            stats->mcastPktsTxOK++;
+            stats->mcastBytesTxOK += tot_len;
+            break;
+        case ETH_PKT_UCAST:
+            stats->ucastPktsTxOK++;
+            stats->ucastBytesTxOK += tot_len;
+            break;
+        default:
+            assert(false);
+        }
+
+        if (s->offload_mode == VMXNET3_OM_TSO) {
+            /*
+             * According to VMWARE headers this statistic is a number
+             * of packets after segmentation but since we don't have
+             * this information in QEMU model, the best we can do is to
+             * provide number of non-segmented packets
+             */
+            stats->TSOPktsTxOK++;
+            stats->TSOBytesTxOK += tot_len;
+        }
+        break;
+
+    case VMXNET3_PKT_STATUS_DISCARD:
+        stats->pktsTxDiscard++;
+        break;
+
+    case VMXNET3_PKT_STATUS_ERROR:
+        stats->pktsTxError++;
+        break;
+
+    default:
+        assert(false);
+    }
+}
+
+static void
+vmxnet3_on_rx_done_update_stats(VMXNET3State *s,
+                                int qidx,
+                                Vmxnet3PktStatus status)
+{
+    struct UPT1_RxStats *stats = &s->rxq_descr[qidx].rxq_stats;
+    size_t tot_len = vmxnet_rx_pkt_get_total_len(s->rx_pkt);
+
+    switch (status) {
+    case VMXNET3_PKT_STATUS_OUT_OF_BUF:
+        stats->pktsRxOutOfBuf++;
+        break;
+
+    case VMXNET3_PKT_STATUS_ERROR:
+        stats->pktsRxError++;
+        break;
+    case VMXNET3_PKT_STATUS_OK:
+        switch (vmxnet_rx_pkt_get_packet_type(s->rx_pkt)) {
+        case ETH_PKT_BCAST:
+            stats->bcastPktsRxOK++;
+            stats->bcastBytesRxOK += tot_len;
+            break;
+        case ETH_PKT_MCAST:
+            stats->mcastPktsRxOK++;
+            stats->mcastBytesRxOK += tot_len;
+            break;
+        case ETH_PKT_UCAST:
+            stats->ucastPktsRxOK++;
+            stats->ucastBytesRxOK += tot_len;
+            break;
+        default:
+            assert(false);
+        }
+
+        if (tot_len > s->mtu) {
+            stats->LROPktsRxOK++;
+            stats->LROBytesRxOK += tot_len;
+        }
+        break;
+    default:
+        assert(false);
+    }
+}
+
+static inline bool
+vmxnet3_pop_next_tx_descr(VMXNET3State *s,
+                          int qidx,
+                          struct Vmxnet3_TxDesc *txd,
+                          uint32_t *descr_idx)
+{
+    Vmxnet3Ring *ring = &s->txq_descr[qidx].tx_ring;
+
+    vmxnet3_ring_read_curr_cell(ring, txd);
+    if (txd->gen == vmxnet3_ring_curr_gen(ring)) {
+        /* Only read after generation field verification */
+        smp_rmb();
+        /* Re-read to be sure we got the latest version */
+        vmxnet3_ring_read_curr_cell(ring, txd);
+        VMXNET3_RING_DUMP(VMW_RIPRN, "TX", qidx, ring);
+        *descr_idx = vmxnet3_ring_curr_cell_idx(ring);
+        vmxnet3_inc_tx_consumption_counter(s, qidx);
+        return true;
+    }
+
+    return false;
+}
+
+static bool
+vmxnet3_send_packet(VMXNET3State *s, uint32_t qidx)
+{
+    Vmxnet3PktStatus status = VMXNET3_PKT_STATUS_OK;
+
+    if (!vmxnet3_setup_tx_offloads(s)) {
+        status = VMXNET3_PKT_STATUS_ERROR;
+        goto func_exit;
+    }
+
+    /* debug prints */
+    vmxnet3_dump_virt_hdr(vmxnet_tx_pkt_get_vhdr(s->tx_pkt));
+    vmxnet_tx_pkt_dump(s->tx_pkt);
+
+    if (!vmxnet_tx_pkt_send(s->tx_pkt, qemu_get_queue(s->nic))) {
+        status = VMXNET3_PKT_STATUS_DISCARD;
+        goto func_exit;
+    }
+
+func_exit:
+    vmxnet3_on_tx_done_update_stats(s, qidx, status);
+    return (status == VMXNET3_PKT_STATUS_OK);
+}
+
+static void vmxnet3_process_tx_queue(VMXNET3State *s, int qidx)
+{
+    struct Vmxnet3_TxDesc txd;
+    uint32_t txd_idx;
+    uint32_t data_len;
+    hwaddr data_pa;
+
+    for (;;) {
+        if (!vmxnet3_pop_next_tx_descr(s, qidx, &txd, &txd_idx)) {
+            break;
+        }
+
+        vmxnet3_dump_tx_descr(&txd);
+
+        if (!s->skip_current_tx_pkt) {
+            data_len = (txd.len > 0) ? txd.len : VMXNET3_MAX_TX_BUF_SIZE;
+            data_pa = le64_to_cpu(txd.addr);
+
+            if (!vmxnet_tx_pkt_add_raw_fragment(s->tx_pkt,
+                                                data_pa,
+                                                data_len)) {
+                s->skip_current_tx_pkt = true;
+            }
+        }
+
+        if (s->tx_sop) {
+            vmxnet3_tx_retrieve_metadata(s, &txd);
+            s->tx_sop = false;
+        }
+
+        if (txd.eop) {
+            if (!s->skip_current_tx_pkt) {
+                vmxnet_tx_pkt_parse(s->tx_pkt);
+
+                if (s->needs_vlan) {
+                    vmxnet_tx_pkt_setup_vlan_header(s->tx_pkt, s->tci);
+                }
+
+                vmxnet3_send_packet(s, qidx);
+            } else {
+                vmxnet3_on_tx_done_update_stats(s, qidx,
+                                                VMXNET3_PKT_STATUS_ERROR);
+            }
+
+            vmxnet3_complete_packet(s, qidx, txd_idx);
+            s->tx_sop = true;
+            s->skip_current_tx_pkt = false;
+            vmxnet_tx_pkt_reset(s->tx_pkt);
+        }
+    }
+}
+
+static inline void
+vmxnet3_read_next_rx_descr(VMXNET3State *s, int qidx, int ridx,
+                           struct Vmxnet3_RxDesc *dbuf, uint32_t *didx)
+{
+    Vmxnet3Ring *ring = &s->rxq_descr[qidx].rx_ring[ridx];
+    *didx = vmxnet3_ring_curr_cell_idx(ring);
+    vmxnet3_ring_read_curr_cell(ring, dbuf);
+}
+
+static inline uint8_t
+vmxnet3_get_rx_ring_gen(VMXNET3State *s, int qidx, int ridx)
+{
+    return s->rxq_descr[qidx].rx_ring[ridx].gen;
+}
+
+static inline hwaddr
+vmxnet3_pop_rxc_descr(VMXNET3State *s, int qidx, uint32_t *descr_gen)
+{
+    uint8_t ring_gen;
+    struct Vmxnet3_RxCompDesc rxcd;
+
+    hwaddr daddr =
+        vmxnet3_ring_curr_cell_pa(&s->rxq_descr[qidx].comp_ring);
+
+    cpu_physical_memory_read(daddr, &rxcd, sizeof(struct Vmxnet3_RxCompDesc));
+    ring_gen = vmxnet3_ring_curr_gen(&s->rxq_descr[qidx].comp_ring);
+
+    if (rxcd.gen != ring_gen) {
+        *descr_gen = ring_gen;
+        vmxnet3_inc_rx_completion_counter(s, qidx);
+        return daddr;
+    }
+
+    return 0;
+}
+
+static inline void
+vmxnet3_revert_rxc_descr(VMXNET3State *s, int qidx)
+{
+    vmxnet3_dec_rx_completion_counter(s, qidx);
+}
+
+#define RXQ_IDX      (0)
+#define RX_HEAD_BODY_RING (0)
+#define RX_BODY_ONLY_RING (1)
+
+static bool
+vmxnet3_get_next_head_rx_descr(VMXNET3State *s,
+                               struct Vmxnet3_RxDesc *descr_buf,
+                               uint32_t *descr_idx,
+                               uint32_t *ridx)
+{
+    for (;;) {
+        uint32_t ring_gen;
+        vmxnet3_read_next_rx_descr(s, RXQ_IDX, RX_HEAD_BODY_RING,
+                                   descr_buf, descr_idx);
+
+        /* If no more free descriptors - return */
+        ring_gen = vmxnet3_get_rx_ring_gen(s, RXQ_IDX, RX_HEAD_BODY_RING);
+        if (descr_buf->gen != ring_gen) {
+            return false;
+        }
+
+        /* Only read after generation field verification */
+        smp_rmb();
+        /* Re-read to be sure we got the latest version */
+        vmxnet3_read_next_rx_descr(s, RXQ_IDX, RX_HEAD_BODY_RING,
+                                   descr_buf, descr_idx);
+
+        /* Mark current descriptor as used/skipped */
+        vmxnet3_inc_rx_consumption_counter(s, RXQ_IDX, RX_HEAD_BODY_RING);
+
+        /* If this is what we are looking for - return */
+        if (descr_buf->btype == VMXNET3_RXD_BTYPE_HEAD) {
+            *ridx = RX_HEAD_BODY_RING;
+            return true;
+        }
+    }
+}
+
+static bool
+vmxnet3_get_next_body_rx_descr(VMXNET3State *s,
+                               struct Vmxnet3_RxDesc *d,
+                               uint32_t *didx,
+                               uint32_t *ridx)
+{
+    vmxnet3_read_next_rx_descr(s, RXQ_IDX, RX_HEAD_BODY_RING, d, didx);
+
+    /* Try to find corresponding descriptor in head/body ring */
+    if (d->gen == vmxnet3_get_rx_ring_gen(s, RXQ_IDX, RX_HEAD_BODY_RING)) {
+        /* Only read after generation field verification */
+        smp_rmb();
+        /* Re-read to be sure we got the latest version */
+        vmxnet3_read_next_rx_descr(s, RXQ_IDX, RX_HEAD_BODY_RING, d, didx);
+        if (d->btype == VMXNET3_RXD_BTYPE_BODY) {
+            vmxnet3_inc_rx_consumption_counter(s, RXQ_IDX, RX_HEAD_BODY_RING);
+            *ridx = RX_HEAD_BODY_RING;
+            return true;
+        }
+    }
+
+    /*
+     * If there is no free descriptors on head/body ring or next free
+     * descriptor is a head descriptor switch to body only ring
+     */
+    vmxnet3_read_next_rx_descr(s, RXQ_IDX, RX_BODY_ONLY_RING, d, didx);
+
+    /* If no more free descriptors - return */
+    if (d->gen == vmxnet3_get_rx_ring_gen(s, RXQ_IDX, RX_BODY_ONLY_RING)) {
+        /* Only read after generation field verification */
+        smp_rmb();
+        /* Re-read to be sure we got the latest version */
+        vmxnet3_read_next_rx_descr(s, RXQ_IDX, RX_BODY_ONLY_RING, d, didx);
+        assert(d->btype == VMXNET3_RXD_BTYPE_BODY);
+        *ridx = RX_BODY_ONLY_RING;
+        vmxnet3_inc_rx_consumption_counter(s, RXQ_IDX, RX_BODY_ONLY_RING);
+        return true;
+    }
+
+    return false;
+}
+
+static inline bool
+vmxnet3_get_next_rx_descr(VMXNET3State *s, bool is_head,
+                          struct Vmxnet3_RxDesc *descr_buf,
+                          uint32_t *descr_idx,
+                          uint32_t *ridx)
+{
+    if (is_head || !s->rx_packets_compound) {
+        return vmxnet3_get_next_head_rx_descr(s, descr_buf, descr_idx, ridx);
+    } else {
+        return vmxnet3_get_next_body_rx_descr(s, descr_buf, descr_idx, ridx);
+    }
+}
+
+static void vmxnet3_rx_update_descr(struct VmxnetRxPkt *pkt,
+    struct Vmxnet3_RxCompDesc *rxcd)
+{
+    int csum_ok, is_gso;
+    bool isip4, isip6, istcp, isudp;
+    struct virtio_net_hdr *vhdr;
+    uint8_t offload_type;
+
+    if (vmxnet_rx_pkt_is_vlan_stripped(pkt)) {
+        rxcd->ts = 1;
+        rxcd->tci = vmxnet_rx_pkt_get_vlan_tag(pkt);
+    }
+
+    if (!vmxnet_rx_pkt_has_virt_hdr(pkt)) {
+        goto nocsum;
+    }
+
+    vhdr = vmxnet_rx_pkt_get_vhdr(pkt);
+    /*
+     * Checksum is valid when lower level tell so or when lower level
+     * requires checksum offload telling that packet produced/bridged
+     * locally and did travel over network after last checksum calculation
+     * or production
+     */
+    csum_ok = VMXNET_FLAG_IS_SET(vhdr->flags, VIRTIO_NET_HDR_F_DATA_VALID) ||
+              VMXNET_FLAG_IS_SET(vhdr->flags, VIRTIO_NET_HDR_F_NEEDS_CSUM);
+
+    offload_type = vhdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN;
+    is_gso = (offload_type != VIRTIO_NET_HDR_GSO_NONE) ? 1 : 0;
+
+    if (!csum_ok && !is_gso) {
+        goto nocsum;
+    }
+
+    vmxnet_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
+    if ((!istcp && !isudp) || (!isip4 && !isip6)) {
+        goto nocsum;
+    }
+
+    rxcd->cnc = 0;
+    rxcd->v4 = isip4 ? 1 : 0;
+    rxcd->v6 = isip6 ? 1 : 0;
+    rxcd->tcp = istcp ? 1 : 0;
+    rxcd->udp = isudp ? 1 : 0;
+    rxcd->fcs = rxcd->tuc = rxcd->ipc = 1;
+    return;
+
+nocsum:
+    rxcd->cnc = 1;
+    return;
+}
+
+static void
+vmxnet3_physical_memory_writev(const struct iovec *iov,
+                               size_t start_iov_off,
+                               hwaddr target_addr,
+                               size_t bytes_to_copy)
+{
+    size_t curr_off = 0;
+    size_t copied = 0;
+
+    while (bytes_to_copy) {
+        if (start_iov_off < (curr_off + iov->iov_len)) {
+            size_t chunk_len =
+                MIN((curr_off + iov->iov_len) - start_iov_off, bytes_to_copy);
+
+            cpu_physical_memory_write(target_addr + copied,
+                                      iov->iov_base + start_iov_off - curr_off,
+                                      chunk_len);
+
+            copied += chunk_len;
+            start_iov_off += chunk_len;
+            curr_off = start_iov_off;
+            bytes_to_copy -= chunk_len;
+        } else {
+            curr_off += iov->iov_len;
+        }
+        iov++;
+    }
+}
+
+static bool
+vmxnet3_indicate_packet(VMXNET3State *s)
+{
+    struct Vmxnet3_RxDesc rxd;
+    bool is_head = true;
+    uint32_t rxd_idx;
+    uint32_t rx_ridx;
+
+    struct Vmxnet3_RxCompDesc rxcd;
+    uint32_t new_rxcd_gen = VMXNET3_INIT_GEN;
+    hwaddr new_rxcd_pa = 0;
+    hwaddr ready_rxcd_pa = 0;
+    struct iovec *data = vmxnet_rx_pkt_get_iovec(s->rx_pkt);
+    size_t bytes_copied = 0;
+    size_t bytes_left = vmxnet_rx_pkt_get_total_len(s->rx_pkt);
+    uint16_t num_frags = 0;
+    size_t chunk_size;
+
+    vmxnet_rx_pkt_dump(s->rx_pkt);
+
+    while (bytes_left > 0) {
+
+        /* cannot add more frags to packet */
+        if (num_frags == s->max_rx_frags) {
+            break;
+        }
+
+        new_rxcd_pa = vmxnet3_pop_rxc_descr(s, RXQ_IDX, &new_rxcd_gen);
+        if (!new_rxcd_pa) {
+            break;
+        }
+
+        if (!vmxnet3_get_next_rx_descr(s, is_head, &rxd, &rxd_idx, &rx_ridx)) {
+            break;
+        }
+
+        chunk_size = MIN(bytes_left, rxd.len);
+        vmxnet3_physical_memory_writev(data, bytes_copied,
+                                       le64_to_cpu(rxd.addr), chunk_size);
+        bytes_copied += chunk_size;
+        bytes_left -= chunk_size;
+
+        vmxnet3_dump_rx_descr(&rxd);
+
+        if (0 != ready_rxcd_pa) {
+            cpu_physical_memory_write(ready_rxcd_pa, &rxcd, sizeof(rxcd));
+        }
+
+        memset(&rxcd, 0, sizeof(struct Vmxnet3_RxCompDesc));
+        rxcd.rxdIdx = rxd_idx;
+        rxcd.len = chunk_size;
+        rxcd.sop = is_head;
+        rxcd.gen = new_rxcd_gen;
+        rxcd.rqID = RXQ_IDX + rx_ridx * s->rxq_num;
+
+        if (0 == bytes_left) {
+            vmxnet3_rx_update_descr(s->rx_pkt, &rxcd);
+        }
+
+        VMW_RIPRN("RX Completion descriptor: rxRing: %lu rxIdx %lu len %lu "
+                  "sop %d csum_correct %lu",
+                  (unsigned long) rx_ridx,
+                  (unsigned long) rxcd.rxdIdx,
+                  (unsigned long) rxcd.len,
+                  (int) rxcd.sop,
+                  (unsigned long) rxcd.tuc);
+
+        is_head = false;
+        ready_rxcd_pa = new_rxcd_pa;
+        new_rxcd_pa = 0;
+    }
+
+    if (0 != ready_rxcd_pa) {
+        rxcd.eop = 1;
+        rxcd.err = (0 != bytes_left);
+        cpu_physical_memory_write(ready_rxcd_pa, &rxcd, sizeof(rxcd));
+
+        /* Flush RX descriptor changes */
+        smp_wmb();
+    }
+
+    if (0 != new_rxcd_pa) {
+        vmxnet3_revert_rxc_descr(s, RXQ_IDX);
+    }
+
+    vmxnet3_trigger_interrupt(s, s->rxq_descr[RXQ_IDX].intr_idx);
+
+    if (bytes_left == 0) {
+        vmxnet3_on_rx_done_update_stats(s, RXQ_IDX, VMXNET3_PKT_STATUS_OK);
+        return true;
+    } else if (num_frags == s->max_rx_frags) {
+        vmxnet3_on_rx_done_update_stats(s, RXQ_IDX, VMXNET3_PKT_STATUS_ERROR);
+        return false;
+    } else {
+        vmxnet3_on_rx_done_update_stats(s, RXQ_IDX,
+                                        VMXNET3_PKT_STATUS_OUT_OF_BUF);
+        return false;
+    }
+}
+
+static void
+vmxnet3_io_bar0_write(void *opaque, hwaddr addr,
+                      uint64_t val, unsigned size)
+{
+    VMXNET3State *s = opaque;
+
+    if (VMW_IS_MULTIREG_ADDR(addr, VMXNET3_REG_TXPROD,
+                        VMXNET3_DEVICE_MAX_TX_QUEUES, VMXNET3_REG_ALIGN)) {
+        int tx_queue_idx =
+            VMW_MULTIREG_IDX_BY_ADDR(addr, VMXNET3_REG_TXPROD,
+                                     VMXNET3_REG_ALIGN);
+        assert(tx_queue_idx <= s->txq_num);
+        vmxnet3_process_tx_queue(s, tx_queue_idx);
+        return;
+    }
+
+    if (VMW_IS_MULTIREG_ADDR(addr, VMXNET3_REG_IMR,
+                        VMXNET3_MAX_INTRS, VMXNET3_REG_ALIGN)) {
+        int l = VMW_MULTIREG_IDX_BY_ADDR(addr, VMXNET3_REG_IMR,
+                                         VMXNET3_REG_ALIGN);
+
+        VMW_CBPRN("Interrupt mask for line %d written: 0x%" PRIx64, l, val);
+
+        vmxnet3_on_interrupt_mask_changed(s, l, val);
+        return;
+    }
+
+    if (VMW_IS_MULTIREG_ADDR(addr, VMXNET3_REG_RXPROD,
+                        VMXNET3_DEVICE_MAX_RX_QUEUES, VMXNET3_REG_ALIGN) ||
+       VMW_IS_MULTIREG_ADDR(addr, VMXNET3_REG_RXPROD2,
+                        VMXNET3_DEVICE_MAX_RX_QUEUES, VMXNET3_REG_ALIGN)) {
+        return;
+    }
+
+    VMW_WRPRN("BAR0 unknown write [%" PRIx64 "] = %" PRIx64 ", size %d",
+              (uint64_t) addr, val, size);
+}
+
+static uint64_t
+vmxnet3_io_bar0_read(void *opaque, hwaddr addr, unsigned size)
+{
+    if (VMW_IS_MULTIREG_ADDR(addr, VMXNET3_REG_IMR,
+                        VMXNET3_MAX_INTRS, VMXNET3_REG_ALIGN)) {
+        assert(false);
+    }
+
+    VMW_CBPRN("BAR0 unknown read [%" PRIx64 "], size %d", addr, size);
+    return 0;
+}
+
+static void vmxnet3_reset_interrupt_states(VMXNET3State *s)
+{
+    int i;
+    for (i = 0; i < ARRAY_SIZE(s->interrupt_states); i++) {
+        s->interrupt_states[i].is_asserted = false;
+        s->interrupt_states[i].is_pending = false;
+        s->interrupt_states[i].is_masked = true;
+    }
+}
+
+static void vmxnet3_reset_mac(VMXNET3State *s)
+{
+    memcpy(&s->conf.macaddr.a, &s->perm_mac.a, sizeof(s->perm_mac.a));
+    VMW_CFPRN("MAC address set to: " VMXNET_MF, VMXNET_MA(s->conf.macaddr.a));
+}
+
+static void vmxnet3_deactivate_device(VMXNET3State *s)
+{
+    VMW_CBPRN("Deactivating vmxnet3...");
+    s->device_active = false;
+}
+
+static void vmxnet3_reset(VMXNET3State *s)
+{
+    VMW_CBPRN("Resetting vmxnet3...");
+
+    vmxnet3_deactivate_device(s);
+    vmxnet3_reset_interrupt_states(s);
+    vmxnet_tx_pkt_reset(s->tx_pkt);
+    s->drv_shmem = 0;
+    s->tx_sop = true;
+    s->skip_current_tx_pkt = false;
+}
+
+static void vmxnet3_update_rx_mode(VMXNET3State *s)
+{
+    s->rx_mode = VMXNET3_READ_DRV_SHARED32(s->drv_shmem,
+                                           devRead.rxFilterConf.rxMode);
+    VMW_CFPRN("RX mode: 0x%08X", s->rx_mode);
+}
+
+static void vmxnet3_update_vlan_filters(VMXNET3State *s)
+{
+    int i;
+
+    /* Copy configuration from shared memory */
+    VMXNET3_READ_DRV_SHARED(s->drv_shmem,
+                            devRead.rxFilterConf.vfTable,
+                            s->vlan_table,
+                            sizeof(s->vlan_table));
+
+    /* Invert byte order when needed */
+    for (i = 0; i < ARRAY_SIZE(s->vlan_table); i++) {
+        s->vlan_table[i] = le32_to_cpu(s->vlan_table[i]);
+    }
+
+    /* Dump configuration for debugging purposes */
+    VMW_CFPRN("Configured VLANs:");
+    for (i = 0; i < sizeof(s->vlan_table) * 8; i++) {
+        if (VMXNET3_VFTABLE_ENTRY_IS_SET(s->vlan_table, i)) {
+            VMW_CFPRN("\tVLAN %d is present", i);
+        }
+    }
+}
+
+static void vmxnet3_update_mcast_filters(VMXNET3State *s)
+{
+    uint16_t list_bytes =
+        VMXNET3_READ_DRV_SHARED16(s->drv_shmem,
+                                  devRead.rxFilterConf.mfTableLen);
+
+    s->mcast_list_len = list_bytes / sizeof(s->mcast_list[0]);
+
+    s->mcast_list = g_realloc(s->mcast_list, list_bytes);
+    if (NULL == s->mcast_list) {
+        if (0 == s->mcast_list_len) {
+            VMW_CFPRN("Current multicast list is empty");
+        } else {
+            VMW_ERPRN("Failed to allocate multicast list of %d elements",
+                      s->mcast_list_len);
+        }
+        s->mcast_list_len = 0;
+    } else {
+        int i;
+        hwaddr mcast_list_pa =
+            VMXNET3_READ_DRV_SHARED64(s->drv_shmem,
+                                      devRead.rxFilterConf.mfTablePA);
+
+        cpu_physical_memory_read(mcast_list_pa, s->mcast_list, list_bytes);
+        VMW_CFPRN("Current multicast list len is %d:", s->mcast_list_len);
+        for (i = 0; i < s->mcast_list_len; i++) {
+            VMW_CFPRN("\t" VMXNET_MF, VMXNET_MA(s->mcast_list[i].a));
+        }
+    }
+}
+
+static void vmxnet3_setup_rx_filtering(VMXNET3State *s)
+{
+    vmxnet3_update_rx_mode(s);
+    vmxnet3_update_vlan_filters(s);
+    vmxnet3_update_mcast_filters(s);
+}
+
+static uint32_t vmxnet3_get_interrupt_config(VMXNET3State *s)
+{
+    uint32_t interrupt_mode = VMXNET3_IT_AUTO | (VMXNET3_IMM_AUTO << 2);
+    VMW_CFPRN("Interrupt config is 0x%X", interrupt_mode);
+    return interrupt_mode;
+}
+
+static void vmxnet3_fill_stats(VMXNET3State *s)
+{
+    int i;
+    for (i = 0; i < s->txq_num; i++) {
+        cpu_physical_memory_write(s->txq_descr[i].tx_stats_pa,
+                                  &s->txq_descr[i].txq_stats,
+                                  sizeof(s->txq_descr[i].txq_stats));
+    }
+
+    for (i = 0; i < s->rxq_num; i++) {
+        cpu_physical_memory_write(s->rxq_descr[i].rx_stats_pa,
+                                  &s->rxq_descr[i].rxq_stats,
+                                  sizeof(s->rxq_descr[i].rxq_stats));
+    }
+}
+
+static void vmxnet3_adjust_by_guest_type(VMXNET3State *s)
+{
+    struct Vmxnet3_GOSInfo gos;
+
+    VMXNET3_READ_DRV_SHARED(s->drv_shmem, devRead.misc.driverInfo.gos,
+                            &gos, sizeof(gos));
+    s->rx_packets_compound =
+        (gos.gosType == VMXNET3_GOS_TYPE_WIN) ? false : true;
+
+    VMW_CFPRN("Guest type specifics: RXCOMPOUND: %d", s->rx_packets_compound);
+}
+
+static void
+vmxnet3_dump_conf_descr(const char *name,
+                        struct Vmxnet3_VariableLenConfDesc *pm_descr)
+{
+    VMW_CFPRN("%s descriptor dump: Version %u, Length %u",
+              name, pm_descr->confVer, pm_descr->confLen);
+
+};
+
+static void vmxnet3_update_pm_state(VMXNET3State *s)
+{
+    struct Vmxnet3_VariableLenConfDesc pm_descr;
+
+    pm_descr.confLen =
+        VMXNET3_READ_DRV_SHARED32(s->drv_shmem, devRead.pmConfDesc.confLen);
+    pm_descr.confVer =
+        VMXNET3_READ_DRV_SHARED32(s->drv_shmem, devRead.pmConfDesc.confVer);
+    pm_descr.confPA =
+        VMXNET3_READ_DRV_SHARED64(s->drv_shmem, devRead.pmConfDesc.confPA);
+
+    vmxnet3_dump_conf_descr("PM State", &pm_descr);
+}
+
+static void vmxnet3_update_features(VMXNET3State *s)
+{
+    uint32_t guest_features;
+    int rxcso_supported;
+
+    guest_features = VMXNET3_READ_DRV_SHARED32(s->drv_shmem,
+                                               devRead.misc.uptFeatures);
+
+    rxcso_supported = VMXNET_FLAG_IS_SET(guest_features, UPT1_F_RXCSUM);
+    s->rx_vlan_stripping = VMXNET_FLAG_IS_SET(guest_features, UPT1_F_RXVLAN);
+    s->lro_supported = VMXNET_FLAG_IS_SET(guest_features, UPT1_F_LRO);
+
+    VMW_CFPRN("Features configuration: LRO: %d, RXCSUM: %d, VLANSTRIP: %d",
+              s->lro_supported, rxcso_supported,
+              s->rx_vlan_stripping);
+    if (s->peer_has_vhdr) {
+        tap_set_offload(qemu_get_queue(s->nic)->peer,
+                        rxcso_supported,
+                        s->lro_supported,
+                        s->lro_supported,
+                        0,
+                        0);
+    }
+}
+
+static void vmxnet3_activate_device(VMXNET3State *s)
+{
+    int i;
+    static const uint32_t VMXNET3_DEF_TX_THRESHOLD = 1;
+    hwaddr qdescr_table_pa;
+    uint64_t pa;
+    uint32_t size;
+
+    /* Verify configuration consistency */
+    if (!vmxnet3_verify_driver_magic(s->drv_shmem)) {
+        VMW_ERPRN("Device configuration received from driver is invalid");
+        return;
+    }
+
+    vmxnet3_adjust_by_guest_type(s);
+    vmxnet3_update_features(s);
+    vmxnet3_update_pm_state(s);
+    vmxnet3_setup_rx_filtering(s);
+    /* Cache fields from shared memory */
+    s->mtu = VMXNET3_READ_DRV_SHARED32(s->drv_shmem, devRead.misc.mtu);
+    VMW_CFPRN("MTU is %u", s->mtu);
+
+    s->max_rx_frags =
+        VMXNET3_READ_DRV_SHARED16(s->drv_shmem, devRead.misc.maxNumRxSG);
+
+    VMW_CFPRN("Max RX fragments is %u", s->max_rx_frags);
+
+    s->event_int_idx =
+        VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.intrConf.eventIntrIdx);
+    VMW_CFPRN("Events interrupt line is %u", s->event_int_idx);
+
+    s->auto_int_masking =
+        VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.intrConf.autoMask);
+    VMW_CFPRN("Automatic interrupt masking is %d", (int)s->auto_int_masking);
+
+    s->txq_num =
+        VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.misc.numTxQueues);
+    s->rxq_num =
+        VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.misc.numRxQueues);
+
+    VMW_CFPRN("Number of TX/RX queues %u/%u", s->txq_num, s->rxq_num);
+    assert(s->txq_num <= VMXNET3_DEVICE_MAX_TX_QUEUES);
+
+    qdescr_table_pa =
+        VMXNET3_READ_DRV_SHARED64(s->drv_shmem, devRead.misc.queueDescPA);
+    VMW_CFPRN("TX queues descriptors table is at 0x%" PRIx64, qdescr_table_pa);
+
+    /*
+     * Worst-case scenario is a packet that holds all TX rings space so
+     * we calculate total size of all TX rings for max TX fragments number
+     */
+    s->max_tx_frags = 0;
+
+    /* TX queues */
+    for (i = 0; i < s->txq_num; i++) {
+        hwaddr qdescr_pa =
+            qdescr_table_pa + i * sizeof(struct Vmxnet3_TxQueueDesc);
+
+        /* Read interrupt number for this TX queue */
+        s->txq_descr[i].intr_idx =
+            VMXNET3_READ_TX_QUEUE_DESCR8(qdescr_pa, conf.intrIdx);
+
+        VMW_CFPRN("TX Queue %d interrupt: %d", i, s->txq_descr[i].intr_idx);
+
+        /* Read rings memory locations for TX queues */
+        pa = VMXNET3_READ_TX_QUEUE_DESCR64(qdescr_pa, conf.txRingBasePA);
+        size = VMXNET3_READ_TX_QUEUE_DESCR32(qdescr_pa, conf.txRingSize);
+
+        vmxnet3_ring_init(&s->txq_descr[i].tx_ring, pa, size,
+                          sizeof(struct Vmxnet3_TxDesc), false);
+        VMXNET3_RING_DUMP(VMW_CFPRN, "TX", i, &s->txq_descr[i].tx_ring);
+
+        s->max_tx_frags += size;
+
+        /* TXC ring */
+        pa = VMXNET3_READ_TX_QUEUE_DESCR64(qdescr_pa, conf.compRingBasePA);
+        size = VMXNET3_READ_TX_QUEUE_DESCR32(qdescr_pa, conf.compRingSize);
+        vmxnet3_ring_init(&s->txq_descr[i].comp_ring, pa, size,
+                          sizeof(struct Vmxnet3_TxCompDesc), true);
+        VMXNET3_RING_DUMP(VMW_CFPRN, "TXC", i, &s->txq_descr[i].comp_ring);
+
+        s->txq_descr[i].tx_stats_pa =
+            qdescr_pa + offsetof(struct Vmxnet3_TxQueueDesc, stats);
+
+        memset(&s->txq_descr[i].txq_stats, 0,
+               sizeof(s->txq_descr[i].txq_stats));
+
+        /* Fill device-managed parameters for queues */
+        VMXNET3_WRITE_TX_QUEUE_DESCR32(qdescr_pa,
+                                       ctrl.txThreshold,
+                                       VMXNET3_DEF_TX_THRESHOLD);
+    }
+
+    /* Preallocate TX packet wrapper */
+    VMW_CFPRN("Max TX fragments is %u", s->max_tx_frags);
+    vmxnet_tx_pkt_init(&s->tx_pkt, s->max_tx_frags, s->peer_has_vhdr);
+    vmxnet_rx_pkt_init(&s->rx_pkt, s->peer_has_vhdr);
+
+    /* Read rings memory locations for RX queues */
+    for (i = 0; i < s->rxq_num; i++) {
+        int j;
+        hwaddr qd_pa =
+            qdescr_table_pa + s->txq_num * sizeof(struct Vmxnet3_TxQueueDesc) +
+            i * sizeof(struct Vmxnet3_RxQueueDesc);
+
+        /* Read interrupt number for this RX queue */
+        s->rxq_descr[i].intr_idx =
+            VMXNET3_READ_TX_QUEUE_DESCR8(qd_pa, conf.intrIdx);
+
+        VMW_CFPRN("RX Queue %d interrupt: %d", i, s->rxq_descr[i].intr_idx);
+
+        /* Read rings memory locations */
+        for (j = 0; j < VMXNET3_RX_RINGS_PER_QUEUE; j++) {
+            /* RX rings */
+            pa = VMXNET3_READ_RX_QUEUE_DESCR64(qd_pa, conf.rxRingBasePA[j]);
+            size = VMXNET3_READ_RX_QUEUE_DESCR32(qd_pa, conf.rxRingSize[j]);
+            vmxnet3_ring_init(&s->rxq_descr[i].rx_ring[j], pa, size,
+                              sizeof(struct Vmxnet3_RxDesc), false);
+            VMW_CFPRN("RX queue %d:%d: Base: %" PRIx64 ", Size: %d",
+                      i, j, pa, size);
+        }
+
+        /* RXC ring */
+        pa = VMXNET3_READ_RX_QUEUE_DESCR64(qd_pa, conf.compRingBasePA);
+        size = VMXNET3_READ_RX_QUEUE_DESCR32(qd_pa, conf.compRingSize);
+        vmxnet3_ring_init(&s->rxq_descr[i].comp_ring, pa, size,
+                          sizeof(struct Vmxnet3_RxCompDesc), true);
+        VMW_CFPRN("RXC queue %d: Base: %" PRIx64 ", Size: %d", i, pa, size);
+
+        s->rxq_descr[i].rx_stats_pa =
+            qd_pa + offsetof(struct Vmxnet3_RxQueueDesc, stats);
+        memset(&s->rxq_descr[i].rxq_stats, 0,
+               sizeof(s->rxq_descr[i].rxq_stats));
+    }
+
+    /* Make sure everything is in place before device activation */
+    smp_wmb();
+
+    vmxnet3_reset_mac(s);
+
+    s->device_active = true;
+}
+
+static void vmxnet3_handle_command(VMXNET3State *s, uint64_t cmd)
+{
+    s->last_command = cmd;
+
+    switch (cmd) {
+    case VMXNET3_CMD_GET_PERM_MAC_HI:
+        VMW_CBPRN("Set: Get upper part of permanent MAC");
+        break;
+
+    case VMXNET3_CMD_GET_PERM_MAC_LO:
+        VMW_CBPRN("Set: Get lower part of permanent MAC");
+        break;
+
+    case VMXNET3_CMD_GET_STATS:
+        VMW_CBPRN("Set: Get device statistics");
+        vmxnet3_fill_stats(s);
+        break;
+
+    case VMXNET3_CMD_ACTIVATE_DEV:
+        VMW_CBPRN("Set: Activating vmxnet3 device");
+        vmxnet3_activate_device(s);
+        break;
+
+    case VMXNET3_CMD_UPDATE_RX_MODE:
+        VMW_CBPRN("Set: Update rx mode");
+        vmxnet3_update_rx_mode(s);
+        break;
+
+    case VMXNET3_CMD_UPDATE_VLAN_FILTERS:
+        VMW_CBPRN("Set: Update VLAN filters");
+        vmxnet3_update_vlan_filters(s);
+        break;
+
+    case VMXNET3_CMD_UPDATE_MAC_FILTERS:
+        VMW_CBPRN("Set: Update MAC filters");
+        vmxnet3_update_mcast_filters(s);
+        break;
+
+    case VMXNET3_CMD_UPDATE_FEATURE:
+        VMW_CBPRN("Set: Update features");
+        vmxnet3_update_features(s);
+        break;
+
+    case VMXNET3_CMD_UPDATE_PMCFG:
+        VMW_CBPRN("Set: Update power management config");
+        vmxnet3_update_pm_state(s);
+        break;
+
+    case VMXNET3_CMD_GET_LINK:
+        VMW_CBPRN("Set: Get link");
+        break;
+
+    case VMXNET3_CMD_RESET_DEV:
+        VMW_CBPRN("Set: Reset device");
+        vmxnet3_reset(s);
+        break;
+
+    case VMXNET3_CMD_QUIESCE_DEV:
+        VMW_CBPRN("Set: VMXNET3_CMD_QUIESCE_DEV - pause the device");
+        vmxnet3_deactivate_device(s);
+        break;
+
+    case VMXNET3_CMD_GET_CONF_INTR:
+        VMW_CBPRN("Set: VMXNET3_CMD_GET_CONF_INTR - interrupt configuration");
+        break;
+
+    default:
+        VMW_CBPRN("Received unknown command: %" PRIx64, cmd);
+        break;
+    }
+}
+
+static uint64_t vmxnet3_get_command_status(VMXNET3State *s)
+{
+    uint64_t ret;
+
+    switch (s->last_command) {
+    case VMXNET3_CMD_ACTIVATE_DEV:
+        ret = (s->device_active) ? 0 : -1;
+        VMW_CFPRN("Device active: %" PRIx64, ret);
+        break;
+
+    case VMXNET3_CMD_GET_LINK:
+        ret = s->link_status_and_speed;
+        VMW_CFPRN("Link and speed: %" PRIx64, ret);
+        break;
+
+    case VMXNET3_CMD_GET_PERM_MAC_LO:
+        ret = vmxnet3_get_mac_low(&s->perm_mac);
+        break;
+
+    case VMXNET3_CMD_GET_PERM_MAC_HI:
+        ret = vmxnet3_get_mac_high(&s->perm_mac);
+        break;
+
+    case VMXNET3_CMD_GET_CONF_INTR:
+        ret = vmxnet3_get_interrupt_config(s);
+        break;
+
+    default:
+        VMW_WRPRN("Received request for unknown command: %x", s->last_command);
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
+
+static void vmxnet3_set_events(VMXNET3State *s, uint32_t val)
+{
+    uint32_t events;
+
+    VMW_CBPRN("Setting events: 0x%x", val);
+    events = VMXNET3_READ_DRV_SHARED32(s->drv_shmem, ecr) | val;
+    VMXNET3_WRITE_DRV_SHARED32(s->drv_shmem, ecr, events);
+}
+
+static void vmxnet3_ack_events(VMXNET3State *s, uint32_t val)
+{
+    uint32_t events;
+
+    VMW_CBPRN("Clearing events: 0x%x", val);
+    events = VMXNET3_READ_DRV_SHARED32(s->drv_shmem, ecr) & ~val;
+    VMXNET3_WRITE_DRV_SHARED32(s->drv_shmem, ecr, events);
+}
+
+static void
+vmxnet3_io_bar1_write(void *opaque,
+                      hwaddr addr,
+                      uint64_t val,
+                      unsigned size)
+{
+    VMXNET3State *s = opaque;
+
+    switch (addr) {
+    /* Vmxnet3 Revision Report Selection */
+    case VMXNET3_REG_VRRS:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_VRRS] = %" PRIx64 ", size %d",
+                  val, size);
+        break;
+
+    /* UPT Version Report Selection */
+    case VMXNET3_REG_UVRS:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_UVRS] = %" PRIx64 ", size %d",
+                  val, size);
+        break;
+
+    /* Driver Shared Address Low */
+    case VMXNET3_REG_DSAL:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_DSAL] = %" PRIx64 ", size %d",
+                  val, size);
+        /*
+         * Guest driver will first write the low part of the shared
+         * memory address. We save it to temp variable and set the
+         * shared address only after we get the high part
+         */
+        if (0 == val) {
+            s->device_active = false;
+        }
+        s->temp_shared_guest_driver_memory = val;
+        s->drv_shmem = 0;
+        break;
+
+    /* Driver Shared Address High */
+    case VMXNET3_REG_DSAH:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_DSAH] = %" PRIx64 ", size %d",
+                  val, size);
+        /*
+         * Set the shared memory between guest driver and device.
+         * We already should have low address part.
+         */
+        s->drv_shmem = s->temp_shared_guest_driver_memory | (val << 32);
+        break;
+
+    /* Command */
+    case VMXNET3_REG_CMD:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_CMD] = %" PRIx64 ", size %d",
+                  val, size);
+        vmxnet3_handle_command(s, val);
+        break;
+
+    /* MAC Address Low */
+    case VMXNET3_REG_MACL:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_MACL] = %" PRIx64 ", size %d",
+                  val, size);
+        s->temp_mac = val;
+        break;
+
+    /* MAC Address High */
+    case VMXNET3_REG_MACH:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_MACH] = %" PRIx64 ", size %d",
+                  val, size);
+        vmxnet3_set_variable_mac(s, val, s->temp_mac);
+        break;
+
+    /* Interrupt Cause Register */
+    case VMXNET3_REG_ICR:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_ICR] = %" PRIx64 ", size %d",
+                  val, size);
+        assert(false);
+        break;
+
+    /* Event Cause Register */
+    case VMXNET3_REG_ECR:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_ECR] = %" PRIx64 ", size %d",
+                  val, size);
+        vmxnet3_ack_events(s, val);
+        break;
+
+    default:
+        VMW_CBPRN("Unknown Write to BAR1 [%" PRIx64 "] = %" PRIx64 ", size %d",
+                  addr, val, size);
+        break;
+    }
+}
+
+static uint64_t
+vmxnet3_io_bar1_read(void *opaque, hwaddr addr, unsigned size)
+{
+        VMXNET3State *s = opaque;
+        uint64_t ret = 0;
+
+        switch (addr) {
+        /* Vmxnet3 Revision Report Selection */
+        case VMXNET3_REG_VRRS:
+            VMW_CBPRN("Read BAR1 [VMXNET3_REG_VRRS], size %d", size);
+            ret = VMXNET3_DEVICE_REVISION;
+            break;
+
+        /* UPT Version Report Selection */
+        case VMXNET3_REG_UVRS:
+            VMW_CBPRN("Read BAR1 [VMXNET3_REG_UVRS], size %d", size);
+            ret = VMXNET3_DEVICE_VERSION;
+            break;
+
+        /* Command */
+        case VMXNET3_REG_CMD:
+            VMW_CBPRN("Read BAR1 [VMXNET3_REG_CMD], size %d", size);
+            ret = vmxnet3_get_command_status(s);
+            break;
+
+        /* MAC Address Low */
+        case VMXNET3_REG_MACL:
+            VMW_CBPRN("Read BAR1 [VMXNET3_REG_MACL], size %d", size);
+            ret = vmxnet3_get_mac_low(&s->conf.macaddr);
+            break;
+
+        /* MAC Address High */
+        case VMXNET3_REG_MACH:
+            VMW_CBPRN("Read BAR1 [VMXNET3_REG_MACH], size %d", size);
+            ret = vmxnet3_get_mac_high(&s->conf.macaddr);
+            break;
+
+        /*
+         * Interrupt Cause Register
+         * Used for legacy interrupts only so interrupt index always 0
+         */
+        case VMXNET3_REG_ICR:
+            VMW_CBPRN("Read BAR1 [VMXNET3_REG_ICR], size %d", size);
+            if (vmxnet3_interrupt_asserted(s, 0)) {
+                vmxnet3_clear_interrupt(s, 0);
+                ret = true;
+            } else {
+                ret = false;
+            }
+            break;
+
+        default:
+            VMW_CBPRN("Unknow read BAR1[%" PRIx64 "], %d bytes", addr, size);
+            break;
+        }
+
+        return ret;
+}
+
+static int
+vmxnet3_can_receive(NetClientState *nc)
+{
+    VMXNET3State *s = qemu_get_nic_opaque(nc);
+    return s->device_active &&
+           VMXNET_FLAG_IS_SET(s->link_status_and_speed, VMXNET3_LINK_STATUS_UP);
+}
+
+static inline bool
+vmxnet3_is_registered_vlan(VMXNET3State *s, const void *data)
+{
+    uint16_t vlan_tag = eth_get_pkt_tci(data) & VLAN_VID_MASK;
+    if (IS_SPECIAL_VLAN_ID(vlan_tag)) {
+        return true;
+    }
+
+    return VMXNET3_VFTABLE_ENTRY_IS_SET(s->vlan_table, vlan_tag);
+}
+
+static bool
+vmxnet3_is_allowed_mcast_group(VMXNET3State *s, const uint8_t *group_mac)
+{
+    int i;
+    for (i = 0; i < s->mcast_list_len; i++) {
+        if (!memcmp(group_mac, s->mcast_list[i].a, sizeof(s->mcast_list[i]))) {
+            return true;
+        }
+    }
+    return false;
+}
+
+static bool
+vmxnet3_rx_filter_may_indicate(VMXNET3State *s, const void *data,
+    size_t size)
+{
+    struct eth_header *ehdr = PKT_GET_ETH_HDR(data);
+
+    if (VMXNET_FLAG_IS_SET(s->rx_mode, VMXNET3_RXM_PROMISC)) {
+        return true;
+    }
+
+    if (!vmxnet3_is_registered_vlan(s, data)) {
+        return false;
+    }
+
+    switch (vmxnet_rx_pkt_get_packet_type(s->rx_pkt)) {
+    case ETH_PKT_UCAST:
+        if (!VMXNET_FLAG_IS_SET(s->rx_mode, VMXNET3_RXM_UCAST)) {
+            return false;
+        }
+        if (memcmp(s->conf.macaddr.a, ehdr->h_dest, ETH_ALEN)) {
+            return false;
+        }
+        break;
+
+    case ETH_PKT_BCAST:
+        if (!VMXNET_FLAG_IS_SET(s->rx_mode, VMXNET3_RXM_BCAST)) {
+            return false;
+        }
+        break;
+
+    case ETH_PKT_MCAST:
+        if (VMXNET_FLAG_IS_SET(s->rx_mode, VMXNET3_RXM_ALL_MULTI)) {
+            return true;
+        }
+        if (!VMXNET_FLAG_IS_SET(s->rx_mode, VMXNET3_RXM_MCAST)) {
+            return false;
+        }
+        if (!vmxnet3_is_allowed_mcast_group(s, ehdr->h_dest)) {
+            return false;
+        }
+        break;
+
+    default:
+        assert(false);
+    }
+
+    return true;
+}
+
+static ssize_t
+vmxnet3_receive(NetClientState *nc, const uint8_t *buf, size_t size)
+{
+    VMXNET3State *s = qemu_get_nic_opaque(nc);
+    size_t bytes_indicated;
+
+    if (!vmxnet3_can_receive(nc)) {
+        VMW_PKPRN("Cannot receive now");
+        return -1;
+    }
+
+    if (s->peer_has_vhdr) {
+        vmxnet_rx_pkt_set_vhdr(s->rx_pkt, (struct virtio_net_hdr *)buf);
+        buf += sizeof(struct virtio_net_hdr);
+        size -= sizeof(struct virtio_net_hdr);
+    }
+
+    vmxnet_rx_pkt_set_packet_type(s->rx_pkt,
+        get_eth_packet_type(PKT_GET_ETH_HDR(buf)));
+
+    if (vmxnet3_rx_filter_may_indicate(s, buf, size)) {
+        vmxnet_rx_pkt_attach_data(s->rx_pkt, buf, size, s->rx_vlan_stripping);
+        bytes_indicated = vmxnet3_indicate_packet(s) ? size : -1;
+        if (bytes_indicated < size) {
+            VMW_PKPRN("RX: %lu of %lu bytes indicated", bytes_indicated, size);
+        }
+    } else {
+        VMW_PKPRN("Packet dropped by RX filter");
+        bytes_indicated = size;
+    }
+
+    assert(size > 0);
+    assert(bytes_indicated != 0);
+    return bytes_indicated;
+}
+
+static void vmxnet3_cleanup(NetClientState *nc)
+{
+    VMXNET3State *s = qemu_get_nic_opaque(nc);
+    s->nic = NULL;
+}
+
+static void vmxnet3_set_link_status(NetClientState *nc)
+{
+    VMXNET3State *s = qemu_get_nic_opaque(nc);
+
+    if (nc->link_down) {
+        s->link_status_and_speed &= ~VMXNET3_LINK_STATUS_UP;
+    } else {
+        s->link_status_and_speed |= VMXNET3_LINK_STATUS_UP;
+    }
+
+    vmxnet3_set_events(s, VMXNET3_ECR_LINK);
+    vmxnet3_trigger_interrupt(s, s->event_int_idx);
+}
+
+static NetClientInfo net_vmxnet3_info = {
+        .type = NET_CLIENT_OPTIONS_KIND_NIC,
+        .size = sizeof(NICState),
+        .can_receive = vmxnet3_can_receive,
+        .receive = vmxnet3_receive,
+        .cleanup = vmxnet3_cleanup,
+        .link_status_changed = vmxnet3_set_link_status,
+};
+
+static bool vmxnet3_peer_has_vnet_hdr(VMXNET3State *s)
+{
+    NetClientState *peer = qemu_get_queue(s->nic)->peer;
+
+    if ((NULL != peer)                              &&
+        (peer->info->type == NET_CLIENT_OPTIONS_KIND_TAP)   &&
+        tap_has_vnet_hdr(peer)) {
+        return true;
+    }
+
+    VMW_WRPRN("Peer has no virtio extension. Task offloads will be emulated.");
+    return false;
+}
+
+static void vmxnet3_net_uninit(VMXNET3State *s)
+{
+    g_free(s->mcast_list);
+    vmxnet_tx_pkt_reset(s->tx_pkt);
+    vmxnet_tx_pkt_uninit(s->tx_pkt);
+    vmxnet_rx_pkt_uninit(s->rx_pkt);
+    qemu_del_net_client(qemu_get_queue(s->nic));
+}
+
+static void vmxnet3_net_init(VMXNET3State *s)
+{
+    DeviceState *d = DEVICE(s);
+
+    VMW_CBPRN("vmxnet3_net_init called...");
+
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+
+    /* Windows guest will query the address that was set on init */
+    memcpy(&s->perm_mac.a, &s->conf.macaddr.a, sizeof(s->perm_mac.a));
+
+    s->mcast_list = NULL;
+    s->mcast_list_len = 0;
+
+    s->link_status_and_speed = VMXNET3_LINK_SPEED | VMXNET3_LINK_STATUS_UP;
+
+    VMW_CFPRN("Permanent MAC: " MAC_FMT, MAC_ARG(s->perm_mac.a));
+
+    s->nic = qemu_new_nic(&net_vmxnet3_info, &s->conf,
+                          object_get_typename(OBJECT(s)),
+                          d->id, s);
+
+    s->peer_has_vhdr = vmxnet3_peer_has_vnet_hdr(s);
+    s->tx_sop = true;
+    s->skip_current_tx_pkt = false;
+    s->tx_pkt = NULL;
+    s->rx_pkt = NULL;
+    s->rx_vlan_stripping = false;
+    s->lro_supported = false;
+
+    if (s->peer_has_vhdr) {
+        tap_set_vnet_hdr_len(qemu_get_queue(s->nic)->peer,
+            sizeof(struct virtio_net_hdr));
+
+        tap_using_vnet_hdr(qemu_get_queue(s->nic)->peer, 1);
+    }
+
+    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+}
+
+static void
+vmxnet3_unuse_msix_vectors(VMXNET3State *s, int num_vectors)
+{
+    PCIDevice *d = PCI_DEVICE(s);
+    int i;
+    for (i = 0; i < num_vectors; i++) {
+        msix_vector_unuse(d, i);
+    }
+}
+
+static bool
+vmxnet3_use_msix_vectors(VMXNET3State *s, int num_vectors)
+{
+    PCIDevice *d = PCI_DEVICE(s);
+    int i;
+    for (i = 0; i < num_vectors; i++) {
+        int res = msix_vector_use(d, i);
+        if (0 > res) {
+            VMW_WRPRN("Failed to use MSI-X vector %d, error %d", i, res);
+            vmxnet3_unuse_msix_vectors(s, i);
+            return false;
+        }
+    }
+    return true;
+}
+
+static bool
+vmxnet3_init_msix(VMXNET3State *s)
+{
+    PCIDevice *d = PCI_DEVICE(s);
+    int res = msix_init(d, VMXNET3_MAX_INTRS,
+                        &s->msix_bar,
+                        VMXNET3_MSIX_BAR_IDX, VMXNET3_OFF_MSIX_TABLE,
+                        &s->msix_bar,
+                        VMXNET3_MSIX_BAR_IDX, VMXNET3_OFF_MSIX_PBA,
+                        0);
+
+    if (0 > res) {
+        VMW_WRPRN("Failed to initialize MSI-X, error %d", res);
+        s->msix_used = false;
+    } else {
+        if (!vmxnet3_use_msix_vectors(s, VMXNET3_MAX_INTRS)) {
+            VMW_WRPRN("Failed to use MSI-X vectors, error %d", res);
+            msix_uninit(d, &s->msix_bar, &s->msix_bar);
+            s->msix_used = false;
+        } else {
+            s->msix_used = true;
+        }
+    }
+    return s->msix_used;
+}
+
+static void
+vmxnet3_cleanup_msix(VMXNET3State *s)
+{
+    PCIDevice *d = PCI_DEVICE(s);
+
+    if (s->msix_used) {
+        msix_vector_unuse(d, VMXNET3_MAX_INTRS);
+        msix_uninit(d, &s->msix_bar, &s->msix_bar);
+    }
+}
+
+#define VMXNET3_MSI_NUM_VECTORS   (1)
+#define VMXNET3_MSI_OFFSET        (0x50)
+#define VMXNET3_USE_64BIT         (true)
+#define VMXNET3_PER_VECTOR_MASK   (false)
+
+static bool
+vmxnet3_init_msi(VMXNET3State *s)
+{
+    PCIDevice *d = PCI_DEVICE(s);
+    int res;
+
+    res = msi_init(d, VMXNET3_MSI_OFFSET, VMXNET3_MSI_NUM_VECTORS,
+                   VMXNET3_USE_64BIT, VMXNET3_PER_VECTOR_MASK);
+    if (0 > res) {
+        VMW_WRPRN("Failed to initialize MSI, error %d", res);
+        s->msi_used = false;
+    } else {
+        s->msi_used = true;
+    }
+
+    return s->msi_used;
+}
+
+static void
+vmxnet3_cleanup_msi(VMXNET3State *s)
+{
+    PCIDevice *d = PCI_DEVICE(s);
+
+    if (s->msi_used) {
+        msi_uninit(d);
+    }
+}
+
+static void
+vmxnet3_msix_save(QEMUFile *f, void *opaque)
+{
+    PCIDevice *d = PCI_DEVICE(opaque);
+    msix_save(d, f);
+}
+
+static int
+vmxnet3_msix_load(QEMUFile *f, void *opaque, int version_id)
+{
+    PCIDevice *d = PCI_DEVICE(opaque);
+    msix_load(d, f);
+    return 0;
+}
+
+static const MemoryRegionOps b0_ops = {
+    .read = vmxnet3_io_bar0_read,
+    .write = vmxnet3_io_bar0_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+            .min_access_size = 4,
+            .max_access_size = 4,
+    },
+};
+
+static const MemoryRegionOps b1_ops = {
+    .read = vmxnet3_io_bar1_read,
+    .write = vmxnet3_io_bar1_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+            .min_access_size = 4,
+            .max_access_size = 4,
+    },
+};
+
+static int vmxnet3_pci_init(PCIDevice *pci_dev)
+{
+    DeviceState *dev = DEVICE(pci_dev);
+    VMXNET3State *s = VMXNET3(pci_dev);
+
+    VMW_CBPRN("Starting init...");
+
+    memory_region_init_io(&s->bar0, &b0_ops, s,
+                          "vmxnet3-b0", VMXNET3_PT_REG_SIZE);
+    pci_register_bar(pci_dev, VMXNET3_BAR0_IDX,
+                     PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0);
+
+    memory_region_init_io(&s->bar1, &b1_ops, s,
+                          "vmxnet3-b1", VMXNET3_VD_REG_SIZE);
+    pci_register_bar(pci_dev, VMXNET3_BAR1_IDX,
+                     PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar1);
+
+    memory_region_init(&s->msix_bar, "vmxnet3-msix-bar",
+                       VMXNET3_MSIX_BAR_SIZE);
+    pci_register_bar(pci_dev, VMXNET3_MSIX_BAR_IDX,
+                     PCI_BASE_ADDRESS_SPACE_MEMORY, &s->msix_bar);
+
+    vmxnet3_reset_interrupt_states(s);
+
+    /* Interrupt pin A */
+    pci_dev->config[PCI_INTERRUPT_PIN] = 0x01;
+
+    if (!vmxnet3_init_msix(s)) {
+        VMW_WRPRN("Failed to initialize MSI-X, configuration is inconsistent.");
+    }
+
+    if (!vmxnet3_init_msi(s)) {
+        VMW_WRPRN("Failed to initialize MSI, configuration is inconsistent.");
+    }
+
+    vmxnet3_net_init(s);
+
+    register_savevm(dev, "vmxnet3-msix", -1, 1,
+                    vmxnet3_msix_save, vmxnet3_msix_load, s);
+
+    add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy at 0");
+
+    return 0;
+}
+
+
+static void vmxnet3_pci_uninit(PCIDevice *pci_dev)
+{
+    DeviceState *dev = DEVICE(pci_dev);
+    VMXNET3State *s = VMXNET3(pci_dev);
+
+    VMW_CBPRN("Starting uninit...");
+
+    unregister_savevm(dev, "vmxnet3-msix", s);
+
+    vmxnet3_net_uninit(s);
+
+    vmxnet3_cleanup_msix(s);
+
+    vmxnet3_cleanup_msi(s);
+
+    memory_region_destroy(&s->bar0);
+    memory_region_destroy(&s->bar1);
+    memory_region_destroy(&s->msix_bar);
+}
+
+static void vmxnet3_qdev_reset(DeviceState *dev)
+{
+    PCIDevice *d = PCI_DEVICE(dev);
+    VMXNET3State *s = VMXNET3(d);
+
+    VMW_CBPRN("Starting QDEV reset...");
+    vmxnet3_reset(s);
+}
+
+static bool vmxnet3_mc_list_needed(void *opaque)
+{
+    return true;
+}
+
+static int vmxnet3_mcast_list_pre_load(void *opaque)
+{
+    VMXNET3State *s = opaque;
+
+    s->mcast_list = g_malloc(s->mcast_list_buff_size);
+
+    return 0;
+}
+
+
+static void vmxnet3_pre_save(void *opaque)
+{
+    VMXNET3State *s = opaque;
+
+    s->mcast_list_buff_size = s->mcast_list_len * sizeof(MACAddr);
+}
+
+static const VMStateDescription vmxstate_vmxnet3_mcast_list = {
+    .name = "vmxnet3/mcast_list",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .pre_load = vmxnet3_mcast_list_pre_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_VBUFFER_UINT32(mcast_list, VMXNET3State, 0, NULL, 0,
+            mcast_list_buff_size),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void vmxnet3_get_ring_from_file(QEMUFile *f, Vmxnet3Ring *r)
+{
+    r->pa = qemu_get_be64(f);
+    r->size = qemu_get_be32(f);
+    r->cell_size = qemu_get_be32(f);
+    r->next = qemu_get_be32(f);
+    r->gen = qemu_get_byte(f);
+}
+
+static void vmxnet3_put_ring_to_file(QEMUFile *f, Vmxnet3Ring *r)
+{
+    qemu_put_be64(f, r->pa);
+    qemu_put_be32(f, r->size);
+    qemu_put_be32(f, r->cell_size);
+    qemu_put_be32(f, r->next);
+    qemu_put_byte(f, r->gen);
+}
+
+static void vmxnet3_get_tx_stats_from_file(QEMUFile *f,
+    struct UPT1_TxStats *tx_stat)
+{
+    tx_stat->TSOPktsTxOK = qemu_get_be64(f);
+    tx_stat->TSOBytesTxOK = qemu_get_be64(f);
+    tx_stat->ucastPktsTxOK = qemu_get_be64(f);
+    tx_stat->ucastBytesTxOK = qemu_get_be64(f);
+    tx_stat->mcastPktsTxOK = qemu_get_be64(f);
+    tx_stat->mcastBytesTxOK = qemu_get_be64(f);
+    tx_stat->bcastPktsTxOK = qemu_get_be64(f);
+    tx_stat->bcastBytesTxOK = qemu_get_be64(f);
+    tx_stat->pktsTxError = qemu_get_be64(f);
+    tx_stat->pktsTxDiscard = qemu_get_be64(f);
+}
+
+static void vmxnet3_put_tx_stats_to_file(QEMUFile *f,
+    struct UPT1_TxStats *tx_stat)
+{
+    qemu_put_be64(f, tx_stat->TSOPktsTxOK);
+    qemu_put_be64(f, tx_stat->TSOBytesTxOK);
+    qemu_put_be64(f, tx_stat->ucastPktsTxOK);
+    qemu_put_be64(f, tx_stat->ucastBytesTxOK);
+    qemu_put_be64(f, tx_stat->mcastPktsTxOK);
+    qemu_put_be64(f, tx_stat->mcastBytesTxOK);
+    qemu_put_be64(f, tx_stat->bcastPktsTxOK);
+    qemu_put_be64(f, tx_stat->bcastBytesTxOK);
+    qemu_put_be64(f, tx_stat->pktsTxError);
+    qemu_put_be64(f, tx_stat->pktsTxDiscard);
+}
+
+static int vmxnet3_get_txq_descr(QEMUFile *f, void *pv, size_t size)
+{
+    Vmxnet3TxqDescr *r = pv;
+
+    vmxnet3_get_ring_from_file(f, &r->tx_ring);
+    vmxnet3_get_ring_from_file(f, &r->comp_ring);
+    r->intr_idx = qemu_get_byte(f);
+    r->tx_stats_pa = qemu_get_be64(f);
+
+    vmxnet3_get_tx_stats_from_file(f, &r->txq_stats);
+
+    return 0;
+}
+
+static void vmxnet3_put_txq_descr(QEMUFile *f, void *pv, size_t size)
+{
+    Vmxnet3TxqDescr *r = pv;
+
+    vmxnet3_put_ring_to_file(f, &r->tx_ring);
+    vmxnet3_put_ring_to_file(f, &r->comp_ring);
+    qemu_put_byte(f, r->intr_idx);
+    qemu_put_be64(f, r->tx_stats_pa);
+    vmxnet3_put_tx_stats_to_file(f, &r->txq_stats);
+}
+
+const VMStateInfo txq_descr_info = {
+    .name = "txq_descr",
+    .get = vmxnet3_get_txq_descr,
+    .put = vmxnet3_put_txq_descr
+};
+
+static void vmxnet3_get_rx_stats_from_file(QEMUFile *f,
+    struct UPT1_RxStats *rx_stat)
+{
+    rx_stat->LROPktsRxOK = qemu_get_be64(f);
+    rx_stat->LROBytesRxOK = qemu_get_be64(f);
+    rx_stat->ucastPktsRxOK = qemu_get_be64(f);
+    rx_stat->ucastBytesRxOK = qemu_get_be64(f);
+    rx_stat->mcastPktsRxOK = qemu_get_be64(f);
+    rx_stat->mcastBytesRxOK = qemu_get_be64(f);
+    rx_stat->bcastPktsRxOK = qemu_get_be64(f);
+    rx_stat->bcastBytesRxOK = qemu_get_be64(f);
+    rx_stat->pktsRxOutOfBuf = qemu_get_be64(f);
+    rx_stat->pktsRxError = qemu_get_be64(f);
+}
+
+static void vmxnet3_put_rx_stats_to_file(QEMUFile *f,
+    struct UPT1_RxStats *rx_stat)
+{
+    qemu_put_be64(f, rx_stat->LROPktsRxOK);
+    qemu_put_be64(f, rx_stat->LROBytesRxOK);
+    qemu_put_be64(f, rx_stat->ucastPktsRxOK);
+    qemu_put_be64(f, rx_stat->ucastBytesRxOK);
+    qemu_put_be64(f, rx_stat->mcastPktsRxOK);
+    qemu_put_be64(f, rx_stat->mcastBytesRxOK);
+    qemu_put_be64(f, rx_stat->bcastPktsRxOK);
+    qemu_put_be64(f, rx_stat->bcastBytesRxOK);
+    qemu_put_be64(f, rx_stat->pktsRxOutOfBuf);
+    qemu_put_be64(f, rx_stat->pktsRxError);
+}
+
+static int vmxnet3_get_rxq_descr(QEMUFile *f, void *pv, size_t size)
+{
+    Vmxnet3RxqDescr *r = pv;
+    int i;
+
+    for (i = 0; i < VMXNET3_RX_RINGS_PER_QUEUE; i++) {
+        vmxnet3_get_ring_from_file(f, &r->rx_ring[i]);
+    }
+
+    vmxnet3_get_ring_from_file(f, &r->comp_ring);
+    r->intr_idx = qemu_get_byte(f);
+    r->rx_stats_pa = qemu_get_be64(f);
+
+    vmxnet3_get_rx_stats_from_file(f, &r->rxq_stats);
+
+    return 0;
+}
+
+static void vmxnet3_put_rxq_descr(QEMUFile *f, void *pv, size_t size)
+{
+    Vmxnet3RxqDescr *r = pv;
+    int i;
+
+    for (i = 0; i < VMXNET3_RX_RINGS_PER_QUEUE; i++) {
+        vmxnet3_put_ring_to_file(f, &r->rx_ring[i]);
+    }
+
+    vmxnet3_put_ring_to_file(f, &r->comp_ring);
+    qemu_put_byte(f, r->intr_idx);
+    qemu_put_be64(f, r->rx_stats_pa);
+    vmxnet3_put_rx_stats_to_file(f, &r->rxq_stats);
+}
+
+static int vmxnet3_post_load(void *opaque, int version_id)
+{
+    VMXNET3State *s = opaque;
+    PCIDevice *d = PCI_DEVICE(s);
+
+    vmxnet_tx_pkt_init(&s->tx_pkt, s->max_tx_frags, s->peer_has_vhdr);
+    vmxnet_rx_pkt_init(&s->rx_pkt, s->peer_has_vhdr);
+
+    if (s->msix_used) {
+        if  (!vmxnet3_use_msix_vectors(s, VMXNET3_MAX_INTRS)) {
+            VMW_WRPRN("Failed to re-use MSI-X vectors");
+            msix_uninit(d, &s->msix_bar, &s->msix_bar);
+            s->msix_used = false;
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+const VMStateInfo rxq_descr_info = {
+    .name = "rxq_descr",
+    .get = vmxnet3_get_rxq_descr,
+    .put = vmxnet3_put_rxq_descr
+};
+
+static int vmxnet3_get_int_state(QEMUFile *f, void *pv, size_t size)
+{
+    Vmxnet3IntState *r = pv;
+
+    r->is_masked = qemu_get_byte(f);
+    r->is_pending = qemu_get_byte(f);
+    r->is_asserted = qemu_get_byte(f);
+
+    return 0;
+}
+
+static void vmxnet3_put_int_state(QEMUFile *f, void *pv, size_t size)
+{
+    Vmxnet3IntState *r = pv;
+
+    qemu_put_byte(f, r->is_masked);
+    qemu_put_byte(f, r->is_pending);
+    qemu_put_byte(f, r->is_asserted);
+}
+
+const VMStateInfo int_state_info = {
+    .name = "int_state",
+    .get = vmxnet3_get_int_state,
+    .put = vmxnet3_put_int_state
+};
+
+static const VMStateDescription vmstate_vmxnet3 = {
+    .name = "vmxnet3",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .pre_save = vmxnet3_pre_save,
+    .post_load = vmxnet3_post_load,
+    .fields      = (VMStateField[]) {
+            VMSTATE_PCI_DEVICE(parent_obj, VMXNET3State),
+            VMSTATE_BOOL(rx_packets_compound, VMXNET3State),
+            VMSTATE_BOOL(rx_vlan_stripping, VMXNET3State),
+            VMSTATE_BOOL(lro_supported, VMXNET3State),
+            VMSTATE_UINT32(rx_mode, VMXNET3State),
+            VMSTATE_UINT32(mcast_list_len, VMXNET3State),
+            VMSTATE_UINT32(mcast_list_buff_size, VMXNET3State),
+            VMSTATE_UINT32_ARRAY(vlan_table, VMXNET3State, VMXNET3_VFT_SIZE),
+            VMSTATE_UINT32(mtu, VMXNET3State),
+            VMSTATE_UINT16(max_rx_frags, VMXNET3State),
+            VMSTATE_UINT32(max_tx_frags, VMXNET3State),
+            VMSTATE_UINT8(event_int_idx, VMXNET3State),
+            VMSTATE_BOOL(auto_int_masking, VMXNET3State),
+            VMSTATE_UINT8(txq_num, VMXNET3State),
+            VMSTATE_UINT8(rxq_num, VMXNET3State),
+            VMSTATE_UINT32(device_active, VMXNET3State),
+            VMSTATE_UINT32(last_command, VMXNET3State),
+            VMSTATE_UINT32(link_status_and_speed, VMXNET3State),
+            VMSTATE_UINT32(temp_mac, VMXNET3State),
+            VMSTATE_UINT64(drv_shmem, VMXNET3State),
+            VMSTATE_UINT64(temp_shared_guest_driver_memory, VMXNET3State),
+
+            VMSTATE_ARRAY(txq_descr, VMXNET3State,
+                VMXNET3_DEVICE_MAX_TX_QUEUES, 0, txq_descr_info,
+                Vmxnet3TxqDescr),
+            VMSTATE_ARRAY(rxq_descr, VMXNET3State,
+                VMXNET3_DEVICE_MAX_RX_QUEUES, 0, rxq_descr_info,
+                Vmxnet3RxqDescr),
+            VMSTATE_ARRAY(interrupt_states, VMXNET3State, VMXNET3_MAX_INTRS,
+                0, int_state_info, Vmxnet3IntState),
+
+            VMSTATE_END_OF_LIST()
+    },
+    .subsections = (VMStateSubsection[]) {
+        {
+            .vmsd = &vmxstate_vmxnet3_mcast_list,
+            .needed = vmxnet3_mc_list_needed
+        },
+        {
+            /* empty element. */
+        }
+    }
+};
+
+static void
+vmxnet3_write_config(PCIDevice *pci_dev, uint32_t addr, uint32_t val, int len)
+{
+    pci_default_write_config(pci_dev, addr, val, len);
+    msix_write_config(pci_dev, addr, val, len);
+    msi_write_config(pci_dev, addr, val, len);
+}
+
+static Property vmxnet3_properties[] = {
+    DEFINE_NIC_PROPERTIES(VMXNET3State, conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void vmxnet3_class_init(ObjectClass *class, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(class);
+    PCIDeviceClass *c = PCI_DEVICE_CLASS(class);
+
+    c->init = vmxnet3_pci_init;
+    c->exit = vmxnet3_pci_uninit;
+    c->vendor_id = PCI_VENDOR_ID_VMWARE;
+    c->device_id = PCI_DEVICE_ID_VMWARE_VMXNET3;
+    c->revision = PCI_DEVICE_ID_VMWARE_VMXNET3_REVISION;
+    c->class_id = PCI_CLASS_NETWORK_ETHERNET;
+    c->subsystem_vendor_id = PCI_VENDOR_ID_VMWARE;
+    c->subsystem_id = PCI_DEVICE_ID_VMWARE_VMXNET3;
+    c->config_write = vmxnet3_write_config,
+    dc->desc = "VMWare Paravirtualized Ethernet v3";
+    dc->reset = vmxnet3_qdev_reset;
+    dc->vmsd = &vmstate_vmxnet3;
+    dc->props = vmxnet3_properties;
+}
+
+static const TypeInfo vmxnet3_info = {
+    .name          = TYPE_VMXNET3,
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(VMXNET3State),
+    .class_init    = vmxnet3_class_init,
+};
+
+static void vmxnet3_register_types(void)
+{
+    VMW_CBPRN("vmxnet3_register_types called...");
+    type_register_static(&vmxnet3_info);
+}
+
+type_init(vmxnet3_register_types)
diff --git a/hw/vmxnet3.h b/hw/vmxnet3.h
new file mode 100644
index 0000000..7db0c8f
--- /dev/null
+++ b/hw/vmxnet3.h
@@ -0,0 +1,760 @@
+/*
+ * QEMU VMWARE VMXNET3 paravirtual NIC interface definitions
+ *
+ * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
+ *
+ * Developed by Daynix Computing LTD (http://www.daynix.com)
+ *
+ * Authors:
+ * Dmitry Fleytman <dmitry at daynix.com>
+ * Tamir Shomer <tamirs at daynix.com>
+ * Yan Vugenfirer <yan at daynix.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef _QEMU_VMXNET3_H
+#define _QEMU_VMXNET3_H
+
+#define VMXNET3_DEVICE_MAX_TX_QUEUES 8
+#define VMXNET3_DEVICE_MAX_RX_QUEUES 8   /* Keep this value as a power of 2 */
+
+/*
+ * VMWARE headers we got from Linux kernel do not fully comply QEMU coding
+ * standards in sense of types and defines used.
+ * Since we didn't want to change VMWARE code, following set of typedefs
+ * and defines needed to compile these headers with QEMU introduced.
+ */
+#define u64     uint64_t
+#define u32     uint32_t
+#define u16     uint16_t
+#define u8      uint8_t
+#define __le16  uint16_t
+#define __le32  uint32_t
+#define __le64  uint64_t
+#define __packed QEMU_PACKED
+
+#if defined(HOST_WORDS_BIGENDIAN)
+#define const_cpu_to_le64(x) bswap_64(x)
+#define __BIG_ENDIAN_BITFIELD
+#else
+#define const_cpu_to_le64(x) (x)
+#endif
+
+/*
+ * Following is an interface definition for
+ * VMXNET3 device as provided by VMWARE
+ * See original copyright from Linux kernel v3.2.8
+ * header file drivers/net/vmxnet3/vmxnet3_defs.h below.
+ */
+
+/*
+ * Linux driver for VMware's vmxnet3 ethernet NIC.
+ *
+ * Copyright (C) 2008-2009, VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License and no 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, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Maintained by: Shreyas Bhatewara <pv-drivers at vmware.com>
+ *
+ */
+
+struct UPT1_TxStats {
+    u64            TSOPktsTxOK;  /* TSO pkts post-segmentation */
+    u64            TSOBytesTxOK;
+    u64            ucastPktsTxOK;
+    u64            ucastBytesTxOK;
+    u64            mcastPktsTxOK;
+    u64            mcastBytesTxOK;
+    u64            bcastPktsTxOK;
+    u64            bcastBytesTxOK;
+    u64            pktsTxError;
+    u64            pktsTxDiscard;
+};
+
+struct UPT1_RxStats {
+    u64            LROPktsRxOK;    /* LRO pkts */
+    u64            LROBytesRxOK;   /* bytes from LRO pkts */
+    /* the following counters are for pkts from the wire, i.e., pre-LRO */
+    u64            ucastPktsRxOK;
+    u64            ucastBytesRxOK;
+    u64            mcastPktsRxOK;
+    u64            mcastBytesRxOK;
+    u64            bcastPktsRxOK;
+    u64            bcastBytesRxOK;
+    u64            pktsRxOutOfBuf;
+    u64            pktsRxError;
+};
+
+/* interrupt moderation level */
+enum {
+    UPT1_IML_NONE        = 0, /* no interrupt moderation */
+    UPT1_IML_HIGHEST    = 7, /* least intr generated */
+    UPT1_IML_ADAPTIVE    = 8, /* adpative intr moderation */
+};
+/* values for UPT1_RSSConf.hashFunc */
+enum {
+    UPT1_RSS_HASH_TYPE_NONE      = 0x0,
+    UPT1_RSS_HASH_TYPE_IPV4      = 0x01,
+    UPT1_RSS_HASH_TYPE_TCP_IPV4  = 0x02,
+    UPT1_RSS_HASH_TYPE_IPV6      = 0x04,
+    UPT1_RSS_HASH_TYPE_TCP_IPV6  = 0x08,
+};
+
+enum {
+    UPT1_RSS_HASH_FUNC_NONE      = 0x0,
+    UPT1_RSS_HASH_FUNC_TOEPLITZ  = 0x01,
+};
+
+#define UPT1_RSS_MAX_KEY_SIZE        40
+#define UPT1_RSS_MAX_IND_TABLE_SIZE  128
+
+struct UPT1_RSSConf {
+    u16            hashType;
+    u16            hashFunc;
+    u16            hashKeySize;
+    u16            indTableSize;
+    u8            hashKey[UPT1_RSS_MAX_KEY_SIZE];
+    u8            indTable[UPT1_RSS_MAX_IND_TABLE_SIZE];
+};
+
+/* features */
+enum {
+    UPT1_F_RXCSUM        = const_cpu_to_le64(0x0001), /* rx csum verification */
+    UPT1_F_RSS        = const_cpu_to_le64(0x0002),
+    UPT1_F_RXVLAN        = const_cpu_to_le64(0x0004), /* VLAN tag stripping */
+    UPT1_F_LRO        = const_cpu_to_le64(0x0008),
+};
+
+/* all registers are 32 bit wide */
+/* BAR 1 */
+enum {
+    VMXNET3_REG_VRRS    = 0x0,    /* Vmxnet3 Revision Report Selection */
+    VMXNET3_REG_UVRS    = 0x8,    /* UPT Version Report Selection */
+    VMXNET3_REG_DSAL    = 0x10,    /* Driver Shared Address Low */
+    VMXNET3_REG_DSAH    = 0x18,    /* Driver Shared Address High */
+    VMXNET3_REG_CMD        = 0x20,    /* Command */
+    VMXNET3_REG_MACL    = 0x28,    /* MAC Address Low */
+    VMXNET3_REG_MACH    = 0x30,    /* MAC Address High */
+    VMXNET3_REG_ICR        = 0x38,    /* Interrupt Cause Register */
+    VMXNET3_REG_ECR        = 0x40    /* Event Cause Register */
+};
+
+/* BAR 0 */
+enum {
+    VMXNET3_REG_IMR        = 0x0,     /* Interrupt Mask Register */
+    VMXNET3_REG_TXPROD    = 0x600, /* Tx Producer Index */
+    VMXNET3_REG_RXPROD    = 0x800, /* Rx Producer Index for ring 1 */
+    VMXNET3_REG_RXPROD2    = 0xA00     /* Rx Producer Index for ring 2 */
+};
+
+#define VMXNET3_PT_REG_SIZE     4096    /* BAR 0 */
+#define VMXNET3_VD_REG_SIZE     4096    /* BAR 1 */
+
+#define VMXNET3_REG_ALIGN       8    /* All registers are 8-byte aligned. */
+#define VMXNET3_REG_ALIGN_MASK  0x7
+
+/* I/O Mapped access to registers */
+#define VMXNET3_IO_TYPE_PT              0
+#define VMXNET3_IO_TYPE_VD              1
+#define VMXNET3_IO_ADDR(type, reg)      (((type) << 24) | ((reg) & 0xFFFFFF))
+#define VMXNET3_IO_TYPE(addr)           ((addr) >> 24)
+#define VMXNET3_IO_REG(addr)            ((addr) & 0xFFFFFF)
+
+enum {
+    VMXNET3_CMD_FIRST_SET = 0xCAFE0000,
+    VMXNET3_CMD_ACTIVATE_DEV = VMXNET3_CMD_FIRST_SET, /* 0xCAFE0000 */
+    VMXNET3_CMD_QUIESCE_DEV,                          /* 0xCAFE0001 */
+    VMXNET3_CMD_RESET_DEV,                            /* 0xCAFE0002 */
+    VMXNET3_CMD_UPDATE_RX_MODE,                       /* 0xCAFE0003 */
+    VMXNET3_CMD_UPDATE_MAC_FILTERS,                   /* 0xCAFE0004 */
+    VMXNET3_CMD_UPDATE_VLAN_FILTERS,                  /* 0xCAFE0005 */
+    VMXNET3_CMD_UPDATE_RSSIDT,                        /* 0xCAFE0006 */
+    VMXNET3_CMD_UPDATE_IML,                           /* 0xCAFE0007 */
+    VMXNET3_CMD_UPDATE_PMCFG,                         /* 0xCAFE0008 */
+    VMXNET3_CMD_UPDATE_FEATURE,                       /* 0xCAFE0009 */
+    VMXNET3_CMD_LOAD_PLUGIN,                          /* 0xCAFE000A */
+
+    VMXNET3_CMD_FIRST_GET = 0xF00D0000,
+    VMXNET3_CMD_GET_QUEUE_STATUS = VMXNET3_CMD_FIRST_GET, /* 0xF00D0000 */
+    VMXNET3_CMD_GET_STATS,                                /* 0xF00D0001 */
+    VMXNET3_CMD_GET_LINK,                                 /* 0xF00D0002 */
+    VMXNET3_CMD_GET_PERM_MAC_LO,                          /* 0xF00D0003 */
+    VMXNET3_CMD_GET_PERM_MAC_HI,                          /* 0xF00D0004 */
+    VMXNET3_CMD_GET_DID_LO,                               /* 0xF00D0005 */
+    VMXNET3_CMD_GET_DID_HI,                               /* 0xF00D0006 */
+    VMXNET3_CMD_GET_DEV_EXTRA_INFO,                       /* 0xF00D0007 */
+    VMXNET3_CMD_GET_CONF_INTR                             /* 0xF00D0008 */
+};
+
+/*
+ *    Little Endian layout of bitfields -
+ *    Byte 0 :    7.....len.....0
+ *    Byte 1 :    rsvd gen 13.len.8
+ *    Byte 2 :     5.msscof.0 ext1  dtype
+ *    Byte 3 :     13...msscof...6
+ *
+ *    Big Endian layout of bitfields -
+ *    Byte 0:        13...msscof...6
+ *    Byte 1 :     5.msscof.0 ext1  dtype
+ *    Byte 2 :    rsvd gen 13.len.8
+ *    Byte 3 :    7.....len.....0
+ *
+ *    Thus, le32_to_cpu on the dword will allow the big endian driver to read
+ *    the bit fields correctly. And cpu_to_le32 will convert bitfields
+ *    bit fields written by big endian driver to format required by device.
+ */
+
+struct Vmxnet3_TxDesc {
+    __le64 addr;
+
+#ifdef __BIG_ENDIAN_BITFIELD
+    u32 msscof:14;  /* MSS, checksum offset, flags */
+    u32 ext1:1;
+    u32 dtype:1;    /* descriptor type */
+    u32 rsvd:1;
+    u32 gen:1;      /* generation bit */
+    u32 len:14;
+#else
+    u32 len:14;
+    u32 gen:1;      /* generation bit */
+    u32 rsvd:1;
+    u32 dtype:1;    /* descriptor type */
+    u32 ext1:1;
+    u32 msscof:14;  /* MSS, checksum offset, flags */
+#endif  /* __BIG_ENDIAN_BITFIELD */
+
+#ifdef __BIG_ENDIAN_BITFIELD
+    u32 tci:16;     /* Tag to Insert */
+    u32 ti:1;       /* VLAN Tag Insertion */
+    u32 ext2:1;
+    u32 cq:1;       /* completion request */
+    u32 eop:1;      /* End Of Packet */
+    u32 om:2;       /* offload mode */
+    u32 hlen:10;    /* header len */
+#else
+    u32 hlen:10;    /* header len */
+    u32 om:2;       /* offload mode */
+    u32 eop:1;      /* End Of Packet */
+    u32 cq:1;       /* completion request */
+    u32 ext2:1;
+    u32 ti:1;       /* VLAN Tag Insertion */
+    u32 tci:16;     /* Tag to Insert */
+#endif  /* __BIG_ENDIAN_BITFIELD */
+};
+
+/* TxDesc.OM values */
+#define VMXNET3_OM_NONE        0
+#define VMXNET3_OM_CSUM        2
+#define VMXNET3_OM_TSO        3
+
+/* fields in TxDesc we access w/o using bit fields */
+#define VMXNET3_TXD_EOP_SHIFT    12
+#define VMXNET3_TXD_CQ_SHIFT    13
+#define VMXNET3_TXD_GEN_SHIFT    14
+#define VMXNET3_TXD_EOP_DWORD_SHIFT 3
+#define VMXNET3_TXD_GEN_DWORD_SHIFT 2
+
+#define VMXNET3_TXD_CQ        (1 << VMXNET3_TXD_CQ_SHIFT)
+#define VMXNET3_TXD_EOP        (1 << VMXNET3_TXD_EOP_SHIFT)
+#define VMXNET3_TXD_GEN        (1 << VMXNET3_TXD_GEN_SHIFT)
+
+#define VMXNET3_HDR_COPY_SIZE   128
+
+
+struct Vmxnet3_TxDataDesc {
+    u8        data[VMXNET3_HDR_COPY_SIZE];
+};
+
+#define VMXNET3_TCD_GEN_SHIFT    31
+#define VMXNET3_TCD_GEN_SIZE    1
+#define VMXNET3_TCD_TXIDX_SHIFT    0
+#define VMXNET3_TCD_TXIDX_SIZE    12
+#define VMXNET3_TCD_GEN_DWORD_SHIFT    3
+
+struct Vmxnet3_TxCompDesc {
+    u32        txdIdx:12;    /* Index of the EOP TxDesc */
+    u32        ext1:20;
+
+    __le32        ext2;
+    __le32        ext3;
+
+    u32        rsvd:24;
+    u32        type:7;       /* completion type */
+    u32        gen:1;        /* generation bit */
+};
+
+struct Vmxnet3_RxDesc {
+    __le64        addr;
+
+#ifdef __BIG_ENDIAN_BITFIELD
+    u32        gen:1;        /* Generation bit */
+    u32        rsvd:15;
+    u32        dtype:1;      /* Descriptor type */
+    u32        btype:1;      /* Buffer Type */
+    u32        len:14;
+#else
+    u32        len:14;
+    u32        btype:1;      /* Buffer Type */
+    u32        dtype:1;      /* Descriptor type */
+    u32        rsvd:15;
+    u32        gen:1;        /* Generation bit */
+#endif
+    u32        ext1;
+};
+
+/* values of RXD.BTYPE */
+#define VMXNET3_RXD_BTYPE_HEAD   0    /* head only */
+#define VMXNET3_RXD_BTYPE_BODY   1    /* body only */
+
+/* fields in RxDesc we access w/o using bit fields */
+#define VMXNET3_RXD_BTYPE_SHIFT  14
+#define VMXNET3_RXD_GEN_SHIFT    31
+
+struct Vmxnet3_RxCompDesc {
+#ifdef __BIG_ENDIAN_BITFIELD
+    u32        ext2:1;
+    u32        cnc:1;        /* Checksum Not Calculated */
+    u32        rssType:4;    /* RSS hash type used */
+    u32        rqID:10;      /* rx queue/ring ID */
+    u32        sop:1;        /* Start of Packet */
+    u32        eop:1;        /* End of Packet */
+    u32        ext1:2;
+    u32        rxdIdx:12;    /* Index of the RxDesc */
+#else
+    u32        rxdIdx:12;    /* Index of the RxDesc */
+    u32        ext1:2;
+    u32        eop:1;        /* End of Packet */
+    u32        sop:1;        /* Start of Packet */
+    u32        rqID:10;      /* rx queue/ring ID */
+    u32        rssType:4;    /* RSS hash type used */
+    u32        cnc:1;        /* Checksum Not Calculated */
+    u32        ext2:1;
+#endif  /* __BIG_ENDIAN_BITFIELD */
+
+    __le32        rssHash;      /* RSS hash value */
+
+#ifdef __BIG_ENDIAN_BITFIELD
+    u32        tci:16;       /* Tag stripped */
+    u32        ts:1;         /* Tag is stripped */
+    u32        err:1;        /* Error */
+    u32        len:14;       /* data length */
+#else
+    u32        len:14;       /* data length */
+    u32        err:1;        /* Error */
+    u32        ts:1;         /* Tag is stripped */
+    u32        tci:16;       /* Tag stripped */
+#endif  /* __BIG_ENDIAN_BITFIELD */
+
+
+#ifdef __BIG_ENDIAN_BITFIELD
+    u32        gen:1;        /* generation bit */
+    u32        type:7;       /* completion type */
+    u32        fcs:1;        /* Frame CRC correct */
+    u32        frg:1;        /* IP Fragment */
+    u32        v4:1;         /* IPv4 */
+    u32        v6:1;         /* IPv6 */
+    u32        ipc:1;        /* IP Checksum Correct */
+    u32        tcp:1;        /* TCP packet */
+    u32        udp:1;        /* UDP packet */
+    u32        tuc:1;        /* TCP/UDP Checksum Correct */
+    u32        csum:16;
+#else
+    u32        csum:16;
+    u32        tuc:1;        /* TCP/UDP Checksum Correct */
+    u32        udp:1;        /* UDP packet */
+    u32        tcp:1;        /* TCP packet */
+    u32        ipc:1;        /* IP Checksum Correct */
+    u32        v6:1;         /* IPv6 */
+    u32        v4:1;         /* IPv4 */
+    u32        frg:1;        /* IP Fragment */
+    u32        fcs:1;        /* Frame CRC correct */
+    u32        type:7;       /* completion type */
+    u32        gen:1;        /* generation bit */
+#endif  /* __BIG_ENDIAN_BITFIELD */
+};
+
+/* fields in RxCompDesc we access via Vmxnet3_GenericDesc.dword[3] */
+#define VMXNET3_RCD_TUC_SHIFT    16
+#define VMXNET3_RCD_IPC_SHIFT    19
+
+/* fields in RxCompDesc we access via Vmxnet3_GenericDesc.qword[1] */
+#define VMXNET3_RCD_TYPE_SHIFT    56
+#define VMXNET3_RCD_GEN_SHIFT    63
+
+/* csum OK for TCP/UDP pkts over IP */
+#define VMXNET3_RCD_CSUM_OK (1 << VMXNET3_RCD_TUC_SHIFT | \
+                     1 << VMXNET3_RCD_IPC_SHIFT)
+#define VMXNET3_TXD_GEN_SIZE 1
+#define VMXNET3_TXD_EOP_SIZE 1
+
+/* value of RxCompDesc.rssType */
+enum {
+    VMXNET3_RCD_RSS_TYPE_NONE     = 0,
+    VMXNET3_RCD_RSS_TYPE_IPV4     = 1,
+    VMXNET3_RCD_RSS_TYPE_TCPIPV4  = 2,
+    VMXNET3_RCD_RSS_TYPE_IPV6     = 3,
+    VMXNET3_RCD_RSS_TYPE_TCPIPV6  = 4,
+};
+
+
+/* a union for accessing all cmd/completion descriptors */
+union Vmxnet3_GenericDesc {
+    __le64                qword[2];
+    __le32                dword[4];
+    __le16                word[8];
+    struct Vmxnet3_TxDesc        txd;
+    struct Vmxnet3_RxDesc        rxd;
+    struct Vmxnet3_TxCompDesc    tcd;
+    struct Vmxnet3_RxCompDesc    rcd;
+};
+
+#define VMXNET3_INIT_GEN       1
+
+/* Max size of a single tx buffer */
+#define VMXNET3_MAX_TX_BUF_SIZE  (1 << 14)
+
+/* # of tx desc needed for a tx buffer size */
+#define VMXNET3_TXD_NEEDED(size) (((size) + VMXNET3_MAX_TX_BUF_SIZE - 1) / \
+                    VMXNET3_MAX_TX_BUF_SIZE)
+
+/* max # of tx descs for a non-tso pkt */
+#define VMXNET3_MAX_TXD_PER_PKT 16
+
+/* Max size of a single rx buffer */
+#define VMXNET3_MAX_RX_BUF_SIZE  ((1 << 14) - 1)
+/* Minimum size of a type 0 buffer */
+#define VMXNET3_MIN_T0_BUF_SIZE  128
+#define VMXNET3_MAX_CSUM_OFFSET  1024
+
+/* Ring base address alignment */
+#define VMXNET3_RING_BA_ALIGN   512
+#define VMXNET3_RING_BA_MASK    (VMXNET3_RING_BA_ALIGN - 1)
+
+/* Ring size must be a multiple of 32 */
+#define VMXNET3_RING_SIZE_ALIGN 32
+#define VMXNET3_RING_SIZE_MASK  (VMXNET3_RING_SIZE_ALIGN - 1)
+
+/* Max ring size */
+#define VMXNET3_TX_RING_MAX_SIZE   4096
+#define VMXNET3_TC_RING_MAX_SIZE   4096
+#define VMXNET3_RX_RING_MAX_SIZE   4096
+#define VMXNET3_RC_RING_MAX_SIZE   8192
+
+/* a list of reasons for queue stop */
+
+enum {
+ VMXNET3_ERR_NOEOP        = 0x80000000, /* cannot find the EOP desc of a pkt */
+ VMXNET3_ERR_TXD_REUSE    = 0x80000001, /* reuse TxDesc before tx completion */
+ VMXNET3_ERR_BIG_PKT      = 0x80000002, /* too many TxDesc for a pkt */
+ VMXNET3_ERR_DESC_NOT_SPT = 0x80000003, /* descriptor type not supported */
+ VMXNET3_ERR_SMALL_BUF    = 0x80000004, /* type 0 buffer too small */
+ VMXNET3_ERR_STRESS       = 0x80000005, /* stress option firing in vmkernel */
+ VMXNET3_ERR_SWITCH       = 0x80000006, /* mode switch failure */
+ VMXNET3_ERR_TXD_INVALID  = 0x80000007, /* invalid TxDesc */
+};
+
+/* completion descriptor types */
+#define VMXNET3_CDTYPE_TXCOMP      0    /* Tx Completion Descriptor */
+#define VMXNET3_CDTYPE_RXCOMP      3    /* Rx Completion Descriptor */
+
+enum {
+    VMXNET3_GOS_BITS_UNK    = 0,   /* unknown */
+    VMXNET3_GOS_BITS_32     = 1,
+    VMXNET3_GOS_BITS_64     = 2,
+};
+
+#define VMXNET3_GOS_TYPE_UNK        0 /* unknown */
+#define VMXNET3_GOS_TYPE_LINUX      1
+#define VMXNET3_GOS_TYPE_WIN        2
+#define VMXNET3_GOS_TYPE_SOLARIS    3
+#define VMXNET3_GOS_TYPE_FREEBSD    4
+#define VMXNET3_GOS_TYPE_PXE        5
+
+struct Vmxnet3_GOSInfo {
+#ifdef __BIG_ENDIAN_BITFIELD
+    u32        gosMisc:10;    /* other info about gos */
+    u32        gosVer:16;     /* gos version */
+    u32        gosType:4;     /* which guest */
+    u32        gosBits:2;    /* 32-bit or 64-bit? */
+#else
+    u32        gosBits:2;     /* 32-bit or 64-bit? */
+    u32        gosType:4;     /* which guest */
+    u32        gosVer:16;     /* gos version */
+    u32        gosMisc:10;    /* other info about gos */
+#endif  /* __BIG_ENDIAN_BITFIELD */
+};
+
+struct Vmxnet3_DriverInfo {
+    __le32                version;
+    struct Vmxnet3_GOSInfo        gos;
+    __le32                vmxnet3RevSpt;
+    __le32                uptVerSpt;
+};
+
+
+#define VMXNET3_REV1_MAGIC  0xbabefee1
+
+/*
+ * QueueDescPA must be 128 bytes aligned. It points to an array of
+ * Vmxnet3_TxQueueDesc followed by an array of Vmxnet3_RxQueueDesc.
+ * The number of Vmxnet3_TxQueueDesc/Vmxnet3_RxQueueDesc are specified by
+ * Vmxnet3_MiscConf.numTxQueues/numRxQueues, respectively.
+ */
+#define VMXNET3_QUEUE_DESC_ALIGN  128
+
+
+struct Vmxnet3_MiscConf {
+    struct Vmxnet3_DriverInfo driverInfo;
+    __le64        uptFeatures;
+    __le64        ddPA;         /* driver data PA */
+    __le64        queueDescPA;  /* queue descriptor table PA */
+    __le32        ddLen;        /* driver data len */
+    __le32        queueDescLen; /* queue desc. table len in bytes */
+    __le32        mtu;
+    __le16        maxNumRxSG;
+    u8        numTxQueues;
+    u8        numRxQueues;
+    __le32        reserved[4];
+};
+
+
+struct Vmxnet3_TxQueueConf {
+    __le64        txRingBasePA;
+    __le64        dataRingBasePA;
+    __le64        compRingBasePA;
+    __le64        ddPA;         /* driver data */
+    __le64        reserved;
+    __le32        txRingSize;   /* # of tx desc */
+    __le32        dataRingSize; /* # of data desc */
+    __le32        compRingSize; /* # of comp desc */
+    __le32        ddLen;        /* size of driver data */
+    u8        intrIdx;
+    u8        _pad[7];
+};
+
+
+struct Vmxnet3_RxQueueConf {
+    __le64        rxRingBasePA[2];
+    __le64        compRingBasePA;
+    __le64        ddPA;            /* driver data */
+    __le64        reserved;
+    __le32        rxRingSize[2];   /* # of rx desc */
+    __le32        compRingSize;    /* # of rx comp desc */
+    __le32        ddLen;           /* size of driver data */
+    u8        intrIdx;
+    u8        _pad[7];
+};
+
+
+enum vmxnet3_intr_mask_mode {
+    VMXNET3_IMM_AUTO   = 0,
+    VMXNET3_IMM_ACTIVE = 1,
+    VMXNET3_IMM_LAZY   = 2
+};
+
+enum vmxnet3_intr_type {
+    VMXNET3_IT_AUTO = 0,
+    VMXNET3_IT_INTX = 1,
+    VMXNET3_IT_MSI  = 2,
+    VMXNET3_IT_MSIX = 3
+};
+
+#define VMXNET3_MAX_TX_QUEUES  8
+#define VMXNET3_MAX_RX_QUEUES  16
+/* addition 1 for events */
+#define VMXNET3_MAX_INTRS      25
+
+/* value of intrCtrl */
+#define VMXNET3_IC_DISABLE_ALL  0x1   /* bit 0 */
+
+
+struct Vmxnet3_IntrConf {
+    bool        autoMask;
+    u8        numIntrs;      /* # of interrupts */
+    u8        eventIntrIdx;
+    u8        modLevels[VMXNET3_MAX_INTRS];    /* moderation level for
+                             * each intr */
+    __le32        intrCtrl;
+    __le32        reserved[2];
+};
+
+/* one bit per VLAN ID, the size is in the units of u32 */
+#define VMXNET3_VFT_SIZE  (4096/(sizeof(uint32_t)*8))
+
+
+struct Vmxnet3_QueueStatus {
+    bool        stopped;
+    u8        _pad[3];
+    __le32        error;
+};
+
+
+struct Vmxnet3_TxQueueCtrl {
+    __le32        txNumDeferred;
+    __le32        txThreshold;
+    __le64        reserved;
+};
+
+
+struct Vmxnet3_RxQueueCtrl {
+    bool        updateRxProd;
+    u8        _pad[7];
+    __le64        reserved;
+};
+
+enum {
+    VMXNET3_RXM_UCAST     = 0x01,  /* unicast only */
+    VMXNET3_RXM_MCAST     = 0x02,  /* multicast passing the filters */
+    VMXNET3_RXM_BCAST     = 0x04,  /* broadcast only */
+    VMXNET3_RXM_ALL_MULTI = 0x08,  /* all multicast */
+    VMXNET3_RXM_PROMISC   = 0x10  /* promiscuous */
+};
+
+struct Vmxnet3_RxFilterConf {
+    __le32        rxMode;       /* VMXNET3_RXM_xxx */
+    __le16        mfTableLen;   /* size of the multicast filter table */
+    __le16        _pad1;
+    __le64        mfTablePA;    /* PA of the multicast filters table */
+    __le32        vfTable[VMXNET3_VFT_SIZE]; /* vlan filter */
+};
+
+
+#define VMXNET3_PM_MAX_FILTERS        6
+#define VMXNET3_PM_MAX_PATTERN_SIZE   128
+#define VMXNET3_PM_MAX_MASK_SIZE      (VMXNET3_PM_MAX_PATTERN_SIZE / 8)
+
+#define VMXNET3_PM_WAKEUP_MAGIC  cpu_to_le16(0x01)  /* wake up on magic pkts */
+#define VMXNET3_PM_WAKEUP_FILTER cpu_to_le16(0x02)  /* wake up on pkts matching
+                                                     * filters */
+
+
+struct Vmxnet3_PM_PktFilter {
+    u8        maskSize;
+    u8        patternSize;
+    u8        mask[VMXNET3_PM_MAX_MASK_SIZE];
+    u8        pattern[VMXNET3_PM_MAX_PATTERN_SIZE];
+    u8        pad[6];
+};
+
+
+struct Vmxnet3_PMConf {
+    __le16        wakeUpEvents;  /* VMXNET3_PM_WAKEUP_xxx */
+    u8        numFilters;
+    u8        pad[5];
+    struct Vmxnet3_PM_PktFilter filters[VMXNET3_PM_MAX_FILTERS];
+};
+
+
+struct Vmxnet3_VariableLenConfDesc {
+    __le32        confVer;
+    __le32        confLen;
+    __le64        confPA;
+};
+
+
+struct Vmxnet3_TxQueueDesc {
+    struct Vmxnet3_TxQueueCtrl        ctrl;
+    struct Vmxnet3_TxQueueConf        conf;
+
+    /* Driver read after a GET command */
+    struct Vmxnet3_QueueStatus        status;
+    struct UPT1_TxStats            stats;
+    u8                    _pad[88]; /* 128 aligned */
+};
+
+
+struct Vmxnet3_RxQueueDesc {
+    struct Vmxnet3_RxQueueCtrl        ctrl;
+    struct Vmxnet3_RxQueueConf        conf;
+    /* Driver read after a GET commad */
+    struct Vmxnet3_QueueStatus        status;
+    struct UPT1_RxStats            stats;
+    u8                      __pad[88]; /* 128 aligned */
+};
+
+
+struct Vmxnet3_DSDevRead {
+    /* read-only region for device, read by dev in response to a SET cmd */
+    struct Vmxnet3_MiscConf            misc;
+    struct Vmxnet3_IntrConf            intrConf;
+    struct Vmxnet3_RxFilterConf        rxFilterConf;
+    struct Vmxnet3_VariableLenConfDesc    rssConfDesc;
+    struct Vmxnet3_VariableLenConfDesc    pmConfDesc;
+    struct Vmxnet3_VariableLenConfDesc    pluginConfDesc;
+};
+
+/* All structures in DriverShared are padded to multiples of 8 bytes */
+struct Vmxnet3_DriverShared {
+    __le32              magic;
+    /* make devRead start at 64bit boundaries */
+    __le32              pad;
+    struct Vmxnet3_DSDevRead    devRead;
+    __le32              ecr;
+    __le32              reserved[5];
+};
+
+
+#define VMXNET3_ECR_RQERR       (1 << 0)
+#define VMXNET3_ECR_TQERR       (1 << 1)
+#define VMXNET3_ECR_LINK        (1 << 2)
+#define VMXNET3_ECR_DIC         (1 << 3)
+#define VMXNET3_ECR_DEBUG       (1 << 4)
+
+/* flip the gen bit of a ring */
+#define VMXNET3_FLIP_RING_GEN(gen) ((gen) = (gen) ^ 0x1)
+
+/* only use this if moving the idx won't affect the gen bit */
+#define VMXNET3_INC_RING_IDX_ONLY(idx, ring_size) \
+    do {\
+        (idx)++;\
+        if (unlikely((idx) == (ring_size))) {\
+            (idx) = 0;\
+        } \
+    } while (0)
+
+#define VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid) \
+    (vfTable[vid >> 5] |= (1 << (vid & 31)))
+#define VMXNET3_CLEAR_VFTABLE_ENTRY(vfTable, vid) \
+    (vfTable[vid >> 5] &= ~(1 << (vid & 31)))
+
+#define VMXNET3_VFTABLE_ENTRY_IS_SET(vfTable, vid) \
+    ((vfTable[vid >> 5] & (1 << (vid & 31))) != 0)
+
+#define VMXNET3_MAX_MTU     9000
+#define VMXNET3_MIN_MTU     60
+
+#define VMXNET3_LINK_UP         (10000 << 16 | 1)    /* 10 Gbps, up */
+#define VMXNET3_LINK_DOWN       0
+
+#undef u64
+#undef u32
+#undef u16
+#undef u8
+#undef __le16
+#undef __le32
+#undef __le64
+#undef __packed
+#undef const_cpu_to_le64
+#if defined(HOST_WORDS_BIGENDIAN)
+#undef __BIG_ENDIAN_BITFIELD
+#endif
+
+#endif
commit e263cd49c73c595af0917c83dc004234660e0c71
Author: Dmitry Fleytman <dmitry at daynix.com>
Date:   Sat Mar 9 11:21:05 2013 +0200

    Packet abstraction for VMWARE network devices
    
    Signed-off-by: Dmitry Fleytman <dmitry at daynix.com>
    Signed-off-by: Yan Vugenfirer <yan at daynix.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 11812c6..1a988ca 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -119,6 +119,7 @@ common-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o
 common-obj-$(CONFIG_PCNET_COMMON) += pcnet.o
 common-obj-$(CONFIG_E1000_PCI) += e1000.o
 common-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
+common-obj-$(CONFIG_VMXNET3_PCI) += vmxnet_tx_pkt.o vmxnet_rx_pkt.o
 
 common-obj-$(CONFIG_SMC91C111) += smc91c111.o
 common-obj-$(CONFIG_LAN9118) += lan9118.o
diff --git a/hw/vmxnet_rx_pkt.c b/hw/vmxnet_rx_pkt.c
new file mode 100644
index 0000000..a40e346
--- /dev/null
+++ b/hw/vmxnet_rx_pkt.c
@@ -0,0 +1,187 @@
+/*
+ * QEMU VMWARE VMXNET* paravirtual NICs - RX packets abstractions
+ *
+ * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
+ *
+ * Developed by Daynix Computing LTD (http://www.daynix.com)
+ *
+ * Authors:
+ * Dmitry Fleytman <dmitry at daynix.com>
+ * Tamir Shomer <tamirs at daynix.com>
+ * Yan Vugenfirer <yan at daynix.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 "vmxnet_rx_pkt.h"
+#include "net/eth.h"
+#include "qemu-common.h"
+#include "qemu/iov.h"
+#include "net/checksum.h"
+#include "net/tap.h"
+
+/*
+ * RX packet may contain up to 2 fragments - rebuilt eth header
+ * in case of VLAN tag stripping
+ * and payload received from QEMU - in any case
+ */
+#define VMXNET_MAX_RX_PACKET_FRAGMENTS (2)
+
+struct VmxnetRxPkt {
+    struct virtio_net_hdr virt_hdr;
+    uint8_t ehdr_buf[ETH_MAX_L2_HDR_LEN];
+    struct iovec vec[VMXNET_MAX_RX_PACKET_FRAGMENTS];
+    uint16_t vec_len;
+    uint32_t tot_len;
+    uint16_t tci;
+    bool vlan_stripped;
+    bool has_virt_hdr;
+    eth_pkt_types_e packet_type;
+
+    /* Analysis results */
+    bool isip4;
+    bool isip6;
+    bool isudp;
+    bool istcp;
+};
+
+void vmxnet_rx_pkt_init(struct VmxnetRxPkt **pkt, bool has_virt_hdr)
+{
+    struct VmxnetRxPkt *p = g_malloc0(sizeof *p);
+    p->has_virt_hdr = has_virt_hdr;
+    *pkt = p;
+}
+
+void vmxnet_rx_pkt_uninit(struct VmxnetRxPkt *pkt)
+{
+    g_free(pkt);
+}
+
+struct virtio_net_hdr *vmxnet_rx_pkt_get_vhdr(struct VmxnetRxPkt *pkt)
+{
+    assert(pkt);
+    return &pkt->virt_hdr;
+}
+
+void vmxnet_rx_pkt_attach_data(struct VmxnetRxPkt *pkt, const void *data,
+                               size_t len, bool strip_vlan)
+{
+    uint16_t tci = 0;
+    uint16_t ploff;
+    assert(pkt);
+    pkt->vlan_stripped = false;
+
+    if (strip_vlan) {
+        pkt->vlan_stripped = eth_strip_vlan(data, pkt->ehdr_buf, &ploff, &tci);
+    }
+
+    if (pkt->vlan_stripped) {
+        pkt->vec[0].iov_base = pkt->ehdr_buf;
+        pkt->vec[0].iov_len = ploff - sizeof(struct vlan_header);
+        pkt->vec[1].iov_base = (uint8_t *) data + ploff;
+        pkt->vec[1].iov_len = len - ploff;
+        pkt->vec_len = 2;
+        pkt->tot_len = len - ploff + sizeof(struct eth_header);
+    } else {
+        pkt->vec[0].iov_base = (void *)data;
+        pkt->vec[0].iov_len = len;
+        pkt->vec_len = 1;
+        pkt->tot_len = len;
+    }
+
+    pkt->tci = tci;
+
+    eth_get_protocols(data, len, &pkt->isip4, &pkt->isip6,
+        &pkt->isudp, &pkt->istcp);
+}
+
+void vmxnet_rx_pkt_dump(struct VmxnetRxPkt *pkt)
+{
+#ifdef VMXNET_RX_PKT_DEBUG
+    VmxnetRxPkt *pkt = (VmxnetRxPkt *)pkt;
+    assert(pkt);
+
+    printf("RX PKT: tot_len: %d, vlan_stripped: %d, vlan_tag: %d\n",
+              pkt->tot_len, pkt->vlan_stripped, pkt->tci);
+#endif
+}
+
+void vmxnet_rx_pkt_set_packet_type(struct VmxnetRxPkt *pkt,
+    eth_pkt_types_e packet_type)
+{
+    assert(pkt);
+
+    pkt->packet_type = packet_type;
+
+}
+
+eth_pkt_types_e vmxnet_rx_pkt_get_packet_type(struct VmxnetRxPkt *pkt)
+{
+    assert(pkt);
+
+    return pkt->packet_type;
+}
+
+size_t vmxnet_rx_pkt_get_total_len(struct VmxnetRxPkt *pkt)
+{
+    assert(pkt);
+
+    return pkt->tot_len;
+}
+
+void vmxnet_rx_pkt_get_protocols(struct VmxnetRxPkt *pkt,
+                                 bool *isip4, bool *isip6,
+                                 bool *isudp, bool *istcp)
+{
+    assert(pkt);
+
+    *isip4 = pkt->isip4;
+    *isip6 = pkt->isip6;
+    *isudp = pkt->isudp;
+    *istcp = pkt->istcp;
+}
+
+struct iovec *vmxnet_rx_pkt_get_iovec(struct VmxnetRxPkt *pkt)
+{
+    assert(pkt);
+
+    return pkt->vec;
+}
+
+void vmxnet_rx_pkt_set_vhdr(struct VmxnetRxPkt *pkt,
+                            struct virtio_net_hdr *vhdr)
+{
+    assert(pkt);
+
+    memcpy(&pkt->virt_hdr, vhdr, sizeof pkt->virt_hdr);
+}
+
+bool vmxnet_rx_pkt_is_vlan_stripped(struct VmxnetRxPkt *pkt)
+{
+    assert(pkt);
+
+    return pkt->vlan_stripped;
+}
+
+bool vmxnet_rx_pkt_has_virt_hdr(struct VmxnetRxPkt *pkt)
+{
+    assert(pkt);
+
+    return pkt->has_virt_hdr;
+}
+
+uint16_t vmxnet_rx_pkt_get_num_frags(struct VmxnetRxPkt *pkt)
+{
+    assert(pkt);
+
+    return pkt->vec_len;
+}
+
+uint16_t vmxnet_rx_pkt_get_vlan_tag(struct VmxnetRxPkt *pkt)
+{
+    assert(pkt);
+
+    return pkt->tci;
+}
diff --git a/hw/vmxnet_rx_pkt.h b/hw/vmxnet_rx_pkt.h
new file mode 100644
index 0000000..6b2c60e
--- /dev/null
+++ b/hw/vmxnet_rx_pkt.h
@@ -0,0 +1,174 @@
+/*
+ * QEMU VMWARE VMXNET* paravirtual NICs - RX packets abstraction
+ *
+ * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
+ *
+ * Developed by Daynix Computing LTD (http://www.daynix.com)
+ *
+ * Authors:
+ * Dmitry Fleytman <dmitry at daynix.com>
+ * Tamir Shomer <tamirs at daynix.com>
+ * Yan Vugenfirer <yan at daynix.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 VMXNET_RX_PKT_H
+#define VMXNET_RX_PKT_H
+
+#include "stdint.h"
+#include "stdbool.h"
+#include "net/eth.h"
+
+/* defines to enable packet dump functions */
+/*#define VMXNET_RX_PKT_DEBUG*/
+
+struct VmxnetRxPkt;
+
+/**
+ * Clean all rx packet resources
+ *
+ * @pkt:            packet
+ *
+ */
+void vmxnet_rx_pkt_uninit(struct VmxnetRxPkt *pkt);
+
+/**
+ * Init function for rx packet functionality
+ *
+ * @pkt:            packet pointer
+ * @has_virt_hdr:   device uses virtio header
+ *
+ */
+void vmxnet_rx_pkt_init(struct VmxnetRxPkt **pkt, bool has_virt_hdr);
+
+/**
+ * returns total length of data attached to rx context
+ *
+ * @pkt:            packet
+ *
+ * Return:  nothing
+ *
+ */
+size_t vmxnet_rx_pkt_get_total_len(struct VmxnetRxPkt *pkt);
+
+/**
+ * fetches packet analysis results
+ *
+ * @pkt:            packet
+ * @isip4:          whether the packet given is IPv4
+ * @isip6:          whether the packet given is IPv6
+ * @isudp:          whether the packet given is UDP
+ * @istcp:          whether the packet given is TCP
+ *
+ */
+void vmxnet_rx_pkt_get_protocols(struct VmxnetRxPkt *pkt,
+                                 bool *isip4, bool *isip6,
+                                 bool *isudp, bool *istcp);
+
+/**
+ * returns virtio header stored in rx context
+ *
+ * @pkt:            packet
+ * @ret:            virtio header
+ *
+ */
+struct virtio_net_hdr *vmxnet_rx_pkt_get_vhdr(struct VmxnetRxPkt *pkt);
+
+/**
+ * returns packet type
+ *
+ * @pkt:            packet
+ * @ret:            packet type
+ *
+ */
+eth_pkt_types_e vmxnet_rx_pkt_get_packet_type(struct VmxnetRxPkt *pkt);
+
+/**
+ * returns vlan tag
+ *
+ * @pkt:            packet
+ * @ret:            VLAN tag
+ *
+ */
+uint16_t vmxnet_rx_pkt_get_vlan_tag(struct VmxnetRxPkt *pkt);
+
+/**
+ * tells whether vlan was stripped from the packet
+ *
+ * @pkt:            packet
+ * @ret:            VLAN stripped sign
+ *
+ */
+bool vmxnet_rx_pkt_is_vlan_stripped(struct VmxnetRxPkt *pkt);
+
+/**
+ * notifies caller if the packet has virtio header
+ *
+ * @pkt:            packet
+ * @ret:            true if packet has virtio header, false otherwize
+ *
+ */
+bool vmxnet_rx_pkt_has_virt_hdr(struct VmxnetRxPkt *pkt);
+
+/**
+ * returns number of frags attached to the packet
+ *
+ * @pkt:            packet
+ * @ret:            number of frags
+ *
+ */
+uint16_t vmxnet_rx_pkt_get_num_frags(struct VmxnetRxPkt *pkt);
+
+/**
+ * attach data to rx packet
+ *
+ * @pkt:            packet
+ * @data:           pointer to the data buffer
+ * @len:            data length
+ * @strip_vlan:     should the module strip vlan from data
+ *
+ */
+void vmxnet_rx_pkt_attach_data(struct VmxnetRxPkt *pkt, const void *data,
+    size_t len, bool strip_vlan);
+
+/**
+ * returns io vector that holds the attached data
+ *
+ * @pkt:            packet
+ * @ret:            pointer to IOVec
+ *
+ */
+struct iovec *vmxnet_rx_pkt_get_iovec(struct VmxnetRxPkt *pkt);
+
+/**
+ * prints rx packet data if debug is enabled
+ *
+ * @pkt:            packet
+ *
+ */
+void vmxnet_rx_pkt_dump(struct VmxnetRxPkt *pkt);
+
+/**
+ * copy passed vhdr data to packet context
+ *
+ * @pkt:            packet
+ * @vhdr:           VHDR buffer
+ *
+ */
+void vmxnet_rx_pkt_set_vhdr(struct VmxnetRxPkt *pkt,
+    struct virtio_net_hdr *vhdr);
+
+/**
+ * save packet type in packet context
+ *
+ * @pkt:            packet
+ * @packet_type:    the packet type
+ *
+ */
+void vmxnet_rx_pkt_set_packet_type(struct VmxnetRxPkt *pkt,
+    eth_pkt_types_e packet_type);
+
+#endif
diff --git a/hw/vmxnet_tx_pkt.c b/hw/vmxnet_tx_pkt.c
new file mode 100644
index 0000000..b1e795b
--- /dev/null
+++ b/hw/vmxnet_tx_pkt.c
@@ -0,0 +1,567 @@
+/*
+ * QEMU VMWARE VMXNET* paravirtual NICs - TX packets abstractions
+ *
+ * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
+ *
+ * Developed by Daynix Computing LTD (http://www.daynix.com)
+ *
+ * Authors:
+ * Dmitry Fleytman <dmitry at daynix.com>
+ * Tamir Shomer <tamirs at daynix.com>
+ * Yan Vugenfirer <yan at daynix.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 "vmxnet_tx_pkt.h"
+#include "net/eth.h"
+#include "qemu-common.h"
+#include "qemu/iov.h"
+#include "net/checksum.h"
+#include "net/tap.h"
+#include "net/net.h"
+#include "exec/cpu-common.h"
+
+enum {
+    VMXNET_TX_PKT_VHDR_FRAG = 0,
+    VMXNET_TX_PKT_L2HDR_FRAG,
+    VMXNET_TX_PKT_L3HDR_FRAG,
+    VMXNET_TX_PKT_PL_START_FRAG
+};
+
+/* TX packet private context */
+struct VmxnetTxPkt {
+    struct virtio_net_hdr virt_hdr;
+    bool has_virt_hdr;
+
+    struct iovec *raw;
+    uint32_t raw_frags;
+    uint32_t max_raw_frags;
+
+    struct iovec *vec;
+
+    uint8_t l2_hdr[ETH_MAX_L2_HDR_LEN];
+
+    uint32_t payload_len;
+
+    uint32_t payload_frags;
+    uint32_t max_payload_frags;
+
+    uint16_t hdr_len;
+    eth_pkt_types_e packet_type;
+    uint8_t l4proto;
+};
+
+void vmxnet_tx_pkt_init(struct VmxnetTxPkt **pkt, uint32_t max_frags,
+    bool has_virt_hdr)
+{
+    struct VmxnetTxPkt *p = g_malloc0(sizeof *p);
+
+    p->vec = g_malloc((sizeof *p->vec) *
+        (max_frags + VMXNET_TX_PKT_PL_START_FRAG));
+
+    p->raw = g_malloc((sizeof *p->raw) * max_frags);
+
+    p->max_payload_frags = max_frags;
+    p->max_raw_frags = max_frags;
+    p->has_virt_hdr = has_virt_hdr;
+    p->vec[VMXNET_TX_PKT_VHDR_FRAG].iov_base = &p->virt_hdr;
+    p->vec[VMXNET_TX_PKT_VHDR_FRAG].iov_len =
+        p->has_virt_hdr ? sizeof p->virt_hdr : 0;
+    p->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_base = &p->l2_hdr;
+    p->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_base = NULL;
+    p->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len = 0;
+
+    *pkt = p;
+}
+
+void vmxnet_tx_pkt_uninit(struct VmxnetTxPkt *pkt)
+{
+    if (pkt) {
+        g_free(pkt->vec);
+        g_free(pkt->raw);
+        g_free(pkt);
+    }
+}
+
+void vmxnet_tx_pkt_update_ip_checksums(struct VmxnetTxPkt *pkt)
+{
+    uint16_t csum;
+    uint32_t ph_raw_csum;
+    assert(pkt);
+    uint8_t gso_type = pkt->virt_hdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN;
+    struct ip_header *ip_hdr;
+
+    if (VIRTIO_NET_HDR_GSO_TCPV4 != gso_type &&
+        VIRTIO_NET_HDR_GSO_UDP != gso_type) {
+        return;
+    }
+
+    ip_hdr = pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_base;
+
+    if (pkt->payload_len + pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len >
+        ETH_MAX_IP_DGRAM_LEN) {
+        return;
+    }
+
+    ip_hdr->ip_len = cpu_to_be16(pkt->payload_len +
+        pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len);
+
+    /* Calculate IP header checksum                    */
+    ip_hdr->ip_sum = 0;
+    csum = net_raw_checksum((uint8_t *)ip_hdr,
+        pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len);
+    ip_hdr->ip_sum = cpu_to_be16(csum);
+
+    /* Calculate IP pseudo header checksum             */
+    ph_raw_csum = eth_calc_pseudo_hdr_csum(ip_hdr, pkt->payload_len);
+    csum = cpu_to_be16(~net_checksum_finish(ph_raw_csum));
+    iov_from_buf(&pkt->vec[VMXNET_TX_PKT_PL_START_FRAG], pkt->payload_frags,
+                 pkt->virt_hdr.csum_offset, &csum, sizeof(csum));
+}
+
+static void vmxnet_tx_pkt_calculate_hdr_len(struct VmxnetTxPkt *pkt)
+{
+    pkt->hdr_len = pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_len +
+        pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len;
+}
+
+static bool vmxnet_tx_pkt_parse_headers(struct VmxnetTxPkt *pkt)
+{
+    struct iovec *l2_hdr, *l3_hdr;
+    size_t bytes_read;
+    size_t full_ip6hdr_len;
+    uint16_t l3_proto;
+
+    assert(pkt);
+
+    l2_hdr = &pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG];
+    l3_hdr = &pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG];
+
+    bytes_read = iov_to_buf(pkt->raw, pkt->raw_frags, 0, l2_hdr->iov_base,
+                            ETH_MAX_L2_HDR_LEN);
+    if (bytes_read < ETH_MAX_L2_HDR_LEN) {
+        l2_hdr->iov_len = 0;
+        return false;
+    } else {
+        l2_hdr->iov_len = eth_get_l2_hdr_length(l2_hdr->iov_base);
+    }
+
+    l3_proto = eth_get_l3_proto(l2_hdr->iov_base, l2_hdr->iov_len);
+
+    switch (l3_proto) {
+    case ETH_P_IP:
+        l3_hdr->iov_base = g_malloc(ETH_MAX_IP4_HDR_LEN);
+
+        bytes_read = iov_to_buf(pkt->raw, pkt->raw_frags, l2_hdr->iov_len,
+                                l3_hdr->iov_base, sizeof(struct ip_header));
+
+        if (bytes_read < sizeof(struct ip_header)) {
+            l3_hdr->iov_len = 0;
+            return false;
+        }
+
+        l3_hdr->iov_len = IP_HDR_GET_LEN(l3_hdr->iov_base);
+        pkt->l4proto = ((struct ip_header *) l3_hdr->iov_base)->ip_p;
+
+        /* copy optional IPv4 header data */
+        bytes_read = iov_to_buf(pkt->raw, pkt->raw_frags,
+                                l2_hdr->iov_len + sizeof(struct ip_header),
+                                l3_hdr->iov_base + sizeof(struct ip_header),
+                                l3_hdr->iov_len - sizeof(struct ip_header));
+        if (bytes_read < l3_hdr->iov_len - sizeof(struct ip_header)) {
+            l3_hdr->iov_len = 0;
+            return false;
+        }
+        break;
+
+    case ETH_P_IPV6:
+        if (!eth_parse_ipv6_hdr(pkt->raw, pkt->raw_frags, l2_hdr->iov_len,
+                               &pkt->l4proto, &full_ip6hdr_len)) {
+            l3_hdr->iov_len = 0;
+            return false;
+        }
+
+        l3_hdr->iov_base = g_malloc(full_ip6hdr_len);
+
+        bytes_read = iov_to_buf(pkt->raw, pkt->raw_frags, l2_hdr->iov_len,
+                                l3_hdr->iov_base, full_ip6hdr_len);
+
+        if (bytes_read < full_ip6hdr_len) {
+            l3_hdr->iov_len = 0;
+            return false;
+        } else {
+            l3_hdr->iov_len = full_ip6hdr_len;
+        }
+        break;
+
+    default:
+        l3_hdr->iov_len = 0;
+        break;
+    }
+
+    vmxnet_tx_pkt_calculate_hdr_len(pkt);
+    pkt->packet_type = get_eth_packet_type(l2_hdr->iov_base);
+    return true;
+}
+
+static bool vmxnet_tx_pkt_rebuild_payload(struct VmxnetTxPkt *pkt)
+{
+    size_t payload_len = iov_size(pkt->raw, pkt->raw_frags) - pkt->hdr_len;
+
+    pkt->payload_frags = iov_copy(&pkt->vec[VMXNET_TX_PKT_PL_START_FRAG],
+                                pkt->max_payload_frags,
+                                pkt->raw, pkt->raw_frags,
+                                pkt->hdr_len, payload_len);
+
+    if (pkt->payload_frags != (uint32_t) -1) {
+        pkt->payload_len = payload_len;
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool vmxnet_tx_pkt_parse(struct VmxnetTxPkt *pkt)
+{
+    return vmxnet_tx_pkt_parse_headers(pkt) &&
+           vmxnet_tx_pkt_rebuild_payload(pkt);
+}
+
+struct virtio_net_hdr *vmxnet_tx_pkt_get_vhdr(struct VmxnetTxPkt *pkt)
+{
+    assert(pkt);
+    return &pkt->virt_hdr;
+}
+
+static uint8_t vmxnet_tx_pkt_get_gso_type(struct VmxnetTxPkt *pkt,
+                                          bool tso_enable)
+{
+    uint8_t rc = VIRTIO_NET_HDR_GSO_NONE;
+    uint16_t l3_proto;
+
+    l3_proto = eth_get_l3_proto(pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_base,
+        pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_len);
+
+    if (!tso_enable) {
+        goto func_exit;
+    }
+
+    rc = eth_get_gso_type(l3_proto, pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_base,
+                          pkt->l4proto);
+
+func_exit:
+    return rc;
+}
+
+void vmxnet_tx_pkt_build_vheader(struct VmxnetTxPkt *pkt, bool tso_enable,
+    bool csum_enable, uint32_t gso_size)
+{
+    struct tcp_hdr l4hdr;
+    assert(pkt);
+
+    /* csum has to be enabled if tso is. */
+    assert(csum_enable || !tso_enable);
+
+    pkt->virt_hdr.gso_type = vmxnet_tx_pkt_get_gso_type(pkt, tso_enable);
+
+    switch (pkt->virt_hdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
+    case VIRTIO_NET_HDR_GSO_NONE:
+        pkt->virt_hdr.hdr_len = 0;
+        pkt->virt_hdr.gso_size = 0;
+        break;
+
+    case VIRTIO_NET_HDR_GSO_UDP:
+        pkt->virt_hdr.gso_size = IP_FRAG_ALIGN_SIZE(gso_size);
+        pkt->virt_hdr.hdr_len = pkt->hdr_len + sizeof(struct udp_header);
+        break;
+
+    case VIRTIO_NET_HDR_GSO_TCPV4:
+    case VIRTIO_NET_HDR_GSO_TCPV6:
+        iov_to_buf(&pkt->vec[VMXNET_TX_PKT_PL_START_FRAG], pkt->payload_frags,
+                   0, &l4hdr, sizeof(l4hdr));
+        pkt->virt_hdr.hdr_len = pkt->hdr_len + l4hdr.th_off * sizeof(uint32_t);
+        pkt->virt_hdr.gso_size = IP_FRAG_ALIGN_SIZE(gso_size);
+        break;
+
+    default:
+        assert(false);
+    }
+
+    if (csum_enable) {
+        switch (pkt->l4proto) {
+        case IP_PROTO_TCP:
+            pkt->virt_hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
+            pkt->virt_hdr.csum_start = pkt->hdr_len;
+            pkt->virt_hdr.csum_offset = offsetof(struct tcp_hdr, th_sum);
+            break;
+        case IP_PROTO_UDP:
+            pkt->virt_hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
+            pkt->virt_hdr.csum_start = pkt->hdr_len;
+            pkt->virt_hdr.csum_offset = offsetof(struct udp_hdr, uh_sum);
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+void vmxnet_tx_pkt_setup_vlan_header(struct VmxnetTxPkt *pkt, uint16_t vlan)
+{
+    bool is_new;
+    assert(pkt);
+
+    eth_setup_vlan_headers(pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_base,
+        vlan, &is_new);
+
+    /* update l2hdrlen */
+    if (is_new) {
+        pkt->hdr_len += sizeof(struct vlan_header);
+        pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_len +=
+            sizeof(struct vlan_header);
+    }
+}
+
+bool vmxnet_tx_pkt_add_raw_fragment(struct VmxnetTxPkt *pkt, hwaddr pa,
+    size_t len)
+{
+    hwaddr mapped_len = 0;
+    struct iovec *ventry;
+    assert(pkt);
+    assert(pkt->max_raw_frags > pkt->raw_frags);
+
+    if (!len) {
+        return true;
+     }
+
+    ventry = &pkt->raw[pkt->raw_frags];
+    mapped_len = len;
+
+    ventry->iov_base = cpu_physical_memory_map(pa, &mapped_len, false);
+    ventry->iov_len = mapped_len;
+    pkt->raw_frags += !!ventry->iov_base;
+
+    if ((ventry->iov_base == NULL) || (len != mapped_len)) {
+        return false;
+    }
+
+    return true;
+}
+
+eth_pkt_types_e vmxnet_tx_pkt_get_packet_type(struct VmxnetTxPkt *pkt)
+{
+    assert(pkt);
+
+    return pkt->packet_type;
+}
+
+size_t vmxnet_tx_pkt_get_total_len(struct VmxnetTxPkt *pkt)
+{
+    assert(pkt);
+
+    return pkt->hdr_len + pkt->payload_len;
+}
+
+void vmxnet_tx_pkt_dump(struct VmxnetTxPkt *pkt)
+{
+#ifdef VMXNET_TX_PKT_DEBUG
+    assert(pkt);
+
+    printf("TX PKT: hdr_len: %d, pkt_type: 0x%X, l2hdr_len: %lu, "
+        "l3hdr_len: %lu, payload_len: %u\n", pkt->hdr_len, pkt->packet_type,
+        pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_len,
+        pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len, pkt->payload_len);
+#endif
+}
+
+void vmxnet_tx_pkt_reset(struct VmxnetTxPkt *pkt)
+{
+    int i;
+
+    /* no assert, as reset can be called before tx_pkt_init */
+    if (!pkt) {
+        return;
+    }
+
+    memset(&pkt->virt_hdr, 0, sizeof(pkt->virt_hdr));
+
+    g_free(pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_base);
+    pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_base = NULL;
+
+    assert(pkt->vec);
+    for (i = VMXNET_TX_PKT_L2HDR_FRAG;
+         i < pkt->payload_frags + VMXNET_TX_PKT_PL_START_FRAG; i++) {
+        pkt->vec[i].iov_len = 0;
+    }
+    pkt->payload_len = 0;
+    pkt->payload_frags = 0;
+
+    assert(pkt->raw);
+    for (i = 0; i < pkt->raw_frags; i++) {
+        assert(pkt->raw[i].iov_base);
+        cpu_physical_memory_unmap(pkt->raw[i].iov_base, pkt->raw[i].iov_len,
+                                  false, pkt->raw[i].iov_len);
+        pkt->raw[i].iov_len = 0;
+    }
+    pkt->raw_frags = 0;
+
+    pkt->hdr_len = 0;
+    pkt->packet_type = 0;
+    pkt->l4proto = 0;
+}
+
+static void vmxnet_tx_pkt_do_sw_csum(struct VmxnetTxPkt *pkt)
+{
+    struct iovec *iov = &pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG];
+    uint32_t csum_cntr;
+    uint16_t csum = 0;
+    /* num of iovec without vhdr */
+    uint32_t iov_len = pkt->payload_frags + VMXNET_TX_PKT_PL_START_FRAG - 1;
+    uint16_t csl;
+    struct ip_header *iphdr;
+    size_t csum_offset = pkt->virt_hdr.csum_start + pkt->virt_hdr.csum_offset;
+
+    /* Put zero to checksum field */
+    iov_from_buf(iov, iov_len, csum_offset, &csum, sizeof csum);
+
+    /* Calculate L4 TCP/UDP checksum */
+    csl = pkt->payload_len;
+
+    /* data checksum */
+    csum_cntr =
+        net_checksum_add_iov(iov, iov_len, pkt->virt_hdr.csum_start, csl);
+    /* add pseudo header to csum */
+    iphdr = pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_base;
+    csum_cntr += eth_calc_pseudo_hdr_csum(iphdr, csl);
+
+    /* Put the checksum obtained into the packet */
+    csum = cpu_to_be16(net_checksum_finish(csum_cntr));
+    iov_from_buf(iov, iov_len, csum_offset, &csum, sizeof csum);
+}
+
+enum {
+    VMXNET_TX_PKT_FRAGMENT_L2_HDR_POS = 0,
+    VMXNET_TX_PKT_FRAGMENT_L3_HDR_POS,
+    VMXNET_TX_PKT_FRAGMENT_HEADER_NUM
+};
+
+#define VMXNET_MAX_FRAG_SG_LIST (64)
+
+static size_t vmxnet_tx_pkt_fetch_fragment(struct VmxnetTxPkt *pkt,
+    int *src_idx, size_t *src_offset, struct iovec *dst, int *dst_idx)
+{
+    size_t fetched = 0;
+    struct iovec *src = pkt->vec;
+
+    *dst_idx = VMXNET_TX_PKT_FRAGMENT_HEADER_NUM;
+
+    while (fetched < pkt->virt_hdr.gso_size) {
+
+        /* no more place in fragment iov */
+        if (*dst_idx == VMXNET_MAX_FRAG_SG_LIST) {
+            break;
+        }
+
+        /* no more data in iovec */
+        if (*src_idx == (pkt->payload_frags + VMXNET_TX_PKT_PL_START_FRAG)) {
+            break;
+        }
+
+
+        dst[*dst_idx].iov_base = src[*src_idx].iov_base + *src_offset;
+        dst[*dst_idx].iov_len = MIN(src[*src_idx].iov_len - *src_offset,
+            pkt->virt_hdr.gso_size - fetched);
+
+        *src_offset += dst[*dst_idx].iov_len;
+        fetched += dst[*dst_idx].iov_len;
+
+        if (*src_offset == src[*src_idx].iov_len) {
+            *src_offset = 0;
+            (*src_idx)++;
+        }
+
+        (*dst_idx)++;
+    }
+
+    return fetched;
+}
+
+static bool vmxnet_tx_pkt_do_sw_fragmentation(struct VmxnetTxPkt *pkt,
+    NetClientState *nc)
+{
+    struct iovec fragment[VMXNET_MAX_FRAG_SG_LIST];
+    size_t fragment_len = 0;
+    bool more_frags = false;
+
+    /* some pointers for shorter code */
+    void *l2_iov_base, *l3_iov_base;
+    size_t l2_iov_len, l3_iov_len;
+    int src_idx =  VMXNET_TX_PKT_PL_START_FRAG, dst_idx;
+    size_t src_offset = 0;
+    size_t fragment_offset = 0;
+
+    l2_iov_base = pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_base;
+    l2_iov_len = pkt->vec[VMXNET_TX_PKT_L2HDR_FRAG].iov_len;
+    l3_iov_base = pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_base;
+    l3_iov_len = pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len;
+
+    /* Copy headers */
+    fragment[VMXNET_TX_PKT_FRAGMENT_L2_HDR_POS].iov_base = l2_iov_base;
+    fragment[VMXNET_TX_PKT_FRAGMENT_L2_HDR_POS].iov_len = l2_iov_len;
+    fragment[VMXNET_TX_PKT_FRAGMENT_L3_HDR_POS].iov_base = l3_iov_base;
+    fragment[VMXNET_TX_PKT_FRAGMENT_L3_HDR_POS].iov_len = l3_iov_len;
+
+
+    /* Put as much data as possible and send */
+    do {
+        fragment_len = vmxnet_tx_pkt_fetch_fragment(pkt, &src_idx, &src_offset,
+            fragment, &dst_idx);
+
+        more_frags = (fragment_offset + fragment_len < pkt->payload_len);
+
+        eth_setup_ip4_fragmentation(l2_iov_base, l2_iov_len, l3_iov_base,
+            l3_iov_len, fragment_len, fragment_offset, more_frags);
+
+        eth_fix_ip4_checksum(l3_iov_base, l3_iov_len);
+
+        qemu_sendv_packet(nc, fragment, dst_idx);
+
+        fragment_offset += fragment_len;
+
+    } while (more_frags);
+
+    return true;
+}
+
+bool vmxnet_tx_pkt_send(struct VmxnetTxPkt *pkt, NetClientState *nc)
+{
+    assert(pkt);
+
+    if (!pkt->has_virt_hdr &&
+        pkt->virt_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
+        vmxnet_tx_pkt_do_sw_csum(pkt);
+    }
+
+    /*
+     * Since underlying infrastructure does not support IP datagrams longer
+     * than 64K we should drop such packets and don't even try to send
+     */
+    if (VIRTIO_NET_HDR_GSO_NONE != pkt->virt_hdr.gso_type) {
+        if (pkt->payload_len >
+            ETH_MAX_IP_DGRAM_LEN -
+            pkt->vec[VMXNET_TX_PKT_L3HDR_FRAG].iov_len) {
+            return false;
+        }
+    }
+
+    if (pkt->has_virt_hdr ||
+        pkt->virt_hdr.gso_type == VIRTIO_NET_HDR_GSO_NONE) {
+        qemu_sendv_packet(nc, pkt->vec,
+            pkt->payload_frags + VMXNET_TX_PKT_PL_START_FRAG);
+        return true;
+    }
+
+    return vmxnet_tx_pkt_do_sw_fragmentation(pkt, nc);
+}
diff --git a/hw/vmxnet_tx_pkt.h b/hw/vmxnet_tx_pkt.h
new file mode 100644
index 0000000..57121a6
--- /dev/null
+++ b/hw/vmxnet_tx_pkt.h
@@ -0,0 +1,148 @@
+/*
+ * QEMU VMWARE VMXNET* paravirtual NICs - TX packets abstraction
+ *
+ * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
+ *
+ * Developed by Daynix Computing LTD (http://www.daynix.com)
+ *
+ * Authors:
+ * Dmitry Fleytman <dmitry at daynix.com>
+ * Tamir Shomer <tamirs at daynix.com>
+ * Yan Vugenfirer <yan at daynix.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 VMXNET_TX_PKT_H
+#define VMXNET_TX_PKT_H
+
+#include "stdint.h"
+#include "stdbool.h"
+#include "net/eth.h"
+#include "exec/hwaddr.h"
+
+/* define to enable packet dump functions */
+/*#define VMXNET_TX_PKT_DEBUG*/
+
+struct VmxnetTxPkt;
+
+/**
+ * Init function for tx packet functionality
+ *
+ * @pkt:            packet pointer
+ * @max_frags:      max tx ip fragments
+ * @has_virt_hdr:   device uses virtio header.
+ */
+void vmxnet_tx_pkt_init(struct VmxnetTxPkt **pkt, uint32_t max_frags,
+    bool has_virt_hdr);
+
+/**
+ * Clean all tx packet resources.
+ *
+ * @pkt:            packet.
+ */
+void vmxnet_tx_pkt_uninit(struct VmxnetTxPkt *pkt);
+
+/**
+ * get virtio header
+ *
+ * @pkt:            packet
+ * @ret:            virtio header
+ */
+struct virtio_net_hdr *vmxnet_tx_pkt_get_vhdr(struct VmxnetTxPkt *pkt);
+
+/**
+ * build virtio header (will be stored in module context)
+ *
+ * @pkt:            packet
+ * @tso_enable:     TSO enabled
+ * @csum_enable:    CSO enabled
+ * @gso_size:       MSS size for TSO
+ *
+ */
+void vmxnet_tx_pkt_build_vheader(struct VmxnetTxPkt *pkt, bool tso_enable,
+    bool csum_enable, uint32_t gso_size);
+
+/**
+ * updates vlan tag, and adds vlan header in case it is missing
+ *
+ * @pkt:            packet
+ * @vlan:           VLAN tag
+ *
+ */
+void vmxnet_tx_pkt_setup_vlan_header(struct VmxnetTxPkt *pkt, uint16_t vlan);
+
+/**
+ * populate data fragment into pkt context.
+ *
+ * @pkt:            packet
+ * @pa:             physical address of fragment
+ * @len:            length of fragment
+ *
+ */
+bool vmxnet_tx_pkt_add_raw_fragment(struct VmxnetTxPkt *pkt, hwaddr pa,
+    size_t len);
+
+/**
+ * fix ip header fields and calculate checksums needed.
+ *
+ * @pkt:            packet
+ *
+ */
+void vmxnet_tx_pkt_update_ip_checksums(struct VmxnetTxPkt *pkt);
+
+/**
+ * get length of all populated data.
+ *
+ * @pkt:            packet
+ * @ret:            total data length
+ *
+ */
+size_t vmxnet_tx_pkt_get_total_len(struct VmxnetTxPkt *pkt);
+
+/**
+ * get packet type
+ *
+ * @pkt:            packet
+ * @ret:            packet type
+ *
+ */
+eth_pkt_types_e vmxnet_tx_pkt_get_packet_type(struct VmxnetTxPkt *pkt);
+
+/**
+ * prints packet data if debug is enabled
+ *
+ * @pkt:            packet
+ *
+ */
+void vmxnet_tx_pkt_dump(struct VmxnetTxPkt *pkt);
+
+/**
+ * reset tx packet private context (needed to be called between packets)
+ *
+ * @pkt:            packet
+ *
+ */
+void vmxnet_tx_pkt_reset(struct VmxnetTxPkt *pkt);
+
+/**
+ * Send packet to qemu. handles sw offloads if vhdr is not supported.
+ *
+ * @pkt:            packet
+ * @nc:             NetClientState
+ * @ret:            operation result
+ *
+ */
+bool vmxnet_tx_pkt_send(struct VmxnetTxPkt *pkt, NetClientState *nc);
+
+/**
+ * parse raw packet data and analyze offload requirements.
+ *
+ * @pkt:            packet
+ *
+ */
+bool vmxnet_tx_pkt_parse(struct VmxnetTxPkt *pkt);
+
+#endif
commit 75020a7021513ad4cbad2aa5f6de5d390016f099
Author: Dmitry Fleytman <dmitry at daynix.com>
Date:   Sat Mar 9 11:21:04 2013 +0200

    Common definitions for VMWARE devices
    
    Signed-off-by: Dmitry Fleytman <dmitry at daynix.com>
    Signed-off-by: Yan Vugenfirer <yan at daynix.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/vmware_utils.h b/hw/vmware_utils.h
new file mode 100644
index 0000000..5307e2c
--- /dev/null
+++ b/hw/vmware_utils.h
@@ -0,0 +1,143 @@
+/*
+ * QEMU VMWARE paravirtual devices - auxiliary code
+ *
+ * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
+ *
+ * Developed by Daynix Computing LTD (http://www.daynix.com)
+ *
+ * Authors:
+ * Dmitry Fleytman <dmitry at daynix.com>
+ * Yan Vugenfirer <yan at daynix.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 VMWARE_UTILS_H
+#define VMWARE_UTILS_H
+
+#include "qemu/range.h"
+
+#ifndef VMW_SHPRN
+#define VMW_SHPRN(fmt, ...) do {} while (0)
+#endif
+
+/*
+ * Shared memory access functions with byte swap support
+ * Each function contains printout for reverse-engineering needs
+ *
+ */
+static inline void
+vmw_shmem_read(hwaddr addr, void *buf, int len)
+{
+    VMW_SHPRN("SHMEM r: %" PRIx64 ", len: %d to %p", addr, len, buf);
+    cpu_physical_memory_read(addr, buf, len);
+}
+
+static inline void
+vmw_shmem_write(hwaddr addr, void *buf, int len)
+{
+    VMW_SHPRN("SHMEM w: %" PRIx64 ", len: %d to %p", addr, len, buf);
+    cpu_physical_memory_write(addr, buf, len);
+}
+
+static inline void
+vmw_shmem_rw(hwaddr addr, void *buf, int len, int is_write)
+{
+    VMW_SHPRN("SHMEM r/w: %" PRIx64 ", len: %d (to %p), is write: %d",
+              addr, len, buf, is_write);
+
+    cpu_physical_memory_rw(addr, buf, len, is_write);
+}
+
+static inline void
+vmw_shmem_set(hwaddr addr, uint8 val, int len)
+{
+    int i;
+    VMW_SHPRN("SHMEM set: %" PRIx64 ", len: %d (value 0x%X)", addr, len, val);
+
+    for (i = 0; i < len; i++) {
+        cpu_physical_memory_write(addr + i, &val, 1);
+    }
+}
+
+static inline uint32_t
+vmw_shmem_ld8(hwaddr addr)
+{
+    uint8_t res = ldub_phys(addr);
+    VMW_SHPRN("SHMEM load8: %" PRIx64 " (value 0x%X)", addr, res);
+    return res;
+}
+
+static inline void
+vmw_shmem_st8(hwaddr addr, uint8_t value)
+{
+    VMW_SHPRN("SHMEM store8: %" PRIx64 " (value 0x%X)", addr, value);
+    stb_phys(addr, value);
+}
+
+static inline uint32_t
+vmw_shmem_ld16(hwaddr addr)
+{
+    uint16_t res = lduw_le_phys(addr);
+    VMW_SHPRN("SHMEM load16: %" PRIx64 " (value 0x%X)", addr, res);
+    return res;
+}
+
+static inline void
+vmw_shmem_st16(hwaddr addr, uint16_t value)
+{
+    VMW_SHPRN("SHMEM store16: %" PRIx64 " (value 0x%X)", addr, value);
+    stw_le_phys(addr, value);
+}
+
+static inline uint32_t
+vmw_shmem_ld32(hwaddr addr)
+{
+    uint32_t res = ldl_le_phys(addr);
+    VMW_SHPRN("SHMEM load32: %" PRIx64 " (value 0x%X)", addr, res);
+    return res;
+}
+
+static inline void
+vmw_shmem_st32(hwaddr addr, uint32_t value)
+{
+    VMW_SHPRN("SHMEM store32: %" PRIx64 " (value 0x%X)", addr, value);
+    stl_le_phys(addr, value);
+}
+
+static inline uint64_t
+vmw_shmem_ld64(hwaddr addr)
+{
+    uint64_t res = ldq_le_phys(addr);
+    VMW_SHPRN("SHMEM load64: %" PRIx64 " (value %" PRIx64 ")", addr, res);
+    return res;
+}
+
+static inline void
+vmw_shmem_st64(hwaddr addr, uint64_t value)
+{
+    VMW_SHPRN("SHMEM store64: %" PRIx64 " (value %" PRIx64 ")", addr, value);
+    stq_le_phys(addr, value);
+}
+
+/* Macros for simplification of operations on array-style registers */
+
+/*
+ * Whether <addr> lies inside of array-style register defined by <base>,
+ * number of elements (<cnt>) and element size (<regsize>)
+ *
+*/
+#define VMW_IS_MULTIREG_ADDR(addr, base, cnt, regsize)                 \
+    range_covers_byte(base, cnt * regsize, addr)
+
+/*
+ * Returns index of given register (<addr>) in array-style register defined by
+ * <base> and element size (<regsize>)
+ *
+*/
+#define VMW_MULTIREG_IDX_BY_ADDR(addr, base, regsize)                  \
+    (((addr) - (base)) / (regsize))
+
+#endif
diff --git a/hw/vmxnet_debug.h b/hw/vmxnet_debug.h
new file mode 100644
index 0000000..96dae0f
--- /dev/null
+++ b/hw/vmxnet_debug.h
@@ -0,0 +1,115 @@
+/*
+ * QEMU VMWARE VMXNET* paravirtual NICs - debugging facilities
+ *
+ * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
+ *
+ * Developed by Daynix Computing LTD (http://www.daynix.com)
+ *
+ * Authors:
+ * Dmitry Fleytman <dmitry at daynix.com>
+ * Tamir Shomer <tamirs at daynix.com>
+ * Yan Vugenfirer <yan at daynix.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 _QEMU_VMXNET_DEBUG_H
+#define _QEMU_VMXNET_DEBUG_H
+
+#define VMXNET_DEVICE_NAME "vmxnet3"
+
+/* #define VMXNET_DEBUG_CB */
+#define VMXNET_DEBUG_WARNINGS
+#define VMXNET_DEBUG_ERRORS
+/* #define VMXNET_DEBUG_INTERRUPTS */
+/* #define VMXNET_DEBUG_CONFIG */
+/* #define VMXNET_DEBUG_RINGS */
+/* #define VMXNET_DEBUG_PACKETS */
+/* #define VMXNET_DEBUG_SHMEM_ACCESS */
+
+#ifdef VMXNET_DEBUG_SHMEM_ACCESS
+#define VMW_SHPRN(fmt, ...)                                                   \
+    do {                                                                      \
+        printf("[%s][SH][%s]: " fmt "\n", VMXNET_DEVICE_NAME, __func__,       \
+            ## __VA_ARGS__);                                                  \
+    } while (0)
+#else
+#define VMW_SHPRN(fmt, ...) do {} while (0)
+#endif
+
+#ifdef VMXNET_DEBUG_CB
+#define VMW_CBPRN(fmt, ...)                                                   \
+    do {                                                                      \
+        printf("[%s][CB][%s]: " fmt "\n", VMXNET_DEVICE_NAME, __func__,       \
+            ## __VA_ARGS__);                                                  \
+    } while (0)
+#else
+#define VMW_CBPRN(fmt, ...) do {} while (0)
+#endif
+
+#ifdef VMXNET_DEBUG_PACKETS
+#define VMW_PKPRN(fmt, ...)                                                   \
+    do {                                                                      \
+        printf("[%s][PK][%s]: " fmt "\n", VMXNET_DEVICE_NAME, __func__,       \
+            ## __VA_ARGS__);                                                  \
+    } while (0)
+#else
+#define VMW_PKPRN(fmt, ...) do {} while (0)
+#endif
+
+#ifdef VMXNET_DEBUG_WARNINGS
+#define VMW_WRPRN(fmt, ...)                                                   \
+    do {                                                                      \
+        printf("[%s][WR][%s]: " fmt "\n", VMXNET_DEVICE_NAME, __func__,       \
+            ## __VA_ARGS__);                                                  \
+    } while (0)
+#else
+#define VMW_WRPRN(fmt, ...) do {} while (0)
+#endif
+
+#ifdef VMXNET_DEBUG_ERRORS
+#define VMW_ERPRN(fmt, ...)                                                   \
+    do {                                                                      \
+        printf("[%s][ER][%s]: " fmt "\n", VMXNET_DEVICE_NAME, __func__,       \
+            ## __VA_ARGS__);                                                  \
+    } while (0)
+#else
+#define VMW_ERPRN(fmt, ...) do {} while (0)
+#endif
+
+#ifdef VMXNET_DEBUG_INTERRUPTS
+#define VMW_IRPRN(fmt, ...)                                                   \
+    do {                                                                      \
+        printf("[%s][IR][%s]: " fmt "\n", VMXNET_DEVICE_NAME, __func__,       \
+            ## __VA_ARGS__);                                                  \
+    } while (0)
+#else
+#define VMW_IRPRN(fmt, ...) do {} while (0)
+#endif
+
+#ifdef VMXNET_DEBUG_CONFIG
+#define VMW_CFPRN(fmt, ...)                                                   \
+    do {                                                                      \
+        printf("[%s][CF][%s]: " fmt "\n", VMXNET_DEVICE_NAME, __func__,       \
+            ## __VA_ARGS__);                                                  \
+    } while (0)
+#else
+#define VMW_CFPRN(fmt, ...) do {} while (0)
+#endif
+
+#ifdef VMXNET_DEBUG_RINGS
+#define VMW_RIPRN(fmt, ...)                                                   \
+    do {                                                                      \
+        printf("[%s][RI][%s]: " fmt "\n", VMXNET_DEVICE_NAME, __func__,       \
+            ## __VA_ARGS__);                                                  \
+    } while (0)
+#else
+#define VMW_RIPRN(fmt, ...) do {} while (0)
+#endif
+
+#define VMXNET_MF       "%02X:%02X:%02X:%02X:%02X:%02X"
+#define VMXNET_MA(a)    (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+
+#endif /* _QEMU_VMXNET3_DEBUG_H  */
diff --git a/include/net/eth.h b/include/net/eth.h
new file mode 100644
index 0000000..1d48e06
--- /dev/null
+++ b/include/net/eth.h
@@ -0,0 +1,347 @@
+/*
+ * QEMU network structures definitions and helper functions
+ *
+ * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
+ *
+ * Developed by Daynix Computing LTD (http://www.daynix.com)
+ *
+ * Portions developed by Free Software Foundation, Inc
+ * Copyright (C) 1991-1997, 2001, 2003, 2006 Free Software Foundation, Inc.
+ * See netinet/ip6.h and netinet/in.h (GNU C Library)
+ *
+ * Portions developed by Igor Kovalenko
+ * Copyright (c) 2006 Igor Kovalenko
+ * See hw/rtl8139.c (QEMU)
+ *
+ * Authors:
+ * Dmitry Fleytman <dmitry at daynix.com>
+ * Tamir Shomer <tamirs at daynix.com>
+ * Yan Vugenfirer <yan at daynix.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 QEMU_ETH_H
+#define QEMU_ETH_H
+
+#include <sys/types.h>
+#include <string.h>
+#include "qemu/bswap.h"
+#include "qemu/iov.h"
+
+#define ETH_ALEN 6
+
+struct eth_header {
+    uint8_t  h_dest[ETH_ALEN];   /* destination eth addr */
+    uint8_t  h_source[ETH_ALEN]; /* source ether addr    */
+    uint16_t h_proto;            /* packet type ID field */
+};
+
+struct vlan_header {
+    uint16_t  h_tci;     /* priority and VLAN ID  */
+    uint16_t  h_proto;   /* encapsulated protocol */
+};
+
+struct ip_header {
+    uint8_t  ip_ver_len;     /* version and header length */
+    uint8_t  ip_tos;         /* type of service */
+    uint16_t ip_len;         /* total length */
+    uint16_t ip_id;          /* identification */
+    uint16_t ip_off;         /* fragment offset field */
+    uint8_t  ip_ttl;         /* time to live */
+    uint8_t  ip_p;           /* protocol */
+    uint16_t ip_sum;         /* checksum */
+    uint32_t ip_src, ip_dst; /* source and destination address */
+};
+
+typedef struct tcp_header {
+    uint16_t th_sport;          /* source port */
+    uint16_t th_dport;          /* destination port */
+    uint32_t th_seq;            /* sequence number */
+    uint32_t th_ack;            /* acknowledgment number */
+    uint16_t th_offset_flags;   /* data offset, reserved 6 bits, */
+                                /* TCP protocol flags */
+    uint16_t th_win;            /* window */
+    uint16_t th_sum;            /* checksum */
+    uint16_t th_urp;            /* urgent pointer */
+} tcp_header;
+
+typedef struct udp_header {
+    uint16_t uh_sport; /* source port */
+    uint16_t uh_dport; /* destination port */
+    uint16_t uh_ulen;  /* udp length */
+    uint16_t uh_sum;   /* udp checksum */
+} udp_header;
+
+typedef struct ip_pseudo_header {
+    uint32_t ip_src;
+    uint32_t ip_dst;
+    uint8_t  zeros;
+    uint8_t  ip_proto;
+    uint16_t ip_payload;
+} ip_pseudo_header;
+
+/* IPv6 address */
+struct in6_addr {
+    union {
+        uint8_t __u6_addr8[16];
+    } __in6_u;
+};
+
+struct ip6_header {
+    union {
+        struct ip6_hdrctl {
+            uint32_t ip6_un1_flow; /* 4 bits version, 8 bits TC,
+                                      20 bits flow-ID */
+            uint16_t ip6_un1_plen; /* payload length */
+            uint8_t  ip6_un1_nxt;  /* next header */
+            uint8_t  ip6_un1_hlim; /* hop limit */
+        } ip6_un1;
+        uint8_t ip6_un2_vfc;       /* 4 bits version, top 4 bits tclass */
+        struct ip6_ecn_access {
+            uint8_t  ip6_un3_vfc;  /* 4 bits version, top 4 bits tclass */
+            uint8_t  ip6_un3_ecn;  /* 2 bits ECN, top 6 bits payload length */
+        } ip6_un3;
+    } ip6_ctlun;
+    struct in6_addr ip6_src;     /* source address */
+    struct in6_addr ip6_dst;     /* destination address */
+};
+
+struct ip6_ext_hdr {
+    uint8_t        ip6r_nxt;   /* next header */
+    uint8_t        ip6r_len;   /* length in units of 8 octets */
+};
+
+struct udp_hdr {
+  uint16_t uh_sport;           /* source port */
+  uint16_t uh_dport;           /* destination port */
+  uint16_t uh_ulen;            /* udp length */
+  uint16_t uh_sum;             /* udp checksum */
+};
+
+struct tcp_hdr {
+    u_short     th_sport;   /* source port */
+    u_short     th_dport;   /* destination port */
+    uint32_t    th_seq;     /* sequence number */
+    uint32_t    th_ack;     /* acknowledgment number */
+#ifdef HOST_WORDS_BIGENDIAN
+    u_char  th_off : 4,     /* data offset */
+        th_x2:4;            /* (unused) */
+#else
+    u_char  th_x2 : 4,      /* (unused) */
+        th_off:4;           /* data offset */
+#endif
+
+#define TH_ELN  0x1 /* explicit loss notification */
+#define TH_ECN  0x2 /* explicit congestion notification */
+#define TH_FS   0x4 /* fast start */
+
+    u_char  th_flags;
+#define TH_FIN  0x01
+#define TH_SYN  0x02
+#define TH_RST  0x04
+#define TH_PUSH 0x08
+#define TH_ACK  0x10
+#define TH_URG  0x20
+    u_short th_win;      /* window */
+    u_short th_sum;      /* checksum */
+    u_short th_urp;      /* urgent pointer */
+};
+
+#define ip6_nxt      ip6_ctlun.ip6_un1.ip6_un1_nxt
+#define ip6_ecn_acc  ip6_ctlun.ip6_un3.ip6_un3_ecn
+
+#define PKT_GET_ETH_HDR(p)        \
+    ((struct eth_header *)(p))
+#define PKT_GET_VLAN_HDR(p)       \
+    ((struct vlan_header *) (((uint8_t *)(p)) + sizeof(struct eth_header)))
+#define PKT_GET_DVLAN_HDR(p)       \
+    (PKT_GET_VLAN_HDR(p) + 1)
+#define PKT_GET_IP_HDR(p)         \
+    ((struct ip_header *)(((uint8_t *)(p)) + eth_get_l2_hdr_length(p)))
+#define IP_HDR_GET_LEN(p)         \
+    ((((struct ip_header *)p)->ip_ver_len & 0x0F) << 2)
+#define PKT_GET_IP_HDR_LEN(p)     \
+    (IP_HDR_GET_LEN(PKT_GET_IP_HDR(p)))
+#define PKT_GET_IP6_HDR(p)        \
+    ((struct ip6_header *) (((uint8_t *)(p)) + eth_get_l2_hdr_length(p)))
+#define IP_HEADER_VERSION(ip)     \
+    ((ip->ip_ver_len >> 4)&0xf)
+
+#define ETH_P_IP                  (0x0800)
+#define ETH_P_IPV6                (0x86dd)
+#define ETH_P_VLAN                (0x8100)
+#define ETH_P_DVLAN               (0x88a8)
+#define VLAN_VID_MASK             0x0fff
+#define IP_HEADER_VERSION_4       (4)
+#define IP_HEADER_VERSION_6       (6)
+#define IP_PROTO_TCP              (6)
+#define IP_PROTO_UDP              (17)
+#define IPTOS_ECN_MASK            0x03
+#define IPTOS_ECN(x)              ((x) & IPTOS_ECN_MASK)
+#define IPTOS_ECN_CE              0x03
+#define IP6_ECN_MASK              0xC0
+#define IP6_ECN(x)                ((x) & IP6_ECN_MASK)
+#define IP6_ECN_CE                0xC0
+#define IP4_DONT_FRAGMENT_FLAG    (1 << 14)
+
+#define IS_SPECIAL_VLAN_ID(x)     \
+    (((x) == 0) || ((x) == 0xFFF))
+
+#define ETH_MAX_L2_HDR_LEN  \
+    (sizeof(struct eth_header) + 2 * sizeof(struct vlan_header))
+
+#define ETH_MAX_IP4_HDR_LEN   (60)
+#define ETH_MAX_IP_DGRAM_LEN  (0xFFFF)
+
+#define IP_FRAG_UNIT_SIZE     (8)
+#define IP_FRAG_ALIGN_SIZE(x) ((x) & ~0x7)
+#define IP_RF                 0x8000           /* reserved fragment flag */
+#define IP_DF                 0x4000           /* don't fragment flag */
+#define IP_MF                 0x2000           /* more fragments flag */
+#define IP_OFFMASK            0x1fff           /* mask for fragmenting bits */
+
+#define IP6_EXT_GRANULARITY   (8)  /* Size granularity for
+                                      IPv6 extension headers */
+
+/* IP6 extension header types */
+#define IP6_HOP_BY_HOP        (0)
+#define IP6_ROUTING           (43)
+#define IP6_FRAGMENT          (44)
+#define IP6_ESP               (50)
+#define IP6_AUTHENTICATION    (51)
+#define IP6_NONE              (59)
+#define IP6_DESTINATON        (60)
+#define IP6_MOBILITY          (135)
+
+static inline int is_multicast_ether_addr(const uint8_t *addr)
+{
+    return 0x01 & addr[0];
+}
+
+static inline int is_broadcast_ether_addr(const uint8_t *addr)
+{
+    return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff;
+}
+
+static inline int is_unicast_ether_addr(const uint8_t *addr)
+{
+    return !is_multicast_ether_addr(addr);
+}
+
+typedef enum {
+    ETH_PKT_UCAST = 0xAABBCC00,
+    ETH_PKT_BCAST,
+    ETH_PKT_MCAST
+} eth_pkt_types_e;
+
+static inline eth_pkt_types_e
+get_eth_packet_type(const struct eth_header *ehdr)
+{
+    if (is_broadcast_ether_addr(ehdr->h_dest)) {
+        return ETH_PKT_BCAST;
+    } else if (is_multicast_ether_addr(ehdr->h_dest)) {
+        return ETH_PKT_MCAST;
+    } else { /* unicast */
+        return ETH_PKT_UCAST;
+    }
+}
+
+static inline uint32_t
+eth_get_l2_hdr_length(const void *p)
+{
+    uint16_t proto = be16_to_cpu(PKT_GET_ETH_HDR(p)->h_proto);
+    struct vlan_header *hvlan = PKT_GET_VLAN_HDR(p);
+    switch (proto) {
+    case ETH_P_VLAN:
+        return sizeof(struct eth_header) + sizeof(struct vlan_header);
+    case ETH_P_DVLAN:
+        if (hvlan->h_proto == ETH_P_VLAN) {
+            return sizeof(struct eth_header) + 2 * sizeof(struct vlan_header);
+        } else {
+            return sizeof(struct eth_header) + sizeof(struct vlan_header);
+        }
+    default:
+        return sizeof(struct eth_header);
+    }
+}
+
+static inline uint16_t
+eth_get_pkt_tci(const void *p)
+{
+    uint16_t proto = be16_to_cpu(PKT_GET_ETH_HDR(p)->h_proto);
+    struct vlan_header *hvlan = PKT_GET_VLAN_HDR(p);
+    switch (proto) {
+    case ETH_P_VLAN:
+    case ETH_P_DVLAN:
+        return be16_to_cpu(hvlan->h_tci);
+    default:
+        return 0;
+    }
+}
+
+static inline bool
+eth_strip_vlan(const void *p, uint8_t *new_ehdr_buf,
+               uint16_t *payload_offset, uint16_t *tci)
+{
+    uint16_t proto = be16_to_cpu(PKT_GET_ETH_HDR(p)->h_proto);
+    struct vlan_header *hvlan = PKT_GET_VLAN_HDR(p);
+    struct eth_header *new_ehdr = (struct eth_header *) new_ehdr_buf;
+
+    switch (proto) {
+    case ETH_P_VLAN:
+    case ETH_P_DVLAN:
+        memcpy(new_ehdr->h_source, PKT_GET_ETH_HDR(p)->h_source, ETH_ALEN);
+        memcpy(new_ehdr->h_dest, PKT_GET_ETH_HDR(p)->h_dest, ETH_ALEN);
+        new_ehdr->h_proto = hvlan->h_proto;
+        *tci = be16_to_cpu(hvlan->h_tci);
+        *payload_offset =
+            sizeof(struct eth_header) + sizeof(struct vlan_header);
+        if (be16_to_cpu(new_ehdr->h_proto) == ETH_P_VLAN) {
+            memcpy(PKT_GET_VLAN_HDR(new_ehdr),
+                   PKT_GET_DVLAN_HDR(p),
+                   sizeof(struct vlan_header));
+            *payload_offset += sizeof(struct vlan_header);
+        }
+        return true;
+    default:
+        return false;
+    }
+}
+
+static inline uint16_t
+eth_get_l3_proto(const void *l2hdr, size_t l2hdr_len)
+{
+    uint8_t *proto_ptr = (uint8_t *) l2hdr + l2hdr_len - sizeof(uint16_t);
+    return be16_to_cpup((uint16_t *)proto_ptr);
+}
+
+void eth_setup_vlan_headers(struct eth_header *ehdr, uint16_t vlan_tag,
+    bool *is_new);
+
+uint8_t eth_get_gso_type(uint16_t l3_proto, uint8_t *l3_hdr, uint8_t l4proto);
+
+void eth_get_protocols(const uint8_t *headers,
+                       uint32_t hdr_length,
+                       bool *isip4, bool *isip6,
+                       bool *isudp, bool *istcp);
+
+void eth_setup_ip4_fragmentation(const void *l2hdr, size_t l2hdr_len,
+                                 void *l3hdr, size_t l3hdr_len,
+                                 size_t l3payload_len,
+                                 size_t frag_offset, bool more_frags);
+
+void
+eth_fix_ip4_checksum(void *l3hdr, size_t l3hdr_len);
+
+uint32_t
+eth_calc_pseudo_hdr_csum(struct ip_header *iphdr, uint16_t csl);
+
+bool
+eth_parse_ipv6_hdr(struct iovec *pkt, int pkt_frags,
+                   size_t ip6hdr_off, uint8_t *l4proto,
+                   size_t *full_hdr_len);
+
+#endif
diff --git a/net/Makefile.objs b/net/Makefile.objs
index a08cd14..4854a14 100644
--- a/net/Makefile.objs
+++ b/net/Makefile.objs
@@ -1,6 +1,7 @@
 common-obj-y = net.o queue.o checksum.o util.o hub.o
 common-obj-y += socket.o
 common-obj-y += dump.o
+common-obj-y += eth.o
 common-obj-$(CONFIG_POSIX) += tap.o
 common-obj-$(CONFIG_LINUX) += tap-linux.o
 common-obj-$(CONFIG_WIN32) += tap-win32.o
diff --git a/net/eth.c b/net/eth.c
new file mode 100644
index 0000000..1d7494d
--- /dev/null
+++ b/net/eth.c
@@ -0,0 +1,217 @@
+/*
+ * QEMU network structures definitions and helper functions
+ *
+ * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
+ *
+ * Developed by Daynix Computing LTD (http://www.daynix.com)
+ *
+ * Authors:
+ * Dmitry Fleytman <dmitry at daynix.com>
+ * Tamir Shomer <tamirs at daynix.com>
+ * Yan Vugenfirer <yan at daynix.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 "net/eth.h"
+#include "net/checksum.h"
+#include "qemu-common.h"
+#include "net/tap.h"
+
+void eth_setup_vlan_headers(struct eth_header *ehdr, uint16_t vlan_tag,
+    bool *is_new)
+{
+    struct vlan_header *vhdr = PKT_GET_VLAN_HDR(ehdr);
+
+    switch (be16_to_cpu(ehdr->h_proto)) {
+    case ETH_P_VLAN:
+    case ETH_P_DVLAN:
+        /* vlan hdr exists */
+        *is_new = false;
+        break;
+
+    default:
+        /* No VLAN header, put a new one */
+        vhdr->h_proto = ehdr->h_proto;
+        ehdr->h_proto = cpu_to_be16(ETH_P_VLAN);
+        *is_new = true;
+        break;
+    }
+    vhdr->h_tci = cpu_to_be16(vlan_tag);
+}
+
+uint8_t
+eth_get_gso_type(uint16_t l3_proto, uint8_t *l3_hdr, uint8_t l4proto)
+{
+    uint8_t ecn_state = 0;
+
+    if (l3_proto == ETH_P_IP) {
+        struct ip_header *iphdr = (struct ip_header *) l3_hdr;
+
+        if (IP_HEADER_VERSION(iphdr) == IP_HEADER_VERSION_4) {
+            if (IPTOS_ECN(iphdr->ip_tos) == IPTOS_ECN_CE) {
+                ecn_state = VIRTIO_NET_HDR_GSO_ECN;
+            }
+            if (l4proto == IP_PROTO_TCP) {
+                return VIRTIO_NET_HDR_GSO_TCPV4 | ecn_state;
+            } else if (l4proto == IP_PROTO_UDP) {
+                return VIRTIO_NET_HDR_GSO_UDP | ecn_state;
+            }
+        }
+    } else if (l3_proto == ETH_P_IPV6) {
+        struct ip6_header *ip6hdr = (struct ip6_header *) l3_hdr;
+
+        if (IP6_ECN(ip6hdr->ip6_ecn_acc) == IP6_ECN_CE) {
+            ecn_state = VIRTIO_NET_HDR_GSO_ECN;
+        }
+
+        if (l4proto == IP_PROTO_TCP) {
+            return VIRTIO_NET_HDR_GSO_TCPV6 | ecn_state;
+        }
+    }
+
+    /* Unsupported offload */
+    assert(false);
+
+    return VIRTIO_NET_HDR_GSO_NONE | ecn_state;
+}
+
+void eth_get_protocols(const uint8_t *headers,
+                       uint32_t hdr_length,
+                       bool *isip4, bool *isip6,
+                       bool *isudp, bool *istcp)
+{
+    int proto;
+    size_t l2hdr_len = eth_get_l2_hdr_length(headers);
+    assert(hdr_length >= eth_get_l2_hdr_length(headers));
+    *isip4 = *isip6 = *isudp = *istcp = false;
+
+    proto = eth_get_l3_proto(headers, l2hdr_len);
+    if (proto == ETH_P_IP) {
+        *isip4 = true;
+
+        struct ip_header *iphdr;
+
+        assert(hdr_length >=
+            eth_get_l2_hdr_length(headers) + sizeof(struct ip_header));
+
+        iphdr = PKT_GET_IP_HDR(headers);
+
+        if (IP_HEADER_VERSION(iphdr) == IP_HEADER_VERSION_4) {
+            if (iphdr->ip_p == IP_PROTO_TCP) {
+                *istcp = true;
+            } else if (iphdr->ip_p == IP_PROTO_UDP) {
+                *isudp = true;
+            }
+        }
+    } else if (proto == ETH_P_IPV6) {
+        uint8_t l4proto;
+        size_t full_ip6hdr_len;
+
+        struct iovec hdr_vec;
+        hdr_vec.iov_base = (void *) headers;
+        hdr_vec.iov_len = hdr_length;
+
+        *isip6 = true;
+        if (eth_parse_ipv6_hdr(&hdr_vec, 1, l2hdr_len,
+                              &l4proto, &full_ip6hdr_len)) {
+            if (l4proto == IP_PROTO_TCP) {
+                *istcp = true;
+            } else if (l4proto == IP_PROTO_UDP) {
+                *isudp = true;
+            }
+        }
+    }
+}
+
+void
+eth_setup_ip4_fragmentation(const void *l2hdr, size_t l2hdr_len,
+                            void *l3hdr, size_t l3hdr_len,
+                            size_t l3payload_len,
+                            size_t frag_offset, bool more_frags)
+{
+    if (eth_get_l3_proto(l2hdr, l2hdr_len) == ETH_P_IP) {
+        uint16_t orig_flags;
+        struct ip_header *iphdr = (struct ip_header *) l3hdr;
+        uint16_t frag_off_units = frag_offset / IP_FRAG_UNIT_SIZE;
+        uint16_t new_ip_off;
+
+        assert(frag_offset % IP_FRAG_UNIT_SIZE == 0);
+        assert((frag_off_units & ~IP_OFFMASK) == 0);
+
+        orig_flags = be16_to_cpu(iphdr->ip_off) & ~(IP_OFFMASK|IP_MF);
+        new_ip_off = frag_off_units | orig_flags  | (more_frags ? IP_MF : 0);
+        iphdr->ip_off = cpu_to_be16(new_ip_off);
+        iphdr->ip_len = cpu_to_be16(l3payload_len + l3hdr_len);
+    }
+}
+
+void
+eth_fix_ip4_checksum(void *l3hdr, size_t l3hdr_len)
+{
+    struct ip_header *iphdr = (struct ip_header *) l3hdr;
+    iphdr->ip_sum = 0;
+    iphdr->ip_sum = cpu_to_be16(net_raw_checksum(l3hdr, l3hdr_len));
+}
+
+uint32_t
+eth_calc_pseudo_hdr_csum(struct ip_header *iphdr, uint16_t csl)
+{
+    struct ip_pseudo_header ipph;
+    ipph.ip_src = iphdr->ip_src;
+    ipph.ip_dst = iphdr->ip_dst;
+    ipph.ip_payload = cpu_to_be16(csl);
+    ipph.ip_proto = iphdr->ip_p;
+    ipph.zeros = 0;
+    return net_checksum_add(sizeof(ipph), (uint8_t *) &ipph);
+}
+
+static bool
+eth_is_ip6_extension_header_type(uint8_t hdr_type)
+{
+    switch (hdr_type) {
+    case IP6_HOP_BY_HOP:
+    case IP6_ROUTING:
+    case IP6_FRAGMENT:
+    case IP6_ESP:
+    case IP6_AUTHENTICATION:
+    case IP6_DESTINATON:
+    case IP6_MOBILITY:
+        return true;
+    default:
+        return false;
+    }
+}
+
+bool eth_parse_ipv6_hdr(struct iovec *pkt, int pkt_frags,
+                        size_t ip6hdr_off, uint8_t *l4proto,
+                        size_t *full_hdr_len)
+{
+    struct ip6_header ip6_hdr;
+    struct ip6_ext_hdr ext_hdr;
+    size_t bytes_read;
+
+    bytes_read = iov_to_buf(pkt, pkt_frags, ip6hdr_off,
+                            &ip6_hdr, sizeof(ip6_hdr));
+    if (bytes_read < sizeof(ip6_hdr)) {
+        return false;
+    }
+
+    *full_hdr_len = sizeof(struct ip6_header);
+
+    if (!eth_is_ip6_extension_header_type(ip6_hdr.ip6_nxt)) {
+        *l4proto = ip6_hdr.ip6_nxt;
+        return true;
+    }
+
+    do {
+        bytes_read = iov_to_buf(pkt, pkt_frags, ip6hdr_off + *full_hdr_len,
+                                &ext_hdr, sizeof(ext_hdr));
+        *full_hdr_len += (ext_hdr.ip6r_len + 1) * IP6_EXT_GRANULARITY;
+    } while (eth_is_ip6_extension_header_type(ext_hdr.ip6r_nxt));
+
+    *l4proto = ext_hdr.ip6r_nxt;
+    return true;
+}
commit 84026301694b98dd08272e613da3497b17023d5c
Author: Dmitry Fleytman <dmitry at daynix.com>
Date:   Sat Mar 9 11:21:03 2013 +0200

    net: iovec checksum calculator
    
    Signed-off-by: Dmitry Fleytman <dmitry at daynix.com>
    Signed-off-by: Yan Vugenfirer <yan at daynix.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/include/net/checksum.h b/include/net/checksum.h
index 3e7b93d..80203fb 100644
--- a/include/net/checksum.h
+++ b/include/net/checksum.h
@@ -38,4 +38,16 @@ net_raw_checksum(uint8_t *data, int length)
     return net_checksum_finish(net_checksum_add(length, data));
 }
 
+/**
+ * net_checksum_add_iov: scatter-gather vector checksumming
+ *
+ * @iov: input scatter-gather array
+ * @iov_cnt: number of array elements
+ * @iov_off: starting iov offset for checksumming
+ * @size: length of data to be checksummed
+ */
+uint32_t net_checksum_add_iov(const struct iovec *iov,
+                              const unsigned int iov_cnt,
+                              uint32_t iov_off, uint32_t size);
+
 #endif /* QEMU_NET_CHECKSUM_H */
diff --git a/net/checksum.c b/net/checksum.c
index 4fa5563..14c0855 100644
--- a/net/checksum.c
+++ b/net/checksum.c
@@ -15,6 +15,7 @@
  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "qemu-common.h"
 #include "net/checksum.h"
 
 #define PROTO_TCP  6
@@ -84,3 +85,31 @@ void net_checksum_calculate(uint8_t *data, int length)
     data[14+hlen+csum_offset]   = csum >> 8;
     data[14+hlen+csum_offset+1] = csum & 0xff;
 }
+
+uint32_t
+net_checksum_add_iov(const struct iovec *iov, const unsigned int iov_cnt,
+                     uint32_t iov_off, uint32_t size)
+{
+    size_t iovec_off, buf_off;
+    unsigned int i;
+    uint32_t res = 0;
+    uint32_t seq = 0;
+
+    iovec_off = 0;
+    buf_off = 0;
+    for (i = 0; i < iov_cnt && size; i++) {
+        if (iov_off < (iovec_off + iov[i].iov_len)) {
+            size_t len = MIN((iovec_off + iov[i].iov_len) - iov_off , size);
+            void *chunk_buf = iov[i].iov_base + (iov_off - iovec_off);
+
+            res += net_checksum_add_cont(len, chunk_buf, seq);
+            seq += len;
+
+            buf_off += len;
+            iov_off += len;
+            size -= len;
+        }
+        iovec_off += iov[i].iov_len;
+    }
+    return res;
+}
commit 5acf5ea4bc1535657692c509092caddec3d719ff
Author: Dmitry Fleytman <dmitry at daynix.com>
Date:   Sat Mar 9 11:21:02 2013 +0200

    Checksum-related utility functions
    
    net_checksum_add_cont()
    checksum calculation for scattered data with odd chunk sizes
    
    net_raw_checksum()
    checksum calculation for a buffer
    
    Signed-off-by: Dmitry Fleytman <dmitry at daynix.com>
    Signed-off-by: Yan Vugenfirer <yan at daynix.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/include/net/checksum.h b/include/net/checksum.h
index 1f05298..3e7b93d 100644
--- a/include/net/checksum.h
+++ b/include/net/checksum.h
@@ -20,10 +20,22 @@
 
 #include <stdint.h>
 
-uint32_t net_checksum_add(int len, uint8_t *buf);
+uint32_t net_checksum_add_cont(int len, uint8_t *buf, int seq);
 uint16_t net_checksum_finish(uint32_t sum);
 uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
                              uint8_t *addrs, uint8_t *buf);
 void net_checksum_calculate(uint8_t *data, int length);
 
+static inline uint32_t
+net_checksum_add(int len, uint8_t *buf)
+{
+    return net_checksum_add_cont(len, buf, 0);
+}
+
+static inline uint16_t
+net_raw_checksum(uint8_t *data, int length)
+{
+    return net_checksum_finish(net_checksum_add(length, data));
+}
+
 #endif /* QEMU_NET_CHECKSUM_H */
diff --git a/net/checksum.c b/net/checksum.c
index 9919b2e..4fa5563 100644
--- a/net/checksum.c
+++ b/net/checksum.c
@@ -20,16 +20,17 @@
 #define PROTO_TCP  6
 #define PROTO_UDP 17
 
-uint32_t net_checksum_add(int len, uint8_t *buf)
+uint32_t net_checksum_add_cont(int len, uint8_t *buf, int seq)
 {
     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;
+    for (i = seq; i < seq + len; i++) {
+        if (i & 1) {
+            sum += (uint32_t)buf[i - seq];
+        } else {
+            sum += (uint32_t)buf[i - seq] << 8;
+        }
     }
     return sum;
 }
commit 20048d0a12b1080f688ff9b82696134df1aa3607
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Feb 27 15:05:47 2013 +0100

    net: use socket_set_nodelay() for -netdev socket
    
    Reduce -netdev socket latency by disabling the Nagle algorithm on
    SOCK_STREAM sockets in net/socket.c.  Since we are tunelling Ethernet
    over TCP we shouldn't artificially delay outgoing packets, let the guest
    decide packet scheduling.
    
    I already get sub-millisecond -netdev socket ping times on localhost, so
    there was no measurable difference in my testing.  This won't hurt
    though and may improve remote socket performance.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Benoit Canet <benoit at irqsave.net>
    Reviewed-by: Daniel P. Berrange <berrange at redhat.com>

diff --git a/net/socket.c b/net/socket.c
index d8b35a2..b0c83e0 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -438,6 +438,9 @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer,
     s->fd = fd;
     s->listen_fd = -1;
 
+    /* Disable Nagle algorithm on TCP sockets to reduce latency */
+    socket_set_nodelay(fd);
+
     if (is_connected) {
         net_socket_connect(s);
     } else {
commit ea804cadf867a0521b9069193db339d041a40689
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Mar 24 08:08:36 2013 +0100

    block: Add options QDict to bdrv_file_open() prototypes (fix MinGW build)
    
    The new parameter is unused yet.
    
    This part was missing in commit 787e4a8500020695eb391e2f1cc4767ee071d441.
    
    Cc: Kevin Wolf <kwolf at redhat.com>
    Cc: Eric Blake <eblake at redhat.com>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/raw-win32.c b/block/raw-win32.c
index 18e0068..ece2f1a 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -221,7 +221,8 @@ static void raw_parse_flags(int flags, int *access_flags, DWORD *overlapped)
     }
 }
 
-static int raw_open(BlockDriverState *bs, const char *filename, int flags)
+static int raw_open(BlockDriverState *bs, const char *filename,
+                    QDict *options, int flags)
 {
     BDRVRawState *s = bs->opaque;
     int access_flags;
@@ -494,7 +495,8 @@ static int hdev_probe_device(const char *filename)
     return 0;
 }
 
-static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
+static int hdev_open(BlockDriverState *bs, const char *filename,
+                     QDict *options, int flags)
 {
     BDRVRawState *s = bs->opaque;
     int access_flags, create_flags;
commit d43731c75830dc63ae94282d84208a5652095bb7
Author: Liu Yuan <tailai.ly at taobao.com>
Date:   Sun Mar 24 15:41:15 2013 +0800

    rbd: fix compile error
    
    Commit 787e4a85 [block: Add options QDict to bdrv_file_open() prototypes] didn't
    update rbd.c accordingly.
    
    Cc: Kevin Wolf <kwolf at redhat.com>
    Cc: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/rbd.c b/block/rbd.c
index 8cd10a7..1a8ea6d 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -441,7 +441,8 @@ static int qemu_rbd_aio_flush_cb(void *opaque)
     return (s->qemu_aio_count > 0);
 }
 
-static int qemu_rbd_open(BlockDriverState *bs, const char *filename, int flags)
+static int qemu_rbd_open(BlockDriverState *bs, const char *filename,
+                         QDict *options, int flags)
 {
     BDRVRBDState *s = bs->opaque;
     char pool[RBD_MAX_POOL_NAME_SIZE];
commit 0099cd43ecf07710a608db5ca0945758514a14c2
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Mar 25 09:13:18 2013 +0100

    ipxe: update binaries
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/pc-bios/efi-e1000.rom b/pc-bios/efi-e1000.rom
index 7dfcea3..21b880a 100644
Binary files a/pc-bios/efi-e1000.rom and b/pc-bios/efi-e1000.rom differ
diff --git a/pc-bios/efi-eepro100.rom b/pc-bios/efi-eepro100.rom
index e5134a2..1799c38 100644
Binary files a/pc-bios/efi-eepro100.rom and b/pc-bios/efi-eepro100.rom differ
diff --git a/pc-bios/efi-ne2k_pci.rom b/pc-bios/efi-ne2k_pci.rom
index 8aa11c3..5d1b38b 100644
Binary files a/pc-bios/efi-ne2k_pci.rom and b/pc-bios/efi-ne2k_pci.rom differ
diff --git a/pc-bios/efi-pcnet.rom b/pc-bios/efi-pcnet.rom
index 200b5d2..79fa7a9 100644
Binary files a/pc-bios/efi-pcnet.rom and b/pc-bios/efi-pcnet.rom differ
diff --git a/pc-bios/efi-rtl8139.rom b/pc-bios/efi-rtl8139.rom
index 8bcd3c7..0b78f1a 100644
Binary files a/pc-bios/efi-rtl8139.rom and b/pc-bios/efi-rtl8139.rom differ
diff --git a/pc-bios/efi-virtio.rom b/pc-bios/efi-virtio.rom
index 25c5c69..e6b2bf7 100644
Binary files a/pc-bios/efi-virtio.rom and b/pc-bios/efi-virtio.rom differ
commit 95ca557d5cfc1ef69ba9708ded552f389afe643d
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Mar 25 09:07:40 2013 +0100

    ipxe: disable two second timeout
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/roms/Makefile b/roms/Makefile
index 3dc5609..7a228ae 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -57,13 +57,13 @@ lgplvgabios-%:
 
 pxerom: $(patsubst %,pxe-rom-%,$(pxerom_variants))
 
-pxe-rom-%:
+pxe-rom-%: ipxe/src/config/local/general.h
 	make -C ipxe/src bin/$(VID)$(DID).rom
 	cp ipxe/src/bin/$(VID)$(DID).rom ../pc-bios/pxe-$*.rom
 
 efirom: $(patsubst %,efi-rom-%,$(pxerom_variants))
 
-efi-rom-%:
+efi-rom-%: ipxe/src/config/local/general.h
 	make -C ipxe/src bin/$(VID)$(DID).rom
 	make -C ipxe/src bin-i386-efi/$(VID)$(DID).efidrv
 	make -C ipxe/src bin-x86_64-efi/$(VID)$(DID).efidrv
@@ -72,3 +72,6 @@ efi-rom-%:
 		-ec ipxe/src/bin-i386-efi/$(VID)$(DID).efidrv \
 		-ec ipxe/src/bin-x86_64-efi/$(VID)$(DID).efidrv \
 		-o ../pc-bios/efi-$*.rom
+
+ipxe/src/config/local/%: config.ipxe.%
+	cp $< $@
diff --git a/roms/config.ipxe.general.h b/roms/config.ipxe.general.h
new file mode 100644
index 0000000..b3fce53
--- /dev/null
+++ b/roms/config.ipxe.general.h
@@ -0,0 +1,2 @@
+#undef BANNER_TIMEOUT
+#define BANNER_TIMEOUT 0
commit fe6344a05fba26e16863fefcb823242e579b0991
Author: Anthony Green <green at moxielogic.com>
Date:   Sun Mar 24 00:43:38 2013 -0400

    Remove device_tree.o from hw/moxie/Makefile.objs.
    
    Here's a fix for the build problem identified by Aurelien Jarno here:
    http://lists.gnu.org/archive/html/qemu-devel/2013-03/msg04177.html
    
    Signed-off-by: Anthony Green <green at moxielogic.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/moxie/Makefile.objs b/hw/moxie/Makefile.objs
index d0772d1..a5f1742 100644
--- a/hw/moxie/Makefile.objs
+++ b/hw/moxie/Makefile.objs
@@ -1,6 +1,5 @@
 # moxie boards
 obj-y = serial.o mc146818rtc.o vga.o
-obj-$(CONFIG_FDT) += device_tree.o
 
 obj-y := $(addprefix ../,$(obj-y))
 obj-y += moxiesim.o
commit 2d497542e1ee66598be8bb7ce6a4606d664417ac
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Mar 21 09:13:33 2013 -0700

    tcg-optimize: Fold sub r,0,x to neg r,x
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/optimize.c b/tcg/optimize.c
index bc6e5c1..1b6644c 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -576,7 +576,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
             break;
         }
 
-        /* Simplify expressions for "shift/rot r, 0, a => movi r, 0" */
+        /* Simplify expressions for "shift/rot r, 0, a => movi r, 0",
+           and "sub r, 0, a => neg r, a" case.  */
         switch (op) {
         CASE_OP_32_64(shl):
         CASE_OP_32_64(shr):
@@ -592,6 +593,37 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                 continue;
             }
             break;
+        CASE_OP_32_64(sub):
+            {
+                TCGOpcode neg_op;
+                bool have_neg;
+
+                if (temps[args[2]].state == TCG_TEMP_CONST) {
+                    /* Proceed with possible constant folding. */
+                    break;
+                }
+                if (op == INDEX_op_sub_i32) {
+                    neg_op = INDEX_op_neg_i32;
+                    have_neg = TCG_TARGET_HAS_neg_i32;
+                } else {
+                    neg_op = INDEX_op_neg_i64;
+                    have_neg = TCG_TARGET_HAS_neg_i64;
+                }
+                if (!have_neg) {
+                    break;
+                }
+                if (temps[args[1]].state == TCG_TEMP_CONST
+                    && temps[args[1]].val == 0) {
+                    s->gen_opc_buf[op_index] = neg_op;
+                    reset_temp(args[0]);
+                    gen_args[0] = args[0];
+                    gen_args[1] = args[2];
+                    args += 3;
+                    gen_args += 2;
+                    continue;
+                }
+            }
+            break;
         default:
             break;
         }
commit 4980ef9e3e12be3b4ef9092abc2d5a665199b422
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Mar 19 12:11:56 2013 -0700

    target-i386: Don't modify env->eflags around cpu_dump_state
    
    We can compute the value in cpu_dump_state anyway, and gratuitous
    modifications to eflags creates heisenbugs.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpu-exec.c b/cpu-exec.c
index b87c1c0..e74e556 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -571,10 +571,7 @@ int cpu_exec(CPUArchState *env)
                 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
                     /* restore flags in standard format */
 #if defined(TARGET_I386)
-                    env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
-                        | (DF & DF_MASK);
                     log_cpu_state(env, CPU_DUMP_CCOP);
-                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
 #elif defined(TARGET_M68K)
                     cpu_m68k_flush_flags(env, env->cc_op);
                     env->cc_op = CC_OP_FLAGS;
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 9449a0c..282494f 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -189,7 +189,7 @@ void cpu_dump_state(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
 
     cpu_synchronize_state(env);
 
-    eflags = env->eflags;
+    eflags = cpu_compute_eflags(env);
 #ifdef TARGET_X86_64
     if (env->hflags & HF_CS64_MASK) {
         cpu_fprintf(f,
commit c53de1a2896ccc9ab18bb9c2f1a2f7b93629b564
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Mar 19 09:40:53 2013 -0700

    target-i386: Fix flags computation for ADOX
    
    When starting from CC_OP_DYNAMIC, and issuing adox before adcx,
    a typo used the wrong value for the resulting CC_OP.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Reported-by: Torbjorn Granlund <tg at gmplib.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index c9cc2ff..7239696 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -4200,7 +4200,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                         carry_in = carry_out;
                         break;
                     default:
-                        end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADCOX);
+                        end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
                         break;
                     }
                     /* If we can't reuse carry-out, get it out of EFLAGS.  */
commit d15a9c2390889623a681b4d0bc56371b4d25893c
Author: Anthony Green <green at moxielogic.com>
Date:   Mon Mar 18 15:49:25 2013 -0400

    Add top level changes for moxie
    
    Signed-off-by: Anthony Green <green at moxielogic.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/MAINTAINERS b/MAINTAINERS
index 0ca7e1d..db14ffc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -91,6 +91,11 @@ M: Aurelien Jarno <aurelien at aurel32.net>
 S: Odd Fixes
 F: target-mips/
 
+Moxie
+M: Anthony Green <green at moxielogic.com>
+S: Maintained
+F: target-moxie/
+
 PowerPC
 M: Alexander Graf <agraf at suse.de>
 L: qemu-ppc at nongnu.org
diff --git a/arch_init.c b/arch_init.c
index 98e2bc6..e8ade9e 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -85,6 +85,8 @@ int graphic_depth = 15;
 #define QEMU_ARCH QEMU_ARCH_MICROBLAZE
 #elif defined(TARGET_MIPS)
 #define QEMU_ARCH QEMU_ARCH_MIPS
+#elif defined(TARGET_MOXIE)
+#define QEMU_ARCH QEMU_ARCH_MOXIE
 #elif defined(TARGET_OPENRISC)
 #define QEMU_ARCH QEMU_ARCH_OPENRISC
 #elif defined(TARGET_PPC)
diff --git a/configure b/configure
index bfc4dc6..f2af714 100755
--- a/configure
+++ b/configure
@@ -961,6 +961,7 @@ mips-softmmu \
 mipsel-softmmu \
 mips64-softmmu \
 mips64el-softmmu \
+moxie-softmmu \
 or32-softmmu \
 ppc-softmmu \
 ppcemb-softmmu \
@@ -3947,7 +3948,7 @@ target_arch2=`echo $target | cut -d '-' -f 1`
 target_bigendian="no"
 
 case "$target_arch2" in
-  armeb|lm32|m68k|microblaze|mips|mipsn32|mips64|or32|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
+  armeb|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or32|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
   target_bigendian=yes
   ;;
 esac
@@ -4051,6 +4052,8 @@ case "$target_arch2" in
     echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak
     target_long_alignment=8
   ;;
+  moxie)
+  ;;
   or32)
     TARGET_ARCH=openrisc
     TARGET_BASE_ARCH=openrisc
@@ -4288,6 +4291,10 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
     echo "CONFIG_MIPS_DIS=y"  >> $config_target_mak
     echo "CONFIG_MIPS_DIS=y"  >> config-all-disas.mak
   ;;
+  moxie*)
+    echo "CONFIG_MOXIE_DIS=y"  >> $config_target_mak
+    echo "CONFIG_MOXIE_DIS=y"  >> config-all-disas.mak
+  ;;
   or32)
     echo "CONFIG_OPENRISC_DIS=y"  >> $config_target_mak
     echo "CONFIG_OPENRISC_DIS=y"  >> config-all-disas.mak
diff --git a/cpu-exec.c b/cpu-exec.c
index 94fedc5..b87c1c0 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -240,6 +240,7 @@ int cpu_exec(CPUArchState *env)
 #elif defined(TARGET_LM32)
 #elif defined(TARGET_MICROBLAZE)
 #elif defined(TARGET_MIPS)
+#elif defined(TARGET_MOXIE)
 #elif defined(TARGET_OPENRISC)
 #elif defined(TARGET_SH4)
 #elif defined(TARGET_CRIS)
@@ -692,6 +693,7 @@ int cpu_exec(CPUArchState *env)
               | env->cc_dest | (env->cc_x << 4);
 #elif defined(TARGET_MICROBLAZE)
 #elif defined(TARGET_MIPS)
+#elif defined(TARGET_MOXIE)
 #elif defined(TARGET_OPENRISC)
 #elif defined(TARGET_SH4)
 #elif defined(TARGET_ALPHA)
diff --git a/default-configs/moxie-softmmu.mak b/default-configs/moxie-softmmu.mak
new file mode 100644
index 0000000..8ede8d5
--- /dev/null
+++ b/default-configs/moxie-softmmu.mak
@@ -0,0 +1 @@
+# Default configuration for moxie-softmmu
diff --git a/qapi-schema.json b/qapi-schema.json
index fdaa9da..088f4e1 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2994,9 +2994,9 @@
 ##
 { 'enum': 'TargetType',
   'data': [ 'alpha', 'arm', 'cris', 'i386', 'lm32', 'm68k', 'microblazeel',
-            'microblaze', 'mips64el', 'mips64', 'mipsel', 'mips', 'or32',
-            'ppc64', 'ppcemb', 'ppc', 's390x', 'sh4eb', 'sh4', 'sparc64',
-            'sparc', 'unicore32', 'x86_64', 'xtensaeb', 'xtensa' ] }
+            'microblaze', 'mips64el', 'mips64', 'mipsel', 'mips', 'moxie',
+            'or32', 'ppc64', 'ppcemb', 'ppc', 's390x', 'sh4eb', 'sh4',
+            'sparc64', 'sparc', 'unicore32', 'x86_64', 'xtensaeb', 'xtensa' ] }
 
 ##
 # @TargetInfo:
commit a360d965821870fa1dbb3effdf7436b715ad3358
Author: Anthony Green <green at moxielogic.com>
Date:   Mon Mar 18 15:49:24 2013 -0400

    Add sample moxie system
    
    Signed-off-by: Anthony Green <green at moxielogic.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/moxie/Makefile.objs b/hw/moxie/Makefile.objs
new file mode 100644
index 0000000..d0772d1
--- /dev/null
+++ b/hw/moxie/Makefile.objs
@@ -0,0 +1,6 @@
+# moxie boards
+obj-y = serial.o mc146818rtc.o vga.o
+obj-$(CONFIG_FDT) += device_tree.o
+
+obj-y := $(addprefix ../,$(obj-y))
+obj-y += moxiesim.o
diff --git a/hw/moxie/moxiesim.c b/hw/moxie/moxiesim.c
new file mode 100644
index 0000000..e1e88a9
--- /dev/null
+++ b/hw/moxie/moxiesim.c
@@ -0,0 +1,174 @@
+/*
+ * QEMU/moxiesim emulation
+ *
+ * Emulates a very simple machine model similiar to the one use by the
+ * GDB moxie simulator.
+ *
+ * Copyright (c) 2008, 2009, 2010, 2013 Anthony Green
+ *
+ * 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/sysbus.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/serial.h"
+#include "exec/address-spaces.h"
+
+#define PHYS_MEM_BASE 0x80000000
+
+typedef struct {
+    uint64_t ram_size;
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *initrd_filename;
+} LoaderParams;
+
+static void load_kernel(MoxieCPU *cpu, LoaderParams *loader_params)
+{
+    uint64_t entry, kernel_low, kernel_high;
+    long kernel_size;
+    long initrd_size;
+    ram_addr_t initrd_offset;
+
+    kernel_size = load_elf(loader_params->kernel_filename,  NULL, NULL,
+                           &entry, &kernel_low, &kernel_high, 1,
+                           ELF_MACHINE, 0);
+
+    if (!kernel_size) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                loader_params->kernel_filename);
+        exit(1);
+    }
+
+    /* load initrd */
+    initrd_size = 0;
+    initrd_offset = 0;
+    if (loader_params->initrd_filename) {
+        initrd_size = get_image_size(loader_params->initrd_filename);
+        if (initrd_size > 0) {
+            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK)
+              & TARGET_PAGE_MASK;
+            if (initrd_offset + initrd_size > loader_params->ram_size) {
+                fprintf(stderr,
+                        "qemu: memory too small for initial ram disk '%s'\n",
+                        loader_params->initrd_filename);
+                exit(1);
+            }
+            initrd_size = load_image_targphys(loader_params->initrd_filename,
+                                              initrd_offset,
+                                              ram_size);
+        }
+        if (initrd_size == (target_ulong)-1) {
+            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                    loader_params->initrd_filename);
+            exit(1);
+        }
+    }
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    MoxieCPU *cpu = opaque;
+
+    cpu_reset(CPU(cpu));
+}
+
+static inline DeviceState *
+moxie_intc_create(hwaddr base, qemu_irq irq, int kind_of_intr)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "moxie,intc");
+    qdev_prop_set_uint32(dev, "kind-of-intr", kind_of_intr);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
+    return dev;
+}
+
+static void moxiesim_init(QEMUMachineInitArgs *args)
+{
+    MoxieCPU *cpu = NULL;
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    CPUMoxieState *env;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *rom = g_new(MemoryRegion, 1);
+    hwaddr ram_base = 0x200000;
+    LoaderParams loader_params;
+
+    /* Init CPUs. */
+    if (cpu_model == NULL) {
+        cpu_model = "MoxieLite-moxie-cpu";
+    }
+    cpu = cpu_moxie_init(cpu_model);
+    if (!cpu) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    qemu_register_reset(main_cpu_reset, cpu);
+
+    /* Allocate RAM. */
+    memory_region_init_ram(ram, "moxiesim.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(address_space_mem, ram_base, ram);
+
+    memory_region_init_ram(rom, "moxie.rom", 128*0x1000);
+    vmstate_register_ram_global(rom);
+    memory_region_add_subregion(get_system_memory(), 0x1000, rom);
+
+    if (kernel_filename) {
+        loader_params.ram_size = ram_size;
+        loader_params.kernel_filename = kernel_filename;
+        loader_params.kernel_cmdline = kernel_cmdline;
+        loader_params.initrd_filename = initrd_filename;
+        load_kernel(cpu, &loader_params);
+    }
+
+    /* A single 16450 sits at offset 0x3f8.  */
+    if (serial_hds[0]) {
+        serial_mm_init(address_space_mem, 0x3f8, 0, env->irq[4],
+                       8000000/16, serial_hds[0], DEVICE_LITTLE_ENDIAN);
+    }
+}
+
+static QEMUMachine moxiesim_machine = {
+    .name = "moxiesim",
+    .desc = "Moxie simulator platform",
+    .init = moxiesim_init,
+    .is_default = 1,
+};
+
+static void moxie_machine_init(void)
+{
+    qemu_register_machine(&moxiesim_machine);
+}
+
+machine_init(moxie_machine_init)
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index 5fc780c..8c8d78e 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -20,6 +20,7 @@ enum {
     QEMU_ARCH_XTENSA = 4096,
     QEMU_ARCH_OPENRISC = 8192,
     QEMU_ARCH_UNICORE32 = 0x4000,
+    QEMU_ARCH_MOXIE = 0x8000,
 };
 
 extern const uint32_t arch_type;
commit bd86a88eedf3fd4ff55664cfabea7d6400e5fbda
Author: Anthony Green <green at moxielogic.com>
Date:   Mon Mar 18 15:49:23 2013 -0400

    Add moxie disassembler
    
    Signed-off-by: Anthony Green <green at moxielogic.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/disas.c b/disas.c
index a46faee..74d3ba0 100644
--- a/disas.c
+++ b/disas.c
@@ -256,6 +256,9 @@ void target_disas(FILE *out, CPUArchState *env, target_ulong code,
 #elif defined(TARGET_MICROBLAZE)
     s.info.mach = bfd_arch_microblaze;
     print_insn = print_insn_microblaze;
+#elif defined(TARGET_MOXIE)
+    s.info.mach = bfd_arch_moxie;
+    print_insn = print_insn_moxie;
 #elif defined(TARGET_LM32)
     s.info.mach = bfd_mach_lm32;
     print_insn = print_insn_lm32;
@@ -462,6 +465,9 @@ void monitor_disas(Monitor *mon, CPUArchState *env,
 #elif defined(TARGET_S390X)
     s.info.mach = bfd_mach_s390_64;
     print_insn = print_insn_s390;
+#elif defined(TARGET_MOXIE)
+    s.info.mach = bfd_arch_moxie;
+    print_insn = print_insn_moxie;
 #elif defined(TARGET_LM32)
     s.info.mach = bfd_mach_lm32;
     print_insn = print_insn_lm32;
diff --git a/disas/Makefile.objs b/disas/Makefile.objs
index ed75f9a..3b1e77a 100644
--- a/disas/Makefile.objs
+++ b/disas/Makefile.objs
@@ -7,6 +7,7 @@ common-obj-$(CONFIG_IA64_DIS) += ia64.o
 common-obj-$(CONFIG_M68K_DIS) += m68k.o
 common-obj-$(CONFIG_MICROBLAZE_DIS) += microblaze.o
 common-obj-$(CONFIG_MIPS_DIS) += mips.o
+common-obj-$(CONFIG_MOXIE_DIS) += moxie.o
 common-obj-$(CONFIG_PPC_DIS) += ppc.o
 common-obj-$(CONFIG_S390_DIS) += s390.o
 common-obj-$(CONFIG_SH4_DIS) += sh4.o
diff --git a/disas/moxie.c b/disas/moxie.c
new file mode 100644
index 0000000..4c5f180
--- /dev/null
+++ b/disas/moxie.c
@@ -0,0 +1,360 @@
+/* Disassemble moxie instructions.
+   Copyright (c) 2009  Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   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/>. */
+
+#include <stdio.h>
+#define STATIC_TABLE
+#define DEFINE_TABLE
+
+#include "disas/bfd.h"
+
+static void *stream;
+
+/* Form 1 instructions come in different flavors:
+
+   Some have no arguments                          (MOXIE_F1_NARG)
+   Some only use the A operand                     (MOXIE_F1_A)
+   Some use A and B registers                      (MOXIE_F1_AB)
+   Some use A and consume a 4 byte immediate value (MOXIE_F1_A4)
+   Some use just a 4 byte immediate value          (MOXIE_F1_4)
+   Some use just a 4 byte memory address           (MOXIE_F1_M)
+   Some use B and an indirect A                    (MOXIE_F1_AiB)
+   Some use A and an indirect B                    (MOXIE_F1_ABi)
+   Some consume a 4 byte immediate value and use X (MOXIE_F1_4A)
+   Some use B and an indirect A plus 4 bytes       (MOXIE_F1_AiB4)
+   Some use A and an indirect B plus 4 bytes       (MOXIE_F1_ABi4)
+
+   Form 2 instructions also come in different flavors:
+
+   Some have no arguments                          (MOXIE_F2_NARG)
+   Some use the A register and an 8-bit value      (MOXIE_F2_A8V)
+
+   Form 3 instructions also come in different flavors:
+
+   Some have no arguments                          (MOXIE_F3_NARG)
+   Some have a 10-bit PC relative operand          (MOXIE_F3_PCREL).  */
+
+#define MOXIE_F1_NARG 0x100
+#define MOXIE_F1_A    0x101
+#define MOXIE_F1_AB   0x102
+/* #define MOXIE_F1_ABC  0x103 */
+#define MOXIE_F1_A4   0x104
+#define MOXIE_F1_4    0x105
+#define MOXIE_F1_AiB  0x106
+#define MOXIE_F1_ABi  0x107
+#define MOXIE_F1_4A   0x108
+#define MOXIE_F1_AiB4 0x109
+#define MOXIE_F1_ABi4 0x10a
+#define MOXIE_F1_M    0x10b
+
+#define MOXIE_F2_NARG 0x200
+#define MOXIE_F2_A8V  0x201
+
+#define MOXIE_F3_NARG  0x300
+#define MOXIE_F3_PCREL 0x301
+
+typedef struct moxie_opc_info_t {
+    short         opcode;
+    unsigned      itype;
+    const char *  name;
+} moxie_opc_info_t;
+
+extern const moxie_opc_info_t moxie_form1_opc_info[64];
+extern const moxie_opc_info_t moxie_form2_opc_info[4];
+extern const moxie_opc_info_t moxie_form3_opc_info[16];
+
+/* The moxie processor's 16-bit instructions come in two forms:
+
+   FORM 1 instructions start with a 0 bit...
+
+   0oooooooaaaabbbb
+   0              F
+
+   ooooooo - form 1 opcode number
+   aaaa    - operand A
+   bbbb    - operand B
+
+   FORM 2 instructions start with bits "10"...
+
+   10ooaaaavvvvvvvv
+   0              F
+
+   oo       - form 2 opcode number
+   aaaa     - operand A
+   vvvvvvvv - 8-bit immediate value
+
+   FORM 3 instructions start with a bits "11"...
+
+   11oooovvvvvvvvvv
+   0              F
+
+   oooo         - form 3 opcode number
+   vvvvvvvvvv   - 10-bit immediate value.  */
+
+const moxie_opc_info_t moxie_form1_opc_info[64] =
+    {
+        { 0x00, MOXIE_F1_NARG, "nop" },
+        { 0x01, MOXIE_F1_A4,   "ldi.l" },
+        { 0x02, MOXIE_F1_AB,   "mov" },
+        { 0x03, MOXIE_F1_M,    "jsra" },
+        { 0x04, MOXIE_F1_NARG, "ret" },
+        { 0x05, MOXIE_F1_AB,   "add.l" },
+        { 0x06, MOXIE_F1_AB,   "push" },
+        { 0x07, MOXIE_F1_AB,   "pop" },
+        { 0x08, MOXIE_F1_A4,   "lda.l" },
+        { 0x09, MOXIE_F1_4A,   "sta.l" },
+        { 0x0a, MOXIE_F1_ABi,  "ld.l" },
+        { 0x0b, MOXIE_F1_AiB,  "st.l" },
+        { 0x0c, MOXIE_F1_ABi4, "ldo.l" },
+        { 0x0d, MOXIE_F1_AiB4, "sto.l" },
+        { 0x0e, MOXIE_F1_AB,   "cmp" },
+        { 0x0f, MOXIE_F1_NARG, "bad" },
+        { 0x10, MOXIE_F1_NARG, "bad" },
+        { 0x11, MOXIE_F1_NARG, "bad" },
+        { 0x12, MOXIE_F1_NARG, "bad" },
+        { 0x13, MOXIE_F1_NARG, "bad" },
+        { 0x14, MOXIE_F1_NARG, "bad" },
+        { 0x15, MOXIE_F1_NARG, "bad" },
+        { 0x16, MOXIE_F1_NARG, "bad" },
+        { 0x17, MOXIE_F1_NARG, "bad" },
+        { 0x18, MOXIE_F1_NARG, "bad" },
+        { 0x19, MOXIE_F1_A,    "jsr" },
+        { 0x1a, MOXIE_F1_M,    "jmpa" },
+        { 0x1b, MOXIE_F1_A4,   "ldi.b" },
+        { 0x1c, MOXIE_F1_ABi,  "ld.b" },
+        { 0x1d, MOXIE_F1_A4,   "lda.b" },
+        { 0x1e, MOXIE_F1_AiB,  "st.b" },
+        { 0x1f, MOXIE_F1_4A,   "sta.b" },
+        { 0x20, MOXIE_F1_A4,   "ldi.s" },
+        { 0x21, MOXIE_F1_ABi,  "ld.s" },
+        { 0x22, MOXIE_F1_A4,   "lda.s" },
+        { 0x23, MOXIE_F1_AiB,  "st.s" },
+        { 0x24, MOXIE_F1_4A,   "sta.s" },
+        { 0x25, MOXIE_F1_A,    "jmp" },
+        { 0x26, MOXIE_F1_AB,   "and" },
+        { 0x27, MOXIE_F1_AB,   "lshr" },
+        { 0x28, MOXIE_F1_AB,   "ashl" },
+        { 0x29, MOXIE_F1_AB,   "sub.l" },
+        { 0x2a, MOXIE_F1_AB,   "neg" },
+        { 0x2b, MOXIE_F1_AB,   "or" },
+        { 0x2c, MOXIE_F1_AB,   "not" },
+        { 0x2d, MOXIE_F1_AB,   "ashr" },
+        { 0x2e, MOXIE_F1_AB,   "xor" },
+        { 0x2f, MOXIE_F1_AB,   "mul.l" },
+        { 0x30, MOXIE_F1_4,    "swi" },
+        { 0x31, MOXIE_F1_AB,   "div.l" },
+        { 0x32, MOXIE_F1_AB,   "udiv.l" },
+        { 0x33, MOXIE_F1_AB,   "mod.l" },
+        { 0x34, MOXIE_F1_AB,   "umod.l" },
+        { 0x35, MOXIE_F1_NARG, "brk" },
+        { 0x36, MOXIE_F1_ABi4, "ldo.b" },
+        { 0x37, MOXIE_F1_AiB4, "sto.b" },
+        { 0x38, MOXIE_F1_ABi4, "ldo.s" },
+        { 0x39, MOXIE_F1_AiB4, "sto.s" },
+        { 0x3a, MOXIE_F1_NARG, "bad" },
+        { 0x3b, MOXIE_F1_NARG, "bad" },
+        { 0x3c, MOXIE_F1_NARG, "bad" },
+        { 0x3d, MOXIE_F1_NARG, "bad" },
+        { 0x3e, MOXIE_F1_NARG, "bad" },
+        { 0x3f, MOXIE_F1_NARG, "bad" }
+    };
+
+const moxie_opc_info_t moxie_form2_opc_info[4] =
+    {
+        { 0x00, MOXIE_F2_A8V,  "inc" },
+        { 0x01, MOXIE_F2_A8V,  "dec" },
+        { 0x02, MOXIE_F2_A8V,  "gsr" },
+        { 0x03, MOXIE_F2_A8V,  "ssr" }
+    };
+
+const moxie_opc_info_t moxie_form3_opc_info[16] =
+    {
+        { 0x00, MOXIE_F3_PCREL,"beq" },
+        { 0x01, MOXIE_F3_PCREL,"bne" },
+        { 0x02, MOXIE_F3_PCREL,"blt" },
+        { 0x03, MOXIE_F3_PCREL,"bgt" },
+        { 0x04, MOXIE_F3_PCREL,"bltu" },
+        { 0x05, MOXIE_F3_PCREL,"bgtu" },
+        { 0x06, MOXIE_F3_PCREL,"bge" },
+        { 0x07, MOXIE_F3_PCREL,"ble" },
+        { 0x08, MOXIE_F3_PCREL,"bgeu" },
+        { 0x09, MOXIE_F3_PCREL,"bleu" },
+        { 0x0a, MOXIE_F3_NARG, "bad" },
+        { 0x0b, MOXIE_F3_NARG, "bad" },
+        { 0x0c, MOXIE_F3_NARG, "bad" },
+        { 0x0d, MOXIE_F3_NARG, "bad" },
+        { 0x0e, MOXIE_F3_NARG, "bad" },
+        { 0x0f, MOXIE_F3_NARG, "bad" }
+    };
+
+/* Macros to extract operands from the instruction word.  */
+#define OP_A(i) ((i >> 4) & 0xf)
+#define OP_B(i) (i & 0xf)
+#define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1)
+
+static const char * reg_names[16] =
+    { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5",
+      "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" };
+
+int
+print_insn_moxie(bfd_vma addr, struct disassemble_info * info)
+{
+    int length = 2;
+    int status;
+    stream = info->stream;
+    const moxie_opc_info_t * opcode;
+    bfd_byte buffer[4];
+    unsigned short iword;
+    fprintf_function fpr = info->fprintf_func;
+
+    if ((status = info->read_memory_func(addr, buffer, 2, info)))
+        goto fail;
+    iword = (bfd_getb16(buffer) >> 16);
+
+    /* Form 1 instructions have the high bit set to 0.  */
+    if ((iword & (1<<15)) == 0) {
+        /* Extract the Form 1 opcode.  */
+        opcode = &moxie_form1_opc_info[iword >> 8];
+        switch (opcode->itype) {
+        case MOXIE_F1_NARG:
+            fpr(stream, "%s", opcode->name);
+            break;
+        case MOXIE_F1_A:
+            fpr(stream, "%s\t%s", opcode->name,
+                reg_names[OP_A(iword)]);
+            break;
+        case MOXIE_F1_AB:
+            fpr(stream, "%s\t%s, %s", opcode->name,
+                reg_names[OP_A(iword)],
+                reg_names[OP_B(iword)]);
+            break;
+        case MOXIE_F1_A4:
+            {
+                unsigned imm;
+                if ((status = info->read_memory_func(addr + 2, buffer, 4, info)))
+                    goto fail;
+                imm = bfd_getb32(buffer);
+                fpr(stream, "%s\t%s, 0x%x", opcode->name,
+                    reg_names[OP_A(iword)], imm);
+                length = 6;
+            }
+            break;
+        case MOXIE_F1_4:
+            {
+                unsigned imm;
+                if ((status = info->read_memory_func(addr + 2, buffer, 4, info)))
+                    goto fail;
+                imm = bfd_getb32(buffer);
+                fpr(stream, "%s\t0x%x", opcode->name, imm);
+                length = 6;
+            }
+            break;
+        case MOXIE_F1_M:
+            {
+                unsigned imm;
+                if ((status = info->read_memory_func(addr + 2, buffer, 4, info)))
+                    goto fail;
+                imm = bfd_getb32(buffer);
+                fpr(stream, "%s\t", opcode->name);
+                info->print_address_func((bfd_vma) imm, info);
+                length = 6;
+            }
+            break;
+        case MOXIE_F1_AiB:
+            fpr (stream, "%s\t(%s), %s", opcode->name,
+                 reg_names[OP_A(iword)], reg_names[OP_B(iword)]);
+            break;
+        case MOXIE_F1_ABi:
+            fpr(stream, "%s\t%s, (%s)", opcode->name,
+                reg_names[OP_A(iword)], reg_names[OP_B(iword)]);
+            break;
+        case MOXIE_F1_4A:
+            {
+                unsigned imm;
+                if ((status = info->read_memory_func(addr + 2, buffer, 4, info)))
+                    goto fail;
+                imm = bfd_getb32(buffer);
+                fpr(stream, "%s\t0x%x, %s",
+                    opcode->name, imm, reg_names[OP_A(iword)]);
+                length = 6;
+            }
+            break;
+        case MOXIE_F1_AiB4:
+            {
+                unsigned imm;
+                if ((status = info->read_memory_func(addr+2, buffer, 4, info)))
+                    goto fail;
+                imm = bfd_getb32(buffer);
+                fpr(stream, "%s\t0x%x(%s), %s", opcode->name,
+                    imm,
+                    reg_names[OP_A(iword)],
+                    reg_names[OP_B(iword)]);
+                length = 6;
+            }
+            break;
+        case MOXIE_F1_ABi4:
+            {
+                unsigned imm;
+                if ((status = info->read_memory_func(addr+2, buffer, 4, info)))
+                    goto fail;
+                imm = bfd_getb32(buffer);
+                fpr(stream, "%s\t%s, 0x%x(%s)",
+                    opcode->name,
+                    reg_names[OP_A(iword)],
+                    imm,
+                    reg_names[OP_B(iword)]);
+                length = 6;
+            }
+            break;
+        default:
+            abort();
+        }
+    }
+    else if ((iword & (1<<14)) == 0) {
+        /* Extract the Form 2 opcode.  */
+        opcode = &moxie_form2_opc_info[(iword >> 12) & 3];
+        switch (opcode->itype) {
+        case MOXIE_F2_A8V:
+            fpr(stream, "%s\t%s, 0x%x",
+                opcode->name,
+                reg_names[(iword >> 8) & 0xf],
+                iword & ((1 << 8) - 1));
+            break;
+        case MOXIE_F2_NARG:
+            fpr(stream, "%s", opcode->name);
+            break;
+        default:
+            abort();
+        }
+    } else {
+        /* Extract the Form 3 opcode.  */
+        opcode = &moxie_form3_opc_info[(iword >> 10) & 15];
+        switch (opcode->itype) {
+        case MOXIE_F3_PCREL:
+            fpr(stream, "%s\t", opcode->name);
+            info->print_address_func((bfd_vma) (addr + INST2OFFSET(iword) + 2),
+                                     info);
+            break;
+        default:
+            abort();
+        }
+    }
+
+    return length;
+
+ fail:
+    info->memory_error_func(status, addr, info);
+    return -1;
+}
diff --git a/include/disas/bfd.h b/include/disas/bfd.h
index 3944b3c..803b6ef 100644
--- a/include/disas/bfd.h
+++ b/include/disas/bfd.h
@@ -218,6 +218,7 @@ enum bfd_architecture
 #define bfd_mach_cris_v32      32
 #define bfd_mach_cris_v10_v32  1032
   bfd_arch_microblaze, /* Xilinx MicroBlaze.  */
+  bfd_arch_moxie,      /* The Moxie core.  */
   bfd_arch_ia64,      /* HP/Intel ia64 */
 #define bfd_mach_ia64_elf64    64
 #define bfd_mach_ia64_elf32    32
@@ -392,6 +393,7 @@ int print_insn_m32r             (bfd_vma, disassemble_info*);
 int print_insn_m88k             (bfd_vma, disassemble_info*);
 int print_insn_mn10200          (bfd_vma, disassemble_info*);
 int print_insn_mn10300          (bfd_vma, disassemble_info*);
+int print_insn_moxie            (bfd_vma, disassemble_info*);
 int print_insn_ns32k            (bfd_vma, disassemble_info*);
 int print_insn_big_powerpc      (bfd_vma, disassemble_info*);
 int print_insn_little_powerpc   (bfd_vma, disassemble_info*);
commit 525bd324c282c68ff95e389acd647ae115fd003c
Author: Anthony Green <green at moxielogic.com>
Date:   Mon Mar 18 15:49:22 2013 -0400

    Add moxie target code
    
    Signed-off-by: Anthony Green <green at moxielogic.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-moxie/Makefile.objs b/target-moxie/Makefile.objs
new file mode 100644
index 0000000..6381d4d
--- /dev/null
+++ b/target-moxie/Makefile.objs
@@ -0,0 +1,2 @@
+obj-y += translate.o helper.o machine.o cpu.o machine.o
+obj-$(CONFIG_SOFTMMU) += mmu.o
diff --git a/target-moxie/cpu.c b/target-moxie/cpu.c
new file mode 100644
index 0000000..c17d3f0
--- /dev/null
+++ b/target-moxie/cpu.c
@@ -0,0 +1,172 @@
+/*
+ * QEMU Moxie CPU
+ *
+ * Copyright (c) 2013 Anthony Green
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "migration/vmstate.h"
+#include "machine.h"
+
+static void moxie_cpu_reset(CPUState *s)
+{
+    MoxieCPU *cpu = MOXIE_CPU(s);
+    MoxieCPUClass *mcc = MOXIE_CPU_GET_CLASS(cpu);
+    CPUMoxieState *env = &cpu->env;
+
+    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+        qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
+        log_cpu_state(env, 0);
+    }
+
+    mcc->parent_reset(s);
+
+    memset(env, 0, offsetof(CPUMoxieState, breakpoints));
+    env->pc = 0x1000;
+
+    tlb_flush(env, 1);
+}
+
+static void moxie_cpu_realizefn(DeviceState *dev, Error **errp)
+{
+    MoxieCPU *cpu = MOXIE_CPU(dev);
+    MoxieCPUClass *occ = MOXIE_CPU_GET_CLASS(dev);
+
+    qemu_init_vcpu(&cpu->env);
+    cpu_reset(CPU(cpu));
+
+    occ->parent_realize(dev, errp);
+}
+
+static void moxie_cpu_initfn(Object *obj)
+{
+    CPUState *cs = CPU(obj);
+    MoxieCPU *cpu = MOXIE_CPU(obj);
+    static int inited;
+
+    cs->env_ptr = &cpu->env;
+    cpu_exec_init(&cpu->env);
+
+    if (tcg_enabled() && !inited) {
+        inited = 1;
+        moxie_translate_init();
+    }
+}
+
+static ObjectClass *moxie_cpu_class_by_name(const char *cpu_model)
+{
+    ObjectClass *oc;
+
+    if (cpu_model == NULL) {
+        return NULL;
+    }
+
+    oc = object_class_by_name(cpu_model);
+    if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_MOXIE_CPU) ||
+                       object_class_is_abstract(oc))) {
+        return NULL;
+    }
+    return oc;
+}
+
+static void moxie_cpu_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    CPUClass *cc = CPU_CLASS(oc);
+    MoxieCPUClass *mcc = MOXIE_CPU_CLASS(oc);
+
+    mcc->parent_realize = dc->realize;
+    dc->realize = moxie_cpu_realizefn;
+
+    mcc->parent_reset = cc->reset;
+    cc->reset = moxie_cpu_reset;
+
+    cc->class_by_name = moxie_cpu_class_by_name;
+
+    dc->vmsd = &vmstate_moxie_cpu;
+}
+
+static void moxielite_initfn(Object *obj)
+{
+    /* Set cpu feature flags */
+}
+
+static void moxie_any_initfn(Object *obj)
+{
+    /* Set cpu feature flags */
+}
+
+typedef struct MoxieCPUInfo {
+    const char *name;
+    void (*initfn)(Object *obj);
+} MoxieCPUInfo;
+
+static const MoxieCPUInfo moxie_cpus[] = {
+    { .name = "MoxieLite",      .initfn = moxielite_initfn },
+    { .name = "any",            .initfn = moxie_any_initfn },
+};
+
+MoxieCPU *cpu_moxie_init(const char *cpu_model)
+{
+    MoxieCPU *cpu;
+    ObjectClass *oc;
+
+    oc = moxie_cpu_class_by_name(cpu_model);
+    if (oc == NULL) {
+        return NULL;
+    }
+    cpu = MOXIE_CPU(object_new(object_class_get_name(oc)));
+    cpu->env.cpu_model_str = cpu_model;
+
+    object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
+
+    return cpu;
+}
+
+static void cpu_register(const MoxieCPUInfo *info)
+{
+    TypeInfo type_info = {
+        .parent = TYPE_MOXIE_CPU,
+        .instance_size = sizeof(MoxieCPU),
+        .instance_init = info->initfn,
+        .class_size = sizeof(MoxieCPUClass),
+    };
+
+    type_info.name = g_strdup_printf("%s-" TYPE_MOXIE_CPU, info->name);
+    type_register(&type_info);
+    g_free((void *)type_info.name);
+}
+
+static const TypeInfo moxie_cpu_type_info = {
+    .name = TYPE_MOXIE_CPU,
+    .parent = TYPE_CPU,
+    .instance_size = sizeof(MoxieCPU),
+    .instance_init = moxie_cpu_initfn,
+    .class_size = sizeof(MoxieCPUClass),
+    .class_init = moxie_cpu_class_init,
+};
+
+static void moxie_cpu_register_types(void)
+{
+    int i;
+    type_register_static(&moxie_cpu_type_info);
+    for (i = 0; i < ARRAY_SIZE(moxie_cpus); i++) {
+        cpu_register(&moxie_cpus[i]);
+    }
+}
+
+type_init(moxie_cpu_register_types)
diff --git a/target-moxie/cpu.h b/target-moxie/cpu.h
new file mode 100644
index 0000000..b96236f
--- /dev/null
+++ b/target-moxie/cpu.h
@@ -0,0 +1,167 @@
+/*
+ *  Moxie emulation
+ *
+ *  Copyright (c) 2008, 2010, 2013 Anthony Green
+ *
+ * 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 General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _CPU_MOXIE_H
+#define _CPU_MOXIE_H
+
+#include "config.h"
+#include "qemu-common.h"
+
+#define TARGET_LONG_BITS 32
+
+#define CPUArchState struct CPUMoxieState
+
+#define TARGET_HAS_ICE 1
+
+#define CPU_SAVE_VERSION 1
+
+#define ELF_MACHINE     0xFEED /* EM_MOXIE */
+
+#define MOXIE_EX_DIV0        0
+#define MOXIE_EX_BAD         1
+#define MOXIE_EX_IRQ         2
+#define MOXIE_EX_SWI         3
+#define MOXIE_EX_MMU_MISS    4
+#define MOXIE_EX_BREAK      16
+
+#include "exec/cpu-defs.h"
+#include "fpu/softfloat.h"
+
+#define TARGET_PAGE_BITS 12     /* 4k */
+
+#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+
+#define NB_MMU_MODES 1
+
+typedef struct CPUMoxieState {
+
+    uint32_t flags;               /* general execution flags */
+    uint32_t gregs[16];           /* general registers */
+    uint32_t sregs[256];          /* special registers */
+    uint32_t pc;                  /* program counter */
+    /* Instead of saving the cc value, we save the cmp arguments
+       and compute cc on demand.  */
+    uint32_t cc_a;                /* reg a for condition code calculation */
+    uint32_t cc_b;                /* reg b for condition code calculation */
+
+    void *irq[8];
+
+    CPU_COMMON
+
+} CPUMoxieState;
+
+#include "qom/cpu.h"
+
+#define TYPE_MOXIE_CPU "moxie-cpu"
+
+#define MOXIE_CPU_CLASS(klass) \
+    OBJECT_CLASS_CHECK(MoxieCPUClass, (klass), TYPE_MOXIE_CPU)
+#define MOXIE_CPU(obj) \
+    OBJECT_CHECK(MoxieCPU, (obj), TYPE_MOXIE_CPU)
+#define MOXIE_CPU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(MoxieCPUClass, (obj), TYPE_MOXIE_CPU)
+
+/**
+ * MoxieCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A Moxie CPU model.
+ */
+typedef struct MoxieCPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+
+    DeviceRealize parent_realize;
+    void (*parent_reset)(CPUState *cpu);
+} MoxieCPUClass;
+
+/**
+ * MoxieCPU:
+ * @env: #CPUMoxieState
+ *
+ * A Moxie CPU.
+ */
+typedef struct MoxieCPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUMoxieState env;
+} MoxieCPU;
+
+static inline MoxieCPU *moxie_env_get_cpu(CPUMoxieState *env)
+{
+    return MOXIE_CPU(container_of(env, MoxieCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(moxie_env_get_cpu(e))
+
+#define ENV_OFFSET offsetof(MoxieCPU, env)
+
+MoxieCPU *cpu_moxie_init(const char *cpu_model);
+int cpu_moxie_exec(CPUMoxieState *s);
+void do_interrupt(CPUMoxieState *env);
+void moxie_translate_init(void);
+int cpu_moxie_signal_handler(int host_signum, void *pinfo,
+                             void *puc);
+
+static inline CPUMoxieState *cpu_init(const char *cpu_model)
+{
+    MoxieCPU *cpu = cpu_moxie_init(cpu_model);
+    if (cpu == NULL) {
+        return NULL;
+    }
+    return &cpu->env;
+}
+
+#define cpu_exec cpu_moxie_exec
+#define cpu_gen_code cpu_moxie_gen_code
+#define cpu_signal_handler cpu_moxie_signal_handler
+
+static inline int cpu_mmu_index(CPUMoxieState *env)
+{
+    return 0;
+}
+
+#include "exec/cpu-all.h"
+#include "exec/exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUMoxieState *env, TranslationBlock *tb)
+{
+    env->pc = tb->pc;
+}
+
+static inline void cpu_get_tb_cpu_state(CPUMoxieState *env, target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *pc = env->pc;
+    *cs_base = 0;
+    *flags = 0;
+}
+
+static inline int cpu_has_work(CPUState *cpu)
+{
+    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
+}
+
+int cpu_moxie_handle_mmu_fault(CPUMoxieState *env, target_ulong address,
+                               int rw, int mmu_idx);
+
+#endif /* _CPU_MOXIE_H */
diff --git a/target-moxie/helper.c b/target-moxie/helper.c
new file mode 100644
index 0000000..8604ce8
--- /dev/null
+++ b/target-moxie/helper.c
@@ -0,0 +1,171 @@
+/*
+ *  Moxie helper routines.
+ *
+ *  Copyright (c) 2008, 2009, 2010, 2013 Anthony Green
+ *
+ * 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 General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "config.h"
+#include "cpu.h"
+#include "mmu.h"
+#include "exec/exec-all.h"
+#include "qemu/host-utils.h"
+#include "helper.h"
+
+#define MMUSUFFIX _mmu
+
+#define SHIFT 0
+#include "exec/softmmu_template.h"
+
+#define SHIFT 1
+#include "exec/softmmu_template.h"
+
+#define SHIFT 2
+#include "exec/softmmu_template.h"
+
+#define SHIFT 3
+#include "exec/softmmu_template.h"
+
+/* 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) */
+void tlb_fill(CPUMoxieState *env, target_ulong addr, int is_write, int mmu_idx,
+              uintptr_t retaddr)
+{
+    int ret;
+
+    ret = cpu_moxie_handle_mmu_fault(env, addr, is_write, mmu_idx);
+    if (unlikely(ret)) {
+        if (retaddr) {
+            cpu_restore_state(env, retaddr);
+        }
+    }
+    cpu_loop_exit(env);
+}
+
+void helper_raise_exception(CPUMoxieState *env, int ex)
+{
+    env->exception_index = ex;
+    /* Stash the exception type.  */
+    env->sregs[2] = ex;
+    /* Stash the address where the exception occurred.  */
+    cpu_restore_state(env, GETPC());
+    env->sregs[5] = env->pc;
+    /* Jump the the exception handline routine.  */
+    env->pc = env->sregs[1];
+    cpu_loop_exit(env);
+}
+
+uint32_t helper_div(CPUMoxieState *env, uint32_t a, uint32_t b)
+{
+    if (unlikely(b == 0)) {
+        helper_raise_exception(env, MOXIE_EX_DIV0);
+        return 0;
+    }
+    if (unlikely(a == INT_MIN && b == -1)) {
+        return INT_MIN;
+    }
+
+    return (int32_t)a / (int32_t)b;
+}
+
+uint32_t helper_udiv(CPUMoxieState *env, uint32_t a, uint32_t b)
+{
+    if (unlikely(b == 0)) {
+        helper_raise_exception(env, MOXIE_EX_DIV0);
+        return 0;
+    }
+    return a / b;
+}
+
+void helper_debug(CPUMoxieState *env)
+{
+    env->exception_index = EXCP_DEBUG;
+    cpu_loop_exit(env);
+}
+
+#if defined(CONFIG_USER_ONLY)
+
+void do_interrupt(CPUState *env)
+{
+    env->exception_index = -1;
+}
+
+int cpu_moxie_handle_mmu_fault(CPUMoxieState *env, target_ulong address,
+                               int rw, int mmu_idx)
+{
+    env->exception_index = 0xaa;
+    env->debug1 = address;
+    cpu_dump_state(env, stderr, fprintf, 0);
+    return 1;
+}
+
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+{
+    return addr;
+}
+
+#else /* !CONFIG_USER_ONLY */
+
+int cpu_moxie_handle_mmu_fault(CPUMoxieState *env, target_ulong address,
+                               int rw, int mmu_idx)
+{
+    MoxieMMUResult res;
+    int prot, miss;
+    target_ulong phy;
+    int r = 1;
+
+    address &= TARGET_PAGE_MASK;
+    prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+    miss = moxie_mmu_translate(&res, env, address, rw, mmu_idx);
+    if (miss) {
+        /* handle the miss.  */
+        phy = 0;
+        env->exception_index = MOXIE_EX_MMU_MISS;
+    } else {
+        phy = res.phy;
+        r = 0;
+    }
+    tlb_set_page(env, address, phy, prot, mmu_idx, TARGET_PAGE_SIZE);
+    return r;
+}
+
+
+void do_interrupt(CPUMoxieState *env)
+{
+    switch (env->exception_index) {
+    case MOXIE_EX_BREAK:
+        break;
+    default:
+        break;
+    }
+}
+
+hwaddr cpu_get_phys_page_debug(CPUMoxieState *env, target_ulong addr)
+{
+    uint32_t phy = addr;
+    MoxieMMUResult res;
+    int miss;
+    miss = moxie_mmu_translate(&res, env, addr, 0, 0);
+    if (!miss) {
+        phy = res.phy;
+    }
+    return phy;
+}
+#endif
diff --git a/target-moxie/helper.h b/target-moxie/helper.h
new file mode 100644
index 0000000..3aa5549
--- /dev/null
+++ b/target-moxie/helper.h
@@ -0,0 +1,9 @@
+#include "exec/def-helper.h"
+
+DEF_HELPER_2(raise_exception, void, env, int)
+DEF_HELPER_1(debug, void, env)
+
+DEF_HELPER_FLAGS_3(div, TCG_CALL_NO_WG, i32, env, i32, i32)
+DEF_HELPER_FLAGS_3(udiv, TCG_CALL_NO_WG, i32, env, i32, i32)
+
+#include "exec/def-helper.h"
diff --git a/target-moxie/machine.c b/target-moxie/machine.c
new file mode 100644
index 0000000..5bfdb28
--- /dev/null
+++ b/target-moxie/machine.c
@@ -0,0 +1,28 @@
+#include "hw/hw.h"
+#include "hw/boards.h"
+
+const VMStateDescription vmstate_moxie_cpu = {
+    .name = "cpu",
+    .version_id = CPU_SAVE_VERSION,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(flags, CPUMoxieState),
+        VMSTATE_UINT32_ARRAY(gregs, CPUMoxieState, 16),
+        VMSTATE_UINT32_ARRAY(sregs, CPUMoxieState, 256),
+        VMSTATE_UINT32(pc, CPUMoxieState),
+        VMSTATE_UINT32(cc_a, CPUMoxieState),
+        VMSTATE_UINT32(cc_b, CPUMoxieState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+void cpu_save(QEMUFile *f, void *opaque)
+{
+    vmstate_save_state(f, &vmstate_moxie_cpu, opaque);
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+    return vmstate_load_state(f, &vmstate_moxie_cpu, opaque, version_id);
+}
diff --git a/target-moxie/machine.h b/target-moxie/machine.h
new file mode 100644
index 0000000..a1b7290
--- /dev/null
+++ b/target-moxie/machine.h
@@ -0,0 +1 @@
+extern const VMStateDescription vmstate_moxie_cpu;
diff --git a/target-moxie/mmu.c b/target-moxie/mmu.c
new file mode 100644
index 0000000..5217eed
--- /dev/null
+++ b/target-moxie/mmu.c
@@ -0,0 +1,36 @@
+/*
+ *  Moxie mmu emulation.
+ *
+ *  Copyright (c) 2008, 2013 Anthony Green
+ *
+ * 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 General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "config.h"
+#include "cpu.h"
+#include "mmu.h"
+#include "exec/exec-all.h"
+
+int moxie_mmu_translate(MoxieMMUResult *res,
+                       CPUMoxieState *env, uint32_t vaddr,
+                       int rw, int mmu_idx)
+{
+    /* Perform no translation yet.  */
+    res->phy = vaddr;
+    return 0;
+}
diff --git a/target-moxie/mmu.h b/target-moxie/mmu.h
new file mode 100644
index 0000000..e01ffc2
--- /dev/null
+++ b/target-moxie/mmu.h
@@ -0,0 +1,19 @@
+#define MOXIE_MMU_ERR_EXEC  0
+#define MOXIE_MMU_ERR_READ  1
+#define MOXIE_MMU_ERR_WRITE 2
+#define MOXIE_MMU_ERR_FLUSH 3
+
+typedef struct {
+    uint32_t phy;
+    uint32_t pfn;
+    int g:1;
+    int v:1;
+    int k:1;
+    int w:1;
+    int e:1;
+    int cause_op;
+} MoxieMMUResult;
+
+int moxie_mmu_translate(MoxieMMUResult *res,
+                        CPUMoxieState *env, uint32_t vaddr,
+                        int rw, int mmu_idx);
diff --git a/target-moxie/translate.c b/target-moxie/translate.c
new file mode 100644
index 0000000..34f166e
--- /dev/null
+++ b/target-moxie/translate.c
@@ -0,0 +1,926 @@
+/*
+ *  Moxie emulation for qemu: main translation routines.
+ *
+ *  Copyright (c) 2009, 2013 Anthony Green
+ *
+ * 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 General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* For information on the Moxie architecture, see
+ *    http://moxielogic.org/wiki
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "disas/disas.h"
+#include "tcg-op.h"
+
+#include "helper.h"
+#define GEN_HELPER 1
+#include "helper.h"
+
+/* This is the state at translation time.  */
+typedef struct DisasContext {
+    struct TranslationBlock *tb;
+    target_ulong pc, saved_pc;
+    uint32_t opcode;
+    uint32_t fp_status;
+    /* Routine used to access memory */
+    int memidx;
+    int bstate;
+    target_ulong btarget;
+    int singlestep_enabled;
+} DisasContext;
+
+enum {
+    BS_NONE     = 0, /* We go out of the TB without reaching a branch or an
+                      * exception condition */
+    BS_STOP     = 1, /* We want to stop translation for any reason */
+    BS_BRANCH   = 2, /* We reached a branch condition     */
+    BS_EXCP     = 3, /* We reached an exception condition */
+};
+
+static TCGv cpu_pc;
+static TCGv cpu_gregs[16];
+static TCGv_ptr cpu_env;
+static TCGv cc_a, cc_b;
+
+#include "exec/gen-icount.h"
+
+#define REG(x) (cpu_gregs[x])
+
+/* Extract the signed 10-bit offset from a 16-bit branch
+   instruction.  */
+static int extract_branch_offset(int opcode)
+{
+  return (((signed short)((opcode & ((1 << 10) - 1)) << 6)) >> 6) << 1;
+}
+
+void cpu_dump_state(CPUArchState *env, FILE *f, fprintf_function cpu_fprintf,
+                    int flags)
+{
+    int i;
+    cpu_fprintf(f, "pc=0x%08x\n", env->pc);
+    cpu_fprintf(f, "$fp=0x%08x $sp=0x%08x $r0=0x%08x $r1=0x%08x\n",
+                env->gregs[0], env->gregs[1], env->gregs[2], env->gregs[3]);
+    for (i = 4; i < 16; i += 4) {
+        cpu_fprintf(f, "$r%d=0x%08x $r%d=0x%08x $r%d=0x%08x $r%d=0x%08x\n",
+                    i-2, env->gregs[i], i-1, env->gregs[i + 1],
+                    i, env->gregs[i + 2], i+1, env->gregs[i + 3]);
+    }
+    for (i = 4; i < 16; i += 4) {
+        cpu_fprintf(f, "sr%d=0x%08x sr%d=0x%08x sr%d=0x%08x sr%d=0x%08x\n",
+                    i-2, env->sregs[i], i-1, env->sregs[i + 1],
+                    i, env->sregs[i + 2], i+1, env->sregs[i + 3]);
+    }
+}
+
+void moxie_translate_init(void)
+{
+    int i;
+    static int done_init;
+    static const char * const gregnames[16] = {
+        "$fp", "$sp", "$r0", "$r1",
+        "$r2", "$r3", "$r4", "$r5",
+        "$r6", "$r7", "$r8", "$r9",
+        "$r10", "$r11", "$r12", "$r13"
+    };
+
+    if (done_init) {
+        return;
+    }
+    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    cpu_pc = tcg_global_mem_new_i32(TCG_AREG0,
+                                    offsetof(CPUMoxieState, pc), "$pc");
+    for (i = 0; i < 16; i++)
+        cpu_gregs[i] = tcg_global_mem_new_i32(TCG_AREG0,
+                                              offsetof(CPUMoxieState, gregs[i]),
+                                              gregnames[i]);
+
+    cc_a = tcg_global_mem_new_i32(TCG_AREG0,
+                                  offsetof(CPUMoxieState, cc_a), "cc_a");
+    cc_b = tcg_global_mem_new_i32(TCG_AREG0,
+                                  offsetof(CPUMoxieState, cc_b), "cc_b");
+
+    done_init = 1;
+}
+
+static inline void gen_goto_tb(CPUMoxieState *env, DisasContext *ctx,
+                               int n, target_ulong dest)
+{
+    TranslationBlock *tb;
+    tb = ctx->tb;
+
+    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
+        !ctx->singlestep_enabled) {
+        tcg_gen_goto_tb(n);
+        tcg_gen_movi_i32(cpu_pc, dest);
+        tcg_gen_exit_tb((long) tb + n);
+    } else {
+        tcg_gen_movi_i32(cpu_pc, dest);
+        if (ctx->singlestep_enabled) {
+            gen_helper_debug(cpu_env);
+        }
+        tcg_gen_exit_tb(0);
+    }
+}
+
+static int decode_opc(MoxieCPU *cpu, DisasContext *ctx)
+{
+    CPUMoxieState *env = &cpu->env;
+
+    /* Local cache for the instruction opcode.  */
+    int opcode;
+    /* Set the default instruction length.  */
+    int length = 2;
+
+    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
+        tcg_gen_debug_insn_start(ctx->pc);
+    }
+
+    /* Examine the 16-bit opcode.  */
+    opcode = ctx->opcode;
+
+    /* Decode instruction.  */
+    if (opcode & (1 << 15)) {
+        if (opcode & (1 << 14)) {
+            /* This is a Form 3 instruction.  */
+            int inst = (opcode >> 10 & 0xf);
+
+#define BRANCH(cond)                                                         \
+    do {                                                                     \
+        int l1 = gen_new_label();                                            \
+        tcg_gen_brcond_i32(cond, cc_a, cc_b, l1);                            \
+        gen_goto_tb(env, ctx, 1, ctx->pc+2);                                 \
+        gen_set_label(l1);                                                   \
+        gen_goto_tb(env, ctx, 0, extract_branch_offset(opcode) + ctx->pc+2); \
+        ctx->bstate = BS_BRANCH;                                             \
+    } while (0)
+
+            switch (inst) {
+            case 0x00: /* beq */
+                BRANCH(TCG_COND_EQ);
+                break;
+            case 0x01: /* bne */
+                BRANCH(TCG_COND_NE);
+                break;
+            case 0x02: /* blt */
+                BRANCH(TCG_COND_LT);
+                break;
+            case 0x03: /* bgt */
+                BRANCH(TCG_COND_GT);
+                break;
+            case 0x04: /* bltu */
+                BRANCH(TCG_COND_LTU);
+                break;
+            case 0x05: /* bgtu */
+                BRANCH(TCG_COND_GTU);
+                break;
+            case 0x06: /* bge */
+                BRANCH(TCG_COND_GE);
+                break;
+            case 0x07: /* ble */
+                BRANCH(TCG_COND_LE);
+                break;
+            case 0x08: /* bgeu */
+                BRANCH(TCG_COND_GEU);
+                break;
+            case 0x09: /* bleu */
+                BRANCH(TCG_COND_LEU);
+                break;
+            default:
+                {
+                    TCGv temp = tcg_temp_new_i32();
+                    tcg_gen_movi_i32(cpu_pc, ctx->pc);
+                    tcg_gen_movi_i32(temp, MOXIE_EX_BAD);
+                    gen_helper_raise_exception(cpu_env, temp);
+                    tcg_temp_free_i32(temp);
+                }
+                break;
+            }
+        } else {
+            /* This is a Form 2 instruction.  */
+            int inst = (opcode >> 12 & 0x3);
+            switch (inst) {
+            case 0x00: /* inc */
+                {
+                    int a = (opcode >> 8) & 0xf;
+                    unsigned int v = (opcode & 0xff);
+                    tcg_gen_addi_i32(REG(a), REG(a), v);
+                }
+                break;
+            case 0x01: /* dec */
+                {
+                    int a = (opcode >> 8) & 0xf;
+                    unsigned int v = (opcode & 0xff);
+                    tcg_gen_subi_i32(REG(a), REG(a), v);
+                }
+                break;
+            case 0x02: /* gsr */
+                {
+                    int a = (opcode >> 8) & 0xf;
+                    unsigned v = (opcode & 0xff);
+                    tcg_gen_ld_i32(REG(a), cpu_env,
+                                   offsetof(CPUMoxieState, sregs[v]));
+                }
+                break;
+            case 0x03: /* ssr */
+                {
+                    int a = (opcode >> 8) & 0xf;
+                    unsigned v = (opcode & 0xff);
+                    tcg_gen_st_i32(REG(a), cpu_env,
+                                   offsetof(CPUMoxieState, sregs[v]));
+                }
+                break;
+            default:
+                {
+                    TCGv temp = tcg_temp_new_i32();
+                    tcg_gen_movi_i32(cpu_pc, ctx->pc);
+                    tcg_gen_movi_i32(temp, MOXIE_EX_BAD);
+                    gen_helper_raise_exception(cpu_env, temp);
+                    tcg_temp_free_i32(temp);
+                }
+                break;
+            }
+        }
+    } else {
+        /* This is a Form 1 instruction.  */
+        int inst = opcode >> 8;
+        switch (inst) {
+        case 0x00: /* nop */
+            break;
+        case 0x01: /* ldi.l (immediate) */
+            {
+                int reg = (opcode >> 4) & 0xf;
+                int val = cpu_ldl_code(env, ctx->pc+2);
+                tcg_gen_movi_i32(REG(reg), val);
+                length = 6;
+            }
+            break;
+        case 0x02: /* mov (register-to-register) */
+            {
+                int dest  = (opcode >> 4) & 0xf;
+                int src = opcode & 0xf;
+                tcg_gen_mov_i32(REG(dest), REG(src));
+            }
+            break;
+        case 0x03: /* jsra */
+            {
+                TCGv t1 = tcg_temp_new_i32();
+                TCGv t2 = tcg_temp_new_i32();
+
+                tcg_gen_movi_i32(t1, ctx->pc + 6);
+
+                /* Make space for the static chain and return address.  */
+                tcg_gen_subi_i32(t2, REG(1), 8);
+                tcg_gen_mov_i32(REG(1), t2);
+                tcg_gen_qemu_st32(t1, REG(1), ctx->memidx);
+
+                /* Push the current frame pointer.  */
+                tcg_gen_subi_i32(t2, REG(1), 4);
+                tcg_gen_mov_i32(REG(1), t2);
+                tcg_gen_qemu_st32(REG(0), REG(1), ctx->memidx);
+
+                /* Set the pc and $fp.  */
+                tcg_gen_mov_i32(REG(0), REG(1));
+
+                gen_goto_tb(env, ctx, 0, cpu_ldl_code(env, ctx->pc+2));
+
+                tcg_temp_free_i32(t1);
+                tcg_temp_free_i32(t2);
+
+                ctx->bstate = BS_BRANCH;
+                length = 6;
+            }
+            break;
+        case 0x04: /* ret */
+            {
+                TCGv t1 = tcg_temp_new_i32();
+
+                /* The new $sp is the old $fp.  */
+                tcg_gen_mov_i32(REG(1), REG(0));
+
+                /* Pop the frame pointer.  */
+                tcg_gen_qemu_ld32u(REG(0), REG(1), ctx->memidx);
+                tcg_gen_addi_i32(t1, REG(1), 4);
+                tcg_gen_mov_i32(REG(1), t1);
+
+
+                /* Pop the return address and skip over the static chain
+                   slot.  */
+                tcg_gen_qemu_ld32u(cpu_pc, REG(1), ctx->memidx);
+                tcg_gen_addi_i32(t1, REG(1), 8);
+                tcg_gen_mov_i32(REG(1), t1);
+
+                tcg_temp_free_i32(t1);
+
+                /* Jump... */
+                tcg_gen_exit_tb(0);
+
+                ctx->bstate = BS_BRANCH;
+            }
+            break;
+        case 0x05: /* add.l */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                tcg_gen_add_i32(REG(a), REG(a), REG(b));
+            }
+            break;
+        case 0x06: /* push */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                TCGv t1 = tcg_temp_new_i32();
+                tcg_gen_subi_i32(t1, REG(a), 4);
+                tcg_gen_mov_i32(REG(a), t1);
+                tcg_gen_qemu_st32(REG(b), REG(a), ctx->memidx);
+                tcg_temp_free_i32(t1);
+            }
+            break;
+        case 0x07: /* pop */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+                TCGv t1 = tcg_temp_new_i32();
+
+                tcg_gen_qemu_ld32u(REG(b), REG(a), ctx->memidx);
+                tcg_gen_addi_i32(t1, REG(a), 4);
+                tcg_gen_mov_i32(REG(a), t1);
+                tcg_temp_free_i32(t1);
+            }
+            break;
+        case 0x08: /* lda.l */
+            {
+                int reg = (opcode >> 4) & 0xf;
+
+                TCGv ptr = tcg_temp_new_i32();
+                tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
+                tcg_gen_qemu_ld32u(REG(reg), ptr, ctx->memidx);
+                tcg_temp_free_i32(ptr);
+
+                length = 6;
+            }
+            break;
+        case 0x09: /* sta.l */
+            {
+                int val = (opcode >> 4) & 0xf;
+
+                TCGv ptr = tcg_temp_new_i32();
+                tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
+                tcg_gen_qemu_st32(REG(val), ptr, ctx->memidx);
+                tcg_temp_free_i32(ptr);
+
+                length = 6;
+            }
+            break;
+        case 0x0a: /* ld.l (register indirect) */
+            {
+                int src  = opcode & 0xf;
+                int dest = (opcode >> 4) & 0xf;
+
+                tcg_gen_qemu_ld32u(REG(dest), REG(src), ctx->memidx);
+            }
+            break;
+        case 0x0b: /* st.l */
+            {
+                int dest = (opcode >> 4) & 0xf;
+                int val  = opcode & 0xf;
+
+                tcg_gen_qemu_st32(REG(val), REG(dest), ctx->memidx);
+            }
+            break;
+        case 0x0c: /* ldo.l */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                TCGv t1 = tcg_temp_new_i32();
+                TCGv t2 = tcg_temp_new_i32();
+                tcg_gen_addi_i32(t1, REG(b), cpu_ldl_code(env, ctx->pc+2));
+                tcg_gen_qemu_ld32u(t2, t1, ctx->memidx);
+                tcg_gen_mov_i32(REG(a), t2);
+
+                tcg_temp_free_i32(t1);
+                tcg_temp_free_i32(t2);
+
+                length = 6;
+            }
+            break;
+        case 0x0d: /* sto.l */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                TCGv t1 = tcg_temp_new_i32();
+                TCGv t2 = tcg_temp_new_i32();
+                tcg_gen_addi_i32(t1, REG(a), cpu_ldl_code(env, ctx->pc+2));
+                tcg_gen_qemu_st32(REG(b), t1, ctx->memidx);
+
+                tcg_temp_free_i32(t1);
+                tcg_temp_free_i32(t2);
+
+                length = 6;
+            }
+            break;
+        case 0x0e: /* cmp */
+            {
+                int a  = (opcode >> 4) & 0xf;
+                int b  = opcode & 0xf;
+
+                tcg_gen_mov_i32(cc_a, REG(a));
+                tcg_gen_mov_i32(cc_b, REG(b));
+            }
+            break;
+        case 0x19: /* jsr */
+            {
+                int fnreg = (opcode >> 4) & 0xf;
+
+                /* Load the stack pointer into T0.  */
+                TCGv t1 = tcg_temp_new_i32();
+                TCGv t2 = tcg_temp_new_i32();
+
+                tcg_gen_movi_i32(t1, ctx->pc+2);
+
+                /* Make space for the static chain and return address.  */
+                tcg_gen_subi_i32(t2, REG(1), 8);
+                tcg_gen_mov_i32(REG(1), t2);
+                tcg_gen_qemu_st32(t1, REG(1), ctx->memidx);
+
+                /* Push the current frame pointer.  */
+                tcg_gen_subi_i32(t2, REG(1), 4);
+                tcg_gen_mov_i32(REG(1), t2);
+                tcg_gen_qemu_st32(REG(0), REG(1), ctx->memidx);
+
+                /* Set the pc and $fp.  */
+                tcg_gen_mov_i32(REG(0), REG(1));
+                tcg_gen_mov_i32(cpu_pc, REG(fnreg));
+                tcg_temp_free_i32(t1);
+                tcg_temp_free_i32(t2);
+                tcg_gen_exit_tb(0);
+                ctx->bstate = BS_BRANCH;
+            }
+            break;
+        case 0x1a: /* jmpa */
+            {
+                tcg_gen_movi_i32(cpu_pc, cpu_ldl_code(env, ctx->pc+2));
+                tcg_gen_exit_tb(0);
+                ctx->bstate = BS_BRANCH;
+                length = 6;
+            }
+            break;
+        case 0x1b: /* ldi.b (immediate) */
+            {
+                int reg = (opcode >> 4) & 0xf;
+                int val = cpu_ldl_code(env, ctx->pc+2);
+                tcg_gen_movi_i32(REG(reg), val);
+                length = 6;
+            }
+            break;
+        case 0x1c: /* ld.b (register indirect) */
+            {
+                int src  = opcode & 0xf;
+                int dest = (opcode >> 4) & 0xf;
+
+                tcg_gen_qemu_ld8u(REG(dest), REG(src), ctx->memidx);
+            }
+            break;
+        case 0x1d: /* lda.b */
+            {
+                int reg = (opcode >> 4) & 0xf;
+
+                TCGv ptr = tcg_temp_new_i32();
+                tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
+                tcg_gen_qemu_ld8u(REG(reg), ptr, ctx->memidx);
+                tcg_temp_free_i32(ptr);
+
+                length = 6;
+            }
+            break;
+        case 0x1e: /* st.b */
+            {
+                int dest = (opcode >> 4) & 0xf;
+                int val  = opcode & 0xf;
+
+                tcg_gen_qemu_st8(REG(val), REG(dest), ctx->memidx);
+            }
+            break;
+        case 0x1f: /* sta.b */
+            {
+                int val = (opcode >> 4) & 0xf;
+
+                TCGv ptr = tcg_temp_new_i32();
+                tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
+                tcg_gen_qemu_st8(REG(val), ptr, ctx->memidx);
+                tcg_temp_free_i32(ptr);
+
+                length = 6;
+            }
+            break;
+        case 0x20: /* ldi.s (immediate) */
+            {
+                int reg = (opcode >> 4) & 0xf;
+                int val = cpu_ldl_code(env, ctx->pc+2);
+                tcg_gen_movi_i32(REG(reg), val);
+                length = 6;
+            }
+            break;
+        case 0x21: /* ld.s (register indirect) */
+            {
+                int src  = opcode & 0xf;
+                int dest = (opcode >> 4) & 0xf;
+
+                tcg_gen_qemu_ld16u(REG(dest), REG(src), ctx->memidx);
+            }
+            break;
+        case 0x22: /* lda.s */
+            {
+                int reg = (opcode >> 4) & 0xf;
+
+                TCGv ptr = tcg_temp_new_i32();
+                tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
+                tcg_gen_qemu_ld16u(REG(reg), ptr, ctx->memidx);
+                tcg_temp_free_i32(ptr);
+
+                length = 6;
+            }
+            break;
+        case 0x23: /* st.s */
+            {
+                int dest = (opcode >> 4) & 0xf;
+                int val  = opcode & 0xf;
+
+                tcg_gen_qemu_st16(REG(val), REG(dest), ctx->memidx);
+            }
+            break;
+        case 0x24: /* sta.s */
+            {
+                int val = (opcode >> 4) & 0xf;
+
+                TCGv ptr = tcg_temp_new_i32();
+                tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
+                tcg_gen_qemu_st16(REG(val), ptr, ctx->memidx);
+                tcg_temp_free_i32(ptr);
+
+                length = 6;
+            }
+            break;
+        case 0x25: /* jmp */
+            {
+                int reg = (opcode >> 4) & 0xf;
+                tcg_gen_mov_i32(cpu_pc, REG(reg));
+                tcg_gen_exit_tb(0);
+                ctx->bstate = BS_BRANCH;
+            }
+            break;
+        case 0x26: /* and */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                tcg_gen_and_i32(REG(a), REG(a), REG(b));
+            }
+            break;
+        case 0x27: /* lshr */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                TCGv sv = tcg_temp_new_i32();
+                tcg_gen_andi_i32(sv, REG(b), 0x1f);
+                tcg_gen_shr_i32(REG(a), REG(a), sv);
+                tcg_temp_free_i32(sv);
+            }
+            break;
+        case 0x28: /* ashl */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                TCGv sv = tcg_temp_new_i32();
+                tcg_gen_andi_i32(sv, REG(b), 0x1f);
+                tcg_gen_shl_i32(REG(a), REG(a), sv);
+                tcg_temp_free_i32(sv);
+            }
+            break;
+        case 0x29: /* sub.l */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                tcg_gen_sub_i32(REG(a), REG(a), REG(b));
+            }
+            break;
+        case 0x2a: /* neg */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                tcg_gen_neg_i32(REG(a), REG(b));
+            }
+            break;
+        case 0x2b: /* or */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                tcg_gen_or_i32(REG(a), REG(a), REG(b));
+            }
+            break;
+        case 0x2c: /* not */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                tcg_gen_not_i32(REG(a), REG(b));
+            }
+            break;
+        case 0x2d: /* ashr */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                TCGv sv = tcg_temp_new_i32();
+                tcg_gen_andi_i32(sv, REG(b), 0x1f);
+                tcg_gen_sar_i32(REG(a), REG(a), sv);
+                tcg_temp_free_i32(sv);
+            }
+            break;
+        case 0x2e: /* xor */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                tcg_gen_xor_i32(REG(a), REG(a), REG(b));
+            }
+            break;
+        case 0x2f: /* mul.l */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                tcg_gen_mul_i32(REG(a), REG(a), REG(b));
+            }
+            break;
+        case 0x30: /* swi */
+            {
+                int val = cpu_ldl_code(env, ctx->pc+2);
+
+                TCGv temp = tcg_temp_new_i32();
+                tcg_gen_movi_i32(temp, val);
+                tcg_gen_st_i32(temp, cpu_env,
+                               offsetof(CPUMoxieState, sregs[3]));
+                tcg_gen_movi_i32(cpu_pc, ctx->pc);
+                tcg_gen_movi_i32(temp, MOXIE_EX_SWI);
+                gen_helper_raise_exception(cpu_env, temp);
+                tcg_temp_free_i32(temp);
+
+                length = 6;
+            }
+            break;
+        case 0x31: /* div.l */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+                tcg_gen_movi_i32(cpu_pc, ctx->pc);
+                gen_helper_div(REG(a), cpu_env, REG(a), REG(b));
+            }
+            break;
+        case 0x32: /* udiv.l */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+                tcg_gen_movi_i32(cpu_pc, ctx->pc);
+                gen_helper_udiv(REG(a), cpu_env, REG(a), REG(b));
+            }
+            break;
+        case 0x33: /* mod.l */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+                tcg_gen_rem_i32(REG(a), REG(a), REG(b));
+            }
+            break;
+        case 0x34: /* umod.l */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+                tcg_gen_remu_i32(REG(a), REG(a), REG(b));
+            }
+            break;
+        case 0x35: /* brk */
+            {
+                TCGv temp = tcg_temp_new_i32();
+                tcg_gen_movi_i32(cpu_pc, ctx->pc);
+                tcg_gen_movi_i32(temp, MOXIE_EX_BREAK);
+                gen_helper_raise_exception(cpu_env, temp);
+                tcg_temp_free_i32(temp);
+            }
+            break;
+        case 0x36: /* ldo.b */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                TCGv t1 = tcg_temp_new_i32();
+                TCGv t2 = tcg_temp_new_i32();
+                tcg_gen_addi_i32(t1, REG(b), cpu_ldl_code(env, ctx->pc+2));
+                tcg_gen_qemu_ld8u(t2, t1, ctx->memidx);
+                tcg_gen_mov_i32(REG(a), t2);
+
+                tcg_temp_free_i32(t1);
+                tcg_temp_free_i32(t2);
+
+                length = 6;
+            }
+            break;
+        case 0x37: /* sto.b */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                TCGv t1 = tcg_temp_new_i32();
+                TCGv t2 = tcg_temp_new_i32();
+                tcg_gen_addi_i32(t1, REG(a), cpu_ldl_code(env, ctx->pc+2));
+                tcg_gen_qemu_st8(REG(b), t1, ctx->memidx);
+
+                tcg_temp_free_i32(t1);
+                tcg_temp_free_i32(t2);
+
+                length = 6;
+            }
+            break;
+        case 0x38: /* ldo.s */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                TCGv t1 = tcg_temp_new_i32();
+                TCGv t2 = tcg_temp_new_i32();
+                tcg_gen_addi_i32(t1, REG(b), cpu_ldl_code(env, ctx->pc+2));
+                tcg_gen_qemu_ld16u(t2, t1, ctx->memidx);
+                tcg_gen_mov_i32(REG(a), t2);
+
+                tcg_temp_free_i32(t1);
+                tcg_temp_free_i32(t2);
+
+                length = 6;
+            }
+            break;
+        case 0x39: /* sto.s */
+            {
+                int a = (opcode >> 4) & 0xf;
+                int b = opcode & 0xf;
+
+                TCGv t1 = tcg_temp_new_i32();
+                TCGv t2 = tcg_temp_new_i32();
+                tcg_gen_addi_i32(t1, REG(a), cpu_ldl_code(env, ctx->pc+2));
+                tcg_gen_qemu_st16(REG(b), t1, ctx->memidx);
+                tcg_temp_free_i32(t1);
+                tcg_temp_free_i32(t2);
+
+                length = 6;
+            }
+            break;
+        default:
+            {
+                TCGv temp = tcg_temp_new_i32();
+                tcg_gen_movi_i32(cpu_pc, ctx->pc);
+                tcg_gen_movi_i32(temp, MOXIE_EX_BAD);
+                gen_helper_raise_exception(cpu_env, temp);
+                tcg_temp_free_i32(temp);
+             }
+            break;
+        }
+    }
+
+    return length;
+}
+
+/* generate intermediate code for basic block 'tb'.  */
+static void
+gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
+                               bool search_pc)
+{
+    DisasContext ctx;
+    target_ulong pc_start;
+    uint16_t *gen_opc_end;
+    CPUBreakpoint *bp;
+    int j, lj = -1;
+    CPUMoxieState *env = &cpu->env;
+    int num_insns;
+
+    pc_start = tb->pc;
+    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
+    ctx.pc = pc_start;
+    ctx.saved_pc = -1;
+    ctx.tb = tb;
+    ctx.memidx = 0;
+    ctx.singlestep_enabled = 0;
+    ctx.bstate = BS_NONE;
+    num_insns = 0;
+
+    gen_tb_start();
+    do {
+        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
+            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+                if (ctx.pc == bp->pc) {
+                    tcg_gen_movi_i32(cpu_pc, ctx.pc);
+                    gen_helper_debug(cpu_env);
+                    ctx.bstate = BS_EXCP;
+                    goto done_generating;
+                }
+            }
+        }
+
+        if (search_pc) {
+            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
+            if (lj < j) {
+                lj++;
+                while (lj < j) {
+                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
+                }
+            }
+            tcg_ctx.gen_opc_pc[lj] = ctx.pc;
+            tcg_ctx.gen_opc_instr_start[lj] = 1;
+            tcg_ctx.gen_opc_icount[lj] = num_insns;
+        }
+        ctx.opcode = cpu_lduw_code(env, ctx.pc);
+        ctx.pc += decode_opc(cpu, &ctx);
+        num_insns++;
+
+        if (env->singlestep_enabled) {
+            break;
+        }
+
+        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) {
+            break;
+        }
+    } while (ctx.bstate == BS_NONE && tcg_ctx.gen_opc_ptr < gen_opc_end);
+
+    if (env->singlestep_enabled) {
+        tcg_gen_movi_tl(cpu_pc, ctx.pc);
+        gen_helper_debug(cpu_env);
+    } else {
+        switch (ctx.bstate) {
+        case BS_STOP:
+        case BS_NONE:
+            gen_goto_tb(env, &ctx, 0, ctx.pc);
+            break;
+        case BS_EXCP:
+            tcg_gen_exit_tb(0);
+            break;
+        case BS_BRANCH:
+        default:
+            break;
+        }
+    }
+ done_generating:
+    gen_tb_end(tb, num_insns);
+    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
+    if (search_pc) {
+        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
+        lj++;
+        while (lj <= j) {
+            tcg_ctx.gen_opc_instr_start[lj++] = 0;
+        }
+    } else {
+        tb->size = ctx.pc - pc_start;
+        tb->icount = num_insns;
+    }
+}
+
+void gen_intermediate_code(CPUMoxieState *env, struct TranslationBlock *tb)
+{
+    gen_intermediate_code_internal(moxie_env_get_cpu(env), tb, false);
+}
+
+void gen_intermediate_code_pc(CPUMoxieState *env, struct TranslationBlock *tb)
+{
+    gen_intermediate_code_internal(moxie_env_get_cpu(env), tb, true);
+}
+
+void restore_state_to_opc(CPUMoxieState *env, TranslationBlock *tb, int pc_pos)
+{
+    env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+}
commit f7c61bf8fc1b05613b49d1dd2300d1a1fbc927de
Merge: d76bb73 b1e5fff
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 23 14:23:26 2013 +0000

    Merge branch 'for-upstream' of git://github.com/mwalle/qemu
    
    * 'for-upstream' of git://github.com/mwalle/qemu:
      configure: rename OpenGL feature to GLX
      configure: proper OpenGL/GLX probe
      target-lm32: use HELPER() macro
      target-lm32: flush tlb after clearing env
      target-lm32: remove dead code
      target-lm32: fix cmpgui and cmpgeui opcodes
      tests: tcg: lm32: add more test cases
      target-lm32: don't log cpu state in translation
      lm32_uart: fix receive buffering
      milkymist-uart: fix receive buffering
      lm32-dis: fix NULL pointer dereference
      target-lm32: fix debug memory access

commit d76bb73549fcac07524aea5135280ea533a94fd6
Merge: 52ae646 9ca3f7f
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Mar 22 21:43:57 2013 +0100

    Merge branch 'ppc-for-upstream' of git://github.com/agraf/qemu
    
    * 'ppc-for-upstream' of git://github.com/agraf/qemu: (58 commits)
      target-ppc: Use NARROW_MODE macro for tlbie
      target-ppc: Use NARROW_MODE macro for addresses
      target-ppc: Use NARROW_MODE macro for comparisons
      target-ppc: Use NARROW_MODE macro for branches
      target-ppc: Fix add and subf carry generation in narrow mode
      target-ppc: Use QOM method dispatch for MMU fault handling
      target-ppc: Move ppc tlb_fill implementation into mmu_helper.c
      target-ppc: Split user only code out of mmu_helper.c
      mmu-hash64: Implement Virtual Page Class Key Protection
      mmu-hash*: Merge translate and fault handling functions
      mmu-hash*: Don't use full ppc_hash{32, 64}_translate() path for get_phys_page_debug()
      mmu-hash*: Correctly mask RPN from hash PTE
      mmu-hash*: Clean up real address calculation
      mmu-hash*: Clean up PTE flags update
      mmu-hash64: Factor SLB N bit into permissions bits
      mmu-hash*: Clean up permission checking
      mmu-hash32: Remove nx from context structure
      mmu-hash*: Don't update PTE flags when permission is denied
      mmu-hash32: Don't look up page tables on BAT permission error
      mmu-hash32: Cleanup BAT lookup
      ...

commit 52ae646d4a3ebdcdcc973492c6a56f2c49b6578f
Author: Yeongkyoon Lee <yeongkyoon.lee at samsung.com>
Date:   Fri Mar 22 21:50:17 2013 +0900

    tcg: Fix occasional TCG broken problem when ldst optimization enabled
    
    is_tcg_gen_code() checks the upper limit of TCG generated code range wrong, so
    that TCG could get broken occasionally only when CONFIG_QEMU_LDST_OPTIMIZATION
    enabled. The reason is code_gen_buffer_max_size does not cover the upper range
    up to (TCG_MAX_OP_SIZE * OPC_BUF_SIZE), thus code_gen_buffer_max_size should be
    modified to code_gen_buffer_size.
    
    CC: qemu-stable at nongnu.org
    Signed-off-by: Yeongkyoon Lee <yeongkyoon.lee at samsung.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/translate-all.c b/translate-all.c
index 1f3237e..a98c646 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1308,11 +1308,11 @@ static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
 /* check whether the given addr is in TCG generated code buffer or not */
 bool is_tcg_gen_code(uintptr_t tc_ptr)
 {
-    /* This can be called during code generation, code_gen_buffer_max_size
+    /* This can be called during code generation, code_gen_buffer_size
        is used instead of code_gen_ptr for upper boundary checking */
     return (tc_ptr >= (uintptr_t)tcg_ctx.code_gen_buffer &&
             tc_ptr < (uintptr_t)(tcg_ctx.code_gen_buffer +
-                    tcg_ctx.code_gen_buffer_max_size));
+                    tcg_ctx.code_gen_buffer_size));
 }
 #endif
 
commit 3f08ffb4a4741d147634761dc053ed386243a0de
Merge: cecd77a 681e7ad
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Mar 22 13:08:01 2013 -0500

    Merge remote-tracking branch 'kwolf/for-anthony' into staging
    
    # By Kevin Wolf (12) and Peter Lieven (2)
    # Via Kevin Wolf
    * kwolf/for-anthony:
      nbd: Check against invalid option combinations
      nbd: Use default port if only host is specified
      block: Allow omitting the file name when using driver-specific options
      block: Make find_image_format safe with NULL filename
      block: Rename variable to avoid shadowing
      block: Introduce .bdrv_parse_filename callback
      nbd: Accept -drive options for the network connection
      nbd: Remove unused functions
      nbd: Keep hostname and port separate
      qemu-socket: Make socket_optslist public
      block: Pass bdrv_file_open() options to block drivers
      block: Add options QDict to bdrv_file_open() prototypes
      block: complete all IOs before resizing a device
      Revert "block: complete all IOs before .bdrv_truncate"

commit cecd77ae6df060bbe8f0eea6691112097e680a52
Merge: f930820 01ed1d5
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Mar 22 13:05:57 2013 -0500

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging
    
    # By liguang (2) and others
    # Via Stefan Hajnoczi
    * stefanha/trivial-patches:
      qdev: remove redundant abort()
      gitignore: ignore more files
      Use proper term in TCG README
      serial: Fix debug format strings
      Fix typos and misspellings
      Advertise --libdir in configure --help output
      memory: fix a bug of detection of memory region collision
      MinGW: Replace setsockopt by qemu_setsocketopt

commit f9308207040dc4a1484cee459bedaec03645b935
Merge: afed260 fe42d7f
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Mar 22 13:05:50 2013 -0500

    Merge remote-tracking branch 'cohuck/virtio-ccw-upstr' into staging
    
    # By Cornelia Huck
    # Via Cornelia Huck
    * cohuck/virtio-ccw-upstr:
      virtio-ccw, s390-virtio: Use generic virtio-blk macro.
      s390-virtio, virtio-ccw: Add config_wce for virtio-blk.
      virtio-ccw: Add missing blk chs properties.

commit 681e7ad024d80123a1ae8e35f86fb1a7f03b1bc9
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 20 19:23:23 2013 +0100

    nbd: Check against invalid option combinations
    
    A file name may only specified if no host or socket path is specified.
    The latter two may not appear at the same time either.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/block/nbd.c b/block/nbd.c
index 67f1df2..3d711b2 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -148,6 +148,15 @@ static void nbd_parse_filename(const char *filename, QDict *options,
     const char *host_spec;
     const char *unixpath;
 
+    if (qdict_haskey(options, "host")
+        || qdict_haskey(options, "port")
+        || qdict_haskey(options, "path"))
+    {
+        error_setg(errp, "host/port/path and a file name may not be specified "
+                         "at the same time");
+        return;
+    }
+
     if (strstr(filename, "://")) {
         int ret = nbd_parse_uri(filename, options);
         if (ret < 0) {
@@ -204,6 +213,11 @@ static int nbd_config(BDRVNBDState *s, QDict *options)
     Error *local_err = NULL;
 
     if (qdict_haskey(options, "path")) {
+        if (qdict_haskey(options, "host")) {
+            qerror_report(ERROR_CLASS_GENERIC_ERROR, "path and host may not "
+                          "be used at the same time.");
+            return -EINVAL;
+        }
         s->is_unix = true;
     } else if (qdict_haskey(options, "host")) {
         s->is_unix = false;
commit bebbf7fa9c6235022ecd15f8f934d27e5ccab63a
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Mar 18 16:56:05 2013 +0100

    nbd: Use default port if only host is specified
    
    The URL method already takes care to apply the default port when none is
    specfied. Directly specifying driver-specific options required the port
    number until now. Allow leaving it out and apply the default.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/block/nbd.c b/block/nbd.c
index 9858f06..67f1df2 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -118,21 +118,18 @@ static int nbd_parse_uri(const char *filename, QDict *options)
         }
         qdict_put(options, "path", qstring_from_str(qp->p[0].value));
     } else {
-        /* nbd[+tcp]://host:port/export */
-        char *port_str;
-
+        /* nbd[+tcp]://host[:port]/export */
         if (!uri->server) {
             ret = -EINVAL;
             goto out;
         }
-        if (!uri->port) {
-            uri->port = NBD_DEFAULT_PORT;
-        }
 
-        port_str = g_strdup_printf("%d", uri->port);
         qdict_put(options, "host", qstring_from_str(uri->server));
-        qdict_put(options, "port", qstring_from_str(port_str));
-        g_free(port_str);
+        if (uri->port) {
+            char* port_str = g_strdup_printf("%d", uri->port);
+            qdict_put(options, "port", qstring_from_str(port_str));
+            g_free(port_str);
+        }
     }
 
 out:
@@ -223,6 +220,10 @@ static int nbd_config(BDRVNBDState *s, QDict *options)
         return -EINVAL;
     }
 
+    if (!qemu_opt_get(s->socket_opts, "port")) {
+        qemu_opt_set_number(s->socket_opts, "port", NBD_DEFAULT_PORT);
+    }
+
     s->export_name = g_strdup(qdict_get_try_str(options, "export"));
     if (s->export_name) {
         qdict_del(options, "export");
commit c2ad1b0c465a9ea8375eaff14bbd85705c673f73
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Mar 18 16:40:51 2013 +0100

    block: Allow omitting the file name when using driver-specific options
    
    After this patch, using -drive with an empty file name continues to open
    the file if driver-specific options are used. If no driver-specific
    options are specified, the semantics stay as it was: It defines a drive
    without an inserted medium.
    
    In order to achieve this, bdrv_open() must be made safe to work with a
    NULL filename parameter. The assumption that is made is that only block
    drivers which implement bdrv_parse_filename() support using driver
    specific options and could therefore work without a filename. These
    drivers must make sure to cope with NULL in their implementation of
    .bdrv_open() (this is only NBD for now). For all other drivers, the
    block layer code will make sure to error out before calling into their
    code - they can't possibly work without a filename.
    
    Now an NBD connection can be opened like this:
    
      qemu-system-x86_64 -drive file.driver=nbd,file.port=1234,file.host=::1
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/block.c b/block.c
index 2c17a34..16a92a4 100644
--- a/block.c
+++ b/block.c
@@ -688,7 +688,11 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
         bdrv_enable_copy_on_read(bs);
     }
 
-    pstrcpy(bs->filename, sizeof(bs->filename), filename);
+    if (filename != NULL) {
+        pstrcpy(bs->filename, sizeof(bs->filename), filename);
+    } else {
+        bs->filename[0] = '\0';
+    }
 
     if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
         return -ENOTSUP;
@@ -708,6 +712,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
             bdrv_swap(file, bs);
             ret = 0;
         } else {
+            assert(drv->bdrv_parse_filename || filename != NULL);
             ret = drv->bdrv_file_open(bs, filename, options, open_flags);
         }
     } else {
@@ -727,6 +732,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
 
 #ifndef _WIN32
     if (bs->is_temporary) {
+        assert(filename != NULL);
         unlink(filename);
     }
 #endif
@@ -753,14 +759,9 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
 {
     BlockDriverState *bs;
     BlockDriver *drv;
+    const char *drvname;
     int ret;
 
-    drv = bdrv_find_protocol(filename);
-    if (!drv) {
-        QDECREF(options);
-        return -ENOENT;
-    }
-
     /* NULL means an empty set of options */
     if (options == NULL) {
         options = qdict_new();
@@ -770,7 +771,26 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
     bs->options = options;
     options = qdict_clone_shallow(options);
 
-    if (drv->bdrv_parse_filename) {
+    /* Find the right block driver */
+    drvname = qdict_get_try_str(options, "driver");
+    if (drvname) {
+        drv = bdrv_find_whitelisted_format(drvname);
+        qdict_del(options, "driver");
+    } else if (filename) {
+        drv = bdrv_find_protocol(filename);
+    } else {
+        qerror_report(ERROR_CLASS_GENERIC_ERROR,
+                      "Must specify either driver or file");
+        drv = NULL;
+    }
+
+    if (!drv) {
+        ret = -ENOENT;
+        goto fail;
+    }
+
+    /* Parse the filename and open it */
+    if (drv->bdrv_parse_filename && filename) {
         Error *local_err = NULL;
         drv->bdrv_parse_filename(filename, options, &local_err);
         if (error_is_set(&local_err)) {
@@ -779,6 +799,12 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
             ret = -EINVAL;
             goto fail;
         }
+    } else if (!drv->bdrv_parse_filename && !filename) {
+        qerror_report(ERROR_CLASS_GENERIC_ERROR,
+                      "The '%s' block driver requires a file name",
+                      drv->format_name);
+        ret = -EINVAL;
+        goto fail;
     }
 
     ret = bdrv_open_common(bs, NULL, filename, options, flags, drv);
@@ -899,6 +925,13 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
         QEMUOptionParameter *create_options;
         char backing_filename[PATH_MAX];
 
+        if (qdict_size(options) != 0) {
+            error_report("Can't use snapshot=on with driver-specific options");
+            ret = -EINVAL;
+            goto fail;
+        }
+        assert(filename != NULL);
+
         /* if snapshot, we create a temporary backing file and open it
            instead of opening 'filename' directly */
 
diff --git a/blockdev.c b/blockdev.c
index 6f2b759..8cdc9ce 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -658,7 +658,11 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
         abort();
     }
     if (!file || !*file) {
-        return dinfo;
+        if (qdict_size(bs_opts)) {
+            file = NULL;
+        } else {
+            return dinfo;
+        }
     }
     if (snapshot) {
         /* always use cache=unsafe with snapshot */
@@ -697,10 +701,10 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     if (ret < 0) {
         if (ret == -EMEDIUMTYPE) {
             error_report("could not open disk image %s: not in %s format",
-                         file, drv->format_name);
+                         file ?: dinfo->id, drv->format_name);
         } else {
             error_report("could not open disk image %s: %s",
-                         file, strerror(-ret));
+                         file ?: dinfo->id, strerror(-ret));
         }
         goto err;
     }
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 1b06a11..0986a2d 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -75,6 +75,9 @@ struct BlockDriver {
     int instance_size;
     int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
     int (*bdrv_probe_device)(const char *filename);
+
+    /* Any driver implementing this callback is expected to be able to handle
+     * NULL file names in its .bdrv_open() implementation */
     void (*bdrv_parse_filename)(const char *filename, QDict *options, Error **errp);
 
     /* For handling image reopen for split or non-split files */
commit f5866fa438bff586f215c137dc71edb4e0770536
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Mar 18 16:20:27 2013 +0100

    block: Make find_image_format safe with NULL filename
    
    In order to achieve this, the .bdrv_probe callbacks of all drivers must
    cope with this. The DMG driver is the only one that bases its decision
    on the filename and it needs to be changed.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/block/dmg.c b/block/dmg.c
index c1066df..3141cb5 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -51,9 +51,16 @@ typedef struct BDRVDMGState {
 
 static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename)
 {
-    int len=strlen(filename);
-    if(len>4 && !strcmp(filename+len-4,".dmg"))
-	return 2;
+    int len;
+
+    if (!filename) {
+        return 0;
+    }
+
+    len = strlen(filename);
+    if (len > 4 && !strcmp(filename + len - 4, ".dmg")) {
+        return 2;
+    }
     return 0;
 }
 
commit 08b392e1510b21d8c9bfa8a50525fae31014a2e2
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Mar 18 16:17:44 2013 +0100

    block: Rename variable to avoid shadowing
    
    bdrv_open() uses two different variables called options. Rename one of
    them to avoid confusion and to allow the outer one to be accessed
    everywhere.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/block.c b/block.c
index 8a95a28..2c17a34 100644
--- a/block.c
+++ b/block.c
@@ -896,7 +896,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
         BlockDriverState *bs1;
         int64_t total_size;
         BlockDriver *bdrv_qcow2;
-        QEMUOptionParameter *options;
+        QEMUOptionParameter *create_options;
         char backing_filename[PATH_MAX];
 
         /* if snapshot, we create a temporary backing file and open it
@@ -928,17 +928,19 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
         }
 
         bdrv_qcow2 = bdrv_find_format("qcow2");
-        options = parse_option_parameters("", bdrv_qcow2->create_options, NULL);
+        create_options = parse_option_parameters("", bdrv_qcow2->create_options,
+                                                 NULL);
 
-        set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size);
-        set_option_parameter(options, BLOCK_OPT_BACKING_FILE, backing_filename);
+        set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size);
+        set_option_parameter(create_options, BLOCK_OPT_BACKING_FILE,
+                             backing_filename);
         if (drv) {
-            set_option_parameter(options, BLOCK_OPT_BACKING_FMT,
+            set_option_parameter(create_options, BLOCK_OPT_BACKING_FMT,
                 drv->format_name);
         }
 
-        ret = bdrv_create(bdrv_qcow2, tmp_filename, options);
-        free_option_parameters(options);
+        ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options);
+        free_option_parameters(create_options);
         if (ret < 0) {
             goto fail;
         }
commit 6963a30d82413bea36c7545137b090b284cc2b18
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 15 18:47:22 2013 +0100

    block: Introduce .bdrv_parse_filename callback
    
    If a driver needs structured data and not just a string, it can provide
    a .bdrv_parse_filename callback now that parses the command line string
    into separate options. Keeping this separate from .bdrv_open_filename
    ensures that the preferred way of directly specifying the options always
    works as well if parsing the string works.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/block.c b/block.c
index ef1ae94..8a95a28 100644
--- a/block.c
+++ b/block.c
@@ -770,6 +770,17 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
     bs->options = options;
     options = qdict_clone_shallow(options);
 
+    if (drv->bdrv_parse_filename) {
+        Error *local_err = NULL;
+        drv->bdrv_parse_filename(filename, options, &local_err);
+        if (error_is_set(&local_err)) {
+            qerror_report_err(local_err);
+            error_free(local_err);
+            ret = -EINVAL;
+            goto fail;
+        }
+    }
+
     ret = bdrv_open_common(bs, NULL, filename, options, flags, drv);
     if (ret < 0) {
         goto fail;
diff --git a/block/nbd.c b/block/nbd.c
index 5ed8502..9858f06 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -143,17 +143,20 @@ out:
     return ret;
 }
 
-static int nbd_parse_filename(const char *filename, QDict *options)
+static void nbd_parse_filename(const char *filename, QDict *options,
+                               Error **errp)
 {
     char *file;
     char *export_name;
     const char *host_spec;
     const char *unixpath;
-    int ret = -EINVAL;
-    Error *local_err = NULL;
 
     if (strstr(filename, "://")) {
-        return nbd_parse_uri(filename, options);
+        int ret = nbd_parse_uri(filename, options);
+        if (ret < 0) {
+            error_setg(errp, "No valid URL specified");
+        }
+        return;
     }
 
     file = g_strdup(filename);
@@ -171,11 +174,11 @@ static int nbd_parse_filename(const char *filename, QDict *options)
 
     /* extract the host_spec - fail if it's not nbd:... */
     if (!strstart(file, "nbd:", &host_spec)) {
+        error_setg(errp, "File name string for NBD must start with 'nbd:'");
         goto out;
     }
 
     if (!*host_spec) {
-        ret = 1;
         goto out;
     }
 
@@ -185,10 +188,8 @@ static int nbd_parse_filename(const char *filename, QDict *options)
     } else {
         InetSocketAddress *addr = NULL;
 
-        addr = inet_parse(host_spec, &local_err);
-        if (local_err != NULL) {
-            qerror_report_err(local_err);
-            error_free(local_err);
+        addr = inet_parse(host_spec, errp);
+        if (error_is_set(errp)) {
             goto out;
         }
 
@@ -197,10 +198,8 @@ static int nbd_parse_filename(const char *filename, QDict *options)
         qapi_free_InetSocketAddress(addr);
     }
 
-    ret = 1;
 out:
     g_free(file);
-    return ret;
 }
 
 static int nbd_config(BDRVNBDState *s, QDict *options)
@@ -437,11 +436,6 @@ static int nbd_open(BlockDriverState *bs, const char* filename,
     qemu_co_mutex_init(&s->free_sema);
 
     /* Pop the config into our state object. Exit if invalid. */
-    result = nbd_parse_filename(filename, options);
-    if (result < 0) {
-        return result;
-    }
-
     result = nbd_config(s, options);
     if (result != 0) {
         return result;
@@ -622,6 +616,7 @@ static BlockDriver bdrv_nbd = {
     .format_name         = "nbd",
     .protocol_name       = "nbd",
     .instance_size       = sizeof(BDRVNBDState),
+    .bdrv_parse_filename = nbd_parse_filename,
     .bdrv_file_open      = nbd_open,
     .bdrv_co_readv       = nbd_co_readv,
     .bdrv_co_writev      = nbd_co_writev,
@@ -635,6 +630,7 @@ static BlockDriver bdrv_nbd_tcp = {
     .format_name         = "nbd",
     .protocol_name       = "nbd+tcp",
     .instance_size       = sizeof(BDRVNBDState),
+    .bdrv_parse_filename = nbd_parse_filename,
     .bdrv_file_open      = nbd_open,
     .bdrv_co_readv       = nbd_co_readv,
     .bdrv_co_writev      = nbd_co_writev,
@@ -648,6 +644,7 @@ static BlockDriver bdrv_nbd_unix = {
     .format_name         = "nbd",
     .protocol_name       = "nbd+unix",
     .instance_size       = sizeof(BDRVNBDState),
+    .bdrv_parse_filename = nbd_parse_filename,
     .bdrv_file_open      = nbd_open,
     .bdrv_co_readv       = nbd_co_readv,
     .bdrv_co_writev      = nbd_co_writev,
diff --git a/include/block/block_int.h b/include/block/block_int.h
index fb2a136..1b06a11 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -75,6 +75,7 @@ struct BlockDriver {
     int instance_size;
     int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
     int (*bdrv_probe_device)(const char *filename);
+    void (*bdrv_parse_filename)(const char *filename, QDict *options, Error **errp);
 
     /* For handling image reopen for split or non-split files */
     int (*bdrv_reopen_prepare)(BDRVReopenState *reopen_state,
commit f53a1febcd9d887149ac1429880a3f2fdb2c117f
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Mar 7 16:15:11 2013 +0100

    nbd: Accept -drive options for the network connection
    
    The existing parsers for the file name now parse everything into the
    bdrv_open() options QDict. Instead of using these parsers, you can now
    directly specify the options on the command line, like this:
    
        qemu-system-x86_64 -drive file=nbd:,file.port=1234,file.host=::1
    
    Clearly the file=... part could use further improvement, but it's a
    start.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/block/nbd.c b/block/nbd.c
index ecbc892..5ed8502 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -32,6 +32,8 @@
 #include "block/block_int.h"
 #include "qemu/module.h"
 #include "qemu/sockets.h"
+#include "qapi/qmp/qjson.h"
+#include "qapi/qmp/qint.h"
 
 #include <sys/types.h>
 #include <unistd.h>
@@ -65,20 +67,19 @@ typedef struct BDRVNBDState {
     Coroutine *recv_coroutine[MAX_NBD_REQUESTS];
     struct nbd_reply reply;
 
-    int is_unix;
-    char *unix_path;
-
-    InetSocketAddress *inet_addr;
+    bool is_unix;
+    QemuOpts *socket_opts;
 
     char *export_name; /* An NBD server may export several devices */
 } BDRVNBDState;
 
-static int nbd_parse_uri(BDRVNBDState *s, const char *filename)
+static int nbd_parse_uri(const char *filename, QDict *options)
 {
     URI *uri;
     const char *p;
     QueryParams *qp = NULL;
     int ret = 0;
+    bool is_unix;
 
     uri = uri_parse(filename);
     if (!uri) {
@@ -87,11 +88,11 @@ static int nbd_parse_uri(BDRVNBDState *s, const char *filename)
 
     /* transport */
     if (!strcmp(uri->scheme, "nbd")) {
-        s->is_unix = false;
+        is_unix = false;
     } else if (!strcmp(uri->scheme, "nbd+tcp")) {
-        s->is_unix = false;
+        is_unix = false;
     } else if (!strcmp(uri->scheme, "nbd+unix")) {
-        s->is_unix = true;
+        is_unix = true;
     } else {
         ret = -EINVAL;
         goto out;
@@ -100,24 +101,26 @@ static int nbd_parse_uri(BDRVNBDState *s, const char *filename)
     p = uri->path ? uri->path : "/";
     p += strspn(p, "/");
     if (p[0]) {
-        s->export_name = g_strdup(p);
+        qdict_put(options, "export", qstring_from_str(p));
     }
 
     qp = query_params_parse(uri->query);
-    if (qp->n > 1 || (s->is_unix && !qp->n) || (!s->is_unix && qp->n)) {
+    if (qp->n > 1 || (is_unix && !qp->n) || (!is_unix && qp->n)) {
         ret = -EINVAL;
         goto out;
     }
 
-    if (s->is_unix) {
+    if (is_unix) {
         /* nbd+unix:///export?socket=path */
         if (uri->server || uri->port || strcmp(qp->p[0].name, "socket")) {
             ret = -EINVAL;
             goto out;
         }
-        s->unix_path = g_strdup(qp->p[0].value);
+        qdict_put(options, "path", qstring_from_str(qp->p[0].value));
     } else {
         /* nbd[+tcp]://host:port/export */
+        char *port_str;
+
         if (!uri->server) {
             ret = -EINVAL;
             goto out;
@@ -126,11 +129,10 @@ static int nbd_parse_uri(BDRVNBDState *s, const char *filename)
             uri->port = NBD_DEFAULT_PORT;
         }
 
-        s->inet_addr = g_new0(InetSocketAddress, 1);
-        *s->inet_addr = (InetSocketAddress) {
-            .host   = g_strdup(uri->server),
-            .port   = g_strdup_printf("%d", uri->port),
-        };
+        port_str = g_strdup_printf("%d", uri->port);
+        qdict_put(options, "host", qstring_from_str(uri->server));
+        qdict_put(options, "port", qstring_from_str(port_str));
+        g_free(port_str);
     }
 
 out:
@@ -141,17 +143,17 @@ out:
     return ret;
 }
 
-static int nbd_config(BDRVNBDState *s, const char *filename)
+static int nbd_parse_filename(const char *filename, QDict *options)
 {
     char *file;
     char *export_name;
     const char *host_spec;
     const char *unixpath;
-    int err = -EINVAL;
+    int ret = -EINVAL;
     Error *local_err = NULL;
 
     if (strstr(filename, "://")) {
-        return nbd_parse_uri(s, filename);
+        return nbd_parse_uri(filename, options);
     }
 
     file = g_strdup(filename);
@@ -163,7 +165,8 @@ static int nbd_config(BDRVNBDState *s, const char *filename)
         }
         export_name[0] = 0; /* truncate 'file' */
         export_name += strlen(EN_OPTSTR);
-        s->export_name = g_strdup(export_name);
+
+        qdict_put(options, "export", qstring_from_str(export_name));
     }
 
     /* extract the host_spec - fail if it's not nbd:... */
@@ -171,32 +174,65 @@ static int nbd_config(BDRVNBDState *s, const char *filename)
         goto out;
     }
 
+    if (!*host_spec) {
+        ret = 1;
+        goto out;
+    }
+
     /* are we a UNIX or TCP socket? */
     if (strstart(host_spec, "unix:", &unixpath)) {
-        s->is_unix = true;
-        s->unix_path = g_strdup(unixpath);
+        qdict_put(options, "path", qstring_from_str(unixpath));
     } else {
-        s->is_unix = false;
-        s->inet_addr = inet_parse(host_spec, &local_err);
+        InetSocketAddress *addr = NULL;
+
+        addr = inet_parse(host_spec, &local_err);
         if (local_err != NULL) {
             qerror_report_err(local_err);
             error_free(local_err);
             goto out;
         }
-    }
 
-    err = 0;
+        qdict_put(options, "host", qstring_from_str(addr->host));
+        qdict_put(options, "port", qstring_from_str(addr->port));
+        qapi_free_InetSocketAddress(addr);
+    }
 
+    ret = 1;
 out:
     g_free(file);
-    if (err != 0) {
-        g_free(s->export_name);
-        g_free(s->unix_path);
-        qapi_free_InetSocketAddress(s->inet_addr);
+    return ret;
+}
+
+static int nbd_config(BDRVNBDState *s, QDict *options)
+{
+    Error *local_err = NULL;
+
+    if (qdict_haskey(options, "path")) {
+        s->is_unix = true;
+    } else if (qdict_haskey(options, "host")) {
+        s->is_unix = false;
+    } else {
+        return -EINVAL;
     }
-    return err;
+
+    s->socket_opts = qemu_opts_create_nofail(&socket_optslist);
+
+    qemu_opts_absorb_qdict(s->socket_opts, options, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -EINVAL;
+    }
+
+    s->export_name = g_strdup(qdict_get_try_str(options, "export"));
+    if (s->export_name) {
+        qdict_del(options, "export");
+    }
+
+    return 0;
 }
 
+
 static void nbd_coroutine_start(BDRVNBDState *s, struct nbd_request *request)
 {
     int i;
@@ -343,24 +379,9 @@ static int nbd_establish_connection(BlockDriverState *bs)
     size_t blocksize;
 
     if (s->is_unix) {
-        sock = unix_socket_outgoing(s->unix_path);
+        sock = unix_socket_outgoing(qemu_opt_get(s->socket_opts, "path"));
     } else {
-        QemuOpts *opts = qemu_opts_create_nofail(&socket_optslist);
-
-        qemu_opt_set(opts, "host", s->inet_addr->host);
-        qemu_opt_set(opts, "port", s->inet_addr->port);
-        if (s->inet_addr->has_to) {
-            qemu_opt_set_number(opts, "to", s->inet_addr->to);
-        }
-        if (s->inet_addr->has_ipv4) {
-            qemu_opt_set_number(opts, "ipv4", s->inet_addr->ipv4);
-        }
-        if (s->inet_addr->has_ipv6) {
-            qemu_opt_set_number(opts, "ipv6", s->inet_addr->ipv6);
-        }
-
-        sock = tcp_socket_outgoing_opts(opts);
-        qemu_opts_del(opts);
+        sock = tcp_socket_outgoing_opts(s->socket_opts);
     }
 
     /* Failed to establish connection */
@@ -416,7 +437,12 @@ static int nbd_open(BlockDriverState *bs, const char* filename,
     qemu_co_mutex_init(&s->free_sema);
 
     /* Pop the config into our state object. Exit if invalid. */
-    result = nbd_config(s, filename);
+    result = nbd_parse_filename(filename, options);
+    if (result < 0) {
+        return result;
+    }
+
+    result = nbd_config(s, options);
     if (result != 0) {
         return result;
     }
@@ -580,8 +606,7 @@ static void nbd_close(BlockDriverState *bs)
 {
     BDRVNBDState *s = bs->opaque;
     g_free(s->export_name);
-    g_free(s->unix_path);
-    qapi_free_InetSocketAddress(s->inet_addr);
+    qemu_opts_del(s->socket_opts);
 
     nbd_teardown_connection(bs);
 }
commit 197a4859b914559489f41b63fd71ea4bfda17c3d
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 15 16:46:38 2013 +0100

    nbd: Remove unused functions
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/include/block/nbd.h b/include/block/nbd.h
index 9b52d50..0903d7a 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -61,9 +61,7 @@ enum {
 #define NBD_BUFFER_SIZE (1024*1024)
 
 ssize_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 tcp_socket_outgoing_opts(QemuOpts *opts);
 int unix_socket_outgoing(const char *path);
diff --git a/nbd.c b/nbd.c
index 97879ca..d1a67ee 100644
--- a/nbd.c
+++ b/nbd.c
@@ -199,25 +199,6 @@ static void combine_addr(char *buf, size_t len, const char* address,
     }
 }
 
-int tcp_socket_outgoing(const char *address, uint16_t port)
-{
-    char address_and_port[128];
-    combine_addr(address_and_port, 128, address, port);
-    return tcp_socket_outgoing_spec(address_and_port);
-}
-
-int tcp_socket_outgoing_spec(const char *address_and_port)
-{
-    Error *local_err = NULL;
-    int fd = inet_connect(address_and_port, &local_err);
-
-    if (local_err != NULL) {
-        qerror_report_err(local_err);
-        error_free(local_err);
-    }
-    return fd;
-}
-
 int tcp_socket_outgoing_opts(QemuOpts *opts)
 {
     Error *local_err = NULL;
commit f17c90bed11a6e277614b5a5d16434004f24d572
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 15 11:55:29 2013 +0100

    nbd: Keep hostname and port separate
    
    The NBD block supports an URL syntax, for which a URL parser returns
    separate hostname and port fields. It also supports the traditional qemu
    syntax encoded in a filename. Until now, after parsing the URL to get
    each piece of information, a new string is built to be fed to socket
    functions.
    
    Instead of building a string in the URL case that is immediately parsed
    again, parse the string in both cases and use the QemuOpts interface to
    qemu-sockets.c.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/block/nbd.c b/block/nbd.c
index 0473908..ecbc892 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -66,7 +66,10 @@ typedef struct BDRVNBDState {
     struct nbd_reply reply;
 
     int is_unix;
-    char *host_spec;
+    char *unix_path;
+
+    InetSocketAddress *inet_addr;
+
     char *export_name; /* An NBD server may export several devices */
 } BDRVNBDState;
 
@@ -112,7 +115,7 @@ static int nbd_parse_uri(BDRVNBDState *s, const char *filename)
             ret = -EINVAL;
             goto out;
         }
-        s->host_spec = g_strdup(qp->p[0].value);
+        s->unix_path = g_strdup(qp->p[0].value);
     } else {
         /* nbd[+tcp]://host:port/export */
         if (!uri->server) {
@@ -122,7 +125,12 @@ static int nbd_parse_uri(BDRVNBDState *s, const char *filename)
         if (!uri->port) {
             uri->port = NBD_DEFAULT_PORT;
         }
-        s->host_spec = g_strdup_printf("%s:%d", uri->server, uri->port);
+
+        s->inet_addr = g_new0(InetSocketAddress, 1);
+        *s->inet_addr = (InetSocketAddress) {
+            .host   = g_strdup(uri->server),
+            .port   = g_strdup_printf("%d", uri->port),
+        };
     }
 
 out:
@@ -140,6 +148,7 @@ static int nbd_config(BDRVNBDState *s, const char *filename)
     const char *host_spec;
     const char *unixpath;
     int err = -EINVAL;
+    Error *local_err = NULL;
 
     if (strstr(filename, "://")) {
         return nbd_parse_uri(s, filename);
@@ -165,10 +174,15 @@ static int nbd_config(BDRVNBDState *s, const char *filename)
     /* are we a UNIX or TCP socket? */
     if (strstart(host_spec, "unix:", &unixpath)) {
         s->is_unix = true;
-        s->host_spec = g_strdup(unixpath);
+        s->unix_path = g_strdup(unixpath);
     } else {
         s->is_unix = false;
-        s->host_spec = g_strdup(host_spec);
+        s->inet_addr = inet_parse(host_spec, &local_err);
+        if (local_err != NULL) {
+            qerror_report_err(local_err);
+            error_free(local_err);
+            goto out;
+        }
     }
 
     err = 0;
@@ -177,7 +191,8 @@ out:
     g_free(file);
     if (err != 0) {
         g_free(s->export_name);
-        g_free(s->host_spec);
+        g_free(s->unix_path);
+        qapi_free_InetSocketAddress(s->inet_addr);
     }
     return err;
 }
@@ -328,9 +343,24 @@ static int nbd_establish_connection(BlockDriverState *bs)
     size_t blocksize;
 
     if (s->is_unix) {
-        sock = unix_socket_outgoing(s->host_spec);
+        sock = unix_socket_outgoing(s->unix_path);
     } else {
-        sock = tcp_socket_outgoing_spec(s->host_spec);
+        QemuOpts *opts = qemu_opts_create_nofail(&socket_optslist);
+
+        qemu_opt_set(opts, "host", s->inet_addr->host);
+        qemu_opt_set(opts, "port", s->inet_addr->port);
+        if (s->inet_addr->has_to) {
+            qemu_opt_set_number(opts, "to", s->inet_addr->to);
+        }
+        if (s->inet_addr->has_ipv4) {
+            qemu_opt_set_number(opts, "ipv4", s->inet_addr->ipv4);
+        }
+        if (s->inet_addr->has_ipv6) {
+            qemu_opt_set_number(opts, "ipv6", s->inet_addr->ipv6);
+        }
+
+        sock = tcp_socket_outgoing_opts(opts);
+        qemu_opts_del(opts);
     }
 
     /* Failed to establish connection */
@@ -550,7 +580,8 @@ static void nbd_close(BlockDriverState *bs)
 {
     BDRVNBDState *s = bs->opaque;
     g_free(s->export_name);
-    g_free(s->host_spec);
+    g_free(s->unix_path);
+    qapi_free_InetSocketAddress(s->inet_addr);
 
     nbd_teardown_connection(bs);
 }
diff --git a/include/block/nbd.h b/include/block/nbd.h
index 344f05b..9b52d50 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -22,6 +22,7 @@
 #include <sys/types.h>
 
 #include "qemu-common.h"
+#include "qemu/option.h"
 
 struct nbd_request {
     uint32_t magic;
@@ -64,6 +65,7 @@ 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 tcp_socket_outgoing_opts(QemuOpts *opts);
 int unix_socket_outgoing(const char *path);
 int unix_socket_incoming(const char *path);
 
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index 21846f9..d225f6d 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -47,6 +47,7 @@ int recv_all(int fd, void *buf, int len1, bool single_read);
  */
 typedef void NonBlockingConnectHandler(int fd, void *opaque);
 
+InetSocketAddress *inet_parse(const char *str, Error **errp);
 int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp);
 int inet_listen(const char *str, char *ostr, int olen,
                 int socktype, int port_offset, Error **errp);
diff --git a/nbd.c b/nbd.c
index 0698a02..97879ca 100644
--- a/nbd.c
+++ b/nbd.c
@@ -218,6 +218,18 @@ int tcp_socket_outgoing_spec(const char *address_and_port)
     return fd;
 }
 
+int tcp_socket_outgoing_opts(QemuOpts *opts)
+{
+    Error *local_err = NULL;
+    int fd = inet_connect_opts(opts, &local_err, NULL, NULL);
+    if (local_err != NULL) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+    }
+
+    return fd;
+}
+
 int tcp_socket_incoming(const char *address, uint16_t port)
 {
     char address_and_port[128];
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 39717d0..dc7524d 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -485,7 +485,7 @@ err:
 }
 
 /* compatibility wrapper */
-static InetSocketAddress *inet_parse(const char *str, Error **errp)
+InetSocketAddress *inet_parse(const char *str, Error **errp)
 {
     InetSocketAddress *addr;
     const char *optstr, *h;
@@ -555,7 +555,7 @@ fail:
     return NULL;
 }
 
-static void inet_addr_to_opts(QemuOpts *opts, InetSocketAddress *addr)
+static void inet_addr_to_opts(QemuOpts *opts, const InetSocketAddress *addr)
 {
     bool ipv4 = addr->ipv4 || !addr->has_ipv4;
     bool ipv6 = addr->ipv6 || !addr->has_ipv6;
@@ -622,7 +622,7 @@ int inet_connect(const char *str, Error **errp)
 
     addr = inet_parse(str, errp);
     if (addr != NULL) {
-        opts = qemu_opts_create_nofail(&dummy_opts);
+        opts = qemu_opts_create_nofail(&socket_optslist);
         inet_addr_to_opts(opts, addr);
         qapi_free_InetSocketAddress(addr);
         sock = inet_connect_opts(opts, errp, NULL, NULL);
commit e62be8888a83aa0ab7f50eeb954deb2ec4e7201d
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 15 17:14:24 2013 +0100

    qemu-socket: Make socket_optslist public
    
    Allow other users to create the QemuOpts needed for inet_connect_opts().
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index ae5c21c..21846f9 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -30,6 +30,8 @@ int inet_aton(const char *cp, struct in_addr *ia);
 #include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
 
+extern QemuOptsList socket_optslist;
+
 /* misc helpers */
 int qemu_socket(int domain, int type, int protocol);
 int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 83e4e08..39717d0 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -33,10 +33,10 @@
 
 static const int on=1, off=0;
 
-/* used temporarely until all users are converted to QemuOpts */
-static QemuOptsList dummy_opts = {
-    .name = "dummy",
-    .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head),
+/* used temporarily until all users are converted to QemuOpts */
+QemuOptsList socket_optslist = {
+    .name = "socket",
+    .head = QTAILQ_HEAD_INITIALIZER(socket_optslist.head),
     .desc = {
         {
             .name = "path",
@@ -583,7 +583,7 @@ int inet_listen(const char *str, char *ostr, int olen,
 
     addr = inet_parse(str, errp);
     if (addr != NULL) {
-        opts = qemu_opts_create_nofail(&dummy_opts);
+        opts = qemu_opts_create_nofail(&socket_optslist);
         inet_addr_to_opts(opts, addr);
         qapi_free_InetSocketAddress(addr);
         sock = inet_listen_opts(opts, port_offset, errp);
@@ -656,7 +656,7 @@ int inet_nonblocking_connect(const char *str,
 
     addr = inet_parse(str, errp);
     if (addr != NULL) {
-        opts = qemu_opts_create_nofail(&dummy_opts);
+        opts = qemu_opts_create_nofail(&socket_optslist);
         inet_addr_to_opts(opts, addr);
         qapi_free_InetSocketAddress(addr);
         sock = inet_connect_opts(opts, errp, callback, opaque);
@@ -799,7 +799,7 @@ int unix_listen(const char *str, char *ostr, int olen, Error **errp)
     char *path, *optstr;
     int sock, len;
 
-    opts = qemu_opts_create_nofail(&dummy_opts);
+    opts = qemu_opts_create_nofail(&socket_optslist);
 
     optstr = strchr(str, ',');
     if (optstr) {
@@ -827,7 +827,7 @@ int unix_connect(const char *path, Error **errp)
     QemuOpts *opts;
     int sock;
 
-    opts = qemu_opts_create_nofail(&dummy_opts);
+    opts = qemu_opts_create_nofail(&socket_optslist);
     qemu_opt_set(opts, "path", path);
     sock = unix_connect_opts(opts, errp, NULL, NULL);
     qemu_opts_del(opts);
@@ -844,7 +844,7 @@ int unix_nonblocking_connect(const char *path,
 
     g_assert(callback != NULL);
 
-    opts = qemu_opts_create_nofail(&dummy_opts);
+    opts = qemu_opts_create_nofail(&socket_optslist);
     qemu_opt_set(opts, "path", path);
     sock = unix_connect_opts(opts, errp, callback, opaque);
     qemu_opts_del(opts);
@@ -895,7 +895,7 @@ int socket_connect(SocketAddress *addr, Error **errp,
     QemuOpts *opts;
     int fd;
 
-    opts = qemu_opts_create_nofail(&dummy_opts);
+    opts = qemu_opts_create_nofail(&socket_optslist);
     switch (addr->kind) {
     case SOCKET_ADDRESS_KIND_INET:
         inet_addr_to_opts(opts, addr->inet);
@@ -926,7 +926,7 @@ int socket_listen(SocketAddress *addr, Error **errp)
     QemuOpts *opts;
     int fd;
 
-    opts = qemu_opts_create_nofail(&dummy_opts);
+    opts = qemu_opts_create_nofail(&socket_optslist);
     switch (addr->kind) {
     case SOCKET_ADDRESS_KIND_INET:
         inet_addr_to_opts(opts, addr->inet);
@@ -954,7 +954,7 @@ int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp)
     QemuOpts *opts;
     int fd;
 
-    opts = qemu_opts_create_nofail(&dummy_opts);
+    opts = qemu_opts_create_nofail(&socket_optslist);
     switch (remote->kind) {
     case SOCKET_ADDRESS_KIND_INET:
         qemu_opt_set(opts, "host", remote->inet->host);
commit 707ff8282b66bb9471e253fe5f17b74576d36825
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 6 12:20:31 2013 +0100

    block: Pass bdrv_file_open() options to block drivers
    
    Specify -drive file.option=... on the command line to pass the option to
    the protocol instead of the format driver.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/block.c b/block.c
index 0fb0165..ef1ae94 100644
--- a/block.c
+++ b/block.c
@@ -676,7 +676,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
 
     assert(drv != NULL);
     assert(bs->file == NULL);
-    assert(options == NULL || bs->options != options);
+    assert(options != NULL && bs->options != options);
 
     trace_bdrv_open_common(bs, filename, flags, drv->format_name);
 
@@ -755,22 +755,48 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
     BlockDriver *drv;
     int ret;
 
-    QDECREF(options);
-
     drv = bdrv_find_protocol(filename);
     if (!drv) {
+        QDECREF(options);
         return -ENOENT;
     }
 
+    /* NULL means an empty set of options */
+    if (options == NULL) {
+        options = qdict_new();
+    }
+
     bs = bdrv_new("");
-    ret = bdrv_open_common(bs, NULL, filename, NULL, flags, drv);
+    bs->options = options;
+    options = qdict_clone_shallow(options);
+
+    ret = bdrv_open_common(bs, NULL, filename, options, flags, drv);
     if (ret < 0) {
-        bdrv_delete(bs);
-        return ret;
+        goto fail;
+    }
+
+    /* Check if any unknown options were used */
+    if (qdict_size(options) != 0) {
+        const QDictEntry *entry = qdict_first(options);
+        qerror_report(ERROR_CLASS_GENERIC_ERROR, "Block protocol '%s' doesn't "
+                      "support the option '%s'",
+                      drv->format_name, entry->key);
+        ret = -EINVAL;
+        goto fail;
     }
+    QDECREF(options);
+
     bs->growable = 1;
     *pbs = bs;
     return 0;
+
+fail:
+    QDECREF(options);
+    if (!bs->drv) {
+        QDECREF(bs->options);
+    }
+    bdrv_delete(bs);
+    return ret;
 }
 
 int bdrv_open_backing_file(BlockDriverState *bs)
@@ -810,6 +836,25 @@ int bdrv_open_backing_file(BlockDriverState *bs)
     return 0;
 }
 
+static void extract_subqdict(QDict *src, QDict **dst, const char *start)
+{
+    const QDictEntry *entry, *next;
+    const char *p;
+
+    *dst = qdict_new();
+    entry = qdict_first(src);
+
+    while (entry != NULL) {
+        next = qdict_next(src, entry);
+        if (strstart(entry->key, start, &p)) {
+            qobject_incref(entry->value);
+            qdict_put_obj(*dst, p, entry->value);
+            qdict_del(src, entry->key);
+        }
+        entry = next;
+    }
+}
+
 /*
  * Opens a disk image (raw, qcow2, vmdk, ...)
  *
@@ -825,6 +870,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
     /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
     char tmp_filename[PATH_MAX + 1];
     BlockDriverState *file = NULL;
+    QDict *file_options = NULL;
 
     /* NULL means an empty set of options */
     if (options == NULL) {
@@ -896,7 +942,10 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
         flags |= BDRV_O_ALLOW_RDWR;
     }
 
-    ret = bdrv_file_open(&file, filename, NULL, bdrv_open_flags(bs, flags));
+    extract_subqdict(options, &file_options, "file.");
+
+    ret = bdrv_file_open(&file, filename, file_options,
+                         bdrv_open_flags(bs, flags));
     if (ret < 0) {
         goto fail;
     }
commit 787e4a8500020695eb391e2f1cc4767ee071d441
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 6 11:52:48 2013 +0100

    block: Add options QDict to bdrv_file_open() prototypes
    
    The new parameter is unused yet.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/block.c b/block.c
index 22647b2..0fb0165 100644
--- a/block.c
+++ b/block.c
@@ -708,7 +708,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
             bdrv_swap(file, bs);
             ret = 0;
         } else {
-            ret = drv->bdrv_file_open(bs, filename, open_flags);
+            ret = drv->bdrv_file_open(bs, filename, options, open_flags);
         }
     } else {
         assert(file != NULL);
@@ -742,13 +742,21 @@ free_and_fail:
 
 /*
  * Opens a file using a protocol (file, host_device, nbd, ...)
+ *
+ * options is a QDict of options to pass to the block drivers, or NULL for an
+ * empty set of options. The reference to the QDict belongs to the block layer
+ * after the call (even on failure), so if the caller intends to reuse the
+ * dictionary, it needs to use QINCREF() before calling bdrv_file_open.
  */
-int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
+int bdrv_file_open(BlockDriverState **pbs, const char *filename,
+                   QDict *options, int flags)
 {
     BlockDriverState *bs;
     BlockDriver *drv;
     int ret;
 
+    QDECREF(options);
+
     drv = bdrv_find_protocol(filename);
     if (!drv) {
         return -ENOENT;
@@ -888,7 +896,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
         flags |= BDRV_O_ALLOW_RDWR;
     }
 
-    ret = bdrv_file_open(&file, filename, bdrv_open_flags(bs, flags));
+    ret = bdrv_file_open(&file, filename, NULL, bdrv_open_flags(bs, flags));
     if (ret < 0) {
         goto fail;
     }
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 6f74637..37cfbc7 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -304,7 +304,8 @@ fail:
 }
 
 /* Valid blkdebug filenames look like blkdebug:path/to/config:path/to/image */
-static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags)
+static int blkdebug_open(BlockDriverState *bs, const char *filename,
+                         QDict *options, int flags)
 {
     BDRVBlkdebugState *s = bs->opaque;
     int ret;
@@ -335,7 +336,7 @@ static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags)
     s->state = 1;
 
     /* Open the backing file */
-    ret = bdrv_file_open(&bs->file, filename, flags);
+    ret = bdrv_file_open(&bs->file, filename, NULL, flags);
     if (ret < 0) {
         return ret;
     }
diff --git a/block/blkverify.c b/block/blkverify.c
index 2086d97..59e3b05 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -69,7 +69,8 @@ static void GCC_FMT_ATTR(2, 3) blkverify_err(BlkverifyAIOCB *acb,
 }
 
 /* Valid blkverify filenames look like blkverify:path/to/raw_image:path/to/image */
-static int blkverify_open(BlockDriverState *bs, const char *filename, int flags)
+static int blkverify_open(BlockDriverState *bs, const char *filename,
+                          QDict *options, int flags)
 {
     BDRVBlkverifyState *s = bs->opaque;
     int ret;
@@ -89,7 +90,7 @@ static int blkverify_open(BlockDriverState *bs, const char *filename, int flags)
 
     raw = g_strdup(filename);
     raw[c - filename] = '\0';
-    ret = bdrv_file_open(&bs->file, raw, flags);
+    ret = bdrv_file_open(&bs->file, raw, NULL, flags);
     g_free(raw);
     if (ret < 0) {
         return ret;
diff --git a/block/cow.c b/block/cow.c
index d73e08c..9f94599 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -279,7 +279,7 @@ static int cow_create(const char *filename, QEMUOptionParameter *options)
         return ret;
     }
 
-    ret = bdrv_file_open(&cow_bs, filename, BDRV_O_RDWR);
+    ret = bdrv_file_open(&cow_bs, filename, NULL, BDRV_O_RDWR);
     if (ret < 0) {
         return ret;
     }
diff --git a/block/curl.c b/block/curl.c
index 98947da..186e3b0 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -335,7 +335,8 @@ static void curl_clean_state(CURLState *s)
     s->in_use = 0;
 }
 
-static int curl_open(BlockDriverState *bs, const char *filename, int flags)
+static int curl_open(BlockDriverState *bs, const char *filename,
+                     QDict *options, int flags)
 {
     BDRVCURLState *s = bs->opaque;
     CURLState *state = NULL;
diff --git a/block/gluster.c b/block/gluster.c
index ccd684d..9ccd4d4 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -283,7 +283,7 @@ static int qemu_gluster_aio_flush_cb(void *opaque)
 }
 
 static int qemu_gluster_open(BlockDriverState *bs, const char *filename,
-    int bdrv_flags)
+    QDict *options, int bdrv_flags)
 {
     BDRVGlusterState *s = bs->opaque;
     int open_flags = O_BINARY;
diff --git a/block/iscsi.c b/block/iscsi.c
index 3d52921..51a2889 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -1007,7 +1007,8 @@ out:
  * We support iscsi url's on the form
  * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
  */
-static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
+static int iscsi_open(BlockDriverState *bs, const char *filename,
+                      QDict *options, int flags)
 {
     IscsiLun *iscsilun = bs->opaque;
     struct iscsi_context *iscsi = NULL;
@@ -1203,7 +1204,7 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options)
     bs.opaque = g_malloc0(sizeof(struct IscsiLun));
     iscsilun = bs.opaque;
 
-    ret = iscsi_open(&bs, filename, 0);
+    ret = iscsi_open(&bs, filename, NULL, 0);
     if (ret != 0) {
         goto out;
     }
diff --git a/block/nbd.c b/block/nbd.c
index a581294..0473908 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -376,7 +376,8 @@ static void nbd_teardown_connection(BlockDriverState *bs)
     closesocket(s->sock);
 }
 
-static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
+static int nbd_open(BlockDriverState *bs, const char* filename,
+                    QDict *options, int flags)
 {
     BDRVNBDState *s = bs->opaque;
     int result;
diff --git a/block/qcow.c b/block/qcow.c
index f6750a5..13d396b 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -679,7 +679,7 @@ static int qcow_create(const char *filename, QEMUOptionParameter *options)
         return ret;
     }
 
-    ret = bdrv_file_open(&qcow_bs, filename, BDRV_O_RDWR);
+    ret = bdrv_file_open(&qcow_bs, filename, NULL, BDRV_O_RDWR);
     if (ret < 0) {
         return ret;
     }
diff --git a/block/qcow2.c b/block/qcow2.c
index 98bb7f3..8ea696a 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1254,7 +1254,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
         return ret;
     }
 
-    ret = bdrv_file_open(&bs, filename, BDRV_O_RDWR);
+    ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR);
     if (ret < 0) {
         return ret;
     }
diff --git a/block/qed.c b/block/qed.c
index 46e12b3..4651403 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -558,7 +558,7 @@ static int qed_create(const char *filename, uint32_t cluster_size,
         return ret;
     }
 
-    ret = bdrv_file_open(&bs, filename, BDRV_O_RDWR | BDRV_O_CACHE_WB);
+    ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR | BDRV_O_CACHE_WB);
     if (ret < 0) {
         return ret;
     }
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 8a3cdbc..99ac869 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -303,7 +303,8 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
     return 0;
 }
 
-static int raw_open(BlockDriverState *bs, const char *filename, int flags)
+static int raw_open(BlockDriverState *bs, const char *filename,
+                    QDict *options, int flags)
 {
     BDRVRawState *s = bs->opaque;
 
@@ -1292,7 +1293,8 @@ static int check_hdev_writable(BDRVRawState *s)
     return 0;
 }
 
-static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
+static int hdev_open(BlockDriverState *bs, const char *filename,
+                     QDict *options, int flags)
 {
     BDRVRawState *s = bs->opaque;
     int ret;
@@ -1530,7 +1532,8 @@ static BlockDriver bdrv_host_device = {
 };
 
 #ifdef __linux__
-static int floppy_open(BlockDriverState *bs, const char *filename, int flags)
+static int floppy_open(BlockDriverState *bs, const char *filename,
+                       QDict *options, int flags)
 {
     BDRVRawState *s = bs->opaque;
     int ret;
@@ -1652,7 +1655,8 @@ static BlockDriver bdrv_host_floppy = {
     .bdrv_eject         = floppy_eject,
 };
 
-static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
+static int cdrom_open(BlockDriverState *bs, const char *filename,
+                      QDict *options, int flags)
 {
     BDRVRawState *s = bs->opaque;
 
@@ -1760,7 +1764,8 @@ static BlockDriver bdrv_host_cdrom = {
 #endif /* __linux__ */
 
 #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
-static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
+static int cdrom_open(BlockDriverState *bs, const char *filename,
+                      QDict *options, int flags)
 {
     BDRVRawState *s = bs->opaque;
     int ret;
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 54d3e53..bb67c4c 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -1126,7 +1126,8 @@ static int write_object(int fd, char *buf, uint64_t oid, int copies,
                              create, cache_flags);
 }
 
-static int sd_open(BlockDriverState *bs, const char *filename, int flags)
+static int sd_open(BlockDriverState *bs, const char *filename,
+                   QDict *options, int flags)
 {
     int ret, fd;
     uint32_t vid = 0;
@@ -1269,7 +1270,7 @@ static int sd_prealloc(const char *filename)
     void *buf = g_malloc0(SD_DATA_OBJ_SIZE);
     int ret;
 
-    ret = bdrv_file_open(&bs, filename, BDRV_O_RDWR);
+    ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR);
     if (ret < 0) {
         goto out;
     }
@@ -1367,7 +1368,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
             goto out;
         }
 
-        ret = bdrv_file_open(&bs, backing_file, 0);
+        ret = bdrv_file_open(&bs, backing_file, NULL, 0);
         if (ret < 0) {
             goto out;
         }
diff --git a/block/vmdk.c b/block/vmdk.c
index e92104a..7bad757 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -661,7 +661,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
 
         path_combine(extent_path, sizeof(extent_path),
                 desc_file_path, fname);
-        ret = bdrv_file_open(&extent_file, extent_path, bs->open_flags);
+        ret = bdrv_file_open(&extent_file, extent_path, NULL, bs->open_flags);
         if (ret) {
             return ret;
         }
diff --git a/block/vvfat.c b/block/vvfat.c
index b8eb38a..ef74c30 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -988,7 +988,8 @@ static void vvfat_rebind(BlockDriverState *bs)
     s->bs = bs;
 }
 
-static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
+static int vvfat_open(BlockDriverState *bs, const char* dirname,
+                      QDict *options, int flags)
 {
     BDRVVVFATState *s = bs->opaque;
     int i, cyls, heads, secs;
diff --git a/include/block/block.h b/include/block/block.h
index d4f34d6..9dc6aad 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -135,7 +135,8 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
 void bdrv_delete(BlockDriverState *bs);
 int bdrv_parse_cache_flags(const char *mode, int *flags);
 int bdrv_parse_discard_flags(const char *mode, int *flags);
-int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
+int bdrv_file_open(BlockDriverState **pbs, const char *filename,
+                   QDict *options, int flags);
 int bdrv_open_backing_file(BlockDriverState *bs);
 int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
               int flags, BlockDriver *drv);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index ce0aa26..fb2a136 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -83,7 +83,8 @@ struct BlockDriver {
     void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state);
 
     int (*bdrv_open)(BlockDriverState *bs, QDict *options, int flags);
-    int (*bdrv_file_open)(BlockDriverState *bs, const char *filename, int flags);
+    int (*bdrv_file_open)(BlockDriverState *bs, const char *filename,
+                          QDict *options, int flags);
     int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
                      uint8_t *buf, int nb_sectors);
     int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
diff --git a/qemu-io.c b/qemu-io.c
index 79be516..475a8bd 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1766,7 +1766,7 @@ static int openfile(char *name, int flags, int growable)
     }
 
     if (growable) {
-        if (bdrv_file_open(&bs, name, flags)) {
+        if (bdrv_file_open(&bs, name, NULL, flags)) {
             fprintf(stderr, "%s: can't open device %s\n", progname, name);
             return 1;
         }
commit 92b7a08d64e5e3129fa885f9d180e5bddcb76b42
Author: Peter Lieven <pl at dlhnet.de>
Date:   Mon Mar 11 11:04:24 2013 +0100

    block: complete all IOs before resizing a device
    
    this patch ensures that all pending IOs are completed
    before a device is resized. this is especially important
    if a device is shrinked as it the bdrv_check_request()
    result is invalidated.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 09f76b7..6f2b759 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1127,6 +1127,9 @@ void qmp_block_resize(const char *device, int64_t size, Error **errp)
         return;
     }
 
+    /* complete all in-flight operations before resizing the device */
+    bdrv_drain_all();
+
     switch (bdrv_truncate(bs, size)) {
     case 0:
         break;
commit 5c916681ae2383f0425bb8a3680ade9d055f5dfe
Author: Peter Lieven <pl at dlhnet.de>
Date:   Mon Mar 11 11:03:28 2013 +0100

    Revert "block: complete all IOs before .bdrv_truncate"
    
    brdv_truncate() is also called from readv/writev commands on self-
    growing file based storage. this will result in requests waiting
    for theirselves to complete.
    
    This reverts commit 9a665b2b8640e464f0a778216fc2dca8d02acf33.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 0a062c9..22647b2 100644
--- a/block.c
+++ b/block.c
@@ -2487,10 +2487,6 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
         return -EACCES;
     if (bdrv_in_use(bs))
         return -EBUSY;
-
-    /* There better not be any in-flight IOs when we truncate the device. */
-    bdrv_drain_all();
-
     ret = drv->bdrv_truncate(bs, offset);
     if (ret == 0) {
         ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
commit 01ed1d527c59356e6c4c9d54b5710a3c9e78ce4e
Author: liguang <lig.fnst at cn.fujitsu.com>
Date:   Fri Mar 22 16:44:14 2013 +0800

    qdev: remove redundant abort()
    
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: liguang <lig.fnst at cn.fujitsu.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 0b20280..708a058 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -117,11 +117,10 @@ DeviceState *qdev_create(BusState *bus, const char *name)
         if (bus) {
             error_report("Unknown device '%s' for bus '%s'", name,
                          object_get_typename(OBJECT(bus)));
-            abort();
         } else {
             error_report("Unknown device '%s' for default sysbus", name);
-            abort();
         }
+        abort();
     }
 
     return dev;
commit 082369e62c5bbaba89f173c2b803bc24115bb111
Author: liguang <lig.fnst at cn.fujitsu.com>
Date:   Fri Mar 22 16:44:13 2013 +0800

    gitignore: ignore more files
    
    ignore *.patch, *.gcda, *.gcno
    
    Signed-off-by: liguang <lig.fnst at cn.fujitsu.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/.gitignore b/.gitignore
index 27ad002..9c234a3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -80,6 +80,9 @@ fsdev/virtfs-proxy-helper.pod
 *.swp
 *.orig
 .pc
+*.patch
+*.gcda
+*.gcno
 patches
 pc-bios/bios-pq/status
 pc-bios/vgabios-pq/status
commit 294e4669a5ef1feacc6635d324fa4ba88062cce0
Author: 陳韋任 (Wei-Ren Chen) <chenwj at iis.sinica.edu.tw>
Date:   Wed Mar 20 11:42:08 2013 +0800

    Use proper term in TCG README
    
      In TCG, "target" means the host architecture for which TCG generates
    the code. Using "guest" rather than "target" to make the document more
    consistent.
    
    Signed-off-by: Chen Wei-Ren <chenwj at iis.sinica.edu.tw>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/tcg/README b/tcg/README
index 934e7af..063aeb9 100644
--- a/tcg/README
+++ b/tcg/README
@@ -14,6 +14,10 @@ the emulated architecture. As TCG started as a generic C backend used
 for cross compiling, it is assumed that the TCG target is different
 from the host, although it is never the case for QEMU.
 
+In this document, we use "guest" to specify what architecture we are
+emulating; "target" always means the TCG target, the machine on which
+we are running QEMU.
+
 A TCG "function" corresponds to a QEMU Translated Block (TB).
 
 A TCG "temporary" is a variable only live in a basic
@@ -379,7 +383,7 @@ double-word product T0.  The later is returned in two single-word outputs.
 
 Similar to mulu2, except the two inputs T1 and T2 are signed.
 
-********* 64-bit target on 32-bit host support
+********* 64-bit guest on 32-bit host support
 
 The following opcodes are internal to TCG.  Thus they are to be implemented by
 32-bit host code generators, but are not to be emitted by guest translators.
@@ -521,9 +525,9 @@ register.
   a better generated code, but it reduces the memory usage of TCG and
   the speed of the translation.
 
-- Don't hesitate to use helpers for complicated or seldom used target
+- Don't hesitate to use helpers for complicated or seldom used guest
   instructions. There is little performance advantage in using TCG to
-  implement target instructions taking more than about twenty TCG
+  implement guest instructions taking more than about twenty TCG
   instructions. Note that this rule of thumb is more applicable to
   helpers doing complex logic or arithmetic, where the C compiler has
   scope to do a good job of optimisation; it is less relevant where
@@ -531,9 +535,9 @@ register.
   inline TCG may still be faster for longer sequences.
 
 - The hard limit on the number of TCG instructions you can generate
-  per target instruction is set by MAX_OP_PER_INSTR in exec-all.h --
+  per guest instruction is set by MAX_OP_PER_INSTR in exec-all.h --
   you cannot exceed this without risking a buffer overrun.
 
 - Use the 'discard' instruction if you know that TCG won't be able to
   prove that a given global is "dead" at a given program point. The
-  x86 target uses it to improve the condition codes optimisation.
+  x86 guest uses it to improve the condition codes optimisation.
commit 9ca3f7f3160365de9030e1a6128a871625abe346
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Mar 21 10:01:49 2013 +0000

    target-ppc: Use NARROW_MODE macro for tlbie
    
    Removing conditional compilation in the process.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 3b47553..5e741d1 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -4320,15 +4320,14 @@ static void gen_tlbie(DisasContext *ctx)
         gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
         return;
     }
-#if defined(TARGET_PPC64)
-    if (!ctx->sf_mode) {
+    if (NARROW_MODE(ctx)) {
         TCGv t0 = tcg_temp_new();
         tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
         gen_helper_tlbie(cpu_env, t0);
         tcg_temp_free(t0);
-    } else
-#endif
+    } else {
         gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
+    }
 #endif
 }
 
commit c791fe8436cf6b93ddb035a5b7a87487da5f7b30
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Mar 21 10:01:48 2013 +0000

    target-ppc: Use NARROW_MODE macro for addresses
    
    Removing conditional compilation in the process.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index bd68ffc..3b47553 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2332,45 +2332,37 @@ static inline void gen_addr_imm_index(DisasContext *ctx, TCGv EA,
 
     simm &= ~maskl;
     if (rA(ctx->opcode) == 0) {
-#if defined(TARGET_PPC64)
-        if (!ctx->sf_mode) {
-            tcg_gen_movi_tl(EA, (uint32_t)simm);
-        } else
-#endif
+        if (NARROW_MODE(ctx)) {
+            simm = (uint32_t)simm;
+        }
         tcg_gen_movi_tl(EA, simm);
     } else if (likely(simm != 0)) {
         tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
-#if defined(TARGET_PPC64)
-        if (!ctx->sf_mode) {
+        if (NARROW_MODE(ctx)) {
             tcg_gen_ext32u_tl(EA, EA);
         }
-#endif
     } else {
-#if defined(TARGET_PPC64)
-        if (!ctx->sf_mode) {
+        if (NARROW_MODE(ctx)) {
             tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
-        } else
-#endif
-        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
+        } else {
+            tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
+        }
     }
 }
 
 static inline void gen_addr_reg_index(DisasContext *ctx, TCGv EA)
 {
     if (rA(ctx->opcode) == 0) {
-#if defined(TARGET_PPC64)
-        if (!ctx->sf_mode) {
+        if (NARROW_MODE(ctx)) {
             tcg_gen_ext32u_tl(EA, cpu_gpr[rB(ctx->opcode)]);
-        } else
-#endif
-        tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
+        } else {
+            tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
+        }
     } else {
         tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
-#if defined(TARGET_PPC64)
-        if (!ctx->sf_mode) {
+        if (NARROW_MODE(ctx)) {
             tcg_gen_ext32u_tl(EA, EA);
         }
-#endif
     }
 }
 
@@ -2378,13 +2370,10 @@ static inline void gen_addr_register(DisasContext *ctx, TCGv EA)
 {
     if (rA(ctx->opcode) == 0) {
         tcg_gen_movi_tl(EA, 0);
+    } else if (NARROW_MODE(ctx)) {
+        tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
     } else {
-#if defined(TARGET_PPC64)
-        if (!ctx->sf_mode) {
-            tcg_gen_ext32u_tl(EA, cpu_gpr[rA(ctx->opcode)]);
-        } else
-#endif
-            tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
+        tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
     }
 }
 
@@ -2392,11 +2381,9 @@ static inline void gen_addr_add(DisasContext *ctx, TCGv ret, TCGv arg1,
                                 target_long val)
 {
     tcg_gen_addi_tl(ret, arg1, val);
-#if defined(TARGET_PPC64)
-    if (!ctx->sf_mode) {
+    if (NARROW_MODE(ctx)) {
         tcg_gen_ext32u_tl(ret, ret);
     }
-#endif
 }
 
 static inline void gen_check_align(DisasContext *ctx, TCGv EA, int mask)
@@ -7586,11 +7573,9 @@ static inline void gen_addr_spe_imm_index(DisasContext *ctx, TCGv EA, int sh)
         tcg_gen_movi_tl(EA, uimm << sh);
     } else {
         tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
-#if defined(TARGET_PPC64)
-        if (!ctx->sf_mode) {
+        if (NARROW_MODE(ctx)) {
             tcg_gen_ext32u_tl(EA, EA);
         }
-#endif
     }
 }
 
commit 02765534f7aff83a975072e8a6fcc85364351ad5
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Mar 21 10:01:47 2013 +0000

    target-ppc: Use NARROW_MODE macro for comparisons
    
    Removing conditional compilation in the process.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 63d4dbc..bd68ffc 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -632,7 +632,6 @@ static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
     tcg_temp_free(t0);
 }
 
-#if defined(TARGET_PPC64)
 static inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
 {
     TCGv t0, t1;
@@ -656,68 +655,62 @@ static inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
     gen_op_cmp32(arg0, t0, s, crf);
     tcg_temp_free(t0);
 }
-#endif
 
 static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
 {
-#if defined(TARGET_PPC64)
-    if (!(ctx->sf_mode))
+    if (NARROW_MODE(ctx)) {
         gen_op_cmpi32(reg, 0, 1, 0);
-    else
-#endif
+    } else {
         gen_op_cmpi(reg, 0, 1, 0);
+    }
 }
 
 /* cmp */
 static void gen_cmp(DisasContext *ctx)
 {
-#if defined(TARGET_PPC64)
-    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
+    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
         gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                      1, crfD(ctx->opcode));
-    else
-#endif
+    } else {
         gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                    1, crfD(ctx->opcode));
+    }
 }
 
 /* cmpi */
 static void gen_cmpi(DisasContext *ctx)
 {
-#if defined(TARGET_PPC64)
-    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
+    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
         gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                       1, crfD(ctx->opcode));
-    else
-#endif
+    } else {
         gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                     1, crfD(ctx->opcode));
+    }
 }
 
 /* cmpl */
 static void gen_cmpl(DisasContext *ctx)
 {
-#if defined(TARGET_PPC64)
-    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
+    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
         gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                      0, crfD(ctx->opcode));
-    else
-#endif
+    } else {
         gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                    0, crfD(ctx->opcode));
+    }
 }
 
 /* cmpli */
 static void gen_cmpli(DisasContext *ctx)
 {
-#if defined(TARGET_PPC64)
-    if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
+    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
         gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
                       0, crfD(ctx->opcode));
-    else
-#endif
+    } else {
         gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
                     0, crfD(ctx->opcode));
+    }
 }
 
 /* isel (PowerPC 2.03 specification) */
@@ -761,11 +754,9 @@ static inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0,
         tcg_gen_andc_tl(cpu_ov, cpu_ov, t0);
     }
     tcg_temp_free(t0);
-#if defined(TARGET_PPC64)
-    if (!ctx->sf_mode) {
+    if (NARROW_MODE(ctx)) {
         tcg_gen_ext32s_tl(cpu_ov, cpu_ov);
     }
-#endif
     tcg_gen_shri_tl(cpu_ov, cpu_ov, TARGET_LONG_BITS - 1);
     tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
 }
commit e0c8f9ce85b360668a7c8cc77cb3b85fac0bd057
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Mar 21 10:01:46 2013 +0000

    target-ppc: Use NARROW_MODE macro for branches
    
    Removing conditional compilation in the process.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 47efcd7..63d4dbc 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -267,12 +267,10 @@ static inline void gen_set_access_type(DisasContext *ctx, int access_type)
 
 static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
 {
-#if defined(TARGET_PPC64)
-    if (ctx->sf_mode)
-        tcg_gen_movi_tl(cpu_nip, nip);
-    else
-#endif
-        tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
+    if (NARROW_MODE(ctx)) {
+        nip = (uint32_t)nip;
+    }
+    tcg_gen_movi_tl(cpu_nip, nip);
 }
 
 static inline void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
@@ -3352,10 +3350,9 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
 {
     TranslationBlock *tb;
     tb = ctx->tb;
-#if defined(TARGET_PPC64)
-    if (!ctx->sf_mode)
+    if (NARROW_MODE(ctx)) {
         dest = (uint32_t) dest;
-#endif
+    }
     if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
         likely(!ctx->singlestep_enabled)) {
         tcg_gen_goto_tb(n);
@@ -3383,12 +3380,10 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
 
 static inline void gen_setlr(DisasContext *ctx, target_ulong nip)
 {
-#if defined(TARGET_PPC64)
-    if (ctx->sf_mode == 0)
-        tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
-    else
-#endif
-        tcg_gen_movi_tl(cpu_lr, nip);
+    if (NARROW_MODE(ctx)) {
+        nip = (uint32_t)nip;
+    }
+    tcg_gen_movi_tl(cpu_lr, nip);
 }
 
 /* b ba bl bla */
@@ -3398,18 +3393,16 @@ static void gen_b(DisasContext *ctx)
 
     ctx->exception = POWERPC_EXCP_BRANCH;
     /* sign extend LI */
-#if defined(TARGET_PPC64)
-    if (ctx->sf_mode)
-        li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
-    else
-#endif
-        li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
-    if (likely(AA(ctx->opcode) == 0))
+    li = LI(ctx->opcode);
+    li = (li ^ 0x02000000) - 0x02000000;
+    if (likely(AA(ctx->opcode) == 0)) {
         target = ctx->nip + li - 4;
-    else
+    } else {
         target = li;
-    if (LK(ctx->opcode))
+    }
+    if (LK(ctx->opcode)) {
         gen_setlr(ctx, ctx->nip);
+    }
     gen_update_cfar(ctx, ctx->nip);
     gen_goto_tb(ctx, 0, target);
 }
@@ -3445,12 +3438,11 @@ static inline void gen_bcond(DisasContext *ctx, int type)
             return;
         }
         tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
-#if defined(TARGET_PPC64)
-        if (!ctx->sf_mode)
+        if (NARROW_MODE(ctx)) {
             tcg_gen_ext32u_tl(temp, cpu_ctr);
-        else
-#endif
+        } else {
             tcg_gen_mov_tl(temp, cpu_ctr);
+        }
         if (bo & 0x2) {
             tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
         } else {
@@ -3484,20 +3476,14 @@ static inline void gen_bcond(DisasContext *ctx, int type)
         gen_set_label(l1);
         gen_goto_tb(ctx, 1, ctx->nip);
     } else {
-#if defined(TARGET_PPC64)
-        if (!(ctx->sf_mode))
+        if (NARROW_MODE(ctx)) {
             tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
-        else
-#endif
+        } else {
             tcg_gen_andi_tl(cpu_nip, target, ~3);
+        }
         tcg_gen_exit_tb(0);
         gen_set_label(l1);
-#if defined(TARGET_PPC64)
-        if (!(ctx->sf_mode))
-            tcg_gen_movi_tl(cpu_nip, (uint32_t)ctx->nip);
-        else
-#endif
-            tcg_gen_movi_tl(cpu_nip, ctx->nip);
+        gen_update_nip(ctx, ctx->nip);
         tcg_gen_exit_tb(0);
     }
 }
commit 79482e5ab38a05ca8869040b0d8b8f451f16ff62
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Mar 21 10:01:45 2013 +0000

    target-ppc: Fix add and subf carry generation in narrow mode
    
    The set of computations used in b5a73f8d8a57e940f9bbeb399a9e47897522ee9a
    are only valid if the current word size == target_long size.  This failed
    to take ppc64 in 32-bit (narrow) mode into account.
    
    Add a NARROW_MODE macro to avoid conditional compilation.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index bb690f8..47efcd7 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -204,6 +204,13 @@ typedef struct DisasContext {
     int singlestep_enabled;
 } DisasContext;
 
+/* True when active word size < size of target_long.  */
+#ifdef TARGET_PPC64
+# define NARROW_MODE(C)  (!(C)->sf_mode)
+#else
+# define NARROW_MODE(C)  0
+#endif
+
 struct opc_handler_t {
     /* invalid bits for instruction 1 (Rc(opcode) == 0) */
     uint32_t inval1;
@@ -778,14 +785,26 @@ static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
     }
 
     if (compute_ca) {
-        TCGv zero = tcg_const_tl(0);
-        if (add_ca) {
-            tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, cpu_ca, zero);
-            tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, arg2, zero);
+        if (NARROW_MODE(ctx)) {
+            TCGv t1 = tcg_temp_new();
+            tcg_gen_ext32u_tl(t1, arg2);
+            tcg_gen_ext32u_tl(t0, arg1);
+            tcg_gen_add_tl(t0, t0, t1);
+            tcg_temp_free(t1);
+            if (add_ca) {
+                tcg_gen_add_tl(t0, t0, cpu_ca);
+            }
+            tcg_gen_shri_tl(cpu_ca, t0, 32);
         } else {
-            tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, arg2, zero);
+            TCGv zero = tcg_const_tl(0);
+            if (add_ca) {
+                tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, cpu_ca, zero);
+                tcg_gen_add2_tl(t0, cpu_ca, t0, cpu_ca, arg2, zero);
+            } else {
+                tcg_gen_add2_tl(t0, cpu_ca, arg1, zero, arg2, zero);
+            }
+            tcg_temp_free(zero);
         }
-        tcg_temp_free(zero);
     } else {
         tcg_gen_add_tl(t0, arg1, arg2);
         if (add_ca) {
@@ -1114,14 +1133,25 @@ static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
 {
     TCGv t0 = ret;
 
-    if (((add_ca && compute_ca) || compute_ov)
-        && (TCGV_EQUAL(ret, arg1) || TCGV_EQUAL(ret, arg2)))  {
+    if (compute_ov && (TCGV_EQUAL(ret, arg1) || TCGV_EQUAL(ret, arg2)))  {
         t0 = tcg_temp_new();
     }
 
-    if (add_ca) {
-        /* dest = ~arg1 + arg2 + ca.  */
-        if (compute_ca) {
+    if (compute_ca) {
+        /* dest = ~arg1 + arg2 [+ ca].  */
+        if (NARROW_MODE(ctx)) {
+            TCGv inv1 = tcg_temp_new();
+            tcg_gen_not_tl(inv1, arg1);
+            tcg_gen_ext32u_tl(t0, arg2);
+            tcg_gen_ext32u_tl(inv1, inv1);
+            if (add_ca) {
+                tcg_gen_add_tl(t0, t0, cpu_ca);
+            } else {
+                tcg_gen_addi_tl(t0, t0, 1);
+            }
+            tcg_gen_add_tl(t0, t0, inv1);
+            tcg_gen_shri_tl(cpu_ca, t0, 32);
+        } else if (add_ca) {
             TCGv zero, inv1 = tcg_temp_new();
             tcg_gen_not_tl(inv1, arg1);
             zero = tcg_const_tl(0);
@@ -1130,14 +1160,16 @@ static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
             tcg_temp_free(zero);
             tcg_temp_free(inv1);
         } else {
+            tcg_gen_setcond_tl(TCG_COND_GEU, cpu_ca, arg2, arg1);
             tcg_gen_sub_tl(t0, arg2, arg1);
-            tcg_gen_add_tl(t0, t0, cpu_ca);
-            tcg_gen_subi_tl(t0, t0, 1);
         }
+    } else if (add_ca) {
+        /* Since we're ignoring carry-out, we can simplify the
+           standard ~arg1 + arg2 + ca to arg2 - arg1 + ca - 1.  */
+        tcg_gen_sub_tl(t0, arg2, arg1);
+        tcg_gen_add_tl(t0, t0, cpu_ca);
+        tcg_gen_subi_tl(t0, t0, 1);
     } else {
-        if (compute_ca) {
-            tcg_gen_setcond_tl(TCG_COND_GEU, cpu_ca, arg2, arg1);
-        }
         tcg_gen_sub_tl(t0, arg2, arg1);
     }
 
commit b632a148b677b773ff155f9de840b37a653567b9
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Wed Mar 13 11:40:33 2013 +1100

    target-ppc: Use QOM method dispatch for MMU fault handling
    
    After previous cleanups, the many scattered checks of env->mmu_model in
    the ppc MMU implementation have, at least for "classic" hash MMUs been
    reduced (almost) to a single switch at the top of
    cpu_ppc_handle_mmu_fault().
    
    An explicit switch is still a pretty ugly way of handling this though.  Now
    that Andreas Färber's CPU QOM cleanups for ppc have gone in, it's quite
    straightforward to instead make the handle_mmu_fault function a QOM method
    on the CPU object.
    
    This patch implements such a scheme, initializing the method pointer at
    the same time as the mmu_model variable.  We need to keep the latter around
    for now, because of the MMU types (BookE, 4xx, et al) which haven't been
    converted to the new scheme yet, and also for a few other uses.  It would
    be good to clean those up eventually.
    
    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/cpu-qom.h b/target-ppc/cpu-qom.h
index 09bfae3..c27cef7 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -68,6 +68,10 @@ typedef struct PowerPCCPUClass {
 #endif
     void (*init_proc)(CPUPPCState *env);
     int  (*check_pow)(CPUPPCState *env);
+#if defined(CONFIG_SOFTMMU)
+    int (*handle_mmu_fault)(CPUPPCState *env, target_ulong eaddr, int rwx,
+                            int mmu_idx);
+#endif
 } PowerPCCPUClass;
 
 /**
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 4c41673..acf0133 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -1391,22 +1391,6 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
     int access_type;
     int ret = 0;
 
-    switch (env->mmu_model) {
-#if defined(TARGET_PPC64)
-    case POWERPC_MMU_64B:
-    case POWERPC_MMU_2_06:
-    case POWERPC_MMU_2_06d:
-        return ppc_hash64_handle_mmu_fault(env, address, rw, mmu_idx);
-#endif
-
-    case POWERPC_MMU_32B:
-    case POWERPC_MMU_601:
-        return ppc_hash32_handle_mmu_fault(env, address, rw, mmu_idx);
-
-    default:
-        ; /* Otherwise fall through to the general code below */
-    }
-
     if (rw == 2) {
         /* code access */
         rw = 0;
@@ -2802,9 +2786,15 @@ void helper_booke206_tlbflush(CPUPPCState *env, uint32_t type)
 void tlb_fill(CPUPPCState *env, target_ulong addr, int is_write, int mmu_idx,
               uintptr_t retaddr)
 {
+    CPUState *cpu = ENV_GET_CPU(env);
+    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
     int ret;
 
-    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx);
+    if (pcc->handle_mmu_fault) {
+        ret = pcc->handle_mmu_fault(env, addr, is_write, mmu_idx);
+    } else {
+        ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx);
+    }
     if (unlikely(ret != 0)) {
         if (likely(retaddr)) {
             /* now we have a real cpu fault */
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 2780f92..781170f 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -25,6 +25,8 @@
 #include "sysemu/arch_init.h"
 #include "sysemu/cpus.h"
 #include "cpu-models.h"
+#include "mmu-hash32.h"
+#include "mmu-hash64.h"
 
 //#define PPC_DUMP_CPU
 //#define PPC_DEBUG_SPR
@@ -4796,6 +4798,9 @@ POWERPC_FAMILY(601)(ObjectClass *oc, void *data)
     pcc->insns_flags2 = PPC_NONE;
     pcc->msr_mask = 0x000000000000FD70ULL;
     pcc->mmu_model = POWERPC_MMU_601;
+#if defined(CONFIG_SOFTMMU)
+    pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
+#endif
     pcc->excp_model = POWERPC_EXCP_601;
     pcc->bus_model = PPC_FLAGS_INPUT_6xx;
     pcc->bfd_mach = bfd_mach_ppc_601;
@@ -4830,7 +4835,9 @@ POWERPC_FAMILY(601v)(ObjectClass *oc, void *data)
     pcc->insns_flags2 = PPC_NONE;
     pcc->msr_mask = 0x000000000000FD70ULL;
     pcc->mmu_model = POWERPC_MMU_601;
-    pcc->excp_model = POWERPC_EXCP_601;
+#if defined(CONFIG_SOFTMMU)
+    pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
+#endif
     pcc->bus_model = PPC_FLAGS_INPUT_6xx;
     pcc->bfd_mach = bfd_mach_ppc_601;
     pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_RTC_CLK;
@@ -5037,6 +5044,9 @@ POWERPC_FAMILY(604)(ObjectClass *oc, void *data)
     pcc->insns_flags2 = PPC_NONE;
     pcc->msr_mask = 0x000000000005FF77ULL;
     pcc->mmu_model = POWERPC_MMU_32B;
+#if defined(CONFIG_SOFTMMU)
+    pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
+#endif
     pcc->excp_model = POWERPC_EXCP_604;
     pcc->bus_model = PPC_FLAGS_INPUT_6xx;
     pcc->bfd_mach = bfd_mach_ppc_604;
@@ -5103,6 +5113,9 @@ POWERPC_FAMILY(604E)(ObjectClass *oc, void *data)
     pcc->insns_flags2 = PPC_NONE;
     pcc->msr_mask = 0x000000000005FF77ULL;
     pcc->mmu_model = POWERPC_MMU_32B;
+#if defined(CONFIG_SOFTMMU)
+    pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
+#endif
     pcc->excp_model = POWERPC_EXCP_604;
     pcc->bus_model = PPC_FLAGS_INPUT_6xx;
     pcc->bfd_mach = bfd_mach_ppc_604;
@@ -5156,6 +5169,9 @@ POWERPC_FAMILY(740)(ObjectClass *oc, void *data)
     pcc->insns_flags2 = PPC_NONE;
     pcc->msr_mask = 0x000000000005FF77ULL;
     pcc->mmu_model = POWERPC_MMU_32B;
+#if defined(CONFIG_SOFTMMU)
+    pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
+#endif
     pcc->excp_model = POWERPC_EXCP_7x0;
     pcc->bus_model = PPC_FLAGS_INPUT_6xx;
     pcc->bfd_mach = bfd_mach_ppc_750;
@@ -5217,6 +5233,9 @@ POWERPC_FAMILY(750)(ObjectClass *oc, void *data)
     pcc->insns_flags2 = PPC_NONE;
     pcc->msr_mask = 0x000000000005FF77ULL;
     pcc->mmu_model = POWERPC_MMU_32B;
+#if defined(CONFIG_SOFTMMU)
+    pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
+#endif
     pcc->excp_model = POWERPC_EXCP_7x0;
     pcc->bus_model = PPC_FLAGS_INPUT_6xx;
     pcc->bfd_mach = bfd_mach_ppc_750;
@@ -5401,6 +5420,9 @@ POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data)
     pcc->insns_flags2 = PPC_NONE;
     pcc->msr_mask = 0x000000000005FF77ULL;
     pcc->mmu_model = POWERPC_MMU_32B;
+#if defined(CONFIG_SOFTMMU)
+    pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
+#endif
     pcc->excp_model = POWERPC_EXCP_7x0;
     pcc->bus_model = PPC_FLAGS_INPUT_6xx;
     pcc->bfd_mach = bfd_mach_ppc_750;
@@ -5466,6 +5488,9 @@ POWERPC_FAMILY(750cx)(ObjectClass *oc, void *data)
     pcc->insns_flags2 = PPC_NONE;
     pcc->msr_mask = 0x000000000005FF77ULL;
     pcc->mmu_model = POWERPC_MMU_32B;
+#if defined(CONFIG_SOFTMMU)
+    pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
+#endif
     pcc->excp_model = POWERPC_EXCP_7x0;
     pcc->bus_model = PPC_FLAGS_INPUT_6xx;
     pcc->bfd_mach = bfd_mach_ppc_750;
@@ -5536,6 +5561,9 @@ POWERPC_FAMILY(750fx)(ObjectClass *oc, void *data)
     pcc->insns_flags2 = PPC_NONE;
     pcc->msr_mask = 0x000000000005FF77ULL;
     pcc->mmu_model = POWERPC_MMU_32B;
+#if defined(CONFIG_SOFTMMU)
+    pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
+#endif
     pcc->excp_model = POWERPC_EXCP_7x0;
     pcc->bus_model = PPC_FLAGS_INPUT_6xx;
     pcc->bfd_mach = bfd_mach_ppc_750;
@@ -5606,6 +5634,9 @@ POWERPC_FAMILY(750gx)(ObjectClass *oc, void *data)
     pcc->insns_flags2 = PPC_NONE;
     pcc->msr_mask = 0x000000000005FF77ULL;
     pcc->mmu_model = POWERPC_MMU_32B;
+#if defined(CONFIG_SOFTMMU)
+    pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
+#endif
     pcc->excp_model = POWERPC_EXCP_7x0;
     pcc->bus_model = PPC_FLAGS_INPUT_6xx;
     pcc->bfd_mach = bfd_mach_ppc_750;
@@ -5798,6 +5829,9 @@ POWERPC_FAMILY(7400)(ObjectClass *oc, void *data)
     pcc->insns_flags2 = PPC_NONE;
     pcc->msr_mask = 0x000000000205FF77ULL;
     pcc->mmu_model = POWERPC_MMU_32B;
+#if defined(CONFIG_SOFTMMU)
+    pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
+#endif
     pcc->excp_model = POWERPC_EXCP_74xx;
     pcc->bus_model = PPC_FLAGS_INPUT_6xx;
     pcc->bfd_mach = bfd_mach_ppc_7400;
@@ -5864,6 +5898,9 @@ POWERPC_FAMILY(7410)(ObjectClass *oc, void *data)
     pcc->insns_flags2 = PPC_NONE;
     pcc->msr_mask = 0x000000000205FF77ULL;
     pcc->mmu_model = POWERPC_MMU_32B;
+#if defined(CONFIG_SOFTMMU)
+    pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault;
+#endif
     pcc->excp_model = POWERPC_EXCP_74xx;
     pcc->bus_model = PPC_FLAGS_INPUT_6xx;
     pcc->bfd_mach = bfd_mach_ppc_7400;
@@ -6570,6 +6607,9 @@ POWERPC_FAMILY(970)(ObjectClass *oc, void *data)
     pcc->insns_flags2 = PPC_NONE;
     pcc->msr_mask = 0x900000000204FF36ULL;
     pcc->mmu_model = POWERPC_MMU_64B;
+#if defined(CONFIG_SOFTMMU)
+    pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
+#endif
     pcc->excp_model = POWERPC_EXCP_970;
     pcc->bus_model = PPC_FLAGS_INPUT_970;
     pcc->bfd_mach = bfd_mach_ppc64;
@@ -6680,6 +6720,9 @@ POWERPC_FAMILY(970FX)(ObjectClass *oc, void *data)
     pcc->insns_flags2 = PPC_NONE;
     pcc->msr_mask = 0x800000000204FF36ULL;
     pcc->mmu_model = POWERPC_MMU_64B;
+#if defined(CONFIG_SOFTMMU)
+    pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
+#endif
     pcc->excp_model = POWERPC_EXCP_970;
     pcc->bus_model = PPC_FLAGS_INPUT_970;
     pcc->bfd_mach = bfd_mach_ppc64;
@@ -6778,6 +6821,9 @@ POWERPC_FAMILY(970GX)(ObjectClass *oc, void *data)
     pcc->insns_flags2 = PPC_NONE;
     pcc->msr_mask = 0x800000000204FF36ULL;
     pcc->mmu_model = POWERPC_MMU_64B;
+#if defined(CONFIG_SOFTMMU)
+    pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
+#endif
     pcc->excp_model = POWERPC_EXCP_970;
     pcc->bus_model = PPC_FLAGS_INPUT_970;
     pcc->bfd_mach = bfd_mach_ppc64;
@@ -6876,6 +6922,9 @@ POWERPC_FAMILY(970MP)(ObjectClass *oc, void *data)
     pcc->insns_flags2 = PPC_NONE;
     pcc->msr_mask = 0x900000000204FF36ULL;
     pcc->mmu_model = POWERPC_MMU_64B;
+#if defined(CONFIG_SOFTMMU)
+    pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
+#endif
     pcc->excp_model = POWERPC_EXCP_970;
     pcc->bus_model = PPC_FLAGS_INPUT_970;
     pcc->bfd_mach = bfd_mach_ppc64;
@@ -6968,6 +7017,9 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
     pcc->insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX;
     pcc->msr_mask = 0x800000000204FF36ULL;
     pcc->mmu_model = POWERPC_MMU_2_06;
+#if defined(CONFIG_SOFTMMU)
+    pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
+#endif
     pcc->excp_model = POWERPC_EXCP_POWER7;
     pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
     pcc->bfd_mach = bfd_mach_ppc64;
commit eb20c1c6da60c8c75f08def03b0822a48af620ac
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:49 2013 +0000

    target-ppc: Move ppc tlb_fill implementation into mmu_helper.c
    
    For softmmu builds the interface from the generic code to the target
    specific MMU implementation is through the tlb_fill() function.  For ppc
    this is currently in mem_helper.c, whereas it would make more sense in
    mmu_helper.c.  This patch moves it, which also allows
    cpu_ppc_handle_mmu_fault() to become a local function in mmu_helper.c
    
    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/cpu.h b/target-ppc/cpu.h
index 1777438..42c36e2 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1090,8 +1090,6 @@ int cpu_ppc_exec (CPUPPCState *s);
    is returned if the signal was handled by the virtual CPU.  */
 int cpu_ppc_signal_handler (int host_signum, void *pinfo,
                             void *puc);
-int cpu_ppc_handle_mmu_fault (CPUPPCState *env, target_ulong address, int rw,
-                              int mmu_idx);
 void ppc_hw_interrupt (CPUPPCState *env);
 #if defined(CONFIG_USER_ONLY)
 int cpu_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
diff --git a/target-ppc/mem_helper.c b/target-ppc/mem_helper.c
index ba383c8..9783e52 100644
--- a/target-ppc/mem_helper.c
+++ b/target-ppc/mem_helper.c
@@ -252,41 +252,3 @@ STVE(stvewx, cpu_stl_data, bswap32, u32)
 
 #undef HI_IDX
 #undef LO_IDX
-
-/*****************************************************************************/
-/* Softmmu support */
-#if !defined(CONFIG_USER_ONLY)
-
-#define MMUSUFFIX _mmu
-
-#define SHIFT 0
-#include "exec/softmmu_template.h"
-
-#define SHIFT 1
-#include "exec/softmmu_template.h"
-
-#define SHIFT 2
-#include "exec/softmmu_template.h"
-
-#define SHIFT 3
-#include "exec/softmmu_template.h"
-
-/* 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(CPUPPCState *env, target_ulong addr, int is_write, int mmu_idx,
-              uintptr_t retaddr)
-{
-    int ret;
-
-    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx);
-    if (unlikely(ret != 0)) {
-        if (likely(retaddr)) {
-            /* now we have a real cpu fault */
-            cpu_restore_state(env, retaddr);
-        }
-        helper_raise_exception_err(env, env->exception_index, env->error_code);
-    }
-}
-#endif /* !CONFIG_USER_ONLY */
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 525eb6f..4c41673 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -1384,8 +1384,8 @@ static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
 }
 
 /* Perform address translation */
-int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
-                             int mmu_idx)
+static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address,
+                                    int rw, int mmu_idx)
 {
     mmu_ctx_t ctx;
     int access_type;
@@ -2777,3 +2777,39 @@ void helper_booke206_tlbflush(CPUPPCState *env, uint32_t type)
 
     booke206_flush_tlb(env, flags, 1);
 }
+
+
+/*****************************************************************************/
+
+#define MMUSUFFIX _mmu
+
+#define SHIFT 0
+#include "exec/softmmu_template.h"
+
+#define SHIFT 1
+#include "exec/softmmu_template.h"
+
+#define SHIFT 2
+#include "exec/softmmu_template.h"
+
+#define SHIFT 3
+#include "exec/softmmu_template.h"
+
+/* 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(CPUPPCState *env, target_ulong addr, int is_write, int mmu_idx,
+              uintptr_t retaddr)
+{
+    int ret;
+
+    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx);
+    if (unlikely(ret != 0)) {
+        if (likely(retaddr)) {
+            /* now we have a real cpu fault */
+            cpu_restore_state(env, retaddr);
+        }
+        helper_raise_exception_err(env, env->exception_index, env->error_code);
+    }
+}
commit cc8eae8ac7a493b6968238cf8aa5a21026858bae
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:48 2013 +0000

    target-ppc: Split user only code out of mmu_helper.c
    
    mmu_helper.c is, for obvious reasons, almost entirely concerned with
    softmmu builds of qemu.  However, it does contain one stub function which
    is used when CONFIG_USER_ONLY=y - the user only versoin of
    cpu_ppc_handle_mmu_fault, which always triggers an exception.  The entire
    rest of the file is surrounded by #if !defined(CONFIG_USER_ONLY).
    
    We clean this up by moving the user only stub into its own new file,
    removing the ifdefs and building mmu_helper.c only when CONFIG_SOFTMMU
    is set.  This also lets us remove the #define of cpu_handle_mmu_fault to
    cpu_ppc_handle_mmu_fault - that name is only used from generic code for
    user only - so we just name our split user version by the generic name.
    
    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/Makefile.objs b/target-ppc/Makefile.objs
index c80911f..2c43c34 100644
--- a/target-ppc/Makefile.objs
+++ b/target-ppc/Makefile.objs
@@ -1,14 +1,14 @@
 obj-y += cpu-models.o
 obj-y += translate.o
 ifeq ($(CONFIG_SOFTMMU),y)
-obj-y += machine.o mmu-hash32.o
+obj-y += machine.o mmu_helper.o mmu-hash32.o
 obj-$(TARGET_PPC64) += mmu-hash64.o
 endif
 obj-$(CONFIG_KVM) += kvm.o kvm_ppc.o
 obj-y += excp_helper.o
 obj-y += fpu_helper.o
 obj-y += int_helper.o
-obj-y += mmu_helper.o
 obj-y += timebase_helper.o
 obj-y += misc_helper.o
 obj-y += mem_helper.o
+obj-$(CONFIG_USER_ONLY) += user_only_helper.o
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index eb793e0..1777438 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1092,8 +1092,11 @@ int cpu_ppc_signal_handler (int host_signum, void *pinfo,
                             void *puc);
 int cpu_ppc_handle_mmu_fault (CPUPPCState *env, target_ulong address, int rw,
                               int mmu_idx);
-#define cpu_handle_mmu_fault cpu_ppc_handle_mmu_fault
 void ppc_hw_interrupt (CPUPPCState *env);
+#if defined(CONFIG_USER_ONLY)
+int cpu_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
+                         int mmu_idx);
+#endif
 
 #if !defined(CONFIG_USER_ONLY)
 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index c780ce1..525eb6f 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -52,31 +52,6 @@
 
 /*****************************************************************************/
 /* PowerPC MMU emulation */
-#if defined(CONFIG_USER_ONLY)
-int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
-                             int mmu_idx)
-{
-    int exception, error_code;
-
-    if (rw == 2) {
-        exception = POWERPC_EXCP_ISI;
-        error_code = 0x40000000;
-    } else {
-        exception = POWERPC_EXCP_DSI;
-        error_code = 0x40000000;
-        if (rw) {
-            error_code |= 0x02000000;
-        }
-        env->spr[SPR_DAR] = address;
-        env->spr[SPR_DSISR] = error_code;
-    }
-    env->exception_index = exception;
-    env->error_code = error_code;
-
-    return 1;
-}
-
-#else
 
 /* Context used internally during MMU translations */
 typedef struct mmu_ctx_t mmu_ctx_t;
@@ -2027,9 +2002,7 @@ void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
 #endif
     }
 }
-#endif /* !defined(CONFIG_USER_ONLY) */
 
-#if !defined(CONFIG_USER_ONLY)
 /* TLB management */
 void helper_tlbia(CPUPPCState *env)
 {
@@ -2804,4 +2777,3 @@ void helper_booke206_tlbflush(CPUPPCState *env, uint32_t type)
 
     booke206_flush_tlb(env, flags, 1);
 }
-#endif
diff --git a/target-ppc/user_only_helper.c b/target-ppc/user_only_helper.c
new file mode 100644
index 0000000..56e686e
--- /dev/null
+++ b/target-ppc/user_only_helper.c
@@ -0,0 +1,44 @@
+/*
+ *  PowerPC MMU stub handling for user mode emulation
+ *
+ *  Copyright (c) 2003-2007 Jocelyn Mayer
+ *  Copyright (c) 2013 David Gibson, IBM Corporation.
+ *
+ * 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 "cpu.h"
+
+int cpu_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
+                         int mmu_idx)
+{
+    int exception, error_code;
+
+    if (rw == 2) {
+        exception = POWERPC_EXCP_ISI;
+        error_code = 0x40000000;
+    } else {
+        exception = POWERPC_EXCP_DSI;
+        error_code = 0x40000000;
+        if (rw) {
+            error_code |= 0x02000000;
+        }
+        env->spr[SPR_DAR] = address;
+        env->spr[SPR_DSISR] = error_code;
+    }
+    env->exception_index = exception;
+    env->error_code = error_code;
+
+    return 1;
+}
commit f80872e21c07edd06eb343eeeefc8af404b518a6
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:47 2013 +0000

    mmu-hash64: Implement Virtual Page Class Key Protection
    
    Version 2.06 of the Power architecture describes an additional page
    protection mechanism.  Each virtual page has a "class" (0-31) recorded in
    the PTE.  The AMR register contains bits which can prohibit reads and/or
    writes on a class by class basis.  Interestingly, the AMR is userspace
    readable and writable, however user mode writes are masked by the contents
    of the UAMOR which is privileged.
    
    This patch implements this protection mechanism, along with the AMR and
    UAMOR SPRs.  The architecture also specifies a hypervisor-privileged AMOR
    register which masks user and supervisor writes to the AMR and UAMOR.  We
    leave this out for now, since we don't at present model hypervisor mode
    correctly in any case.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    [agraf: fix 32-bit hosts]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index e96afa6..eb793e0 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -113,11 +113,13 @@ enum powerpc_mmu_t {
 #if defined(TARGET_PPC64)
 #define POWERPC_MMU_64       0x00010000
 #define POWERPC_MMU_1TSEG    0x00020000
+#define POWERPC_MMU_AMR      0x00040000
     /* 64 bits PowerPC MMU                                     */
     POWERPC_MMU_64B        = POWERPC_MMU_64 | 0x00000001,
     /* Architecture 2.06 variant                               */
-    POWERPC_MMU_2_06       = POWERPC_MMU_64 | POWERPC_MMU_1TSEG | 0x00000003,
-    /* Architecture 2.06 "degraded" (no 1T segments)           */
+    POWERPC_MMU_2_06       = POWERPC_MMU_64 | POWERPC_MMU_1TSEG
+                             | POWERPC_MMU_AMR | 0x00000003,
+    /* Architecture 2.06 "degraded" (no 1T segments or AMR)    */
     POWERPC_MMU_2_06d      = POWERPC_MMU_64 | 0x00000003,
 #endif /* defined(TARGET_PPC64) */
 };
@@ -1223,6 +1225,7 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
 #define SPR_601_UDECR         (0x006)
 #define SPR_LR                (0x008)
 #define SPR_CTR               (0x009)
+#define SPR_UAMR              (0x00C)
 #define SPR_DSCR              (0x011)
 #define SPR_DSISR             (0x012)
 #define SPR_DAR               (0x013) /* DAE for PowerPC 601 */
@@ -1260,6 +1263,7 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
 #define SPR_MPC_CMPH          (0x09B)
 #define SPR_MPC_LCTRL1        (0x09C)
 #define SPR_MPC_LCTRL2        (0x09D)
+#define SPR_UAMOR             (0x09D)
 #define SPR_MPC_ICTRL         (0x09E)
 #define SPR_MPC_BAR           (0x09F)
 #define SPR_VRSAVE            (0x100)
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index f18c98f..43ccf45 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -275,6 +275,33 @@ static int ppc_hash64_pte_prot(CPUPPCState *env,
     return prot;
 }
 
+static int ppc_hash64_amr_prot(CPUPPCState *env, ppc_hash_pte64_t pte)
+{
+    int key, amrbits;
+    int prot = PAGE_EXEC;
+
+
+    /* Only recent MMUs implement Virtual Page Class Key Protection */
+    if (!(env->mmu_model & POWERPC_MMU_AMR)) {
+        return PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+    }
+
+    key = HPTE64_R_KEY(pte.pte1);
+    amrbits = (env->spr[SPR_AMR] >> 2*(31 - key)) & 0x3;
+
+    /* fprintf(stderr, "AMR protection: key=%d AMR=0x%" PRIx64 "\n", key, */
+    /*         env->spr[SPR_AMR]); */
+
+    if (amrbits & 0x2) {
+        prot |= PAGE_WRITE;
+    }
+    if (amrbits & 0x1) {
+        prot |= PAGE_READ;
+    }
+
+    return prot;
+}
+
 static hwaddr ppc_hash64_pteg_search(CPUPPCState *env, hwaddr pteg_off,
                                      bool secondary, target_ulong ptem,
                                      ppc_hash_pte64_t *pte)
@@ -375,7 +402,7 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong eaddr,
     ppc_slb_t *slb;
     hwaddr pte_offset;
     ppc_hash_pte64_t pte;
-    int prot;
+    int pp_prot, amr_prot, prot;
     uint64_t new_pte1;
     const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC};
     hwaddr raddr;
@@ -437,7 +464,9 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong eaddr,
 
     /* 5. Check access permissions */
 
-    prot = ppc_hash64_pte_prot(env, slb, pte);
+    pp_prot = ppc_hash64_pte_prot(env, slb, pte);
+    amr_prot = ppc_hash64_amr_prot(env, pte);
+    prot = pp_prot & amr_prot;
 
     if ((need_prot[rwx] & ~prot) != 0) {
         /* Access right violation */
@@ -446,14 +475,21 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong eaddr,
             env->exception_index = POWERPC_EXCP_ISI;
             env->error_code = 0x08000000;
         } else {
+            target_ulong dsisr = 0;
+
             env->exception_index = POWERPC_EXCP_DSI;
             env->error_code = 0;
             env->spr[SPR_DAR] = eaddr;
+            if (need_prot[rwx] & ~pp_prot) {
+                dsisr |= 0x08000000;
+            }
             if (rwx == 1) {
-                env->spr[SPR_DSISR] = 0x0A000000;
-            } else {
-                env->spr[SPR_DSISR] = 0x08000000;
+                dsisr |= 0x02000000;
+            }
+            if (need_prot[rwx] & ~amr_prot) {
+                dsisr |= 0x00200000;
             }
+            env->spr[SPR_DSISR] = dsisr;
         }
         return 1;
     }
diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h
index 37ed7ca..55f5a23 100644
--- a/target-ppc/mmu-hash64.h
+++ b/target-ppc/mmu-hash64.h
@@ -69,6 +69,8 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
 #define HPTE64_R_C              0x0000000000000080ULL
 #define HPTE64_R_R              0x0000000000000100ULL
 #define HPTE64_R_KEY_LO         0x0000000000000e00ULL
+#define HPTE64_R_KEY(x)         ((((x) & HPTE64_R_KEY_HI) >> 60) | \
+                                 (((x) & HPTE64_R_KEY_LO) >> 9))
 
 #define HPTE64_V_1TB_SEG        0x4000000000000000ULL
 #define HPTE64_V_VRMA_MASK      0x4001ffffff000000ULL
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 09fb29e..2780f92 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -1017,6 +1017,54 @@ static void gen_spr_7xx (CPUPPCState *env)
                  0x00000000);
 }
 
+#ifdef TARGET_PPC64
+#ifndef CONFIG_USER_ONLY
+static void spr_read_uamr (void *opaque, int gprn, int sprn)
+{
+    gen_load_spr(cpu_gpr[gprn], SPR_AMR);
+    spr_load_dump_spr(SPR_AMR);
+}
+
+static void spr_write_uamr (void *opaque, int sprn, int gprn)
+{
+    gen_store_spr(SPR_AMR, cpu_gpr[gprn]);
+    spr_store_dump_spr(SPR_AMR);
+}
+
+static void spr_write_uamr_pr (void *opaque, int sprn, int gprn)
+{
+    TCGv t0 = tcg_temp_new();
+
+    gen_load_spr(t0, SPR_UAMOR);
+    tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]);
+    gen_store_spr(SPR_AMR, t0);
+    spr_store_dump_spr(SPR_AMR);
+}
+#endif /* CONFIG_USER_ONLY */
+
+static void gen_spr_amr (CPUPPCState *env)
+{
+#ifndef CONFIG_USER_ONLY
+    /* Virtual Page Class Key protection */
+    /* The AMR is accessible either via SPR 13 or SPR 29.  13 is
+     * userspace accessible, 29 is privileged.  So we only need to set
+     * the kvm ONE_REG id on one of them, we use 29 */
+    spr_register(env, SPR_UAMR, "UAMR",
+                 &spr_read_uamr, &spr_write_uamr_pr,
+                 &spr_read_uamr, &spr_write_uamr,
+                 0);
+    spr_register_kvm(env, SPR_AMR, "AMR",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_AMR, 0xffffffffffffffffULL);
+    spr_register_kvm(env, SPR_UAMOR, "UAMOR",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_UAMOR, 0);
+#endif /* !CONFIG_USER_ONLY */
+}
+#endif /* TARGET_PPC64 */
+
 static void gen_spr_thrm (CPUPPCState *env)
 {
     /* Thermal management */
@@ -6872,6 +6920,7 @@ static void init_proc_POWER7 (CPUPPCState *env)
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, SPR_NOACCESS,
                  0x00000000); /* TOFIX */
+    gen_spr_amr(env);
     /* XXX : not implemented */
     spr_register(env, SPR_CTRL, "SPR_CTRLT",
                  SPR_NOACCESS, SPR_NOACCESS,
commit caa597bd9f5439cb16653119f362ad85a9f02b55
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:46 2013 +0000

    mmu-hash*: Merge translate and fault handling functions
    
    ppc_hash{32,64}_handle_mmu_fault() is now the only caller of
    ppc_hash{32,64{_translate(), so this patch combines them together.  This
    means that instead of one returning a variety of non-obvious error codes
    which then get translated into the various mmu exception conditions, we can
    just generate the exceptions as we discover problems in the translation
    path.  This also removes the last usage of mmu_ctx_hash{32,64}.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 5ec1a09..f6adf22 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -238,7 +238,9 @@ static int ppc_hash32_direct_store(CPUPPCState *env, target_ulong sr,
 
     if (rwx == 2) {
         /* No code fetch is allowed in direct-store areas */
-        return -4;
+        env->exception_index = POWERPC_EXCP_ISI;
+        env->error_code = 0x10000000;
+        return 1;
     }
 
     switch (env->access_type) {
@@ -247,10 +249,20 @@ static int ppc_hash32_direct_store(CPUPPCState *env, target_ulong sr,
         break;
     case ACCESS_FLOAT:
         /* Floating point load/store */
-        return -4;
+        env->exception_index = POWERPC_EXCP_ALIGN;
+        env->error_code = POWERPC_EXCP_ALIGN_FP;
+        env->spr[SPR_DAR] = eaddr;
+        return 1;
     case ACCESS_RES:
         /* lwarx, ldarx or srwcx. */
-        return -4;
+        env->error_code = 0;
+        env->spr[SPR_DAR] = eaddr;
+        if (rwx == 1) {
+            env->spr[SPR_DSISR] = 0x06000000;
+        } else {
+            env->spr[SPR_DSISR] = 0x04000000;
+        }
+        return 1;
     case ACCESS_CACHE:
         /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
         /* Should make the instruction do no-op.
@@ -260,17 +272,33 @@ static int ppc_hash32_direct_store(CPUPPCState *env, target_ulong sr,
         return 0;
     case ACCESS_EXT:
         /* eciwx or ecowx */
-        return -4;
+        env->exception_index = POWERPC_EXCP_DSI;
+        env->error_code = 0;
+        env->spr[SPR_DAR] = eaddr;
+        if (rwx == 1) {
+            env->spr[SPR_DSISR] = 0x06100000;
+        } else {
+            env->spr[SPR_DSISR] = 0x04100000;
+        }
+        return 1;
     default:
         qemu_log("ERROR: instruction should not need "
                  "address translation\n");
-        return -4;
+        abort();
     }
     if ((rwx == 1 || key != 1) && (rwx == 0 || key != 0)) {
         *raddr = eaddr;
-        return 2;
+        return 0;
     } else {
-        return -2;
+        env->exception_index = POWERPC_EXCP_DSI;
+        env->error_code = 0;
+        env->spr[SPR_DAR] = eaddr;
+        if (rwx == 1) {
+            env->spr[SPR_DSISR] = 0x0a000000;
+        } else {
+            env->spr[SPR_DSISR] = 0x08000000;
+        }
+        return 1;
     }
 }
 
@@ -352,32 +380,53 @@ static hwaddr ppc_hash32_pte_raddr(target_ulong sr, ppc_hash_pte32_t pte,
     return (rpn & ~mask) | (eaddr & mask);
 }
 
-static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
-                                target_ulong eaddr, int rwx)
+int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong eaddr, int rwx,
+                                int mmu_idx)
 {
     target_ulong sr;
     hwaddr pte_offset;
     ppc_hash_pte32_t pte;
+    int prot;
     uint32_t new_pte1;
     const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC};
+    hwaddr raddr;
 
     assert((rwx == 0) || (rwx == 1) || (rwx == 2));
 
     /* 1. Handle real mode accesses */
     if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
         /* Translation is off */
-        ctx->raddr = eaddr;
-        ctx->prot = PAGE_READ | PAGE_EXEC | PAGE_WRITE;
+        raddr = eaddr;
+        tlb_set_page(env, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
+                     PAGE_READ | PAGE_WRITE | PAGE_EXEC, mmu_idx,
+                     TARGET_PAGE_SIZE);
         return 0;
     }
 
     /* 2. Check Block Address Translation entries (BATs) */
     if (env->nb_BATs != 0) {
-        ctx->raddr = ppc_hash32_bat_lookup(env, eaddr, rwx, &ctx->prot);
-        if (ctx->raddr != -1) {
-            if (need_prot[rwx] & ~ctx->prot) {
-                return -2;
+        raddr = ppc_hash32_bat_lookup(env, eaddr, rwx, &prot);
+        if (raddr != -1) {
+            if (need_prot[rwx] & ~prot) {
+                if (rwx == 2) {
+                    env->exception_index = POWERPC_EXCP_ISI;
+                    env->error_code = 0x08000000;
+                } else {
+                    env->exception_index = POWERPC_EXCP_DSI;
+                    env->error_code = 0;
+                    env->spr[SPR_DAR] = eaddr;
+                    if (rwx == 1) {
+                        env->spr[SPR_DSISR] = 0x0a000000;
+                    } else {
+                        env->spr[SPR_DSISR] = 0x08000000;
+                    }
+                }
+                return 1;
             }
+
+            tlb_set_page(env, eaddr & TARGET_PAGE_MASK,
+                         raddr & TARGET_PAGE_MASK, prot, mmu_idx,
+                         TARGET_PAGE_SIZE);
             return 0;
         }
     }
@@ -387,30 +436,66 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
 
     /* 4. Handle direct store segments */
     if (sr & SR32_T) {
-        return ppc_hash32_direct_store(env, sr, eaddr, rwx,
-                                       &ctx->raddr, &ctx->prot);
+        if (ppc_hash32_direct_store(env, sr, eaddr, rwx,
+                                    &raddr, &prot) == 0) {
+            tlb_set_page(env, eaddr & TARGET_PAGE_MASK,
+                         raddr & TARGET_PAGE_MASK, prot, mmu_idx,
+                         TARGET_PAGE_SIZE);
+            return 0;
+        } else {
+            return 1;
+        }
     }
 
     /* 5. Check for segment level no-execute violation */
     if ((rwx == 2) && (sr & SR32_NX)) {
-        return -3;
+        env->exception_index = POWERPC_EXCP_ISI;
+        env->error_code = 0x10000000;
+        return 1;
     }
 
     /* 6. Locate the PTE in the hash table */
     pte_offset = ppc_hash32_htab_lookup(env, sr, eaddr, &pte);
     if (pte_offset == -1) {
-        return -1;
+        if (rwx == 2) {
+            env->exception_index = POWERPC_EXCP_ISI;
+            env->error_code = 0x40000000;
+        } else {
+            env->exception_index = POWERPC_EXCP_DSI;
+            env->error_code = 0;
+            env->spr[SPR_DAR] = eaddr;
+            if (rwx == 1) {
+                env->spr[SPR_DSISR] = 0x42000000;
+            } else {
+                env->spr[SPR_DSISR] = 0x40000000;
+            }
+        }
+
+        return 1;
     }
     LOG_MMU("found PTE at offset %08" HWADDR_PRIx "\n", pte_offset);
 
     /* 7. Check access permissions */
 
-    ctx->prot = ppc_hash32_pte_prot(env, sr, pte);
+    prot = ppc_hash32_pte_prot(env, sr, pte);
 
-    if (need_prot[rwx] & ~ctx->prot) {
+    if (need_prot[rwx] & ~prot) {
         /* Access right violation */
         LOG_MMU("PTE access rejected\n");
-        return -2;
+        if (rwx == 2) {
+            env->exception_index = POWERPC_EXCP_ISI;
+            env->error_code = 0x08000000;
+        } else {
+            env->exception_index = POWERPC_EXCP_DSI;
+            env->error_code = 0;
+            env->spr[SPR_DAR] = eaddr;
+            if (rwx == 1) {
+                env->spr[SPR_DSISR] = 0x0a000000;
+            } else {
+                env->spr[SPR_DSISR] = 0x08000000;
+            }
+        }
+        return 1;
     }
 
     LOG_MMU("PTE access granted !\n");
@@ -423,7 +508,7 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     } else {
         /* Treat the page as read-only for now, so that a later write
          * will pass through this function again to set the C bit */
-        ctx->prot &= ~PAGE_WRITE;
+        prot &= ~PAGE_WRITE;
     }
 
     if (new_pte1 != pte.pte1) {
@@ -432,7 +517,10 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
 
     /* 9. Determine the real address from the PTE */
 
-    ctx->raddr = ppc_hash32_pte_raddr(sr, pte, eaddr);
+    raddr = ppc_hash32_pte_raddr(sr, pte, eaddr);
+
+    tlb_set_page(env, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
+                 prot, mmu_idx, TARGET_PAGE_SIZE);
 
     return 0;
 }
@@ -470,117 +558,3 @@ hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong eaddr)
 
     return ppc_hash32_pte_raddr(sr, pte, eaddr) & TARGET_PAGE_MASK;
 }
-
-int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rwx,
-                                int mmu_idx)
-{
-    struct mmu_ctx_hash32 ctx;
-    int ret = 0;
-
-    ret = ppc_hash32_translate(env, &ctx, address, rwx);
-    if (ret == 0) {
-        tlb_set_page(env, address & TARGET_PAGE_MASK,
-                     ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
-                     mmu_idx, TARGET_PAGE_SIZE);
-        ret = 0;
-    } else if (ret < 0) {
-        LOG_MMU_STATE(env);
-        if (rwx == 2) {
-            switch (ret) {
-            case -1:
-                /* No matches in page tables or TLB */
-                env->exception_index = POWERPC_EXCP_ISI;
-                env->error_code = 0x40000000;
-                break;
-            case -2:
-                /* Access rights violation */
-                env->exception_index = POWERPC_EXCP_ISI;
-                env->error_code = 0x08000000;
-                break;
-            case -3:
-                /* No execute protection violation */
-                env->exception_index = POWERPC_EXCP_ISI;
-                env->error_code = 0x10000000;
-                break;
-            case -4:
-                /* Direct store exception */
-                /* No code fetch is allowed in direct-store areas */
-                env->exception_index = POWERPC_EXCP_ISI;
-                env->error_code = 0x10000000;
-                break;
-            }
-        } else {
-            switch (ret) {
-            case -1:
-                /* No matches in page tables or TLB */
-                env->exception_index = POWERPC_EXCP_DSI;
-                env->error_code = 0;
-                env->spr[SPR_DAR] = address;
-                if (rwx == 1) {
-                    env->spr[SPR_DSISR] = 0x42000000;
-                } else {
-                    env->spr[SPR_DSISR] = 0x40000000;
-                }
-                break;
-            case -2:
-                /* Access rights violation */
-                env->exception_index = POWERPC_EXCP_DSI;
-                env->error_code = 0;
-                env->spr[SPR_DAR] = address;
-                if (rwx == 1) {
-                    env->spr[SPR_DSISR] = 0x0A000000;
-                } else {
-                    env->spr[SPR_DSISR] = 0x08000000;
-                }
-                break;
-            case -4:
-                /* Direct store exception */
-                switch (env->access_type) {
-                case ACCESS_FLOAT:
-                    /* Floating point load/store */
-                    env->exception_index = POWERPC_EXCP_ALIGN;
-                    env->error_code = POWERPC_EXCP_ALIGN_FP;
-                    env->spr[SPR_DAR] = address;
-                    break;
-                case ACCESS_RES:
-                    /* lwarx, ldarx or stwcx. */
-                    env->exception_index = POWERPC_EXCP_DSI;
-                    env->error_code = 0;
-                    env->spr[SPR_DAR] = address;
-                    if (rwx == 1) {
-                        env->spr[SPR_DSISR] = 0x06000000;
-                    } else {
-                        env->spr[SPR_DSISR] = 0x04000000;
-                    }
-                    break;
-                case ACCESS_EXT:
-                    /* eciwx or ecowx */
-                    env->exception_index = POWERPC_EXCP_DSI;
-                    env->error_code = 0;
-                    env->spr[SPR_DAR] = address;
-                    if (rwx == 1) {
-                        env->spr[SPR_DSISR] = 0x06100000;
-                    } else {
-                        env->spr[SPR_DSISR] = 0x04100000;
-                    }
-                    break;
-                default:
-                    printf("DSI: invalid exception (%d)\n", ret);
-                    env->exception_index = POWERPC_EXCP_PROGRAM;
-                    env->error_code =
-                        POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
-                    env->spr[SPR_DAR] = address;
-                    break;
-                }
-                break;
-            }
-        }
-#if 0
-        printf("%s: set exception to %d %02x\n", __func__,
-               env->exception, env->error_code);
-#endif
-        ret = 1;
-    }
-
-    return ret;
-}
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 4a7dbbb..f18c98f 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -40,11 +40,6 @@
 #  define LOG_SLB(...) do { } while (0)
 #endif
 
-struct mmu_ctx_hash64 {
-    hwaddr raddr;      /* Real address              */
-    int prot;                      /* Protection bits           */
-};
-
 /*
  * SLB handling
  */
@@ -374,14 +369,16 @@ static hwaddr ppc_hash64_pte_raddr(ppc_slb_t *slb, ppc_hash_pte64_t pte,
     return (rpn & ~mask) | (eaddr & mask);
 }
 
-static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
-                                target_ulong eaddr, int rwx)
+int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong eaddr,
+                                int rwx, int mmu_idx)
 {
     ppc_slb_t *slb;
     hwaddr pte_offset;
     ppc_hash_pte64_t pte;
+    int prot;
     uint64_t new_pte1;
     const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC};
+    hwaddr raddr;
 
     assert((rwx == 0) || (rwx == 1) || (rwx == 2));
 
@@ -389,8 +386,10 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
     if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
         /* Translation is off */
         /* In real mode the top 4 effective address bits are ignored */
-        ctx->raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL;
-        ctx->prot = PAGE_READ | PAGE_EXEC | PAGE_WRITE;
+        raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL;
+        tlb_set_page(env, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
+                     PAGE_READ | PAGE_WRITE | PAGE_EXEC, mmu_idx,
+                     TARGET_PAGE_SIZE);
         return 0;
     }
 
@@ -398,29 +397,65 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
     slb = slb_lookup(env, eaddr);
 
     if (!slb) {
-        return -5;
+        if (rwx == 2) {
+            env->exception_index = POWERPC_EXCP_ISEG;
+            env->error_code = 0;
+        } else {
+            env->exception_index = POWERPC_EXCP_DSEG;
+            env->error_code = 0;
+            env->spr[SPR_DAR] = eaddr;
+        }
+        return 1;
     }
 
     /* 3. Check for segment level no-execute violation */
     if ((rwx == 2) && (slb->vsid & SLB_VSID_N)) {
-        return -3;
+        env->exception_index = POWERPC_EXCP_ISI;
+        env->error_code = 0x10000000;
+        return 1;
     }
 
     /* 4. Locate the PTE in the hash table */
     pte_offset = ppc_hash64_htab_lookup(env, slb, eaddr, &pte);
     if (pte_offset == -1) {
-        return -1;
+        if (rwx == 2) {
+            env->exception_index = POWERPC_EXCP_ISI;
+            env->error_code = 0x40000000;
+        } else {
+            env->exception_index = POWERPC_EXCP_DSI;
+            env->error_code = 0;
+            env->spr[SPR_DAR] = eaddr;
+            if (rwx == 1) {
+                env->spr[SPR_DSISR] = 0x42000000;
+            } else {
+                env->spr[SPR_DSISR] = 0x40000000;
+            }
+        }
+        return 1;
     }
     LOG_MMU("found PTE at offset %08" HWADDR_PRIx "\n", pte_offset);
 
     /* 5. Check access permissions */
 
-    ctx->prot = ppc_hash64_pte_prot(env, slb, pte);
+    prot = ppc_hash64_pte_prot(env, slb, pte);
 
-    if ((need_prot[rwx] & ~ctx->prot) != 0) {
+    if ((need_prot[rwx] & ~prot) != 0) {
         /* Access right violation */
         LOG_MMU("PTE access rejected\n");
-        return -2;
+        if (rwx == 2) {
+            env->exception_index = POWERPC_EXCP_ISI;
+            env->error_code = 0x08000000;
+        } else {
+            env->exception_index = POWERPC_EXCP_DSI;
+            env->error_code = 0;
+            env->spr[SPR_DAR] = eaddr;
+            if (rwx == 1) {
+                env->spr[SPR_DSISR] = 0x0A000000;
+            } else {
+                env->spr[SPR_DSISR] = 0x08000000;
+            }
+        }
+        return 1;
     }
 
     LOG_MMU("PTE access granted !\n");
@@ -433,7 +468,7 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
     } else {
         /* Treat the page as read-only for now, so that a later write
          * will pass through this function again to set the C bit */
-        ctx->prot &= ~PAGE_WRITE;
+        prot &= ~PAGE_WRITE;
     }
 
     if (new_pte1 != pte.pte1) {
@@ -442,7 +477,10 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
 
     /* 7. Determine the real address from the PTE */
 
-    ctx->raddr = ppc_hash64_pte_raddr(slb, pte, eaddr);
+    raddr = ppc_hash64_pte_raddr(slb, pte, eaddr);
+
+    tlb_set_page(env, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
+                 prot, mmu_idx, TARGET_PAGE_SIZE);
 
     return 0;
 }
@@ -470,81 +508,3 @@ hwaddr ppc_hash64_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
 
     return ppc_hash64_pte_raddr(slb, pte, addr) & TARGET_PAGE_MASK;
 }
-
-int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rwx,
-                                int mmu_idx)
-{
-    struct mmu_ctx_hash64 ctx;
-    int ret = 0;
-
-    ret = ppc_hash64_translate(env, &ctx, address, rwx);
-    if (ret == 0) {
-        tlb_set_page(env, address & TARGET_PAGE_MASK,
-                     ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
-                     mmu_idx, TARGET_PAGE_SIZE);
-        ret = 0;
-    } else if (ret < 0) {
-        LOG_MMU_STATE(env);
-        if (rwx == 2) {
-            switch (ret) {
-            case -1:
-                env->exception_index = POWERPC_EXCP_ISI;
-                env->error_code = 0x40000000;
-                break;
-            case -2:
-                /* Access rights violation */
-                env->exception_index = POWERPC_EXCP_ISI;
-                env->error_code = 0x08000000;
-                break;
-            case -3:
-                /* No execute protection violation */
-                env->exception_index = POWERPC_EXCP_ISI;
-                env->error_code = 0x10000000;
-                break;
-            case -5:
-                /* No match in segment table */
-                env->exception_index = POWERPC_EXCP_ISEG;
-                env->error_code = 0;
-                break;
-            }
-        } else {
-            switch (ret) {
-            case -1:
-                /* No matches in page tables or TLB */
-                env->exception_index = POWERPC_EXCP_DSI;
-                env->error_code = 0;
-                env->spr[SPR_DAR] = address;
-                if (rwx == 1) {
-                    env->spr[SPR_DSISR] = 0x42000000;
-                } else {
-                    env->spr[SPR_DSISR] = 0x40000000;
-                }
-                break;
-            case -2:
-                /* Access rights violation */
-                env->exception_index = POWERPC_EXCP_DSI;
-                env->error_code = 0;
-                env->spr[SPR_DAR] = address;
-                if (rwx == 1) {
-                    env->spr[SPR_DSISR] = 0x0A000000;
-                } else {
-                    env->spr[SPR_DSISR] = 0x08000000;
-                }
-                break;
-            case -5:
-                /* No match in segment table */
-                env->exception_index = POWERPC_EXCP_DSEG;
-                env->error_code = 0;
-                env->spr[SPR_DAR] = address;
-                break;
-            }
-        }
-#if 0
-        printf("%s: set exception to %d %02x\n", __func__,
-               env->exception, env->error_code);
-#endif
-        ret = 1;
-    }
-
-    return ret;
-}
commit 5883d8b29691e15c72e338a586509abfc65c3106
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:45 2013 +0000

    mmu-hash*: Don't use full ppc_hash{32, 64}_translate() path for get_phys_page_debug()
    
    Currently the hash mmu versionsof get_phys_page_debug() use the same
    ppc64_hash64_translate() function to do the translation logic as the normal
    mm fault handler code.
    
    That sounds like a good idea, but has some complications. The debug path
    doesn't need, or even want some parts of the full translation path, like
    permissions checking.  Furthermore, the pte flags update included in the
    normal path means that the debug call is not quite side effect free.
    
    This patch, therefore, reimplements get_phys_page_debug as the minimal
    required subset of the full translation path.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>`z
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 07e9b8c..5ec1a09 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -437,18 +437,38 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     return 0;
 }
 
-hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
+hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong eaddr)
 {
-    struct mmu_ctx_hash32 ctx;
+    target_ulong sr;
+    hwaddr pte_offset;
+    ppc_hash_pte32_t pte;
+    int prot;
+
+    if (msr_dr == 0) {
+        /* Translation is off */
+        return eaddr;
+    }
+
+    if (env->nb_BATs != 0) {
+        hwaddr raddr = ppc_hash32_bat_lookup(env, eaddr, 0, &prot);
+        if (raddr != -1) {
+            return raddr;
+        }
+    }
+
+    sr = env->sr[eaddr >> 28];
+
+    if (sr & SR32_T) {
+        /* FIXME: Add suitable debug support for Direct Store segments */
+        return -1;
+    }
 
-    /* FIXME: Will not behave sanely for direct store segments, but
-     * they're almost never used */
-    if (unlikely(ppc_hash32_translate(env, &ctx, addr, 0)
-                 != 0)) {
+    pte_offset = ppc_hash32_htab_lookup(env, sr, eaddr, &pte);
+    if (pte_offset == -1) {
         return -1;
     }
 
-    return ctx.raddr & TARGET_PAGE_MASK;
+    return ppc_hash32_pte_raddr(sr, pte, eaddr) & TARGET_PAGE_MASK;
 }
 
 int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rwx,
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index d986c0f..4a7dbbb 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -449,13 +449,26 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
 
 hwaddr ppc_hash64_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
 {
-    struct mmu_ctx_hash64 ctx;
+    ppc_slb_t *slb;
+    hwaddr pte_offset;
+    ppc_hash_pte64_t pte;
+
+    if (msr_dr == 0) {
+        /* In real mode the top 4 effective address bits are ignored */
+        return addr & 0x0FFFFFFFFFFFFFFFULL;
+    }
 
-    if (unlikely(ppc_hash64_translate(env, &ctx, addr, 0) != 0)) {
+    slb = slb_lookup(env, addr);
+    if (!slb) {
+        return -1;
+    }
+
+    pte_offset = ppc_hash64_htab_lookup(env, slb, addr, &pte);
+    if (pte_offset == -1) {
         return -1;
     }
 
-    return ctx.raddr & TARGET_PAGE_MASK;
+    return ppc_hash64_pte_raddr(slb, pte, addr) & TARGET_PAGE_MASK;
 }
 
 int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rwx,
commit 75d5ec89c03cb2f1a2bd0d9912e624ceb6fd1999
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:44 2013 +0000

    mmu-hash*: Correctly mask RPN from hash PTE
    
    BEHAVIOUR CHANGE
    
    At present we take the whole of word 1 of the hash PTE as the real page
    number used to calculate the translated address.  This is incorrect,
    because it leaves the flags from the low bits of PTE word 1 in place in the
    rpm.  We mostly get away with that because the value is later masked by
    TARGET_PAGE_MASK.
    
    More recent 64-bit CPUs also have a small number of flag bits (PP0 and
    KEY) in the top bits of PTE word 1.  Any guest which used those bits would
    fail with the current code.
    
    This patch fixes the problem by correctly masking out the RPN field of
    PTE word 1.  This is safe, even for older CPUs which didn't have PP0 and
    KEY, because although the RPN notionally extended to the very top of PTE
    word 1, none of those CPUs actually implemented that many real address
    bits.
    
    We add analogous masking to the 32-bit code, even though it also doesn't
    have the high flag bits, for consistency and clarity.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index e5ee29b..07e9b8c 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -346,7 +346,7 @@ static hwaddr ppc_hash32_htab_lookup(CPUPPCState *env,
 static hwaddr ppc_hash32_pte_raddr(target_ulong sr, ppc_hash_pte32_t pte,
                                    target_ulong eaddr)
 {
-    hwaddr rpn = pte.pte1;
+    hwaddr rpn = pte.pte1 & HPTE32_R_RPN;
     hwaddr mask = ~TARGET_PAGE_MASK;
 
     return (rpn & ~mask) | (eaddr & mask);
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 5e168d5..d986c0f 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -365,7 +365,7 @@ static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env,
 static hwaddr ppc_hash64_pte_raddr(ppc_slb_t *slb, ppc_hash_pte64_t pte,
                                    target_ulong eaddr)
 {
-    hwaddr rpn = pte.pte1;
+    hwaddr rpn = pte.pte1 & HPTE64_R_RPN;
     /* FIXME: Add support for SLLP extended page sizes */
     int target_page_bits = (slb->vsid & SLB_VSID_L)
         ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
commit 6d11d998bb866c92b0f81eb3cea2f7a3e617feb8
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:43 2013 +0000

    mmu-hash*: Clean up real address calculation
    
    More recent 64-bit hash MMUs support multiple page sizes, and PTEs for
    large pages only include the offset of the whole large page.  But the qemu
    tlb only handles pages of the base size (4k) so we need to break up the
    large pages into 4k pieces for the qemu tlb.  To do that we have a somewhat
    awkward piece of code that adds the folds address bits 4k and the page size
    from the virtual address into the real address from the pte.
    
    This patch simplifies this redefining the raddr output of
    ppc_hash64_translate() to be the full real address of the faulting address,
    rather than just the (4k) page offset.  Computing that turns out to be
    simpler, and is fine for the caller, since it already masks with
    TARGET_PAGE_MASK before inserting into the qemu tlb.
    
    The multiple page size complication doesn't exist for 32-bit hash mmus, but
    we make an analogous cleanup there for consistency.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 314b7d1..e5ee29b 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -343,6 +343,15 @@ static hwaddr ppc_hash32_htab_lookup(CPUPPCState *env,
     return pte_offset;
 }
 
+static hwaddr ppc_hash32_pte_raddr(target_ulong sr, ppc_hash_pte32_t pte,
+                                   target_ulong eaddr)
+{
+    hwaddr rpn = pte.pte1;
+    hwaddr mask = ~TARGET_PAGE_MASK;
+
+    return (rpn & ~mask) | (eaddr & mask);
+}
+
 static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
                                 target_ulong eaddr, int rwx)
 {
@@ -421,8 +430,9 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
         ppc_hash32_store_hpte1(env, pte_offset, new_pte1);
     }
 
-    /* Keep the matching PTE informations */
-    ctx->raddr = pte.pte1;
+    /* 9. Determine the real address from the PTE */
+
+    ctx->raddr = ppc_hash32_pte_raddr(sr, pte, eaddr);
 
     return 0;
 }
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index c76abb7..5e168d5 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -362,6 +362,18 @@ static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env,
     return pte_offset;
 }
 
+static hwaddr ppc_hash64_pte_raddr(ppc_slb_t *slb, ppc_hash_pte64_t pte,
+                                   target_ulong eaddr)
+{
+    hwaddr rpn = pte.pte1;
+    /* FIXME: Add support for SLLP extended page sizes */
+    int target_page_bits = (slb->vsid & SLB_VSID_L)
+        ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
+    hwaddr mask = (1ULL << target_page_bits) - 1;
+
+    return (rpn & ~mask) | (eaddr & mask);
+}
+
 static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
                                 target_ulong eaddr, int rwx)
 {
@@ -369,7 +381,6 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
     hwaddr pte_offset;
     ppc_hash_pte64_t pte;
     uint64_t new_pte1;
-    int target_page_bits;
     const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC};
 
     assert((rwx == 0) || (rwx == 1) || (rwx == 2));
@@ -429,17 +440,10 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
         ppc_hash64_store_hpte1(env, pte_offset, new_pte1);
     }
 
-    /* Keep the matching PTE informations */
-    ctx->raddr = pte.pte1;
+    /* 7. Determine the real address from the PTE */
+
+    ctx->raddr = ppc_hash64_pte_raddr(slb, pte, eaddr);
 
-    /* We have a TLB that saves 4K pages, so let's
-     * split a huge page to 4k chunks */
-    target_page_bits = (slb->vsid & SLB_VSID_L)
-        ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
-    if (target_page_bits != TARGET_PAGE_BITS) {
-        ctx->raddr |= (eaddr & ((1 << target_page_bits) - 1))
-                      & TARGET_PAGE_MASK;
-    }
     return 0;
 }
 
commit b344074642e58fc83635c38105f38b85fc086666
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:42 2013 +0000

    mmu-hash*: Clean up PTE flags update
    
    Currently the ppc_hash{32,64}_pte_update_flags() helper functions update a
    PTE's referenced and changed bits as necessary to reflect the access.  It
    is somewhat long winded, though.  This patch open codes them in their
    (single) callers, in a simpler way.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 6581d0f..314b7d1 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -274,31 +274,6 @@ static int ppc_hash32_direct_store(CPUPPCState *env, target_ulong sr,
     }
 }
 
-static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx, uint32_t *pte1p,
-                                       int ret, int rwx)
-{
-    int store = 0;
-
-    /* Update page flags */
-    if (!(*pte1p & HPTE32_R_R)) {
-        /* Update accessed flag */
-        *pte1p |= HPTE32_R_R;
-        store = 1;
-    }
-    if (!(*pte1p & HPTE32_R_C)) {
-        if (rwx == 1 && ret == 0) {
-            /* Update changed flag */
-            *pte1p |= HPTE32_R_C;
-            store = 1;
-        } else {
-            /* Force page fault for first write access */
-            ctx->prot &= ~PAGE_WRITE;
-        }
-    }
-
-    return store;
-}
-
 hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash)
 {
     return (hash * HASH_PTEG_SIZE_32) & env->htab_mask;
@@ -374,6 +349,7 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     target_ulong sr;
     hwaddr pte_offset;
     ppc_hash_pte32_t pte;
+    uint32_t new_pte1;
     const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC};
 
     assert((rwx == 0) || (rwx == 1) || (rwx == 2));
@@ -432,8 +408,17 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
 
     /* 8. Update PTE referenced and changed bits if necessary */
 
-    if (ppc_hash32_pte_update_flags(ctx, &pte.pte1, 0, rwx) == 1) {
-        ppc_hash32_store_hpte1(env, pte_offset, pte.pte1);
+    new_pte1 = pte.pte1 | HPTE32_R_R; /* set referenced bit */
+    if (rwx == 1) {
+        new_pte1 |= HPTE32_R_C; /* set changed (dirty) bit */
+    } else {
+        /* Treat the page as read-only for now, so that a later write
+         * will pass through this function again to set the C bit */
+        ctx->prot &= ~PAGE_WRITE;
+    }
+
+    if (new_pte1 != pte.pte1) {
+        ppc_hash32_store_hpte1(env, pte_offset, new_pte1);
     }
 
     /* Keep the matching PTE informations */
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 5607ce8..c76abb7 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -280,31 +280,6 @@ static int ppc_hash64_pte_prot(CPUPPCState *env,
     return prot;
 }
 
-static int ppc_hash64_pte_update_flags(struct mmu_ctx_hash64 *ctx,
-                                       uint64_t *pte1p, int ret, int rw)
-{
-    int store = 0;
-
-    /* Update page flags */
-    if (!(*pte1p & HPTE64_R_R)) {
-        /* Update accessed flag */
-        *pte1p |= HPTE64_R_R;
-        store = 1;
-    }
-    if (!(*pte1p & HPTE64_R_C)) {
-        if (rw == 1 && ret == 0) {
-            /* Update changed flag */
-            *pte1p |= HPTE64_R_C;
-            store = 1;
-        } else {
-            /* Force page fault for first write access */
-            ctx->prot &= ~PAGE_WRITE;
-        }
-    }
-
-    return store;
-}
-
 static hwaddr ppc_hash64_pteg_search(CPUPPCState *env, hwaddr pteg_off,
                                      bool secondary, target_ulong ptem,
                                      ppc_hash_pte64_t *pte)
@@ -393,6 +368,7 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
     ppc_slb_t *slb;
     hwaddr pte_offset;
     ppc_hash_pte64_t pte;
+    uint64_t new_pte1;
     int target_page_bits;
     const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC};
 
@@ -440,8 +416,17 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
 
     /* 6. Update PTE referenced and changed bits if necessary */
 
-    if (ppc_hash64_pte_update_flags(ctx, &pte.pte1, 0, rwx) == 1) {
-        ppc_hash64_store_hpte1(env, pte_offset, pte.pte1);
+    new_pte1 = pte.pte1 | HPTE64_R_R; /* set referenced bit */
+    if (rwx == 1) {
+        new_pte1 |= HPTE64_R_C; /* set changed (dirty) bit */
+    } else {
+        /* Treat the page as read-only for now, so that a later write
+         * will pass through this function again to set the C bit */
+        ctx->prot &= ~PAGE_WRITE;
+    }
+
+    if (new_pte1 != pte.pte1) {
+        ppc_hash64_store_hpte1(env, pte_offset, new_pte1);
     }
 
     /* Keep the matching PTE informations */
commit 57d0a39d98b0d0e4712e736084667bcb5aed3474
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:41 2013 +0000

    mmu-hash64: Factor SLB N bit into permissions bits
    
    BEHAVIOUR CHANGE
    
    Currently, for 64-bit hash mmu, the execute protection bit placed into the
    qemu tlb is based only on the N (No execute) bit from the PTE.  However,
    No Execute can also be set at the segment level.  We do check this on
    execute faults, but this still means we could incorrectly allow execution
    of code from a No Execute segment, if a prior read or write fault caused
    the page to be loaded into the qemu tlb with PROT_EXEC set.
    
    To correct this, we (re-)check the segment level no execute permission when
    generating the protection bits for the qemu tlb.
    
    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/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 1458f15..5607ce8 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -272,7 +272,8 @@ static int ppc_hash64_pte_prot(CPUPPCState *env,
     }
 
     /* No execute if either noexec or guarded bits set */
-    if (!(pte.pte1 & HPTE64_R_N) || (pte.pte1 & HPTE64_R_G)) {
+    if (!(pte.pte1 & HPTE64_R_N) || (pte.pte1 & HPTE64_R_G)
+        || (slb->vsid & SLB_VSID_N)) {
         prot |= PAGE_EXEC;
     }
 
commit e01b444523e2b0c663b42b3e8f44ef48a6153051
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:40 2013 +0000

    mmu-hash*: Clean up permission checking
    
    Currently checking of PTE permission bits is split messily amongst
    ppc_hash{32,64}_pp_check(), ppc_hash{32,64}_check_prot() and their callers.
    This patch cleans this up to have the new function
    ppc_hash{32,64}_pte_prot() compute the page permissions from the SLBE (for
    64-bit) or segment register (32-bit) and the pte.  A greatly simplified
    version of the actual permissions check is then open coded in the callers.
    
    The 32-bit version of ppc_hash32_pte_prot() is implemented in terms of
    ppc_hash32_pp_prot(), a renamed and slightly cleaned up version of the old
    ppc_hash32_pp_check(), which is also used for checking BAT permissions on
    the 601.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 2b88b9f..6581d0f 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -47,69 +47,60 @@ struct mmu_ctx_hash32 {
     int key;                       /* Access key                */
 };
 
-static int ppc_hash32_pp_check(int key, int pp, int nx)
+static int ppc_hash32_pp_prot(int key, int pp, int nx)
 {
-    int access;
+    int prot;
 
-    /* Compute access rights */
-    access = 0;
     if (key == 0) {
         switch (pp) {
         case 0x0:
         case 0x1:
         case 0x2:
-            access |= PAGE_WRITE;
-            /* No break here */
+            prot = PAGE_READ | PAGE_WRITE;
+            break;
+
         case 0x3:
-            access |= PAGE_READ;
+            prot = PAGE_READ;
             break;
+
+        default:
+            abort();
         }
     } else {
         switch (pp) {
         case 0x0:
-            access = 0;
+            prot = 0;
             break;
+
         case 0x1:
         case 0x3:
-            access = PAGE_READ;
+            prot = PAGE_READ;
             break;
+
         case 0x2:
-            access = PAGE_READ | PAGE_WRITE;
+            prot = PAGE_READ | PAGE_WRITE;
             break;
+
+        default:
+            abort();
         }
     }
     if (nx == 0) {
-        access |= PAGE_EXEC;
+        prot |= PAGE_EXEC;
     }
 
-    return access;
+    return prot;
 }
 
-static int ppc_hash32_check_prot(int prot, int rwx)
+static int ppc_hash32_pte_prot(CPUPPCState *env,
+                               target_ulong sr, ppc_hash_pte32_t pte)
 {
-    int ret;
+    unsigned pp, key;
 
-    if (rwx == 2) {
-        if (prot & PAGE_EXEC) {
-            ret = 0;
-        } else {
-            ret = -2;
-        }
-    } else if (rwx) {
-        if (prot & PAGE_WRITE) {
-            ret = 0;
-        } else {
-            ret = -2;
-        }
-    } else {
-        if (prot & PAGE_READ) {
-            ret = 0;
-        } else {
-            ret = -2;
-        }
-    }
+    key = !!(msr_pr ? (sr & SR32_KP) : (sr & SR32_KS));
+    pp = pte.pte1 & HPTE32_R_PP;
 
-    return ret;
+    return ppc_hash32_pp_prot(key, pp, !!(sr & SR32_NX));
 }
 
 static target_ulong hash32_bat_size(CPUPPCState *env,
@@ -160,7 +151,7 @@ static int hash32_bat_601_prot(CPUPPCState *env,
     } else {
         key = !!(batu & BATU32_601_KP);
     }
-    return ppc_hash32_pp_check(key, pp, 0);
+    return ppc_hash32_pp_prot(key, pp, 0);
 }
 
 static hwaddr ppc_hash32_bat_lookup(CPUPPCState *env, target_ulong ea, int rwx,
@@ -380,11 +371,10 @@ static hwaddr ppc_hash32_htab_lookup(CPUPPCState *env,
 static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
                                 target_ulong eaddr, int rwx)
 {
-    int ret;
     target_ulong sr;
-    bool nx;
     hwaddr pte_offset;
     ppc_hash_pte32_t pte;
+    const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC};
 
     assert((rwx == 0) || (rwx == 1) || (rwx == 2));
 
@@ -400,7 +390,10 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     if (env->nb_BATs != 0) {
         ctx->raddr = ppc_hash32_bat_lookup(env, eaddr, rwx, &ctx->prot);
         if (ctx->raddr != -1) {
-            return ppc_hash32_check_prot(ctx->prot, rwx);
+            if (need_prot[rwx] & ~ctx->prot) {
+                return -2;
+            }
+            return 0;
         }
     }
 
@@ -414,8 +407,7 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     }
 
     /* 5. Check for segment level no-execute violation */
-    nx = !!(sr & SR32_NX);
-    if ((rwx == 2) && nx) {
+    if ((rwx == 2) && (sr & SR32_NX)) {
         return -3;
     }
 
@@ -427,34 +419,27 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     LOG_MMU("found PTE at offset %08" HWADDR_PRIx "\n", pte_offset);
 
     /* 7. Check access permissions */
-    ctx->key = (((sr & SR32_KP) && (msr_pr != 0)) ||
-                ((sr & SR32_KS) && (msr_pr == 0))) ? 1 : 0;
-
-    int access, pp;
 
-    pp = pte.pte1 & HPTE32_R_PP;
-    /* Compute access rights */
-    access = ppc_hash32_pp_check(ctx->key, pp, nx);
-    /* Keep the matching PTE informations */
-    ctx->raddr = pte.pte1;
-    ctx->prot = access;
-    ret = ppc_hash32_check_prot(ctx->prot, rwx);
+    ctx->prot = ppc_hash32_pte_prot(env, sr, pte);
 
-    if (ret) {
+    if (need_prot[rwx] & ~ctx->prot) {
         /* Access right violation */
         LOG_MMU("PTE access rejected\n");
-        return ret;
+        return -2;
     }
 
     LOG_MMU("PTE access granted !\n");
 
     /* 8. Update PTE referenced and changed bits if necessary */
 
-    if (ppc_hash32_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) {
+    if (ppc_hash32_pte_update_flags(ctx, &pte.pte1, 0, rwx) == 1) {
         ppc_hash32_store_hpte1(env, pte_offset, pte.pte1);
     }
 
-    return ret;
+    /* Keep the matching PTE informations */
+    ctx->raddr = pte.pte1;
+
+    return 0;
 }
 
 hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index f7aa352..1458f15 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -43,7 +43,6 @@
 struct mmu_ctx_hash64 {
     hwaddr raddr;      /* Real address              */
     int prot;                      /* Protection bits           */
-    int key;                       /* Access key                */
 };
 
 /*
@@ -229,72 +228,55 @@ target_ulong helper_load_slb_vsid(CPUPPCState *env, target_ulong rb)
  * 64-bit hash table MMU handling
  */
 
-static int ppc_hash64_pp_check(int key, int pp, bool nx)
+static int ppc_hash64_pte_prot(CPUPPCState *env,
+                               ppc_slb_t *slb, ppc_hash_pte64_t pte)
 {
-    int access;
+    unsigned pp, key;
+    /* Some pp bit combinations have undefined behaviour, so default
+     * to no access in those cases */
+    int prot = 0;
+
+    key = !!(msr_pr ? (slb->vsid & SLB_VSID_KP)
+             : (slb->vsid & SLB_VSID_KS));
+    pp = (pte.pte1 & HPTE64_R_PP) | ((pte.pte1 & HPTE64_R_PP0) >> 61);
 
-    /* Compute access rights */
-    /* When pp is 4, 5 or 7, the result is undefined. Set it to noaccess */
-    access = 0;
     if (key == 0) {
         switch (pp) {
         case 0x0:
         case 0x1:
         case 0x2:
-            access |= PAGE_WRITE;
-            /* No break here */
+            prot = PAGE_READ | PAGE_WRITE;
+            break;
+
         case 0x3:
         case 0x6:
-            access |= PAGE_READ;
+            prot = PAGE_READ;
             break;
         }
     } else {
         switch (pp) {
         case 0x0:
         case 0x6:
-            access = 0;
+            prot = 0;
             break;
+
         case 0x1:
         case 0x3:
-            access = PAGE_READ;
+            prot = PAGE_READ;
             break;
+
         case 0x2:
-            access = PAGE_READ | PAGE_WRITE;
+            prot = PAGE_READ | PAGE_WRITE;
             break;
         }
     }
-    if (!nx) {
-        access |= PAGE_EXEC;
-    }
-
-    return access;
-}
-
-static int ppc_hash64_check_prot(int prot, int rwx)
-{
-    int ret;
 
-    if (rwx == 2) {
-        if (prot & PAGE_EXEC) {
-            ret = 0;
-        } else {
-            ret = -2;
-        }
-    } else if (rwx == 1) {
-        if (prot & PAGE_WRITE) {
-            ret = 0;
-        } else {
-            ret = -2;
-        }
-    } else {
-        if (prot & PAGE_READ) {
-            ret = 0;
-        } else {
-            ret = -2;
-        }
+    /* No execute if either noexec or guarded bits set */
+    if (!(pte.pte1 & HPTE64_R_N) || (pte.pte1 & HPTE64_R_G)) {
+        prot |= PAGE_EXEC;
     }
 
-    return ret;
+    return prot;
 }
 
 static int ppc_hash64_pte_update_flags(struct mmu_ctx_hash64 *ctx,
@@ -407,11 +389,11 @@ static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env,
 static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
                                 target_ulong eaddr, int rwx)
 {
-    int ret;
     ppc_slb_t *slb;
     hwaddr pte_offset;
     ppc_hash_pte64_t pte;
     int target_page_bits;
+    const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC};
 
     assert((rwx == 0) || (rwx == 1) || (rwx == 2));
 
@@ -444,37 +426,26 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
     LOG_MMU("found PTE at offset %08" HWADDR_PRIx "\n", pte_offset);
 
     /* 5. Check access permissions */
-    ctx->key = !!(msr_pr ? (slb->vsid & SLB_VSID_KP)
-                  : (slb->vsid & SLB_VSID_KS));
 
+    ctx->prot = ppc_hash64_pte_prot(env, slb, pte);
 
-    int access, pp;
-    bool nx;
-
-    pp = (pte.pte1 & HPTE64_R_PP) | ((pte.pte1 & HPTE64_R_PP0) >> 61);
-    /* No execute if either noexec or guarded bits set */
-    nx = (pte.pte1 & HPTE64_R_N) || (pte.pte1 & HPTE64_R_G);
-    /* Compute access rights */
-    access = ppc_hash64_pp_check(ctx->key, pp, nx);
-    /* Keep the matching PTE informations */
-    ctx->raddr = pte.pte1;
-    ctx->prot = access;
-    ret = ppc_hash64_check_prot(ctx->prot, rwx);
-
-    if (ret) {
+    if ((need_prot[rwx] & ~ctx->prot) != 0) {
         /* Access right violation */
         LOG_MMU("PTE access rejected\n");
-        return ret;
+        return -2;
     }
 
     LOG_MMU("PTE access granted !\n");
 
     /* 6. Update PTE referenced and changed bits if necessary */
 
-    if (ppc_hash64_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) {
+    if (ppc_hash64_pte_update_flags(ctx, &pte.pte1, 0, rwx) == 1) {
         ppc_hash64_store_hpte1(env, pte_offset, pte.pte1);
     }
 
+    /* Keep the matching PTE informations */
+    ctx->raddr = pte.pte1;
+
     /* We have a TLB that saves 4K pages, so let's
      * split a huge page to 4k chunks */
     target_page_bits = (slb->vsid & SLB_VSID_L)
@@ -483,7 +454,7 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
         ctx->raddr |= (eaddr & ((1 << target_page_bits) - 1))
                       & TARGET_PAGE_MASK;
     }
-    return ret;
+    return 0;
 }
 
 hwaddr ppc_hash64_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
commit e1a53ba2e0f6dcf4a8b25586cc9d8ec1e408305c
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:39 2013 +0000

    mmu-hash32: Remove nx from context structure
    
    Previous cleanups have meant the nx field of the mmu_ctx_hash32 structure
    is now only used within ppc_hash32_translate(), and so it can be replaced
    by a local variable.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index ae606fd..2b88b9f 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -45,7 +45,6 @@ struct mmu_ctx_hash32 {
     hwaddr raddr;      /* Real address              */
     int prot;                      /* Protection bits           */
     int key;                       /* Access key                */
-    int nx;                        /* Non-execute area          */
 };
 
 static int ppc_hash32_pp_check(int key, int pp, int nx)
@@ -383,6 +382,7 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
 {
     int ret;
     target_ulong sr;
+    bool nx;
     hwaddr pte_offset;
     ppc_hash_pte32_t pte;
 
@@ -414,8 +414,8 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     }
 
     /* 5. Check for segment level no-execute violation */
-    ctx->nx = !!(sr & SR32_NX);
-    if ((rwx == 2) && ctx->nx) {
+    nx = !!(sr & SR32_NX);
+    if ((rwx == 2) && nx) {
         return -3;
     }
 
@@ -434,7 +434,7 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
 
     pp = pte.pte1 & HPTE32_R_PP;
     /* Compute access rights */
-    access = ppc_hash32_pp_check(ctx->key, pp, ctx->nx);
+    access = ppc_hash32_pp_check(ctx->key, pp, nx);
     /* Keep the matching PTE informations */
     ctx->raddr = pte.pte1;
     ctx->prot = access;
commit 87dc3fd13e9c573fc435678973d8eb9726d50c3b
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:38 2013 +0000

    mmu-hash*: Don't update PTE flags when permission is denied
    
    BEHAVIOUR CHANGE
    
    Currently if ppc_hash{32,64}_translate() finds a PTE matching the given
    virtual address, it will always update the PTE's R & C (Referenced and
    Changed) bits.  This happens even if the PTE's permissions mean we are
    about to deny the translation.
    
    This is clearly a bug, although we get away with it because:
      a) It will only incorrectly set, never reset the bits, which should not
    cause guest correctness problems.
      b) Linux guests never use the R & C bits anyway.
    
    This patch fixes the behaviour, only updating R & C when access is granted
    by the PTE.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 3488092..ae606fd 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -439,15 +439,17 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     ctx->raddr = pte.pte1;
     ctx->prot = access;
     ret = ppc_hash32_check_prot(ctx->prot, rwx);
-    if (ret == 0) {
-        /* Access granted */
-        LOG_MMU("PTE access granted !\n");
-    } else {
+
+    if (ret) {
         /* Access right violation */
         LOG_MMU("PTE access rejected\n");
+        return ret;
     }
 
-    /* Update page flags */
+    LOG_MMU("PTE access granted !\n");
+
+    /* 8. Update PTE referenced and changed bits if necessary */
+
     if (ppc_hash32_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) {
         ppc_hash32_store_hpte1(env, pte_offset, pte.pte1);
     }
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 2e109f4..f7aa352 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -460,15 +460,17 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
     ctx->raddr = pte.pte1;
     ctx->prot = access;
     ret = ppc_hash64_check_prot(ctx->prot, rwx);
-    if (ret == 0) {
-        /* Access granted */
-        LOG_MMU("PTE access granted !\n");
-    } else {
+
+    if (ret) {
         /* Access right violation */
         LOG_MMU("PTE access rejected\n");
+        return ret;
     }
 
-    /* Update page flags */
+    LOG_MMU("PTE access granted !\n");
+
+    /* 6. Update PTE referenced and changed bits if necessary */
+
     if (ppc_hash64_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) {
         ppc_hash64_store_hpte1(env, pte_offset, pte.pte1);
     }
commit 59acbe28552eb7bd7be75b22b3f3de93d7d40556
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:37 2013 +0000

    mmu-hash32: Don't look up page tables on BAT permission error
    
    BEHAVIOUR CHANGE
    
    Currently, on any failure translating an address with BATs, we proceed to
    normal segment and page table translation.  That's incorrect if the
    BAT error was due to permissions, rather than not finding a matching BAT.
    We've gotten away with it because a guest would not usually put
    translations for the same address in both BATs and page table.  Nonetheless
    this patch corrects the logic, only doing page table lookup if no BAT
    is found.  A matching BAT with bad permissions will now correctly trigger
    an exception.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index d4d91dd..3488092 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -400,10 +400,7 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     if (env->nb_BATs != 0) {
         ctx->raddr = ppc_hash32_bat_lookup(env, eaddr, rwx, &ctx->prot);
         if (ctx->raddr != -1) {
-            ret = ppc_hash32_check_prot(ctx->prot, rwx);
-            if (ret == 0) {
-                return 0;
-            }
+            return ppc_hash32_check_prot(ctx->prot, rwx);
         }
     }
 
commit 145e52f31826045d8cccf5b840dc77d21a696651
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:36 2013 +0000

    mmu-hash32: Cleanup BAT lookup
    
    This patch makes a general cleanup of the ppc_hash32_get_bat() function,
    renaming it to ppc_hash32_bat_lookup().  In particular, the new function
    only looks for a matching BAT, with the permissions check from the old
    function moved to the caller.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 40d3564..d4d91dd 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -164,15 +164,14 @@ static int hash32_bat_601_prot(CPUPPCState *env,
     return ppc_hash32_pp_check(key, pp, 0);
 }
 
-static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
-                              target_ulong virtual, int rwx)
+static hwaddr ppc_hash32_bat_lookup(CPUPPCState *env, target_ulong ea, int rwx,
+                                    int *prot)
 {
     target_ulong *BATlt, *BATut;
-    int i, prot;
-    int ret = -1;
+    int i;
 
     LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
-             rwx == 2 ? 'I' : 'D', virtual);
+             rwx == 2 ? 'I' : 'D', ea);
     if (rwx == 2) {
         BATlt = env->IBAT[1];
         BATut = env->IBAT[0];
@@ -187,52 +186,46 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
 
         if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
             mask = hash32_bat_601_size(env, batu, batl);
-            prot = hash32_bat_601_prot(env, batu, batl);
         } else {
             mask = hash32_bat_size(env, batu, batl);
-            prot = hash32_bat_prot(env, batu, batl);
         }
         LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
                  " BATl " TARGET_FMT_lx "\n", __func__,
-                 type == ACCESS_CODE ? 'I' : 'D', i, virtual, batu, batl);
-
-        if (mask && ((virtual & mask) == (batu & BATU32_BEPI))) {
-            /* BAT matches */
-            /* Get physical address */
-            ctx->raddr = (batl & mask) | (virtual & ~mask);
-            ctx->raddr &= TARGET_PAGE_MASK;
-            /* Compute access rights */
-            ctx->prot = prot;
-            ret = ppc_hash32_check_prot(ctx->prot, rwx);
-            if (ret == 0) {
-                LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
-                         i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
-                         ctx->prot & PAGE_WRITE ? 'W' : '-');
+                 type == ACCESS_CODE ? 'I' : 'D', i, ea, batu, batl);
+
+        if (mask && ((ea & mask) == (batu & BATU32_BEPI))) {
+            hwaddr raddr = (batl & mask) | (ea & ~mask);
+
+            if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
+                *prot = hash32_bat_601_prot(env, batu, batl);
+            } else {
+                *prot = hash32_bat_prot(env, batu, batl);
             }
-            break;
+
+            return raddr & TARGET_PAGE_MASK;
         }
     }
-    if (ret < 0) {
+
+    /* No hit */
 #if defined(DEBUG_BATS)
-        if (qemu_log_enabled()) {
-            LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
-            for (i = 0; i < 4; i++) {
-                BATu = &BATut[i];
-                BATl = &BATlt[i];
-                BEPIu = *BATu & BATU32_BEPIU;
-                BEPIl = *BATu & BATU32_BEPIL;
-                bl = (*BATu & 0x00001FFC) << 15;
-                LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
-                         " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
-                         TARGET_FMT_lx " " TARGET_FMT_lx "\n",
-                         __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
-                         *BATu, *BATl, BEPIu, BEPIl, bl);
-            }
+    if (qemu_log_enabled()) {
+        LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", ea);
+        for (i = 0; i < 4; i++) {
+            BATu = &BATut[i];
+            BATl = &BATlt[i];
+            BEPIu = *BATu & BATU32_BEPIU;
+            BEPIl = *BATu & BATU32_BEPIL;
+            bl = (*BATu & 0x00001FFC) << 15;
+            LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
+                     " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
+                     TARGET_FMT_lx " " TARGET_FMT_lx "\n",
+                     __func__, type == ACCESS_CODE ? 'I' : 'D', i, ea,
+                     *BATu, *BATl, BEPIu, BEPIl, bl);
         }
-#endif
     }
-    /* No hit */
-    return ret;
+#endif
+
+    return -1;
 }
 
 static int ppc_hash32_direct_store(CPUPPCState *env, target_ulong sr,
@@ -405,9 +398,12 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
 
     /* 2. Check Block Address Translation entries (BATs) */
     if (env->nb_BATs != 0) {
-        ret = ppc_hash32_get_bat(env, ctx, eaddr, rwx);
-        if (ret == 0) {
-            return 0;
+        ctx->raddr = ppc_hash32_bat_lookup(env, eaddr, rwx, &ctx->prot);
+        if (ctx->raddr != -1) {
+            ret = ppc_hash32_check_prot(ctx->prot, rwx);
+            if (ret == 0) {
+                return 0;
+            }
         }
     }
 
commit 6fc76aa9adc1c8896a97059f12a1e5e6c1820c64
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:35 2013 +0000

    mmu-hash32: Clean up BAT matching logic
    
    The code to search for a matching BAT for a virtual address is somewhat
    longwinded and awkward.  In particular, it relies on seperate size and
    validity information being returned from the hash32_bat_size() function
    (and 601 specific variant).
    
    We simplify this by having hash32_bat_size() return instead a mask of the
    virtual address bits to match, and 0 for invalid (since a BAT can never
    match the entire address space).
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 6c71ebd..40d3564 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -113,20 +113,15 @@ static int ppc_hash32_check_prot(int prot, int rwx)
     return ret;
 }
 
-static void hash32_bat_size(CPUPPCState *env, target_ulong *blp, int *validp,
-                            target_ulong batu, target_ulong batl)
+static target_ulong hash32_bat_size(CPUPPCState *env,
+                                    target_ulong batu, target_ulong batl)
 {
-    target_ulong bl;
-    int valid;
-
-    bl = (batu & BATU32_BL) << 15;
-    valid = 0;
-    if (((msr_pr == 0) && (batu & BATU32_VS)) ||
-        ((msr_pr != 0) && (batu & BATU32_VP))) {
-        valid = 1;
+    if ((msr_pr && !(batu & BATU32_VP))
+        || (!msr_pr && !(batu & BATU32_VS))) {
+        return 0;
     }
-    *blp = bl;
-    *validp = valid;
+
+    return BATU32_BEPI & ~((batu & BATU32_BL) << 15);
 }
 
 static int hash32_bat_prot(CPUPPCState *env,
@@ -145,18 +140,14 @@ static int hash32_bat_prot(CPUPPCState *env,
     return prot;
 }
 
-static void hash32_bat_601_size(CPUPPCState *env, target_ulong *blp, int *validp,
+static target_ulong hash32_bat_601_size(CPUPPCState *env,
                                 target_ulong batu, target_ulong batl)
 {
-    target_ulong bl;
-    int valid;
-
-    bl = (batl & BATL32_601_BL) << 17;
-    LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
-             (uint8_t)(batl & BATL32_601_BL), bl, ~bl);
-    valid = !!(batl & BATL32_601_V);
-    *blp = bl;
-    *validp = valid;
+    if (!(batl & BATL32_601_V)) {
+        return 0;
+    }
+
+    return BATU32_BEPI & ~((batl & BATL32_601_BL) << 17);
 }
 
 static int hash32_bat_601_prot(CPUPPCState *env,
@@ -177,8 +168,7 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
                               target_ulong virtual, int rwx)
 {
     target_ulong *BATlt, *BATut;
-    target_ulong BEPIl, BEPIu, bl;
-    int i, valid, prot;
+    int i, prot;
     int ret = -1;
 
     LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
@@ -193,37 +183,33 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     for (i = 0; i < env->nb_BATs; i++) {
         target_ulong batu = BATut[i];
         target_ulong batl = BATlt[i];
+        target_ulong mask;
 
-        BEPIu = batu & BATU32_BEPIU;
-        BEPIl = batu & BATU32_BEPIL;
         if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
-            hash32_bat_601_size(env, &bl, &valid, batu, batl);
+            mask = hash32_bat_601_size(env, batu, batl);
             prot = hash32_bat_601_prot(env, batu, batl);
         } else {
-            hash32_bat_size(env, &bl, &valid, batu, batl);
+            mask = hash32_bat_size(env, batu, batl);
             prot = hash32_bat_prot(env, batu, batl);
         }
         LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
                  " BATl " TARGET_FMT_lx "\n", __func__,
                  type == ACCESS_CODE ? 'I' : 'D', i, virtual, batu, batl);
-        if ((virtual & BATU32_BEPIU) == BEPIu &&
-            ((virtual & BATU32_BEPIL) & ~bl) == BEPIl) {
+
+        if (mask && ((virtual & mask) == (batu & BATU32_BEPI))) {
             /* BAT matches */
-            if (valid != 0) {
-                /* Get physical address */
-                ctx->raddr = (batl & BATL32_BRPNU) |
-                    ((virtual & BATU32_BEPIL & bl) | (batl & BATL32_BRPNL)) |
-                    (virtual & 0x0001F000);
-                /* Compute access rights */
-                ctx->prot = prot;
-                ret = ppc_hash32_check_prot(ctx->prot, rwx);
-                if (ret == 0) {
-                    LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
-                             i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
-                             ctx->prot & PAGE_WRITE ? 'W' : '-');
-                }
-                break;
+            /* Get physical address */
+            ctx->raddr = (batl & mask) | (virtual & ~mask);
+            ctx->raddr &= TARGET_PAGE_MASK;
+            /* Compute access rights */
+            ctx->prot = prot;
+            ret = ppc_hash32_check_prot(ctx->prot, rwx);
+            if (ret == 0) {
+                LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
+                         i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
+                         ctx->prot & PAGE_WRITE ? 'W' : '-');
             }
+            break;
         }
     }
     if (ret < 0) {
diff --git a/target-ppc/mmu-hash32.h b/target-ppc/mmu-hash32.h
index f990edc..884786b 100644
--- a/target-ppc/mmu-hash32.h
+++ b/target-ppc/mmu-hash32.h
@@ -22,16 +22,12 @@ int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
  * Block Address Translation (BAT) definitions
  */
 
-#define BATU32_BEPIU            0xf0000000
-#define BATU32_BEPIL            0x0ffe0000
 #define BATU32_BEPI             0xfffe0000
 #define BATU32_BL               0x00001ffc
 #define BATU32_VS               0x00000002
 #define BATU32_VP               0x00000001
 
 
-#define BATL32_BRPNU            0xf0000000
-#define BATL32_BRPNL            0x0ffe0000
 #define BATL32_BRPN             0xfffe0000
 #define BATL32_WIMG             0x00000078
 #define BATL32_PP               0x00000003
commit e1d4951593426c886c1856211bc6ca81ed7c435d
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:34 2013 +0000

    mmu-hash32: Split BAT size logic from permissions logic
    
    hash32_bat_size_prot() and its 601 variant, as the name suggests, returns
    both a BAT's size - needed to search for a matching BAT - and its
    permissions, only relevant once a matching BAT has been located.
    
    There's no particular advantage to combining these, so we split these roles
    into seperate functions for clarity.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index b7f6e8f..6c71ebd 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -113,57 +113,64 @@ static int ppc_hash32_check_prot(int prot, int rwx)
     return ret;
 }
 
-/* Perform BAT hit & translation */
-static void hash32_bat_size_prot(CPUPPCState *env, target_ulong *blp,
-                                 int *validp, int *protp,
-                                 target_ulong batu, target_ulong batl)
+static void hash32_bat_size(CPUPPCState *env, target_ulong *blp, int *validp,
+                            target_ulong batu, target_ulong batl)
 {
     target_ulong bl;
-    int pp, valid, prot;
+    int valid;
 
     bl = (batu & BATU32_BL) << 15;
     valid = 0;
-    prot = 0;
     if (((msr_pr == 0) && (batu & BATU32_VS)) ||
         ((msr_pr != 0) && (batu & BATU32_VP))) {
         valid = 1;
-        pp = batl & BATL32_PP;
-        if (pp != 0) {
-            prot = PAGE_READ | PAGE_EXEC;
-            if (pp == 0x2) {
-                prot |= PAGE_WRITE;
-            }
-        }
     }
     *blp = bl;
     *validp = valid;
-    *protp = prot;
 }
 
-static void hash32_bat_601_size_prot(CPUPPCState *env, target_ulong *blp,
-                                     int *validp, int *protp,
-                                     target_ulong batu, target_ulong batl)
+static int hash32_bat_prot(CPUPPCState *env,
+                           target_ulong batu, target_ulong batl)
+{
+    int pp, prot;
+
+    prot = 0;
+    pp = batl & BATL32_PP;
+    if (pp != 0) {
+        prot = PAGE_READ | PAGE_EXEC;
+        if (pp == 0x2) {
+            prot |= PAGE_WRITE;
+        }
+    }
+    return prot;
+}
+
+static void hash32_bat_601_size(CPUPPCState *env, target_ulong *blp, int *validp,
+                                target_ulong batu, target_ulong batl)
 {
     target_ulong bl;
-    int key, pp, valid, prot;
+    int valid;
 
     bl = (batl & BATL32_601_BL) << 17;
     LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
              (uint8_t)(batl & BATL32_601_BL), bl, ~bl);
-    prot = 0;
     valid = !!(batl & BATL32_601_V);
-    if (valid) {
-        pp = batu & BATU32_601_PP;
-        if (msr_pr == 0) {
-            key = !!(batu & BATU32_601_KS);
-        } else {
-            key = !!(batu & BATU32_601_KP);
-        }
-        prot = ppc_hash32_pp_check(key, pp, 0);
-    }
     *blp = bl;
     *validp = valid;
-    *protp = prot;
+}
+
+static int hash32_bat_601_prot(CPUPPCState *env,
+                               target_ulong batu, target_ulong batl)
+{
+    int key, pp;
+
+    pp = batu & BATU32_601_PP;
+    if (msr_pr == 0) {
+        key = !!(batu & BATU32_601_KS);
+    } else {
+        key = !!(batu & BATU32_601_KP);
+    }
+    return ppc_hash32_pp_check(key, pp, 0);
 }
 
 static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
@@ -190,9 +197,11 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
         BEPIu = batu & BATU32_BEPIU;
         BEPIl = batu & BATU32_BEPIL;
         if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
-            hash32_bat_601_size_prot(env, &bl, &valid, &prot, batu, batl);
+            hash32_bat_601_size(env, &bl, &valid, batu, batl);
+            prot = hash32_bat_601_prot(env, batu, batl);
         } else {
-            hash32_bat_size_prot(env, &bl, &valid, &prot, batu, batl);
+            hash32_bat_size(env, &bl, &valid, batu, batl);
+            prot = hash32_bat_prot(env, batu, batl);
         }
         LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
                  " BATl " TARGET_FMT_lx "\n", __func__,
commit 9986ed1ed07a01bdd236524b1a5cee695e68954a
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:33 2013 +0000

    mmu-hash32: Remove odd pointer usage from BAT code
    
    In the code for handling BATs, the hash32_bat_size_prot() and
    hash32_bat_601_size_prot() functions are passed the BAT contents by
    reference (pointer) for no clear reason, since they only need the values
    within.
    
    This patch removes this odd usage, and uses the resulting change to clean
    up the caller slightly.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 53e86de..b7f6e8f 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -115,19 +115,19 @@ static int ppc_hash32_check_prot(int prot, int rwx)
 
 /* Perform BAT hit & translation */
 static void hash32_bat_size_prot(CPUPPCState *env, target_ulong *blp,
-                                 int *validp, int *protp, target_ulong *BATu,
-                                 target_ulong *BATl)
+                                 int *validp, int *protp,
+                                 target_ulong batu, target_ulong batl)
 {
     target_ulong bl;
     int pp, valid, prot;
 
-    bl = (*BATu & BATU32_BL) << 15;
+    bl = (batu & BATU32_BL) << 15;
     valid = 0;
     prot = 0;
-    if (((msr_pr == 0) && (*BATu & BATU32_VS)) ||
-        ((msr_pr != 0) && (*BATu & BATU32_VP))) {
+    if (((msr_pr == 0) && (batu & BATU32_VS)) ||
+        ((msr_pr != 0) && (batu & BATU32_VP))) {
         valid = 1;
-        pp = *BATl & BATL32_PP;
+        pp = batl & BATL32_PP;
         if (pp != 0) {
             prot = PAGE_READ | PAGE_EXEC;
             if (pp == 0x2) {
@@ -142,22 +142,22 @@ static void hash32_bat_size_prot(CPUPPCState *env, target_ulong *blp,
 
 static void hash32_bat_601_size_prot(CPUPPCState *env, target_ulong *blp,
                                      int *validp, int *protp,
-                                     target_ulong *BATu, target_ulong *BATl)
+                                     target_ulong batu, target_ulong batl)
 {
     target_ulong bl;
     int key, pp, valid, prot;
 
-    bl = (*BATl & BATL32_601_BL) << 17;
+    bl = (batl & BATL32_601_BL) << 17;
     LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
-             (uint8_t)(*BATl & BATL32_601_BL), bl, ~bl);
+             (uint8_t)(batl & BATL32_601_BL), bl, ~bl);
     prot = 0;
-    valid = !!(*BATl & BATL32_601_V);
+    valid = !!(batl & BATL32_601_V);
     if (valid) {
-        pp = *BATu & BATU32_601_PP;
+        pp = batu & BATU32_601_PP;
         if (msr_pr == 0) {
-            key = !!(*BATu & BATU32_601_KS);
+            key = !!(batu & BATU32_601_KS);
         } else {
-            key = !!(*BATu & BATU32_601_KP);
+            key = !!(batu & BATU32_601_KP);
         }
         prot = ppc_hash32_pp_check(key, pp, 0);
     }
@@ -169,7 +169,7 @@ static void hash32_bat_601_size_prot(CPUPPCState *env, target_ulong *blp,
 static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
                               target_ulong virtual, int rwx)
 {
-    target_ulong *BATlt, *BATut, *BATu, *BATl;
+    target_ulong *BATlt, *BATut;
     target_ulong BEPIl, BEPIu, bl;
     int i, valid, prot;
     int ret = -1;
@@ -184,25 +184,26 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
         BATut = env->DBAT[0];
     }
     for (i = 0; i < env->nb_BATs; i++) {
-        BATu = &BATut[i];
-        BATl = &BATlt[i];
-        BEPIu = *BATu & BATU32_BEPIU;
-        BEPIl = *BATu & BATU32_BEPIL;
+        target_ulong batu = BATut[i];
+        target_ulong batl = BATlt[i];
+
+        BEPIu = batu & BATU32_BEPIU;
+        BEPIl = batu & BATU32_BEPIL;
         if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
-            hash32_bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
+            hash32_bat_601_size_prot(env, &bl, &valid, &prot, batu, batl);
         } else {
-            hash32_bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
+            hash32_bat_size_prot(env, &bl, &valid, &prot, batu, batl);
         }
         LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
                  " BATl " TARGET_FMT_lx "\n", __func__,
-                 type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
+                 type == ACCESS_CODE ? 'I' : 'D', i, virtual, batu, batl);
         if ((virtual & BATU32_BEPIU) == BEPIu &&
             ((virtual & BATU32_BEPIL) & ~bl) == BEPIl) {
             /* BAT matches */
             if (valid != 0) {
                 /* Get physical address */
-                ctx->raddr = (*BATl & BATL32_BRPNU) |
-                    ((virtual & BATU32_BEPIL & bl) | (*BATl & BATL32_BRPNL)) |
+                ctx->raddr = (batl & BATL32_BRPNU) |
+                    ((virtual & BATU32_BEPIL & bl) | (batl & BATL32_BRPNL)) |
                     (virtual & 0x0001F000);
                 /* Compute access rights */
                 ctx->prot = prot;
commit 6a9801106ed90b8817128e15b187a9d5f71a54d9
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:32 2013 +0000

    mmu-hash*: Fold pte_check*() logic into caller
    
    With previous cleanups made, the 32-bit and 64-bit pte_check*() functions
    are pretty trivial and only have one call site.  This patch therefore
    clarifies the overall code flow by folding those functions into their
    call site.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 8b403fe..53e86de 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -295,31 +295,8 @@ static int ppc_hash32_direct_store(CPUPPCState *env, target_ulong sr,
     }
 }
 
-static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0,
-                            target_ulong pte1, int rwx)
-{
-    int access, ret, pp;
-
-    pp = pte1 & HPTE32_R_PP;
-    /* Compute access rights */
-    access = ppc_hash32_pp_check(ctx->key, pp, ctx->nx);
-    /* Keep the matching PTE informations */
-    ctx->raddr = pte1;
-    ctx->prot = access;
-    ret = ppc_hash32_check_prot(ctx->prot, rwx);
-    if (ret == 0) {
-        /* Access granted */
-        LOG_MMU("PTE access granted !\n");
-    } else {
-        /* Access right violation */
-        LOG_MMU("PTE access rejected\n");
-    }
-
-    return ret;
-}
-
-static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx,
-                                       uint32_t *pte1p, int ret, int rwx)
+static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx, uint32_t *pte1p,
+                                       int ret, int rwx)
 {
     int store = 0;
 
@@ -420,6 +397,8 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     hwaddr pte_offset;
     ppc_hash_pte32_t pte;
 
+    assert((rwx == 0) || (rwx == 1) || (rwx == 2));
+
     /* 1. Handle real mode accesses */
     if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
         /* Translation is off */
@@ -461,7 +440,24 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     /* 7. Check access permissions */
     ctx->key = (((sr & SR32_KP) && (msr_pr != 0)) ||
                 ((sr & SR32_KS) && (msr_pr == 0))) ? 1 : 0;
-    ret = pte_check_hash32(ctx, pte.pte0, pte.pte1, rwx);
+
+    int access, pp;
+
+    pp = pte.pte1 & HPTE32_R_PP;
+    /* Compute access rights */
+    access = ppc_hash32_pp_check(ctx->key, pp, ctx->nx);
+    /* Keep the matching PTE informations */
+    ctx->raddr = pte.pte1;
+    ctx->prot = access;
+    ret = ppc_hash32_check_prot(ctx->prot, rwx);
+    if (ret == 0) {
+        /* Access granted */
+        LOG_MMU("PTE access granted !\n");
+    } else {
+        /* Access right violation */
+        LOG_MMU("PTE access rejected\n");
+    }
+
     /* Update page flags */
     if (ppc_hash32_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) {
         ppc_hash32_store_hpte1(env, pte_offset, pte.pte1);
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 10372f0..2e109f4 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -297,32 +297,6 @@ static int ppc_hash64_check_prot(int prot, int rwx)
     return ret;
 }
 
-static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0,
-                       target_ulong pte1, int rwx)
-{
-    int access, ret, pp;
-    bool nx;
-
-    pp = (pte1 & HPTE64_R_PP) | ((pte1 & HPTE64_R_PP0) >> 61);
-    /* No execute if either noexec or guarded bits set */
-    nx = (pte1 & HPTE64_R_N) || (pte1 & HPTE64_R_G);
-    /* Compute access rights */
-    access = ppc_hash64_pp_check(ctx->key, pp, nx);
-    /* Keep the matching PTE informations */
-    ctx->raddr = pte1;
-    ctx->prot = access;
-    ret = ppc_hash64_check_prot(ctx->prot, rwx);
-    if (ret == 0) {
-        /* Access granted */
-        LOG_MMU("PTE access granted !\n");
-    } else {
-        /* Access right violation */
-        LOG_MMU("PTE access rejected\n");
-    }
-
-    return ret;
-}
-
 static int ppc_hash64_pte_update_flags(struct mmu_ctx_hash64 *ctx,
                                        uint64_t *pte1p, int ret, int rw)
 {
@@ -439,6 +413,8 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
     ppc_hash_pte64_t pte;
     int target_page_bits;
 
+    assert((rwx == 0) || (rwx == 1) || (rwx == 2));
+
     /* 1. Handle real mode accesses */
     if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
         /* Translation is off */
@@ -471,7 +447,27 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
     ctx->key = !!(msr_pr ? (slb->vsid & SLB_VSID_KP)
                   : (slb->vsid & SLB_VSID_KS));
 
-    ret = pte64_check(ctx, pte.pte0, pte.pte1, rwx);
+
+    int access, pp;
+    bool nx;
+
+    pp = (pte.pte1 & HPTE64_R_PP) | ((pte.pte1 & HPTE64_R_PP0) >> 61);
+    /* No execute if either noexec or guarded bits set */
+    nx = (pte.pte1 & HPTE64_R_N) || (pte.pte1 & HPTE64_R_G);
+    /* Compute access rights */
+    access = ppc_hash64_pp_check(ctx->key, pp, nx);
+    /* Keep the matching PTE informations */
+    ctx->raddr = pte.pte1;
+    ctx->prot = access;
+    ret = ppc_hash64_check_prot(ctx->prot, rwx);
+    if (ret == 0) {
+        /* Access granted */
+        LOG_MMU("PTE access granted !\n");
+    } else {
+        /* Access right violation */
+        LOG_MMU("PTE access rejected\n");
+    }
+
     /* Update page flags */
     if (ppc_hash64_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) {
         ppc_hash64_store_hpte1(env, pte_offset, pte.pte1);
commit 181488987671841407c52b6f958650f68b66f3f4
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:31 2013 +0000

    mmu-hash64: Clean up ppc_hash64_htab_lookup()
    
    This patch makes a general cleanup of the address mangling logic in
    ppc_hash64_htab_lookup().  In particular it now avoids repeatedly switching
    on the segment size.  The lack of SLB and multiple segment sizes on 32-bit
    means an analogous cleanup is not needed there.
    
    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/mmu-hash64.c b/target-ppc/mmu-hash64.c
index a98e008..10372f0 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -379,31 +379,29 @@ static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env,
                                      ppc_hash_pte64_t *pte)
 {
     hwaddr pteg_off, pte_offset;
-    uint64_t vsid, pageaddr, ptem;
     hwaddr hash;
-    int segment_bits, target_page_bits;
+    uint64_t vsid, epnshift, epnmask, epn, ptem;
 
-    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)
+    /* Page size according to the SLB, which we use to generate the
+     * EPN for hash table lookup..  When we implement more recent MMU
+     * extensions this might be different from the actual page size
+     * encoded in the PTE */
+    epnshift = (slb->vsid & SLB_VSID_L)
         ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
+    epnmask = ~((1ULL << epnshift) - 1);
 
-    pageaddr = eaddr & ((1ULL << segment_bits)
-                            - (1ULL << target_page_bits));
     if (slb->vsid & SLB_VSID_B) {
-        hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits);
+        /* 1TB segment */
+        vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;
+        epn = (eaddr & ~SEGMENT_MASK_1T) & epnmask;
+        hash = vsid ^ (vsid << 25) ^ (epn >> epnshift);
     } else {
-        hash = vsid ^ (pageaddr >> target_page_bits);
+        /* 256M segment */
+        vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
+        epn = (eaddr & ~SEGMENT_MASK_256M) & epnmask;
+        hash = vsid ^ (epn >> epnshift);
     }
-    /* Only 5 bits of the page index are used in the AVPN */
-    ptem = (slb->vsid & SLB_VSID_PTEM) |
-        ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
+    ptem = (slb->vsid & SLB_VSID_PTEM) | ((epn >> 16) & HPTE64_V_AVPN);
 
     /* Page address translation */
     LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
commit 7f3bdc2d8e17999a26ac0f6649caef92fedfc1c0
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:30 2013 +0000

    mmu-hash*: Remove permission checking from find_pte{32, 64}()
    
    find_pte{32,64}() are poorly named, since they both find a PTE and do
    permissions checking of it.  This patch makes them only locate a matching
    PTE, moving the permission checking and other logic to the caller.  We
    rename the resulting search functions ppc_hash{32,64}_htab_lookup().
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index b7a26a2..8b403fe 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -374,19 +374,15 @@ static hwaddr ppc_hash32_pteg_search(CPUPPCState *env, hwaddr pteg_off,
     return -1;
 }
 
-static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
-                      target_ulong sr, target_ulong eaddr, int rwx)
+static hwaddr ppc_hash32_htab_lookup(CPUPPCState *env,
+                                     target_ulong sr, target_ulong eaddr,
+                                     ppc_hash_pte32_t *pte)
 {
     hwaddr pteg_off, pte_offset;
-    ppc_hash_pte32_t pte;
     hwaddr hash;
     uint32_t vsid, pgidx, ptem;
-    int ret;
 
-    ret = -1; /* No entry found */
     vsid = sr & SR32_VSID;
-    ctx->key = (((sr & SR32_KP) && (msr_pr != 0)) ||
-                ((sr & SR32_KS) && (msr_pr == 0))) ? 1 : 0;
     pgidx = (eaddr & ~SEGMENT_MASK_256M) >> TARGET_PAGE_BITS;
     hash = vsid ^ pgidx;
     ptem = (vsid << 7) | (pgidx >> 10);
@@ -402,7 +398,7 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
             " hash=" TARGET_FMT_plx "\n",
             env->htab_base, env->htab_mask, vsid, ptem, hash);
     pteg_off = get_pteg_offset32(env, hash);
-    pte_offset = ppc_hash32_pteg_search(env, pteg_off, 0, ptem, &pte);
+    pte_offset = ppc_hash32_pteg_search(env, pteg_off, 0, ptem, pte);
     if (pte_offset == -1) {
         /* Secondary PTEG lookup */
         LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
@@ -410,20 +406,10 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
                 " hash=" TARGET_FMT_plx "\n", env->htab_base,
                 env->htab_mask, vsid, ptem, ~hash);
         pteg_off = get_pteg_offset32(env, ~hash);
-        pte_offset = ppc_hash32_pteg_search(env, pteg_off, 1, ptem, &pte);
+        pte_offset = ppc_hash32_pteg_search(env, pteg_off, 1, ptem, pte);
     }
 
-    if (pte_offset != -1) {
-        ret = pte_check_hash32(ctx, pte.pte0, pte.pte1, rwx);
-        LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n",
-                ctx->raddr, ctx->prot, ret);
-        /* Update page flags */
-        if (ppc_hash32_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) {
-            ppc_hash32_store_hpte1(env, pte_offset, pte.pte1);
-        }
-    }
-
-    return ret;
+    return pte_offset;
 }
 
 static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
@@ -431,6 +417,8 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
 {
     int ret;
     target_ulong sr;
+    hwaddr pte_offset;
+    ppc_hash_pte32_t pte;
 
     /* 1. Handle real mode accesses */
     if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
@@ -462,7 +450,22 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     if ((rwx == 2) && ctx->nx) {
         return -3;
     }
-    ret = find_pte32(env, ctx, sr, eaddr, rwx);
+
+    /* 6. Locate the PTE in the hash table */
+    pte_offset = ppc_hash32_htab_lookup(env, sr, eaddr, &pte);
+    if (pte_offset == -1) {
+        return -1;
+    }
+    LOG_MMU("found PTE at offset %08" HWADDR_PRIx "\n", pte_offset);
+
+    /* 7. Check access permissions */
+    ctx->key = (((sr & SR32_KP) && (msr_pr != 0)) ||
+                ((sr & SR32_KS) && (msr_pr == 0))) ? 1 : 0;
+    ret = pte_check_hash32(ctx, pte.pte0, pte.pte1, rwx);
+    /* Update page flags */
+    if (ppc_hash32_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) {
+        ppc_hash32_store_hpte1(env, pte_offset, pte.pte1);
+    }
 
     return ret;
 }
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 36e2c84..a98e008 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -374,17 +374,14 @@ static hwaddr ppc_hash64_pteg_search(CPUPPCState *env, hwaddr pteg_off,
     return -1;
 }
 
-static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
-                      ppc_slb_t *slb, target_ulong eaddr, int rwx)
+static hwaddr ppc_hash64_htab_lookup(CPUPPCState *env,
+                                     ppc_slb_t *slb, target_ulong eaddr,
+                                     ppc_hash_pte64_t *pte)
 {
     hwaddr pteg_off, pte_offset;
-    ppc_hash_pte64_t pte;
     uint64_t vsid, pageaddr, ptem;
     hwaddr hash;
     int segment_bits, target_page_bits;
-    int ret;
-
-    ret = -1; /* No entry found */
 
     if (slb->vsid & SLB_VSID_B) {
         vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;
@@ -396,8 +393,6 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
 
     target_page_bits = (slb->vsid & SLB_VSID_L)
         ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
-    ctx->key = !!(msr_pr ? (slb->vsid & SLB_VSID_KP)
-                  : (slb->vsid & SLB_VSID_KS));
 
     pageaddr = eaddr & ((1ULL << segment_bits)
                             - (1ULL << target_page_bits));
@@ -410,21 +405,19 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
     ptem = (slb->vsid & SLB_VSID_PTEM) |
         ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
 
-    ret = -1;
-
     /* Page address translation */
     LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
             " hash " TARGET_FMT_plx "\n",
             env->htab_base, env->htab_mask, hash);
 
-
     /* Primary PTEG lookup */
     LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
             " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
             " hash=" TARGET_FMT_plx "\n",
             env->htab_base, env->htab_mask, vsid, ptem,  hash);
     pteg_off = (hash * HASH_PTEG_SIZE_64) & env->htab_mask;
-    pte_offset = ppc_hash64_pteg_search(env, pteg_off, 0, ptem, &pte);
+    pte_offset = ppc_hash64_pteg_search(env, pteg_off, 0, ptem, pte);
+
     if (pte_offset == -1) {
         /* Secondary PTEG lookup */
         LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
@@ -433,26 +426,10 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
                 env->htab_mask, vsid, ptem, ~hash);
 
         pteg_off = (~hash * HASH_PTEG_SIZE_64) & env->htab_mask;
-        pte_offset = ppc_hash64_pteg_search(env, pteg_off, 1, ptem, &pte);
+        pte_offset = ppc_hash64_pteg_search(env, pteg_off, 1, ptem, pte);
     }
 
-    if (pte_offset != -1) {
-        ret = pte64_check(ctx, pte.pte0, pte.pte1, rwx);
-        LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n",
-                ctx->raddr, ctx->prot, ret);
-        /* Update page flags */
-        if (ppc_hash64_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) {
-            ppc_hash64_store_hpte1(env, pte_offset, pte.pte1);
-        }
-    }
-
-    /* We have a TLB that saves 4K pages, so let's
-     * split a huge page to 4k chunks */
-    if (target_page_bits != TARGET_PAGE_BITS) {
-        ctx->raddr |= (eaddr & ((1 << target_page_bits) - 1))
-                      & TARGET_PAGE_MASK;
-    }
-    return ret;
+    return pte_offset;
 }
 
 static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
@@ -460,6 +437,9 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
 {
     int ret;
     ppc_slb_t *slb;
+    hwaddr pte_offset;
+    ppc_hash_pte64_t pte;
+    int target_page_bits;
 
     /* 1. Handle real mode accesses */
     if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
@@ -482,8 +462,31 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
         return -3;
     }
 
-    ret = find_pte64(env, ctx, slb, eaddr, rwx);
+    /* 4. Locate the PTE in the hash table */
+    pte_offset = ppc_hash64_htab_lookup(env, slb, eaddr, &pte);
+    if (pte_offset == -1) {
+        return -1;
+    }
+    LOG_MMU("found PTE at offset %08" HWADDR_PRIx "\n", pte_offset);
+
+    /* 5. Check access permissions */
+    ctx->key = !!(msr_pr ? (slb->vsid & SLB_VSID_KP)
+                  : (slb->vsid & SLB_VSID_KS));
+
+    ret = pte64_check(ctx, pte.pte0, pte.pte1, rwx);
+    /* Update page flags */
+    if (ppc_hash64_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) {
+        ppc_hash64_store_hpte1(env, pte_offset, pte.pte1);
+    }
 
+    /* We have a TLB that saves 4K pages, so let's
+     * split a huge page to 4k chunks */
+    target_page_bits = (slb->vsid & SLB_VSID_L)
+        ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
+    if (target_page_bits != TARGET_PAGE_BITS) {
+        ctx->raddr |= (eaddr & ((1 << target_page_bits) - 1))
+                      & TARGET_PAGE_MASK;
+    }
     return ret;
 }
 
commit a1ff751abda89006f167b14fa4bfc5b59e4980f0
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:29 2013 +0000

    mmu-hash*: Make find_pte{32, 64} do more of the job of finding ptes
    
    find_pte{32,64}() are not particularly well named.  They only "find" a PTE
    within a given PTE group, and they also do permissions checking and other
    things.
    
    This patch makes it somewhat close to matching the name, by folding the
    search of both primary and secondary hash bucket into it, along with the
    various address bit shuffling to determine the right hash buckets.
    
    In the 32-bit case we also remove the code for splitting large pages into
    4k pieces for the qemu tlb, since no 32-bit hash MMUs support multiple page
    sizes.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 7c13a49..b7a26a2 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -44,8 +44,6 @@
 struct mmu_ctx_hash32 {
     hwaddr raddr;      /* Real address              */
     int prot;                      /* Protection bits           */
-    hwaddr hash[2];    /* Pagetable hash values     */
-    target_ulong ptem;             /* Virtual segment ID | API  */
     int key;                       /* Access key                */
     int nx;                        /* Non-execute area          */
 };
@@ -377,15 +375,44 @@ static hwaddr ppc_hash32_pteg_search(CPUPPCState *env, hwaddr pteg_off,
 }
 
 static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
-                      target_ulong eaddr, int h, int rwx, int target_page_bits)
+                      target_ulong sr, target_ulong eaddr, int rwx)
 {
     hwaddr pteg_off, pte_offset;
     ppc_hash_pte32_t pte;
+    hwaddr hash;
+    uint32_t vsid, pgidx, ptem;
     int ret;
 
     ret = -1; /* No entry found */
-    pteg_off = get_pteg_offset32(env, ctx->hash[h]);
-    pte_offset = ppc_hash32_pteg_search(env, pteg_off, h, ctx->ptem, &pte);
+    vsid = sr & SR32_VSID;
+    ctx->key = (((sr & SR32_KP) && (msr_pr != 0)) ||
+                ((sr & SR32_KS) && (msr_pr == 0))) ? 1 : 0;
+    pgidx = (eaddr & ~SEGMENT_MASK_256M) >> TARGET_PAGE_BITS;
+    hash = vsid ^ pgidx;
+    ptem = (vsid << 7) | (pgidx >> 10);
+
+    /* Page address translation */
+    LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
+            " hash " TARGET_FMT_plx "\n",
+            env->htab_base, env->htab_mask, hash);
+
+    /* Primary PTEG lookup */
+    LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+            " vsid=%" PRIx32 " ptem=%" PRIx32
+            " hash=" TARGET_FMT_plx "\n",
+            env->htab_base, env->htab_mask, vsid, ptem, hash);
+    pteg_off = get_pteg_offset32(env, hash);
+    pte_offset = ppc_hash32_pteg_search(env, pteg_off, 0, ptem, &pte);
+    if (pte_offset == -1) {
+        /* Secondary PTEG lookup */
+        LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+                " vsid=%" PRIx32 " api=%" PRIx32
+                " hash=" TARGET_FMT_plx "\n", env->htab_base,
+                env->htab_mask, vsid, ptem, ~hash);
+        pteg_off = get_pteg_offset32(env, ~hash);
+        pte_offset = ppc_hash32_pteg_search(env, pteg_off, 1, ptem, &pte);
+    }
+
     if (pte_offset != -1) {
         ret = pte_check_hash32(ctx, pte.pte0, pte.pte1, rwx);
         LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n",
@@ -396,23 +423,14 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
         }
     }
 
-    /* We have a TLB that saves 4K pages, so let's
-     * split a huge page to 4k chunks */
-    if (target_page_bits != TARGET_PAGE_BITS) {
-        ctx->raddr |= (eaddr & ((1 << target_page_bits) - 1))
-                      & TARGET_PAGE_MASK;
-    }
     return ret;
 }
 
 static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
                                 target_ulong eaddr, int rwx)
 {
-    hwaddr hash;
-    target_ulong vsid;
-    int pr, target_page_bits;
-    int ret, ret2;
-    target_ulong sr, pgidx;
+    int ret;
+    target_ulong sr;
 
     /* 1. Handle real mode accesses */
     if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
@@ -444,71 +462,7 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     if ((rwx == 2) && ctx->nx) {
         return -3;
     }
-
-    pr = msr_pr;
-    ctx->key = (((sr & SR32_KP) && (pr != 0)) ||
-                ((sr & SR32_KS) && (pr == 0))) ? 1 : 0;
-
-    vsid = sr & SR32_VSID;
-    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
-            " ir=%d dr=%d pr=%d %d\n",
-            eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
-            (int)msr_dr, pr != 0 ? 1 : 0, rwx);
-    pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
-    hash = vsid ^ pgidx;
-    ctx->ptem = (vsid << 7) | (pgidx >> 10);
-
-    LOG_MMU("pte segment: key=%d nx %d vsid " TARGET_FMT_lx "\n",
-            ctx->key, ctx->nx, vsid);
-    ret = -1;
-
-    /* Page address translation */
-    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;
-
-    LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
-            " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
-            " hash=" TARGET_FMT_plx "\n",
-            env->htab_base, env->htab_mask, vsid, ctx->ptem,
-            ctx->hash[0]);
-    /* Primary table lookup */
-    ret = find_pte32(env, ctx, eaddr, 0, rwx, target_page_bits);
-    if (ret == -1) {
-        /* Secondary table lookup */
-        LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
-                " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
-                " hash=" TARGET_FMT_plx "\n", env->htab_base,
-                env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
-        ret2 = find_pte32(env, ctx, eaddr, 1, rwx, target_page_bits);
-        if (ret2 != -1) {
-            ret = ret2;
-        }
-    }
-#if defined(DUMP_PAGE_TABLES)
-    if (qemu_log_enabled()) {
-        hwaddr curaddr;
-        uint32_t a0, a1, a2, a3;
-
-        qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
-                 "\n", sdr, mask + 0x80);
-        for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
-             curaddr += 16) {
-            a0 = ldl_phys(curaddr);
-            a1 = ldl_phys(curaddr + 4);
-            a2 = ldl_phys(curaddr + 8);
-            a3 = ldl_phys(curaddr + 12);
-            if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
-                qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
-                         curaddr, a0, a1, a2, a3);
-            }
-        }
-    }
-#endif
+    ret = find_pte32(env, ctx, sr, eaddr, rwx);
 
     return ret;
 }
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 66b2d24..36e2c84 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -43,8 +43,6 @@
 struct mmu_ctx_hash64 {
     hwaddr raddr;      /* Real address              */
     int prot;                      /* Protection bits           */
-    hwaddr hash[2];    /* Pagetable hash values     */
-    target_ulong ptem;             /* Virtual segment ID | API  */
     int key;                       /* Access key                */
 };
 
@@ -377,15 +375,67 @@ static hwaddr ppc_hash64_pteg_search(CPUPPCState *env, hwaddr pteg_off,
 }
 
 static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
-                      target_ulong eaddr, int h, int rwx, int target_page_bits)
+                      ppc_slb_t *slb, target_ulong eaddr, int rwx)
 {
     hwaddr pteg_off, pte_offset;
     ppc_hash_pte64_t pte;
+    uint64_t vsid, pageaddr, ptem;
+    hwaddr hash;
+    int segment_bits, target_page_bits;
     int ret;
 
     ret = -1; /* No entry found */
-    pteg_off = (ctx->hash[h] * HASH_PTEG_SIZE_64) & env->htab_mask;
-    pte_offset = ppc_hash64_pteg_search(env, pteg_off, h, ctx->ptem, &pte);
+
+    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 = !!(msr_pr ? (slb->vsid & SLB_VSID_KP)
+                  : (slb->vsid & SLB_VSID_KS));
+
+    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 */
+    ptem = (slb->vsid & SLB_VSID_PTEM) |
+        ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
+
+    ret = -1;
+
+    /* Page address translation */
+    LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
+            " hash " TARGET_FMT_plx "\n",
+            env->htab_base, env->htab_mask, hash);
+
+
+    /* Primary PTEG lookup */
+    LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+            " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
+            " hash=" TARGET_FMT_plx "\n",
+            env->htab_base, env->htab_mask, vsid, ptem,  hash);
+    pteg_off = (hash * HASH_PTEG_SIZE_64) & env->htab_mask;
+    pte_offset = ppc_hash64_pteg_search(env, pteg_off, 0, ptem, &pte);
+    if (pte_offset == -1) {
+        /* Secondary PTEG lookup */
+        LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+                " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
+                " hash=" TARGET_FMT_plx "\n", env->htab_base,
+                env->htab_mask, vsid, ptem, ~hash);
+
+        pteg_off = (~hash * HASH_PTEG_SIZE_64) & env->htab_mask;
+        pte_offset = ppc_hash64_pteg_search(env, pteg_off, 1, ptem, &pte);
+    }
+
     if (pte_offset != -1) {
         ret = pte64_check(ctx, pte.pte0, pte.pte1, rwx);
         LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n",
@@ -408,13 +458,8 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
 static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
                                 target_ulong eaddr, int rwx)
 {
-    hwaddr hash;
-    target_ulong vsid;
-    int pr, target_page_bits;
-    int ret, ret2;
+    int ret;
     ppc_slb_t *slb;
-    target_ulong pageaddr;
-    int segment_bits;
 
     /* 1. Handle real mode accesses */
     if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
@@ -437,61 +482,7 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
         return -3;
     }
 
-    pr = msr_pr;
-
-    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)
-                  : (slb->vsid & SLB_VSID_KS));
-
-    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) & ((1ULL << segment_bits) - 0x80));
-
-    LOG_MMU("pte segment: key=%d nx %d vsid " TARGET_FMT_lx "\n",
-            ctx->key, !!(slb->vsid & SLB_VSID_N), vsid);
-    ret = -1;
-
-    /* Page address translation */
-    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;
-
-    LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
-            " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
-            " hash=" TARGET_FMT_plx "\n",
-            env->htab_base, env->htab_mask, vsid, ctx->ptem,
-            ctx->hash[0]);
-    /* Primary table lookup */
-    ret = find_pte64(env, ctx, eaddr, 0, rwx, target_page_bits);
-    if (ret == -1) {
-        /* Secondary table lookup */
-        LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
-                " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
-                " hash=" TARGET_FMT_plx "\n", env->htab_base,
-                env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
-        ret2 = find_pte64(env, ctx, eaddr, 1, rwx, target_page_bits);
-        if (ret2 != -1) {
-            ret = ret2;
-        }
-    }
+    ret = find_pte64(env, ctx, slb, eaddr, rwx);
 
     return ret;
 }
commit aea390e4be652d5b5457771d25eded0dba14fe37
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:28 2013 +0000

    mmu-hash*: Separate PTEG searching from permissions checking
    
    find_pte{32,64{() do several things.  First they search through a PTEG
    ooking for a PTE matching our virtual address.  Then they do permissions
    checking and other processing on that PTE.
    
    This patch separates the search by VA out from the rest.  The search is
    combined with the pte{32,64}_match() functions into new
    ppc_has{32,64}_pteg_search() functions.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 3be1002..7c13a49 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -297,14 +297,6 @@ static int ppc_hash32_direct_store(CPUPPCState *env, target_ulong sr,
     }
 }
 
-static bool pte32_match(target_ulong pte0, target_ulong pte1,
-                        bool secondary, target_ulong ptem)
-{
-    return (pte0 & HPTE32_V_VALID)
-        && (secondary == !!(pte0 & HPTE32_V_SECONDARY))
-        && HPTE32_V_COMPARE(pte0, ptem);
-}
-
 static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0,
                             target_ulong pte1, int rwx)
 {
@@ -328,8 +320,8 @@ static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0,
     return ret;
 }
 
-static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx, target_ulong *pte1p,
-                                       int ret, int rwx)
+static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx,
+                                       uint32_t *pte1p, int ret, int rwx)
 {
     int store = 0;
 
@@ -358,40 +350,49 @@ hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash)
     return (hash * HASH_PTEG_SIZE_32) & env->htab_mask;
 }
 
-/* PTE table lookup */
+static hwaddr ppc_hash32_pteg_search(CPUPPCState *env, hwaddr pteg_off,
+                                     bool secondary, target_ulong ptem,
+                                     ppc_hash_pte32_t *pte)
+{
+    hwaddr pte_offset = pteg_off;
+    target_ulong pte0, pte1;
+    int i;
+
+    for (i = 0; i < HPTES_PER_GROUP; i++) {
+        pte0 = ppc_hash32_load_hpte0(env, pte_offset);
+        pte1 = ppc_hash32_load_hpte1(env, pte_offset);
+
+        if ((pte0 & HPTE32_V_VALID)
+            && (secondary == !!(pte0 & HPTE32_V_SECONDARY))
+            && HPTE32_V_COMPARE(pte0, ptem)) {
+            pte->pte0 = pte0;
+            pte->pte1 = pte1;
+            return pte_offset;
+        }
+
+        pte_offset += HASH_PTE_SIZE_32;
+    }
+
+    return -1;
+}
+
 static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
                       target_ulong eaddr, int h, int rwx, int target_page_bits)
 {
-    hwaddr pteg_off;
-    target_ulong pte0, pte1;
-    int i, good = -1;
+    hwaddr pteg_off, pte_offset;
+    ppc_hash_pte32_t pte;
     int ret;
 
     ret = -1; /* No entry found */
     pteg_off = get_pteg_offset32(env, ctx->hash[h]);
-    for (i = 0; i < HPTES_PER_GROUP; i++) {
-        pte0 = ppc_hash32_load_hpte0(env, pteg_off + i*HASH_PTE_SIZE_32);
-        pte1 = ppc_hash32_load_hpte1(env, pteg_off + i*HASH_PTE_SIZE_32);
-
-        LOG_MMU("Load pte from %08" HWADDR_PRIx " => " TARGET_FMT_lx " "
-                TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
-                pteg_off + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
-                (int)((pte0 >> 6) & 1), ctx->ptem);
-
-        if (pte32_match(pte0, pte1, h, ctx->ptem)) {
-            good = i;
-            break;
-        }
-    }
-    if (good != -1) {
-        ret = pte_check_hash32(ctx, pte0, pte1, rwx);
+    pte_offset = ppc_hash32_pteg_search(env, pteg_off, h, ctx->ptem, &pte);
+    if (pte_offset != -1) {
+        ret = pte_check_hash32(ctx, pte.pte0, pte.pte1, rwx);
         LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n",
                 ctx->raddr, ctx->prot, ret);
         /* Update page flags */
-        pte1 = ctx->raddr;
-        if (ppc_hash32_pte_update_flags(ctx, &pte1, ret, rwx) == 1) {
-            ppc_hash32_store_hpte1(env, pteg_off + good * HASH_PTE_SIZE_32,
-                                   pte1);
+        if (ppc_hash32_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) {
+            ppc_hash32_store_hpte1(env, pte_offset, pte.pte1);
         }
     }
 
diff --git a/target-ppc/mmu-hash32.h b/target-ppc/mmu-hash32.h
index 2344184..f990edc 100644
--- a/target-ppc/mmu-hash32.h
+++ b/target-ppc/mmu-hash32.h
@@ -97,6 +97,10 @@ static inline void ppc_hash32_store_hpte1(CPUPPCState *env,
     stl_phys(env->htab_base + pte_offset + HASH_PTE_SIZE_32/2, pte1);
 }
 
+typedef struct {
+    uint32_t pte0, pte1;
+} ppc_hash_pte32_t;
+
 #endif /* CONFIG_USER_ONLY */
 
 #endif /* __MMU_HASH32_H__ */
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 8664116..66b2d24 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -299,14 +299,6 @@ static int ppc_hash64_check_prot(int prot, int rwx)
     return ret;
 }
 
-static bool pte64_match(target_ulong pte0, target_ulong pte1,
-                        bool secondary, target_ulong ptem)
-{
-    return (pte0 & HPTE64_V_VALID)
-        && (secondary == !!(pte0 & HPTE64_V_SECONDARY))
-        && HPTE64_V_COMPARE(pte0, ptem);
-}
-
 static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0,
                        target_ulong pte1, int rwx)
 {
@@ -334,8 +326,7 @@ static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0,
 }
 
 static int ppc_hash64_pte_update_flags(struct mmu_ctx_hash64 *ctx,
-                                       target_ulong *pte1p,
-                                       int ret, int rw)
+                                       uint64_t *pte1p, int ret, int rw)
 {
     int store = 0;
 
@@ -359,39 +350,49 @@ static int ppc_hash64_pte_update_flags(struct mmu_ctx_hash64 *ctx,
     return store;
 }
 
-/* PTE table lookup */
+static hwaddr ppc_hash64_pteg_search(CPUPPCState *env, hwaddr pteg_off,
+                                     bool secondary, target_ulong ptem,
+                                     ppc_hash_pte64_t *pte)
+{
+    hwaddr pte_offset = pteg_off;
+    target_ulong pte0, pte1;
+    int i;
+
+    for (i = 0; i < HPTES_PER_GROUP; i++) {
+        pte0 = ppc_hash64_load_hpte0(env, pte_offset);
+        pte1 = ppc_hash64_load_hpte1(env, pte_offset);
+
+        if ((pte0 & HPTE64_V_VALID)
+            && (secondary == !!(pte0 & HPTE64_V_SECONDARY))
+            && HPTE64_V_COMPARE(pte0, ptem)) {
+            pte->pte0 = pte0;
+            pte->pte1 = pte1;
+            return pte_offset;
+        }
+
+        pte_offset += HASH_PTE_SIZE_64;
+    }
+
+    return -1;
+}
+
 static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
                       target_ulong eaddr, int h, int rwx, int target_page_bits)
 {
-    hwaddr pteg_off;
-    target_ulong pte0, pte1;
-    int i, good = -1;
+    hwaddr pteg_off, pte_offset;
+    ppc_hash_pte64_t pte;
     int ret;
 
     ret = -1; /* No entry found */
     pteg_off = (ctx->hash[h] * HASH_PTEG_SIZE_64) & env->htab_mask;
-    for (i = 0; i < HPTES_PER_GROUP; i++) {
-        pte0 = ppc_hash64_load_hpte0(env, pteg_off + i*HASH_PTE_SIZE_64);
-        pte1 = ppc_hash64_load_hpte1(env, pteg_off + i*HASH_PTE_SIZE_64);
-
-        LOG_MMU("Load pte from %016" HWADDR_PRIx " => " TARGET_FMT_lx " "
-                TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
-                pteg_off + (i * 16), pte0, pte1, !!(pte0 & HPTE64_V_VALID),
-                h, !!(pte0 & HPTE64_V_SECONDARY), ctx->ptem);
-
-        if (pte64_match(pte0, pte1, h, ctx->ptem)) {
-            good = i;
-            break;
-        }
-    }
-    if (good != -1) {
-        ret = pte64_check(ctx, pte0, pte1, rwx);
+    pte_offset = ppc_hash64_pteg_search(env, pteg_off, h, ctx->ptem, &pte);
+    if (pte_offset != -1) {
+        ret = pte64_check(ctx, pte.pte0, pte.pte1, rwx);
         LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n",
                 ctx->raddr, ctx->prot, ret);
         /* Update page flags */
-        pte1 = ctx->raddr;
-        if (ppc_hash64_pte_update_flags(ctx, &pte1, ret, rwx) == 1) {
-            ppc_hash64_store_hpte1(env, pteg_off + good * HASH_PTE_SIZE_64, pte1);
+        if (ppc_hash64_pte_update_flags(ctx, &pte.pte1, ret, rwx) == 1) {
+            ppc_hash64_store_hpte1(env, pte_offset, pte.pte1);
         }
     }
 
diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h
index 84576c0..37ed7ca 100644
--- a/target-ppc/mmu-hash64.h
+++ b/target-ppc/mmu-hash64.h
@@ -113,6 +113,10 @@ static inline void ppc_hash64_store_hpte1(CPUPPCState *env,
     }
 }
 
+typedef struct {
+    uint64_t pte0, pte1;
+} ppc_hash_pte64_t;
+
 #endif /* CONFIG_USER_ONLY */
 
 #endif /* !defined (__MMU_HASH64_H__) */
commit f95d7cc7fecbc0e320e83c864ce2d99fee3d9236
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:27 2013 +0000

    mmu-hash*: Don't keep looking for PTEs after we find a match
    
    BEHAVIOUR CHANGE
    
    The ppc hash mmu hashes each virtual address to a primary and secondary
    possible hash bucket (aka PTE group or PTEG) each with 8 PTEs.  Then we
    need a linear search through the PTEs to find the correct one for the
    virtual address we're translating.
    
    It is a programming error for the guest to insert multiple PTEs mapping the
    same virtual address into a PTEG - in this case the ppc architecture says
    the MMU can either act as if just one was present, or give a machine check.
    Currently our code takes the first matching PTE in a PTEG if it finds a
    successful translation.  But if a matching PTE is found, but permission
    bits don't allow the access, we keep looking through the PTEG, checking
    that any other matching PTEs contain an identical translation.
    
    That behaviour is perhaps not exactly wrong, but it's certainly not useful.
    This patch changes it to always just find the first matching PTE in a PTEG.
    
    In addition, if we get a permissions problem on the primary PTEG, we then
    search the secondary PTEG.  This is incorrect - a permission denying PTE
    in the primary PTEG should not be overwritten by an access granting PTE in
    the secondary (although again, it would be a programming error for the
    guest to set up such a situation anyway).  So additionally we update the
    code to only search the secondary PTEG if no matching PTE is found in the
    primary at all.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index d812adb..3be1002 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -50,8 +50,6 @@ struct mmu_ctx_hash32 {
     int nx;                        /* Non-execute area          */
 };
 
-#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
-
 static int ppc_hash32_pp_check(int key, int pp, int nx)
 {
     int access;
@@ -299,40 +297,32 @@ static int ppc_hash32_direct_store(CPUPPCState *env, target_ulong sr,
     }
 }
 
+static bool pte32_match(target_ulong pte0, target_ulong pte1,
+                        bool secondary, target_ulong ptem)
+{
+    return (pte0 & HPTE32_V_VALID)
+        && (secondary == !!(pte0 & HPTE32_V_SECONDARY))
+        && HPTE32_V_COMPARE(pte0, ptem);
+}
+
 static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0,
-                            target_ulong pte1, int h, int rwx)
+                            target_ulong pte1, int rwx)
 {
-    target_ulong mmask;
     int access, ret, pp;
 
-    ret = -1;
-    /* Check validity and table match */
-    if ((pte0 & HPTE32_V_VALID) && (h == !!(pte0 & HPTE32_V_SECONDARY))) {
-        /* Check vsid & api */
-        mmask = PTE_CHECK_MASK;
-        pp = pte1 & HPTE32_R_PP;
-        if (HPTE32_V_COMPARE(pte0, ctx->ptem)) {
-            if (ctx->raddr != (hwaddr)-1ULL) {
-                /* all matches should have equal RPN, WIMG & PP */
-                if ((ctx->raddr & mmask) != (pte1 & mmask)) {
-                    qemu_log("Bad RPN/WIMG/PP\n");
-                    return -3;
-                }
-            }
-            /* Compute access rights */
-            access = ppc_hash32_pp_check(ctx->key, pp, ctx->nx);
-            /* Keep the matching PTE informations */
-            ctx->raddr = pte1;
-            ctx->prot = access;
-            ret = ppc_hash32_check_prot(ctx->prot, rwx);
-            if (ret == 0) {
-                /* Access granted */
-                LOG_MMU("PTE access granted !\n");
-            } else {
-                /* Access right violation */
-                LOG_MMU("PTE access rejected\n");
-            }
-        }
+    pp = pte1 & HPTE32_R_PP;
+    /* Compute access rights */
+    access = ppc_hash32_pp_check(ctx->key, pp, ctx->nx);
+    /* Keep the matching PTE informations */
+    ctx->raddr = pte1;
+    ctx->prot = access;
+    ret = ppc_hash32_check_prot(ctx->prot, rwx);
+    if (ret == 0) {
+        /* Access granted */
+        LOG_MMU("PTE access granted !\n");
+    } else {
+        /* Access right violation */
+        LOG_MMU("PTE access rejected\n");
     }
 
     return ret;
@@ -375,44 +365,26 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     hwaddr pteg_off;
     target_ulong pte0, pte1;
     int i, good = -1;
-    int ret, r;
+    int ret;
 
     ret = -1; /* No entry found */
     pteg_off = get_pteg_offset32(env, ctx->hash[h]);
     for (i = 0; i < HPTES_PER_GROUP; i++) {
         pte0 = ppc_hash32_load_hpte0(env, pteg_off + i*HASH_PTE_SIZE_32);
         pte1 = ppc_hash32_load_hpte1(env, pteg_off + i*HASH_PTE_SIZE_32);
-        r = pte_check_hash32(ctx, pte0, pte1, h, rwx);
+
         LOG_MMU("Load pte from %08" HWADDR_PRIx " => " TARGET_FMT_lx " "
                 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
                 pteg_off + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
                 (int)((pte0 >> 6) & 1), ctx->ptem);
-        switch (r) {
-        case -3:
-            /* PTE inconsistency */
-            return -1;
-        case -2:
-            /* Access violation */
-            ret = -2;
+
+        if (pte32_match(pte0, pte1, h, ctx->ptem)) {
             good = i;
             break;
-        case -1:
-        default:
-            /* No PTE match */
-            break;
-        case 0:
-            /* access granted */
-            /* XXX: we should go on looping to check all PTEs consistency
-             *      but if we can speed-up the whole thing as the
-             *      result would be undefined if PTEs are not consistent.
-             */
-            ret = 0;
-            good = i;
-            goto done;
         }
     }
     if (good != -1) {
-    done:
+        ret = pte_check_hash32(ctx, pte0, pte1, rwx);
         LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n",
                 ctx->raddr, ctx->prot, ret);
         /* Update page flags */
@@ -498,8 +470,6 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     ctx->hash[0] = hash;
     ctx->hash[1] = ~hash;
 
-    /* Initialize real address with an invalid value */
-    ctx->raddr = (hwaddr)-1ULL;
     LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
             " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
             " hash=" TARGET_FMT_plx "\n",
@@ -507,7 +477,7 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
             ctx->hash[0]);
     /* Primary table lookup */
     ret = find_pte32(env, ctx, eaddr, 0, rwx, target_page_bits);
-    if (ret < 0) {
+    if (ret == -1) {
         /* Secondary table lookup */
         LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
                 " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 4fb7ecd..8664116 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -231,8 +231,6 @@ target_ulong helper_load_slb_vsid(CPUPPCState *env, target_ulong rb)
  * 64-bit hash table MMU handling
  */
 
-#define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
-
 static int ppc_hash64_pp_check(int key, int pp, bool nx)
 {
     int access;
@@ -301,44 +299,35 @@ static int ppc_hash64_check_prot(int prot, int rwx)
     return ret;
 }
 
+static bool pte64_match(target_ulong pte0, target_ulong pte1,
+                        bool secondary, target_ulong ptem)
+{
+    return (pte0 & HPTE64_V_VALID)
+        && (secondary == !!(pte0 & HPTE64_V_SECONDARY))
+        && HPTE64_V_COMPARE(pte0, ptem);
+}
+
 static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0,
-                       target_ulong pte1, int h, int rwx)
+                       target_ulong pte1, int rwx)
 {
-    target_ulong mmask;
     int access, ret, pp;
+    bool nx;
 
-    ret = -1;
-    /* Check validity and table match */
-    if ((pte0 & HPTE64_V_VALID) && (h == !!(pte0 & HPTE64_V_SECONDARY))) {
-        bool nx;
-
-        /* Check vsid & api */
-        mmask = PTE64_CHECK_MASK;
-        pp = (pte1 & HPTE64_R_PP) | ((pte1 & HPTE64_R_PP0) >> 61);
-        /* No execute if either noexec or guarded bits set */
-        nx = (pte1 & HPTE64_R_N) || (pte1 & HPTE64_R_G);
-        if (HPTE64_V_COMPARE(pte0, ctx->ptem)) {
-            if (ctx->raddr != (hwaddr)-1ULL) {
-                /* all matches should have equal RPN, WIMG & PP */
-                if ((ctx->raddr & mmask) != (pte1 & mmask)) {
-                    qemu_log("Bad RPN/WIMG/PP\n");
-                    return -3;
-                }
-            }
-            /* Compute access rights */
-            access = ppc_hash64_pp_check(ctx->key, pp, nx);
-            /* Keep the matching PTE informations */
-            ctx->raddr = pte1;
-            ctx->prot = access;
-            ret = ppc_hash64_check_prot(ctx->prot, rwx);
-            if (ret == 0) {
-                /* Access granted */
-                LOG_MMU("PTE access granted !\n");
-            } else {
-                /* Access right violation */
-                LOG_MMU("PTE access rejected\n");
-            }
-        }
+    pp = (pte1 & HPTE64_R_PP) | ((pte1 & HPTE64_R_PP0) >> 61);
+    /* No execute if either noexec or guarded bits set */
+    nx = (pte1 & HPTE64_R_N) || (pte1 & HPTE64_R_G);
+    /* Compute access rights */
+    access = ppc_hash64_pp_check(ctx->key, pp, nx);
+    /* Keep the matching PTE informations */
+    ctx->raddr = pte1;
+    ctx->prot = access;
+    ret = ppc_hash64_check_prot(ctx->prot, rwx);
+    if (ret == 0) {
+        /* Access granted */
+        LOG_MMU("PTE access granted !\n");
+    } else {
+        /* Access right violation */
+        LOG_MMU("PTE access rejected\n");
     }
 
     return ret;
@@ -377,7 +366,7 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
     hwaddr pteg_off;
     target_ulong pte0, pte1;
     int i, good = -1;
-    int ret, r;
+    int ret;
 
     ret = -1; /* No entry found */
     pteg_off = (ctx->hash[h] * HASH_PTEG_SIZE_64) & env->htab_mask;
@@ -385,37 +374,18 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
         pte0 = ppc_hash64_load_hpte0(env, pteg_off + i*HASH_PTE_SIZE_64);
         pte1 = ppc_hash64_load_hpte1(env, pteg_off + i*HASH_PTE_SIZE_64);
 
-        r = pte64_check(ctx, pte0, pte1, h, rwx);
         LOG_MMU("Load pte from %016" HWADDR_PRIx " => " TARGET_FMT_lx " "
                 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
-                pteg_off + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
-                (int)((pte0 >> 1) & 1), ctx->ptem);
-        switch (r) {
-        case -3:
-            /* PTE inconsistency */
-            return -1;
-        case -2:
-            /* Access violation */
-            ret = -2;
+                pteg_off + (i * 16), pte0, pte1, !!(pte0 & HPTE64_V_VALID),
+                h, !!(pte0 & HPTE64_V_SECONDARY), ctx->ptem);
+
+        if (pte64_match(pte0, pte1, h, ctx->ptem)) {
             good = i;
             break;
-        case -1:
-        default:
-            /* No PTE match */
-            break;
-        case 0:
-            /* access granted */
-            /* XXX: we should go on looping to check all PTEs consistency
-             *      but if we can speed-up the whole thing as the
-             *      result would be undefined if PTEs are not consistent.
-             */
-            ret = 0;
-            good = i;
-            goto done;
         }
     }
     if (good != -1) {
-    done:
+        ret = pte64_check(ctx, pte0, pte1, rwx);
         LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n",
                 ctx->raddr, ctx->prot, ret);
         /* Update page flags */
@@ -503,8 +473,6 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
     ctx->hash[0] = hash;
     ctx->hash[1] = ~hash;
 
-    /* Initialize real address with an invalid value */
-    ctx->raddr = (hwaddr)-1ULL;
     LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
             " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
             " hash=" TARGET_FMT_plx "\n",
@@ -512,7 +480,7 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
             ctx->hash[0]);
     /* Primary table lookup */
     ret = find_pte64(env, ctx, eaddr, 0, rwx, target_page_bits);
-    if (ret < 0) {
+    if (ret == -1) {
         /* Secondary table lookup */
         LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
                 " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
commit bb218042c8b4e4bbcf2ab3c8d961d78876178831
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:26 2013 +0000

    mmu-hash*: Cleanup segment-level NX check
    
    On the ppc hash mmus, no-execute can be set at the segment level (on more
    recent 64-bit hash mmus it can also be set at the page level).  This patch
    separates out this check to make it clearer what is going on, and avoiding
    excessive indentation of the remaining translation code.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index dbde264..d812adb 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -466,10 +466,16 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
                                        &ctx->raddr, &ctx->prot);
     }
 
+    /* 5. Check for segment level no-execute violation */
+    ctx->nx = !!(sr & SR32_NX);
+    if ((rwx == 2) && ctx->nx) {
+        return -3;
+    }
+
     pr = msr_pr;
     ctx->key = (((sr & SR32_KP) && (pr != 0)) ||
                 ((sr & SR32_KS) && (pr == 0))) ? 1 : 0;
-    ctx->nx = !!(sr & SR32_NX);
+
     vsid = sr & SR32_VSID;
     target_page_bits = TARGET_PAGE_BITS;
     LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
@@ -485,59 +491,53 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
             ctx->key, ctx->nx, vsid);
     ret = -1;
 
-    /* Check if instruction fetch is allowed, if needed */
-    if (rwx != 2 || ctx->nx == 0) {
-        /* Page address translation */
-        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;
-
-        /* Initialize real address with an invalid value */
-        ctx->raddr = (hwaddr)-1ULL;
-        LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
-                " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
-                " hash=" TARGET_FMT_plx "\n",
-                env->htab_base, env->htab_mask, vsid, ctx->ptem,
-                ctx->hash[0]);
-        /* Primary table lookup */
-        ret = find_pte32(env, ctx, eaddr, 0, rwx, target_page_bits);
-        if (ret < 0) {
-            /* Secondary table lookup */
-            LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
-                    " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
-                    " hash=" TARGET_FMT_plx "\n", env->htab_base,
-                    env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
-            ret2 = find_pte32(env, ctx, eaddr, 1, rwx, target_page_bits);
-            if (ret2 != -1) {
-                ret = ret2;
-            }
+    /* Page address translation */
+    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;
+
+    /* Initialize real address with an invalid value */
+    ctx->raddr = (hwaddr)-1ULL;
+    LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+            " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
+            " hash=" TARGET_FMT_plx "\n",
+            env->htab_base, env->htab_mask, vsid, ctx->ptem,
+            ctx->hash[0]);
+    /* Primary table lookup */
+    ret = find_pte32(env, ctx, eaddr, 0, rwx, target_page_bits);
+    if (ret < 0) {
+        /* Secondary table lookup */
+        LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+                " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
+                " hash=" TARGET_FMT_plx "\n", env->htab_base,
+                env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
+        ret2 = find_pte32(env, ctx, eaddr, 1, rwx, target_page_bits);
+        if (ret2 != -1) {
+            ret = ret2;
         }
+    }
 #if defined(DUMP_PAGE_TABLES)
-        if (qemu_log_enabled()) {
-            hwaddr curaddr;
-            uint32_t a0, a1, a2, a3;
-
-            qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
-                     "\n", sdr, mask + 0x80);
-            for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
-                 curaddr += 16) {
-                a0 = ldl_phys(curaddr);
-                a1 = ldl_phys(curaddr + 4);
-                a2 = ldl_phys(curaddr + 8);
-                a3 = ldl_phys(curaddr + 12);
-                if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
-                    qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
-                             curaddr, a0, a1, a2, a3);
-                }
+    if (qemu_log_enabled()) {
+        hwaddr curaddr;
+        uint32_t a0, a1, a2, a3;
+
+        qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
+                 "\n", sdr, mask + 0x80);
+        for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
+             curaddr += 16) {
+            a0 = ldl_phys(curaddr);
+            a1 = ldl_phys(curaddr + 4);
+            a2 = ldl_phys(curaddr + 8);
+            a3 = ldl_phys(curaddr + 12);
+            if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
+                qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
+                         curaddr, a0, a1, a2, a3);
             }
         }
-#endif
-    } else {
-        LOG_MMU("No access allowed\n");
-        ret = -3;
     }
+#endif
 
     return ret;
 }
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 9afc418..4fb7ecd 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -454,14 +454,20 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
         return 0;
     }
 
-    pr = msr_pr;
-
-    LOG_MMU("Check SLBs\n");
+    /* 2. Translation is on, so look up the SLB */
     slb = slb_lookup(env, eaddr);
+
     if (!slb) {
         return -5;
     }
 
+    /* 3. Check for segment level no-execute violation */
+    if ((rwx == 2) && (slb->vsid & SLB_VSID_N)) {
+        return -3;
+    }
+
+    pr = msr_pr;
+
     if (slb->vsid & SLB_VSID_B) {
         vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;
         segment_bits = 40;
@@ -490,38 +496,32 @@ static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
             ctx->key, !!(slb->vsid & SLB_VSID_N), vsid);
     ret = -1;
 
-    /* Check if instruction fetch is allowed, if needed */
-    if (rwx != 2 || !(slb->vsid & SLB_VSID_N)) {
-        /* Page address translation */
-        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;
-
-        /* Initialize real address with an invalid value */
-        ctx->raddr = (hwaddr)-1ULL;
-        LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
-                " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
-                " hash=" TARGET_FMT_plx "\n",
-                env->htab_base, env->htab_mask, vsid, ctx->ptem,
-                ctx->hash[0]);
-        /* Primary table lookup */
-        ret = find_pte64(env, ctx, eaddr, 0, rwx, target_page_bits);
-        if (ret < 0) {
-            /* Secondary table lookup */
-            LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
-                    " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
-                    " hash=" TARGET_FMT_plx "\n", env->htab_base,
-                    env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
-            ret2 = find_pte64(env, ctx, eaddr, 1, rwx, target_page_bits);
-            if (ret2 != -1) {
-                ret = ret2;
-            }
+    /* Page address translation */
+    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;
+
+    /* Initialize real address with an invalid value */
+    ctx->raddr = (hwaddr)-1ULL;
+    LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+            " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
+            " hash=" TARGET_FMT_plx "\n",
+            env->htab_base, env->htab_mask, vsid, ctx->ptem,
+            ctx->hash[0]);
+    /* Primary table lookup */
+    ret = find_pte64(env, ctx, eaddr, 0, rwx, target_page_bits);
+    if (ret < 0) {
+        /* Secondary table lookup */
+        LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+                " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
+                " hash=" TARGET_FMT_plx "\n", env->htab_base,
+                env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
+        ret2 = find_pte64(env, ctx, eaddr, 1, rwx, target_page_bits);
+        if (ret2 != -1) {
+            ret = ret2;
         }
-    } else {
-        LOG_MMU("No access allowed\n");
-        ret = -3;
     }
 
     return ret;
commit 723ed73ada1ed66a67722f3051059f634d60ebf7
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:25 2013 +0000

    mmu-hash32: Split direct store segment handling into a helper
    
    This further separates the unusual case handling of direct store segments
    from the main translation path by moving its logic into a helper function,
    with some tiny cleanups along the way.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 04ddf1d..dbde264 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -243,6 +243,62 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     return ret;
 }
 
+static int ppc_hash32_direct_store(CPUPPCState *env, target_ulong sr,
+                                   target_ulong eaddr, int rwx,
+                                   hwaddr *raddr, int *prot)
+{
+    int key = !!(msr_pr ? (sr & SR32_KP) : (sr & SR32_KS));
+
+    LOG_MMU("direct store...\n");
+
+    if ((sr & 0x1FF00000) >> 20 == 0x07f) {
+        /* Memory-forced I/O controller interface access */
+        /* If T=1 and BUID=x'07F', the 601 performs a memory access
+         * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
+         */
+        *raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
+        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+        return 0;
+    }
+
+    if (rwx == 2) {
+        /* No code fetch is allowed in direct-store areas */
+        return -4;
+    }
+
+    switch (env->access_type) {
+    case ACCESS_INT:
+        /* Integer load/store : only access allowed */
+        break;
+    case ACCESS_FLOAT:
+        /* Floating point load/store */
+        return -4;
+    case ACCESS_RES:
+        /* lwarx, ldarx or srwcx. */
+        return -4;
+    case ACCESS_CACHE:
+        /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
+        /* Should make the instruction do no-op.
+         * As it already do no-op, it's quite easy :-)
+         */
+        *raddr = eaddr;
+        return 0;
+    case ACCESS_EXT:
+        /* eciwx or ecowx */
+        return -4;
+    default:
+        qemu_log("ERROR: instruction should not need "
+                 "address translation\n");
+        return -4;
+    }
+    if ((rwx == 1 || key != 1) && (rwx == 0 || key != 0)) {
+        *raddr = eaddr;
+        return 2;
+    } else {
+        return -2;
+    }
+}
+
 static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0,
                             target_ulong pte1, int h, int rwx)
 {
@@ -404,66 +460,15 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     /* 3. Look up the Segment Register */
     sr = env->sr[eaddr >> 28];
 
-    pr = msr_pr;
-    ctx->key = (((sr & SR32_KP) && (pr != 0)) ||
-                ((sr & SR32_KS) && (pr == 0))) ? 1 : 0;
-
     /* 4. Handle direct store segments */
     if (sr & SR32_T) {
-        LOG_MMU("direct store...\n");
-        /* Direct-store segment : absolutely *BUGGY* for now */
-
-        /* Direct-store implies a 32-bit MMU.
-         * Check the Segment Register's bus unit ID (BUID).
-         */
-        if ((sr & 0x1FF00000) >> 20 == 0x07f) {
-            /* Memory-forced I/O controller interface access */
-            /* If T=1 and BUID=x'07F', the 601 performs a memory access
-             * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
-             */
-            ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
-            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
-            return 0;
-        }
-
-        if (rwx == 2) {
-            /* No code fetch is allowed in direct-store areas */
-            return -4;
-        }
-
-        switch (env->access_type) {
-        case ACCESS_INT:
-            /* Integer load/store : only access allowed */
-            break;
-        case ACCESS_FLOAT:
-            /* Floating point load/store */
-            return -4;
-        case ACCESS_RES:
-            /* lwarx, ldarx or srwcx. */
-            return -4;
-        case ACCESS_CACHE:
-            /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
-            /* Should make the instruction do no-op.
-             * As it already do no-op, it's quite easy :-)
-             */
-            ctx->raddr = eaddr;
-            return 0;
-        case ACCESS_EXT:
-            /* eciwx or ecowx */
-            return -4;
-        default:
-            qemu_log("ERROR: instruction should not need "
-                        "address translation\n");
-            return -4;
-        }
-        if ((rwx == 1 || ctx->key != 1) && (rwx == 0 || ctx->key != 0)) {
-            ctx->raddr = eaddr;
-            return 2;
-        } else {
-            return -2;
-        }
+        return ppc_hash32_direct_store(env, sr, eaddr, rwx,
+                                       &ctx->raddr, &ctx->prot);
     }
 
+    pr = msr_pr;
+    ctx->key = (((sr & SR32_KP) && (pr != 0)) ||
+                ((sr & SR32_KS) && (pr == 0))) ? 1 : 0;
     ctx->nx = !!(sr & SR32_NX);
     vsid = sr & SR32_VSID;
     target_page_bits = TARGET_PAGE_BITS;
commit 4b9605a5b16f86d9e8eccbc0bd522904137c1200
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:24 2013 +0000

    mmu-hash32: Split out handling of direct store segments
    
    At present a large chunk of ppc_hash32_translate() is taken up with an
    ugly if selecting between direct store segments (hardly ever used) and
    normal paged segments.  This patch clarifies the flow of code by
    handling direct store segments immediately then returning, leaving the
    straight line code to describe the normal MMU path.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index bc97834..04ddf1d 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -381,7 +381,7 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
 {
     hwaddr hash;
     target_ulong vsid;
-    int ds, pr, target_page_bits;
+    int pr, target_page_bits;
     int ret, ret2;
     target_ulong sr, pgidx;
 
@@ -401,91 +401,21 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
         }
     }
 
-    pr = msr_pr;
-
+    /* 3. Look up the Segment Register */
     sr = env->sr[eaddr >> 28];
+
+    pr = msr_pr;
     ctx->key = (((sr & SR32_KP) && (pr != 0)) ||
                 ((sr & SR32_KS) && (pr == 0))) ? 1 : 0;
-    ds = !!(sr & SR32_T);
-    ctx->nx = !!(sr & SR32_NX);
-    vsid = sr & SR32_VSID;
-    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
-            " ir=%d dr=%d pr=%d %d\n",
-            eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
-            (int)msr_dr, pr != 0 ? 1 : 0, rwx);
-    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);
-    ret = -1;
-    if (!ds) {
-        /* Check if instruction fetch is allowed, if needed */
-        if (rwx != 2 || ctx->nx == 0) {
-            /* Page address translation */
-            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;
-
-            /* Initialize real address with an invalid value */
-            ctx->raddr = (hwaddr)-1ULL;
-            LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
-                    " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
-                    " hash=" TARGET_FMT_plx "\n",
-                    env->htab_base, env->htab_mask, vsid, ctx->ptem,
-                    ctx->hash[0]);
-            /* Primary table lookup */
-            ret = find_pte32(env, ctx, eaddr, 0, rwx, target_page_bits);
-            if (ret < 0) {
-                /* Secondary table lookup */
-                LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
-                        " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
-                        " hash=" TARGET_FMT_plx "\n", env->htab_base,
-                        env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
-                ret2 = find_pte32(env, ctx, eaddr, 1, rwx, target_page_bits);
-                if (ret2 != -1) {
-                    ret = ret2;
-                }
-            }
-#if defined(DUMP_PAGE_TABLES)
-            if (qemu_log_enabled()) {
-                hwaddr curaddr;
-                uint32_t a0, a1, a2, a3;
-
-                qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
-                         "\n", sdr, mask + 0x80);
-                for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
-                     curaddr += 16) {
-                    a0 = ldl_phys(curaddr);
-                    a1 = ldl_phys(curaddr + 4);
-                    a2 = ldl_phys(curaddr + 8);
-                    a3 = ldl_phys(curaddr + 12);
-                    if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
-                        qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
-                                 curaddr, a0, a1, a2, a3);
-                    }
-                }
-            }
-#endif
-        } else {
-            LOG_MMU("No access allowed\n");
-            ret = -3;
-        }
-    } else {
-        target_ulong sr;
 
+    /* 4. Handle direct store segments */
+    if (sr & SR32_T) {
         LOG_MMU("direct store...\n");
         /* Direct-store segment : absolutely *BUGGY* for now */
 
         /* Direct-store implies a 32-bit MMU.
          * Check the Segment Register's bus unit ID (BUID).
          */
-        sr = env->sr[eaddr >> 28];
         if ((sr & 0x1FF00000) >> 20 == 0x07f) {
             /* Memory-forced I/O controller interface access */
             /* If T=1 and BUID=x'07F', the 601 performs a memory access
@@ -528,10 +458,80 @@ static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
         }
         if ((rwx == 1 || ctx->key != 1) && (rwx == 0 || ctx->key != 0)) {
             ctx->raddr = eaddr;
-            ret = 2;
+            return 2;
         } else {
-            ret = -2;
+            return -2;
+        }
+    }
+
+    ctx->nx = !!(sr & SR32_NX);
+    vsid = sr & SR32_VSID;
+    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
+            " ir=%d dr=%d pr=%d %d\n",
+            eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
+            (int)msr_dr, pr != 0 ? 1 : 0, rwx);
+    pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
+    hash = vsid ^ pgidx;
+    ctx->ptem = (vsid << 7) | (pgidx >> 10);
+
+    LOG_MMU("pte segment: key=%d nx %d vsid " TARGET_FMT_lx "\n",
+            ctx->key, ctx->nx, vsid);
+    ret = -1;
+
+    /* Check if instruction fetch is allowed, if needed */
+    if (rwx != 2 || ctx->nx == 0) {
+        /* Page address translation */
+        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;
+
+        /* Initialize real address with an invalid value */
+        ctx->raddr = (hwaddr)-1ULL;
+        LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+                " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
+                " hash=" TARGET_FMT_plx "\n",
+                env->htab_base, env->htab_mask, vsid, ctx->ptem,
+                ctx->hash[0]);
+        /* Primary table lookup */
+        ret = find_pte32(env, ctx, eaddr, 0, rwx, target_page_bits);
+        if (ret < 0) {
+            /* Secondary table lookup */
+            LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+                    " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
+                    " hash=" TARGET_FMT_plx "\n", env->htab_base,
+                    env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
+            ret2 = find_pte32(env, ctx, eaddr, 1, rwx, target_page_bits);
+            if (ret2 != -1) {
+                ret = ret2;
+            }
         }
+#if defined(DUMP_PAGE_TABLES)
+        if (qemu_log_enabled()) {
+            hwaddr curaddr;
+            uint32_t a0, a1, a2, a3;
+
+            qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
+                     "\n", sdr, mask + 0x80);
+            for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
+                 curaddr += 16) {
+                a0 = ldl_phys(curaddr);
+                a1 = ldl_phys(curaddr + 4);
+                a2 = ldl_phys(curaddr + 8);
+                a3 = ldl_phys(curaddr + 12);
+                if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
+                    qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
+                             curaddr, a0, a1, a2, a3);
+                }
+            }
+        }
+#endif
+    } else {
+        LOG_MMU("No access allowed\n");
+        ret = -3;
     }
 
     return ret;
commit 65d61643d01fec2792d195130531cbb71c783e8e
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:23 2013 +0000

    mmu-hash*: Combine ppc_hash{32, 64}_get_physical_address and get_segment{32, 64}()
    
    After previous work, ppc_hash{32,64}_get_physical_address() are almost
    trivial wrappers around get_segment{32,64}() which does nearly all the work of
    translating an address according to the hash mmu model.  Therefore combine the
    two functions into one, under the better name of
    ppc_hash{32,64}_translate().
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 8001563..bc97834 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -376,8 +376,8 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     return ret;
 }
 
-static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
-                         target_ulong eaddr, int rwx)
+static int ppc_hash32_translate(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
+                                target_ulong eaddr, int rwx)
 {
     hwaddr hash;
     target_ulong vsid;
@@ -385,6 +385,22 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     int ret, ret2;
     target_ulong sr, pgidx;
 
+    /* 1. Handle real mode accesses */
+    if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
+        /* Translation is off */
+        ctx->raddr = eaddr;
+        ctx->prot = PAGE_READ | PAGE_EXEC | PAGE_WRITE;
+        return 0;
+    }
+
+    /* 2. Check Block Address Translation entries (BATs) */
+    if (env->nb_BATs != 0) {
+        ret = ppc_hash32_get_bat(env, ctx, eaddr, rwx);
+        if (ret == 0) {
+            return 0;
+        }
+    }
+
     pr = msr_pr;
 
     sr = env->sr[eaddr >> 28];
@@ -521,38 +537,13 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     return ret;
 }
 
-static int ppc_hash32_get_physical_address(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
-                                           target_ulong eaddr, int rwx)
-{
-    bool real_mode = (rwx == 2 && msr_ir == 0)
-        || (rwx != 2 && msr_dr == 0);
-
-    if (real_mode) {
-        ctx->raddr = eaddr;
-        ctx->prot = PAGE_READ | PAGE_EXEC | PAGE_WRITE;
-        return 0;
-    } else {
-        int ret = -1;
-
-        /* Try to find a BAT */
-        if (env->nb_BATs != 0) {
-            ret = ppc_hash32_get_bat(env, ctx, eaddr, rwx);
-        }
-        if (ret < 0) {
-            /* We didn't match any BAT entry or don't have BATs */
-            ret = get_segment32(env, ctx, eaddr, rwx);
-        }
-        return ret;
-    }
-}
-
 hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
 {
     struct mmu_ctx_hash32 ctx;
 
     /* FIXME: Will not behave sanely for direct store segments, but
      * they're almost never used */
-    if (unlikely(ppc_hash32_get_physical_address(env, &ctx, addr, 0)
+    if (unlikely(ppc_hash32_translate(env, &ctx, addr, 0)
                  != 0)) {
         return -1;
     }
@@ -566,7 +557,7 @@ int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rwx,
     struct mmu_ctx_hash32 ctx;
     int ret = 0;
 
-    ret = ppc_hash32_get_physical_address(env, &ctx, address, rwx);
+    ret = ppc_hash32_translate(env, &ctx, address, rwx);
     if (ret == 0) {
         tlb_set_page(env, address & TARGET_PAGE_MASK,
                      ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 407c6e6..9afc418 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -434,19 +434,28 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
     return ret;
 }
 
-static int get_segment64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
-                         target_ulong eaddr, int rwx)
+static int ppc_hash64_translate(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
+                                target_ulong eaddr, int rwx)
 {
     hwaddr hash;
     target_ulong vsid;
     int pr, target_page_bits;
     int ret, ret2;
-
-    pr = msr_pr;
     ppc_slb_t *slb;
     target_ulong pageaddr;
     int segment_bits;
 
+    /* 1. Handle real mode accesses */
+    if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
+        /* Translation is off */
+        /* In real mode the top 4 effective address bits are ignored */
+        ctx->raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL;
+        ctx->prot = PAGE_READ | PAGE_EXEC | PAGE_WRITE;
+        return 0;
+    }
+
+    pr = msr_pr;
+
     LOG_MMU("Check SLBs\n");
     slb = slb_lookup(env, eaddr);
     if (!slb) {
@@ -518,27 +527,11 @@ static int get_segment64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
     return ret;
 }
 
-static int ppc_hash64_get_physical_address(CPUPPCState *env,
-                                           struct mmu_ctx_hash64 *ctx,
-                                           target_ulong eaddr, int rwx)
-{
-    bool real_mode = (rwx == 2 && msr_ir == 0)
-        || (rwx != 2 && msr_dr == 0);
-
-    if (real_mode) {
-        ctx->raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL;
-        ctx->prot = PAGE_READ | PAGE_EXEC | PAGE_WRITE;
-        return 0;
-    } else {
-        return get_segment64(env, ctx, eaddr, rwx);
-    }
-}
-
 hwaddr ppc_hash64_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
 {
     struct mmu_ctx_hash64 ctx;
 
-    if (unlikely(ppc_hash64_get_physical_address(env, &ctx, addr, 0) != 0)) {
+    if (unlikely(ppc_hash64_translate(env, &ctx, addr, 0) != 0)) {
         return -1;
     }
 
@@ -551,7 +544,7 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rwx,
     struct mmu_ctx_hash64 ctx;
     int ret = 0;
 
-    ret = ppc_hash64_get_physical_address(env, &ctx, address, rwx);
+    ret = ppc_hash64_translate(env, &ctx, address, rwx);
     if (ret == 0) {
         tlb_set_page(env, address & TARGET_PAGE_MASK,
                      ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
commit f078cd46de9efb5f102a4b32aaf1c8b96a90bfbd
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:22 2013 +0000

    mmu-hash*: Remove eaddr field from mmu_ctx_hash{32, 64}
    
    The eaddr field of mmu_ctx_hash{32,64} is effectively just used to pass the
    effective address from get_segment{32,64}() to find_pte{32,64}().  Just
    pass it as a normal parameter instead.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index ad5ef44..8001563 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -43,7 +43,6 @@
 
 struct mmu_ctx_hash32 {
     hwaddr raddr;      /* Real address              */
-    hwaddr eaddr;      /* Effective address         */
     int prot;                      /* Protection bits           */
     hwaddr hash[2];    /* Pagetable hash values     */
     target_ulong ptem;             /* Virtual segment ID | API  */
@@ -314,8 +313,8 @@ hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash)
 }
 
 /* PTE table lookup */
-static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h,
-                      int rwx, int target_page_bits)
+static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
+                      target_ulong eaddr, int h, int rwx, int target_page_bits)
 {
     hwaddr pteg_off;
     target_ulong pte0, pte1;
@@ -371,7 +370,7 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h,
     /* We have a TLB that saves 4K pages, so let's
      * split a huge page to 4k chunks */
     if (target_page_bits != TARGET_PAGE_BITS) {
-        ctx->raddr |= (ctx->eaddr & ((1 << target_page_bits) - 1))
+        ctx->raddr |= (eaddr & ((1 << target_page_bits) - 1))
                       & TARGET_PAGE_MASK;
     }
     return ret;
@@ -387,7 +386,6 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     target_ulong sr, pgidx;
 
     pr = msr_pr;
-    ctx->eaddr = eaddr;
 
     sr = env->sr[eaddr >> 28];
     ctx->key = (((sr & SR32_KP) && (pr != 0)) ||
@@ -426,14 +424,14 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
                     env->htab_base, env->htab_mask, vsid, ctx->ptem,
                     ctx->hash[0]);
             /* Primary table lookup */
-            ret = find_pte32(env, ctx, 0, rwx, target_page_bits);
+            ret = find_pte32(env, ctx, eaddr, 0, rwx, target_page_bits);
             if (ret < 0) {
                 /* Secondary table lookup */
                 LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
                         " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
                         " hash=" TARGET_FMT_plx "\n", env->htab_base,
                         env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
-                ret2 = find_pte32(env, ctx, 1, rwx, target_page_bits);
+                ret2 = find_pte32(env, ctx, eaddr, 1, rwx, target_page_bits);
                 if (ret2 != -1) {
                     ret = ret2;
                 }
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index f89d005..407c6e6 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -42,7 +42,6 @@
 
 struct mmu_ctx_hash64 {
     hwaddr raddr;      /* Real address              */
-    hwaddr eaddr;      /* Effective address         */
     int prot;                      /* Protection bits           */
     hwaddr hash[2];    /* Pagetable hash values     */
     target_ulong ptem;             /* Virtual segment ID | API  */
@@ -372,8 +371,8 @@ static int ppc_hash64_pte_update_flags(struct mmu_ctx_hash64 *ctx,
 }
 
 /* PTE table lookup */
-static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h,
-                      int rwx, int target_page_bits)
+static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
+                      target_ulong eaddr, int h, int rwx, int target_page_bits)
 {
     hwaddr pteg_off;
     target_ulong pte0, pte1;
@@ -429,7 +428,7 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h,
     /* We have a TLB that saves 4K pages, so let's
      * split a huge page to 4k chunks */
     if (target_page_bits != TARGET_PAGE_BITS) {
-        ctx->raddr |= (ctx->eaddr & ((1 << target_page_bits) - 1))
+        ctx->raddr |= (eaddr & ((1 << target_page_bits) - 1))
                       & TARGET_PAGE_MASK;
     }
     return ret;
@@ -444,7 +443,6 @@ static int get_segment64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
     int ret, ret2;
 
     pr = msr_pr;
-    ctx->eaddr = eaddr;
     ppc_slb_t *slb;
     target_ulong pageaddr;
     int segment_bits;
@@ -500,14 +498,14 @@ static int get_segment64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
                 env->htab_base, env->htab_mask, vsid, ctx->ptem,
                 ctx->hash[0]);
         /* Primary table lookup */
-        ret = find_pte64(env, ctx, 0, rwx, target_page_bits);
+        ret = find_pte64(env, ctx, eaddr, 0, rwx, target_page_bits);
         if (ret < 0) {
             /* Secondary table lookup */
             LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
                     " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
                     " hash=" TARGET_FMT_plx "\n", env->htab_base,
                     env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
-            ret2 = find_pte64(env, ctx, 1, rwx, target_page_bits);
+            ret2 = find_pte64(env, ctx, eaddr, 1, rwx, target_page_bits);
             if (ret2 != -1) {
                 ret = ret2;
             }
commit ba36ed10059f63c981d046a3fe0d716f77959429
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:21 2013 +0000

    mmu-hash64: Remove nx from mmu_ctx_hash64
    
    The nx field in mmu_ctx_hash64 is used in two different functions.  But its
    used for slightly different things in each place, and the value is never
    propagated between them.  In other words, it might as well be two local
    variables.  This patch makes it so.
    
    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/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 654ef06..f89d005 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -47,7 +47,6 @@ struct mmu_ctx_hash64 {
     hwaddr hash[2];    /* Pagetable hash values     */
     target_ulong ptem;             /* Virtual segment ID | API  */
     int key;                       /* Access key                */
-    int nx;                        /* Non-execute area          */
 };
 
 /*
@@ -235,7 +234,7 @@ target_ulong helper_load_slb_vsid(CPUPPCState *env, target_ulong rb)
 
 #define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
 
-static int ppc_hash64_pp_check(int key, int pp, int nx)
+static int ppc_hash64_pp_check(int key, int pp, bool nx)
 {
     int access;
 
@@ -269,7 +268,7 @@ static int ppc_hash64_pp_check(int key, int pp, int nx)
             break;
         }
     }
-    if (nx == 0) {
+    if (!nx) {
         access |= PAGE_EXEC;
     }
 
@@ -312,11 +311,13 @@ static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0,
     ret = -1;
     /* Check validity and table match */
     if ((pte0 & HPTE64_V_VALID) && (h == !!(pte0 & HPTE64_V_SECONDARY))) {
+        bool nx;
+
         /* Check vsid & api */
         mmask = PTE64_CHECK_MASK;
         pp = (pte1 & HPTE64_R_PP) | ((pte1 & HPTE64_R_PP0) >> 61);
         /* No execute if either noexec or guarded bits set */
-        ctx->nx = (pte1 & HPTE64_R_N) || (pte1 & HPTE64_R_G);
+        nx = (pte1 & HPTE64_R_N) || (pte1 & HPTE64_R_G);
         if (HPTE64_V_COMPARE(pte0, ctx->ptem)) {
             if (ctx->raddr != (hwaddr)-1ULL) {
                 /* all matches should have equal RPN, WIMG & PP */
@@ -326,7 +327,7 @@ static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0,
                 }
             }
             /* Compute access rights */
-            access = ppc_hash64_pp_check(ctx->key, pp, ctx->nx);
+            access = ppc_hash64_pp_check(ctx->key, pp, nx);
             /* Keep the matching PTE informations */
             ctx->raddr = pte1;
             ctx->prot = access;
@@ -466,7 +467,6 @@ static int get_segment64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
         ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
     ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP)
                   : (slb->vsid & SLB_VSID_KS));
-    ctx->nx = !!(slb->vsid & SLB_VSID_N);
 
     pageaddr = eaddr & ((1ULL << segment_bits)
                             - (1ULL << target_page_bits));
@@ -480,11 +480,11 @@ static int get_segment64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
         ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
 
     LOG_MMU("pte segment: key=%d nx %d vsid " TARGET_FMT_lx "\n",
-            ctx->key, ctx->nx, vsid);
+            ctx->key, !!(slb->vsid & SLB_VSID_N), vsid);
     ret = -1;
 
     /* Check if instruction fetch is allowed, if needed */
-    if (rwx != 2 || ctx->nx == 0) {
+    if (rwx != 2 || !(slb->vsid & SLB_VSID_N)) {
         /* Page address translation */
         LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
                 " hash " TARGET_FMT_plx "\n",
commit 91cda45b69e45a089f9989979a65db3f710c9925
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:20 2013 +0000

    mmu-hash*: Reduce use of access_type
    
    In ppc env->access_type is updated by e.g. integer load/stores with
    ACCESS_INT floating point load/stores with ACCESS_FLOAT and so forth.  In
    hash mmu fault paths it can also b set to ACCESS_CODE for instruction
    fetch accesses.
    
    But the only place which uses anything more of the access_type than
    whether it is instruction fetch or data access is the direct store segment
    handling.  Instruction versus data access can be more simply determined
    from the rw value passed down from the top.
    
    This changes the code to use rw in preference to checking access_type.
    For the 32-bit case there is a small amount of code (for direct store
    segments) that still needs the full access type.  Instead of passing it
    all the way down the stack, we retrieve it from the env structure, which
    is where it came anyway, before this patch.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index a7c2e35..ad5ef44 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -91,17 +91,17 @@ static int ppc_hash32_pp_check(int key, int pp, int nx)
     return access;
 }
 
-static int ppc_hash32_check_prot(int prot, int rw, int access_type)
+static int ppc_hash32_check_prot(int prot, int rwx)
 {
     int ret;
 
-    if (access_type == ACCESS_CODE) {
+    if (rwx == 2) {
         if (prot & PAGE_EXEC) {
             ret = 0;
         } else {
             ret = -2;
         }
-    } else if (rw) {
+    } else if (rwx) {
         if (prot & PAGE_WRITE) {
             ret = 0;
         } else {
@@ -172,7 +172,7 @@ static void hash32_bat_601_size_prot(CPUPPCState *env, target_ulong *blp,
 }
 
 static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
-                              target_ulong virtual, int rw, int type)
+                              target_ulong virtual, int rwx)
 {
     target_ulong *BATlt, *BATut, *BATu, *BATl;
     target_ulong BEPIl, BEPIu, bl;
@@ -180,16 +180,13 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     int ret = -1;
 
     LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
-             type == ACCESS_CODE ? 'I' : 'D', virtual);
-    switch (type) {
-    case ACCESS_CODE:
+             rwx == 2 ? 'I' : 'D', virtual);
+    if (rwx == 2) {
         BATlt = env->IBAT[1];
         BATut = env->IBAT[0];
-        break;
-    default:
+    } else {
         BATlt = env->DBAT[1];
         BATut = env->DBAT[0];
-        break;
     }
     for (i = 0; i < env->nb_BATs; i++) {
         BATu = &BATut[i];
@@ -214,7 +211,7 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
                     (virtual & 0x0001F000);
                 /* Compute access rights */
                 ctx->prot = prot;
-                ret = ppc_hash32_check_prot(ctx->prot, rw, type);
+                ret = ppc_hash32_check_prot(ctx->prot, rwx);
                 if (ret == 0) {
                     LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
                              i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
@@ -248,7 +245,7 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
 }
 
 static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0,
-                            target_ulong pte1, int h, int rw, int type)
+                            target_ulong pte1, int h, int rwx)
 {
     target_ulong mmask;
     int access, ret, pp;
@@ -272,7 +269,7 @@ static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0,
             /* Keep the matching PTE informations */
             ctx->raddr = pte1;
             ctx->prot = access;
-            ret = ppc_hash32_check_prot(ctx->prot, rw, type);
+            ret = ppc_hash32_check_prot(ctx->prot, rwx);
             if (ret == 0) {
                 /* Access granted */
                 LOG_MMU("PTE access granted !\n");
@@ -287,7 +284,7 @@ static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0,
 }
 
 static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx, target_ulong *pte1p,
-                                       int ret, int rw)
+                                       int ret, int rwx)
 {
     int store = 0;
 
@@ -298,7 +295,7 @@ static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx, target_ulong
         store = 1;
     }
     if (!(*pte1p & HPTE32_R_C)) {
-        if (rw == 1 && ret == 0) {
+        if (rwx == 1 && ret == 0) {
             /* Update changed flag */
             *pte1p |= HPTE32_R_C;
             store = 1;
@@ -318,7 +315,7 @@ hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash)
 
 /* PTE table lookup */
 static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h,
-                      int rw, int type, int target_page_bits)
+                      int rwx, int target_page_bits)
 {
     hwaddr pteg_off;
     target_ulong pte0, pte1;
@@ -330,7 +327,7 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h,
     for (i = 0; i < HPTES_PER_GROUP; i++) {
         pte0 = ppc_hash32_load_hpte0(env, pteg_off + i*HASH_PTE_SIZE_32);
         pte1 = ppc_hash32_load_hpte1(env, pteg_off + i*HASH_PTE_SIZE_32);
-        r = pte_check_hash32(ctx, pte0, pte1, h, rw, type);
+        r = pte_check_hash32(ctx, pte0, pte1, h, rwx);
         LOG_MMU("Load pte from %08" HWADDR_PRIx " => " TARGET_FMT_lx " "
                 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
                 pteg_off + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
@@ -365,7 +362,7 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h,
                 ctx->raddr, ctx->prot, ret);
         /* Update page flags */
         pte1 = ctx->raddr;
-        if (ppc_hash32_pte_update_flags(ctx, &pte1, ret, rw) == 1) {
+        if (ppc_hash32_pte_update_flags(ctx, &pte1, ret, rwx) == 1) {
             ppc_hash32_store_hpte1(env, pteg_off + good * HASH_PTE_SIZE_32,
                                    pte1);
         }
@@ -381,7 +378,7 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h,
 }
 
 static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
-                         target_ulong eaddr, int rw, int type)
+                         target_ulong eaddr, int rwx)
 {
     hwaddr hash;
     target_ulong vsid;
@@ -401,9 +398,9 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     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
-            " ir=%d dr=%d pr=%d %d t=%d\n",
+            " ir=%d dr=%d pr=%d %d\n",
             eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
-            (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
+            (int)msr_dr, pr != 0 ? 1 : 0, rwx);
     pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
     hash = vsid ^ pgidx;
     ctx->ptem = (vsid << 7) | (pgidx >> 10);
@@ -413,7 +410,7 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     ret = -1;
     if (!ds) {
         /* Check if instruction fetch is allowed, if needed */
-        if (type != ACCESS_CODE || ctx->nx == 0) {
+        if (rwx != 2 || ctx->nx == 0) {
             /* Page address translation */
             LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
                     " hash " TARGET_FMT_plx "\n",
@@ -429,15 +426,14 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
                     env->htab_base, env->htab_mask, vsid, ctx->ptem,
                     ctx->hash[0]);
             /* Primary table lookup */
-            ret = find_pte32(env, ctx, 0, rw, type, target_page_bits);
+            ret = find_pte32(env, ctx, 0, rwx, target_page_bits);
             if (ret < 0) {
                 /* Secondary table lookup */
                 LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
                         " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
                         " hash=" TARGET_FMT_plx "\n", env->htab_base,
                         env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
-                ret2 = find_pte32(env, ctx, 1, rw, type,
-                                  target_page_bits);
+                ret2 = find_pte32(env, ctx, 1, rwx, target_page_bits);
                 if (ret2 != -1) {
                     ret = ret2;
                 }
@@ -486,13 +482,15 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
             return 0;
         }
 
-        switch (type) {
+        if (rwx == 2) {
+            /* No code fetch is allowed in direct-store areas */
+            return -4;
+        }
+
+        switch (env->access_type) {
         case ACCESS_INT:
             /* Integer load/store : only access allowed */
             break;
-        case ACCESS_CODE:
-            /* No code fetch is allowed in direct-store areas */
-            return -4;
         case ACCESS_FLOAT:
             /* Floating point load/store */
             return -4;
@@ -514,7 +512,7 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
                         "address translation\n");
             return -4;
         }
-        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
+        if ((rwx == 1 || ctx->key != 1) && (rwx == 0 || ctx->key != 0)) {
             ctx->raddr = eaddr;
             ret = 2;
         } else {
@@ -526,11 +524,10 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
 }
 
 static int ppc_hash32_get_physical_address(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
-                                           target_ulong eaddr, int rw,
-                                           int access_type)
+                                           target_ulong eaddr, int rwx)
 {
-    bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0)
-        || (access_type != ACCESS_CODE && msr_dr == 0);
+    bool real_mode = (rwx == 2 && msr_ir == 0)
+        || (rwx != 2 && msr_dr == 0);
 
     if (real_mode) {
         ctx->raddr = eaddr;
@@ -541,11 +538,11 @@ static int ppc_hash32_get_physical_address(CPUPPCState *env, struct mmu_ctx_hash
 
         /* Try to find a BAT */
         if (env->nb_BATs != 0) {
-            ret = ppc_hash32_get_bat(env, ctx, eaddr, rw, access_type);
+            ret = ppc_hash32_get_bat(env, ctx, eaddr, rwx);
         }
         if (ret < 0) {
             /* We didn't match any BAT entry or don't have BATs */
-            ret = get_segment32(env, ctx, eaddr, rw, access_type);
+            ret = get_segment32(env, ctx, eaddr, rwx);
         }
         return ret;
     }
@@ -555,7 +552,9 @@ hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
 {
     struct mmu_ctx_hash32 ctx;
 
-    if (unlikely(ppc_hash32_get_physical_address(env, &ctx, addr, 0, ACCESS_INT)
+    /* FIXME: Will not behave sanely for direct store segments, but
+     * they're almost never used */
+    if (unlikely(ppc_hash32_get_physical_address(env, &ctx, addr, 0)
                  != 0)) {
         return -1;
     }
@@ -563,22 +562,13 @@ hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
     return ctx.raddr & TARGET_PAGE_MASK;
 }
 
-int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
+int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rwx,
                                 int mmu_idx)
 {
     struct mmu_ctx_hash32 ctx;
-    int access_type;
     int ret = 0;
 
-    if (rw == 2) {
-        /* code access */
-        rw = 0;
-        access_type = ACCESS_CODE;
-    } else {
-        /* data access */
-        access_type = env->access_type;
-    }
-    ret = ppc_hash32_get_physical_address(env, &ctx, address, rw, access_type);
+    ret = ppc_hash32_get_physical_address(env, &ctx, address, rwx);
     if (ret == 0) {
         tlb_set_page(env, address & TARGET_PAGE_MASK,
                      ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
@@ -586,7 +576,7 @@ int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
         ret = 0;
     } else if (ret < 0) {
         LOG_MMU_STATE(env);
-        if (access_type == ACCESS_CODE) {
+        if (rwx == 2) {
             switch (ret) {
             case -1:
                 /* No matches in page tables or TLB */
@@ -617,7 +607,7 @@ int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                 env->exception_index = POWERPC_EXCP_DSI;
                 env->error_code = 0;
                 env->spr[SPR_DAR] = address;
-                if (rw == 1) {
+                if (rwx == 1) {
                     env->spr[SPR_DSISR] = 0x42000000;
                 } else {
                     env->spr[SPR_DSISR] = 0x40000000;
@@ -628,7 +618,7 @@ int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                 env->exception_index = POWERPC_EXCP_DSI;
                 env->error_code = 0;
                 env->spr[SPR_DAR] = address;
-                if (rw == 1) {
+                if (rwx == 1) {
                     env->spr[SPR_DSISR] = 0x0A000000;
                 } else {
                     env->spr[SPR_DSISR] = 0x08000000;
@@ -636,7 +626,7 @@ int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                 break;
             case -4:
                 /* Direct store exception */
-                switch (access_type) {
+                switch (env->access_type) {
                 case ACCESS_FLOAT:
                     /* Floating point load/store */
                     env->exception_index = POWERPC_EXCP_ALIGN;
@@ -648,7 +638,7 @@ int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                     env->exception_index = POWERPC_EXCP_DSI;
                     env->error_code = 0;
                     env->spr[SPR_DAR] = address;
-                    if (rw == 1) {
+                    if (rwx == 1) {
                         env->spr[SPR_DSISR] = 0x06000000;
                     } else {
                         env->spr[SPR_DSISR] = 0x04000000;
@@ -659,7 +649,7 @@ int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                     env->exception_index = POWERPC_EXCP_DSI;
                     env->error_code = 0;
                     env->spr[SPR_DAR] = address;
-                    if (rw == 1) {
+                    if (rwx == 1) {
                         env->spr[SPR_DSISR] = 0x06100000;
                     } else {
                         env->spr[SPR_DSISR] = 0x04100000;
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 30c25dd..654ef06 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -276,17 +276,17 @@ static int ppc_hash64_pp_check(int key, int pp, int nx)
     return access;
 }
 
-static int ppc_hash64_check_prot(int prot, int rw, int access_type)
+static int ppc_hash64_check_prot(int prot, int rwx)
 {
     int ret;
 
-    if (access_type == ACCESS_CODE) {
+    if (rwx == 2) {
         if (prot & PAGE_EXEC) {
             ret = 0;
         } else {
             ret = -2;
         }
-    } else if (rw) {
+    } else if (rwx == 1) {
         if (prot & PAGE_WRITE) {
             ret = 0;
         } else {
@@ -304,7 +304,7 @@ static int ppc_hash64_check_prot(int prot, int rw, int access_type)
 }
 
 static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0,
-                       target_ulong pte1, int h, int rw, int type)
+                       target_ulong pte1, int h, int rwx)
 {
     target_ulong mmask;
     int access, ret, pp;
@@ -330,7 +330,7 @@ static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0,
             /* Keep the matching PTE informations */
             ctx->raddr = pte1;
             ctx->prot = access;
-            ret = ppc_hash64_check_prot(ctx->prot, rw, type);
+            ret = ppc_hash64_check_prot(ctx->prot, rwx);
             if (ret == 0) {
                 /* Access granted */
                 LOG_MMU("PTE access granted !\n");
@@ -372,7 +372,7 @@ static int ppc_hash64_pte_update_flags(struct mmu_ctx_hash64 *ctx,
 
 /* PTE table lookup */
 static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h,
-                      int rw, int type, int target_page_bits)
+                      int rwx, int target_page_bits)
 {
     hwaddr pteg_off;
     target_ulong pte0, pte1;
@@ -385,7 +385,7 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h,
         pte0 = ppc_hash64_load_hpte0(env, pteg_off + i*HASH_PTE_SIZE_64);
         pte1 = ppc_hash64_load_hpte1(env, pteg_off + i*HASH_PTE_SIZE_64);
 
-        r = pte64_check(ctx, pte0, pte1, h, rw, type);
+        r = pte64_check(ctx, pte0, pte1, h, rwx);
         LOG_MMU("Load pte from %016" HWADDR_PRIx " => " TARGET_FMT_lx " "
                 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
                 pteg_off + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
@@ -420,7 +420,7 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h,
                 ctx->raddr, ctx->prot, ret);
         /* Update page flags */
         pte1 = ctx->raddr;
-        if (ppc_hash64_pte_update_flags(ctx, &pte1, ret, rw) == 1) {
+        if (ppc_hash64_pte_update_flags(ctx, &pte1, ret, rwx) == 1) {
             ppc_hash64_store_hpte1(env, pteg_off + good * HASH_PTE_SIZE_64, pte1);
         }
     }
@@ -435,7 +435,7 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h,
 }
 
 static int get_segment64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
-                         target_ulong eaddr, int rw, int type)
+                         target_ulong eaddr, int rwx)
 {
     hwaddr hash;
     target_ulong vsid;
@@ -484,7 +484,7 @@ static int get_segment64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
     ret = -1;
 
     /* Check if instruction fetch is allowed, if needed */
-    if (type != ACCESS_CODE || ctx->nx == 0) {
+    if (rwx != 2 || ctx->nx == 0) {
         /* Page address translation */
         LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
                 " hash " TARGET_FMT_plx "\n",
@@ -500,14 +500,14 @@ static int get_segment64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
                 env->htab_base, env->htab_mask, vsid, ctx->ptem,
                 ctx->hash[0]);
         /* Primary table lookup */
-        ret = find_pte64(env, ctx, 0, rw, type, target_page_bits);
+        ret = find_pte64(env, ctx, 0, rwx, target_page_bits);
         if (ret < 0) {
             /* Secondary table lookup */
             LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
                     " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
                     " hash=" TARGET_FMT_plx "\n", env->htab_base,
                     env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
-            ret2 = find_pte64(env, ctx, 1, rw, type, target_page_bits);
+            ret2 = find_pte64(env, ctx, 1, rwx, target_page_bits);
             if (ret2 != -1) {
                 ret = ret2;
             }
@@ -522,18 +522,17 @@ static int get_segment64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
 
 static int ppc_hash64_get_physical_address(CPUPPCState *env,
                                            struct mmu_ctx_hash64 *ctx,
-                                           target_ulong eaddr, int rw,
-                                           int access_type)
+                                           target_ulong eaddr, int rwx)
 {
-    bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0)
-        || (access_type != ACCESS_CODE && msr_dr == 0);
+    bool real_mode = (rwx == 2 && msr_ir == 0)
+        || (rwx != 2 && msr_dr == 0);
 
     if (real_mode) {
         ctx->raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL;
         ctx->prot = PAGE_READ | PAGE_EXEC | PAGE_WRITE;
         return 0;
     } else {
-        return get_segment64(env, ctx, eaddr, rw, access_type);
+        return get_segment64(env, ctx, eaddr, rwx);
     }
 }
 
@@ -541,30 +540,20 @@ hwaddr ppc_hash64_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
 {
     struct mmu_ctx_hash64 ctx;
 
-    if (unlikely(ppc_hash64_get_physical_address(env, &ctx, addr, 0, ACCESS_INT)
-                 != 0)) {
+    if (unlikely(ppc_hash64_get_physical_address(env, &ctx, addr, 0) != 0)) {
         return -1;
     }
 
     return ctx.raddr & TARGET_PAGE_MASK;
 }
 
-int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
+int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rwx,
                                 int mmu_idx)
 {
     struct mmu_ctx_hash64 ctx;
-    int access_type;
     int ret = 0;
 
-    if (rw == 2) {
-        /* code access */
-        rw = 0;
-        access_type = ACCESS_CODE;
-    } else {
-        /* data access */
-        access_type = env->access_type;
-    }
-    ret = ppc_hash64_get_physical_address(env, &ctx, address, rw, access_type);
+    ret = ppc_hash64_get_physical_address(env, &ctx, address, rwx);
     if (ret == 0) {
         tlb_set_page(env, address & TARGET_PAGE_MASK,
                      ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
@@ -572,7 +561,7 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
         ret = 0;
     } else if (ret < 0) {
         LOG_MMU_STATE(env);
-        if (access_type == ACCESS_CODE) {
+        if (rwx == 2) {
             switch (ret) {
             case -1:
                 env->exception_index = POWERPC_EXCP_ISI;
@@ -601,7 +590,7 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                 env->exception_index = POWERPC_EXCP_DSI;
                 env->error_code = 0;
                 env->spr[SPR_DAR] = address;
-                if (rw == 1) {
+                if (rwx == 1) {
                     env->spr[SPR_DSISR] = 0x42000000;
                 } else {
                     env->spr[SPR_DSISR] = 0x40000000;
@@ -612,7 +601,7 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                 env->exception_index = POWERPC_EXCP_DSI;
                 env->error_code = 0;
                 env->spr[SPR_DAR] = address;
-                if (rw == 1) {
+                if (rwx == 1) {
                     env->spr[SPR_DSISR] = 0x0A000000;
                 } else {
                     env->spr[SPR_DSISR] = 0x08000000;
commit dffdaf6162d20b992e34c4708969ed4de0353417
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:19 2013 +0000

    mmu-hash*: Add hash pte load/store helpers
    
    On real hardware the ppc hash page table is stored in memory; accordingly
    our mmu emulation code can read a hash page table in guest memory.  But,
    when paravirtualized under PAPR, the real hash page table is in host
    memory, accessible to the guest only via hypercalls.  We model this by
    also allowing the MMU emulation code to access a specially allocated hash
    page table outside the guest's memory image. At present these two options
    are implemented with some ugly conditionals at each access point in the mmu
    emulation code.  In the implementation of the PAPR hypercalls, we assume
    the external hash table.
    
    This patch cleans things up by adding helpers to load and store from the
    hash table for both 32-bit and 64-bit hash mmus.  The 64-bit versions
    handle both the in-guest-memory and outside guest memory cases.  The 32-bit
    versions only handle the in-guest-memory case since no 32-bit systems can
    have an external hash table at present.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 7be743c..22cfb7e 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -52,7 +52,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     target_ulong page_shift = 12;
     target_ulong raddr;
     target_ulong i;
-    uint8_t *hpte;
+    hwaddr hpte;
 
     /* only handle 4k and 16M pages for now */
     if (pteh & HPTE64_V_LARGE) {
@@ -97,26 +97,26 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     }
     if (likely((flags & H_EXACT) == 0)) {
         pte_index &= ~7ULL;
-        hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
+        hpte = pte_index * HASH_PTE_SIZE_64;
         for (i = 0; ; ++i) {
             if (i == 8) {
                 return H_PTEG_FULL;
             }
-            if ((ldq_p(hpte) & HPTE64_V_VALID) == 0) {
+            if ((ppc_hash64_load_hpte0(env, hpte) & HPTE64_V_VALID) == 0) {
                 break;
             }
             hpte += HASH_PTE_SIZE_64;
         }
     } else {
         i = 0;
-        hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
-        if (ldq_p(hpte) & HPTE64_V_VALID) {
+        hpte = pte_index * HASH_PTE_SIZE_64;
+        if (ppc_hash64_load_hpte0(env, hpte) & HPTE64_V_VALID) {
             return H_PTEG_FULL;
         }
     }
-    stq_p(hpte + (HASH_PTE_SIZE_64/2), ptel);
+    ppc_hash64_store_hpte1(env, hpte, ptel);
     /* eieio();  FIXME: need some sort of barrier for smp? */
-    stq_p(hpte, pteh);
+    ppc_hash64_store_hpte0(env, hpte, pteh);
 
     args[0] = pte_index + i;
     return H_SUCCESS;
@@ -134,17 +134,17 @@ static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex,
                                 target_ulong flags,
                                 target_ulong *vp, target_ulong *rp)
 {
-    uint8_t *hpte;
+    hwaddr hpte;
     target_ulong v, r, rb;
 
     if ((ptex * HASH_PTE_SIZE_64) & ~env->htab_mask) {
         return REMOVE_PARM;
     }
 
-    hpte = env->external_htab + (ptex * HASH_PTE_SIZE_64);
+    hpte = ptex * HASH_PTE_SIZE_64;
 
-    v = ldq_p(hpte);
-    r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
+    v = ppc_hash64_load_hpte0(env, hpte);
+    r = ppc_hash64_load_hpte1(env, hpte);
 
     if ((v & HPTE64_V_VALID) == 0 ||
         ((flags & H_AVPN) && (v & ~0x7fULL) != avpn) ||
@@ -153,7 +153,7 @@ static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex,
     }
     *vp = v;
     *rp = r;
-    stq_p(hpte, 0);
+    ppc_hash64_store_hpte0(env, hpte, 0);
     rb = compute_tlbie_rb(v, r, ptex);
     ppc_tlb_invalidate_one(env, rb);
     return REMOVE_SUCCESS;
@@ -260,17 +260,17 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     target_ulong flags = args[0];
     target_ulong pte_index = args[1];
     target_ulong avpn = args[2];
-    uint8_t *hpte;
+    hwaddr 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);
+    hpte = pte_index * HASH_PTE_SIZE_64;
 
-    v = ldq_p(hpte);
-    r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
+    v = ppc_hash64_load_hpte0(env, hpte);
+    r = ppc_hash64_load_hpte1(env, hpte);
 
     if ((v & HPTE64_V_VALID) == 0 ||
         ((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) {
@@ -283,11 +283,11 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     r |= (flags << 48) & HPTE64_R_KEY_HI;
     r |= flags & (HPTE64_R_PP | HPTE64_R_N | HPTE64_R_KEY_LO);
     rb = compute_tlbie_rb(v, r, pte_index);
-    stq_p(hpte, v & ~HPTE64_V_VALID);
+    ppc_hash64_store_hpte0(env, hpte, v & ~HPTE64_V_VALID);
     ppc_tlb_invalidate_one(env, rb);
-    stq_p(hpte + (HASH_PTE_SIZE_64/2), r);
+    ppc_hash64_store_hpte1(env, hpte, r);
     /* Don't need a memory barrier, due to qemu's global lock */
-    stq_p(hpte, v);
+    ppc_hash64_store_hpte0(env, hpte, v);
     return H_SUCCESS;
 }
 
diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c
index a1bbd50..a7c2e35 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -328,13 +328,8 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h,
     ret = -1; /* No entry found */
     pteg_off = get_pteg_offset32(env, ctx->hash[h]);
     for (i = 0; i < HPTES_PER_GROUP; i++) {
-        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);
-        }
+        pte0 = ppc_hash32_load_hpte0(env, pteg_off + i*HASH_PTE_SIZE_32);
+        pte1 = ppc_hash32_load_hpte1(env, pteg_off + i*HASH_PTE_SIZE_32);
         r = pte_check_hash32(ctx, pte0, pte1, h, rw, type);
         LOG_MMU("Load pte from %08" HWADDR_PRIx " => " TARGET_FMT_lx " "
                 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
@@ -371,13 +366,8 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h,
         /* Update page flags */
         pte1 = ctx->raddr;
         if (ppc_hash32_pte_update_flags(ctx, &pte1, ret, rw) == 1) {
-            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);
-            }
+            ppc_hash32_store_hpte1(env, pteg_off + good * HASH_PTE_SIZE_32,
+                                   pte1);
         }
     }
 
diff --git a/target-ppc/mmu-hash32.h b/target-ppc/mmu-hash32.h
index a09ccb3..2344184 100644
--- a/target-ppc/mmu-hash32.h
+++ b/target-ppc/mmu-hash32.h
@@ -69,6 +69,34 @@ int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
 #define HPTE32_R_WIMG           0x00000078
 #define HPTE32_R_PP             0x00000003
 
+static inline target_ulong ppc_hash32_load_hpte0(CPUPPCState *env,
+                                                 hwaddr pte_offset)
+{
+    assert(!env->external_htab); /* Not supported on 32-bit for now */
+    return ldl_phys(env->htab_base + pte_offset);
+}
+
+static inline target_ulong ppc_hash32_load_hpte1(CPUPPCState *env,
+                                                 hwaddr pte_offset)
+{
+    assert(!env->external_htab); /* Not supported on 32-bit for now */
+    return ldl_phys(env->htab_base + pte_offset + HASH_PTE_SIZE_32/2);
+}
+
+static inline void ppc_hash32_store_hpte0(CPUPPCState *env,
+                                          hwaddr pte_offset, target_ulong pte0)
+{
+    assert(!env->external_htab); /* Not supported on 32-bit for now */
+    stl_phys(env->htab_base + pte_offset, pte0);
+}
+
+static inline void ppc_hash32_store_hpte1(CPUPPCState *env,
+                                          hwaddr pte_offset, target_ulong pte1)
+{
+    assert(!env->external_htab); /* Not supported on 32-bit for now */
+    stl_phys(env->htab_base + pte_offset + HASH_PTE_SIZE_32/2, pte1);
+}
+
 #endif /* CONFIG_USER_ONLY */
 
 #endif /* __MMU_HASH32_H__ */
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index f3223dd..30c25dd 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -382,13 +382,8 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h,
     ret = -1; /* No entry found */
     pteg_off = (ctx->hash[h] * HASH_PTEG_SIZE_64) & env->htab_mask;
     for (i = 0; i < HPTES_PER_GROUP; i++) {
-        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);
-        }
+        pte0 = ppc_hash64_load_hpte0(env, pteg_off + i*HASH_PTE_SIZE_64);
+        pte1 = ppc_hash64_load_hpte1(env, pteg_off + i*HASH_PTE_SIZE_64);
 
         r = pte64_check(ctx, pte0, pte1, h, rw, type);
         LOG_MMU("Load pte from %016" HWADDR_PRIx " => " TARGET_FMT_lx " "
@@ -426,13 +421,7 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h,
         /* Update page flags */
         pte1 = ctx->raddr;
         if (ppc_hash64_pte_update_flags(ctx, &pte1, ret, rw) == 1) {
-            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);
-            }
+            ppc_hash64_store_hpte1(env, pteg_off + good * HASH_PTE_SIZE_64, pte1);
         }
     }
 
diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h
index 80b86d9..84576c0 100644
--- a/target-ppc/mmu-hash64.h
+++ b/target-ppc/mmu-hash64.h
@@ -73,6 +73,46 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
 #define HPTE64_V_1TB_SEG        0x4000000000000000ULL
 #define HPTE64_V_VRMA_MASK      0x4001ffffff000000ULL
 
+static inline target_ulong ppc_hash64_load_hpte0(CPUPPCState *env,
+                                                 hwaddr pte_offset)
+{
+    if (env->external_htab) {
+        return  ldq_p(env->external_htab + pte_offset);
+    } else {
+        return ldq_phys(env->htab_base + pte_offset);
+    }
+}
+
+static inline target_ulong ppc_hash64_load_hpte1(CPUPPCState *env,
+                                                 hwaddr pte_offset)
+{
+    if (env->external_htab) {
+        return ldq_p(env->external_htab + pte_offset + HASH_PTE_SIZE_64/2);
+    } else {
+        return ldq_phys(env->htab_base + pte_offset + HASH_PTE_SIZE_64/2);
+    }
+}
+
+static inline void ppc_hash64_store_hpte0(CPUPPCState *env,
+                                          hwaddr pte_offset, target_ulong pte0)
+{
+    if (env->external_htab) {
+        stq_p(env->external_htab + pte_offset, pte0);
+    } else {
+        stq_phys(env->htab_base + pte_offset, pte0);
+    }
+}
+
+static inline void ppc_hash64_store_hpte1(CPUPPCState *env,
+                                          hwaddr pte_offset, target_ulong pte1)
+{
+    if (env->external_htab) {
+        stq_p(env->external_htab + pte_offset + HASH_PTE_SIZE_64/2, pte1);
+    } else {
+        stq_phys(env->htab_base + pte_offset + HASH_PTE_SIZE_64/2, pte1);
+    }
+}
+
 #endif /* CONFIG_USER_ONLY */
 
 #endif /* !defined (__MMU_HASH64_H__) */
commit d5aea6f367d25b630a952a5a0c8289add774a8e8
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:18 2013 +0000

    mmu-hash*: Add header file for definitions
    
    Currently cpu.h contains a number of definitions relating to the 64-bit
    hash MMU.  Some are used in the MMU emulation code, but some are only used
    in the spapr MMU management hcall implementations.
    
    This patch moves these definitions (except for a few that are needed
    more widely) into mmu-hash64.h header, shared between the MMU emulation
    code and the spapr hcall code.  The MMU emulation code is also updated to
    actually use a number of those definitions in place of hard coded
    constants.
    
    Similarly, we add new analogous definitions to mmu-hash32.h and use those
    in place of many hard-coded constants in mmu-hash32.c
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    [agraf: fix 32-bit hosts]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index dd72743..7be743c 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -3,39 +3,7 @@
 #include "sysemu/sysemu.h"
 #include "helper_regs.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
+#include "mmu-hash64.h"
 
 static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
                                      target_ulong pte_index)
@@ -44,17 +12,17 @@ static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
 
     rb = (v & ~0x7fULL) << 16; /* AVA field */
     va_low = pte_index >> 3;
-    if (v & HPTE_V_SECONDARY) {
+    if (v & HPTE64_V_SECONDARY) {
         va_low = ~va_low;
     }
     /* xor vsid from AVA */
-    if (!(v & HPTE_V_1TB_SEG)) {
+    if (!(v & HPTE64_V_1TB_SEG)) {
         va_low ^= v >> 12;
     } else {
         va_low ^= v >> 24;
     }
     va_low &= 0x7ff;
-    if (v & HPTE_V_LARGE) {
+    if (v & HPTE64_V_LARGE) {
         rb |= 1;                         /* L field */
 #if 0 /* Disable that P7 specific bit for now */
         if (r & 0xff000) {
@@ -87,7 +55,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     uint8_t *hpte;
 
     /* only handle 4k and 16M pages for now */
-    if (pteh & HPTE_V_LARGE) {
+    if (pteh & HPTE64_V_LARGE) {
 #if 0 /* We don't support 64k pages yet */
         if ((ptel & 0xf000) == 0x1000) {
             /* 64k page */
@@ -105,11 +73,11 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
         }
     }
 
-    raddr = (ptel & HPTE_R_RPN) & ~((1ULL << page_shift) - 1);
+    raddr = (ptel & HPTE64_R_RPN) & ~((1ULL << page_shift) - 1);
 
     if (raddr < spapr->ram_limit) {
         /* Regular RAM - should have WIMG=0010 */
-        if ((ptel & HPTE_R_WIMG) != HPTE_R_M) {
+        if ((ptel & HPTE64_R_WIMG) != HPTE64_R_M) {
             return H_PARAMETER;
         }
     } else {
@@ -117,7 +85,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
         /* FIXME: What WIMG combinations could be sensible for IO?
          * For now we allow WIMG=010x, but are there others? */
         /* FIXME: Should we check against registered IO addresses? */
-        if ((ptel & (HPTE_R_W | HPTE_R_I | HPTE_R_M)) != HPTE_R_I) {
+        if ((ptel & (HPTE64_R_W | HPTE64_R_I | HPTE64_R_M)) != HPTE64_R_I) {
             return H_PARAMETER;
         }
     }
@@ -134,7 +102,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
             if (i == 8) {
                 return H_PTEG_FULL;
             }
-            if ((ldq_p(hpte) & HPTE_V_VALID) == 0) {
+            if ((ldq_p(hpte) & HPTE64_V_VALID) == 0) {
                 break;
             }
             hpte += HASH_PTE_SIZE_64;
@@ -142,7 +110,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     } else {
         i = 0;
         hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
-        if (ldq_p(hpte) & HPTE_V_VALID) {
+        if (ldq_p(hpte) & HPTE64_V_VALID) {
             return H_PTEG_FULL;
         }
     }
@@ -178,7 +146,7 @@ static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex,
     v = ldq_p(hpte);
     r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
 
-    if ((v & HPTE_V_VALID) == 0 ||
+    if ((v & HPTE64_V_VALID) == 0 ||
         ((flags & H_AVPN) && (v & ~0x7fULL) != avpn) ||
         ((flags & H_ANDCOND) && (v & avpn) != 0)) {
         return REMOVE_NOT_FOUND;
@@ -271,7 +239,7 @@ static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 
         switch (ret) {
         case REMOVE_SUCCESS:
-            *tsh |= (r & (HPTE_R_C | HPTE_R_R)) << 43;
+            *tsh |= (r & (HPTE64_R_C | HPTE64_R_R)) << 43;
             break;
 
         case REMOVE_PARM:
@@ -304,18 +272,18 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     v = ldq_p(hpte);
     r = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
 
-    if ((v & HPTE_V_VALID) == 0 ||
+    if ((v & HPTE64_V_VALID) == 0 ||
         ((flags & H_AVPN) && (v & ~0x7fULL) != avpn)) {
         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);
+    r &= ~(HPTE64_R_PP0 | HPTE64_R_PP | HPTE64_R_N |
+           HPTE64_R_KEY_HI | HPTE64_R_KEY_LO);
+    r |= (flags << 55) & HPTE64_R_PP0;
+    r |= (flags << 48) & HPTE64_R_KEY_HI;
+    r |= flags & (HPTE64_R_PP | HPTE64_R_N | HPTE64_R_KEY_LO);
     rb = compute_tlbie_rb(v, r, pte_index);
-    stq_p(hpte, v & ~HPTE_V_VALID);
+    stq_p(hpte, v & ~HPTE64_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 */
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index e5f46b3..e96afa6 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -394,36 +394,12 @@ 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;
     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_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
-#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))
 
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 9870d60..597066f 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -32,6 +32,7 @@
 #include "sysemu/device_tree.h"
 #include "hw/sysbus.h"
 #include "hw/spapr.h"
+#include "mmu-hash64.h"
 
 #include "hw/sysbus.h"
 #include "hw/spapr.h"
diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 5b48aa8..a1bbd50 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -51,7 +51,6 @@ struct mmu_ctx_hash32 {
     int nx;                        /* Non-execute area          */
 };
 
-#define PTE_PTEM_MASK 0x7FFFFFBF
 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
 
 static int ppc_hash32_pp_check(int key, int pp, int nx)
@@ -127,13 +126,13 @@ static void hash32_bat_size_prot(CPUPPCState *env, target_ulong *blp,
     target_ulong bl;
     int pp, valid, prot;
 
-    bl = (*BATu & 0x00001FFC) << 15;
+    bl = (*BATu & BATU32_BL) << 15;
     valid = 0;
     prot = 0;
-    if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
-        ((msr_pr != 0) && (*BATu & 0x00000001))) {
+    if (((msr_pr == 0) && (*BATu & BATU32_VS)) ||
+        ((msr_pr != 0) && (*BATu & BATU32_VP))) {
         valid = 1;
-        pp = *BATl & 0x00000003;
+        pp = *BATl & BATL32_PP;
         if (pp != 0) {
             prot = PAGE_READ | PAGE_EXEC;
             if (pp == 0x2) {
@@ -153,17 +152,17 @@ static void hash32_bat_601_size_prot(CPUPPCState *env, target_ulong *blp,
     target_ulong bl;
     int key, pp, valid, prot;
 
-    bl = (*BATl & 0x0000003F) << 17;
+    bl = (*BATl & BATL32_601_BL) << 17;
     LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
-             (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
+             (uint8_t)(*BATl & BATL32_601_BL), bl, ~bl);
     prot = 0;
-    valid = (*BATl >> 6) & 1;
+    valid = !!(*BATl & BATL32_601_V);
     if (valid) {
-        pp = *BATu & 0x00000003;
+        pp = *BATu & BATU32_601_PP;
         if (msr_pr == 0) {
-            key = (*BATu >> 3) & 1;
+            key = !!(*BATu & BATU32_601_KS);
         } else {
-            key = (*BATu >> 2) & 1;
+            key = !!(*BATu & BATU32_601_KP);
         }
         prot = ppc_hash32_pp_check(key, pp, 0);
     }
@@ -195,8 +194,8 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     for (i = 0; i < env->nb_BATs; i++) {
         BATu = &BATut[i];
         BATl = &BATlt[i];
-        BEPIu = *BATu & 0xF0000000;
-        BEPIl = *BATu & 0x0FFE0000;
+        BEPIu = *BATu & BATU32_BEPIU;
+        BEPIl = *BATu & BATU32_BEPIL;
         if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
             hash32_bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
         } else {
@@ -205,13 +204,13 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
         LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
                  " BATl " TARGET_FMT_lx "\n", __func__,
                  type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
-        if ((virtual & 0xF0000000) == BEPIu &&
-            ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
+        if ((virtual & BATU32_BEPIU) == BEPIu &&
+            ((virtual & BATU32_BEPIL) & ~bl) == BEPIl) {
             /* BAT matches */
             if (valid != 0) {
                 /* Get physical address */
-                ctx->raddr = (*BATl & 0xF0000000) |
-                    ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
+                ctx->raddr = (*BATl & BATL32_BRPNU) |
+                    ((virtual & BATU32_BEPIL & bl) | (*BATl & BATL32_BRPNL)) |
                     (virtual & 0x0001F000);
                 /* Compute access rights */
                 ctx->prot = prot;
@@ -232,8 +231,8 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
             for (i = 0; i < 4; i++) {
                 BATu = &BATut[i];
                 BATl = &BATlt[i];
-                BEPIu = *BATu & 0xF0000000;
-                BEPIl = *BATu & 0x0FFE0000;
+                BEPIu = *BATu & BATU32_BEPIU;
+                BEPIl = *BATu & BATU32_BEPIL;
                 bl = (*BATu & 0x00001FFC) << 15;
                 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
                          " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
@@ -248,28 +247,19 @@ static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     return ret;
 }
 
-
-static inline int pte_is_valid_hash32(target_ulong pte0)
-{
-    return pte0 & 0x80000000 ? 1 : 0;
-}
-
 static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0,
                             target_ulong pte1, int h, int rw, int type)
 {
-    target_ulong ptem, mmask;
-    int access, ret, pteh, ptev, pp;
+    target_ulong mmask;
+    int access, ret, pp;
 
     ret = -1;
     /* Check validity and table match */
-    ptev = pte_is_valid_hash32(pte0);
-    pteh = (pte0 >> 6) & 1;
-    if (ptev && h == pteh) {
+    if ((pte0 & HPTE32_V_VALID) && (h == !!(pte0 & HPTE32_V_SECONDARY))) {
         /* Check vsid & api */
-        ptem = pte0 & PTE_PTEM_MASK;
         mmask = PTE_CHECK_MASK;
-        pp = pte1 & 0x00000003;
-        if (ptem == ctx->ptem) {
+        pp = pte1 & HPTE32_R_PP;
+        if (HPTE32_V_COMPARE(pte0, ctx->ptem)) {
             if (ctx->raddr != (hwaddr)-1ULL) {
                 /* all matches should have equal RPN, WIMG & PP */
                 if ((ctx->raddr & mmask) != (pte1 & mmask)) {
@@ -302,15 +292,15 @@ static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx, target_ulong
     int store = 0;
 
     /* Update page flags */
-    if (!(*pte1p & 0x00000100)) {
+    if (!(*pte1p & HPTE32_R_R)) {
         /* Update accessed flag */
-        *pte1p |= 0x00000100;
+        *pte1p |= HPTE32_R_R;
         store = 1;
     }
-    if (!(*pte1p & 0x00000080)) {
+    if (!(*pte1p & HPTE32_R_C)) {
         if (rw == 1 && ret == 0) {
             /* Update changed flag */
-            *pte1p |= 0x00000080;
+            *pte1p |= HPTE32_R_C;
             store = 1;
         } else {
             /* Force page fault for first write access */
@@ -323,7 +313,7 @@ static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx, target_ulong
 
 hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash)
 {
-    return (hash * HASH_PTE_SIZE_32 * 8) & env->htab_mask;
+    return (hash * HASH_PTEG_SIZE_32) & env->htab_mask;
 }
 
 /* PTE table lookup */
@@ -337,7 +327,7 @@ static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h,
 
     ret = -1; /* No entry found */
     pteg_off = get_pteg_offset32(env, ctx->hash[h]);
-    for (i = 0; i < 8; i++) {
+    for (i = 0; i < HPTES_PER_GROUP; i++) {
         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);
@@ -413,11 +403,11 @@ static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
     ctx->eaddr = eaddr;
 
     sr = env->sr[eaddr >> 28];
-    ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
-                ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
-    ds = sr & 0x80000000 ? 1 : 0;
-    ctx->nx = sr & 0x10000000 ? 1 : 0;
-    vsid = sr & 0x00FFFFFF;
+    ctx->key = (((sr & SR32_KP) && (pr != 0)) ||
+                ((sr & SR32_KS) && (pr == 0))) ? 1 : 0;
+    ds = !!(sr & SR32_T);
+    ctx->nx = !!(sr & SR32_NX);
+    vsid = sr & SR32_VSID;
     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
diff --git a/target-ppc/mmu-hash32.h b/target-ppc/mmu-hash32.h
index 3435aa5..a09ccb3 100644
--- a/target-ppc/mmu-hash32.h
+++ b/target-ppc/mmu-hash32.h
@@ -8,6 +8,67 @@ hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong addr);
 int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                                 int mmu_idx);
 
+/*
+ * Segment register definitions
+ */
+
+#define SR32_T                  0x80000000
+#define SR32_KS                 0x40000000
+#define SR32_KP                 0x20000000
+#define SR32_NX                 0x10000000
+#define SR32_VSID               0x00ffffff
+
+/*
+ * Block Address Translation (BAT) definitions
+ */
+
+#define BATU32_BEPIU            0xf0000000
+#define BATU32_BEPIL            0x0ffe0000
+#define BATU32_BEPI             0xfffe0000
+#define BATU32_BL               0x00001ffc
+#define BATU32_VS               0x00000002
+#define BATU32_VP               0x00000001
+
+
+#define BATL32_BRPNU            0xf0000000
+#define BATL32_BRPNL            0x0ffe0000
+#define BATL32_BRPN             0xfffe0000
+#define BATL32_WIMG             0x00000078
+#define BATL32_PP               0x00000003
+
+/* PowerPC 601 has slightly different BAT registers */
+
+#define BATU32_601_KS           0x00000008
+#define BATU32_601_KP           0x00000004
+#define BATU32_601_PP           0x00000003
+
+#define BATL32_601_V            0x00000040
+#define BATL32_601_BL           0x0000003f
+
+/*
+ * Hash page table definitions
+ */
+
+#define HPTES_PER_GROUP         8
+#define HASH_PTE_SIZE_32        8
+#define HASH_PTEG_SIZE_32       (HASH_PTE_SIZE_32 * HPTES_PER_GROUP)
+
+#define HPTE32_V_VALID          0x80000000
+#define HPTE32_V_VSID           0x7fffff80
+#define HPTE32_V_SECONDARY      0x00000040
+#define HPTE32_V_API            0x0000003f
+#define HPTE32_V_COMPARE(x, y)  (!(((x) ^ (y)) & 0x7fffffbf))
+
+#define HPTE32_R_RPN            0xfffff000
+#define HPTE32_R_R              0x00000100
+#define HPTE32_R_C              0x00000080
+#define HPTE32_R_W              0x00000040
+#define HPTE32_R_I              0x00000020
+#define HPTE32_R_M              0x00000010
+#define HPTE32_R_G              0x00000008
+#define HPTE32_R_WIMG           0x00000078
+#define HPTE32_R_PP             0x00000003
+
 #endif /* CONFIG_USER_ONLY */
 
 #endif /* __MMU_HASH32_H__ */
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 3008be8..f3223dd 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -233,7 +233,6 @@ target_ulong helper_load_slb_vsid(CPUPPCState *env, target_ulong rb)
  * 64-bit hash table MMU handling
  */
 
-#define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
 #define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
 
 static int ppc_hash64_pp_check(int key, int pp, int nx)
@@ -304,29 +303,21 @@ static int ppc_hash64_check_prot(int prot, int rw, int access_type)
     return ret;
 }
 
-static inline int pte64_is_valid(target_ulong pte0)
-{
-    return pte0 & 0x0000000000000001ULL ? 1 : 0;
-}
-
 static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0,
                        target_ulong pte1, int h, int rw, int type)
 {
-    target_ulong ptem, mmask;
-    int access, ret, pteh, ptev, pp;
+    target_ulong mmask;
+    int access, ret, pp;
 
     ret = -1;
     /* Check validity and table match */
-    ptev = pte64_is_valid(pte0);
-    pteh = (pte0 >> 1) & 1;
-    if (ptev && h == pteh) {
+    if ((pte0 & HPTE64_V_VALID) && (h == !!(pte0 & HPTE64_V_SECONDARY))) {
         /* Check vsid & api */
-        ptem = pte0 & PTE64_PTEM_MASK;
         mmask = PTE64_CHECK_MASK;
-        pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
-        ctx->nx  = (pte1 >> 2) & 1; /* No execute bit */
-        ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit    */
-        if (ptem == ctx->ptem) {
+        pp = (pte1 & HPTE64_R_PP) | ((pte1 & HPTE64_R_PP0) >> 61);
+        /* No execute if either noexec or guarded bits set */
+        ctx->nx = (pte1 & HPTE64_R_N) || (pte1 & HPTE64_R_G);
+        if (HPTE64_V_COMPARE(pte0, ctx->ptem)) {
             if (ctx->raddr != (hwaddr)-1ULL) {
                 /* all matches should have equal RPN, WIMG & PP */
                 if ((ctx->raddr & mmask) != (pte1 & mmask)) {
@@ -360,15 +351,15 @@ static int ppc_hash64_pte_update_flags(struct mmu_ctx_hash64 *ctx,
     int store = 0;
 
     /* Update page flags */
-    if (!(*pte1p & 0x00000100)) {
+    if (!(*pte1p & HPTE64_R_R)) {
         /* Update accessed flag */
-        *pte1p |= 0x00000100;
+        *pte1p |= HPTE64_R_R;
         store = 1;
     }
-    if (!(*pte1p & 0x00000080)) {
+    if (!(*pte1p & HPTE64_R_C)) {
         if (rw == 1 && ret == 0) {
             /* Update changed flag */
-            *pte1p |= 0x00000080;
+            *pte1p |= HPTE64_R_C;
             store = 1;
         } else {
             /* Force page fault for first write access */
@@ -389,8 +380,8 @@ static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h,
     int ret, r;
 
     ret = -1; /* No entry found */
-    pteg_off = (ctx->hash[h] * HASH_PTE_SIZE_64 * 8) & env->htab_mask;
-    for (i = 0; i < 8; i++) {
+    pteg_off = (ctx->hash[h] * HASH_PTEG_SIZE_64) & env->htab_mask;
+    for (i = 0; i < HPTES_PER_GROUP; i++) {
         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);
diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h
index 665d3b0..80b86d9 100644
--- a/target-ppc/mmu-hash64.h
+++ b/target-ppc/mmu-hash64.h
@@ -11,6 +11,68 @@ int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                                 int mmu_idx);
 #endif
 
+/*
+ * SLB definitions
+ */
+
+/* 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_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
+#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
+
+/*
+ * Hash page table definitions
+ */
+
+#define HPTES_PER_GROUP         8
+#define HASH_PTE_SIZE_64        16
+#define HASH_PTEG_SIZE_64       (HASH_PTE_SIZE_64 * HPTES_PER_GROUP)
+
+#define HPTE64_V_SSIZE_SHIFT    62
+#define HPTE64_V_AVPN_SHIFT     7
+#define HPTE64_V_AVPN           0x3fffffffffffff80ULL
+#define HPTE64_V_AVPN_VAL(x)    (((x) & HPTE64_V_AVPN) >> HPTE64_V_AVPN_SHIFT)
+#define HPTE64_V_COMPARE(x, y)  (!(((x) ^ (y)) & 0xffffffffffffff80ULL))
+#define HPTE64_V_LARGE          0x0000000000000004ULL
+#define HPTE64_V_SECONDARY      0x0000000000000002ULL
+#define HPTE64_V_VALID          0x0000000000000001ULL
+
+#define HPTE64_R_PP0            0x8000000000000000ULL
+#define HPTE64_R_TS             0x4000000000000000ULL
+#define HPTE64_R_KEY_HI         0x3000000000000000ULL
+#define HPTE64_R_RPN_SHIFT      12
+#define HPTE64_R_RPN            0x0ffffffffffff000ULL
+#define HPTE64_R_FLAGS          0x00000000000003ffULL
+#define HPTE64_R_PP             0x0000000000000003ULL
+#define HPTE64_R_N              0x0000000000000004ULL
+#define HPTE64_R_G              0x0000000000000008ULL
+#define HPTE64_R_M              0x0000000000000010ULL
+#define HPTE64_R_I              0x0000000000000020ULL
+#define HPTE64_R_W              0x0000000000000040ULL
+#define HPTE64_R_WIMG           0x0000000000000078ULL
+#define HPTE64_R_C              0x0000000000000080ULL
+#define HPTE64_R_R              0x0000000000000100ULL
+#define HPTE64_R_KEY_LO         0x0000000000000e00ULL
+
+#define HPTE64_V_1TB_SEG        0x4000000000000000ULL
+#define HPTE64_V_VRMA_MASK      0x4001ffffff000000ULL
+
 #endif /* CONFIG_USER_ONLY */
 
 #endif /* !defined (__MMU_HASH64_H__) */
commit 5dc68eb0e4e41462bf93cf5c67fe4045571fc7bf
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:17 2013 +0000

    target-ppc: mmu_ctx_t should not be a global type
    
    mmu_ctx_t is currently defined in cpu.h.  However it is used for temporary
    information relating to mmu translation, and is only used in mmu_helper.c
    and (now) mmu-hash{32,64}.c.  Furthermore it contains information which
    should be specific to particular MMU types.  Therefore, move its definition
    to mmu_helper.c.  mmu-hash{32,64}.c are converted to use new data types
    private to the relevant MMUs (identical to mmu_ctx_t for now, but that will
    change in future patches).
    
    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/cpu.h b/target-ppc/cpu.h
index a3e1362..e5f46b3 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1101,20 +1101,6 @@ do {                                            \
     env->wdt_period[3] = (d_);                  \
  } while (0)
 
-#if !defined(CONFIG_USER_ONLY)
-/* Context used internally during MMU translations */
-typedef struct mmu_ctx_t mmu_ctx_t;
-struct mmu_ctx_t {
-    hwaddr raddr;      /* Real address              */
-    hwaddr eaddr;      /* Effective address         */
-    int prot;                      /* Protection bits           */
-    hwaddr hash[2];    /* Pagetable hash values     */
-    target_ulong ptem;             /* Virtual segment ID | API  */
-    int key;                       /* Access key                */
-    int nx;                        /* Non-execute area          */
-};
-#endif
-
 #include "cpu-qom.h"
 
 /*****************************************************************************/
diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c
index f94b65d..5b48aa8 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -41,6 +41,16 @@
 #  define LOG_BATS(...) do { } while (0)
 #endif
 
+struct mmu_ctx_hash32 {
+    hwaddr raddr;      /* Real address              */
+    hwaddr eaddr;      /* Effective address         */
+    int prot;                      /* Protection bits           */
+    hwaddr hash[2];    /* Pagetable hash values     */
+    target_ulong ptem;             /* Virtual segment ID | API  */
+    int key;                       /* Access key                */
+    int nx;                        /* Non-execute area          */
+};
+
 #define PTE_PTEM_MASK 0x7FFFFFBF
 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
 
@@ -162,7 +172,7 @@ static void hash32_bat_601_size_prot(CPUPPCState *env, target_ulong *blp,
     *protp = prot;
 }
 
-static int ppc_hash32_get_bat(CPUPPCState *env, mmu_ctx_t *ctx,
+static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
                               target_ulong virtual, int rw, int type)
 {
     target_ulong *BATlt, *BATut, *BATu, *BATl;
@@ -244,7 +254,7 @@ static inline int pte_is_valid_hash32(target_ulong pte0)
     return pte0 & 0x80000000 ? 1 : 0;
 }
 
-static int pte_check_hash32(mmu_ctx_t *ctx, target_ulong pte0,
+static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0,
                             target_ulong pte1, int h, int rw, int type)
 {
     target_ulong ptem, mmask;
@@ -286,7 +296,7 @@ static int pte_check_hash32(mmu_ctx_t *ctx, target_ulong pte0,
     return ret;
 }
 
-static int ppc_hash32_pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
+static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx, target_ulong *pte1p,
                                        int ret, int rw)
 {
     int store = 0;
@@ -317,7 +327,7 @@ hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash)
 }
 
 /* PTE table lookup */
-static int find_pte32(CPUPPCState *env, mmu_ctx_t *ctx, int h,
+static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h,
                       int rw, int type, int target_page_bits)
 {
     hwaddr pteg_off;
@@ -390,7 +400,7 @@ static int find_pte32(CPUPPCState *env, mmu_ctx_t *ctx, int h,
     return ret;
 }
 
-static int get_segment32(CPUPPCState *env, mmu_ctx_t *ctx,
+static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
                          target_ulong eaddr, int rw, int type)
 {
     hwaddr hash;
@@ -535,7 +545,7 @@ static int get_segment32(CPUPPCState *env, mmu_ctx_t *ctx,
     return ret;
 }
 
-static int ppc_hash32_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
+static int ppc_hash32_get_physical_address(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
                                            target_ulong eaddr, int rw,
                                            int access_type)
 {
@@ -563,7 +573,7 @@ static int ppc_hash32_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
 
 hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
 {
-    mmu_ctx_t ctx;
+    struct mmu_ctx_hash32 ctx;
 
     if (unlikely(ppc_hash32_get_physical_address(env, &ctx, addr, 0, ACCESS_INT)
                  != 0)) {
@@ -576,7 +586,7 @@ hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
 int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                                 int mmu_idx)
 {
-    mmu_ctx_t ctx;
+    struct mmu_ctx_hash32 ctx;
     int access_type;
     int ret = 0;
 
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 7134616..3008be8 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -40,6 +40,16 @@
 #  define LOG_SLB(...) do { } while (0)
 #endif
 
+struct mmu_ctx_hash64 {
+    hwaddr raddr;      /* Real address              */
+    hwaddr eaddr;      /* Effective address         */
+    int prot;                      /* Protection bits           */
+    hwaddr hash[2];    /* Pagetable hash values     */
+    target_ulong ptem;             /* Virtual segment ID | API  */
+    int key;                       /* Access key                */
+    int nx;                        /* Non-execute area          */
+};
+
 /*
  * SLB handling
  */
@@ -299,7 +309,7 @@ static inline int pte64_is_valid(target_ulong pte0)
     return pte0 & 0x0000000000000001ULL ? 1 : 0;
 }
 
-static int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
+static int pte64_check(struct mmu_ctx_hash64 *ctx, target_ulong pte0,
                        target_ulong pte1, int h, int rw, int type)
 {
     target_ulong ptem, mmask;
@@ -343,7 +353,8 @@ static int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
     return ret;
 }
 
-static int ppc_hash64_pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
+static int ppc_hash64_pte_update_flags(struct mmu_ctx_hash64 *ctx,
+                                       target_ulong *pte1p,
                                        int ret, int rw)
 {
     int store = 0;
@@ -369,7 +380,7 @@ static int ppc_hash64_pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
 }
 
 /* PTE table lookup */
-static int find_pte64(CPUPPCState *env, mmu_ctx_t *ctx, int h,
+static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx, int h,
                       int rw, int type, int target_page_bits)
 {
     hwaddr pteg_off;
@@ -443,7 +454,7 @@ static int find_pte64(CPUPPCState *env, mmu_ctx_t *ctx, int h,
     return ret;
 }
 
-static int get_segment64(CPUPPCState *env, mmu_ctx_t *ctx,
+static int get_segment64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,
                          target_ulong eaddr, int rw, int type)
 {
     hwaddr hash;
@@ -529,7 +540,8 @@ static int get_segment64(CPUPPCState *env, mmu_ctx_t *ctx,
     return ret;
 }
 
-static int ppc_hash64_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
+static int ppc_hash64_get_physical_address(CPUPPCState *env,
+                                           struct mmu_ctx_hash64 *ctx,
                                            target_ulong eaddr, int rw,
                                            int access_type)
 {
@@ -547,7 +559,7 @@ static int ppc_hash64_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
 
 hwaddr ppc_hash64_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
 {
-    mmu_ctx_t ctx;
+    struct mmu_ctx_hash64 ctx;
 
     if (unlikely(ppc_hash64_get_physical_address(env, &ctx, addr, 0, ACCESS_INT)
                  != 0)) {
@@ -560,7 +572,7 @@ hwaddr ppc_hash64_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
 int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                                 int mmu_idx)
 {
-    mmu_ctx_t ctx;
+    struct mmu_ctx_hash64 ctx;
     int access_type;
     int ret = 0;
 
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 9471d59..c780ce1 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -77,6 +77,19 @@ int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
 }
 
 #else
+
+/* Context used internally during MMU translations */
+typedef struct mmu_ctx_t mmu_ctx_t;
+struct mmu_ctx_t {
+    hwaddr raddr;      /* Real address              */
+    hwaddr eaddr;      /* Effective address         */
+    int prot;                      /* Protection bits           */
+    hwaddr hash[2];    /* Pagetable hash values     */
+    target_ulong ptem;             /* Virtual segment ID | API  */
+    int key;                       /* Access key                */
+    int nx;                        /* Non-execute area          */
+};
+
 /* Common routines used by software and hardware TLBs emulation */
 static inline int pte_is_valid(target_ulong pte0)
 {
commit 9813279664162fa50d6124fe8c5ac4871fa59c13
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:16 2013 +0000

    target-ppc: Disentangle BAT code for 32-bit hash MMUs
    
    The functions for looking up BATs (Block Address Translation - essentially
    a level 0 TLB) are shared between the classic 32-bit hash MMUs and the
    6xx style software loaded TLB implementations.
    
    This patch splits out a copy for the 32-bit hash MMUs, to facilitate
    cleaning it up.  The remaining version is left, but cleaned up slightly
    to no longer deal with PowerPC 601 peculiarities (601 has a hash MMU).
    
    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/cpu.h b/target-ppc/cpu.h
index 86e8978..a3e1362 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1133,8 +1133,6 @@ void ppc_hw_interrupt (CPUPPCState *env);
 
 #if !defined(CONFIG_USER_ONLY)
 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
-int get_bat(CPUPPCState *env, mmu_ctx_t *ctx,
-            target_ulong virtual, int rw, int type);
 #endif /* !defined(CONFIG_USER_ONLY) */
 void ppc_store_msr (CPUPPCState *env, target_ulong value);
 
diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 0ccaf7c..f94b65d 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -25,6 +25,7 @@
 #include "mmu-hash32.h"
 
 //#define DEBUG_MMU
+//#define DEBUG_BAT
 
 #ifdef DEBUG_MMU
 #  define LOG_MMU(...) qemu_log(__VA_ARGS__)
@@ -34,6 +35,12 @@
 #  define LOG_MMU_STATE(...) do { } while (0)
 #endif
 
+#ifdef DEBUG_BATS
+#  define LOG_BATS(...) qemu_log(__VA_ARGS__)
+#else
+#  define LOG_BATS(...) do { } while (0)
+#endif
+
 #define PTE_PTEM_MASK 0x7FFFFFBF
 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
 
@@ -102,6 +109,136 @@ static int ppc_hash32_check_prot(int prot, int rw, int access_type)
     return ret;
 }
 
+/* Perform BAT hit & translation */
+static void hash32_bat_size_prot(CPUPPCState *env, target_ulong *blp,
+                                 int *validp, int *protp, target_ulong *BATu,
+                                 target_ulong *BATl)
+{
+    target_ulong bl;
+    int pp, valid, prot;
+
+    bl = (*BATu & 0x00001FFC) << 15;
+    valid = 0;
+    prot = 0;
+    if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
+        ((msr_pr != 0) && (*BATu & 0x00000001))) {
+        valid = 1;
+        pp = *BATl & 0x00000003;
+        if (pp != 0) {
+            prot = PAGE_READ | PAGE_EXEC;
+            if (pp == 0x2) {
+                prot |= PAGE_WRITE;
+            }
+        }
+    }
+    *blp = bl;
+    *validp = valid;
+    *protp = prot;
+}
+
+static void hash32_bat_601_size_prot(CPUPPCState *env, target_ulong *blp,
+                                     int *validp, int *protp,
+                                     target_ulong *BATu, target_ulong *BATl)
+{
+    target_ulong bl;
+    int key, pp, valid, prot;
+
+    bl = (*BATl & 0x0000003F) << 17;
+    LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
+             (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
+    prot = 0;
+    valid = (*BATl >> 6) & 1;
+    if (valid) {
+        pp = *BATu & 0x00000003;
+        if (msr_pr == 0) {
+            key = (*BATu >> 3) & 1;
+        } else {
+            key = (*BATu >> 2) & 1;
+        }
+        prot = ppc_hash32_pp_check(key, pp, 0);
+    }
+    *blp = bl;
+    *validp = valid;
+    *protp = prot;
+}
+
+static int ppc_hash32_get_bat(CPUPPCState *env, mmu_ctx_t *ctx,
+                              target_ulong virtual, int rw, int type)
+{
+    target_ulong *BATlt, *BATut, *BATu, *BATl;
+    target_ulong BEPIl, BEPIu, bl;
+    int i, valid, prot;
+    int ret = -1;
+
+    LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
+             type == ACCESS_CODE ? 'I' : 'D', virtual);
+    switch (type) {
+    case ACCESS_CODE:
+        BATlt = env->IBAT[1];
+        BATut = env->IBAT[0];
+        break;
+    default:
+        BATlt = env->DBAT[1];
+        BATut = env->DBAT[0];
+        break;
+    }
+    for (i = 0; i < env->nb_BATs; i++) {
+        BATu = &BATut[i];
+        BATl = &BATlt[i];
+        BEPIu = *BATu & 0xF0000000;
+        BEPIl = *BATu & 0x0FFE0000;
+        if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
+            hash32_bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
+        } else {
+            hash32_bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
+        }
+        LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
+                 " BATl " TARGET_FMT_lx "\n", __func__,
+                 type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
+        if ((virtual & 0xF0000000) == BEPIu &&
+            ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
+            /* BAT matches */
+            if (valid != 0) {
+                /* Get physical address */
+                ctx->raddr = (*BATl & 0xF0000000) |
+                    ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
+                    (virtual & 0x0001F000);
+                /* Compute access rights */
+                ctx->prot = prot;
+                ret = ppc_hash32_check_prot(ctx->prot, rw, type);
+                if (ret == 0) {
+                    LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
+                             i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
+                             ctx->prot & PAGE_WRITE ? 'W' : '-');
+                }
+                break;
+            }
+        }
+    }
+    if (ret < 0) {
+#if defined(DEBUG_BATS)
+        if (qemu_log_enabled()) {
+            LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
+            for (i = 0; i < 4; i++) {
+                BATu = &BATut[i];
+                BATl = &BATlt[i];
+                BEPIu = *BATu & 0xF0000000;
+                BEPIl = *BATu & 0x0FFE0000;
+                bl = (*BATu & 0x00001FFC) << 15;
+                LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
+                         " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
+                         TARGET_FMT_lx " " TARGET_FMT_lx "\n",
+                         __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
+                         *BATu, *BATl, BEPIu, BEPIl, bl);
+            }
+        }
+#endif
+    }
+    /* No hit */
+    return ret;
+}
+
+
 static inline int pte_is_valid_hash32(target_ulong pte0)
 {
     return pte0 & 0x80000000 ? 1 : 0;
@@ -398,7 +535,6 @@ static int get_segment32(CPUPPCState *env, mmu_ctx_t *ctx,
     return ret;
 }
 
-
 static int ppc_hash32_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
                                            target_ulong eaddr, int rw,
                                            int access_type)
@@ -415,7 +551,7 @@ static int ppc_hash32_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
 
         /* Try to find a BAT */
         if (env->nb_BATs != 0) {
-            ret = get_bat(env, ctx, eaddr, rw, access_type);
+            ret = ppc_hash32_get_bat(env, ctx, eaddr, rw, access_type);
         }
         if (ret < 0) {
             /* We didn't match any BAT entry or don't have BATs */
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 50ec0ac..9471d59 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -397,34 +397,8 @@ static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp,
     *protp = prot;
 }
 
-static inline void bat_601_size_prot(CPUPPCState *env, target_ulong *blp,
-                                     int *validp, int *protp,
-                                     target_ulong *BATu, target_ulong *BATl)
-{
-    target_ulong bl;
-    int key, pp, valid, prot;
-
-    bl = (*BATl & 0x0000003F) << 17;
-    LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
-             (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
-    prot = 0;
-    valid = (*BATl >> 6) & 1;
-    if (valid) {
-        pp = *BATu & 0x00000003;
-        if (msr_pr == 0) {
-            key = (*BATu >> 3) & 1;
-        } else {
-            key = (*BATu >> 2) & 1;
-        }
-        prot = pp_check(key, pp, 0);
-    }
-    *blp = bl;
-    *validp = valid;
-    *protp = prot;
-}
-
-int get_bat(CPUPPCState *env, mmu_ctx_t *ctx,
-            target_ulong virtual, int rw, int type)
+static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
+                           target_ulong virtual, int rw, int type)
 {
     target_ulong *BATlt, *BATut, *BATu, *BATl;
     target_ulong BEPIl, BEPIu, bl;
@@ -448,11 +422,7 @@ int get_bat(CPUPPCState *env, mmu_ctx_t *ctx,
         BATl = &BATlt[i];
         BEPIu = *BATu & 0xF0000000;
         BEPIl = *BATu & 0x0FFE0000;
-        if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
-            bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
-        } else {
-            bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
-        }
+        bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
         LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
                  " BATl " TARGET_FMT_lx "\n", __func__,
                  type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
@@ -1309,7 +1279,7 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
         } else {
             /* Try to find a BAT */
             if (env->nb_BATs != 0) {
-                ret = get_bat(env, ctx, eaddr, rw, access_type);
+                ret = get_bat_6xx_tlb(env, ctx, eaddr, rw, access_type);
             }
             if (ret < 0) {
                 /* We didn't match any BAT entry or don't have BATs */
commit 59191721a16ae393c01280dc633937374cdf474e
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:15 2013 +0000

    target-ppc: Don't share get_pteg_offset() between 32 and 64-bit
    
    The get_pteg_offset() helper function is currently shared between 32-bit
    and 64-bit hash mmus, taking a parameter for the hash pte size.  In the
    64-bit paths, it's only called in one place, and it's a trivial
    calculation.  This patch, therefore, open codes it for 64-bit.  The
    remaining version, which is used in two places is made 32-bit only and
    moved to mmu-hash32.c.
    
    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/cpu.h b/target-ppc/cpu.h
index 41cd5d6..86e8978 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1133,7 +1133,6 @@ void ppc_hw_interrupt (CPUPPCState *env);
 
 #if !defined(CONFIG_USER_ONLY)
 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
-hwaddr get_pteg_offset(CPUPPCState *env, hwaddr hash, int pte_size);
 int get_bat(CPUPPCState *env, mmu_ctx_t *ctx,
             target_ulong virtual, int rw, int type);
 #endif /* !defined(CONFIG_USER_ONLY) */
diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 4b7598b..0ccaf7c 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -174,6 +174,11 @@ static int ppc_hash32_pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
     return store;
 }
 
+hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash)
+{
+    return (hash * HASH_PTE_SIZE_32 * 8) & env->htab_mask;
+}
+
 /* PTE table lookup */
 static int find_pte32(CPUPPCState *env, mmu_ctx_t *ctx, int h,
                       int rw, int type, int target_page_bits)
@@ -184,7 +189,7 @@ static int find_pte32(CPUPPCState *env, mmu_ctx_t *ctx, int h,
     int ret, r;
 
     ret = -1; /* No entry found */
-    pteg_off = get_pteg_offset(env, ctx->hash[h], HASH_PTE_SIZE_32);
+    pteg_off = get_pteg_offset32(env, ctx->hash[h]);
     for (i = 0; i < 8; i++) {
         if (env->external_htab) {
             pte0 = ldl_p(env->external_htab + pteg_off + (i * 8));
diff --git a/target-ppc/mmu-hash32.h b/target-ppc/mmu-hash32.h
index 8f10e0d..3435aa5 100644
--- a/target-ppc/mmu-hash32.h
+++ b/target-ppc/mmu-hash32.h
@@ -3,7 +3,7 @@
 
 #ifndef CONFIG_USER_ONLY
 
-int pte32_is_valid(target_ulong pte0);
+hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash);
 hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong addr);
 int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                                 int mmu_idx);
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index f9c5b09..7134616 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -378,7 +378,7 @@ static int find_pte64(CPUPPCState *env, mmu_ctx_t *ctx, int h,
     int ret, r;
 
     ret = -1; /* No entry found */
-    pteg_off = get_pteg_offset(env, ctx->hash[h], HASH_PTE_SIZE_64);
+    pteg_off = (ctx->hash[h] * HASH_PTE_SIZE_64 * 8) & env->htab_mask;
     for (i = 0; i < 8; i++) {
         if (env->external_htab) {
             pte0 = ldq_p(env->external_htab + pteg_off + (i * 16));
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 2deb635..50ec0ac 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -499,11 +499,6 @@ int get_bat(CPUPPCState *env, mmu_ctx_t *ctx,
     return ret;
 }
 
-hwaddr get_pteg_offset(CPUPPCState *env, hwaddr hash, int pte_size)
-{
-    return (hash * pte_size * 8) & env->htab_mask;
-}
-
 /* Perform segment based translation */
 static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
                                       target_ulong eaddr, int rw, int type)
@@ -1551,9 +1546,9 @@ int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                 tlb_miss:
                     env->error_code |= ctx.key << 19;
                     env->spr[SPR_HASH1] = env->htab_base +
-                        get_pteg_offset(env, ctx.hash[0], HASH_PTE_SIZE_32);
+                        get_pteg_offset32(env, ctx.hash[0]);
                     env->spr[SPR_HASH2] = env->htab_base +
-                        get_pteg_offset(env, ctx.hash[1], HASH_PTE_SIZE_32);
+                        get_pteg_offset32(env, ctx.hash[1]);
                     break;
                 case POWERPC_MMU_SOFT_74xx:
                     if (rw == 1) {
commit 496272a7018ba01aa2b87a1a5ed866ff85133401
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:14 2013 +0000

    target-ppc: Disentangle hash mmu helper functions
    
    The newly separated paths for hash mmus rely on several helper functions
    which are still shared with 32-bit hash mmus: pp_check(), check_prot() and
    pte_update_flags().  While these don't have ugly ifdefs on the mmu type,
    they're not very well thought out, so sharing them impedes cleaning up the
    hash mmu paths.  For now, put near-duplicate versions into mmu-hash64.c and
    mmu-hash32.c, leaving the old version in mmu_helper.c for 6xx software
    loaded tlb implementations.  The hash 32 and software loaded
    implementations are simplfied slightly, using the fact that no 32-bit CPUs
    implement the 3rd page protection bit.
    
    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/cpu.h b/target-ppc/cpu.h
index 716ffe0..41cd5d6 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1133,9 +1133,6 @@ void ppc_hw_interrupt (CPUPPCState *env);
 
 #if !defined(CONFIG_USER_ONLY)
 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
-int pp_check(int key, int pp, int nx);
-int check_prot(int prot, int rw, int access_type);
-int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p, int ret, int rw);
 hwaddr get_pteg_offset(CPUPPCState *env, hwaddr hash, int pte_size);
 int get_bat(CPUPPCState *env, mmu_ctx_t *ctx,
             target_ulong virtual, int rw, int type);
diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c
index c0e5742..4b7598b 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -37,6 +37,71 @@
 #define PTE_PTEM_MASK 0x7FFFFFBF
 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
 
+static int ppc_hash32_pp_check(int key, int pp, int nx)
+{
+    int access;
+
+    /* Compute access rights */
+    access = 0;
+    if (key == 0) {
+        switch (pp) {
+        case 0x0:
+        case 0x1:
+        case 0x2:
+            access |= PAGE_WRITE;
+            /* No break here */
+        case 0x3:
+            access |= PAGE_READ;
+            break;
+        }
+    } else {
+        switch (pp) {
+        case 0x0:
+            access = 0;
+            break;
+        case 0x1:
+        case 0x3:
+            access = PAGE_READ;
+            break;
+        case 0x2:
+            access = PAGE_READ | PAGE_WRITE;
+            break;
+        }
+    }
+    if (nx == 0) {
+        access |= PAGE_EXEC;
+    }
+
+    return access;
+}
+
+static int ppc_hash32_check_prot(int prot, int rw, int access_type)
+{
+    int ret;
+
+    if (access_type == ACCESS_CODE) {
+        if (prot & PAGE_EXEC) {
+            ret = 0;
+        } else {
+            ret = -2;
+        }
+    } else if (rw) {
+        if (prot & PAGE_WRITE) {
+            ret = 0;
+        } else {
+            ret = -2;
+        }
+    } else {
+        if (prot & PAGE_READ) {
+            ret = 0;
+        } else {
+            ret = -2;
+        }
+    }
+
+    return ret;
+}
+
 static inline int pte_is_valid_hash32(target_ulong pte0)
 {
     return pte0 & 0x80000000 ? 1 : 0;
@@ -66,11 +131,11 @@ static int pte_check_hash32(mmu_ctx_t *ctx, target_ulong pte0,
                 }
             }
             /* Compute access rights */
-            access = pp_check(ctx->key, pp, ctx->nx);
+            access = ppc_hash32_pp_check(ctx->key, pp, ctx->nx);
             /* Keep the matching PTE informations */
             ctx->raddr = pte1;
             ctx->prot = access;
-            ret = check_prot(ctx->prot, rw, type);
+            ret = ppc_hash32_check_prot(ctx->prot, rw, type);
             if (ret == 0) {
                 /* Access granted */
                 LOG_MMU("PTE access granted !\n");
@@ -84,6 +149,31 @@ static int pte_check_hash32(mmu_ctx_t *ctx, target_ulong pte0,
     return ret;
 }
 
+static int ppc_hash32_pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
+                                       int ret, int rw)
+{
+    int store = 0;
+
+    /* Update page flags */
+    if (!(*pte1p & 0x00000100)) {
+        /* Update accessed flag */
+        *pte1p |= 0x00000100;
+        store = 1;
+    }
+    if (!(*pte1p & 0x00000080)) {
+        if (rw == 1 && ret == 0) {
+            /* Update changed flag */
+            *pte1p |= 0x00000080;
+            store = 1;
+        } else {
+            /* Force page fault for first write access */
+            ctx->prot &= ~PAGE_WRITE;
+        }
+    }
+
+    return store;
+}
+
 /* PTE table lookup */
 static int find_pte32(CPUPPCState *env, mmu_ctx_t *ctx, int h,
                       int rw, int type, int target_page_bits)
@@ -138,7 +228,7 @@ static int find_pte32(CPUPPCState *env, mmu_ctx_t *ctx, int h,
                 ctx->raddr, ctx->prot, ret);
         /* Update page flags */
         pte1 = ctx->raddr;
-        if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
+        if (ppc_hash32_pte_update_flags(ctx, &pte1, ret, rw) == 1) {
             if (env->external_htab) {
                 stl_p(env->external_htab + pteg_off + (good * 8) + 4,
                       pte1);
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 427b095..f9c5b09 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -226,6 +226,74 @@ target_ulong helper_load_slb_vsid(CPUPPCState *env, target_ulong rb)
 #define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
 #define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
 
+static int ppc_hash64_pp_check(int key, int pp, int nx)
+{
+    int access;
+
+    /* Compute access rights */
+    /* When pp is 4, 5 or 7, the result is undefined. Set it to noaccess */
+    access = 0;
+    if (key == 0) {
+        switch (pp) {
+        case 0x0:
+        case 0x1:
+        case 0x2:
+            access |= PAGE_WRITE;
+            /* No break here */
+        case 0x3:
+        case 0x6:
+            access |= PAGE_READ;
+            break;
+        }
+    } else {
+        switch (pp) {
+        case 0x0:
+        case 0x6:
+            access = 0;
+            break;
+        case 0x1:
+        case 0x3:
+            access = PAGE_READ;
+            break;
+        case 0x2:
+            access = PAGE_READ | PAGE_WRITE;
+            break;
+        }
+    }
+    if (nx == 0) {
+        access |= PAGE_EXEC;
+    }
+
+    return access;
+}
+
+static int ppc_hash64_check_prot(int prot, int rw, int access_type)
+{
+    int ret;
+
+    if (access_type == ACCESS_CODE) {
+        if (prot & PAGE_EXEC) {
+            ret = 0;
+        } else {
+            ret = -2;
+        }
+    } else if (rw) {
+        if (prot & PAGE_WRITE) {
+            ret = 0;
+        } else {
+            ret = -2;
+        }
+    } else {
+        if (prot & PAGE_READ) {
+            ret = 0;
+        } else {
+            ret = -2;
+        }
+    }
+
+    return ret;
+}
+
 static inline int pte64_is_valid(target_ulong pte0)
 {
     return pte0 & 0x0000000000000001ULL ? 1 : 0;
@@ -257,11 +325,11 @@ static int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
                 }
             }
             /* Compute access rights */
-            access = pp_check(ctx->key, pp, ctx->nx);
+            access = ppc_hash64_pp_check(ctx->key, pp, ctx->nx);
             /* Keep the matching PTE informations */
             ctx->raddr = pte1;
             ctx->prot = access;
-            ret = check_prot(ctx->prot, rw, type);
+            ret = ppc_hash64_check_prot(ctx->prot, rw, type);
             if (ret == 0) {
                 /* Access granted */
                 LOG_MMU("PTE access granted !\n");
@@ -275,6 +343,31 @@ static int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
     return ret;
 }
 
+static int ppc_hash64_pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
+                                       int ret, int rw)
+{
+    int store = 0;
+
+    /* Update page flags */
+    if (!(*pte1p & 0x00000100)) {
+        /* Update accessed flag */
+        *pte1p |= 0x00000100;
+        store = 1;
+    }
+    if (!(*pte1p & 0x00000080)) {
+        if (rw == 1 && ret == 0) {
+            /* Update changed flag */
+            *pte1p |= 0x00000080;
+            store = 1;
+        } else {
+            /* Force page fault for first write access */
+            ctx->prot &= ~PAGE_WRITE;
+        }
+    }
+
+    return store;
+}
+
 /* PTE table lookup */
 static int find_pte64(CPUPPCState *env, mmu_ctx_t *ctx, int h,
                       int rw, int type, int target_page_bits)
@@ -330,7 +423,7 @@ static int find_pte64(CPUPPCState *env, mmu_ctx_t *ctx, int h,
                 ctx->raddr, ctx->prot, ret);
         /* Update page flags */
         pte1 = ctx->raddr;
-        if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
+        if (ppc_hash64_pte_update_flags(ctx, &pte1, ret, rw) == 1) {
             if (env->external_htab) {
                 stq_p(env->external_htab + pteg_off + (good * 16) + 8,
                       pte1);
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 818f1b5..2deb635 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -91,12 +91,11 @@ static inline void pte_invalidate(target_ulong *pte0)
 #define PTE_PTEM_MASK 0x7FFFFFBF
 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
 
-int pp_check(int key, int pp, int nx)
+static int pp_check(int key, int pp, int nx)
 {
     int access;
 
     /* Compute access rights */
-    /* When pp is 3/7, the result is undefined. Set it to noaccess */
     access = 0;
     if (key == 0) {
         switch (pp) {
@@ -106,14 +105,12 @@ int pp_check(int key, int pp, int nx)
             access |= PAGE_WRITE;
             /* No break here */
         case 0x3:
-        case 0x6:
             access |= PAGE_READ;
             break;
         }
     } else {
         switch (pp) {
         case 0x0:
-        case 0x6:
             access = 0;
             break;
         case 0x1:
@@ -132,7 +129,7 @@ int pp_check(int key, int pp, int nx)
     return access;
 }
 
-int check_prot(int prot, int rw, int access_type)
+static int check_prot(int prot, int rw, int access_type)
 {
     int ret;
 
@@ -201,8 +198,8 @@ static inline int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
     return ret;
 }
 
-int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
-                     int ret, int rw)
+static int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
+                            int ret, int rw)
 {
     int store = 0;
 
commit f2ad6be83bc284d6c7677bdca879db38d4fdccd5
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:13 2013 +0000

    target-ppc: Disentangle hash mmu versions of cpu_get_phys_page_debug()
    
    cpu_get_phys_page_debug() is a trivial wrapper around
    get_physical_address().  But even the signature of
    get_physical_address() has some things we'd like to clean up on a
    per-mmu basis, so this patch moves the test on mmu model out to
    cpu_get_phys_page_debug(), moving the version for 64-bit hash MMUs out
    to mmu-hash64.c and the version for 32-bit hash MMUs to mmu-hash32.c
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 50f8c54..c0e5742 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -304,8 +304,9 @@ static int get_segment32(CPUPPCState *env, mmu_ctx_t *ctx,
 }
 
 
-int ppc_hash32_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
-                                    target_ulong eaddr, int rw, int access_type)
+static int ppc_hash32_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
+                                           target_ulong eaddr, int rw,
+                                           int access_type)
 {
     bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0)
         || (access_type != ACCESS_CODE && msr_dr == 0);
@@ -329,6 +330,18 @@ int ppc_hash32_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
     }
 }
 
+hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
+{
+    mmu_ctx_t ctx;
+
+    if (unlikely(ppc_hash32_get_physical_address(env, &ctx, addr, 0, ACCESS_INT)
+                 != 0)) {
+        return -1;
+    }
+
+    return ctx.raddr & TARGET_PAGE_MASK;
+}
+
 int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                                 int mmu_idx)
 {
diff --git a/target-ppc/mmu-hash32.h b/target-ppc/mmu-hash32.h
index 8f1f2a9..8f10e0d 100644
--- a/target-ppc/mmu-hash32.h
+++ b/target-ppc/mmu-hash32.h
@@ -4,8 +4,7 @@
 #ifndef CONFIG_USER_ONLY
 
 int pte32_is_valid(target_ulong pte0);
-int ppc_hash32_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
-                                    target_ulong eaddr, int rw, int access_type);
+hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong addr);
 int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                                 int mmu_idx);
 
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 32825ff..427b095 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -436,8 +436,9 @@ static int get_segment64(CPUPPCState *env, mmu_ctx_t *ctx,
     return ret;
 }
 
-int ppc_hash64_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
-                                    target_ulong eaddr, int rw, int access_type)
+static int ppc_hash64_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
+                                           target_ulong eaddr, int rw,
+                                           int access_type)
 {
     bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0)
         || (access_type != ACCESS_CODE && msr_dr == 0);
@@ -451,6 +452,18 @@ int ppc_hash64_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
     }
 }
 
+hwaddr ppc_hash64_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
+{
+    mmu_ctx_t ctx;
+
+    if (unlikely(ppc_hash64_get_physical_address(env, &ctx, addr, 0, ACCESS_INT)
+                 != 0)) {
+        return -1;
+    }
+
+    return ctx.raddr & TARGET_PAGE_MASK;
+}
+
 int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                                 int mmu_idx)
 {
diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h
index 3a53e61..665d3b0 100644
--- a/target-ppc/mmu-hash64.h
+++ b/target-ppc/mmu-hash64.h
@@ -6,8 +6,7 @@
 #ifdef TARGET_PPC64
 void dump_slb(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env);
 int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
-int ppc_hash64_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
-                                    target_ulong eaddr, int rw, int access_type);
+hwaddr ppc_hash64_get_phys_page_debug(CPUPPCState *env, target_ulong addr);
 int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                                 int mmu_idx);
 #endif
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 287334f..818f1b5 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -1310,11 +1310,6 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
 #endif
 
     switch (env->mmu_model) {
-    case POWERPC_MMU_32B:
-    case POWERPC_MMU_601:
-        ret = ppc_hash32_get_physical_address(env, ctx, eaddr, rw, access_type);
-        break;
-
     case POWERPC_MMU_SOFT_6xx:
     case POWERPC_MMU_SOFT_74xx:
         if (real_mode) {
@@ -1331,14 +1326,6 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
         }
         break;
 
-#if defined(TARGET_PPC64)
-    case POWERPC_MMU_64B:
-    case POWERPC_MMU_2_06:
-    case POWERPC_MMU_2_06d:
-        ret = ppc_hash64_get_physical_address(env, ctx, eaddr, rw, access_type);
-        break;
-#endif
-
     case POWERPC_MMU_SOFT_4xx:
     case POWERPC_MMU_SOFT_4xx_Z:
         if (real_mode) {
@@ -1383,6 +1370,22 @@ hwaddr cpu_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
 {
     mmu_ctx_t ctx;
 
+    switch (env->mmu_model) {
+#if defined(TARGET_PPC64)
+    case POWERPC_MMU_64B:
+    case POWERPC_MMU_2_06:
+    case POWERPC_MMU_2_06d:
+        return ppc_hash64_get_phys_page_debug(env, addr);
+#endif
+
+    case POWERPC_MMU_32B:
+    case POWERPC_MMU_601:
+        return ppc_hash32_get_phys_page_debug(env, addr);
+
+    default:
+        ;
+    }
+
     if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0)) {
         return -1;
     }
commit 25de24ab838be5801d5cc13b8a347922a3770fa5
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:12 2013 +0000

    target-ppc: Disentangle hash mmu paths for cpu_ppc_handle_mmu_fault
    
    cpu_ppc_handle_mmu_fault() calls get_physical_address() (whose behaviour
    depends on MMU type) then, if that fails, issues an appropriate exception
    - which again has a number of dependencies on MMU type.
    
    This patch starts converting cpu_ppc_handle_mmu_fault() to have a
    single switch on MMU type, calling MMU specific fault handler
    functions which deal with both translation and exception delivery
    appropriately for the MMU type.  We convert 32-bit and 64-bit hash
    MMUs to this new model, but the existing code is left in place for
    other MMU types for now.
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 3998d63..50f8c54 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -303,6 +303,7 @@ static int get_segment32(CPUPPCState *env, mmu_ctx_t *ctx,
     return ret;
 }
 
+
 int ppc_hash32_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
                                     target_ulong eaddr, int rw, int access_type)
 {
@@ -327,3 +328,126 @@ int ppc_hash32_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
         return ret;
     }
 }
+
+int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
+                                int mmu_idx)
+{
+    mmu_ctx_t ctx;
+    int access_type;
+    int ret = 0;
+
+    if (rw == 2) {
+        /* code access */
+        rw = 0;
+        access_type = ACCESS_CODE;
+    } else {
+        /* data access */
+        access_type = env->access_type;
+    }
+    ret = ppc_hash32_get_physical_address(env, &ctx, address, rw, access_type);
+    if (ret == 0) {
+        tlb_set_page(env, address & TARGET_PAGE_MASK,
+                     ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
+                     mmu_idx, TARGET_PAGE_SIZE);
+        ret = 0;
+    } else if (ret < 0) {
+        LOG_MMU_STATE(env);
+        if (access_type == ACCESS_CODE) {
+            switch (ret) {
+            case -1:
+                /* No matches in page tables or TLB */
+                env->exception_index = POWERPC_EXCP_ISI;
+                env->error_code = 0x40000000;
+                break;
+            case -2:
+                /* Access rights violation */
+                env->exception_index = POWERPC_EXCP_ISI;
+                env->error_code = 0x08000000;
+                break;
+            case -3:
+                /* No execute protection violation */
+                env->exception_index = POWERPC_EXCP_ISI;
+                env->error_code = 0x10000000;
+                break;
+            case -4:
+                /* Direct store exception */
+                /* No code fetch is allowed in direct-store areas */
+                env->exception_index = POWERPC_EXCP_ISI;
+                env->error_code = 0x10000000;
+                break;
+            }
+        } else {
+            switch (ret) {
+            case -1:
+                /* No matches in page tables or TLB */
+                env->exception_index = POWERPC_EXCP_DSI;
+                env->error_code = 0;
+                env->spr[SPR_DAR] = address;
+                if (rw == 1) {
+                    env->spr[SPR_DSISR] = 0x42000000;
+                } else {
+                    env->spr[SPR_DSISR] = 0x40000000;
+                }
+                break;
+            case -2:
+                /* Access rights violation */
+                env->exception_index = POWERPC_EXCP_DSI;
+                env->error_code = 0;
+                env->spr[SPR_DAR] = address;
+                if (rw == 1) {
+                    env->spr[SPR_DSISR] = 0x0A000000;
+                } else {
+                    env->spr[SPR_DSISR] = 0x08000000;
+                }
+                break;
+            case -4:
+                /* Direct store exception */
+                switch (access_type) {
+                case ACCESS_FLOAT:
+                    /* Floating point load/store */
+                    env->exception_index = POWERPC_EXCP_ALIGN;
+                    env->error_code = POWERPC_EXCP_ALIGN_FP;
+                    env->spr[SPR_DAR] = address;
+                    break;
+                case ACCESS_RES:
+                    /* lwarx, ldarx or stwcx. */
+                    env->exception_index = POWERPC_EXCP_DSI;
+                    env->error_code = 0;
+                    env->spr[SPR_DAR] = address;
+                    if (rw == 1) {
+                        env->spr[SPR_DSISR] = 0x06000000;
+                    } else {
+                        env->spr[SPR_DSISR] = 0x04000000;
+                    }
+                    break;
+                case ACCESS_EXT:
+                    /* eciwx or ecowx */
+                    env->exception_index = POWERPC_EXCP_DSI;
+                    env->error_code = 0;
+                    env->spr[SPR_DAR] = address;
+                    if (rw == 1) {
+                        env->spr[SPR_DSISR] = 0x06100000;
+                    } else {
+                        env->spr[SPR_DSISR] = 0x04100000;
+                    }
+                    break;
+                default:
+                    printf("DSI: invalid exception (%d)\n", ret);
+                    env->exception_index = POWERPC_EXCP_PROGRAM;
+                    env->error_code =
+                        POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
+                    env->spr[SPR_DAR] = address;
+                    break;
+                }
+                break;
+            }
+        }
+#if 0
+        printf("%s: set exception to %d %02x\n", __func__,
+               env->exception, env->error_code);
+#endif
+        ret = 1;
+    }
+
+    return ret;
+}
diff --git a/target-ppc/mmu-hash32.h b/target-ppc/mmu-hash32.h
index 1318562..8f1f2a9 100644
--- a/target-ppc/mmu-hash32.h
+++ b/target-ppc/mmu-hash32.h
@@ -6,6 +6,8 @@
 int pte32_is_valid(target_ulong pte0);
 int ppc_hash32_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
                                     target_ulong eaddr, int rw, int access_type);
+int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
+                                int mmu_idx);
 
 #endif /* CONFIG_USER_ONLY */
 
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index c727298..32825ff 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -450,3 +450,90 @@ int ppc_hash64_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
         return get_segment64(env, ctx, eaddr, rw, access_type);
     }
 }
+
+int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
+                                int mmu_idx)
+{
+    mmu_ctx_t ctx;
+    int access_type;
+    int ret = 0;
+
+    if (rw == 2) {
+        /* code access */
+        rw = 0;
+        access_type = ACCESS_CODE;
+    } else {
+        /* data access */
+        access_type = env->access_type;
+    }
+    ret = ppc_hash64_get_physical_address(env, &ctx, address, rw, access_type);
+    if (ret == 0) {
+        tlb_set_page(env, address & TARGET_PAGE_MASK,
+                     ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
+                     mmu_idx, TARGET_PAGE_SIZE);
+        ret = 0;
+    } else if (ret < 0) {
+        LOG_MMU_STATE(env);
+        if (access_type == ACCESS_CODE) {
+            switch (ret) {
+            case -1:
+                env->exception_index = POWERPC_EXCP_ISI;
+                env->error_code = 0x40000000;
+                break;
+            case -2:
+                /* Access rights violation */
+                env->exception_index = POWERPC_EXCP_ISI;
+                env->error_code = 0x08000000;
+                break;
+            case -3:
+                /* No execute protection violation */
+                env->exception_index = POWERPC_EXCP_ISI;
+                env->error_code = 0x10000000;
+                break;
+            case -5:
+                /* No match in segment table */
+                env->exception_index = POWERPC_EXCP_ISEG;
+                env->error_code = 0;
+                break;
+            }
+        } else {
+            switch (ret) {
+            case -1:
+                /* No matches in page tables or TLB */
+                env->exception_index = POWERPC_EXCP_DSI;
+                env->error_code = 0;
+                env->spr[SPR_DAR] = address;
+                if (rw == 1) {
+                    env->spr[SPR_DSISR] = 0x42000000;
+                } else {
+                    env->spr[SPR_DSISR] = 0x40000000;
+                }
+                break;
+            case -2:
+                /* Access rights violation */
+                env->exception_index = POWERPC_EXCP_DSI;
+                env->error_code = 0;
+                env->spr[SPR_DAR] = address;
+                if (rw == 1) {
+                    env->spr[SPR_DSISR] = 0x0A000000;
+                } else {
+                    env->spr[SPR_DSISR] = 0x08000000;
+                }
+                break;
+            case -5:
+                /* No match in segment table */
+                env->exception_index = POWERPC_EXCP_DSEG;
+                env->error_code = 0;
+                env->spr[SPR_DAR] = address;
+                break;
+            }
+        }
+#if 0
+        printf("%s: set exception to %d %02x\n", __func__,
+               env->exception, env->error_code);
+#endif
+        ret = 1;
+    }
+
+    return ret;
+}
diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h
index d8eb8de..3a53e61 100644
--- a/target-ppc/mmu-hash64.h
+++ b/target-ppc/mmu-hash64.h
@@ -8,6 +8,8 @@ void dump_slb(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env);
 int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
 int ppc_hash64_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
                                     target_ulong eaddr, int rw, int access_type);
+int ppc_hash64_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
+                                int mmu_idx);
 #endif
 
 #endif /* CONFIG_USER_ONLY */
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index ce39f49..287334f 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -1438,6 +1438,22 @@ int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
     int access_type;
     int ret = 0;
 
+    switch (env->mmu_model) {
+#if defined(TARGET_PPC64)
+    case POWERPC_MMU_64B:
+    case POWERPC_MMU_2_06:
+    case POWERPC_MMU_2_06d:
+        return ppc_hash64_handle_mmu_fault(env, address, rw, mmu_idx);
+#endif
+
+    case POWERPC_MMU_32B:
+    case POWERPC_MMU_601:
+        return ppc_hash32_handle_mmu_fault(env, address, rw, mmu_idx);
+
+    default:
+        ; /* Otherwise fall through to the general code below */
+    }
+
     if (rw == 2) {
         /* code access */
         rw = 0;
@@ -1475,16 +1491,6 @@ int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                     env->spr[SPR_40x_DEAR] = address;
                     env->spr[SPR_40x_ESR] = 0x00000000;
                     break;
-                case POWERPC_MMU_32B:
-                case POWERPC_MMU_601:
-#if defined(TARGET_PPC64)
-                case POWERPC_MMU_64B:
-                case POWERPC_MMU_2_06:
-                case POWERPC_MMU_2_06d:
-#endif
-                    env->exception_index = POWERPC_EXCP_ISI;
-                    env->error_code = 0x40000000;
-                    break;
                 case POWERPC_MMU_BOOKE206:
                     booke206_update_mas_tlb_miss(env, address, rw);
                     /* fall through */
@@ -1526,13 +1532,6 @@ int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                 env->exception_index = POWERPC_EXCP_ISI;
                 env->error_code = 0x10000000;
                 break;
-#if defined(TARGET_PPC64)
-            case -5:
-                /* No match in segment table */
-                env->exception_index = POWERPC_EXCP_ISEG;
-                env->error_code = 0;
-                break;
-#endif
             }
         } else {
             switch (ret) {
@@ -1580,22 +1579,6 @@ int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                         env->spr[SPR_40x_ESR] = 0x00000000;
                     }
                     break;
-                case POWERPC_MMU_32B:
-                case POWERPC_MMU_601:
-#if defined(TARGET_PPC64)
-                case POWERPC_MMU_64B:
-                case POWERPC_MMU_2_06:
-                case POWERPC_MMU_2_06d:
-#endif
-                    env->exception_index = POWERPC_EXCP_DSI;
-                    env->error_code = 0;
-                    env->spr[SPR_DAR] = address;
-                    if (rw == 1) {
-                        env->spr[SPR_DSISR] = 0x42000000;
-                    } else {
-                        env->spr[SPR_DSISR] = 0x40000000;
-                    }
-                    break;
                 case POWERPC_MMU_MPC8xx:
                     /* XXX: TODO */
                     cpu_abort(env, "MPC8xx MMU model is not implemented\n");
@@ -1681,14 +1664,6 @@ int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                     break;
                 }
                 break;
-#if defined(TARGET_PPC64)
-            case -5:
-                /* No match in segment table */
-                env->exception_index = POWERPC_EXCP_DSEG;
-                env->error_code = 0;
-                env->spr[SPR_DAR] = address;
-                break;
-#endif
             }
         }
 #if 0
commit 629bd516fda67c95ba1c7d1393bacb9e68ea0712
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:11 2013 +0000

    target-ppc: Disentangle get_physical_address() paths
    
    Depending on the MSR state, for 64-bit hash MMUs, get_physical_address
    can either call check_physical (which has further tests for mmu type)
    or get_segment64.  Similarly for 32-bit hash MMUs we can either call
    check_physucal or get_bat() and get_segment32().
    
    This patch splits off the whole get_physical_addresss() path for hash
    MMUs into 32-bit and 64-bit versions, handling real mode correctly for
    such MMUs without going to check_physical and rechecking the mmu type.
    Correspondingly, the hash MMU specific paths in check_physical() are
    removed.
    
    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/cpu.h b/target-ppc/cpu.h
index cf8ba2e..716ffe0 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1137,6 +1137,8 @@ int pp_check(int key, int pp, int nx);
 int check_prot(int prot, int rw, int access_type);
 int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p, int ret, int rw);
 hwaddr get_pteg_offset(CPUPPCState *env, hwaddr hash, int pte_size);
+int get_bat(CPUPPCState *env, mmu_ctx_t *ctx,
+            target_ulong virtual, int rw, int type);
 #endif /* !defined(CONFIG_USER_ONLY) */
 void ppc_store_msr (CPUPPCState *env, target_ulong value);
 
diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c
index 4bae72a..3998d63 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -158,8 +158,8 @@ static int find_pte32(CPUPPCState *env, mmu_ctx_t *ctx, int h,
     return ret;
 }
 
-int get_segment32(CPUPPCState *env, mmu_ctx_t *ctx,
-                  target_ulong eaddr, int rw, int type)
+static int get_segment32(CPUPPCState *env, mmu_ctx_t *ctx,
+                         target_ulong eaddr, int rw, int type)
 {
     hwaddr hash;
     target_ulong vsid;
@@ -302,3 +302,28 @@ int get_segment32(CPUPPCState *env, mmu_ctx_t *ctx,
 
     return ret;
 }
+
+int ppc_hash32_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
+                                    target_ulong eaddr, int rw, int access_type)
+{
+    bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0)
+        || (access_type != ACCESS_CODE && msr_dr == 0);
+
+    if (real_mode) {
+        ctx->raddr = eaddr;
+        ctx->prot = PAGE_READ | PAGE_EXEC | PAGE_WRITE;
+        return 0;
+    } else {
+        int ret = -1;
+
+        /* Try to find a BAT */
+        if (env->nb_BATs != 0) {
+            ret = get_bat(env, ctx, eaddr, rw, access_type);
+        }
+        if (ret < 0) {
+            /* We didn't match any BAT entry or don't have BATs */
+            ret = get_segment32(env, ctx, eaddr, rw, access_type);
+        }
+        return ret;
+    }
+}
diff --git a/target-ppc/mmu-hash32.h b/target-ppc/mmu-hash32.h
index 6f9a0c2..1318562 100644
--- a/target-ppc/mmu-hash32.h
+++ b/target-ppc/mmu-hash32.h
@@ -4,8 +4,8 @@
 #ifndef CONFIG_USER_ONLY
 
 int pte32_is_valid(target_ulong pte0);
-int get_segment32(CPUPPCState *env, mmu_ctx_t *ctx,
-                  target_ulong eaddr, int rw, int type);
+int ppc_hash32_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
+                                    target_ulong eaddr, int rw, int access_type);
 
 #endif /* CONFIG_USER_ONLY */
 
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 23eb480..c727298 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -350,8 +350,8 @@ static int find_pte64(CPUPPCState *env, mmu_ctx_t *ctx, int h,
     return ret;
 }
 
-int get_segment64(CPUPPCState *env, mmu_ctx_t *ctx,
-                  target_ulong eaddr, int rw, int type)
+static int get_segment64(CPUPPCState *env, mmu_ctx_t *ctx,
+                         target_ulong eaddr, int rw, int type)
 {
     hwaddr hash;
     target_ulong vsid;
@@ -435,3 +435,18 @@ int get_segment64(CPUPPCState *env, mmu_ctx_t *ctx,
 
     return ret;
 }
+
+int ppc_hash64_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
+                                    target_ulong eaddr, int rw, int access_type)
+{
+    bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0)
+        || (access_type != ACCESS_CODE && msr_dr == 0);
+
+    if (real_mode) {
+        ctx->raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL;
+        ctx->prot = PAGE_READ | PAGE_EXEC | PAGE_WRITE;
+        return 0;
+    } else {
+        return get_segment64(env, ctx, eaddr, rw, access_type);
+    }
+}
diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h
index 690c1d8..d8eb8de 100644
--- a/target-ppc/mmu-hash64.h
+++ b/target-ppc/mmu-hash64.h
@@ -6,8 +6,8 @@
 #ifdef TARGET_PPC64
 void dump_slb(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env);
 int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
-int get_segment64(CPUPPCState *env, mmu_ctx_t *ctx,
-                  target_ulong eaddr, int rw, int type);
+int ppc_hash64_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
+                                    target_ulong eaddr, int rw, int access_type);
 #endif
 
 #endif /* CONFIG_USER_ONLY */
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 5b82731..ce39f49 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -426,8 +426,8 @@ static inline void bat_601_size_prot(CPUPPCState *env, target_ulong *blp,
     *protp = prot;
 }
 
-static inline int get_bat(CPUPPCState *env, mmu_ctx_t *ctx,
-                          target_ulong virtual, int rw, int type)
+int get_bat(CPUPPCState *env, mmu_ctx_t *ctx,
+            target_ulong virtual, int rw, int type)
 {
     target_ulong *BATlt, *BATut, *BATu, *BATl;
     target_ulong BEPIl, BEPIu, bl;
@@ -1256,8 +1256,6 @@ static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx,
     ctx->prot = PAGE_READ | PAGE_EXEC;
     ret = 0;
     switch (env->mmu_model) {
-    case POWERPC_MMU_32B:
-    case POWERPC_MMU_601:
     case POWERPC_MMU_SOFT_6xx:
     case POWERPC_MMU_SOFT_74xx:
     case POWERPC_MMU_SOFT_4xx:
@@ -1265,15 +1263,7 @@ static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx,
     case POWERPC_MMU_BOOKE:
         ctx->prot |= PAGE_WRITE;
         break;
-#if defined(TARGET_PPC64)
-    case POWERPC_MMU_64B:
-    case POWERPC_MMU_2_06:
-    case POWERPC_MMU_2_06d:
-        /* Real address are 60 bits long */
-        ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
-        ctx->prot |= PAGE_WRITE;
-        break;
-#endif
+
     case POWERPC_MMU_SOFT_4xx_Z:
         if (unlikely(msr_pe != 0)) {
             /* 403 family add some particular protections,
@@ -1298,15 +1288,10 @@ static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx,
             }
         }
         break;
-    case POWERPC_MMU_MPC8xx:
-        /* XXX: TODO */
-        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
-        break;
-    case POWERPC_MMU_BOOKE206:
-        cpu_abort(env, "BookE 2.06 MMU doesn't have physical real mode\n");
-        break;
+
     default:
-        cpu_abort(env, "Unknown or invalid MMU model\n");
+        /* Caller's checks mean we should never get here for other models */
+        abort();
         return -1;
     }
 
@@ -1327,18 +1312,7 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
     switch (env->mmu_model) {
     case POWERPC_MMU_32B:
     case POWERPC_MMU_601:
-        if (real_mode) {
-            ret = check_physical(env, ctx, eaddr, rw);
-        } else {
-            /* Try to find a BAT */
-            if (env->nb_BATs != 0) {
-                ret = get_bat(env, ctx, eaddr, rw, access_type);
-            }
-            if (ret < 0) {
-                /* We didn't match any BAT entry or don't have BATs */
-                ret = get_segment32(env, ctx, eaddr, rw, access_type);
-            }
-        }
+        ret = ppc_hash32_get_physical_address(env, ctx, eaddr, rw, access_type);
         break;
 
     case POWERPC_MMU_SOFT_6xx:
@@ -1361,11 +1335,7 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
     case POWERPC_MMU_64B:
     case POWERPC_MMU_2_06:
     case POWERPC_MMU_2_06d:
-        if (real_mode) {
-            ret = check_physical(env, ctx, eaddr, rw);
-        } else {
-            ret = get_segment64(env, ctx, eaddr, rw, access_type);
-        }
+        ret = ppc_hash64_get_physical_address(env, ctx, eaddr, rw, access_type);
         break;
 #endif
 
commit 44bc910794eff956ceba0030f0751a26bed748b5
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:10 2013 +0000

    target-ppc: Rework get_physical_address()
    
    Currently get_physical_address() first checks to see if translation is
    enabled in the MSR, then in the translation on case switches on the mmu
    type.  Except that for BookE MMUs, translation is always on, and so it
    has to switch in the "translation off" case as well and do the same thing
    as the translation on path for those MMUs.  Plus, even translation off
    doesn't behave exactly the same on the various MMU types so there are
    further mmu type checks in the "translation off" path.
    
    As a first step to cleaning this up, this patch moves the switch on mmu
    type to the top level, then makes the translation on/off check just for
    those mmu types where it is meaningful.
    
    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/mmu_helper.c b/target-ppc/mmu_helper.c
index db5c15a..5b82731 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -1316,30 +1316,20 @@ static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx,
 static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
                                 target_ulong eaddr, int rw, int access_type)
 {
-    int ret;
+    int ret = -1;
+    bool real_mode = (access_type == ACCESS_CODE && msr_ir == 0)
+        || (access_type != ACCESS_CODE && msr_dr == 0);
 
 #if 0
     qemu_log("%s\n", __func__);
 #endif
-    if ((access_type == ACCESS_CODE && msr_ir == 0) ||
-        (access_type != ACCESS_CODE && msr_dr == 0)) {
-        if (env->mmu_model == POWERPC_MMU_BOOKE) {
-            /* The BookE MMU always performs address translation. The
-               IS and DS bits only affect the address space.  */
-            ret = mmubooke_get_physical_address(env, ctx, eaddr,
-                                                rw, access_type);
-        } else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
-            ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
-                                                   access_type);
-        } else {
-            /* No address translation.  */
+
+    switch (env->mmu_model) {
+    case POWERPC_MMU_32B:
+    case POWERPC_MMU_601:
+        if (real_mode) {
             ret = check_physical(env, ctx, eaddr, rw);
-        }
-    } else {
-        ret = -1;
-        switch (env->mmu_model) {
-        case POWERPC_MMU_32B:
-        case POWERPC_MMU_601:
+        } else {
             /* Try to find a BAT */
             if (env->nb_BATs != 0) {
                 ret = get_bat(env, ctx, eaddr, rw, access_type);
@@ -1348,10 +1338,14 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
                 /* We didn't match any BAT entry or don't have BATs */
                 ret = get_segment32(env, ctx, eaddr, rw, access_type);
             }
-            break;
+        }
+        break;
 
-        case POWERPC_MMU_SOFT_6xx:
-        case POWERPC_MMU_SOFT_74xx:
+    case POWERPC_MMU_SOFT_6xx:
+    case POWERPC_MMU_SOFT_74xx:
+        if (real_mode) {
+            ret = check_physical(env, ctx, eaddr, rw);
+        } else {
             /* Try to find a BAT */
             if (env->nb_BATs != 0) {
                 ret = get_bat(env, ctx, eaddr, rw, access_type);
@@ -1360,40 +1354,52 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
                 /* We didn't match any BAT entry or don't have BATs */
                 ret = get_segment_6xx_tlb(env, ctx, eaddr, rw, access_type);
             }
-            break;
+        }
+        break;
 
 #if defined(TARGET_PPC64)
-        case POWERPC_MMU_64B:
-        case POWERPC_MMU_2_06:
-        case POWERPC_MMU_2_06d:
+    case POWERPC_MMU_64B:
+    case POWERPC_MMU_2_06:
+    case POWERPC_MMU_2_06d:
+        if (real_mode) {
+            ret = check_physical(env, ctx, eaddr, rw);
+        } else {
             ret = get_segment64(env, ctx, eaddr, rw, access_type);
-            break;
+        }
+        break;
 #endif
 
-        case POWERPC_MMU_SOFT_4xx:
-        case POWERPC_MMU_SOFT_4xx_Z:
+    case POWERPC_MMU_SOFT_4xx:
+    case POWERPC_MMU_SOFT_4xx_Z:
+        if (real_mode) {
+            ret = check_physical(env, ctx, eaddr, rw);
+        } else {
             ret = mmu40x_get_physical_address(env, ctx, eaddr,
                                               rw, access_type);
-            break;
-        case POWERPC_MMU_BOOKE:
-            ret = mmubooke_get_physical_address(env, ctx, eaddr,
-                                                rw, access_type);
-            break;
-        case POWERPC_MMU_BOOKE206:
-            ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
+        }
+        break;
+    case POWERPC_MMU_BOOKE:
+        ret = mmubooke_get_physical_address(env, ctx, eaddr,
+                                            rw, access_type);
+        break;
+    case POWERPC_MMU_BOOKE206:
+        ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
                                                access_type);
-            break;
-        case POWERPC_MMU_MPC8xx:
-            /* XXX: TODO */
-            cpu_abort(env, "MPC8xx MMU model is not implemented\n");
-            break;
-        case POWERPC_MMU_REAL:
+        break;
+    case POWERPC_MMU_MPC8xx:
+        /* XXX: TODO */
+        cpu_abort(env, "MPC8xx MMU model is not implemented\n");
+        break;
+    case POWERPC_MMU_REAL:
+        if (real_mode) {
+            ret = check_physical(env, ctx, eaddr, rw);
+        } else {
             cpu_abort(env, "PowerPC in real mode do not do any translation\n");
-            return -1;
-        default:
-            cpu_abort(env, "Unknown or invalid MMU model\n");
-            return -1;
         }
+        return -1;
+    default:
+        cpu_abort(env, "Unknown or invalid MMU model\n");
+        return -1;
     }
 #if 0
     qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
commit 0480884f1404295ba0d242791e036b05c4957bab
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:09 2013 +0000

    target-ppc: Disentangle get_segment()
    
    The poorly named get_segment() function handles most of the address
    translation logic for hash-based MMUs.  It has many ugly conditionals on
    whether the MMU is 32-bit or 64-bit.
    
    This patch splits the function into 32 and 64-bit versions, using the
    switch on mmu_type that's already in the caller
    (get_physical_address()) to select the right one.  Most of the
    original function remains in mmu_helper.c to support the 6xx software
    loaded TLB implementations (cleaning those up is a project for another
    day).
    
    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/mmu-hash32.c b/target-ppc/mmu-hash32.c
index f852e5c..4bae72a 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -85,8 +85,8 @@ static int pte_check_hash32(mmu_ctx_t *ctx, target_ulong pte0,
 }
 
 /* PTE table lookup */
-int find_pte32(CPUPPCState *env, mmu_ctx_t *ctx, int h,
-               int rw, int type, int target_page_bits)
+static int find_pte32(CPUPPCState *env, mmu_ctx_t *ctx, int h,
+                      int rw, int type, int target_page_bits)
 {
     hwaddr pteg_off;
     target_ulong pte0, pte1;
@@ -157,3 +157,148 @@ int find_pte32(CPUPPCState *env, mmu_ctx_t *ctx, int h,
     }
     return ret;
 }
+
+int get_segment32(CPUPPCState *env, mmu_ctx_t *ctx,
+                  target_ulong eaddr, int rw, int type)
+{
+    hwaddr hash;
+    target_ulong vsid;
+    int ds, pr, target_page_bits;
+    int ret, ret2;
+    target_ulong sr, pgidx;
+
+    pr = msr_pr;
+    ctx->eaddr = eaddr;
+
+    sr = env->sr[eaddr >> 28];
+    ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
+                ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
+    ds = sr & 0x80000000 ? 1 : 0;
+    ctx->nx = sr & 0x10000000 ? 1 : 0;
+    vsid = sr & 0x00FFFFFF;
+    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
+            " 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);
+    ret = -1;
+    if (!ds) {
+        /* Check if instruction fetch is allowed, if needed */
+        if (type != ACCESS_CODE || ctx->nx == 0) {
+            /* Page address translation */
+            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;
+
+            /* Initialize real address with an invalid value */
+            ctx->raddr = (hwaddr)-1ULL;
+            LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+                    " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
+                    " hash=" TARGET_FMT_plx "\n",
+                    env->htab_base, env->htab_mask, vsid, ctx->ptem,
+                    ctx->hash[0]);
+            /* Primary table lookup */
+            ret = find_pte32(env, ctx, 0, rw, type, target_page_bits);
+            if (ret < 0) {
+                /* Secondary table lookup */
+                LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+                        " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
+                        " hash=" TARGET_FMT_plx "\n", env->htab_base,
+                        env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
+                ret2 = find_pte32(env, ctx, 1, rw, type,
+                                  target_page_bits);
+                if (ret2 != -1) {
+                    ret = ret2;
+                }
+            }
+#if defined(DUMP_PAGE_TABLES)
+            if (qemu_log_enabled()) {
+                hwaddr curaddr;
+                uint32_t a0, a1, a2, a3;
+
+                qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
+                         "\n", sdr, mask + 0x80);
+                for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
+                     curaddr += 16) {
+                    a0 = ldl_phys(curaddr);
+                    a1 = ldl_phys(curaddr + 4);
+                    a2 = ldl_phys(curaddr + 8);
+                    a3 = ldl_phys(curaddr + 12);
+                    if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
+                        qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
+                                 curaddr, a0, a1, a2, a3);
+                    }
+                }
+            }
+#endif
+        } else {
+            LOG_MMU("No access allowed\n");
+            ret = -3;
+        }
+    } else {
+        target_ulong sr;
+
+        LOG_MMU("direct store...\n");
+        /* Direct-store segment : absolutely *BUGGY* for now */
+
+        /* Direct-store implies a 32-bit MMU.
+         * Check the Segment Register's bus unit ID (BUID).
+         */
+        sr = env->sr[eaddr >> 28];
+        if ((sr & 0x1FF00000) >> 20 == 0x07f) {
+            /* Memory-forced I/O controller interface access */
+            /* If T=1 and BUID=x'07F', the 601 performs a memory access
+             * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
+             */
+            ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
+            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+            return 0;
+        }
+
+        switch (type) {
+        case ACCESS_INT:
+            /* Integer load/store : only access allowed */
+            break;
+        case ACCESS_CODE:
+            /* No code fetch is allowed in direct-store areas */
+            return -4;
+        case ACCESS_FLOAT:
+            /* Floating point load/store */
+            return -4;
+        case ACCESS_RES:
+            /* lwarx, ldarx or srwcx. */
+            return -4;
+        case ACCESS_CACHE:
+            /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
+            /* Should make the instruction do no-op.
+             * As it already do no-op, it's quite easy :-)
+             */
+            ctx->raddr = eaddr;
+            return 0;
+        case ACCESS_EXT:
+            /* eciwx or ecowx */
+            return -4;
+        default:
+            qemu_log("ERROR: instruction should not need "
+                        "address translation\n");
+            return -4;
+        }
+        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
+            ctx->raddr = eaddr;
+            ret = 2;
+        } else {
+            ret = -2;
+        }
+    }
+
+    return ret;
+}
diff --git a/target-ppc/mmu-hash32.h b/target-ppc/mmu-hash32.h
index 6bf8f92..6f9a0c2 100644
--- a/target-ppc/mmu-hash32.h
+++ b/target-ppc/mmu-hash32.h
@@ -4,8 +4,8 @@
 #ifndef CONFIG_USER_ONLY
 
 int pte32_is_valid(target_ulong pte0);
-int find_pte32(CPUPPCState *env, mmu_ctx_t *ctx, int h,
-               int rw, int type, int target_page_bits);
+int get_segment32(CPUPPCState *env, mmu_ctx_t *ctx,
+                  target_ulong eaddr, int rw, int type);
 
 #endif /* CONFIG_USER_ONLY */
 
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index a525bd5..23eb480 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -44,7 +44,7 @@
  * SLB handling
  */
 
-ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr)
+static ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr)
 {
     uint64_t esid_256M, esid_1T;
     int n;
@@ -276,8 +276,8 @@ static int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
 }
 
 /* PTE table lookup */
-int find_pte64(CPUPPCState *env, mmu_ctx_t *ctx, int h,
-               int rw, int type, int target_page_bits)
+static int find_pte64(CPUPPCState *env, mmu_ctx_t *ctx, int h,
+                      int rw, int type, int target_page_bits)
 {
     hwaddr pteg_off;
     target_ulong pte0, pte1;
@@ -349,3 +349,89 @@ int find_pte64(CPUPPCState *env, mmu_ctx_t *ctx, int h,
     }
     return ret;
 }
+
+int get_segment64(CPUPPCState *env, mmu_ctx_t *ctx,
+                  target_ulong eaddr, int rw, int type)
+{
+    hwaddr hash;
+    target_ulong vsid;
+    int pr, target_page_bits;
+    int ret, ret2;
+
+    pr = msr_pr;
+    ctx->eaddr = eaddr;
+    ppc_slb_t *slb;
+    target_ulong pageaddr;
+    int segment_bits;
+
+    LOG_MMU("Check SLBs\n");
+    slb = slb_lookup(env, eaddr);
+    if (!slb) {
+        return -5;
+    }
+
+    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)
+                  : (slb->vsid & SLB_VSID_KS));
+    ctx->nx = !!(slb->vsid & SLB_VSID_N);
+
+    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) & ((1ULL << segment_bits) - 0x80));
+
+    LOG_MMU("pte segment: key=%d nx %d vsid " TARGET_FMT_lx "\n",
+            ctx->key, ctx->nx, vsid);
+    ret = -1;
+
+    /* Check if instruction fetch is allowed, if needed */
+    if (type != ACCESS_CODE || ctx->nx == 0) {
+        /* Page address translation */
+        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;
+
+        /* Initialize real address with an invalid value */
+        ctx->raddr = (hwaddr)-1ULL;
+        LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+                " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
+                " hash=" TARGET_FMT_plx "\n",
+                env->htab_base, env->htab_mask, vsid, ctx->ptem,
+                ctx->hash[0]);
+        /* Primary table lookup */
+        ret = find_pte64(env, ctx, 0, rw, type, target_page_bits);
+        if (ret < 0) {
+            /* Secondary table lookup */
+            LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+                    " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
+                    " hash=" TARGET_FMT_plx "\n", env->htab_base,
+                    env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
+            ret2 = find_pte64(env, ctx, 1, rw, type, target_page_bits);
+            if (ret2 != -1) {
+                ret = ret2;
+            }
+        }
+    } else {
+        LOG_MMU("No access allowed\n");
+        ret = -3;
+    }
+
+    return ret;
+}
diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h
index 7b9713d..690c1d8 100644
--- a/target-ppc/mmu-hash64.h
+++ b/target-ppc/mmu-hash64.h
@@ -4,11 +4,10 @@
 #ifndef CONFIG_USER_ONLY
 
 #ifdef TARGET_PPC64
-ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr);
 void dump_slb(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env);
 int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
-int find_pte64(CPUPPCState *env, mmu_ctx_t *ctx, int h,
-               int rw, int type, int target_page_bits);
+int get_segment64(CPUPPCState *env, mmu_ctx_t *ctx,
+                  target_ulong eaddr, int rw, int type);
 #endif
 
 #endif /* CONFIG_USER_ONLY */
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 1301391..db5c15a 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -507,87 +507,35 @@ hwaddr get_pteg_offset(CPUPPCState *env, hwaddr hash, int pte_size)
     return (hash * pte_size * 8) & env->htab_mask;
 }
 
-static inline int find_pte(CPUPPCState *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);
-    }
-#endif
-
-    return find_pte32(env, ctx, h, rw, type, target_page_bits);
-}
-
 /* Perform segment based translation */
-static inline int get_segment(CPUPPCState *env, mmu_ctx_t *ctx,
-                              target_ulong eaddr, int rw, int type)
+static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
+                                      target_ulong eaddr, int rw, int type)
 {
     hwaddr hash;
     target_ulong vsid;
     int ds, pr, target_page_bits;
-    int ret, ret2;
+    int ret;
+    target_ulong sr, pgidx;
 
     pr = msr_pr;
     ctx->eaddr = eaddr;
-#if defined(TARGET_PPC64)
-    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);
-        if (!slb) {
-            return -5;
-        }
-
-        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)
-                      : (slb->vsid & SLB_VSID_KS));
-        ds = 0;
-        ctx->nx = !!(slb->vsid & SLB_VSID_N);
 
-        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) & ((1ULL << segment_bits) - 0x80));
-    } else
-#endif /* defined(TARGET_PPC64) */
-    {
-        target_ulong sr, pgidx;
+    sr = env->sr[eaddr >> 28];
+    ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
+                ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
+    ds = sr & 0x80000000 ? 1 : 0;
+    ctx->nx = sr & 0x10000000 ? 1 : 0;
+    vsid = sr & 0x00FFFFFF;
+    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
+            " 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);
 
-        sr = env->sr[eaddr >> 28];
-        ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
-                    ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
-        ds = sr & 0x80000000 ? 1 : 0;
-        ctx->nx = sr & 0x10000000 ? 1 : 0;
-        vsid = sr & 0x00FFFFFF;
-        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
-                " 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);
     ret = -1;
@@ -603,31 +551,8 @@ static inline int get_segment(CPUPPCState *env, mmu_ctx_t *ctx,
 
             /* Initialize real address with an invalid value */
             ctx->raddr = (hwaddr)-1ULL;
-            if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
-                         env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
-                /* Software TLB search */
-                ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
-            } else {
-                LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
-                        " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
-                        " hash=" TARGET_FMT_plx "\n",
-                        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);
-                if (ret < 0) {
-                    /* Secondary table lookup */
-                    LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
-                            " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
-                            " hash=" TARGET_FMT_plx "\n", env->htab_base,
-                            env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
-                    ret2 = find_pte(env, ctx, 1, rw, type,
-                                    target_page_bits);
-                    if (ret2 != -1) {
-                        ret = ret2;
-                    }
-                }
-            }
+            /* Software TLB search */
+            ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
 #if defined(DUMP_PAGE_TABLES)
             if (qemu_log_enabled()) {
                 hwaddr curaddr;
@@ -1415,22 +1340,36 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
         switch (env->mmu_model) {
         case POWERPC_MMU_32B:
         case POWERPC_MMU_601:
+            /* Try to find a BAT */
+            if (env->nb_BATs != 0) {
+                ret = get_bat(env, ctx, eaddr, rw, access_type);
+            }
+            if (ret < 0) {
+                /* We didn't match any BAT entry or don't have BATs */
+                ret = get_segment32(env, ctx, eaddr, rw, access_type);
+            }
+            break;
+
         case POWERPC_MMU_SOFT_6xx:
         case POWERPC_MMU_SOFT_74xx:
             /* Try to find a BAT */
             if (env->nb_BATs != 0) {
                 ret = get_bat(env, ctx, eaddr, rw, access_type);
             }
+            if (ret < 0) {
+                /* We didn't match any BAT entry or don't have BATs */
+                ret = get_segment_6xx_tlb(env, ctx, eaddr, rw, access_type);
+            }
+            break;
+
 #if defined(TARGET_PPC64)
         case POWERPC_MMU_64B:
         case POWERPC_MMU_2_06:
         case POWERPC_MMU_2_06d:
-#endif
-            if (ret < 0) {
-                /* We didn't match any BAT entry or don't have BATs */
-                ret = get_segment(env, ctx, eaddr, rw, access_type);
-            }
+            ret = get_segment64(env, ctx, eaddr, rw, access_type);
             break;
+#endif
+
         case POWERPC_MMU_SOFT_4xx:
         case POWERPC_MMU_SOFT_4xx_Z:
             ret = mmu40x_get_physical_address(env, ctx, eaddr,
commit c69b6151e7f242b02f261f321c392e5ef933176f
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:08 2013 +0000

    target-ppc: Disentangle find_pte()
    
    32-bit and 64-bit hash MMU implementations currently share a find_pte
    function.  This results in a whole bunch of ugly conditionals in the shared
    function, and not all that much actually shared code.
    
    This patch separates out the 32-bit and 64-bit versions, putting then
    in mmu-hash64.c and mmu-has32.c, and removes the conditionals from
    both versions.
    
    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/cpu.h b/target-ppc/cpu.h
index 625feb2..cf8ba2e 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1135,6 +1135,8 @@ void ppc_hw_interrupt (CPUPPCState *env);
 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
 int pp_check(int key, int pp, int nx);
 int check_prot(int prot, int rw, int access_type);
+int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p, int ret, int rw);
+hwaddr get_pteg_offset(CPUPPCState *env, hwaddr hash, int pte_size);
 #endif /* !defined(CONFIG_USER_ONLY) */
 void ppc_store_msr (CPUPPCState *env, target_ulong value);
 
diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c
index ce5389d..f852e5c 100644
--- a/target-ppc/mmu-hash32.c
+++ b/target-ppc/mmu-hash32.c
@@ -42,8 +42,8 @@ static inline int pte_is_valid_hash32(target_ulong pte0)
     return pte0 & 0x80000000 ? 1 : 0;
 }
 
-int pte_check_hash32(mmu_ctx_t *ctx, target_ulong pte0,
-                     target_ulong pte1, int h, int rw, int type)
+static int pte_check_hash32(mmu_ctx_t *ctx, target_ulong pte0,
+                            target_ulong pte1, int h, int rw, int type)
 {
     target_ulong ptem, mmask;
     int access, ret, pteh, ptev, pp;
@@ -83,3 +83,77 @@ int pte_check_hash32(mmu_ctx_t *ctx, target_ulong pte0,
 
     return ret;
 }
+
+/* PTE table lookup */
+int find_pte32(CPUPPCState *env, mmu_ctx_t *ctx, int h,
+               int rw, int type, int target_page_bits)
+{
+    hwaddr pteg_off;
+    target_ulong pte0, pte1;
+    int i, good = -1;
+    int ret, r;
+
+    ret = -1; /* No entry found */
+    pteg_off = get_pteg_offset(env, ctx->hash[h], HASH_PTE_SIZE_32);
+    for (i = 0; i < 8; i++) {
+        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 = pte_check_hash32(ctx, pte0, pte1, h, rw, type);
+        LOG_MMU("Load pte from %08" HWADDR_PRIx " => " TARGET_FMT_lx " "
+                TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
+                pteg_off + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
+                (int)((pte0 >> 6) & 1), ctx->ptem);
+        switch (r) {
+        case -3:
+            /* PTE inconsistency */
+            return -1;
+        case -2:
+            /* Access violation */
+            ret = -2;
+            good = i;
+            break;
+        case -1:
+        default:
+            /* No PTE match */
+            break;
+        case 0:
+            /* access granted */
+            /* XXX: we should go on looping to check all PTEs consistency
+             *      but if we can speed-up the whole thing as the
+             *      result would be undefined if PTEs are not consistent.
+             */
+            ret = 0;
+            good = i;
+            goto done;
+        }
+    }
+    if (good != -1) {
+    done:
+        LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n",
+                ctx->raddr, ctx->prot, ret);
+        /* Update page flags */
+        pte1 = ctx->raddr;
+        if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
+            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);
+            }
+        }
+    }
+
+    /* We have a TLB that saves 4K pages, so let's
+     * split a huge page to 4k chunks */
+    if (target_page_bits != TARGET_PAGE_BITS) {
+        ctx->raddr |= (ctx->eaddr & ((1 << target_page_bits) - 1))
+                      & TARGET_PAGE_MASK;
+    }
+    return ret;
+}
diff --git a/target-ppc/mmu-hash32.h b/target-ppc/mmu-hash32.h
index 2411085..6bf8f92 100644
--- a/target-ppc/mmu-hash32.h
+++ b/target-ppc/mmu-hash32.h
@@ -4,8 +4,8 @@
 #ifndef CONFIG_USER_ONLY
 
 int pte32_is_valid(target_ulong pte0);
-int pte_check_hash32(mmu_ctx_t *ctx, target_ulong pte0,
-                     target_ulong pte1, int h, int rw, int type);
+int find_pte32(CPUPPCState *env, mmu_ctx_t *ctx, int h,
+               int rw, int type, int target_page_bits);
 
 #endif /* CONFIG_USER_ONLY */
 
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index 9c0de1b..a525bd5 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -231,8 +231,8 @@ static inline int pte64_is_valid(target_ulong pte0)
     return pte0 & 0x0000000000000001ULL ? 1 : 0;
 }
 
-int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
-                target_ulong pte1, int h, int rw, int type)
+static int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
+                       target_ulong pte1, int h, int rw, int type)
 {
     target_ulong ptem, mmask;
     int access, ret, pteh, ptev, pp;
@@ -274,3 +274,78 @@ int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
 
     return ret;
 }
+
+/* PTE table lookup */
+int find_pte64(CPUPPCState *env, mmu_ctx_t *ctx, int h,
+               int rw, int type, int target_page_bits)
+{
+    hwaddr pteg_off;
+    target_ulong pte0, pte1;
+    int i, good = -1;
+    int ret, r;
+
+    ret = -1; /* No entry found */
+    pteg_off = get_pteg_offset(env, ctx->hash[h], HASH_PTE_SIZE_64);
+    for (i = 0; i < 8; i++) {
+        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);
+        }
+
+        r = pte64_check(ctx, pte0, pte1, h, rw, type);
+        LOG_MMU("Load pte from %016" HWADDR_PRIx " => " TARGET_FMT_lx " "
+                TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
+                pteg_off + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
+                (int)((pte0 >> 1) & 1), ctx->ptem);
+        switch (r) {
+        case -3:
+            /* PTE inconsistency */
+            return -1;
+        case -2:
+            /* Access violation */
+            ret = -2;
+            good = i;
+            break;
+        case -1:
+        default:
+            /* No PTE match */
+            break;
+        case 0:
+            /* access granted */
+            /* XXX: we should go on looping to check all PTEs consistency
+             *      but if we can speed-up the whole thing as the
+             *      result would be undefined if PTEs are not consistent.
+             */
+            ret = 0;
+            good = i;
+            goto done;
+        }
+    }
+    if (good != -1) {
+    done:
+        LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n",
+                ctx->raddr, ctx->prot, ret);
+        /* Update page flags */
+        pte1 = ctx->raddr;
+        if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
+            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);
+            }
+        }
+    }
+
+    /* We have a TLB that saves 4K pages, so let's
+     * split a huge page to 4k chunks */
+    if (target_page_bits != TARGET_PAGE_BITS) {
+        ctx->raddr |= (ctx->eaddr & ((1 << target_page_bits) - 1))
+                      & TARGET_PAGE_MASK;
+    }
+    return ret;
+}
diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h
index 1a2e3e7..7b9713d 100644
--- a/target-ppc/mmu-hash64.h
+++ b/target-ppc/mmu-hash64.h
@@ -7,8 +7,8 @@
 ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr);
 void dump_slb(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env);
 int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
-int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
-                target_ulong pte1, int h, int rw, int type);
+int find_pte64(CPUPPCState *env, mmu_ctx_t *ctx, int h,
+               int rw, int type, int target_page_bits);
 #endif
 
 #endif /* CONFIG_USER_ONLY */
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index c7620c0..1301391 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -201,8 +201,8 @@ static inline int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
     return ret;
 }
 
-static inline int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
-                                   int ret, int rw)
+int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
+                     int ret, int rw)
 {
     int store = 0;
 
@@ -502,130 +502,21 @@ static inline int get_bat(CPUPPCState *env, mmu_ctx_t *ctx,
     return ret;
 }
 
-static inline hwaddr get_pteg_offset(CPUPPCState *env,
-                                                 hwaddr hash,
-                                                 int pte_size)
+hwaddr get_pteg_offset(CPUPPCState *env, hwaddr hash, int pte_size)
 {
     return (hash * pte_size * 8) & env->htab_mask;
 }
 
-/* PTE table lookup */
-static inline int find_pte2(CPUPPCState *env, mmu_ctx_t *ctx, int is_64b, int h,
-                            int rw, int type, int target_page_bits)
-{
-    hwaddr pteg_off;
-    target_ulong pte0, pte1;
-    int i, good = -1;
-    int ret, r;
-
-    ret = -1; /* No entry found */
-    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) {
-            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);
-            }
-
-            r = pte64_check(ctx, pte0, pte1, h, rw, type);
-            LOG_MMU("Load pte from %016" HWADDR_PRIx " => " TARGET_FMT_lx " "
-                    TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
-                    pteg_off + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
-                    (int)((pte0 >> 1) & 1), ctx->ptem);
-        } else
-#endif
-        {
-            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 = pte_check_hash32(ctx, pte0, pte1, h, rw, type);
-            LOG_MMU("Load pte from %08" HWADDR_PRIx " => " TARGET_FMT_lx " "
-                    TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
-                    pteg_off + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
-                    (int)((pte0 >> 6) & 1), ctx->ptem);
-        }
-        switch (r) {
-        case -3:
-            /* PTE inconsistency */
-            return -1;
-        case -2:
-            /* Access violation */
-            ret = -2;
-            good = i;
-            break;
-        case -1:
-        default:
-            /* No PTE match */
-            break;
-        case 0:
-            /* access granted */
-            /* XXX: we should go on looping to check all PTEs consistency
-             *      but if we can speed-up the whole thing as the
-             *      result would be undefined if PTEs are not consistent.
-             */
-            ret = 0;
-            good = i;
-            goto done;
-        }
-    }
-    if (good != -1) {
-    done:
-        LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n",
-                ctx->raddr, ctx->prot, ret);
-        /* Update page flags */
-        pte1 = ctx->raddr;
-        if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
-#if defined(TARGET_PPC64)
-            if (is_64b) {
-                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
-            {
-                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);
-                }
-            }
-        }
-    }
-
-    /* We have a TLB that saves 4K pages, so let's
-     * split a huge page to 4k chunks */
-    if (target_page_bits != TARGET_PAGE_BITS) {
-        ctx->raddr |= (ctx->eaddr & ((1 << target_page_bits) - 1))
-                      & TARGET_PAGE_MASK;
-    }
-    return ret;
-}
-
 static inline int find_pte(CPUPPCState *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_pte2(env, ctx, 1, h, rw, type, target_page_bits);
+        return find_pte64(env, ctx, h, rw, type, target_page_bits);
     }
 #endif
 
-    return find_pte2(env, ctx, 0, h, rw, type, target_page_bits);
+    return find_pte32(env, ctx, h, rw, type, target_page_bits);
 }
 
 /* Perform segment based translation */
commit 9d7c3f4a2935a70e7299a6862792bbfc48d62211
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:07 2013 +0000

    target-ppc: Disentangle pte_check()
    
    Currently support for both 32-bit and 64-bit hash MMUs share an
    implementation of pte_check.  But there are enough differences that this
    means the shared function has several very ugly conditionals on "is_64b".
    
    This patch cleans things up by separating out the 64-bit version
    (putting it into mmu-hash64.c) and the 32-bit hash version (putting it
    in mmu-hash32.c).  Another copy remains in mmu_helper.c, which is used
    for the 6xx software loaded TLB paths.
    
    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/Makefile.objs b/target-ppc/Makefile.objs
index 4ef9fc0..c80911f 100644
--- a/target-ppc/Makefile.objs
+++ b/target-ppc/Makefile.objs
@@ -1,7 +1,7 @@
 obj-y += cpu-models.o
 obj-y += translate.o
 ifeq ($(CONFIG_SOFTMMU),y)
-obj-y += machine.o
+obj-y += machine.o mmu-hash32.o
 obj-$(TARGET_PPC64) += mmu-hash64.o
 endif
 obj-$(CONFIG_KVM) += kvm.o kvm_ppc.o
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index a3e1362..625feb2 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1133,6 +1133,8 @@ void ppc_hw_interrupt (CPUPPCState *env);
 
 #if !defined(CONFIG_USER_ONLY)
 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
+int pp_check(int key, int pp, int nx);
+int check_prot(int prot, int rw, int access_type);
 #endif /* !defined(CONFIG_USER_ONLY) */
 void ppc_store_msr (CPUPPCState *env, target_ulong value);
 
diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c
new file mode 100644
index 0000000..ce5389d
--- /dev/null
+++ b/target-ppc/mmu-hash32.c
@@ -0,0 +1,85 @@
+/*
+ *  PowerPC MMU, TLB and BAT emulation helpers for QEMU.
+ *
+ *  Copyright (c) 2003-2007 Jocelyn Mayer
+ *  Copyright (c) 2013 David Gibson, IBM Corporation
+ *
+ * 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 "cpu.h"
+#include "helper.h"
+#include "sysemu/kvm.h"
+#include "kvm_ppc.h"
+#include "mmu-hash32.h"
+
+//#define DEBUG_MMU
+
+#ifdef DEBUG_MMU
+#  define LOG_MMU(...) qemu_log(__VA_ARGS__)
+#  define LOG_MMU_STATE(env) log_cpu_state((env), 0)
+#else
+#  define LOG_MMU(...) do { } while (0)
+#  define LOG_MMU_STATE(...) do { } while (0)
+#endif
+
+#define PTE_PTEM_MASK 0x7FFFFFBF
+#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
+
+static inline int pte_is_valid_hash32(target_ulong pte0)
+{
+    return pte0 & 0x80000000 ? 1 : 0;
+}
+
+int pte_check_hash32(mmu_ctx_t *ctx, target_ulong pte0,
+                     target_ulong pte1, int h, int rw, int type)
+{
+    target_ulong ptem, mmask;
+    int access, ret, pteh, ptev, pp;
+
+    ret = -1;
+    /* Check validity and table match */
+    ptev = pte_is_valid_hash32(pte0);
+    pteh = (pte0 >> 6) & 1;
+    if (ptev && h == pteh) {
+        /* Check vsid & api */
+        ptem = pte0 & PTE_PTEM_MASK;
+        mmask = PTE_CHECK_MASK;
+        pp = pte1 & 0x00000003;
+        if (ptem == ctx->ptem) {
+            if (ctx->raddr != (hwaddr)-1ULL) {
+                /* all matches should have equal RPN, WIMG & PP */
+                if ((ctx->raddr & mmask) != (pte1 & mmask)) {
+                    qemu_log("Bad RPN/WIMG/PP\n");
+                    return -3;
+                }
+            }
+            /* Compute access rights */
+            access = pp_check(ctx->key, pp, ctx->nx);
+            /* Keep the matching PTE informations */
+            ctx->raddr = pte1;
+            ctx->prot = access;
+            ret = check_prot(ctx->prot, rw, type);
+            if (ret == 0) {
+                /* Access granted */
+                LOG_MMU("PTE access granted !\n");
+            } else {
+                /* Access right violation */
+                LOG_MMU("PTE access rejected\n");
+            }
+        }
+    }
+
+    return ret;
+}
diff --git a/target-ppc/mmu-hash32.h b/target-ppc/mmu-hash32.h
new file mode 100644
index 0000000..2411085
--- /dev/null
+++ b/target-ppc/mmu-hash32.h
@@ -0,0 +1,12 @@
+#if !defined (__MMU_HASH32_H__)
+#define __MMU_HASH32_H__
+
+#ifndef CONFIG_USER_ONLY
+
+int pte32_is_valid(target_ulong pte0);
+int pte_check_hash32(mmu_ctx_t *ctx, target_ulong pte0,
+                     target_ulong pte1, int h, int rw, int type);
+
+#endif /* CONFIG_USER_ONLY */
+
+#endif /* __MMU_HASH32_H__ */
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index a72e7c1..9c0de1b 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -23,8 +23,17 @@
 #include "kvm_ppc.h"
 #include "mmu-hash64.h"
 
+//#define DEBUG_MMU
 //#define DEBUG_SLB
 
+#ifdef DEBUG_MMU
+#  define LOG_MMU(...) qemu_log(__VA_ARGS__)
+#  define LOG_MMU_STATE(env) log_cpu_state((env), 0)
+#else
+#  define LOG_MMU(...) do { } while (0)
+#  define LOG_MMU_STATE(...) do { } while (0)
+#endif
+
 #ifdef DEBUG_SLB
 #  define LOG_SLB(...) qemu_log(__VA_ARGS__)
 #else
@@ -209,3 +218,59 @@ target_ulong helper_load_slb_vsid(CPUPPCState *env, target_ulong rb)
     }
     return rt;
 }
+
+/*
+ * 64-bit hash table MMU handling
+ */
+
+#define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
+#define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
+
+static inline int pte64_is_valid(target_ulong pte0)
+{
+    return pte0 & 0x0000000000000001ULL ? 1 : 0;
+}
+
+int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
+                target_ulong pte1, int h, int rw, int type)
+{
+    target_ulong ptem, mmask;
+    int access, ret, pteh, ptev, pp;
+
+    ret = -1;
+    /* Check validity and table match */
+    ptev = pte64_is_valid(pte0);
+    pteh = (pte0 >> 1) & 1;
+    if (ptev && h == pteh) {
+        /* Check vsid & api */
+        ptem = pte0 & PTE64_PTEM_MASK;
+        mmask = PTE64_CHECK_MASK;
+        pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
+        ctx->nx  = (pte1 >> 2) & 1; /* No execute bit */
+        ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit    */
+        if (ptem == ctx->ptem) {
+            if (ctx->raddr != (hwaddr)-1ULL) {
+                /* all matches should have equal RPN, WIMG & PP */
+                if ((ctx->raddr & mmask) != (pte1 & mmask)) {
+                    qemu_log("Bad RPN/WIMG/PP\n");
+                    return -3;
+                }
+            }
+            /* Compute access rights */
+            access = pp_check(ctx->key, pp, ctx->nx);
+            /* Keep the matching PTE informations */
+            ctx->raddr = pte1;
+            ctx->prot = access;
+            ret = check_prot(ctx->prot, rw, type);
+            if (ret == 0) {
+                /* Access granted */
+                LOG_MMU("PTE access granted !\n");
+            } else {
+                /* Access right violation */
+                LOG_MMU("PTE access rejected\n");
+            }
+        }
+    }
+
+    return ret;
+}
diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h
index 894b1f2..1a2e3e7 100644
--- a/target-ppc/mmu-hash64.h
+++ b/target-ppc/mmu-hash64.h
@@ -7,6 +7,8 @@
 ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr);
 void dump_slb(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env);
 int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
+int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
+                target_ulong pte1, int h, int rw, int type);
 #endif
 
 #endif /* CONFIG_USER_ONLY */
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 671ca5e..c7620c0 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -21,6 +21,7 @@
 #include "sysemu/kvm.h"
 #include "kvm_ppc.h"
 #include "mmu-hash64.h"
+#include "mmu-hash32.h"
 
 //#define DEBUG_MMU
 //#define DEBUG_BATS
@@ -87,21 +88,10 @@ static inline void pte_invalidate(target_ulong *pte0)
     *pte0 &= ~0x80000000;
 }
 
-#if defined(TARGET_PPC64)
-static inline int pte64_is_valid(target_ulong pte0)
-{
-    return pte0 & 0x0000000000000001ULL ? 1 : 0;
-}
-#endif
-
 #define PTE_PTEM_MASK 0x7FFFFFBF
 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
-#if defined(TARGET_PPC64)
-#define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
-#define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
-#endif
 
-static inline int pp_check(int key, int pp, int nx)
+int pp_check(int key, int pp, int nx)
 {
     int access;
 
@@ -142,7 +132,7 @@ static inline int pp_check(int key, int pp, int nx)
     return access;
 }
 
-static inline int check_prot(int prot, int rw, int access_type)
+int check_prot(int prot, int rw, int access_type)
 {
     int ret;
 
@@ -169,40 +159,21 @@ static inline int check_prot(int prot, int rw, int access_type)
     return ret;
 }
 
-static inline int pte_check(mmu_ctx_t *ctx, int is_64b, target_ulong pte0,
-                            target_ulong pte1, int h, int rw, int type)
+static inline int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
+                                       target_ulong pte1, int h, int rw, int type)
 {
     target_ulong ptem, mmask;
     int access, ret, pteh, ptev, pp;
 
     ret = -1;
     /* Check validity and table match */
-#if defined(TARGET_PPC64)
-    if (is_64b) {
-        ptev = pte64_is_valid(pte0);
-        pteh = (pte0 >> 1) & 1;
-    } else
-#endif
-    {
-        ptev = pte_is_valid(pte0);
-        pteh = (pte0 >> 6) & 1;
-    }
+    ptev = pte_is_valid(pte0);
+    pteh = (pte0 >> 6) & 1;
     if (ptev && h == pteh) {
         /* Check vsid & api */
-#if defined(TARGET_PPC64)
-        if (is_64b) {
-            ptem = pte0 & PTE64_PTEM_MASK;
-            mmask = PTE64_CHECK_MASK;
-            pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
-            ctx->nx  = (pte1 >> 2) & 1; /* No execute bit */
-            ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit    */
-        } else
-#endif
-        {
-            ptem = pte0 & PTE_PTEM_MASK;
-            mmask = PTE_CHECK_MASK;
-            pp = pte1 & 0x00000003;
-        }
+        ptem = pte0 & PTE_PTEM_MASK;
+        mmask = PTE_CHECK_MASK;
+        pp = pte1 & 0x00000003;
         if (ptem == ctx->ptem) {
             if (ctx->raddr != (hwaddr)-1ULL) {
                 /* all matches should have equal RPN, WIMG & PP */
@@ -230,20 +201,6 @@ static inline int pte_check(mmu_ctx_t *ctx, int is_64b, target_ulong pte0,
     return ret;
 }
 
-static inline int pte32_check(mmu_ctx_t *ctx, target_ulong pte0,
-                              target_ulong pte1, int h, int rw, int type)
-{
-    return pte_check(ctx, 0, pte0, pte1, h, rw, type);
-}
-
-#if defined(TARGET_PPC64)
-static inline int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
-                              target_ulong pte1, int h, int rw, int type)
-{
-    return pte_check(ctx, 1, pte0, pte1, h, rw, type);
-}
-#endif
-
 static inline int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
                                    int ret, int rw)
 {
@@ -381,7 +338,7 @@ static inline int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx,
                   pte_is_valid(tlb->pte0) ? "valid" : "inval",
                   tlb->EPN, eaddr, tlb->pte1,
                   rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
-        switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
+        switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
         case -3:
             /* TLB inconsistency */
             return -1;
@@ -590,7 +547,7 @@ static inline int find_pte2(CPUPPCState *env, mmu_ctx_t *ctx, int is_64b, int h,
                 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);
+            r = pte_check_hash32(ctx, pte0, pte1, h, rw, type);
             LOG_MMU("Load pte from %08" HWADDR_PRIx " => " TARGET_FMT_lx " "
                     TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
                     pteg_off + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
commit 10b4652543313ca82284193fa107151c437f9b04
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:06 2013 +0000

    target-ppc: Move SLB handling into a mmu-hash64.c
    
    As a first step to disentangling the handling for 64-bit hash MMUs from
    the rest, we move the code handling the Segment Lookaside Buffer (SLB)
    (which only exists on 64-bit hash MMUs) into a new mmu-hash64.c file.
    
    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/Makefile.objs b/target-ppc/Makefile.objs
index 00ac4ad..4ef9fc0 100644
--- a/target-ppc/Makefile.objs
+++ b/target-ppc/Makefile.objs
@@ -1,6 +1,9 @@
 obj-y += cpu-models.o
 obj-y += translate.o
-obj-$(CONFIG_SOFTMMU) += machine.o
+ifeq ($(CONFIG_SOFTMMU),y)
+obj-y += machine.o
+obj-$(TARGET_PPC64) += mmu-hash64.o
+endif
 obj-$(CONFIG_KVM) += kvm.o kvm_ppc.o
 obj-y += excp_helper.o
 obj-y += fpu_helper.o
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 83b41f3..a3e1362 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1133,9 +1133,6 @@ void ppc_hw_interrupt (CPUPPCState *env);
 
 #if !defined(CONFIG_USER_ONLY)
 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
-#if defined(TARGET_PPC64)
-int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
-#endif /* defined(TARGET_PPC64) */
 #endif /* !defined(CONFIG_USER_ONLY) */
 void ppc_store_msr (CPUPPCState *env, target_ulong value);
 
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
new file mode 100644
index 0000000..a72e7c1
--- /dev/null
+++ b/target-ppc/mmu-hash64.c
@@ -0,0 +1,211 @@
+/*
+ *  PowerPC MMU, TLB, SLB and BAT emulation helpers for QEMU.
+ *
+ *  Copyright (c) 2003-2007 Jocelyn Mayer
+ *  Copyright (c) 2013 David Gibson, IBM Corporation
+ *
+ * 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 "cpu.h"
+#include "helper.h"
+#include "sysemu/kvm.h"
+#include "kvm_ppc.h"
+#include "mmu-hash64.h"
+
+//#define DEBUG_SLB
+
+#ifdef DEBUG_SLB
+#  define LOG_SLB(...) qemu_log(__VA_ARGS__)
+#else
+#  define LOG_SLB(...) do { } while (0)
+#endif
+
+/*
+ * SLB handling
+ */
+
+ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr)
+{
+    uint64_t esid_256M, esid_1T;
+    int n;
+
+    LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
+
+    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);
+        /* 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;
+        }
+    }
+
+    return NULL;
+}
+
+void dump_slb(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env)
+{
+    int i;
+    uint64_t slbe, slbv;
+
+    cpu_synchronize_state(env);
+
+    cpu_fprintf(f, "SLB\tESID\t\t\tVSID\n");
+    for (i = 0; i < env->slb_nr; i++) {
+        slbe = env->slb[i].esid;
+        slbv = env->slb[i].vsid;
+        if (slbe == 0 && slbv == 0) {
+            continue;
+        }
+        cpu_fprintf(f, "%d\t0x%016" PRIx64 "\t0x%016" PRIx64 "\n",
+                    i, slbe, slbv);
+    }
+}
+
+void helper_slbia(CPUPPCState *env)
+{
+    int n, do_invalidate;
+
+    do_invalidate = 0;
+    /* XXX: Warning: slbia never invalidates the first segment */
+    for (n = 1; n < env->slb_nr; n++) {
+        ppc_slb_t *slb = &env->slb[n];
+
+        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
+             */
+            do_invalidate = 1;
+        }
+    }
+    if (do_invalidate) {
+        tlb_flush(env, 1);
+    }
+}
+
+void helper_slbie(CPUPPCState *env, target_ulong addr)
+{
+    ppc_slb_t *slb;
+
+    slb = slb_lookup(env, addr);
+    if (!slb) {
+        return;
+    }
+
+    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
+         */
+        tlb_flush(env, 1);
+    }
+}
+
+int ppc_store_slb(CPUPPCState *env, target_ulong rb, target_ulong rs)
+{
+    int slot = rb & 0xfff;
+    ppc_slb_t *slb = &env->slb[slot];
+
+    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 */
+    }
+
+    /* 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
+            " %016" PRIx64 "\n", __func__, slot, rb, rs,
+            slb->esid, slb->vsid);
+
+    return 0;
+}
+
+static 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;
+}
+
+static 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;
+}
+
+void helper_store_slb(CPUPPCState *env, target_ulong rb, target_ulong rs)
+{
+    if (ppc_store_slb(env, rb, rs) < 0) {
+        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
+                                   POWERPC_EXCP_INVAL);
+    }
+}
+
+target_ulong helper_load_slb_esid(CPUPPCState *env, target_ulong rb)
+{
+    target_ulong rt = 0;
+
+    if (ppc_load_slb_esid(env, rb, &rt) < 0) {
+        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
+                                   POWERPC_EXCP_INVAL);
+    }
+    return rt;
+}
+
+target_ulong helper_load_slb_vsid(CPUPPCState *env, target_ulong rb)
+{
+    target_ulong rt = 0;
+
+    if (ppc_load_slb_vsid(env, rb, &rt) < 0) {
+        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
+                                   POWERPC_EXCP_INVAL);
+    }
+    return rt;
+}
diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h
new file mode 100644
index 0000000..894b1f2
--- /dev/null
+++ b/target-ppc/mmu-hash64.h
@@ -0,0 +1,14 @@
+#if !defined (__MMU_HASH64_H__)
+#define __MMU_HASH64_H__
+
+#ifndef CONFIG_USER_ONLY
+
+#ifdef TARGET_PPC64
+ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr);
+void dump_slb(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env);
+int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
+#endif
+
+#endif /* CONFIG_USER_ONLY */
+
+#endif /* !defined (__MMU_HASH64_H__) */
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index f1de84c..671ca5e 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -20,10 +20,10 @@
 #include "helper.h"
 #include "sysemu/kvm.h"
 #include "kvm_ppc.h"
+#include "mmu-hash64.h"
 
 //#define DEBUG_MMU
 //#define DEBUG_BATS
-//#define DEBUG_SLB
 //#define DEBUG_SOFTWARE_TLB
 //#define DUMP_PAGE_TABLES
 //#define DEBUG_SOFTWARE_TLB
@@ -49,12 +49,6 @@
 #  define LOG_BATS(...) do { } while (0)
 #endif
 
-#ifdef DEBUG_SLB
-#  define LOG_SLB(...) qemu_log(__VA_ARGS__)
-#else
-#  define LOG_SLB(...) do { } while (0)
-#endif
-
 /*****************************************************************************/
 /* PowerPC MMU emulation */
 #if defined(CONFIG_USER_ONLY)
@@ -677,137 +671,6 @@ static inline int find_pte(CPUPPCState *env, mmu_ctx_t *ctx, int h, int rw,
     return find_pte2(env, ctx, 0, h, rw, type, target_page_bits);
 }
 
-#if defined(TARGET_PPC64)
-static inline ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr)
-{
-    uint64_t esid_256M, esid_1T;
-    int n;
-
-    LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
-
-    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);
-        /* 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;
-        }
-    }
-
-    return NULL;
-}
-
-/*****************************************************************************/
-/* SPR accesses */
-
-void helper_slbia(CPUPPCState *env)
-{
-    int n, do_invalidate;
-
-    do_invalidate = 0;
-    /* XXX: Warning: slbia never invalidates the first segment */
-    for (n = 1; n < env->slb_nr; n++) {
-        ppc_slb_t *slb = &env->slb[n];
-
-        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
-             */
-            do_invalidate = 1;
-        }
-    }
-    if (do_invalidate) {
-        tlb_flush(env, 1);
-    }
-}
-
-void helper_slbie(CPUPPCState *env, target_ulong addr)
-{
-    ppc_slb_t *slb;
-
-    slb = slb_lookup(env, addr);
-    if (!slb) {
-        return;
-    }
-
-    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
-         */
-        tlb_flush(env, 1);
-    }
-}
-
-int ppc_store_slb(CPUPPCState *env, target_ulong rb, target_ulong rs)
-{
-    int slot = rb & 0xfff;
-    ppc_slb_t *slb = &env->slb[slot];
-
-    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 */
-    }
-
-    /* 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
-            " %016" PRIx64 "\n", __func__, slot, rb, rs,
-            slb->esid, slb->vsid);
-
-    return 0;
-}
-
-static 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;
-}
-
-static 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 */
 static inline int get_segment(CPUPPCState *env, mmu_ctx_t *ctx,
                               target_ulong eaddr, int rw, int type)
@@ -1304,7 +1167,7 @@ static hwaddr booke206_tlb_to_page_size(CPUPPCState *env,
 /* TLB check function for MAS based SoftTLBs */
 static int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
                             hwaddr *raddrp,
-                            target_ulong address, uint32_t pid)
+                     target_ulong address, uint32_t pid)
 {
     target_ulong mask;
     uint32_t tlb_pid;
@@ -1590,28 +1453,6 @@ static void mmubooke206_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
     }
 }
 
-#if defined(TARGET_PPC64)
-static void mmubooks_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
-                              CPUPPCState *env)
-{
-    int i;
-    uint64_t slbe, slbv;
-
-    cpu_synchronize_state(env);
-
-    cpu_fprintf(f, "SLB\tESID\t\t\tVSID\n");
-    for (i = 0; i < env->slb_nr; i++) {
-        slbe = env->slb[i].esid;
-        slbv = env->slb[i].vsid;
-        if (slbe == 0 && slbv == 0) {
-            continue;
-        }
-        cpu_fprintf(f, "%d\t0x%016" PRIx64 "\t0x%016" PRIx64 "\n",
-                    i, slbe, slbv);
-    }
-}
-#endif
-
 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env)
 {
     switch (env->mmu_model) {
@@ -1625,7 +1466,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env)
     case POWERPC_MMU_64B:
     case POWERPC_MMU_2_06:
     case POWERPC_MMU_2_06d:
-        mmubooks_dump_mmu(f, cpu_fprintf, env);
+        dump_slb(f, cpu_fprintf, env);
         break;
 #endif
     default:
@@ -2473,39 +2314,6 @@ void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
 #endif /* !defined(CONFIG_USER_ONLY) */
 
 #if !defined(CONFIG_USER_ONLY)
-/* SLB management */
-#if defined(TARGET_PPC64)
-void helper_store_slb(CPUPPCState *env, target_ulong rb, target_ulong rs)
-{
-    if (ppc_store_slb(env, rb, rs) < 0) {
-        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-                                   POWERPC_EXCP_INVAL);
-    }
-}
-
-target_ulong helper_load_slb_esid(CPUPPCState *env, target_ulong rb)
-{
-    target_ulong rt = 0;
-
-    if (ppc_load_slb_esid(env, rb, &rt) < 0) {
-        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-                                   POWERPC_EXCP_INVAL);
-    }
-    return rt;
-}
-
-target_ulong helper_load_slb_vsid(CPUPPCState *env, target_ulong rb)
-{
-    target_ulong rt = 0;
-
-    if (ppc_load_slb_vsid(env, rb, &rt) < 0) {
-        helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
-                                   POWERPC_EXCP_INVAL);
-    }
-    return rt;
-}
-#endif /* defined(TARGET_PPC64) */
-
 /* TLB management */
 void helper_tlbia(CPUPPCState *env)
 {
commit 8152ceaf6eea6d63f6ee65eb419fff56bb3b987b
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:05 2013 +0000

    target-ppc: Remove address check for logging
    
    One LOG_MMU statement in mmu_helper.c has an odd check on the effective
    address being translated.  I can see no reason for this; I suspect it was
    a debugging hack from long ago.  This patch removes it.
    
    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/mmu_helper.c b/target-ppc/mmu_helper.c
index 3570e91..f1de84c 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -906,12 +906,10 @@ static inline int get_segment(CPUPPCState *env, mmu_ctx_t *ctx,
                 ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
                 if (ret < 0) {
                     /* Secondary table lookup */
-                    if (eaddr != 0xEFFFFFFF) {
-                        LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
-                                " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
-                                " hash=" TARGET_FMT_plx "\n", env->htab_base,
-                                env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
-                    }
+                    LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
+                            " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
+                            " hash=" TARGET_FMT_plx "\n", env->htab_base,
+                            env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
                     ret2 = find_pte(env, ctx, 1, rw, type,
                                     target_page_bits);
                     if (ret2 != -1) {
commit 213c718080f51aa4f054a79c0c5743e0e2c15f67
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:04 2013 +0000

    target-ppc: Trivial cleanups in mmu_helper.c
    
    This removes the never-used pte64_invalidate() function, and makes
    ppcmas_tlb_check() static, since it's only used within that file.
    
    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/cpu.h b/target-ppc/cpu.h
index c8b6fc4..83b41f3 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1167,9 +1167,6 @@ void store_40x_dbcr0 (CPUPPCState *env, uint32_t val);
 void store_40x_sler (CPUPPCState *env, uint32_t val);
 void store_booke_tcr (CPUPPCState *env, target_ulong val);
 void store_booke_tsr (CPUPPCState *env, target_ulong val);
-int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
-                     hwaddr *raddrp, target_ulong address,
-                     uint32_t pid);
 void ppc_tlb_invalidate_all (CPUPPCState *env);
 void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr);
 #endif
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 2f01b31..3570e91 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -98,11 +98,6 @@ static inline int pte64_is_valid(target_ulong pte0)
 {
     return pte0 & 0x0000000000000001ULL ? 1 : 0;
 }
-
-static inline void pte64_invalidate(target_ulong *pte0)
-{
-    *pte0 &= ~0x0000000000000001ULL;
-}
 #endif
 
 #define PTE_PTEM_MASK 0x7FFFFFBF
@@ -1309,9 +1304,9 @@ static hwaddr booke206_tlb_to_page_size(CPUPPCState *env,
 }
 
 /* TLB check function for MAS based SoftTLBs */
-int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
-                     hwaddr *raddrp,
-                     target_ulong address, uint32_t pid)
+static int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
+                            hwaddr *raddrp,
+                            target_ulong address, uint32_t pid)
 {
     target_ulong mask;
     uint32_t tlb_pid;
commit 9baea4a303323932ec913728173ea38a4af05f3e
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 00:31:03 2013 +0000

    target-ppc: Remove vestigial PowerPC 620 support
    
    The PowerPC 620 was the very first 64-bit PowerPC implementation, but
    hardly anyone ever actually used the chips.  qemu notionally supports the
    620, but since we don't actually have code to implement the segment table,
    the support is broken (quite likely in other ways too).
    
    This patch, therefore, removes all remaining pieces of 620 support, to
    stop it cluttering up the platforms we actually care about.  This includes
    removing support for the ASR register, used only on segment table based
    machines.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/monitor.c b/monitor.c
index 680d344..881589b 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2960,10 +2960,6 @@ static const MonitorDef monitor_defs[] = {
     { "xer", 0, &monitor_get_xer, },
     { "tbu", 0, &monitor_get_tbu, },
     { "tbl", 0, &monitor_get_tbl, },
-#if defined(TARGET_PPC64)
-    /* Address space register */
-    { "asr", offsetof(CPUPPCState, asr) },
-#endif
     /* Segment registers */
     { "sdr1", offsetof(CPUPPCState, spr[SPR_SDR1]) },
     { "sr0", offsetof(CPUPPCState, sr[0]) },
diff --git a/target-ppc/cpu-models.c b/target-ppc/cpu-models.c
index 20ca84e..17f56b7 100644
--- a/target-ppc/cpu-models.c
+++ b/target-ppc/cpu-models.c
@@ -1101,9 +1101,9 @@
                 "PowerPC 7457A v1.2 (G4)")
     /* 64 bits PowerPC                                                       */
 #if defined (TARGET_PPC64)
+#if defined(TODO)
     POWERPC_DEF("620",           CPU_POWERPC_620,                    620,
                 "PowerPC 620")
-#if defined(TODO)
     POWERPC_DEF("630",           CPU_POWERPC_630,                    630,
                 "PowerPC 630 (POWER3)")
 #endif
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 9b9c784..c8b6fc4 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -115,8 +115,6 @@ enum powerpc_mmu_t {
 #define POWERPC_MMU_1TSEG    0x00020000
     /* 64 bits PowerPC MMU                                     */
     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,
     /* Architecture 2.06 "degraded" (no 1T segments)           */
@@ -965,8 +963,6 @@ struct CPUPPCState {
     /* MMU context - only relevant for full system emulation */
 #if !defined(CONFIG_USER_ONLY)
 #if defined(TARGET_PPC64)
-    /* Address space register */
-    target_ulong asr;
     /* PowerPC 64 SLB area */
     ppc_slb_t slb[64];
     int slb_nr;
@@ -1138,7 +1134,6 @@ void ppc_hw_interrupt (CPUPPCState *env);
 #if !defined(CONFIG_USER_ONLY)
 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
 #if defined(TARGET_PPC64)
-void ppc_store_asr (CPUPPCState *env, target_ulong value);
 int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
 #endif /* defined(TARGET_PPC64) */
 #endif /* !defined(CONFIG_USER_ONLY) */
@@ -1491,11 +1486,9 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
 #define SPR_RCPU_MI_RBA2      (0x302)
 #define SPR_MPC_MI_AP         (0x302)
 #define SPR_PERF3             (0x303)
-#define SPR_620_PMC1R         (0x303)
 #define SPR_RCPU_MI_RBA3      (0x303)
 #define SPR_MPC_MI_EPN        (0x303)
 #define SPR_PERF4             (0x304)
-#define SPR_620_PMC2R         (0x304)
 #define SPR_PERF5             (0x305)
 #define SPR_MPC_MI_TWC        (0x305)
 #define SPR_PERF6             (0x306)
@@ -1511,7 +1504,6 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
 #define SPR_RCPU_L2U_RBA2     (0x30A)
 #define SPR_MPC_MD_AP         (0x30A)
 #define SPR_PERFB             (0x30B)
-#define SPR_620_MMCR0R        (0x30B)
 #define SPR_RCPU_L2U_RBA3     (0x30B)
 #define SPR_MPC_MD_EPN        (0x30B)
 #define SPR_PERFC             (0x30C)
@@ -1526,9 +1518,7 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
 #define SPR_UPERF1            (0x311)
 #define SPR_UPERF2            (0x312)
 #define SPR_UPERF3            (0x313)
-#define SPR_620_PMC1W         (0x313)
 #define SPR_UPERF4            (0x314)
-#define SPR_620_PMC2W         (0x314)
 #define SPR_UPERF5            (0x315)
 #define SPR_UPERF6            (0x316)
 #define SPR_UPERF7            (0x317)
@@ -1536,7 +1526,6 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
 #define SPR_UPERF9            (0x319)
 #define SPR_UPERFA            (0x31A)
 #define SPR_UPERFB            (0x31B)
-#define SPR_620_MMCR0W        (0x31B)
 #define SPR_UPERFC            (0x31C)
 #define SPR_UPERFD            (0x31D)
 #define SPR_UPERFE            (0x31E)
@@ -1608,49 +1597,33 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
 #define SPR_USDA              (0x3AF)
 #define SPR_40x_ZPR           (0x3B0)
 #define SPR_BOOKE_MAS7        (0x3B0)
-#define SPR_620_PMR0          (0x3B0)
 #define SPR_MMCR2             (0x3B0)
 #define SPR_PMC5              (0x3B1)
 #define SPR_40x_PID           (0x3B1)
-#define SPR_620_PMR1          (0x3B1)
 #define SPR_PMC6              (0x3B2)
 #define SPR_440_MMUCR         (0x3B2)
-#define SPR_620_PMR2          (0x3B2)
 #define SPR_4xx_CCR0          (0x3B3)
 #define SPR_BOOKE_EPLC        (0x3B3)
-#define SPR_620_PMR3          (0x3B3)
 #define SPR_405_IAC3          (0x3B4)
 #define SPR_BOOKE_EPSC        (0x3B4)
-#define SPR_620_PMR4          (0x3B4)
 #define SPR_405_IAC4          (0x3B5)
-#define SPR_620_PMR5          (0x3B5)
 #define SPR_405_DVC1          (0x3B6)
-#define SPR_620_PMR6          (0x3B6)
 #define SPR_405_DVC2          (0x3B7)
-#define SPR_620_PMR7          (0x3B7)
 #define SPR_BAMR              (0x3B7)
 #define SPR_MMCR0             (0x3B8)
-#define SPR_620_PMR8          (0x3B8)
 #define SPR_PMC1              (0x3B9)
 #define SPR_40x_SGR           (0x3B9)
-#define SPR_620_PMR9          (0x3B9)
 #define SPR_PMC2              (0x3BA)
 #define SPR_40x_DCWR          (0x3BA)
-#define SPR_620_PMRA          (0x3BA)
 #define SPR_SIAR              (0x3BB)
 #define SPR_405_SLER          (0x3BB)
-#define SPR_620_PMRB          (0x3BB)
 #define SPR_MMCR1             (0x3BC)
 #define SPR_405_SU0R          (0x3BC)
-#define SPR_620_PMRC          (0x3BC)
 #define SPR_401_SKR           (0x3BC)
 #define SPR_PMC3              (0x3BD)
 #define SPR_405_DBCR1         (0x3BD)
-#define SPR_620_PMRD          (0x3BD)
 #define SPR_PMC4              (0x3BE)
-#define SPR_620_PMRE          (0x3BE)
 #define SPR_SDA               (0x3BF)
-#define SPR_620_PMRF          (0x3BF)
 #define SPR_403_VTBL          (0x3CC)
 #define SPR_403_VTBU          (0x3CD)
 #define SPR_DMISS             (0x3D0)
@@ -1718,15 +1691,12 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
 #define SPR_LDSTCR            (0x3F8)
 #define SPR_L2PMCR            (0x3F8)
 #define SPR_750FX_HID2        (0x3F8)
-#define SPR_620_BUSCSR        (0x3F8)
 #define SPR_Exxx_L1FINV0      (0x3F8)
 #define SPR_L2CR              (0x3F9)
-#define SPR_620_L2CR          (0x3F9)
 #define SPR_L3CR              (0x3FA)
 #define SPR_750_TDCH          (0x3FA)
 #define SPR_IABR2             (0x3FA)
 #define SPR_40x_DCCR          (0x3FA)
-#define SPR_620_L2SR          (0x3FA)
 #define SPR_ICTC              (0x3FB)
 #define SPR_40x_ICCR          (0x3FB)
 #define SPR_THRM1             (0x3FC)
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index fcf372a..d33ee66 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -382,7 +382,6 @@ DEF_HELPER_1(load_601_rtcl, tl, env)
 DEF_HELPER_1(load_601_rtcu, tl, env)
 #if !defined(CONFIG_USER_ONLY)
 #if defined(TARGET_PPC64)
-DEF_HELPER_2(store_asr, void, env, tl)
 DEF_HELPER_1(load_purr, tl, env)
 #endif
 DEF_HELPER_2(store_sdr1, void, env, tl)
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index 708a840..235b0d5 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -37,7 +37,7 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_be32s(f, &fpscr);
     qemu_put_sbe32s(f, &env->access_type);
 #if defined(TARGET_PPC64)
-    qemu_put_betls(f, &env->asr);
+    qemu_put_betls(f, &env->spr[SPR_ASR]);
     qemu_put_sbe32s(f, &env->slb_nr);
 #endif
     qemu_put_betls(f, &env->spr[SPR_SDR1]);
@@ -125,7 +125,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     env->fpscr = fpscr;
     qemu_get_sbe32s(f, &env->access_type);
 #if defined(TARGET_PPC64)
-    qemu_get_betls(f, &env->asr);
+    qemu_get_betls(f, &env->spr[SPR_ASR]);
     qemu_get_sbe32s(f, &env->slb_nr);
 #endif
     qemu_get_betls(f, &sdr1);
diff --git a/target-ppc/misc_helper.c b/target-ppc/misc_helper.c
index 26edcca..616aab6 100644
--- a/target-ppc/misc_helper.c
+++ b/target-ppc/misc_helper.c
@@ -35,12 +35,6 @@ void helper_store_dump_spr(CPUPPCState *env, uint32_t sprn)
              env->spr[sprn]);
 }
 #if !defined(CONFIG_USER_ONLY)
-#if defined(TARGET_PPC64)
-void helper_store_asr(CPUPPCState *env, target_ulong val)
-{
-    ppc_store_asr(env, val);
-}
-#endif
 
 void helper_store_sdr1(CPUPPCState *env, target_ulong val)
 {
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 1cc1c16..2f01b31 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -1659,7 +1659,6 @@ static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx,
         ctx->prot |= PAGE_WRITE;
         break;
 #if defined(TARGET_PPC64)
-    case POWERPC_MMU_620:
     case POWERPC_MMU_64B:
     case POWERPC_MMU_2_06:
     case POWERPC_MMU_2_06d:
@@ -1741,7 +1740,6 @@ static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
                 ret = get_bat(env, ctx, eaddr, rw, access_type);
             }
 #if defined(TARGET_PPC64)
-        case POWERPC_MMU_620:
         case POWERPC_MMU_64B:
         case POWERPC_MMU_2_06:
         case POWERPC_MMU_2_06d:
@@ -1883,7 +1881,6 @@ int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                 case POWERPC_MMU_32B:
                 case POWERPC_MMU_601:
 #if defined(TARGET_PPC64)
-                case POWERPC_MMU_620:
                 case POWERPC_MMU_64B:
                 case POWERPC_MMU_2_06:
                 case POWERPC_MMU_2_06d:
@@ -1935,14 +1932,8 @@ int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
 #if defined(TARGET_PPC64)
             case -5:
                 /* No match in segment table */
-                if (env->mmu_model == POWERPC_MMU_620) {
-                    env->exception_index = POWERPC_EXCP_ISI;
-                    /* XXX: this might be incorrect */
-                    env->error_code = 0x40000000;
-                } else {
-                    env->exception_index = POWERPC_EXCP_ISEG;
-                    env->error_code = 0;
-                }
+                env->exception_index = POWERPC_EXCP_ISEG;
+                env->error_code = 0;
                 break;
 #endif
             }
@@ -1995,7 +1986,6 @@ int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
                 case POWERPC_MMU_32B:
                 case POWERPC_MMU_601:
 #if defined(TARGET_PPC64)
-                case POWERPC_MMU_620:
                 case POWERPC_MMU_64B:
                 case POWERPC_MMU_2_06:
                 case POWERPC_MMU_2_06d:
@@ -2097,21 +2087,9 @@ int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
 #if defined(TARGET_PPC64)
             case -5:
                 /* No match in segment table */
-                if (env->mmu_model == POWERPC_MMU_620) {
-                    env->exception_index = POWERPC_EXCP_DSI;
-                    env->error_code = 0;
-                    env->spr[SPR_DAR] = address;
-                    /* XXX: this might be incorrect */
-                    if (rw == 1) {
-                        env->spr[SPR_DSISR] = 0x42000000;
-                    } else {
-                        env->spr[SPR_DSISR] = 0x40000000;
-                    }
-                } else {
-                    env->exception_index = POWERPC_EXCP_DSEG;
-                    env->error_code = 0;
-                    env->spr[SPR_DAR] = address;
-                }
+                env->exception_index = POWERPC_EXCP_DSEG;
+                env->error_code = 0;
+                env->spr[SPR_DAR] = address;
                 break;
 #endif
             }
@@ -2326,7 +2304,6 @@ void ppc_tlb_invalidate_all(CPUPPCState *env)
     case POWERPC_MMU_32B:
     case POWERPC_MMU_601:
 #if defined(TARGET_PPC64)
-    case POWERPC_MMU_620:
     case POWERPC_MMU_64B:
     case POWERPC_MMU_2_06:
     case POWERPC_MMU_2_06d:
@@ -2396,7 +2373,6 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
         tlb_flush_page(env, addr | (0xF << 28));
         break;
 #if defined(TARGET_PPC64)
-    case POWERPC_MMU_620:
     case POWERPC_MMU_64B:
     case POWERPC_MMU_2_06:
     case POWERPC_MMU_2_06d:
@@ -2420,16 +2396,6 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
 
 /*****************************************************************************/
 /* Special registers manipulation */
-#if defined(TARGET_PPC64)
-void ppc_store_asr(CPUPPCState *env, target_ulong value)
-{
-    if (env->asr != value) {
-        env->asr = value;
-        tlb_flush(env, 1);
-    }
-}
-#endif
-
 void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
 {
     LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 380a884..bb690f8 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9428,7 +9428,6 @@ void cpu_dump_state (CPUPPCState *env, FILE *f, fprintf_function cpu_fprintf,
     case POWERPC_MMU_SOFT_6xx:
     case POWERPC_MMU_SOFT_74xx:
 #if defined(TARGET_PPC64)
-    case POWERPC_MMU_620:
     case POWERPC_MMU_64B:
 #endif
         cpu_fprintf(f, " SDR1 " TARGET_FMT_lx "\n", env->spr[SPR_SDR1]);
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index bd5033c..09fb29e 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -365,7 +365,6 @@ static void spr_write_sdr1 (void *opaque, int sprn, int gprn)
 }
 
 /* 64 bits PowerPC specific SPRs */
-/* ASR */
 #if defined(TARGET_PPC64)
 static void spr_read_hior (void *opaque, int gprn, int sprn)
 {
@@ -379,16 +378,6 @@ static void spr_write_hior (void *opaque, int sprn, int gprn)
     tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, excp_prefix));
     tcg_temp_free(t0);
 }
-
-static void spr_read_asr (void *opaque, int gprn, int sprn)
-{
-    tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, asr));
-}
-
-static void spr_write_asr (void *opaque, int sprn, int gprn)
-{
-    gen_helper_store_asr(cpu_env, cpu_gpr[gprn]);
-}
 #endif
 #endif
 
@@ -2151,173 +2140,6 @@ static void gen_spr_compress (CPUPPCState *env)
                  0x00000000);
 }
 
-#if defined (TARGET_PPC64)
-/* SPR specific to PowerPC 620 */
-static void gen_spr_620 (CPUPPCState *env)
-{
-    /* Processor identification */
-    spr_register(env, SPR_PIR, "PIR",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_pir,
-                 0x00000000);
-    spr_register(env, SPR_ASR, "ASR",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_asr, &spr_write_asr,
-                 0x00000000);
-    /* Breakpoints */
-    /* XXX : not implemented */
-    spr_register(env, SPR_IABR, "IABR",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_DABR, "DABR",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_SIAR, "SIAR",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, SPR_NOACCESS,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_SDA, "SDA",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, SPR_NOACCESS,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMC1R, "PMC1",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, SPR_NOACCESS,
-                 0x00000000);
-    spr_register(env, SPR_620_PMC1W, "PMC1",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                  SPR_NOACCESS, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMC2R, "PMC2",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, SPR_NOACCESS,
-                 0x00000000);
-    spr_register(env, SPR_620_PMC2W, "PMC2",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                  SPR_NOACCESS, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_MMCR0R, "MMCR0",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, SPR_NOACCESS,
-                 0x00000000);
-    spr_register(env, SPR_620_MMCR0W, "MMCR0",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                  SPR_NOACCESS, &spr_write_generic,
-                 0x00000000);
-    /* External access control */
-    /* XXX : not implemented */
-    spr_register(env, SPR_EAR, "EAR",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-#if 0 // XXX: check this
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMR0, "PMR0",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMR1, "PMR1",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMR2, "PMR2",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMR3, "PMR3",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMR4, "PMR4",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMR5, "PMR5",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMR6, "PMR6",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMR7, "PMR7",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMR8, "PMR8",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMR9, "PMR9",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMRA, "PMR10",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMRB, "PMR11",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMRC, "PMR12",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMRD, "PMR13",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMRE, "PMR14",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_PMRF, "PMR15",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-#endif
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_BUSCSR, "BUSCSR",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_L2CR, "L2CR",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* XXX : not implemented */
-    spr_register(env, SPR_620_L2SR, "L2SR",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-}
-#endif /* defined (TARGET_PPC64) */
-
 static void gen_spr_5xx_8xx (CPUPPCState *env)
 {
     /* Exception processing */
@@ -2993,31 +2815,6 @@ static void init_excp_604 (CPUPPCState *env)
 #endif
 }
 
-#if defined(TARGET_PPC64)
-static void init_excp_620 (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_ISI]      = 0x00000400;
-    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_SYSCALL]  = 0x00000C00;
-    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
-    env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
-    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
-    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
-    env->hreset_excp_prefix = 0xFFF00000UL;
-    /* Hardware reset vector */
-    env->hreset_vector = 0x0000000000000100ULL;
-#endif
-}
-#endif /* defined(TARGET_PPC64) */
-
 static void init_excp_7x0 (CPUPPCState *env)
 {
 #if !defined(CONFIG_USER_ONLY)
@@ -7129,55 +6926,6 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
                  POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR;
 }
-
-static void init_proc_620 (CPUPPCState *env)
-{
-    gen_spr_ne_601(env);
-    gen_spr_620(env);
-    /* Time base */
-    gen_tbl(env);
-    /* Hardware implementation registers */
-    /* XXX : not implemented */
-    spr_register(env, SPR_HID0, "HID0",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    /* Memory management */
-    gen_low_BATs(env);
-    init_excp_620(env);
-    env->dcache_line_size = 64;
-    env->icache_line_size = 64;
-    /* Allocate hardware IRQ controller */
-    ppc6xx_irq_init(env);
-}
-
-POWERPC_FAMILY(620)(ObjectClass *oc, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(oc);
-    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
-
-    dc->desc = "PowerPC 620";
-    pcc->init_proc = init_proc_620;
-    pcc->check_pow = check_pow_nocheck; /* Check this */
-    pcc->insns_flags = 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_DCBZ |
-                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
-                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
-                       PPC_SEGMENT | PPC_EXTERN |
-                       PPC_64B | PPC_SLBI;
-    pcc->insns_flags2 = PPC_NONE;
-    pcc->msr_mask = 0x800000000005FF77ULL;
-    pcc->mmu_model = POWERPC_MMU_620;
-    pcc->excp_model = POWERPC_EXCP_970;
-    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
-    pcc->bfd_mach = bfd_mach_ppc64;
-    pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
-                 POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
-}
-
 #endif /* defined (TARGET_PPC64) */
 
 
@@ -7915,9 +7663,6 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp)
         case POWERPC_MMU_64B:
             mmu_model = "PowerPC 64";
             break;
-        case POWERPC_MMU_620:
-            mmu_model = "PowerPC 620";
-            break;
 #endif
         default:
             mmu_model = "Unknown or invalid";
commit d6478bc7e92db4669fac701d7bb8c51756b61d8a
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Tue Mar 19 07:41:53 2013 +0000

    PPC/GDB: handle read and write of fpscr
    
    Although the support of this register may be uncomplete, there are no
    reason to prevent the debugger from reading or writing it.
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/gdbstub.c b/gdbstub.c
index 43b7d4d..5167c64 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -781,7 +781,8 @@ static int cpu_gdb_write_register(CPUPPCState *env, uint8_t *mem_buf, int n)
             /* fpscr */
             if (gdb_has_xml)
                 return 0;
-            return 4;
+            store_fpscr(env, ldtul_p(mem_buf), 0xffffffff);
+            return sizeof(target_ulong);
         }
     }
     return 0;
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 6886666..9b9c784 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1180,6 +1180,8 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr);
 #endif
 #endif
 
+void store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask);
+
 static inline uint64_t ppc_dump_gpr(CPUPPCState *env, int gprn)
 {
     uint64_t gprv;
diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c
index 9d67926..9e779ea 100644
--- a/target-ppc/fpu_helper.c
+++ b/target-ppc/fpu_helper.c
@@ -463,6 +463,11 @@ void helper_store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask)
     fpscr_set_rounding_mode(env);
 }
 
+void store_fpscr(CPUPPCState *env, uint64_t arg, uint32_t mask)
+{
+    helper_store_fpscr(env, arg, mask);
+}
+
 void helper_float_check_status(CPUPPCState *env)
 {
     if (env->exception_index == POWERPC_EXCP_PROGRAM &&
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 15eebe9..bd5033c 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7693,7 +7693,7 @@ static int gdb_set_float_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
         return 8;
     }
     if (n == 32) {
-        /* FPSCR not implemented  */
+        helper_store_fpscr(env, ldl_p(mem_buf), 0xffffffff);
         return 4;
     }
     return 0;
commit 7b5651605836fd29572fd4c8769af5378d351712
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Wed Mar 13 15:53:28 2013 +0000

    pseries: Move XICS initialization before cpu initialization
    
    Currently, the pseries machine initializes the cpus, then the XICS
    interrupt controller.  However, to support the upcoming in-kernel XICS
    implementation we will need to initialize the irq controller before the
    vcpus.  This patch makes the necesssary rearrangement.  This means the
    xics init code can no longer auto-detect the number of cpus ("interrupt
    servers" in XICS terminology) and so we must pass that in explicitly from
    the platform code.
    
    Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
    Signed-off-by: Ben Herrenschmidt <benh at kernel.crashing.org>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 74ae83b..7b2a11f 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -779,6 +779,11 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
         spapr->htab_shift++;
     }
 
+    /* Set up Interrupt Controller before we create the VCPUs */
+    spapr->icp = xics_system_init(smp_cpus * kvmppc_smt_threads() / smp_threads,
+                                  XICS_IRQS);
+    spapr->next_irq = XICS_IRQ_BASE;
+
     /* init CPUs */
     if (cpu_model == NULL) {
         cpu_model = kvm_enabled() ? "host" : "POWER7";
@@ -791,6 +796,8 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
         }
         env = &cpu->env;
 
+        xics_cpu_setup(spapr->icp, cpu);
+
         /* Set time-base frequency to 512 MHz */
         cpu_ppc_tb_init(env, TIMEBASE_FREQ);
 
@@ -830,11 +837,6 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
     }
     g_free(filename);
 
-
-    /* Set up Interrupt Controller */
-    spapr->icp = xics_system_init(XICS_IRQS);
-    spapr->next_irq = XICS_IRQ_BASE;
-
     /* Set up EPOW events infrastructure */
     spapr_events_init(spapr);
 
diff --git a/hw/ppc/xics.c b/hw/ppc/xics.c
index c3ef12f..374da5b 100644
--- a/hw/ppc/xics.c
+++ b/hw/ppc/xics.c
@@ -521,45 +521,38 @@ static void xics_reset(void *opaque)
     }
 }
 
-struct icp_state *xics_system_init(int nr_irqs)
+void xics_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu)
 {
-    CPUPPCState *env;
-    CPUState *cpu;
-    int max_server_num;
-    struct icp_state *icp;
-    struct ics_state *ics;
+    CPUState *cs = CPU(cpu);
+    CPUPPCState *env = &cpu->env;
+    struct icp_server_state *ss = &icp->ss[cs->cpu_index];
 
-    max_server_num = -1;
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu = CPU(ppc_env_get_cpu(env));
-        if (cpu->cpu_index > max_server_num) {
-            max_server_num = cpu->cpu_index;
-        }
-    }
+    assert(cs->cpu_index < icp->nr_servers);
 
-    icp = g_malloc0(sizeof(*icp));
-    icp->nr_servers = max_server_num + 1;
-    icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state));
+    switch (PPC_INPUT(env)) {
+    case PPC_FLAGS_INPUT_POWER7:
+        ss->output = env->irq_inputs[POWER7_INPUT_INT];
+        break;
 
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu = CPU(ppc_env_get_cpu(env));
-        struct icp_server_state *ss = &icp->ss[cpu->cpu_index];
+    case PPC_FLAGS_INPUT_970:
+        ss->output = env->irq_inputs[PPC970_INPUT_INT];
+        break;
 
-        switch (PPC_INPUT(env)) {
-        case PPC_FLAGS_INPUT_POWER7:
-            ss->output = env->irq_inputs[POWER7_INPUT_INT];
-            break;
+    default:
+        fprintf(stderr, "XICS interrupt controller does not support this CPU "
+                "bus model\n");
+        abort();
+    }
+}
 
-        case PPC_FLAGS_INPUT_970:
-            ss->output = env->irq_inputs[PPC970_INPUT_INT];
-            break;
+struct icp_state *xics_system_init(int nr_servers, int nr_irqs)
+{
+    struct icp_state *icp;
+    struct ics_state *ics;
 
-        default:
-            hw_error("XICS interrupt model does not support this CPU bus "
-                     "model\n");
-            exit(1);
-        }
-    }
+    icp = g_malloc0(sizeof(*icp));
+    icp->nr_servers = nr_servers;
+    icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state));
 
     ics = g_malloc0(sizeof(*ics));
     ics->nr_irqs = nr_irqs;
diff --git a/hw/xics.h b/hw/xics.h
index c3bf008..6bce042 100644
--- a/hw/xics.h
+++ b/hw/xics.h
@@ -35,6 +35,7 @@ struct icp_state;
 qemu_irq xics_get_qirq(struct icp_state *icp, int irq);
 void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi);
 
-struct icp_state *xics_system_init(int nr_irqs);
+struct icp_state *xics_system_init(int nr_servers, int nr_irqs);
+void xics_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu);
 
 #endif /* __XICS_H__ */
commit c6304a4a6822f0e3e45c94b89d4e328057355683
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Wed Mar 13 15:53:27 2013 +0000

    target-ppc: Remove CONFIG_PSERIES dependency in kvm.c
    
    target-ppc/kvm.c has an #ifdef on CONFIG_PSERIES, for the handling of
    KVM exits due to a PAPR hypercall from the guest.  However, since commit
    e4c8b28cde12d01ada8fe869567dc5717a2dfcb7 "ppc: express FDT dependency of
    pSeries and e500 boards via default-configs/", this hasn't worked properly.
    That patch altered the configuration setup so that although CONFIG_PSERIES
    is visible from the Makefiles, it is not visible from C files.  This broke
    the pseries machine when KVM is in use.
    
    This patch makes a quick and dirty fix, by removing the CONFIG_PSERIES
    dependency, replacing it with TARGET_PPC64 (since removing it entirely
    leads to type mismatch errors).  Technically this breaks the build when
    configured with --disable-fdt, since that disables CONFIG_PSERIES on
    TARGET_PPC64.  However, it turns out the build was already broken in that
    case, so this fixes pseries kvm without breaking anything extra.  I'm
    looking into how to fix that build breakage, but I don't think that need
    delay applying this patch.
    
    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.c b/target-ppc/kvm.c
index e663ff0..9870d60 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1077,7 +1077,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
         dprintf("handle halt\n");
         ret = kvmppc_handle_halt(cpu);
         break;
-#ifdef CONFIG_PSERIES
+#if defined(TARGET_PPC64)
     case KVM_EXIT_PAPR_HCALL:
         dprintf("handle PAPR hypercall\n");
         run->papr_hcall.ret = spapr_hypercall(cpu,
commit 89dfd6e1b3c0b31ef700203808be2a9a71947d1d
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Wed Mar 13 15:53:25 2013 +0000

    pseries: Remove "busname" property for PCI host bridge
    
    Currently the "spapr-pci-host-bridge" device has a "busname" property which
    can be used to override the default assignment of qbus names for the bus
    subordinate to the PHB.  We use that for the default primary PCI bus, to
    make libvirt happy, which expects there to be a bus named simply "pci".
    The default qdev core logic would name the bus "pci.0", and the pseries
    code would otherwise name it "pci at 800000020000000" which is the name it
    is given in the device tree based on its BUID.
    
    The "busname" property is rather clunky though, so this patch simplifies
    things by just using a special case hack for the default PHB, setting
    busname to "pci" when index=0.
    
    Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index d45098d..74ae83b 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -856,7 +856,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
     /* Set up PCI */
     spapr_pci_rtas_init();
 
-    phb = spapr_create_phb(spapr, 0, "pci");
+    phb = spapr_create_phb(spapr, 0);
 
     for (i = 0; i < nb_nics; i++) {
         NICInfo *nd = &nd_table[i];
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 36adbc5..42c8b61 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -518,6 +518,7 @@ static int spapr_phb_init(SysBusDevice *s)
 {
     sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
     PCIHostState *phb = PCI_HOST_BRIDGE(s);
+    const char *busname;
     char *namebuf;
     int i;
     PCIBus *bus;
@@ -575,9 +576,6 @@ static int spapr_phb_init(SysBusDevice *s)
     }
 
     sphb->dtbusname = g_strdup_printf("pci@%" PRIx64, sphb->buid);
-    if (!sphb->busname) {
-        sphb->busname = sphb->dtbusname;
-    }
 
     namebuf = alloca(strlen(sphb->dtbusname) + 32);
 
@@ -621,7 +619,26 @@ static int spapr_phb_init(SysBusDevice *s)
                                     &sphb->msiwindow);
     }
 
-    bus = pci_register_bus(DEVICE(s), sphb->busname,
+    /*
+     * Selecting a busname is more complex than you'd think, due to
+     * interacting constraints.  If the user has specified an id
+     * explicitly for the phb , then we want to use the qdev default
+     * of naming the bus based on the bridge device (so the user can
+     * then assign devices to it in the way they expect).  For the
+     * first / default PCI bus (index=0) we want to use just "pci"
+     * because libvirt expects there to be a bus called, simply,
+     * "pci".  Otherwise, we use the same name as in the device tree,
+     * since it's unique by construction, and makes the guest visible
+     * BUID clear.
+     */
+    if (s->qdev.id) {
+        busname = NULL;
+    } else if (sphb->index == 0) {
+        busname = "pci";
+    } else {
+        busname = sphb->dtbusname;
+    }
+    bus = pci_register_bus(DEVICE(s), busname,
                            pci_spapr_set_irq, pci_spapr_map_irq, sphb,
                            &sphb->memspace, &sphb->iospace,
                            PCI_DEVFN(0, 0), PCI_NUM_PINS);
@@ -663,7 +680,6 @@ static void spapr_phb_reset(DeviceState *qdev)
 }
 
 static Property spapr_phb_properties[] = {
-    DEFINE_PROP_STRING("busname", sPAPRPHBState, busname),
     DEFINE_PROP_INT32("index", sPAPRPHBState, index, -1),
     DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, -1),
     DEFINE_PROP_HEX32("liobn", sPAPRPHBState, dma_liobn, -1),
@@ -694,14 +710,12 @@ static const TypeInfo spapr_phb_info = {
     .class_init    = spapr_phb_class_init,
 };
 
-PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index,
-                               const char *busname)
+PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index)
 {
     DeviceState *dev;
 
     dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE);
     qdev_prop_set_uint32(dev, "index", index);
-    qdev_prop_set_string(dev, "busname", busname);
     qdev_init_nofail(dev);
 
     return PCI_HOST_BRIDGE(dev);
diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h
index 8bb3c62..8bd8a66 100644
--- a/hw/spapr_pci.h
+++ b/hw/spapr_pci.h
@@ -39,7 +39,6 @@ typedef struct sPAPRPHBState {
 
     int32_t index;
     uint64_t buid;
-    char *busname;
     char *dtbusname;
 
     MemoryRegion memspace, iospace;
@@ -82,8 +81,7 @@ static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin)
     return xics_get_qirq(spapr->icp, phb->lsi_table[pin].irq);
 }
 
-PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index,
-                               const char *busname);
+PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index);
 
 int spapr_populate_pci_dt(sPAPRPHBState *phb,
                           uint32_t xics_phandle,
commit a4e044c30e0044947fd0d69b1888d916f96bba6b
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Thu Mar 14 17:59:29 2013 +0000

    pseries: Fix breakage in CPU QOM conversion
    
    Commit 259186a7d2f7184efc96ae99bc5658e6159f53ad "cpu: Move halted and
    interrupt_request fields to CPUState" broke the pseries machine.  That's
    because it uses CPU() instead of ENV_GET_CPU() to convert from the global
    first_cpu pointer (still a CPUArchState) to a CPUState.  This patch fixes
    the breakage.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index f355a9b..d45098d 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -629,7 +629,7 @@ static void ppc_spapr_reset(void)
                        spapr->rtas_size);
 
     /* Set up the entry state */
-    first_cpu_cpu = CPU(first_cpu);
+    first_cpu_cpu = ENV_GET_CPU(first_cpu);
     first_cpu->gpr[3] = spapr->fdt_addr;
     first_cpu->gpr[5] = 0;
     first_cpu_cpu->halted = 0;
commit 8b4a89884196aaa9115fee900396498b78245c91
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 19 12:25:43 2013 +0100

    serial: Fix debug format strings
    
    This fixes the build of hw/serial.c with DEBUG_SERIAL enabled.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/serial.c b/hw/serial.c
index 48a5eb6..0ccc499 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -306,7 +306,7 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
     SerialState *s = opaque;
 
     addr &= 7;
-    DPRINTF("write addr=0x%02x val=0x%02x\n", addr, val);
+    DPRINTF("write addr=0x%" HWADDR_PRIx " val=0x%" PRIx64 "\n", addr, val);
     switch(addr) {
     default:
     case 0:
@@ -527,7 +527,7 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size)
         ret = s->scr;
         break;
     }
-    DPRINTF("read addr=0x%02x val=0x%02x\n", addr, ret);
+    DPRINTF("read addr=0x%" HWADDR_PRIx " val=0x%02x\n", addr, ret);
     return ret;
 }
 
commit 085d813407453e498e05c37d988efba8c6f5af0a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Mar 18 17:20:07 2013 +0000

    Fix typos and misspellings
    
    Fix various typos and misspellings. The bulk of these were found with
    codespell.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/docs/usb-storage.txt b/docs/usb-storage.txt
index fa93111..c5a3866 100644
--- a/docs/usb-storage.txt
+++ b/docs/usb-storage.txt
@@ -5,7 +5,7 @@ qemu usb storage emulation
 QEMU has three devices for usb storage emulation.
 
 Number one emulates the classic bulk-only transport protocol which is
-used by 99% of the usb sticks on the marked today and is called
+used by 99% of the usb sticks on the market today and is called
 "usb-storage".  Usage (hooking up to xhci, other host controllers work
 too):
 
@@ -36,7 +36,7 @@ It's called "usb-bot".  It shares most code with "usb-storage", and
 the guest will not be able to see the difference.  The qemu command
 line interface is simliar to usb-uas though, i.e. no automatic scsi
 disk creation.  It also features support for up to 16 LUNs.  The LUN
-numbers must be continous, i.e. for three devices you must use 0+1+2.
+numbers must be continuous, i.e. for three devices you must use 0+1+2.
 The 0+1+5 numbering from the "usb-uas" example isn't going to work
 with "usb-bot".
 
diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index cba7553..7b2b02d 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -14,7 +14,7 @@
 #include "exec/memory.h"
 #include "hw/irq.h"
 
-/* The CPU is also modeled as an interrupt controller.  */
+/* The CPU is also modelled as an interrupt controller.  */
 #define ARM_PIC_CPU_IRQ 0
 #define ARM_PIC_CPU_FIQ 1
 qemu_irq *arm_pic_init_cpu(ARMCPU *cpu);
diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c
index daca1c1..12254b1 100644
--- a/hw/pci/pci_host.c
+++ b/hw/pci/pci_host.c
@@ -38,7 +38,7 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
  * bit  0 -  7: offset in configuration space of a given pci device
  */
 
-/* the helper functio to get a PCIDeice* for a given pci address */
+/* the helper function to get a PCIDevice* for a given pci address */
 static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr)
 {
     uint8_t bus_num = addr >> 16;
diff --git a/hw/sdhci.c b/hw/sdhci.c
index 93feada..4a29e6c 100644
--- a/hw/sdhci.c
+++ b/hw/sdhci.c
@@ -763,7 +763,7 @@ static void sdhci_do_adma(SDHCIState *s)
         }
     }
 
-    /* we have unfinished bussiness - reschedule to continue ADMA */
+    /* we have unfinished business - reschedule to continue ADMA */
     qemu_mod_timer(s->transfer_timer,
                    qemu_get_clock_ns(vm_clock) + SDHC_TRANSFER_DELAY);
 }
diff --git a/include/qom/object.h b/include/qom/object.h
index cf094e7..d0f99c5 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -202,7 +202,7 @@ typedef struct InterfaceInfo InterfaceInfo;
  * Methods are always <emphasis>virtual</emphasis>. Overriding a method in
  * #TypeInfo.class_init of a subclass leads to any user of the class obtained
  * via OBJECT_GET_CLASS() accessing the overridden function.
- * The original function is not automatically invoked. It is the responsability
+ * The original function is not automatically invoked. It is the responsibility
  * of the overriding class to determine whether and when to invoke the method
  * being overridden.
  *
diff --git a/monitor.c b/monitor.c
index 680d344..cfb5d64 100644
--- a/monitor.c
+++ b/monitor.c
@@ -3560,10 +3560,10 @@ static const mon_cmd_t *qmp_find_cmd(const char *cmdname)
  * If @cmdline is blank, return NULL.
  * If it can't be parsed, report to @mon, and return NULL.
  * Else, insert command arguments into @qdict, and return the command.
- * If sub-command table exist, and if @cmdline contains addtional string for
- * sub-command, this function will try search sub-command table. if no
- * addtional string for sub-command exist, this function will return the found
- * one in @table.
+ * If a sub-command table exists, and if @cmdline contains an additional string
+ * for a sub-command, this function will try to search the sub-command table.
+ * If no additional string for a sub-command is present, this function will
+ * return the command found in @table.
  * Do not assume the returned command points into @table!  It doesn't
  * when the command is a sub-command.
  */
diff --git a/net/tap.c b/net/tap.c
index daab350..ce79699 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -696,7 +696,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
     /* QEMU vlans does not support multiqueue tap, in this case peer is set.
      * For -netdev, peer is always NULL. */
     if (peer && (tap->has_queues || tap->has_fds || tap->has_vhostfds)) {
-        error_report("Multiqueue tap cannnot be used with QEMU vlans");
+        error_report("Multiqueue tap cannot be used with QEMU vlans");
         return -1;
     }
 
diff --git a/qemu-options.hx b/qemu-options.hx
index 06dd565..d7afeab 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1123,7 +1123,7 @@ is a TCP port number, not a display number.
 @item websocket
 
 Opens an additional TCP listening port dedicated to VNC Websocket connections.
-By defintion the Websocket port is 5700+ at var{display}. If @var{host} is
+By definition the Websocket port is 5700+ at var{display}. If @var{host} is
 specified connections will only be allowed from this host.
 As an alternative the Websocket port could be specified by using
 @code{websocket}=@var{port}.
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index d7da850..3b5c536 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -120,7 +120,7 @@ void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
         return;
     }
 
-    /* succeded */
+    /* succeeded */
 }
 
 int64_t qmp_guest_get_time(Error **errp)
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 705147a..c9cc2ff 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -4746,7 +4746,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             }
             s->pc++;
 
-            /* 4.1.1-4.1.3: No preceeding lock, 66, f2, f3, or rex prefixes. */
+            /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
             if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
                             | PREFIX_LOCK | PREFIX_DATA)) {
                 goto illegal_op;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 88e481c..a4f2194 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1142,7 +1142,7 @@ struct DisasInsn {
 };
 
 /* ====================================================================== */
-/* Miscelaneous helpers, used by several operations.  */
+/* Miscellaneous helpers, used by several operations.  */
 
 static void help_l2_shift(DisasContext *s, DisasFields *f,
                           DisasOps *o, int mask)
commit a7b66fa7aefb8dce564f0fa665de7965d3007148
Author: Doug Goldstein <cardoe at cardoe.com>
Date:   Sun Mar 17 15:43:26 2013 -0500

    Advertise --libdir in configure --help output
    
    The configure script allows you to supply a libdir via --libdir but was
    not advertising this in --help.
    
    Signed-off-by: Doug Goldstein <cardoe at cardoe.com>
    CC: qemu-trivial at nongnu.org
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/configure b/configure
index 46a7594..497ce29 100755
--- a/configure
+++ b/configure
@@ -1050,6 +1050,7 @@ echo "  --mandir=PATH            install man pages in PATH"
 echo "  --datadir=PATH           install firmware in PATH$confsuffix"
 echo "  --docdir=PATH            install documentation in PATH$confsuffix"
 echo "  --bindir=PATH            install binaries in PATH"
+echo "  --libdir=PATH            install libraries in PATH"
 echo "  --sysconfdir=PATH        install config in PATH$confsuffix"
 echo "  --localstatedir=PATH     install local state in PATH"
 echo "  --with-confsuffix=SUFFIX suffix for QEMU data inside datadir and sysconfdir [$confsuffix]"
commit 2c7cfd65b326fcff9cb0bf53c643768a5f1e6b7a
Author: Hu Tao <hutao at cn.fujitsu.com>
Date:   Fri Mar 15 14:32:01 2013 +0800

    memory: fix a bug of detection of memory region collision
    
    The collision reports before and after this patch are:
    
    before:
    
    warning: subregion collision cfc/4 (pci-conf-data) vs cf8/4 (pci-conf-idx)
    warning: subregion collision 8000000/f8000000 (pci-hole) vs 0/8000000 (ram-below-4g)
    warning: subregion collision 100000000/4000000000000000 (pci-hole64) vs 8000000/f8000000 (pci-hole)
    warning: subregion collision 4d1/1 (kvm-elcr) vs 4d0/1 (kvm-elcr)
    warning: subregion collision fec00000/1000 (kvm-ioapic) vs 8000000/f8000000 (pci-hole)
    warning: subregion collision 80/1 (ioport80) vs 7e/2 (kvmvapic)
    warning: subregion collision fed00000/400 (hpet) vs 8000000/f8000000 (pci-hole)
    warning: subregion collision 81/3 (dma-page) vs 80/1 (ioport80)
    warning: subregion collision 8/8 (dma-cont) vs 0/8 (dma-chan)
    warning: subregion collision d0/10 (dma-cont) vs c0/10 (dma-chan)
    warning: subregion collision 0/80 (ich9-pm) vs 8/8 (dma-cont)
    warning: subregion collision 0/80 (ich9-pm) vs 0/8 (dma-chan)
    warning: subregion collision 0/80 (ich9-pm) vs 64/1 (i8042-cmd)
    warning: subregion collision 0/80 (ich9-pm) vs 60/1 (i8042-data)
    warning: subregion collision 0/80 (ich9-pm) vs 61/1 (elcr)
    warning: subregion collision 0/80 (ich9-pm) vs 40/4 (kvm-pit)
    warning: subregion collision 0/80 (ich9-pm) vs 70/2 (rtc)
    warning: subregion collision 0/80 (ich9-pm) vs 20/2 (kvm-pic)
    warning: subregion collision 0/80 (ich9-pm) vs 7e/2 (kvmvapic)
    warning: subregion collision 4/2 (acpi-cnt) vs 0/4 (acpi-evt)
    warning: subregion collision 30/8 (apci-smi) vs 20/10 (apci-gpe0)
    warning: subregion collision b0000000/10000000 (pcie-mmcfg) vs 8000000/f8000000 (pci-hole)
    
    after:
    
    warning: subregion collision fec00000/1000 (kvm-ioapic) vs 8000000/f8000000 (pci-hole)
    warning: subregion collision fed00000/400 (hpet) vs 8000000/f8000000 (pci-hole)
    warning: subregion collision 0/80 (ich9-pm) vs 8/8 (dma-cont)
    warning: subregion collision 0/80 (ich9-pm) vs 0/8 (dma-chan)
    warning: subregion collision 0/80 (ich9-pm) vs 64/1 (i8042-cmd)
    warning: subregion collision 0/80 (ich9-pm) vs 60/1 (i8042-data)
    warning: subregion collision 0/80 (ich9-pm) vs 61/1 (elcr)
    warning: subregion collision 0/80 (ich9-pm) vs 40/4 (kvm-pit)
    warning: subregion collision 0/80 (ich9-pm) vs 70/2 (rtc)
    warning: subregion collision 0/80 (ich9-pm) vs 20/2 (kvm-pic)
    warning: subregion collision 0/80 (ich9-pm) vs 7e/2 (kvmvapic)
    warning: subregion collision b0000000/10000000 (pcie-mmcfg) vs 8000000/f8000000 (pci-hole)
    
    Signed-off-by: Hu Tao <hutao at cn.fujitsu.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/memory.c b/memory.c
index 92a2196..75ca281 100644
--- a/memory.c
+++ b/memory.c
@@ -1321,7 +1321,7 @@ static void memory_region_add_subregion_common(MemoryRegion *mr,
         if (subregion->may_overlap || other->may_overlap) {
             continue;
         }
-        if (int128_gt(int128_make64(offset),
+        if (int128_ge(int128_make64(offset),
                       int128_add(int128_make64(other->addr), other->size))
             || int128_le(int128_add(int128_make64(offset), subregion->size),
                          int128_make64(other->addr))) {
commit 9957fc7f1ed731e5228089ead3f350341cdd29c0
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Mar 8 19:58:32 2013 +0100

    MinGW: Replace setsockopt by qemu_setsocketopt
    
    Instead of adding missing type casts which are needed by MinGW for the
    4th argument, the patch uses qemu_setsockopt which was invented for this
    purpose.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/bt-host.c b/bt-host.c
index 2092754..2da3c32 100644
--- a/bt-host.c
+++ b/bt-host.c
@@ -171,7 +171,7 @@ struct HCIInfo *bt_host_hci(const char *id)
     hci_filter_all_ptypes(&flt);
     hci_filter_all_events(&flt);
 
-    if (setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
+    if (qemu_setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
         fprintf(stderr, "qemu: Can't set HCI filter on socket (%i)\n", errno);
         return 0;
     }
diff --git a/gdbstub.c b/gdbstub.c
index 43b7d4d..decb505 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2887,7 +2887,7 @@ static int gdbserver_open(int port)
 
     /* allow fast reuse */
     val = 1;
-    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
+    qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
 
     sockaddr.sin_family = AF_INET;
     sockaddr.sin_port = htons(port);
diff --git a/net/socket.c b/net/socket.c
index 396dc8c..d8b35a2 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -262,8 +262,7 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
     }
 
     val = 1;
-    ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
-                   (const char *)&val, sizeof(val));
+    ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
     if (ret < 0) {
         perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
         goto fail;
@@ -283,8 +282,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
         imr.imr_interface.s_addr = htonl(INADDR_ANY);
     }
 
-    ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
-                     (const char *)&imr, sizeof(struct ip_mreq));
+    ret = qemu_setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+                          &imr, sizeof(struct ip_mreq));
     if (ret < 0) {
         perror("setsockopt(IP_ADD_MEMBERSHIP)");
         goto fail;
@@ -292,8 +291,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
 
     /* Force mcast msgs to loopback (eg. several QEMUs in same host */
     loop = 1;
-    ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
-                   (const char *)&loop, sizeof(loop));
+    ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
+                          &loop, sizeof(loop));
     if (ret < 0) {
         perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
         goto fail;
@@ -301,8 +300,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
 
     /* If a bind address is given, only send packets from that address */
     if (localaddr != NULL) {
-        ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
-                         (const char *)localaddr, sizeof(*localaddr));
+        ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
+                              localaddr, sizeof(*localaddr));
         if (ret < 0) {
             perror("setsockopt(IP_MULTICAST_IF)");
             goto fail;
@@ -521,7 +520,7 @@ static int net_socket_listen_init(NetClientState *peer,
 
     /* allow fast reuse */
     val = 1;
-    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
+    qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
 
     ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
     if (ret < 0) {
@@ -659,8 +658,8 @@ static int net_socket_udp_init(NetClientState *peer,
         return -1;
     }
     val = 1;
-    ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
-                   (const char *)&val, sizeof(val));
+    ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+                          &val, sizeof(val));
     if (ret < 0) {
         perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
         closesocket(fd);
diff --git a/slirp/misc.c b/slirp/misc.c
index d4df972..6b9c2c4 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -212,9 +212,9 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
                 } while (so->s < 0 && errno == EINTR);
                 closesocket(s);
                 opt = 1;
-                setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int));
+                qemu_setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
                 opt = 1;
-                setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int));
+                qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
 		socket_set_nonblock(so->s);
 
 		/* Append the telnet options now */
diff --git a/slirp/socket.c b/slirp/socket.c
index bb639ae..8e8819c 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -627,7 +627,7 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
 	addr.sin_port = hport;
 
 	if (((s = qemu_socket(AF_INET,SOCK_STREAM,0)) < 0) ||
-	    (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
+	    (qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)) < 0) ||
 	    (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
 	    (listen(s,1) < 0)) {
 		int tmperrno = errno; /* Don't clobber the real reason we failed */
@@ -642,7 +642,7 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
 #endif
 		return NULL;
 	}
-	setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
+	qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
 
 	getsockname(s,(struct sockaddr *)&addr,&addrlen);
 	so->so_fport = addr.sin_port;
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 7b7ad60..84a6bb5 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -338,9 +338,9 @@ int tcp_fconnect(struct socket *so)
 
     socket_set_nonblock(s);
     opt = 1;
-    setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt ));
+    qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
     opt = 1;
-    setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt ));
+    qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
 
     addr.sin_family = AF_INET;
     if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
@@ -427,9 +427,9 @@ void tcp_connect(struct socket *inso)
     }
     socket_set_nonblock(s);
     opt = 1;
-    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int));
+    qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
     opt = 1;
-    setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int));
+    qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
     socket_set_nodelay(s);
 
     so->so_fport = addr.sin_port;
diff --git a/slirp/udp.c b/slirp/udp.c
index 9286cb7..b105f87 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -372,7 +372,7 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
 		udp_detach(so);
 		return NULL;
 	}
-	setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
+	qemu_setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
 
 	getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
 	so->so_fport = addr.sin_port;
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 83e4e08..d70bbf0 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -156,12 +156,12 @@ int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp)
             continue;
         }
 
-        setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
+        qemu_setsockopt(slisten, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
 #ifdef IPV6_V6ONLY
         if (e->ai_family == PF_INET6) {
             /* listen on both ipv4 and ipv6 */
-            setsockopt(slisten,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&off,
-                sizeof(off));
+            qemu_setsockopt(slisten, IPPROTO_IPV6, IPV6_V6ONLY, &off,
+                            sizeof(off));
         }
 #endif
 
@@ -229,7 +229,7 @@ static void wait_for_connect(void *opaque)
     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
 
     do {
-        rc = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, (void *) &val, &valsize);
+        rc = qemu_getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &val, &valsize);
     } while (rc == -1 && socket_error() == EINTR);
 
     /* update rc to contain error */
@@ -456,7 +456,7 @@ int inet_dgram_opts(QemuOpts *opts, Error **errp)
         error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED);
         goto err;
     }
-    setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
+    qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
 
     /* bind socket */
     if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) {
commit fe42d7fb0f4a05fb393e1efbd681f33a0154c644
Author: Cornelia Huck <cornelia.huck at de.ibm.com>
Date:   Wed Mar 20 08:27:50 2013 +0100

    virtio-ccw, s390-virtio: Use generic virtio-blk macro.
    
    Now that virtio-ccw and s390-virtio define all common properties
    for virtio-blk, we can switch to using the generic
    DEFINE_VIRTIO_BLK_PROPERTIES macro.
    
    CC: Alexander Graf <agraf at suse.de>
    Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com>

diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index 5d55a9d..c5d5456 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -435,13 +435,7 @@ static const TypeInfo s390_virtio_net = {
 };
 
 static Property s390_virtio_blk_properties[] = {
-    DEFINE_BLOCK_PROPERTIES(VirtIOBlkS390, blk.conf),
-    DEFINE_BLOCK_CHS_PROPERTIES(VirtIOBlkS390, blk.conf),
-    DEFINE_PROP_STRING("serial", VirtIOBlkS390, blk.serial),
-#ifdef __linux__
-    DEFINE_PROP_BIT("scsi", VirtIOBlkS390, blk.scsi, 0, true),
-#endif
-    DEFINE_PROP_BIT("config-wce", VirtIOBlkS390, blk.config_wce, 0, true),
+    DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOBlkS390, blk),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index afaf348..4c44b7e 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -756,14 +756,8 @@ static const TypeInfo virtio_ccw_net = {
 
 static Property virtio_ccw_blk_properties[] = {
     DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
-    DEFINE_BLOCK_PROPERTIES(VirtIOBlkCcw, blk.conf),
-    DEFINE_BLOCK_CHS_PROPERTIES(VirtIOBlkCcw, blk.conf),
-    DEFINE_PROP_STRING("serial", VirtIOBlkCcw, blk.serial),
-#ifdef __linux__
-    DEFINE_PROP_BIT("scsi", VirtIOBlkCcw, blk.scsi, 0, true),
-#endif
-    DEFINE_PROP_BIT("config-wce", VirtIOBlkCcw, blk.config_wce, 0, true),
     DEFINE_VIRTIO_BLK_FEATURES(VirtioCcwDevice, host_features[0]),
+    DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOBlkCcw, blk),
     DEFINE_PROP_END_OF_LIST(),
 };
 
commit da0a58b93c88d874233902f459e01300a78e5f9d
Author: Cornelia Huck <cornelia.huck at de.ibm.com>
Date:   Wed Mar 13 15:20:07 2013 +0100

    s390-virtio, virtio-ccw: Add config_wce for virtio-blk.
    
    There's no reason why we wouldn't want to make the cache mode
    configurable.
    
    Acked-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com>

diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index 76bc99a..5d55a9d 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -441,6 +441,7 @@ static Property s390_virtio_blk_properties[] = {
 #ifdef __linux__
     DEFINE_PROP_BIT("scsi", VirtIOBlkS390, blk.scsi, 0, true),
 #endif
+    DEFINE_PROP_BIT("config-wce", VirtIOBlkS390, blk.config_wce, 0, true),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index fc95116..afaf348 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -762,6 +762,7 @@ static Property virtio_ccw_blk_properties[] = {
 #ifdef __linux__
     DEFINE_PROP_BIT("scsi", VirtIOBlkCcw, blk.scsi, 0, true),
 #endif
+    DEFINE_PROP_BIT("config-wce", VirtIOBlkCcw, blk.config_wce, 0, true),
     DEFINE_VIRTIO_BLK_FEATURES(VirtioCcwDevice, host_features[0]),
     DEFINE_PROP_END_OF_LIST(),
 };
commit 131cd73705bc5551ae4b64476399d440e8ac55a7
Author: Cornelia Huck <cornelia.huck at de.ibm.com>
Date:   Wed Mar 13 14:43:22 2013 +0100

    virtio-ccw: Add missing blk chs properties.
    
    Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com>

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 9688835..fc95116 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -757,6 +757,7 @@ static const TypeInfo virtio_ccw_net = {
 static Property virtio_ccw_blk_properties[] = {
     DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
     DEFINE_BLOCK_PROPERTIES(VirtIOBlkCcw, blk.conf),
+    DEFINE_BLOCK_CHS_PROPERTIES(VirtIOBlkCcw, blk.conf),
     DEFINE_PROP_STRING("serial", VirtIOBlkCcw, blk.serial),
 #ifdef __linux__
     DEFINE_PROP_BIT("scsi", VirtIOBlkCcw, blk.scsi, 0, true),
commit afed26082219b49443193b4ac32d113bbcf967fd
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Tue Mar 19 17:34:47 2013 +0100

    microblaze: Ignore non-cpu accesses to unmapped areas
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index 1c62f3c..f2cb88b 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -500,7 +500,7 @@ void cpu_unassigned_access(CPUMBState *env, hwaddr addr,
 {
     qemu_log_mask(CPU_LOG_INT, "Unassigned " TARGET_FMT_plx " wr=%d exe=%d\n",
              addr, is_write, is_exec);
-    if (!(env->sregs[SR_MSR] & MSR_EE)) {
+    if (!env || !(env->sregs[SR_MSR] & MSR_EE)) {
         return;
     }
 
commit f7d42093a5e54d48cab62695a374806d4303bd6b
Merge: c8a6ae8 c45e5b5
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 19 08:01:07 2013 -0500

    Merge remote-tracking branch 'kraxel/ipxe.2' into staging
    
    # By Gerd Hoffmann
    # Via Gerd Hoffmann
    * kraxel/ipxe.2:
      Switch to efi-enabled nic roms by default
      Add efi rom binaries
      Add Makefile rules to build nic rom binaries with efi support
      Update ipxe submodule to latest master
      Add Makefile rules to build nic rom binaries

commit c8a6ae8bb95477d5ac11d9b491b603b2d190a96e
Author: Amos Kong <akong at redhat.com>
Date:   Tue Mar 19 14:23:27 2013 +0800

    add a boot option to do strict boot
    
    Seabios already added a new device type to halt booting.
    Qemu can add "HALT" at the end of bootindex string, then
    seabios will halt booting after trying to boot from all
    selected devices.
    
    This patch added a new boot option to configure if boot
    from un-selected devices.
    
    This option only effects when boot priority is changed by
    bootindex options, the old style(-boot order=..) will still
    try to boot from un-selected devices.
    
    v2: add HALT entry in get_boot_devices_list()
    v3: rebase to latest qemu upstream
    
    Signed-off-by: Amos Kong <akong at redhat.com>
    Message-id: 1363674207-31496-1-git-send-email-akong at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index 30fb85d..06dd565 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -161,14 +161,14 @@ ETEXI
 
 DEF("boot", HAS_ARG, QEMU_OPTION_boot,
     "-boot [order=drives][,once=drives][,menu=on|off]\n"
-    "      [,splash=sp_name][,splash-time=sp_time][,reboot-timeout=rb_time]\n"
+    "      [,splash=sp_name][,splash-time=sp_time][,reboot-timeout=rb_time][,strict=on|off]\n"
     "                'drives': floppy (a), hard disk (c), CD-ROM (d), network (n)\n"
     "                'sp_name': the file's name that would be passed to bios as logo picture, if menu=on\n"
     "                'sp_time': the period that splash picture last if menu=on, unit is ms\n"
     "                'rb_timeout': the timeout before guest reboot when boot failed, unit is ms\n",
     QEMU_ARCH_ALL)
 STEXI
- at item -boot [order=@var{drives}][,once=@var{drives}][,menu=on|off][,splash=@var{sp_name}][,splash-time=@var{sp_time}][,reboot-timeout=@var{rb_timeout}]
+ at item -boot [order=@var{drives}][,once=@var{drives}][,menu=on|off][,splash=@var{sp_name}][,splash-time=@var{sp_time}][,reboot-timeout=@var{rb_timeout}][,strict=on|off]
 @findex -boot
 Specify boot order @var{drives} as a string of drive letters. Valid
 drive letters depend on the target achitecture. The x86 PC uses: a, b
@@ -192,6 +192,10 @@ when boot failed, then reboot. If @var{rb_timeout} is '-1', guest will not
 reboot, qemu passes '-1' to bios by default. Currently Seabios for X86
 system support it.
 
+Do strict boot via @option{strict=on} as far as firmware/BIOS
+supports it. This only effects when boot priority is changed by
+bootindex options. The default is non-strict boot.
+
 @example
 # try to boot from network first, then from hard disk
 qemu-system-i386 -boot order=nc
diff --git a/vl.c b/vl.c
index ce51e65..aeed7f4 100644
--- a/vl.c
+++ b/vl.c
@@ -234,6 +234,7 @@ int ctrl_grab = 0;
 unsigned int nb_prom_envs = 0;
 const char *prom_envs[MAX_PROM_ENVS];
 int boot_menu;
+bool boot_strict;
 uint8_t *boot_splash_filedata;
 size_t boot_splash_filedata_size;
 uint8_t qemu_extra_params_fw[2];
@@ -458,6 +459,9 @@ static QemuOptsList qemu_boot_opts = {
         }, {
             .name = "reboot-timeout",
             .type = QEMU_OPT_STRING,
+        }, {
+            .name = "strict",
+            .type = QEMU_OPT_STRING,
         },
         { /*End of list */ }
     },
@@ -1267,6 +1271,12 @@ char *get_boot_devices_list(size_t *size)
 
     *size = total;
 
+    if (boot_strict && *size > 0) {
+        list[total-1] = '\n';
+        list = g_realloc(list, total + 4);
+        memcpy(&list[total], "HALT", 4);
+        *size = total + 4;
+    }
     return list;
 }
 
@@ -3131,7 +3141,7 @@ int main(int argc, char **argv, char **envp)
                     static const char * const params[] = {
                         "order", "once", "menu",
                         "splash", "splash-time",
-                        "reboot-timeout", NULL
+                        "reboot-timeout", "strict", NULL
                     };
                     char buf[sizeof(boot_devices)];
                     char *standard_boot_devices;
@@ -3174,6 +3184,19 @@ int main(int argc, char **argv, char **envp)
                                 exit(1);
                             }
                         }
+                        if (get_param_value(buf, sizeof(buf),
+                                            "strict", optarg)) {
+                            if (!strcmp(buf, "on")) {
+                                boot_strict = true;
+                            } else if (!strcmp(buf, "off")) {
+                                boot_strict = false;
+                            } else {
+                                fprintf(stderr,
+                                        "qemu: invalid option value '%s'\n",
+                                        buf);
+                                exit(1);
+                            }
+                        }
                         if (!qemu_opts_parse(qemu_find_opts("boot-opts"),
                                              optarg, 0)) {
                             exit(1);
commit 8510d91ebad522685bc1a29e7bbc1f5050af0d2c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Mar 18 20:28:21 2013 +0000

    ui/cocoa.m: Fix compile failures introduced by recent console changes
    
    Fix various compilation failures introduced by the recent console
    changes.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1363638501-29603-1-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/cocoa.m b/ui/cocoa.m
index 8e0eaa2..048cc97 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -403,6 +403,9 @@ QemuCocoaView *cocoaView;
 {
     COCOA_DEBUG("QemuCocoaView: switchSurface\n");
 
+    int w = surface_width(surface);
+    int h = surface_height(surface);
+
     // update screenBuffer
     if (dataProviderRef)
         CGDataProviderRelease(dataProviderRef);
@@ -1014,9 +1017,9 @@ static void cocoa_cleanup(void)
 
 static const DisplayChangeListenerOps dcl_ops = {
     .dpy_name          = "cocoa",
-    .dpy_gfx_update = cocoa_update;
-    .dpy_gfx_switch = cocoa_switch;
-    .dpy_refresh = cocoa_refresh;
+    .dpy_gfx_update = cocoa_update,
+    .dpy_gfx_switch = cocoa_switch,
+    .dpy_refresh = cocoa_refresh,
 };
 
 void cocoa_display_init(DisplayState *ds, int full_screen)
commit 277ba8a6d717abb2f36896cd9877a68d2cf03d77
Merge: 2c8a594 a8e5cc0
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 19 07:58:44 2013 -0500

    Merge remote-tracking branch 'kwolf/for-anthony' into staging
    
    # By Stefan Hajnoczi (2) and others
    # Via Kevin Wolf
    * kwolf/for-anthony:
      virtio-blk: Do not segfault fault if failed to initialize dataplane
      qemu-iotests: add 052 BDRV_O_SNAPSHOT test
      block: fix BDRV_O_SNAPSHOT protocol detection
      qcow2: Fix segfault in qcow2_invalidate_cache
      sheepdog: show error message for halt status

commit 2c8a59422c06fe1e37c85502d92ccdfb5e2ac987
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 19 13:38:09 2013 +0100

    char: Fix return type of qemu_chr_fe_add_watch()
    
    qemu_chr_fe_add_watch() can return negative errors, therefore it must
    not have an unsigned return type. For consistency with other
    qemu_chr_fe_* functions, this uses a standard C int instead of glib
    types.
    
    In situations where qemu_chr_fe_add_watch() is falsely assumed to have
    succeeded, the serial ports would go into a state where it never becomes
    ready for transmitting more data; this is fixed by this patch.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/char/char.h b/include/char/char.h
index d6a0351..0326b2a 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -153,8 +153,8 @@ void qemu_chr_fe_close(struct CharDriverState *chr);
 void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...)
     GCC_FMT_ATTR(2, 3);
 
-guint qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
-                            GIOFunc func, void *user_data);
+int qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
+                          GIOFunc func, void *user_data);
 
 /**
  * @qemu_chr_fe_write:
diff --git a/qemu-char.c b/qemu-char.c
index e633797..4e011df 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3397,8 +3397,8 @@ void qemu_chr_fe_close(struct CharDriverState *chr)
     }
 }
 
-guint qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
-                            GIOFunc func, void *user_data)
+int qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
+                          GIOFunc func, void *user_data)
 {
     GSource *src;
     guint tag;
commit f628926bb423fa8a7e0b114511400ea9df38b76a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Mar 19 10:57:56 2013 +0100

    fix monitor
    
    chardev flow control broke monitor, fix it by adding watch support.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/monitor.c b/monitor.c
index 112e920..680d344 100644
--- a/monitor.c
+++ b/monitor.c
@@ -261,11 +261,30 @@ int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
     }
 }
 
+static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond,
+                                  void *opaque)
+{
+    monitor_flush(opaque);
+    return FALSE;
+}
+
 void monitor_flush(Monitor *mon)
 {
+    int rc;
+
     if (mon && mon->outbuf_index != 0 && !mon->mux_out) {
-        qemu_chr_fe_write(mon->chr, mon->outbuf, mon->outbuf_index);
-        mon->outbuf_index = 0;
+        rc = qemu_chr_fe_write(mon->chr, mon->outbuf, mon->outbuf_index);
+        if (rc == mon->outbuf_index) {
+            /* all flushed */
+            mon->outbuf_index = 0;
+            return;
+        }
+        if (rc > 0) {
+            /* partinal write */
+            memmove(mon->outbuf, mon->outbuf + rc, mon->outbuf_index - rc);
+            mon->outbuf_index -= rc;
+        }
+        qemu_chr_fe_add_watch(mon->chr, G_IO_OUT, monitor_unblocked, mon);
     }
 }
 
commit a8e5cc0c076a6e3a62f0e9aad88b007dccf3dd17
Author: Dunrong Huang <huangdr at cloud-times.com>
Date:   Tue Mar 19 16:27:29 2013 +0800

    virtio-blk: Do not segfault fault if failed to initialize dataplane
    
    $ ~/usr/bin/qemu-system-x86_64 -enable-kvm -m 1024 -drive if=none,id=drive0,cache=none,aio=native,format=raw,file=/root/Image/centos-6.4.raw -device virtio-blk-pci,drive=drive0,scsi=off,x-data-plane=on,config-wce=on # make dataplane fail to initialize
    qemu-system-x86_64: -device virtio-blk-pci,drive=drive0,scsi=off,x-data-plane=on,config-wce=on: device is incompatible with x-data-plane, use config-wce=off
    *** glibc detected *** /root/usr/bin/qemu-system-x86_64: free(): invalid pointer: 0x00007f001fef12f8 ***
    ======= Backtrace: =========
    /lib64/libc.so.6(+0x7d776)[0x7f00153a5776]
    /root/usr/bin/qemu-system-x86_64(+0x2c34ec)[0x7f001cf5b4ec]
    /root/usr/bin/qemu-system-x86_64(+0x342f9a)[0x7f001cfdaf9a]
    /root/usr/bin/qemu-system-x86_64(+0x33694e)[0x7f001cfce94e]
    ....................
    
     (gdb) bt
     #0  0x00007f3bf3a12015 in raise () from /lib64/libc.so.6
     #1  0x00007f3bf3a1348b in abort () from /lib64/libc.so.6
     #2  0x00007f3bf3a51a4e in __libc_message () from /lib64/libc.so.6
     #3  0x00007f3bf3a57776 in malloc_printerr () from /lib64/libc.so.6
     #4  0x00007f3bfb60d4ec in free_and_trace (mem=0x7f3bfe0129f8) at vl.c:2786
     #5  0x00007f3bfb68cf9a in virtio_cleanup (vdev=0x7f3bfe0129f8) at /root/Develop/QEMU/qemu/hw/virtio.c:900
     #6  0x00007f3bfb68094e in virtio_blk_device_init (vdev=0x7f3bfe0129f8) at /root/Develop/QEMU/qemu/hw/virtio-blk.c:666
     #7  0x00007f3bfb68dadf in virtio_device_init (qdev=0x7f3bfe0129f8) at /root/Develop/QEMU/qemu/hw/virtio.c:1092
     #8  0x00007f3bfb50da46 in device_realize (dev=0x7f3bfe0129f8, err=0x7fff479c9258) at hw/qdev.c:176
    .............................
    
    In virtio_blk_device_init(), the memory which vdev point to is a static
    member of "struct VirtIOBlkPCI", not heap memory, and it does not
    get freed. So we shoule use virtio_common_cleanup() to clean this VirtIODevice
    rather than virtio_cleanup(), which attempts to free the vdev.
    
    This error was introduced by commit 05ff686536f408ba6e8426b1b54d25bd3379fda2
    recently.
    
    Signed-off-by: Dunrong Huang <huangdr at cloud-times.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index e6f8875..f2143fd 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -663,7 +663,7 @@ static int virtio_blk_device_init(VirtIODevice *vdev)
     s->vq = virtio_add_queue(vdev, 128, virtio_blk_handle_output);
 #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
     if (!virtio_blk_data_plane_create(vdev, blk, &s->dataplane)) {
-        virtio_cleanup(vdev);
+        virtio_common_cleanup(vdev);
         return -1;
     }
 #endif
commit f95e26ddf526a025aa1334bbe527739397970443
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Mon Mar 18 17:58:54 2013 +0100

    qemu-iotests: add 052 BDRV_O_SNAPSHOT test
    
    Check that writes to an image opened with BDRV_O_SNAPSHOT do not modify
    the underlying image file.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/052 b/tests/qemu-iotests/052
new file mode 100755
index 0000000..14a5126
--- /dev/null
+++ b/tests/qemu-iotests/052
@@ -0,0 +1,61 @@
+#!/bin/bash
+#
+# Test bdrv_read/bdrv_write using BDRV_O_SNAPSHOT
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=stefanha at redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+_cleanup()
+{
+	_cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt generic
+_supported_proto generic
+_supported_os Linux
+
+
+size=128M
+_make_test_img $size
+
+echo
+echo "== reading whole image =="
+$QEMU_IO -s -c "read 0 $size" $TEST_IMG | _filter_qemu_io
+
+echo
+echo "== writing whole image does not modify image =="
+$QEMU_IO -s -c "write -P 0xa 0 $size" $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c "read -P 0 0 $size" $TEST_IMG | _filter_qemu_io
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/052.out b/tests/qemu-iotests/052.out
new file mode 100644
index 0000000..8617aa2
--- /dev/null
+++ b/tests/qemu-iotests/052.out
@@ -0,0 +1,13 @@
+QA output created by 052
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 
+
+== reading whole image ==
+read 134217728/134217728 bytes at offset 0
+128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== writing whole image does not modify image ==
+wrote 134217728/134217728 bytes at offset 0
+128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 134217728/134217728 bytes at offset 0
+128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 1d7e4f3..73c5966 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -57,3 +57,4 @@
 048 img auto quick
 049 rw auto
 050 rw auto backing quick
+052 rw auto backing
commit 4d70655bcb852ea0a006d3923f0b0a9c69ff462e
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Mon Mar 18 17:58:53 2013 +0100

    block: fix BDRV_O_SNAPSHOT protocol detection
    
    realpath(3) is used to get an absolute path to the image file when
    creating a -drive snapshot=on temporary qcow2.  This does not work for
    protocols since their filenames ("proto:foo:...") do not correspond to
    file system paths.
    
    Commit 7c96d46ec245d73fd76726588409f9abe4bd5dc1 ("Let snapshot work with
    protocols") skipped realpath(3) for protocols.  Later on the "raw"
    format was introduced and broke the check.
    
    Use path_has_protocol(filename) to decide if this image uses a protocol
    or a filename.
    
    Reported-by: Richard Jones <rjones at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 037e15e..0a062c9 100644
--- a/block.c
+++ b/block.c
@@ -830,7 +830,6 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
     if (flags & BDRV_O_SNAPSHOT) {
         BlockDriverState *bs1;
         int64_t total_size;
-        int is_protocol = 0;
         BlockDriver *bdrv_qcow2;
         QEMUOptionParameter *options;
         char backing_filename[PATH_MAX];
@@ -847,9 +846,6 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
         }
         total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK;
 
-        if (bs1->drv && bs1->drv->protocol_name)
-            is_protocol = 1;
-
         bdrv_delete(bs1);
 
         ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));
@@ -858,7 +854,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
         }
 
         /* Real path is meaningless for protocols */
-        if (is_protocol) {
+        if (path_has_protocol(filename)) {
             snprintf(backing_filename, sizeof(backing_filename),
                      "%s", filename);
         } else if (!realpath(filename, backing_filename)) {
commit acdfb480ba7e2779bdbffb5280cf12ff6e43669c
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Mar 18 13:08:10 2013 +0100

    qcow2: Fix segfault in qcow2_invalidate_cache
    
    Need to pass an options QDict to qcow2_open() now. This fixes a segfault
    on the migration target with qcow2.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 1f99866..98bb7f3 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -29,6 +29,7 @@
 #include "block/qcow2.h"
 #include "qemu/error-report.h"
 #include "qapi/qmp/qerror.h"
+#include "qapi/qmp/qbool.h"
 #include "trace.h"
 
 /*
@@ -520,7 +521,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags)
         goto fail;
     }
 
-    s->use_lazy_refcounts = qemu_opt_get_bool(opts, "lazy_refcounts",
+    s->use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS,
         (s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS));
 
     qemu_opts_del(opts);
@@ -930,6 +931,7 @@ static void qcow2_invalidate_cache(BlockDriverState *bs)
     AES_KEY aes_encrypt_key;
     AES_KEY aes_decrypt_key;
     uint32_t crypt_method = 0;
+    QDict *options;
 
     /*
      * Backing files are read-only which makes all of their metadata immutable,
@@ -944,8 +946,14 @@ static void qcow2_invalidate_cache(BlockDriverState *bs)
 
     qcow2_close(bs);
 
+    options = qdict_new();
+    qdict_put(options, QCOW2_OPT_LAZY_REFCOUNTS,
+              qbool_from_int(s->use_lazy_refcounts));
+
     memset(s, 0, sizeof(BDRVQcowState));
-    qcow2_open(bs, NULL, flags);
+    qcow2_open(bs, options, flags);
+
+    QDECREF(options);
 
     if (crypt_method) {
         s->crypt_method = crypt_method;
diff --git a/block/qcow2.h b/block/qcow2.h
index 103abdb..e4b5e11 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -58,6 +58,9 @@
 
 #define DEFAULT_CLUSTER_SIZE 65536
 
+
+#define QCOW2_OPT_LAZY_REFCOUNTS "lazy_refcounts"
+
 typedef struct QCowHeader {
     uint32_t magic;
     uint32_t version;
commit fca23f0ad211e4debf80796a65165d0eea146424
Author: Liu Yuan <tailai.ly at taobao.com>
Date:   Mon Mar 18 14:27:55 2013 +0800

    sheepdog: show error message for halt status
    
    Sheepdog (neither quorum nor unsafe mode) will refuse to serve IO requests when
    number of alive nodes is less than that of copies specified by users. This will
    return 0x19 to QEMU client which currently doesn't recognize it.
    
    This patch adds an error description when QEMU client receives it, other than
    plainly printing 'Invalid error code'
    
    Cc: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Cc: Kevin Wolf <kwolf at redhat.com>
    Cc: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index 4245328..54d3e53 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -65,6 +65,7 @@
 #define SD_RES_WAIT_FOR_FORMAT  0x16 /* Waiting for a format operation */
 #define SD_RES_WAIT_FOR_JOIN    0x17 /* Waiting for other nodes joining */
 #define SD_RES_JOIN_FAILED   0x18 /* Target node had failed to join sheepdog */
+#define SD_RES_HALT          0x19 /* Sheepdog is stopped serving IO request */
 
 /*
  * Object ID rules
@@ -344,6 +345,7 @@ static const char * sd_strerror(int err)
         {SD_RES_WAIT_FOR_FORMAT, "Sheepdog is waiting for a format operation"},
         {SD_RES_WAIT_FOR_JOIN, "Sheepdog is waiting for other nodes joining"},
         {SD_RES_JOIN_FAILED, "Target node had failed to join sheepdog"},
+        {SD_RES_HALT, "Sheepdog is stopped serving IO request"},
     };
 
     for (i = 0; i < ARRAY_SIZE(errors); ++i) {
commit b1e5fff4afd0c47148b0d9f9341887ae2c3eb9af
Author: Michael Walle <michael at walle.cc>
Date:   Wed Mar 6 20:23:32 2013 +0100

    configure: rename OpenGL feature to GLX
    
    As the probe now actually checks for the availability of GLX, rename it
    accordingly. The only user of this feature is the milkymist-tmu2 model.
    
    Signed-off-by: Michael Walle <michael at walle.cc>

diff --git a/configure b/configure
index d44d6b8..3505040 100755
--- a/configure
+++ b/configure
@@ -217,7 +217,7 @@ spice=""
 rbd=""
 smartcard_nss=""
 usb_redir=""
-opengl=""
+glx=""
 zlib="yes"
 guest_agent="yes"
 want_tools="yes"
@@ -858,9 +858,9 @@ for opt do
   ;;
   --enable-vhost-net) vhost_net="yes"
   ;;
-  --disable-opengl) opengl="no"
+  --disable-glx) glx="no"
   ;;
-  --enable-opengl) opengl="yes"
+  --enable-glx) glx="yes"
   ;;
   --disable-rbd) rbd="no"
   ;;
@@ -2435,9 +2435,9 @@ EOF
 fi
 
 ##########################################
-# opengl probe, used by milkymist-tmu2
-if test "$opengl" != "no" ; then
-  opengl_libs="-lGL -lX11"
+# GLX probe, used by milkymist-tmu2
+if test "$glx" != "no" ; then
+  glx_libs="-lGL -lX11"
   cat > $TMPC << EOF
 #include <X11/Xlib.h>
 #include <GL/gl.h>
@@ -2445,13 +2445,13 @@ if test "$opengl" != "no" ; then
 int main(void) { glBegin(0); glXQueryVersion(0,0,0); return 0; }
 EOF
   if compile_prog "" "-lGL -lX11" ; then
-    opengl=yes
+    glx=yes
   else
-    if test "$opengl" = "yes" ; then
-      feature_not_found "opengl"
+    if test "$glx" = "yes" ; then
+      feature_not_found "glx"
     fi
-    opengl_libs=
-    opengl=no
+    glx_libs=
+    glx=no
   fi
 fi
 
@@ -3429,7 +3429,7 @@ echo "rbd support       $rbd"
 echo "xfsctl support    $xfs"
 echo "nss used          $smartcard_nss"
 echo "usb net redir     $usb_redir"
-echo "OpenGL support    $opengl"
+echo "GLX support       $glx"
 echo "libiscsi support  $libiscsi"
 echo "build guest agent $guest_agent"
 echo "seccomp support   $seccomp"
@@ -3740,8 +3740,8 @@ if test "$usb_redir" = "yes" ; then
   echo "CONFIG_USB_REDIR=y" >> $config_host_mak
 fi
 
-if test "$opengl" = "yes" ; then
-  echo "CONFIG_OPENGL=y" >> $config_host_mak
+if test "$glx" = "yes" ; then
+  echo "CONFIG_GLX=y" >> $config_host_mak
 fi
 
 if test "$libiscsi" = "yes" ; then
@@ -4019,7 +4019,7 @@ case "$target_arch2" in
     target_nptl="yes"
   ;;
   lm32)
-    target_libs_softmmu="$opengl_libs"
+    target_libs_softmmu="$glx_libs"
   ;;
   m68k)
     bflt="yes"
diff --git a/hw/lm32/Makefile.objs b/hw/lm32/Makefile.objs
index 4592fe5..68ca90a 100644
--- a/hw/lm32/Makefile.objs
+++ b/hw/lm32/Makefile.objs
@@ -11,7 +11,7 @@ obj-y += milkymist-minimac2.o
 obj-y += milkymist-pfpu.o
 obj-y += milkymist-softusb.o
 obj-y += milkymist-sysctl.o
-obj-$(CONFIG_OPENGL) += milkymist-tmu2.o
+obj-$(CONFIG_GLX) += milkymist-tmu2.o
 obj-y += milkymist-uart.o
 obj-y += milkymist-vgafb.o
 obj-y += framebuffer.o
diff --git a/hw/milkymist-hw.h b/hw/milkymist-hw.h
index ced1c5f..c047a70 100644
--- a/hw/milkymist-hw.h
+++ b/hw/milkymist-hw.h
@@ -87,7 +87,7 @@ static inline DeviceState *milkymist_pfpu_create(hwaddr base,
     return dev;
 }
 
-#ifdef CONFIG_OPENGL
+#ifdef CONFIG_GLX
 #include <X11/Xlib.h>
 #include <GL/glx.h>
 static const int glx_fbconfig_attr[] = {
@@ -101,7 +101,7 @@ static const int glx_fbconfig_attr[] = {
 static inline DeviceState *milkymist_tmu2_create(hwaddr base,
         qemu_irq irq)
 {
-#ifdef CONFIG_OPENGL
+#ifdef CONFIG_GLX
     DeviceState *dev;
     Display *d;
     GLXFBConfig *configs;
commit d3fcbb16789c6f975ba6e22d8a2ba477519f51bc
Author: Michael Walle <michael at walle.cc>
Date:   Wed Mar 6 20:16:58 2013 +0100

    configure: proper OpenGL/GLX probe
    
    Probe for GL and GLX symbols and X11 library. This fixes a build error
    where the header files are available but the libraries are not.
    
    Signed-off-by: Michael Walle <michael at walle.cc>

diff --git a/configure b/configure
index 46a7594..d44d6b8 100755
--- a/configure
+++ b/configure
@@ -2442,9 +2442,9 @@ if test "$opengl" != "no" ; then
 #include <X11/Xlib.h>
 #include <GL/gl.h>
 #include <GL/glx.h>
-int main(void) { return GL_VERSION != 0; }
+int main(void) { glBegin(0); glXQueryVersion(0,0,0); return 0; }
 EOF
-  if compile_prog "" "-lGL" ; then
+  if compile_prog "" "-lGL -lX11" ; then
     opengl=yes
   else
     if test "$opengl" = "yes" ; then
commit 6635075596e0ae583de9c04ff605e16ceaa7d294
Author: Michael Walle <michael at walle.cc>
Date:   Sun Mar 3 23:17:48 2013 +0100

    target-lm32: use HELPER() macro
    
    Instead of hardcoding the function name, use the HELPER() macro for this.
    
    Signed-off-by: Michael Walle <michael at walle.cc>

diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c
index ebc94a0..7ff991e 100644
--- a/target-lm32/op_helper.c
+++ b/target-lm32/op_helper.c
@@ -17,13 +17,13 @@
 #define SHIFT 3
 #include "exec/softmmu_template.h"
 
-void helper_raise_exception(CPULM32State *env, uint32_t index)
+void HELPER(raise_exception)(CPULM32State *env, uint32_t index)
 {
     env->exception_index = index;
     cpu_loop_exit(env);
 }
 
-void helper_hlt(CPULM32State *env)
+void HELPER(hlt)(CPULM32State *env)
 {
     CPUState *cs = CPU(lm32_env_get_cpu(env));
 
@@ -32,42 +32,42 @@ void helper_hlt(CPULM32State *env)
     cpu_loop_exit(env);
 }
 
-void helper_wcsr_im(CPULM32State *env, uint32_t im)
+void HELPER(wcsr_im)(CPULM32State *env, uint32_t im)
 {
     lm32_pic_set_im(env->pic_state, im);
 }
 
-void helper_wcsr_ip(CPULM32State *env, uint32_t im)
+void HELPER(wcsr_ip)(CPULM32State *env, uint32_t im)
 {
     lm32_pic_set_ip(env->pic_state, im);
 }
 
-void helper_wcsr_jtx(CPULM32State *env, uint32_t jtx)
+void HELPER(wcsr_jtx)(CPULM32State *env, uint32_t jtx)
 {
     lm32_juart_set_jtx(env->juart_state, jtx);
 }
 
-void helper_wcsr_jrx(CPULM32State *env, uint32_t jrx)
+void HELPER(wcsr_jrx)(CPULM32State *env, uint32_t jrx)
 {
     lm32_juart_set_jrx(env->juart_state, jrx);
 }
 
-uint32_t helper_rcsr_im(CPULM32State *env)
+uint32_t HELPER(rcsr_im)(CPULM32State *env)
 {
     return lm32_pic_get_im(env->pic_state);
 }
 
-uint32_t helper_rcsr_ip(CPULM32State *env)
+uint32_t HELPER(rcsr_ip)(CPULM32State *env)
 {
     return lm32_pic_get_ip(env->pic_state);
 }
 
-uint32_t helper_rcsr_jtx(CPULM32State *env)
+uint32_t HELPER(rcsr_jtx)(CPULM32State *env)
 {
     return lm32_juart_get_jtx(env->juart_state);
 }
 
-uint32_t helper_rcsr_jrx(CPULM32State *env)
+uint32_t HELPER(rcsr_jrx)(CPULM32State *env)
 {
     return lm32_juart_get_jrx(env->juart_state);
 }
commit a5b0f6d5c0f6678c078354c432a1f0943374f087
Author: Michael Walle <michael at walle.cc>
Date:   Tue Feb 26 19:51:52 2013 +0100

    target-lm32: flush tlb after clearing env
    
    The tlb data is stored within the CPU env. Therefore, the initialization
    has to be done after we clear the environment. Otherwise the tlb will have
    a valid entry for address 0x0.
    
    Signed-off-by: Michael Walle <michael at walle.cc>

diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
index bbb7fbf..23c05dd 100644
--- a/target-lm32/cpu.c
+++ b/target-lm32/cpu.c
@@ -36,10 +36,10 @@ static void lm32_cpu_reset(CPUState *s)
 
     lcc->parent_reset(s);
 
-    tlb_flush(env, 1);
-
     /* reset cpu state */
     memset(env, 0, offsetof(CPULM32State, breakpoints));
+
+    tlb_flush(env, 1);
 }
 
 static void lm32_cpu_realizefn(DeviceState *dev, Error **errp)
commit de55c4bd8bd163ec6c10edc085193bbcf8f9e15e
Author: Michael Walle <michael at walle.cc>
Date:   Mon Feb 25 18:28:57 2013 +0100

    target-lm32: remove dead code
    
    Signed-off-by: Michael Walle <michael at walle.cc>

diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index fd50b53..bfb9150 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -229,18 +229,8 @@ static inline void cpu_set_tls(CPULM32State *env, target_ulong newtls)
 {
 }
 
-static inline int cpu_interrupts_enabled(CPULM32State *env)
-{
-    return env->ie & IE_IE;
-}
-
 #include "exec/cpu-all.h"
 
-static inline target_ulong cpu_get_pc(CPULM32State *env)
-{
-    return env->pc;
-}
-
 static inline void cpu_get_tb_cpu_state(CPULM32State *env, target_ulong *pc,
                                         target_ulong *cs_base, int *flags)
 {
commit df5eb7d2c871ccd708e0f45cdc5d79b73550731b
Author: Michael Walle <michael at walle.cc>
Date:   Fri Dec 14 18:14:04 2012 +0100

    target-lm32: fix cmpgui and cmpgeui opcodes
    
    For unsigned compares the immediate has to be zero extended.
    
    Signed-off-by: Michael Walle <michael at walle.cc>

diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index f51ffc5..e885bb3 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -324,10 +324,20 @@ 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;
+    int i;
 
     if (dc->format == OP_FMT_RI) {
-        tcg_gen_setcondi_tl(cond, cpu_R[rX], cpu_R[rY],
-                sign_extend(dc->imm16, 16));
+        switch (cond) {
+        case TCG_COND_GEU:
+        case TCG_COND_GTU:
+            i = zero_extend(dc->imm16, 16);
+            break;
+        default:
+            i = sign_extend(dc->imm16, 16);
+            break;
+        }
+
+        tcg_gen_setcondi_tl(cond, cpu_R[rX], cpu_R[rY], i);
     } else {
         tcg_gen_setcond_tl(cond, cpu_R[rX], cpu_R[rY], cpu_R[rZ]);
     }
@@ -373,7 +383,7 @@ 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));
+                zero_extend(dc->imm16, 16));
     } else {
         LOG_DIS("cmpgeu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
     }
@@ -385,7 +395,7 @@ 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));
+                zero_extend(dc->imm16, 16));
     } else {
         LOG_DIS("cmpgu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
     }
commit 6036e9d87e73c511fef48a3c06267f92e613fca9
Author: Michael Walle <michael at walle.cc>
Date:   Fri Dec 14 18:13:06 2012 +0100

    tests: tcg: lm32: add more test cases
    
    Esp. for testing zero/sign extend in compare operations.
    
    Signed-off-by: Michael Walle <michael at walle.cc>

diff --git a/tests/tcg/lm32/test_cmpgei.S b/tests/tcg/lm32/test_cmpgei.S
index 6a8870f..6e388a2 100644
--- a/tests/tcg/lm32/test_cmpgei.S
+++ b/tests/tcg/lm32/test_cmpgei.S
@@ -52,4 +52,19 @@ mvi r3, 0
 cmpgei r3, r3, 0
 check_r3 1
 
+test_name CMPGEI_11
+mvi r1, 0
+cmpgei r3, r1, -32768
+check_r3 1
+
+test_name CMPGEI_12
+mvi r1, -1
+cmpgei r3, r1, -32768
+check_r3 1
+
+test_name CMPGEI_13
+mvi r1, -32768
+cmpgei r3, r1, -32768
+check_r3 1
+
 end
diff --git a/tests/tcg/lm32/test_cmpgeui.S b/tests/tcg/lm32/test_cmpgeui.S
index b9d1755..3866d96 100644
--- a/tests/tcg/lm32/test_cmpgeui.S
+++ b/tests/tcg/lm32/test_cmpgeui.S
@@ -52,4 +52,19 @@ mvi r3, 0
 cmpgeui r3, r3, 0
 check_r3 1
 
+test_name CMPGEUI_11
+mvi r1, 0
+cmpgeui r3, r1, 0x8000
+check_r3 0
+
+test_name CMPGEUI_12
+mvi r1, -1
+cmpgeui r3, r1, 0x8000
+check_r3 1
+
+test_name CMPGEUI_13
+ori r1, r0, 0x8000
+cmpgeui r3, r1, 0x8000
+check_r3 1
+
 end
diff --git a/tests/tcg/lm32/test_cmpgi.S b/tests/tcg/lm32/test_cmpgi.S
index 1f622d2..21695f9 100644
--- a/tests/tcg/lm32/test_cmpgi.S
+++ b/tests/tcg/lm32/test_cmpgi.S
@@ -52,4 +52,19 @@ mvi r3, 0
 cmpgi r3, r3, 0
 check_r3 0
 
+test_name CMPGI_11
+mvi r1, 0
+cmpgi r3, r1, -32768
+check_r3 1
+
+test_name CMPGI_12
+mvi r1, -1
+cmpgi r3, r1, -32768
+check_r3 1
+
+test_name CMPGI_13
+mvi r1, -32768
+cmpgi r3, r1, -32768
+check_r3 0
+
 end
diff --git a/tests/tcg/lm32/test_cmpgui.S b/tests/tcg/lm32/test_cmpgui.S
index 759bb64..dd94001 100644
--- a/tests/tcg/lm32/test_cmpgui.S
+++ b/tests/tcg/lm32/test_cmpgui.S
@@ -35,7 +35,7 @@ check_r3 1
 test_name CMPGUI_7
 mvi r1, -1
 cmpgui r3, r1, 0xffff
-check_r3 0
+check_r3 1
 
 test_name CMPGUI_8
 mvi r3, 0
@@ -52,4 +52,19 @@ mvi r3, 0
 cmpgui r3, r3, 0
 check_r3 0
 
+test_name CMPGUI_11
+mvi r1, 0
+cmpgui r3, r1, 0x8000
+check_r3 0
+
+test_name CMPGUI_12
+mvi r1, -1
+cmpgui r3, r1, 0x8000
+check_r3 1
+
+test_name CMPGUI_13
+ori r1, r0, 0x8000
+cmpgui r3, r1, 0x8000
+check_r3 0
+
 end
commit 608a03c1df217f2111765575a91c6448218369a7
Author: Michael Walle <michael at walle.cc>
Date:   Wed Sep 12 19:48:42 2012 +0200

    target-lm32: don't log cpu state in translation
    
    Don't dump the cpu state because it can also be enabled by the "-d cpu"
    parameter.
    
    Signed-off-by: Michael Walle <michael at walle.cc>

diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index 695d9c5..f51ffc5 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -1027,11 +1027,6 @@ static void gen_intermediate_code_internal(CPULM32State *env,
         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;
commit 562f5f5d9e8415cac3ca2eb768dabf068e8e0f4a
Author: Michael Walle <michael at walle.cc>
Date:   Tue Jul 31 00:04:57 2012 +0200

    lm32_uart: fix receive buffering
    
    Inform qemu-char when more input data can be received.
    
    Signed-off-by: Michael Walle <michael at walle.cc>

diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c
index 02f6f89..32bc37a 100644
--- a/hw/lm32_uart.c
+++ b/hw/lm32_uart.c
@@ -137,6 +137,7 @@ static uint64_t uart_read(void *opaque, hwaddr addr,
         r = s->regs[R_RXTX];
         s->regs[R_LSR] &= ~LSR_DR;
         uart_update_irq(s);
+        qemu_chr_accept_input(s->chr);
         break;
     case R_IIR:
     case R_LSR:
commit 44ac582d80688ea049c96a20868f4333c6885404
Author: Michael Walle <michael at walle.cc>
Date:   Tue Jul 31 00:04:57 2012 +0200

    milkymist-uart: fix receive buffering
    
    Inform qemu-char when more input data can be received.
    
    Signed-off-by: Michael Walle <michael at walle.cc>

diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c
index ac6f537..f3bdf69 100644
--- a/hw/milkymist-uart.c
+++ b/hw/milkymist-uart.c
@@ -132,6 +132,7 @@ static void uart_write(void *opaque, hwaddr addr, uint64_t value,
     case R_STAT:
         /* write one to clear bits */
         s->regs[addr] &= ~(value & (STAT_RX_EVT | STAT_TX_EVT));
+        qemu_chr_accept_input(s->chr);
         break;
 
     default:
commit ab2b9f174db088633922eaa82c2bcffd84e6bb94
Author: Michael Walle <michael at walle.cc>
Date:   Mon Jul 16 19:05:59 2012 +0200

    lm32-dis: fix NULL pointer dereference
    
    Signed-off-by: Michael Walle <michael at walle.cc>

diff --git a/disas/lm32.c b/disas/lm32.c
index a8eefe0..1718c86 100644
--- a/disas/lm32.c
+++ b/disas/lm32.c
@@ -303,11 +303,11 @@ int print_insn_lm32(bfd_vma memaddr, struct disassemble_info *info)
                 }
                 case 'c': {
                     uint8_t csr;
-                    const char *csr_name;
+                    const Lm32CsrInfo *info;
                     csr = (op >> 21) & 0x1f;
-                    csr_name = find_csr_info(csr)->name;
-                    if (csr_name) {
-                        fprintf_fn(stream, "%s", csr_name);
+                    info = find_csr_info(csr);
+                    if (info) {
+                        fprintf_fn(stream, "%s", info->name);
                     } else {
                         fprintf_fn(stream, "0x%x", csr);
                     }
commit b92e062a6f53251feef0969135b539d1fb33f7d6
Author: Michael Walle <michael at walle.cc>
Date:   Thu Apr 5 19:52:54 2012 +0200

    target-lm32: fix debug memory access
    
    CPU models which have the LM32_FLAG_IGNORE_MSB flag set will shadow the
    lower 2GB to the upper 2GB memory space. This will fix the debug memory
    access used by qemu console and GDB to match this behaviour.
    
    Signed-off-by: Michael Walle <michael at walle.cc>

diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index a0a8399..03fa5fb 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -39,7 +39,12 @@ int cpu_lm32_handle_mmu_fault(CPULM32State *env, target_ulong address, int rw,
 
 hwaddr cpu_get_phys_page_debug(CPULM32State *env, target_ulong addr)
 {
-    return addr & TARGET_PAGE_MASK;
+    addr &= TARGET_PAGE_MASK;
+    if (env->flags & LM32_FLAG_IGNORE_MSB) {
+        return addr & 0x7fffffff;
+    } else {
+        return addr;
+    }
 }
 
 void lm32_cpu_do_interrupt(CPUState *cs)
commit 2d62a95766025e6a0a333528278936e2cc8bf978
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Mon Mar 18 17:37:28 2013 +0100

    virtio-blk: cleanup: remove qdev field.
    
    The qdev field is no longer needed, just drop it.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1363624648-16906-12-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 663edcd..e6f8875 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -669,7 +669,6 @@ static int virtio_blk_device_init(VirtIODevice *vdev)
 #endif
 
     s->change = qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
-    s->qdev = qdev;
     register_savevm(qdev, "virtio-blk", virtio_blk_id++, 2,
                     virtio_blk_save, virtio_blk_load, s);
     bdrv_set_dev_ops(s->bs, &virtio_block_ops, s);
@@ -690,7 +689,7 @@ static int virtio_blk_device_exit(DeviceState *dev)
     s->dataplane = NULL;
 #endif
     qemu_del_vm_change_state_handler(s->change);
-    unregister_savevm(s->qdev, "virtio-blk", s);
+    unregister_savevm(dev, "virtio-blk", s);
     blockdev_mark_auto_del(s->bs);
     virtio_common_cleanup(vdev);
     return 0;
diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h
index 51ac010..8c6c78b 100644
--- a/hw/virtio-blk.h
+++ b/hw/virtio-blk.h
@@ -124,7 +124,6 @@ typedef struct VirtIOBlock {
     BlockConf *conf;
     VirtIOBlkConf blk;
     unsigned short sector_mask;
-    DeviceState *qdev;
     VMChangeStateEntry *change;
 #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
     VirtIOBlockDataPlane *dataplane;
commit 1cc91b7df687289abc0ae09083ac564d01408be8
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Mon Mar 18 17:37:27 2013 +0100

    virtio-blk: cleanup: QOM cast
    
    Use QOM casts inside virtio-blk.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1363624648-16906-11-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 9e7cd1f..663edcd 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -23,14 +23,6 @@
 #endif
 #include "hw/virtio-bus.h"
 
-/*
- * Moving to QOM later in this series.
- */
-static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
-{
-    return (VirtIOBlock *)vdev;
-}
-
 typedef struct VirtIOBlockReq
 {
     VirtIOBlock *dev;
@@ -46,12 +38,13 @@ typedef struct VirtIOBlockReq
 static void virtio_blk_req_complete(VirtIOBlockReq *req, int status)
 {
     VirtIOBlock *s = req->dev;
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
 
     trace_virtio_blk_req_complete(req, status);
 
     stb_p(&req->in->status, status);
     virtqueue_push(s->vq, &req->elem, req->qiov.size + sizeof(*req->in));
-    virtio_notify(&s->vdev, s->vq);
+    virtio_notify(vdev, s->vq);
 }
 
 static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
@@ -396,7 +389,7 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
 
 static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
 {
-    VirtIOBlock *s = to_virtio_blk(vdev);
+    VirtIOBlock *s = VIRTIO_BLK(vdev);
     VirtIOBlockReq *req;
     MultiReqBuffer mrb = {
         .num_writes = 0,
@@ -464,7 +457,7 @@ static void virtio_blk_dma_restart_cb(void *opaque, int running,
 static void virtio_blk_reset(VirtIODevice *vdev)
 {
 #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
-    VirtIOBlock *s = to_virtio_blk(vdev);
+    VirtIOBlock *s = VIRTIO_BLK(vdev);
 
     if (s->dataplane) {
         virtio_blk_data_plane_stop(s->dataplane);
@@ -482,7 +475,7 @@ static void virtio_blk_reset(VirtIODevice *vdev)
  */
 static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
 {
-    VirtIOBlock *s = to_virtio_blk(vdev);
+    VirtIOBlock *s = VIRTIO_BLK(vdev);
     struct virtio_blk_config blkcfg;
     uint64_t capacity;
     int blk_size = s->conf->logical_block_size;
@@ -521,7 +514,7 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
 
 static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
 {
-    VirtIOBlock *s = to_virtio_blk(vdev);
+    VirtIOBlock *s = VIRTIO_BLK(vdev);
     struct virtio_blk_config blkcfg;
 
     memcpy(&blkcfg, config, sizeof(blkcfg));
@@ -530,7 +523,7 @@ static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
 
 static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
 {
-    VirtIOBlock *s = to_virtio_blk(vdev);
+    VirtIOBlock *s = VIRTIO_BLK(vdev);
 
     features |= (1 << VIRTIO_BLK_F_SEG_MAX);
     features |= (1 << VIRTIO_BLK_F_GEOMETRY);
@@ -552,7 +545,7 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
 
 static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
 {
-    VirtIOBlock *s = to_virtio_blk(vdev);
+    VirtIOBlock *s = VIRTIO_BLK(vdev);
     uint32_t features;
 
 #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
@@ -573,9 +566,10 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
 static void virtio_blk_save(QEMUFile *f, void *opaque)
 {
     VirtIOBlock *s = opaque;
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
     VirtIOBlockReq *req = s->rq;
 
-    virtio_save(&s->vdev, f);
+    virtio_save(vdev, f);
     
     while (req) {
         qemu_put_sbyte(f, 1);
@@ -588,12 +582,13 @@ static void virtio_blk_save(QEMUFile *f, void *opaque)
 static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
 {
     VirtIOBlock *s = opaque;
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
     int ret;
 
     if (version_id != 2)
         return -EINVAL;
 
-    ret = virtio_load(&s->vdev, f);
+    ret = virtio_load(vdev, f);
     if (ret) {
         return ret;
     }
@@ -615,9 +610,9 @@ static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
 
 static void virtio_blk_resize(void *opaque)
 {
-    VirtIOBlock *s = opaque;
+    VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
 
-    virtio_notify_config(&s->vdev);
+    virtio_notify_config(vdev);
 }
 
 static const BlockDevOps virtio_block_ops = {
diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h
index a040c01..51ac010 100644
--- a/hw/virtio-blk.h
+++ b/hw/virtio-blk.h
@@ -116,7 +116,7 @@ struct VirtIOBlkConf
 };
 
 typedef struct VirtIOBlock {
-    VirtIODevice vdev;
+    VirtIODevice parent_obj;
     BlockDriverState *bs;
     VirtQueue *vq;
     void *rq;
commit 05ff686536f408ba6e8426b1b54d25bd3379fda2
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Mon Mar 18 17:37:26 2013 +0100

    virtio-blk: cleanup: init and exit functions.
    
    As all virtio-blk-* are switched to the new API, we can remove the separate
    init/exit for the old API.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1363624648-16906-10-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 3622bb9..9e7cd1f 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -630,102 +630,59 @@ void virtio_blk_set_conf(DeviceState *dev, VirtIOBlkConf *blk)
     memcpy(&(s->blk), blk, sizeof(struct VirtIOBlkConf));
 }
 
-static VirtIODevice *virtio_blk_common_init(DeviceState *dev,
-                                          VirtIOBlkConf *blk, VirtIOBlock **ps)
+static int virtio_blk_device_init(VirtIODevice *vdev)
 {
-    VirtIOBlock *s = *ps;
+    DeviceState *qdev = DEVICE(vdev);
+    VirtIOBlock *s = VIRTIO_BLK(vdev);
+    VirtIOBlkConf *blk = &(s->blk);
     static int virtio_blk_id;
 
     if (!blk->conf.bs) {
         error_report("drive property not set");
-        return NULL;
+        return -1;
     }
     if (!bdrv_is_inserted(blk->conf.bs)) {
         error_report("Device needs media, but drive is empty");
-        return NULL;
+        return -1;
     }
 
     blkconf_serial(&blk->conf, &blk->serial);
     if (blkconf_geometry(&blk->conf, NULL, 65535, 255, 255) < 0) {
-        return NULL;
+        return -1;
     }
 
-    /*
-     * We have two cases here: the old virtio-blk-pci device, and the
-     * refactored virtio-blk.
-     */
-    if (s == NULL) {
-        /* virtio-blk-pci */
-        s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
-                                              sizeof(struct virtio_blk_config),
-                                              sizeof(VirtIOBlock));
-    } else {
-        /* virtio-blk */
-        virtio_init(VIRTIO_DEVICE(s), "virtio-blk", VIRTIO_ID_BLOCK,
-                    sizeof(struct virtio_blk_config));
-    }
+    virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK,
+                sizeof(struct virtio_blk_config));
 
-    s->vdev.get_config = virtio_blk_update_config;
-    s->vdev.set_config = virtio_blk_set_config;
-    s->vdev.get_features = virtio_blk_get_features;
-    s->vdev.set_status = virtio_blk_set_status;
-    s->vdev.reset = virtio_blk_reset;
+    vdev->get_config = virtio_blk_update_config;
+    vdev->set_config = virtio_blk_set_config;
+    vdev->get_features = virtio_blk_get_features;
+    vdev->set_status = virtio_blk_set_status;
+    vdev->reset = virtio_blk_reset;
     s->bs = blk->conf.bs;
     s->conf = &blk->conf;
     memcpy(&(s->blk), blk, sizeof(struct VirtIOBlkConf));
     s->rq = NULL;
     s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
 
-    s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
+    s->vq = virtio_add_queue(vdev, 128, virtio_blk_handle_output);
 #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
-    if (!virtio_blk_data_plane_create(&s->vdev, blk, &s->dataplane)) {
-        virtio_cleanup(&s->vdev);
-        return NULL;
+    if (!virtio_blk_data_plane_create(vdev, blk, &s->dataplane)) {
+        virtio_cleanup(vdev);
+        return -1;
     }
 #endif
 
     s->change = qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
-    s->qdev = dev;
-    register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
+    s->qdev = qdev;
+    register_savevm(qdev, "virtio-blk", virtio_blk_id++, 2,
                     virtio_blk_save, virtio_blk_load, s);
     bdrv_set_dev_ops(s->bs, &virtio_block_ops, s);
     bdrv_set_buffer_alignment(s->bs, s->conf->logical_block_size);
 
     bdrv_iostatus_enable(s->bs);
-    add_boot_device_path(s->conf->bootindex, dev, "/disk at 0,0");
 
-    return &s->vdev;
-}
-
-VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
-{
-    VirtIOBlock *s = NULL;
-    return virtio_blk_common_init(dev, blk, &s);
-}
-
-void virtio_blk_exit(VirtIODevice *vdev)
-{
-    VirtIOBlock *s = to_virtio_blk(vdev);
-
-#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
-    virtio_blk_data_plane_destroy(s->dataplane);
-    s->dataplane = NULL;
-#endif
-    qemu_del_vm_change_state_handler(s->change);
-    unregister_savevm(s->qdev, "virtio-blk", s);
-    blockdev_mark_auto_del(s->bs);
-    virtio_cleanup(vdev);
-}
-
-
-static int virtio_blk_device_init(VirtIODevice *vdev)
-{
-    DeviceState *qdev = DEVICE(vdev);
-    VirtIOBlock *s = VIRTIO_BLK(vdev);
-    VirtIOBlkConf *blk = &(s->blk);
-    if (virtio_blk_common_init(qdev, blk, &s) == NULL) {
-        return -1;
-    }
+    add_boot_device_path(s->conf->bootindex, qdev, "/disk at 0,0");
     return 0;
 }
 
diff --git a/hw/virtio.h b/hw/virtio.h
index ca43fd7..fdbe931 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -240,7 +240,6 @@ void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
 
 /* Base devices.  */
 typedef struct VirtIOBlkConf VirtIOBlkConf;
-VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk);
 struct virtio_net_conf;
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
                               struct virtio_net_conf *net,
@@ -258,7 +257,6 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
 
 
 void virtio_net_exit(VirtIODevice *vdev);
-void virtio_blk_exit(VirtIODevice *vdev);
 void virtio_serial_exit(VirtIODevice *vdev);
 void virtio_balloon_exit(VirtIODevice *vdev);
 void virtio_scsi_exit(VirtIODevice *vdev);
commit 3400c455048a8db26db1b537ea32fa21335ea301
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Mon Mar 18 17:37:25 2013 +0100

    virtio-blk-ccw switch to new API.
    
    Here the virtio-ccw-s390 is modified for the new API. The device
    virtio-ccw-s390 extends virtio-ccw-device as before. It creates and
    connects a virtio-ccw during the init. The properties are not modified.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1363624648-16906-9-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index d80de67..9688835 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -570,22 +570,24 @@ static int virtio_ccw_net_exit(VirtioCcwDevice *dev)
     return virtio_ccw_exit(dev);
 }
 
-static int virtio_ccw_blk_init(VirtioCcwDevice *dev)
+static int virtio_ccw_blk_init(VirtioCcwDevice *ccw_dev)
 {
-    VirtIODevice *vdev;
-
-    vdev = virtio_blk_init((DeviceState *)dev, &dev->blk);
-    if (!vdev) {
+    VirtIOBlkCcw *dev = VIRTIO_BLK_CCW(ccw_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
+    virtio_blk_set_conf(vdev, &(dev->blk));
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    if (qdev_init(vdev) < 0) {
         return -1;
     }
 
-    return virtio_ccw_device_init(dev, vdev);
+    return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
 }
 
-static int virtio_ccw_blk_exit(VirtioCcwDevice *dev)
+static void virtio_ccw_blk_instance_init(Object *obj)
 {
-    virtio_blk_exit(dev->vdev);
-    return virtio_ccw_exit(dev);
+    VirtIOBlkCcw *dev = VIRTIO_BLK_CCW(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_BLK);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 }
 
 static int virtio_ccw_serial_init(VirtioCcwDevice *dev)
@@ -754,10 +756,10 @@ static const TypeInfo virtio_ccw_net = {
 
 static Property virtio_ccw_blk_properties[] = {
     DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
-    DEFINE_BLOCK_PROPERTIES(VirtioCcwDevice, blk.conf),
-    DEFINE_PROP_STRING("serial", VirtioCcwDevice, blk.serial),
+    DEFINE_BLOCK_PROPERTIES(VirtIOBlkCcw, blk.conf),
+    DEFINE_PROP_STRING("serial", VirtIOBlkCcw, blk.serial),
 #ifdef __linux__
-    DEFINE_PROP_BIT("scsi", VirtioCcwDevice, blk.scsi, 0, true),
+    DEFINE_PROP_BIT("scsi", VirtIOBlkCcw, blk.scsi, 0, true),
 #endif
     DEFINE_VIRTIO_BLK_FEATURES(VirtioCcwDevice, host_features[0]),
     DEFINE_PROP_END_OF_LIST(),
@@ -769,15 +771,16 @@ static void virtio_ccw_blk_class_init(ObjectClass *klass, void *data)
     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
 
     k->init = virtio_ccw_blk_init;
-    k->exit = virtio_ccw_blk_exit;
+    k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
     dc->props = virtio_ccw_blk_properties;
 }
 
 static const TypeInfo virtio_ccw_blk = {
-    .name          = "virtio-blk-ccw",
+    .name          = TYPE_VIRTIO_BLK_CCW,
     .parent        = TYPE_VIRTIO_CCW_DEVICE,
-    .instance_size = sizeof(VirtioCcwDevice),
+    .instance_size = sizeof(VirtIOBlkCcw),
+    .instance_init = virtio_ccw_blk_instance_init,
     .class_init    = virtio_ccw_blk_class_init,
 };
 
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 88c46c0..3993bc5 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -72,7 +72,6 @@ struct VirtioCcwDevice {
     SubchDev *sch;
     VirtIODevice *vdev;
     char *bus_id;
-    VirtIOBlkConf blk;
     NICConf nic;
     uint32_t host_features[VIRTIO_CCW_FEATURE_SIZE];
     virtio_serial_conf serial;
@@ -94,6 +93,19 @@ typedef struct VirtualCssBus {
 #define VIRTUAL_CSS_BUS(obj) \
      OBJECT_CHECK(VirtualCssBus, (obj), TYPE_VIRTUAL_CSS_BUS)
 
+/* virtio-blk-ccw */
+
+#define TYPE_VIRTIO_BLK_CCW "virtio-blk-ccw"
+#define VIRTIO_BLK_CCW(obj) \
+        OBJECT_CHECK(VirtIOBlkCcw, (obj), TYPE_VIRTIO_BLK_CCW)
+
+typedef struct VirtIOBlkCcw {
+    VirtioCcwDevice parent_obj;
+    VirtIOBlock vdev;
+    VirtIOBlkConf blk;
+} VirtIOBlkCcw;
+
+
 VirtualCssBus *virtual_css_bus_init(void);
 void virtio_ccw_device_update_status(SubchDev *sch);
 VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch);
commit 55d11e01cca9b83b8cdccbd29d4f078cbe4a185c
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Mon Mar 18 17:37:24 2013 +0100

    virtio-blk-s390: switch to the new API.
    
    Here the virtio-blk-s390 is modified for the new API. The device
    virtio-blk-s390 extends virtio-s390-device as before. It creates and
    connects a virtio-blk during the init. The properties are not modified.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1363624648-16906-8-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index 8d4fd72..76bc99a 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -162,16 +162,23 @@ static int s390_virtio_net_init(VirtIOS390Device *dev)
     return s390_virtio_device_init(dev, vdev);
 }
 
-static int s390_virtio_blk_init(VirtIOS390Device *dev)
+static int s390_virtio_blk_init(VirtIOS390Device *s390_dev)
 {
-    VirtIODevice *vdev;
-
-    vdev = virtio_blk_init((DeviceState *)dev, &dev->blk);
-    if (!vdev) {
+    VirtIOBlkS390 *dev = VIRTIO_BLK_S390(s390_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
+    virtio_blk_set_conf(vdev, &(dev->blk));
+    qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
+    if (qdev_init(vdev) < 0) {
         return -1;
     }
+    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
+}
 
-    return s390_virtio_device_init(dev, vdev);
+static void s390_virtio_blk_instance_init(Object *obj)
+{
+    VirtIOBlkS390 *dev = VIRTIO_BLK_S390(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_BLK);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 }
 
 static int s390_virtio_serial_init(VirtIOS390Device *dev)
@@ -428,11 +435,11 @@ static const TypeInfo s390_virtio_net = {
 };
 
 static Property s390_virtio_blk_properties[] = {
-    DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, blk.conf),
-    DEFINE_BLOCK_CHS_PROPERTIES(VirtIOS390Device, blk.conf),
-    DEFINE_PROP_STRING("serial", VirtIOS390Device, blk.serial),
+    DEFINE_BLOCK_PROPERTIES(VirtIOBlkS390, blk.conf),
+    DEFINE_BLOCK_CHS_PROPERTIES(VirtIOBlkS390, blk.conf),
+    DEFINE_PROP_STRING("serial", VirtIOBlkS390, blk.serial),
 #ifdef __linux__
-    DEFINE_PROP_BIT("scsi", VirtIOS390Device, blk.scsi, 0, true),
+    DEFINE_PROP_BIT("scsi", VirtIOBlkS390, blk.scsi, 0, true),
 #endif
     DEFINE_PROP_END_OF_LIST(),
 };
@@ -449,7 +456,8 @@ static void s390_virtio_blk_class_init(ObjectClass *klass, void *data)
 static const TypeInfo s390_virtio_blk = {
     .name          = "virtio-blk-s390",
     .parent        = TYPE_VIRTIO_S390_DEVICE,
-    .instance_size = sizeof(VirtIOS390Device),
+    .instance_size = sizeof(VirtIOBlkS390),
+    .instance_init = s390_virtio_blk_instance_init,
     .class_init    = s390_virtio_blk_class_init,
 };
 
diff --git a/hw/s390x/s390-virtio-bus.h b/hw/s390x/s390-virtio-bus.h
index 4aacf83..1a63411 100644
--- a/hw/s390x/s390-virtio-bus.h
+++ b/hw/s390x/s390-virtio-bus.h
@@ -89,7 +89,6 @@ struct VirtIOS390Device {
     ram_addr_t feat_offs;
     uint8_t feat_len;
     VirtIODevice *vdev;
-    VirtIOBlkConf blk;
     NICConf nic;
     uint32_t host_features;
     virtio_serial_conf serial;
@@ -120,5 +119,17 @@ VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem);
 void s390_virtio_device_sync(VirtIOS390Device *dev);
 void s390_virtio_reset_idx(VirtIOS390Device *dev);
 
+/* virtio-blk-s390 */
+
+#define TYPE_VIRTIO_BLK_S390 "virtio-blk-s390"
+#define VIRTIO_BLK_S390(obj) \
+        OBJECT_CHECK(VirtIOBlkS390, (obj), TYPE_VIRTIO_BLK_S390)
+
+typedef struct VirtIOBlkS390 {
+    VirtIOS390Device parent_obj;
+    VirtIOBlock vdev;
+    VirtIOBlkConf blk;
+} VirtIOBlkS390;
+
 
 #endif
commit 653ced071b061bbd9cc7d03374be93dcefb37910
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Mon Mar 18 17:37:23 2013 +0100

    virtio-blk-pci: switch to new API.
    
    Here the virtio-blk-pci is modified for the new API. The device
    virtio-blk-pci extends virtio-pci. It creates and connects a virtio-blk
    during the init. The properties are not changed.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1363624648-16906-7-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index c0b859c..d65f085 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -924,26 +924,6 @@ void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev)
     proxy->host_features = vdev->get_features(vdev, proxy->host_features);
 }
 
-static int virtio_blk_init_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-    VirtIODevice *vdev;
-
-    if (proxy->class_code != PCI_CLASS_STORAGE_SCSI &&
-        proxy->class_code != PCI_CLASS_STORAGE_OTHER)
-        proxy->class_code = PCI_CLASS_STORAGE_SCSI;
-
-    vdev = virtio_blk_init(&pci_dev->qdev, &proxy->blk);
-    if (!vdev) {
-        return -1;
-    }
-    vdev->nvectors = proxy->nvectors;
-    virtio_init_pci(proxy, vdev);
-    /* make the actual value visible */
-    proxy->nvectors = vdev->nvectors;
-    return 0;
-}
-
 static void virtio_exit_pci(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
@@ -952,15 +932,6 @@ static void virtio_exit_pci(PCIDevice *pci_dev)
     msix_uninit_exclusive_bar(pci_dev);
 }
 
-static void virtio_blk_exit_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-
-    virtio_pci_stop_ioeventfd(proxy);
-    virtio_blk_exit(proxy->vdev);
-    virtio_exit_pci(pci_dev);
-}
-
 static int virtio_serial_init_pci(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
@@ -1082,40 +1053,6 @@ static void virtio_rng_exit_pci(PCIDevice *pci_dev)
     virtio_exit_pci(pci_dev);
 }
 
-static Property virtio_blk_properties[] = {
-    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
-    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
-#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
-    DEFINE_PROP_BIT("x-data-plane", VirtIOPCIProxy, blk.data_plane, 0, false),
-#endif
-    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
-    DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
-    DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOPCIProxy, blk),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void virtio_blk_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = virtio_blk_init_pci;
-    k->exit = virtio_blk_exit_pci;
-    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
-    k->device_id = PCI_DEVICE_ID_VIRTIO_BLOCK;
-    k->revision = VIRTIO_PCI_ABI_VERSION;
-    k->class_id = PCI_CLASS_STORAGE_SCSI;
-    dc->reset = virtio_pci_reset;
-    dc->props = virtio_blk_properties;
-}
-
-static const TypeInfo virtio_blk_info = {
-    .name          = "virtio-blk-pci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(VirtIOPCIProxy),
-    .class_init    = virtio_blk_class_init,
-};
-
 static Property virtio_net_properties[] = {
     DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
     DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
@@ -1460,6 +1397,62 @@ static const TypeInfo virtio_pci_info = {
     .abstract      = true,
 };
 
+/* virtio-blk-pci */
+
+static Property virtio_blk_pci_properties[] = {
+    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
+    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
+                    VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
+    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+    DEFINE_PROP_BIT("x-data-plane", VirtIOBlkPCI, blk.data_plane, 0, false),
+#endif
+    DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOBlkPCI, blk),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static int virtio_blk_pci_init(VirtIOPCIProxy *vpci_dev)
+{
+    VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(vpci_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
+    virtio_blk_set_conf(vdev, &(dev->blk));
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    if (qdev_init(vdev) < 0) {
+        return -1;
+    }
+    return 0;
+}
+
+static void virtio_blk_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
+    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+
+    dc->props = virtio_blk_pci_properties;
+    k->init = virtio_blk_pci_init;
+    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BLOCK;
+    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
+    pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI;
+}
+
+static void virtio_blk_pci_instance_init(Object *obj)
+{
+    VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_BLK);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+}
+
+static const TypeInfo virtio_blk_pci_info = {
+    .name          = TYPE_VIRTIO_BLK_PCI,
+    .parent        = TYPE_VIRTIO_PCI,
+    .instance_size = sizeof(VirtIOBlkPCI),
+    .instance_init = virtio_blk_pci_instance_init,
+    .class_init    = virtio_blk_pci_class_init,
+};
+
 /* virtio-pci-bus */
 
 void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev)
@@ -1498,7 +1491,6 @@ static const TypeInfo virtio_pci_bus_info = {
 
 static void virtio_pci_register_types(void)
 {
-    type_register_static(&virtio_blk_info);
     type_register_static(&virtio_net_info);
     type_register_static(&virtio_serial_info);
     type_register_static(&virtio_balloon_info);
@@ -1509,6 +1501,7 @@ static void virtio_pci_register_types(void)
 #ifdef CONFIG_VIRTFS
     type_register_static(&virtio_9p_info);
 #endif
+    type_register_static(&virtio_blk_pci_info);
 }
 
 type_init(virtio_pci_register_types)
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index 2ae96f8..a9dbfff 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -25,6 +25,7 @@
 #include "hw/9pfs/virtio-9p-device.h"
 
 typedef struct VirtIOPCIProxy VirtIOPCIProxy;
+typedef struct VirtIOBlkPCI VirtIOBlkPCI;
 
 /* virtio-pci-bus */
 
@@ -73,7 +74,6 @@ struct VirtIOPCIProxy {
     uint32_t flags;
     uint32_t class_code;
     uint32_t nvectors;
-    VirtIOBlkConf blk;
     NICConf nic;
     uint32_t host_features;
 #ifdef CONFIG_VIRTFS
@@ -90,6 +90,19 @@ struct VirtIOPCIProxy {
     VirtioBusState bus;
 };
 
+/*
+ * virtio-blk-pci: This extends VirtioPCIProxy.
+ */
+#define TYPE_VIRTIO_BLK_PCI "virtio-blk-pci"
+#define VIRTIO_BLK_PCI(obj) \
+        OBJECT_CHECK(VirtIOBlkPCI, (obj), TYPE_VIRTIO_BLK_PCI)
+
+struct VirtIOBlkPCI {
+    VirtIOPCIProxy parent_obj;
+    VirtIOBlock vdev;
+    VirtIOBlkConf blk;
+};
+
 void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
 void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev);
 
commit 1c028ddfb0c5004c8ec86c96ae09068026e77a38
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Mon Mar 18 17:37:22 2013 +0100

    virtio-blk: add the virtio-blk device.
    
    Create virtio-blk which extends virtio-device, so it can be connected on
    virtio-bus.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1363624648-16906-6-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 908c316..3622bb9 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -21,7 +21,11 @@
 #ifdef __linux__
 # include <scsi/sg.h>
 #endif
+#include "hw/virtio-bus.h"
 
+/*
+ * Moving to QOM later in this series.
+ */
 static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
 {
     return (VirtIOBlock *)vdev;
@@ -620,9 +624,16 @@ static const BlockDevOps virtio_block_ops = {
     .resize_cb = virtio_blk_resize,
 };
 
-VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
+void virtio_blk_set_conf(DeviceState *dev, VirtIOBlkConf *blk)
 {
-    VirtIOBlock *s;
+    VirtIOBlock *s = VIRTIO_BLK(dev);
+    memcpy(&(s->blk), blk, sizeof(struct VirtIOBlkConf));
+}
+
+static VirtIODevice *virtio_blk_common_init(DeviceState *dev,
+                                          VirtIOBlkConf *blk, VirtIOBlock **ps)
+{
+    VirtIOBlock *s = *ps;
     static int virtio_blk_id;
 
     if (!blk->conf.bs) {
@@ -639,9 +650,20 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
         return NULL;
     }
 
-    s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
-                                          sizeof(struct virtio_blk_config),
-                                          sizeof(VirtIOBlock));
+    /*
+     * We have two cases here: the old virtio-blk-pci device, and the
+     * refactored virtio-blk.
+     */
+    if (s == NULL) {
+        /* virtio-blk-pci */
+        s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
+                                              sizeof(struct virtio_blk_config),
+                                              sizeof(VirtIOBlock));
+    } else {
+        /* virtio-blk */
+        virtio_init(VIRTIO_DEVICE(s), "virtio-blk", VIRTIO_ID_BLOCK,
+                    sizeof(struct virtio_blk_config));
+    }
 
     s->vdev.get_config = virtio_blk_update_config;
     s->vdev.set_config = virtio_blk_set_config;
@@ -675,6 +697,12 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
     return &s->vdev;
 }
 
+VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
+{
+    VirtIOBlock *s = NULL;
+    return virtio_blk_common_init(dev, blk, &s);
+}
+
 void virtio_blk_exit(VirtIODevice *vdev)
 {
     VirtIOBlock *s = to_virtio_blk(vdev);
@@ -688,3 +716,63 @@ void virtio_blk_exit(VirtIODevice *vdev)
     blockdev_mark_auto_del(s->bs);
     virtio_cleanup(vdev);
 }
+
+
+static int virtio_blk_device_init(VirtIODevice *vdev)
+{
+    DeviceState *qdev = DEVICE(vdev);
+    VirtIOBlock *s = VIRTIO_BLK(vdev);
+    VirtIOBlkConf *blk = &(s->blk);
+    if (virtio_blk_common_init(qdev, blk, &s) == NULL) {
+        return -1;
+    }
+    return 0;
+}
+
+static int virtio_blk_device_exit(DeviceState *dev)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VirtIOBlock *s = VIRTIO_BLK(dev);
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+    virtio_blk_data_plane_destroy(s->dataplane);
+    s->dataplane = NULL;
+#endif
+    qemu_del_vm_change_state_handler(s->change);
+    unregister_savevm(s->qdev, "virtio-blk", s);
+    blockdev_mark_auto_del(s->bs);
+    virtio_common_cleanup(vdev);
+    return 0;
+}
+
+static Property virtio_blk_properties[] = {
+    DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOBlock, blk),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_blk_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+    dc->exit = virtio_blk_device_exit;
+    dc->props = virtio_blk_properties;
+    vdc->init = virtio_blk_device_init;
+    vdc->get_config = virtio_blk_update_config;
+    vdc->set_config = virtio_blk_set_config;
+    vdc->get_features = virtio_blk_get_features;
+    vdc->set_status = virtio_blk_set_status;
+    vdc->reset = virtio_blk_reset;
+}
+
+static const TypeInfo virtio_device_info = {
+    .name = TYPE_VIRTIO_BLK,
+    .parent = TYPE_VIRTIO_DEVICE,
+    .instance_size = sizeof(VirtIOBlock),
+    .class_init = virtio_blk_class_init,
+};
+
+static void virtio_register_types(void)
+{
+    type_register_static(&virtio_device_info);
+}
+
+type_init(virtio_register_types)
diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h
index b704d50..a040c01 100644
--- a/hw/virtio-blk.h
+++ b/hw/virtio-blk.h
@@ -20,6 +20,10 @@
 #include "dataplane/virtio-blk.h"
 #endif
 
+#define TYPE_VIRTIO_BLK "virtio-blk"
+#define VIRTIO_BLK(obj) \
+        OBJECT_CHECK(VirtIOBlock, (obj), TYPE_VIRTIO_BLK)
+
 /* from Linux's linux/virtio_blk.h */
 
 /* The ID for virtio_block */
@@ -130,4 +134,21 @@ typedef struct VirtIOBlock {
 #define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
         DEFINE_VIRTIO_COMMON_FEATURES(_state, _field)
 
+#ifdef __linux__
+#define DEFINE_VIRTIO_BLK_PROPERTIES(_state, _field)                          \
+        DEFINE_BLOCK_PROPERTIES(_state, _field.conf),                         \
+        DEFINE_BLOCK_CHS_PROPERTIES(_state, _field.conf),                     \
+        DEFINE_PROP_STRING("serial", _state, _field.serial),                  \
+        DEFINE_PROP_BIT("config-wce", _state, _field.config_wce, 0, true),    \
+        DEFINE_PROP_BIT("scsi", _state, _field.scsi, 0, true)
+#else
+#define DEFINE_VIRTIO_BLK_PROPERTIES(_state, _field)                          \
+        DEFINE_BLOCK_PROPERTIES(_state, _field.conf),                         \
+        DEFINE_BLOCK_CHS_PROPERTIES(_state, _field.conf),                     \
+        DEFINE_PROP_STRING("serial", _state, _field.serial),                  \
+        DEFINE_PROP_BIT("config-wce", _state, _field.config_wce, 0, true)
+#endif /* __linux__ */
+
+void virtio_blk_set_conf(DeviceState *dev, VirtIOBlkConf *blk);
+
 #endif
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index f0dd823..c0b859c 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -1084,19 +1084,13 @@ static void virtio_rng_exit_pci(PCIDevice *pci_dev)
 
 static Property virtio_blk_properties[] = {
     DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
-    DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, blk.conf),
-    DEFINE_BLOCK_CHS_PROPERTIES(VirtIOPCIProxy, blk.conf),
-    DEFINE_PROP_STRING("serial", VirtIOPCIProxy, blk.serial),
-#ifdef __linux__
-    DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true),
-#endif
-    DEFINE_PROP_BIT("config-wce", VirtIOPCIProxy, blk.config_wce, 0, true),
     DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
 #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
     DEFINE_PROP_BIT("x-data-plane", VirtIOPCIProxy, blk.data_plane, 0, false),
 #endif
     DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
     DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOPCIProxy, blk),
     DEFINE_PROP_END_OF_LIST(),
 };
 
commit da3dcefa648f92bfef2f99351fb6ec6a86da4695
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Mon Mar 18 17:37:21 2013 +0100

    virtio-blk: don't use pointer for configuration.
    
    The configuration field must not be a pointer as it will be used for virtio-blk
    properties. So *blk is replaced by blk in VirtIOBlock structure.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1363624648-16906-5-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 6714b01..908c316 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -151,7 +151,7 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
      */
     req->scsi = (void *)req->elem.in_sg[req->elem.in_num - 2].iov_base;
 
-    if (!req->dev->blk->scsi) {
+    if (!req->dev->blk.scsi) {
         status = VIRTIO_BLK_S_UNSUPP;
         goto fail;
     }
@@ -371,7 +371,7 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
          * terminated by '\0' only when shorter than buffer.
          */
         strncpy(req->elem.in_sg[0].iov_base,
-                s->blk->serial ? s->blk->serial : "",
+                s->blk.serial ? s->blk.serial : "",
                 MIN(req->elem.in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES));
         virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
         g_free(req);
@@ -534,7 +534,7 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
     features |= (1 << VIRTIO_BLK_F_BLK_SIZE);
     features |= (1 << VIRTIO_BLK_F_SCSI);
 
-    if (s->blk->config_wce) {
+    if (s->blk.config_wce) {
         features |= (1 << VIRTIO_BLK_F_CONFIG_WCE);
     }
     if (bdrv_enable_write_cache(s->bs))
@@ -650,7 +650,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
     s->vdev.reset = virtio_blk_reset;
     s->bs = blk->conf.bs;
     s->conf = &blk->conf;
-    s->blk = blk;
+    memcpy(&(s->blk), blk, sizeof(struct VirtIOBlkConf));
     s->rq = NULL;
     s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
 
diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h
index 19ec569..b704d50 100644
--- a/hw/virtio-blk.h
+++ b/hw/virtio-blk.h
@@ -118,7 +118,7 @@ typedef struct VirtIOBlock {
     void *rq;
     QEMUBH *bh;
     BlockConf *conf;
-    VirtIOBlkConf *blk;
+    VirtIOBlkConf blk;
     unsigned short sector_mask;
     DeviceState *qdev;
     VMChangeStateEntry *change;
commit 10479a80893fb2666026ce0fea2251be3070b6e2
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Mon Mar 18 17:37:20 2013 +0100

    virtio-pci: fix hot unplug.
    
    Hot unplug failed because it tried to free the virtio device two times.
    
    This fix the issue by removing the call to virtio_bus_destroy_device.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Message-id: 1363624648-16906-4-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index c795cc6..f0dd823 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -1412,13 +1412,6 @@ static void virtio_pci_device_plugged(DeviceState *d)
                                                       proxy->host_features);
 }
 
-/* This is called by virtio-bus just before the device is unplugged. */
-static void virtio_pci_device_unplug(DeviceState *d)
-{
-    VirtIOPCIProxy *dev = VIRTIO_PCI(d);
-    virtio_pci_stop_ioeventfd(dev);
-}
-
 static int virtio_pci_init(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *dev = VIRTIO_PCI(pci_dev);
@@ -1433,10 +1426,7 @@ static int virtio_pci_init(PCIDevice *pci_dev)
 static void virtio_pci_exit(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev);
-    VirtioBusState *bus = VIRTIO_BUS(&proxy->bus);
-    BusState *qbus = BUS(&proxy->bus);
-    virtio_bus_destroy_device(bus);
-    qbus_free(qbus);
+    virtio_pci_stop_ioeventfd(proxy);
     virtio_exit_pci(pci_dev);
 }
 
@@ -1503,7 +1493,6 @@ static void virtio_pci_bus_class_init(ObjectClass *klass, void *data)
     k->set_guest_notifiers = virtio_pci_set_guest_notifiers;
     k->vmstate_change = virtio_pci_vmstate_change;
     k->device_plugged = virtio_pci_device_plugged;
-    k->device_unplug = virtio_pci_device_unplug;
 }
 
 static const TypeInfo virtio_pci_bus_info = {
commit cbd19063e75c64ac5e4029f76198c7ba65a63b00
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Mon Mar 18 17:37:19 2013 +0100

    virtio-x-bus: fix allow_hotplug assertion.
    
    This set allow_hotplug for each existing virtio-x-bus, allowing the
    refactored devices to be hot pluggable.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Message-id: 1363624648-16906-3-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index d9b7f83..8d4fd72 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -588,7 +588,7 @@ void virtio_s390_bus_new(VirtioBusState *bus, VirtIOS390Device *dev)
     BusState *qbus;
     qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_S390_BUS, qdev, NULL);
     qbus = BUS(bus);
-    qbus->allow_hotplug = 0;
+    qbus->allow_hotplug = 1;
 }
 
 static void virtio_s390_bus_class_init(ObjectClass *klass, void *data)
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index d4361f6..d80de67 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -982,7 +982,7 @@ void virtio_ccw_bus_new(VirtioBusState *bus, VirtioCcwDevice *dev)
 
     qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_CCW_BUS, qdev, NULL);
     qbus = BUS(bus);
-    qbus->allow_hotplug = 0;
+    qbus->allow_hotplug = 1;
 }
 
 static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data)
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 39c1966..c795cc6 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -1484,7 +1484,7 @@ void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev)
     BusState *qbus;
     qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_PCI_BUS, qdev, NULL);
     qbus = BUS(bus);
-    qbus->allow_hotplug = 0;
+    qbus->allow_hotplug = 1;
 }
 
 static void virtio_pci_bus_class_init(ObjectClass *klass, void *data)
commit f1b24e840f9f85a2bb3912e4507d887e7858219d
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Mon Mar 18 17:37:18 2013 +0100

    virtio: make virtio device's structures public.
    
    These structures must be made public to avoid two memory allocations for
    refactored virtio devices.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1363624648-16906-2-git-send-email-fred.konrad at greensocs.com
    
    Changes V4 <- V3:
       * Rebased on current git.
    
    Changes V3 <- V2:
        * Style correction spotted by Andreas (virtio-scsi.h).
        * Style correction for virtio-net.h.
    
    Changes V2 <- V1:
        * Move the dataplane include into the header (virtio-blk).
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index 6bfcddc..54a4372 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -29,21 +29,6 @@
 #include <sys/mman.h>
 #endif
 
-typedef struct VirtIOBalloon
-{
-    VirtIODevice vdev;
-    VirtQueue *ivq, *dvq, *svq;
-    uint32_t num_pages;
-    uint32_t actual;
-    uint64_t stats[VIRTIO_BALLOON_S_NR];
-    VirtQueueElement stats_vq_elem;
-    size_t stats_vq_offset;
-    QEMUTimer *stats_timer;
-    int64_t stats_last_update;
-    int64_t stats_poll_interval;
-    DeviceState *qdev;
-} VirtIOBalloon;
-
 static VirtIOBalloon *to_virtio_balloon(VirtIODevice *vdev)
 {
     return (VirtIOBalloon *)vdev;
diff --git a/hw/virtio-balloon.h b/hw/virtio-balloon.h
index f37f31b..b007042 100644
--- a/hw/virtio-balloon.h
+++ b/hw/virtio-balloon.h
@@ -52,4 +52,18 @@ typedef struct VirtIOBalloonStat {
     uint64_t val;
 } QEMU_PACKED VirtIOBalloonStat;
 
+typedef struct VirtIOBalloon {
+    VirtIODevice vdev;
+    VirtQueue *ivq, *dvq, *svq;
+    uint32_t num_pages;
+    uint32_t actual;
+    uint64_t stats[VIRTIO_BALLOON_S_NR];
+    VirtQueueElement stats_vq_elem;
+    size_t stats_vq_offset;
+    QEMUTimer *stats_timer;
+    int64_t stats_last_update;
+    int64_t stats_poll_interval;
+    DeviceState *qdev;
+} VirtIOBalloon;
+
 #endif
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 6b69236..6714b01 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -17,31 +17,11 @@
 #include "hw/block-common.h"
 #include "sysemu/blockdev.h"
 #include "hw/virtio-blk.h"
-#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
-#include "dataplane/virtio-blk.h"
-#endif
 #include "hw/scsi-defs.h"
 #ifdef __linux__
 # include <scsi/sg.h>
 #endif
 
-typedef struct VirtIOBlock
-{
-    VirtIODevice vdev;
-    BlockDriverState *bs;
-    VirtQueue *vq;
-    void *rq;
-    QEMUBH *bh;
-    BlockConf *conf;
-    VirtIOBlkConf *blk;
-    unsigned short sector_mask;
-    DeviceState *qdev;
-    VMChangeStateEntry *change;
-#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
-    VirtIOBlockDataPlane *dataplane;
-#endif
-} VirtIOBlock;
-
 static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
 {
     return (VirtIOBlock *)vdev;
diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h
index 7ef2f35..19ec569 100644
--- a/hw/virtio-blk.h
+++ b/hw/virtio-blk.h
@@ -16,6 +16,9 @@
 
 #include "hw/virtio.h"
 #include "hw/block-common.h"
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+#include "dataplane/virtio-blk.h"
+#endif
 
 /* from Linux's linux/virtio_blk.h */
 
@@ -108,6 +111,22 @@ struct VirtIOBlkConf
     uint32_t data_plane;
 };
 
+typedef struct VirtIOBlock {
+    VirtIODevice vdev;
+    BlockDriverState *bs;
+    VirtQueue *vq;
+    void *rq;
+    QEMUBH *bh;
+    BlockConf *conf;
+    VirtIOBlkConf *blk;
+    unsigned short sector_mask;
+    DeviceState *qdev;
+    VMChangeStateEntry *change;
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+    VirtIOBlockDataPlane *dataplane;
+#endif
+} VirtIOBlock;
+
 #define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
         DEFINE_VIRTIO_COMMON_FEATURES(_state, _field)
 
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 8c9d871..4bb49eb 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -26,56 +26,6 @@
 #define MAC_TABLE_ENTRIES    64
 #define MAX_VLAN    (1 << 12)   /* Per 802.1Q definition */
 
-typedef struct VirtIONetQueue {
-    VirtQueue *rx_vq;
-    VirtQueue *tx_vq;
-    QEMUTimer *tx_timer;
-    QEMUBH *tx_bh;
-    int tx_waiting;
-    struct {
-        VirtQueueElement elem;
-        ssize_t len;
-    } async_tx;
-    struct VirtIONet *n;
-} VirtIONetQueue;
-
-typedef struct VirtIONet
-{
-    VirtIODevice vdev;
-    uint8_t mac[ETH_ALEN];
-    uint16_t status;
-    VirtIONetQueue *vqs;
-    VirtQueue *ctrl_vq;
-    NICState *nic;
-    uint32_t tx_timeout;
-    int32_t tx_burst;
-    uint32_t has_vnet_hdr;
-    size_t host_hdr_len;
-    size_t guest_hdr_len;
-    uint8_t has_ufo;
-    int mergeable_rx_bufs;
-    uint8_t promisc;
-    uint8_t allmulti;
-    uint8_t alluni;
-    uint8_t nomulti;
-    uint8_t nouni;
-    uint8_t nobcast;
-    uint8_t vhost_started;
-    struct {
-        int in_use;
-        int first_multi;
-        uint8_t multi_overflow;
-        uint8_t uni_overflow;
-        uint8_t *macs;
-    } mac_table;
-    uint32_t *vlans;
-    DeviceState *qdev;
-    int multiqueue;
-    uint16_t max_queues;
-    uint16_t curr_queues;
-    size_t config_size;
-} VirtIONet;
-
 /*
  * Calculate the number of bytes up to and including the given 'field' of
  * 'container'.
diff --git a/hw/virtio-net.h b/hw/virtio-net.h
index 0c83ca5..4d1a8cd 100644
--- a/hw/virtio-net.h
+++ b/hw/virtio-net.h
@@ -134,6 +134,56 @@ struct virtio_net_ctrl_mac {
     uint32_t entries;
     uint8_t macs[][ETH_ALEN];
 };
+
+typedef struct VirtIONetQueue {
+    VirtQueue *rx_vq;
+    VirtQueue *tx_vq;
+    QEMUTimer *tx_timer;
+    QEMUBH *tx_bh;
+    int tx_waiting;
+    struct {
+        VirtQueueElement elem;
+        ssize_t len;
+    } async_tx;
+    struct VirtIONet *n;
+} VirtIONetQueue;
+
+typedef struct VirtIONet {
+    VirtIODevice vdev;
+    uint8_t mac[ETH_ALEN];
+    uint16_t status;
+    VirtIONetQueue *vqs;
+    VirtQueue *ctrl_vq;
+    NICState *nic;
+    uint32_t tx_timeout;
+    int32_t tx_burst;
+    uint32_t has_vnet_hdr;
+    size_t host_hdr_len;
+    size_t guest_hdr_len;
+    uint8_t has_ufo;
+    int mergeable_rx_bufs;
+    uint8_t promisc;
+    uint8_t allmulti;
+    uint8_t alluni;
+    uint8_t nomulti;
+    uint8_t nouni;
+    uint8_t nobcast;
+    uint8_t vhost_started;
+    struct {
+        int in_use;
+        int first_multi;
+        uint8_t multi_overflow;
+        uint8_t uni_overflow;
+        uint8_t *macs;
+    } mac_table;
+    uint32_t *vlans;
+    DeviceState *qdev;
+    int multiqueue;
+    uint16_t max_queues;
+    uint16_t curr_queues;
+    size_t config_size;
+} VirtIONet;
+
 #define VIRTIO_NET_CTRL_MAC    1
  #define VIRTIO_NET_CTRL_MAC_TABLE_SET        0
  #define VIRTIO_NET_CTRL_MAC_ADDR_SET         1
diff --git a/hw/virtio-rng.c b/hw/virtio-rng.c
index 54c1421..fa8e8f3 100644
--- a/hw/virtio-rng.c
+++ b/hw/virtio-rng.c
@@ -16,25 +16,6 @@
 #include "hw/virtio-rng.h"
 #include "qemu/rng.h"
 
-typedef struct VirtIORNG {
-    VirtIODevice vdev;
-
-    DeviceState *qdev;
-
-    /* Only one vq - guest puts buffer(s) on it when it needs entropy */
-    VirtQueue *vq;
-
-    VirtIORNGConf *conf;
-
-    RngBackend *rng;
-
-    /* We purposefully don't migrate this state.  The quota will reset on the
-     * destination as a result.  Rate limiting is host state, not guest state.
-     */
-    QEMUTimer *rate_limit_timer;
-    int64_t quota_remaining;
-} VirtIORNG;
-
 static bool is_guest_ready(VirtIORNG *vrng)
 {
     if (virtio_queue_ready(vrng->vq)
diff --git a/hw/virtio-rng.h b/hw/virtio-rng.h
index f42d748..3711c97 100644
--- a/hw/virtio-rng.h
+++ b/hw/virtio-rng.h
@@ -25,4 +25,23 @@ struct VirtIORNGConf {
     RndRandom *default_backend;
 };
 
+typedef struct VirtIORNG {
+    VirtIODevice vdev;
+
+    DeviceState *qdev;
+
+    /* Only one vq - guest puts buffer(s) on it when it needs entropy */
+    VirtQueue *vq;
+
+    VirtIORNGConf *conf;
+
+    RngBackend *rng;
+
+    /* We purposefully don't migrate this state.  The quota will reset on the
+     * destination as a result.  Rate limiting is host state, not guest state.
+     */
+    QEMUTimer *rate_limit_timer;
+    int64_t quota_remaining;
+} VirtIORNG;
+
 #endif
diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 72cc519..8620712 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -130,21 +130,6 @@ typedef struct {
     uint32_t max_lun;
 } QEMU_PACKED VirtIOSCSIConfig;
 
-typedef struct {
-    VirtIODevice vdev;
-    DeviceState *qdev;
-    VirtIOSCSIConf *conf;
-
-    SCSIBus bus;
-    uint32_t sense_size;
-    uint32_t cdb_size;
-    int resetting;
-    bool events_dropped;
-    VirtQueue *ctrl_vq;
-    VirtQueue *event_vq;
-    VirtQueue *cmd_vqs[0];
-} VirtIOSCSI;
-
 typedef struct VirtIOSCSIReq {
     VirtIOSCSI *dev;
     VirtQueue *vq;
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
index 81b3279..ccf1e42 100644
--- a/hw/virtio-scsi.h
+++ b/hw/virtio-scsi.h
@@ -16,6 +16,7 @@
 
 #include "hw/virtio.h"
 #include "hw/pci/pci.h"
+#include "hw/scsi.h"
 
 /* The ID for virtio_scsi */
 #define VIRTIO_ID_SCSI  8
@@ -31,6 +32,21 @@ struct VirtIOSCSIConf {
     uint32_t cmd_per_lun;
 };
 
+typedef struct VirtIOSCSI {
+    VirtIODevice vdev;
+    DeviceState *qdev;
+    VirtIOSCSIConf *conf;
+
+    SCSIBus bus;
+    uint32_t sense_size;
+    uint32_t cdb_size;
+    int resetting;
+    bool events_dropped;
+    VirtQueue *ctrl_vq;
+    VirtQueue *event_vq;
+    VirtQueue *cmd_vqs[0];
+} VirtIOSCSI;
+
 #define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _features_field, _conf_field) \
     DEFINE_VIRTIO_COMMON_FEATURES(_state, _features_field), \
     DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 7d0515f..ab7168e 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -25,47 +25,6 @@
 #include "trace.h"
 #include "hw/virtio-serial.h"
 
-/* The virtio-serial bus on top of which the ports will ride as devices */
-struct VirtIOSerialBus {
-    BusState qbus;
-
-    /* This is the parent device that provides the bus for ports. */
-    VirtIOSerial *vser;
-
-    /* The maximum number of ports that can ride on top of this bus */
-    uint32_t max_nr_ports;
-};
-
-typedef struct VirtIOSerialPostLoad {
-    QEMUTimer *timer;
-    uint32_t nr_active_ports;
-    struct {
-        VirtIOSerialPort *port;
-        uint8_t host_connected;
-    } *connected;
-} VirtIOSerialPostLoad;
-
-struct VirtIOSerial {
-    VirtIODevice vdev;
-
-    VirtQueue *c_ivq, *c_ovq;
-    /* Arrays of ivqs and ovqs: one per port */
-    VirtQueue **ivqs, **ovqs;
-
-    VirtIOSerialBus bus;
-
-    DeviceState *qdev;
-
-    QTAILQ_HEAD(, VirtIOSerialPort) ports;
-
-    /* bitmap for identifying active ports */
-    uint32_t *ports_map;
-
-    struct virtio_console_config config;
-
-    struct VirtIOSerialPostLoad *post_load;
-};
-
 static VirtIOSerialPort *find_port_by_id(VirtIOSerial *vser, uint32_t id)
 {
     VirtIOSerialPort *port;
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
index d2d9fb7..484dcfe 100644
--- a/hw/virtio-serial.h
+++ b/hw/virtio-serial.h
@@ -173,6 +173,47 @@ struct VirtIOSerialPort {
     bool throttled;
 };
 
+/* The virtio-serial bus on top of which the ports will ride as devices */
+struct VirtIOSerialBus {
+    BusState qbus;
+
+    /* This is the parent device that provides the bus for ports. */
+    VirtIOSerial *vser;
+
+    /* The maximum number of ports that can ride on top of this bus */
+    uint32_t max_nr_ports;
+};
+
+typedef struct VirtIOSerialPostLoad {
+    QEMUTimer *timer;
+    uint32_t nr_active_ports;
+    struct {
+        VirtIOSerialPort *port;
+        uint8_t host_connected;
+    } *connected;
+} VirtIOSerialPostLoad;
+
+struct VirtIOSerial {
+    VirtIODevice vdev;
+
+    VirtQueue *c_ivq, *c_ovq;
+    /* Arrays of ivqs and ovqs: one per port */
+    VirtQueue **ivqs, **ovqs;
+
+    VirtIOSerialBus bus;
+
+    DeviceState *qdev;
+
+    QTAILQ_HEAD(, VirtIOSerialPort) ports;
+
+    /* bitmap for identifying active ports */
+    uint32_t *ports_map;
+
+    struct virtio_console_config config;
+
+    struct VirtIOSerialPostLoad *post_load;
+};
+
 /* Interface to the virtio-serial bus */
 
 /*
commit e531761d63b7f8fe6b6423fafb3616ebbff768aa
Merge: b1999e8 1562e53
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 18 07:34:24 2013 -0500

    Merge remote-tracking branch 'kraxel/pixman.v8' into staging
    
    # By Gerd Hoffmann (18) and others
    # Via Blue Swirl (1) and Gerd Hoffmann (1)
    * kraxel/pixman.v8: (37 commits)
      console: remove ds_get_* helper functions
      console: zap color_table
      console: stop using DisplayState in gfx hardware emulation
      console: zap displaystate from dcl callbacks
      cocoa: stop using DisplayState
      spice: stop using DisplayState
      sdl: stop using DisplayState
      vnc: stop using DisplayState
      gtk: stop using DisplayState
      console: add surface_*() getters
      console: rework DisplaySurface handling [dcl/ui side]
      console: rework DisplaySurface handling [vga emu side]
      sdl: drop dead code
      qxl: better vga init in enter_vga_mode
      qxl: zap qxl0 global
      spice: zap sdpy global
      console: kill DisplayState->opaque
      console: fix displaychangelisteners interface
      s390: Fix cpu refactoring fallout.
      target-mips: fix rndrashift_short_acc and code for EXTR_ instructions
      ...

commit 1562e53112fd1082c656a06d953a7447ab17e6e1
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Mar 6 13:40:47 2013 +0100

    console: remove ds_get_* helper functions
    
    Switch the few remaining ds_get_* uses in console.c over to the new
    surface_* accessors.
    
    While doing so tripped over a few leftovers from commit
    a93a4a226a2afba147ba5df688b85d844f537c68 (code using depth == 0
    as indicator for textmode rendering).  Fixed them up.
    
    Finally dropped ds_get_* helper helpers.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/include/ui/console.h b/include/ui/console.h
index 92c31a9..a234c72 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -268,66 +268,6 @@ static inline int surface_bytes_per_pixel(DisplaySurface *s)
     return (bits + 7) / 8;
 }
 
-static inline int ds_get_linesize(DisplayState *ds)
-{
-    return surface_stride(ds->surface);
-}
-
-static inline uint8_t* ds_get_data(DisplayState *ds)
-{
-    return surface_data(ds->surface);
-}
-
-static inline int ds_get_width(DisplayState *ds)
-{
-    return surface_width(ds->surface);
-}
-
-static inline int ds_get_height(DisplayState *ds)
-{
-    return surface_height(ds->surface);
-}
-
-static inline int ds_get_bits_per_pixel(DisplayState *ds)
-{
-    return surface_bits_per_pixel(ds->surface);
-}
-
-static inline int ds_get_bytes_per_pixel(DisplayState *ds)
-{
-    return surface_bytes_per_pixel(ds->surface);
-}
-
-static inline pixman_format_code_t ds_get_format(DisplayState *ds)
-{
-    return ds->surface->format;
-}
-
-static inline pixman_image_t *ds_get_image(DisplayState *ds)
-{
-    return ds->surface->image;
-}
-
-static inline int ds_get_depth(DisplayState *ds)
-{
-    return ds->surface->pf.depth;
-}
-
-static inline int ds_get_rmask(DisplayState *ds)
-{
-    return ds->surface->pf.rmask;
-}
-
-static inline int ds_get_gmask(DisplayState *ds)
-{
-    return ds->surface->pf.gmask;
-}
-
-static inline int ds_get_bmask(DisplayState *ds)
-{
-    return ds->surface->pf.bmask;
-}
-
 #ifdef CONFIG_CURSES
 #include <curses.h>
 typedef chtype console_ch_t;
diff --git a/ui/console.c b/ui/console.c
index 27b1659..eb7a2bc 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -208,15 +208,17 @@ void vga_hw_text_update(console_ch_t *chardata)
         active_console->hw_text_update(active_console->hw, chardata);
 }
 
-static void vga_fill_rect (DisplayState *ds,
-                           int posx, int posy, int width, int height, uint32_t color)
+static void vga_fill_rect(QemuConsole *con,
+                          int posx, int posy, int width, int height,
+                          uint32_t color)
 {
+    DisplaySurface *surface = qemu_console_surface(con);
     uint8_t *d, *d1;
     int x, y, bpp;
 
-    bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
-    d1 = ds_get_data(ds) +
-        ds_get_linesize(ds) * posy + bpp * posx;
+    bpp = surface_bytes_per_pixel(surface);
+    d1 = surface_data(surface) +
+        surface_stride(surface) * posy + bpp * posx;
     for (y = 0; y < height; y++) {
         d = d1;
         switch(bpp) {
@@ -239,38 +241,40 @@ static void vga_fill_rect (DisplayState *ds,
             }
             break;
         }
-        d1 += ds_get_linesize(ds);
+        d1 += surface_stride(surface);
     }
 }
 
 /* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */
-static void vga_bitblt(DisplayState *ds, int xs, int ys, int xd, int yd, int w, int h)
+static void vga_bitblt(QemuConsole *con,
+                       int xs, int ys, int xd, int yd, int w, int h)
 {
+    DisplaySurface *surface = qemu_console_surface(con);
     const uint8_t *s;
     uint8_t *d;
     int wb, y, bpp;
 
-    bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
+    bpp = surface_bytes_per_pixel(surface);
     wb = w * bpp;
     if (yd <= ys) {
-        s = ds_get_data(ds) +
-            ds_get_linesize(ds) * ys + bpp * xs;
-        d = ds_get_data(ds) +
-            ds_get_linesize(ds) * yd + bpp * xd;
+        s = surface_data(surface) +
+            surface_stride(surface) * ys + bpp * xs;
+        d = surface_data(surface) +
+            surface_stride(surface) * yd + bpp * xd;
         for (y = 0; y < h; y++) {
             memmove(d, s, wb);
-            d += ds_get_linesize(ds);
-            s += ds_get_linesize(ds);
+            d += surface_stride(surface);
+            s += surface_stride(surface);
         }
     } else {
-        s = ds_get_data(ds) +
-            ds_get_linesize(ds) * (ys + h - 1) + bpp * xs;
-        d = ds_get_data(ds) +
-            ds_get_linesize(ds) * (yd + h - 1) + bpp * xd;
+        s = surface_data(surface) +
+            surface_stride(surface) * (ys + h - 1) + bpp * xs;
+        d = surface_data(surface) +
+            surface_stride(surface) * (yd + h - 1) + bpp * xd;
        for (y = 0; y < h; y++) {
             memmove(d, s, wb);
-            d -= ds_get_linesize(ds);
-            s -= ds_get_linesize(ds);
+            d -= surface_stride(surface);
+            s -= surface_stride(surface);
         }
     }
 }
@@ -391,9 +395,10 @@ static void console_print_text_attributes(TextAttributes *t_attrib, char ch)
 }
 #endif
 
-static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
+static void vga_putcharxy(QemuConsole *s, int x, int y, int ch,
                           TextAttributes *t_attrib)
 {
+    DisplaySurface *surface = qemu_console_surface(s);
     uint8_t *d;
     const uint8_t *font_ptr;
     unsigned int font_data, linesize, xorcol, bpp;
@@ -413,13 +418,13 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
         bgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol];
     }
 
-    bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
-    d = ds_get_data(ds) +
-        ds_get_linesize(ds) * y * FONT_HEIGHT + bpp * x * FONT_WIDTH;
-    linesize = ds_get_linesize(ds);
+    bpp = surface_bytes_per_pixel(surface);
+    d = surface_data(surface) +
+        surface_stride(surface) * y * FONT_HEIGHT + bpp * x * FONT_WIDTH;
+    linesize = surface_stride(surface);
     font_ptr = vgafont16 + FONT_HEIGHT * ch;
     xorcol = bgcol ^ fgcol;
-    switch(ds_get_bits_per_pixel(ds)) {
+    switch (surface_bits_per_pixel(surface)) {
     case 8:
         for(i = 0; i < FONT_HEIGHT; i++) {
             font_data = *font_ptr++;
@@ -524,19 +529,22 @@ static void update_xy(QemuConsole *s, int x, int y)
     TextCell *c;
     int y1, y2;
 
-    if (s == active_console) {
-        if (!ds_get_bits_per_pixel(s->ds)) {
-            text_update_xy(s, x, y);
-            return;
-        }
+    if (s != active_console) {
+        return;
+    }
+
+    if (s->ds->have_text) {
+        text_update_xy(s, x, y);
+    }
 
+    if (s->ds->have_gfx) {
         y1 = (s->y_base + y) % s->total_height;
         y2 = y1 - s->y_displayed;
         if (y2 < 0)
             y2 += s->total_height;
         if (y2 < s->height) {
             c = &s->cells[y1 * s->width + x];
-            vga_putcharxy(s->ds, x, y2, c->ch,
+            vga_putcharxy(s, x, y2, c->ch,
                           &(c->t_attrib));
             invalidate_xy(s, x, y2);
         }
@@ -547,15 +555,17 @@ static void console_show_cursor(QemuConsole *s, int show)
 {
     TextCell *c;
     int y, y1;
+    int x = s->x;
 
-    if (s == active_console) {
-        int x = s->x;
+    if (s != active_console) {
+        return;
+    }
 
-        if (!ds_get_bits_per_pixel(s->ds)) {
-            s->cursor_invalidate = 1;
-            return;
-        }
+    if (s->ds->have_text) {
+        s->cursor_invalidate = 1;
+    }
 
+    if (s->ds->have_gfx) {
         if (x >= s->width) {
             x = s->width - 1;
         }
@@ -568,9 +578,9 @@ static void console_show_cursor(QemuConsole *s, int show)
             if (show && s->cursor_visible_phase) {
                 TextAttributes t_attrib = s->t_attrib_default;
                 t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */
-                vga_putcharxy(s->ds, x, y, c->ch, &t_attrib);
+                vga_putcharxy(s, x, y, c->ch, &t_attrib);
             } else {
-                vga_putcharxy(s->ds, x, y, c->ch, &(c->t_attrib));
+                vga_putcharxy(s, x, y, c->ch, &(c->t_attrib));
             }
             invalidate_xy(s, x, y);
         }
@@ -579,6 +589,7 @@ static void console_show_cursor(QemuConsole *s, int show)
 
 static void console_refresh(QemuConsole *s)
 {
+    DisplaySurface *surface = qemu_console_surface(s);
     TextCell *c;
     int x, y, y1;
 
@@ -594,13 +605,13 @@ static void console_refresh(QemuConsole *s)
     }
 
     if (s->ds->have_gfx) {
-        vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
+        vga_fill_rect(s, 0, 0, surface_width(surface), surface_height(surface),
                       color_table_rgb[0][COLOR_BLACK]);
         y1 = s->y_displayed;
         for (y = 0; y < s->height; y++) {
             c = s->cells + y1 * s->width;
             for (x = 0; x < s->width; x++) {
-                vga_putcharxy(s->ds, x, y, c->ch,
+                vga_putcharxy(s, x, y, c->ch,
                               &(c->t_attrib));
                 c++;
             }
@@ -609,7 +620,8 @@ static void console_refresh(QemuConsole *s)
             }
         }
         console_show_cursor(s, 1);
-        dpy_gfx_update(s, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
+        dpy_gfx_update(s, 0, 0,
+                       surface_width(surface), surface_height(surface));
     }
 }
 
@@ -672,24 +684,25 @@ static void console_put_lf(QemuConsole *s)
             c++;
         }
         if (s == active_console && s->y_displayed == s->y_base) {
-            if (!ds_get_bits_per_pixel(s->ds)) {
+            if (s->ds->have_text) {
                 s->text_x[0] = 0;
                 s->text_y[0] = 0;
                 s->text_x[1] = s->width - 1;
                 s->text_y[1] = s->height - 1;
-                return;
             }
 
-            vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0,
-                       s->width * FONT_WIDTH,
-                       (s->height - 1) * FONT_HEIGHT);
-            vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT,
-                          s->width * FONT_WIDTH, FONT_HEIGHT,
-                          color_table_rgb[0][s->t_attrib_default.bgcol]);
-            s->update_x0 = 0;
-            s->update_y0 = 0;
-            s->update_x1 = s->width * FONT_WIDTH;
-            s->update_y1 = s->height * FONT_HEIGHT;
+            if (s->ds->have_gfx) {
+                vga_bitblt(s, 0, FONT_HEIGHT, 0, 0,
+                           s->width * FONT_WIDTH,
+                           (s->height - 1) * FONT_HEIGHT);
+                vga_fill_rect(s, 0, (s->height - 1) * FONT_HEIGHT,
+                              s->width * FONT_WIDTH, FONT_HEIGHT,
+                              color_table_rgb[0][s->t_attrib_default.bgcol]);
+                s->update_x0 = 0;
+                s->update_y0 = 0;
+                s->update_x1 = s->width * FONT_WIDTH;
+                s->update_y1 = s->height * FONT_HEIGHT;
+            }
         }
     }
 }
@@ -1027,13 +1040,15 @@ static void console_putchar(QemuConsole *s, int ch)
 
 void console_select(unsigned int index)
 {
+    DisplaySurface *surface;
     QemuConsole *s;
 
     if (index >= MAX_CONSOLES)
         return;
     if (active_console) {
-        active_console->g_width = ds_get_width(active_console->ds);
-        active_console->g_height = ds_get_height(active_console->ds);
+        surface = qemu_console_surface(active_console);
+        active_console->g_width = surface_width(surface);
+        active_console->g_height = surface_height(surface);
     }
     s = consoles[index];
     if (s) {
@@ -1044,7 +1059,6 @@ void console_select(unsigned int index)
         }
         active_console = s;
         if (ds->have_gfx) {
-            DisplaySurface *surface;
             surface = qemu_create_displaysurface(s->g_width, s->g_height);
             dpy_gfx_replace_surface(s, surface);
         }
@@ -1162,9 +1176,11 @@ void kbd_put_keysym(int keysym)
 static void text_console_invalidate(void *opaque)
 {
     QemuConsole *s = (QemuConsole *) opaque;
-    if (!ds_get_bits_per_pixel(s->ds) && s->console_type == TEXT_CONSOLE) {
-        s->g_width = ds_get_width(s->ds);
-        s->g_height = ds_get_height(s->ds);
+    DisplaySurface *surface = qemu_console_surface(s);
+
+    if (s->ds->have_text && s->console_type == TEXT_CONSOLE) {
+        s->g_width = surface_width(surface);
+        s->g_height = surface_height(surface);
         text_console_resize(s);
     }
     console_refresh(s);
@@ -1551,8 +1567,8 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
     s->x = 0;
     s->y = 0;
     if (s->console_type == TEXT_CONSOLE) {
-        s->g_width = ds_get_width(s->ds);
-        s->g_height = ds_get_height(s->ds);
+        s->g_width = surface_width(s->ds->surface);
+        s->g_height = surface_height(s->ds->surface);
     }
 
     s->cursor_timer =
commit cf6f05481affb600da22dba3c0bc2564e918e8f1
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Mar 6 09:50:51 2013 +0100

    console: zap color_table
    
    qemu_create_surface hands out 32bpp surfaces.
    So we can just use color_table_rgb directly.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/console.c b/ui/console.c
index d5ec271..27b1659 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -208,42 +208,6 @@ void vga_hw_text_update(console_ch_t *chardata)
         active_console->hw_text_update(active_console->hw, chardata);
 }
 
-/* convert a RGBA color to a color index usable in graphic primitives */
-static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba)
-{
-    unsigned int r, g, b, color;
-
-    switch(ds_get_bits_per_pixel(ds)) {
-#if 0
-    case 8:
-        r = (rgba >> 16) & 0xff;
-        g = (rgba >> 8) & 0xff;
-        b = (rgba) & 0xff;
-        color = (rgb_to_index[r] * 6 * 6) +
-            (rgb_to_index[g] * 6) +
-            (rgb_to_index[b]);
-        break;
-#endif
-    case 15:
-        r = (rgba >> 16) & 0xff;
-        g = (rgba >> 8) & 0xff;
-        b = (rgba) & 0xff;
-        color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
-        break;
-    case 16:
-        r = (rgba >> 16) & 0xff;
-        g = (rgba >> 8) & 0xff;
-        b = (rgba) & 0xff;
-        color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
-        break;
-    case 32:
-    default:
-        color = rgba;
-        break;
-    }
-    return color;
-}
-
 static void vga_fill_rect (DisplayState *ds,
                            int posx, int posy, int width, int height, uint32_t color)
 {
@@ -358,8 +322,6 @@ static const uint32_t dmask4[4] = {
     PAT(0xffffffff),
 };
 
-static uint32_t color_table[2][8];
-
 #ifndef CONFIG_CURSES
 enum color_names {
     COLOR_BLACK   = 0,
@@ -396,23 +358,6 @@ static const uint32_t color_table_rgb[2][8] = {
     }
 };
 
-static inline unsigned int col_expand(DisplayState *ds, unsigned int col)
-{
-    switch(ds_get_bits_per_pixel(ds)) {
-    case 8:
-        col |= col << 8;
-        col |= col << 16;
-        break;
-    case 15:
-    case 16:
-        col |= col << 16;
-        break;
-    default:
-        break;
-    }
-
-    return col;
-}
 #ifdef DEBUG_CONSOLE
 static void console_print_text_attributes(TextAttributes *t_attrib, char ch)
 {
@@ -461,11 +406,11 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
 #endif
 
     if (t_attrib->invers) {
-        bgcol = color_table[t_attrib->bold][t_attrib->fgcol];
-        fgcol = color_table[t_attrib->bold][t_attrib->bgcol];
+        bgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol];
+        fgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol];
     } else {
-        fgcol = color_table[t_attrib->bold][t_attrib->fgcol];
-        bgcol = color_table[t_attrib->bold][t_attrib->bgcol];
+        fgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol];
+        bgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol];
     }
 
     bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
@@ -650,7 +595,7 @@ static void console_refresh(QemuConsole *s)
 
     if (s->ds->have_gfx) {
         vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
-                      color_table[0][COLOR_BLACK]);
+                      color_table_rgb[0][COLOR_BLACK]);
         y1 = s->y_displayed;
         for (y = 0; y < s->height; y++) {
             c = s->cells + y1 * s->width;
@@ -740,7 +685,7 @@ static void console_put_lf(QemuConsole *s)
                        (s->height - 1) * FONT_HEIGHT);
             vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT,
                           s->width * FONT_WIDTH, FONT_HEIGHT,
-                          color_table[0][s->t_attrib_default.bgcol]);
+                          color_table_rgb[0][s->t_attrib_default.bgcol]);
             s->update_x0 = 0;
             s->update_y0 = 0;
             s->update_x1 = s->width * FONT_WIDTH;
@@ -1570,17 +1515,6 @@ int is_fixedsize_console(void)
     return active_console && active_console->console_type != TEXT_CONSOLE;
 }
 
-void console_color_init(DisplayState *ds)
-{
-    int i, j;
-    for (j = 0; j < 2; j++) {
-        for (i = 0; i < 8; i++) {
-            color_table[j][i] = col_expand(ds,
-                   vga_get_color(ds, color_table_rgb[j][i]));
-        }
-    }
-}
-
 static void text_console_set_echo(CharDriverState *chr, bool echo)
 {
     QemuConsole *s = chr->opaque;
@@ -1601,7 +1535,6 @@ static void text_console_update_cursor(void *opaque)
 static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
 {
     QemuConsole *s;
-    static int color_inited;
 
     s = chr->opaque;
 
@@ -1612,10 +1545,6 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
     s->kbd_timer = qemu_new_timer_ms(rt_clock, kbd_send_chars, s);
     s->ds = ds;
 
-    if (!color_inited) {
-        color_inited = 1;
-        console_color_init(s->ds);
-    }
     s->y_displayed = 0;
     s->y_base = 0;
     s->total_height = DEFAULT_BACKSCROLL;
commit c78f71378a345ea240c288993ca1378ded5504b9
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Mar 5 15:24:14 2013 +0100

    console: stop using DisplayState in gfx hardware emulation
    
    Use QemuConsole instead.  Updates interfaces in console.[ch] and adapts
    gfx hardware emulation code.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index a37dbd7..edd5282 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -462,7 +462,7 @@ typedef struct musicpal_lcd_state {
     uint32_t irqctrl;
     uint32_t page;
     uint32_t page_off;
-    DisplayState *ds;
+    QemuConsole *con;
     uint8_t video_ram[128*64/8];
 } musicpal_lcd_state;
 
@@ -483,7 +483,8 @@ static inline void glue(set_lcd_pixel, depth) \
         (musicpal_lcd_state *s, int x, int y, type col) \
 { \
     int dx, dy; \
-    type *pixel = &((type *) ds_get_data(s->ds))[(y * 128 * 3 + x) * 3]; \
+    DisplaySurface *surface = qemu_console_surface(s->con); \
+    type *pixel = &((type *) surface_data(surface))[(y * 128 * 3 + x) * 3]; \
 \
     for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
         for (dx = 0; dx < 3; dx++, pixel++) \
@@ -496,9 +497,10 @@ SET_LCD_PIXEL(32, uint32_t)
 static void lcd_refresh(void *opaque)
 {
     musicpal_lcd_state *s = opaque;
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int x, y, col;
 
-    switch (ds_get_bits_per_pixel(s->ds)) {
+    switch (surface_bits_per_pixel(surface)) {
     case 0:
         return;
 #define LCD_REFRESH(depth, func) \
@@ -518,14 +520,14 @@ static void lcd_refresh(void *opaque)
         break;
     LCD_REFRESH(8, rgb_to_pixel8)
     LCD_REFRESH(16, rgb_to_pixel16)
-    LCD_REFRESH(32, (is_surface_bgr(s->ds->surface) ?
+    LCD_REFRESH(32, (is_surface_bgr(surface) ?
                      rgb_to_pixel32bgr : rgb_to_pixel32))
     default:
         hw_error("unsupported colour depth %i\n",
-                  ds_get_bits_per_pixel(s->ds));
+                 surface_bits_per_pixel(surface));
     }
 
-    dpy_gfx_update(s->ds, 0, 0, 128*3, 64*3);
+    dpy_gfx_update(s->con, 0, 0, 128*3, 64*3);
 }
 
 static void lcd_invalidate(void *opaque)
@@ -609,9 +611,9 @@ static int musicpal_lcd_init(SysBusDevice *dev)
                           "musicpal-lcd", MP_LCD_SIZE);
     sysbus_init_mmio(dev, &s->iomem);
 
-    s->ds = graphic_console_init(lcd_refresh, lcd_invalidate,
-                                 NULL, NULL, s);
-    qemu_console_resize(s->ds, 128*3, 64*3);
+    s->con = graphic_console_init(lcd_refresh, lcd_invalidate,
+                                  NULL, NULL, s);
+    qemu_console_resize(s->con, 128*3, 64*3);
 
     qdev_init_gpio_in(&dev->qdev, musicpal_lcd_gpio_brigthness_in, 3);
 
diff --git a/hw/blizzard.c b/hw/blizzard.c
index 805f4d5..020d3de 100644
--- a/hw/blizzard.c
+++ b/hw/blizzard.c
@@ -69,7 +69,7 @@ typedef struct {
     uint8_t effect;
     uint8_t iformat;
     uint8_t source;
-    DisplayState *state;
+    QemuConsole *con;
     blizzard_fn_t *line_fn_tab[2];
     void *fb;
 
@@ -144,6 +144,7 @@ static inline void blizzard_rgb2yuv(int r, int g, int b,
 
 static void blizzard_window(BlizzardState *s)
 {
+    DisplaySurface *surface = qemu_console_surface(s->con);
     uint8_t *src, *dst;
     int bypp[2];
     int bypl[3];
@@ -162,7 +163,7 @@ static void blizzard_window(BlizzardState *s)
         s->my[1] = s->data.y + s->data.dy;
 
     bypp[0] = s->bpp;
-    bypp[1] = (ds_get_bits_per_pixel(s->state) + 7) >> 3;
+    bypp[1] = surface_bytes_per_pixel(surface);
     bypl[0] = bypp[0] * s->data.pitch;
     bypl[1] = bypp[1] * s->x;
     bypl[2] = bypp[0] * s->data.dx;
@@ -883,23 +884,25 @@ void s1d13745_write_block(void *opaque, int dc,
 static void blizzard_update_display(void *opaque)
 {
     BlizzardState *s = (BlizzardState *) opaque;
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int y, bypp, bypl, bwidth;
     uint8_t *src, *dst;
 
     if (!s->enable)
         return;
 
-    if (s->x != ds_get_width(s->state) || s->y != ds_get_height(s->state)) {
+    if (s->x != surface_width(surface) || s->y != surface_height(surface)) {
         s->invalidate = 1;
-        qemu_console_resize(s->state, s->x, s->y);
+        qemu_console_resize(s->con, s->x, s->y);
+        surface = qemu_console_surface(s->con);
     }
 
     if (s->invalidate) {
         s->invalidate = 0;
 
         if (s->blank) {
-            bypp = (ds_get_bits_per_pixel(s->state) + 7) >> 3;
-            memset(ds_get_data(s->state), 0, bypp * s->x * s->y);
+            bypp = surface_bytes_per_pixel(surface);
+            memset(surface_data(surface), 0, bypp * s->x * s->y);
             return;
         }
 
@@ -912,16 +915,16 @@ static void blizzard_update_display(void *opaque)
     if (s->mx[1] <= s->mx[0])
         return;
 
-    bypp = (ds_get_bits_per_pixel(s->state) + 7) >> 3;
+    bypp = surface_bytes_per_pixel(surface);
     bypl = bypp * s->x;
     bwidth = bypp * (s->mx[1] - s->mx[0]);
     y = s->my[0];
     src = s->fb + bypl * y + bypp * s->mx[0];
-    dst = ds_get_data(s->state) + bypl * y + bypp * s->mx[0];
+    dst = surface_data(surface) + bypl * y + bypp * s->mx[0];
     for (; y < s->my[1]; y ++, src += bypl, dst += bypl)
         memcpy(dst, src, bwidth);
 
-    dpy_gfx_update(s->state, s->mx[0], s->my[0],
+    dpy_gfx_update(s->con, s->mx[0], s->my[0],
                    s->mx[1] - s->mx[0], y - s->my[0]);
 
     s->mx[0] = s->x;
@@ -934,10 +937,12 @@ static void blizzard_screen_dump(void *opaque, const char *filename,
                                  bool cswitch, Error **errp)
 {
     BlizzardState *s = (BlizzardState *) opaque;
+    DisplaySurface *surface = qemu_console_surface(s->con);
 
     blizzard_update_display(opaque);
-    if (s && ds_get_data(s->state))
-        ppm_save(filename, s->state->surface, errp);
+    if (s && surface_data(surface)) {
+        ppm_save(filename, surface, errp);
+    }
 }
 
 #define DEPTH 8
@@ -954,14 +959,16 @@ static void blizzard_screen_dump(void *opaque, const char *filename,
 void *s1d13745_init(qemu_irq gpio_int)
 {
     BlizzardState *s = (BlizzardState *) g_malloc0(sizeof(*s));
+    DisplaySurface *surface;
 
     s->fb = g_malloc(0x180000);
 
-    s->state = graphic_console_init(blizzard_update_display,
-                                 blizzard_invalidate_display,
-                                 blizzard_screen_dump, NULL, s);
+    s->con = graphic_console_init(blizzard_update_display,
+                                  blizzard_invalidate_display,
+                                  blizzard_screen_dump, NULL, s);
+    surface = qemu_console_surface(s->con);
 
-    switch (ds_get_bits_per_pixel(s->state)) {
+    switch (surface_bits_per_pixel(surface)) {
     case 0:
         s->line_fn_tab[0] = s->line_fn_tab[1] =
                 g_malloc0(sizeof(blizzard_fn_t) * 0x10);
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 7babcb6..7a4d634 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -729,11 +729,12 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
 		      s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
 		      s->cirrus_blt_width, s->cirrus_blt_height);
 
-    if (notify)
-	qemu_console_copy(s->vga.ds,
+    if (notify) {
+        qemu_console_copy(s->vga.con,
 			  sx, sy, dx, dy,
 			  s->cirrus_blt_width / depth,
 			  s->cirrus_blt_height);
+    }
 
     /* we don't have to notify the display that this portion has
        changed since qemu_console_copy implies this */
@@ -2176,6 +2177,7 @@ static void cirrus_cursor_invalidate(VGACommonState *s1)
 static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y)
 {
     CirrusVGAState *s = container_of(s1, CirrusVGAState, vga);
+    DisplaySurface *surface = qemu_console_surface(s->vga.con);
     int w, h, bpp, x1, x2, poffset;
     unsigned int color0, color1;
     const uint8_t *palette, *src;
@@ -2228,9 +2230,9 @@ static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y)
     color1 = s->vga.rgb_to_pixel(c6_to_8(palette[0xf * 3]),
                                  c6_to_8(palette[0xf * 3 + 1]),
                                  c6_to_8(palette[0xf * 3 + 2]));
-    bpp = ((ds_get_bits_per_pixel(s->vga.ds) + 7) >> 3);
+    bpp = surface_bytes_per_pixel(surface);
     d1 += x1 * bpp;
-    switch(ds_get_bits_per_pixel(s->vga.ds)) {
+    switch (surface_bits_per_pixel(surface)) {
     default:
         break;
     case 8:
@@ -2908,9 +2910,9 @@ static int vga_initfn(ISADevice *dev)
     vga_common_init(s);
     cirrus_init_common(&d->cirrus_vga, CIRRUS_ID_CLGD5430, 0,
                        isa_address_space(dev), isa_address_space_io(dev));
-    s->ds = graphic_console_init(s->update, s->invalidate,
-                                 s->screen_dump, s->text_update,
-                                 s);
+    s->con = graphic_console_init(s->update, s->invalidate,
+                                  s->screen_dump, s->text_update,
+                                  s);
     rom_add_vga(VGABIOS_CIRRUS_FILENAME);
     /* XXX ISA-LFB support */
     /* FIXME not qdev yet */
@@ -2957,9 +2959,9 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
      vga_common_init(&s->vga);
      cirrus_init_common(s, device_id, 1, pci_address_space(dev),
                         pci_address_space_io(dev));
-     s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate,
-                                      s->vga.screen_dump, s->vga.text_update,
-                                      &s->vga);
+     s->vga.con = graphic_console_init(s->vga.update, s->vga.invalidate,
+                                       s->vga.screen_dump, s->vga.text_update,
+                                       &s->vga);
 
      /* setup PCI */
 
diff --git a/hw/exynos4210_fimd.c b/hw/exynos4210_fimd.c
index 6b31ae3..bf316c6 100644
--- a/hw/exynos4210_fimd.c
+++ b/hw/exynos4210_fimd.c
@@ -296,7 +296,7 @@ struct Exynos4210fimdWindow {
 typedef struct {
     SysBusDevice busdev;
     MemoryRegion iomem;
-    DisplayState *console;
+    QemuConsole *console;
     qemu_irq irq[3];
 
     uint32_t vidcon[4];     /* Video main control registers 0-3 */
@@ -1221,16 +1221,18 @@ static void exynos4210_fimd_invalidate(void *opaque)
 
 static void exynos4210_update_resolution(Exynos4210fimdState *s)
 {
+    DisplaySurface *surface = qemu_console_surface(s->console);
+
     /* LCD resolution is stored in VIDEO TIME CONTROL REGISTER 2 */
     uint32_t width = ((s->vidtcon[2] >> FIMD_VIDTCON2_HOR_SHIFT) &
             FIMD_VIDTCON2_SIZE_MASK) + 1;
     uint32_t height = ((s->vidtcon[2] >> FIMD_VIDTCON2_VER_SHIFT) &
             FIMD_VIDTCON2_SIZE_MASK) + 1;
 
-    if (s->ifb == NULL || ds_get_width(s->console) != width ||
-            ds_get_height(s->console) != height) {
+    if (s->ifb == NULL || surface_width(surface) != width ||
+            surface_height(surface) != height) {
         DPRINT_L1("Resolution changed from %ux%u to %ux%u\n",
-           ds_get_width(s->console), ds_get_height(s->console), width, height);
+           surface_width(surface), surface_height(surface), width, height);
         qemu_console_resize(s->console, width, height);
         s->ifb = g_realloc(s->ifb, width * height * RGBA_SIZE + 1);
         memset(s->ifb, 0, width * height * RGBA_SIZE + 1);
@@ -1241,6 +1243,7 @@ static void exynos4210_update_resolution(Exynos4210fimdState *s)
 static void exynos4210_fimd_update(void *opaque)
 {
     Exynos4210fimdState *s = (Exynos4210fimdState *)opaque;
+    DisplaySurface *surface = qemu_console_surface(s->console);
     Exynos4210fimdWindow *w;
     int i, line;
     hwaddr fb_line_addr, inc_size;
@@ -1253,7 +1256,7 @@ static void exynos4210_fimd_update(void *opaque)
     const int global_height = ((s->vidtcon[2] >> FIMD_VIDTCON2_VER_SHIFT) &
             FIMD_VIDTCON2_SIZE_MASK) + 1;
 
-    if (!s || !s->console || !ds_get_bits_per_pixel(s->console) ||
+    if (!s || !s->console || !surface_bits_per_pixel(surface) ||
             !s->enabled) {
         return;
     }
@@ -1299,10 +1302,10 @@ static void exynos4210_fimd_update(void *opaque)
         uint8_t *d;
         int bpp;
 
-        bpp = ds_get_bits_per_pixel(s->console);
+        bpp = surface_bits_per_pixel(surface);
         fimd_update_putpix_qemu(bpp);
         bpp = (bpp + 1) >> 3;
-        d = ds_get_data(s->console);
+        d = surface_data(surface);
         for (line = first_line; line <= last_line; line++) {
             fimd_copy_line_toqemu(global_width, s->ifb + global_width * line *
                     RGBA_SIZE, d + global_width * line * bpp);
diff --git a/hw/framebuffer.c b/hw/framebuffer.c
index d341aa0..7326a98 100644
--- a/hw/framebuffer.c
+++ b/hw/framebuffer.c
@@ -24,7 +24,7 @@
 /* Render an image from a shared memory framebuffer.  */
    
 void framebuffer_update_display(
-    DisplayState *ds,
+    DisplaySurface *ds,
     MemoryRegion *address_space,
     hwaddr base,
     int cols, /* Width in pixels.  */
@@ -73,7 +73,7 @@ void framebuffer_update_display(
         return;
     }
     src = src_base;
-    dest = ds_get_data(ds);
+    dest = surface_data(ds);
     if (dest_col_pitch < 0)
         dest -= dest_col_pitch * (cols - 1);
     if (dest_row_pitch < 0) {
diff --git a/hw/framebuffer.h b/hw/framebuffer.h
index 11f53ed..6eae035 100644
--- a/hw/framebuffer.h
+++ b/hw/framebuffer.h
@@ -8,7 +8,7 @@
 typedef void (*drawfn)(void *, uint8_t *, const uint8_t *, int, int);
 
 void framebuffer_update_display(
-    DisplayState *ds,
+    DisplaySurface *ds,
     MemoryRegion *address_space,
     hwaddr base,
     int cols,
diff --git a/hw/g364fb.c b/hw/g364fb.c
index 7b69815..f7014e9 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -39,7 +39,7 @@ typedef struct G364State {
     uint32_t top_of_screen;
     uint32_t width, height; /* in pixels */
     /* display refresh support */
-    DisplayState *ds;
+    QemuConsole *con;
     int depth;
     int blanked;
 } G364State;
@@ -77,6 +77,7 @@ static inline void reset_dirty(G364State *s,
 
 static void g364fb_draw_graphic8(G364State *s)
 {
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int i, w;
     uint8_t *vram;
     uint8_t *data_display, *dd;
@@ -87,7 +88,7 @@ static void g364fb_draw_graphic8(G364State *s)
     int xcursor, ycursor;
     unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned int b);
 
-    switch (ds_get_bits_per_pixel(s->ds)) {
+    switch (surface_bits_per_pixel(surface)) {
         case 8:
             rgb_to_pixel = rgb_to_pixel8;
             w = 1;
@@ -106,7 +107,7 @@ static void g364fb_draw_graphic8(G364State *s)
             break;
         default:
             hw_error("g364: unknown host depth %d",
-                     ds_get_bits_per_pixel(s->ds));
+                     surface_bits_per_pixel(surface));
             return;
     }
 
@@ -129,7 +130,7 @@ static void g364fb_draw_graphic8(G364State *s)
 
     vram = s->vram + s->top_of_screen;
     /* XXX: out of range in vram? */
-    data_display = dd = ds_get_data(s->ds);
+    data_display = dd = surface_data(surface);
     while (y < s->height) {
         if (check_dirty(s, page)) {
             if (y < ymin)
@@ -182,7 +183,7 @@ static void g364fb_draw_graphic8(G364State *s)
                         ymax = s->height - 1;
                         goto done;
                     }
-                    data_display = dd = data_display + ds_get_linesize(s->ds);
+                    data_display = dd = data_display + surface_stride(surface);
                     xmin = 0;
                     x = 0;
                 }
@@ -197,7 +198,7 @@ static void g364fb_draw_graphic8(G364State *s)
                 reset_dirty(s, page_min, page_max);
                 page_min = (ram_addr_t)-1;
                 page_max = 0;
-                dpy_gfx_update(s->ds, xmin, ymin,
+                dpy_gfx_update(s->con, xmin, ymin,
                                xmax - xmin + 1, ymax - ymin + 1);
                 xmin = s->width;
                 xmax = 0;
@@ -209,7 +210,7 @@ static void g364fb_draw_graphic8(G364State *s)
             x = x % s->width;
             y += dy;
             vram += G364_PAGE_SIZE;
-            data_display += dy * ds_get_linesize(s->ds);
+            data_display += dy * surface_stride(surface);
             dd = data_display + x * w;
         }
         page += G364_PAGE_SIZE;
@@ -217,13 +218,14 @@ static void g364fb_draw_graphic8(G364State *s)
 
 done:
     if (page_min != (ram_addr_t)-1) {
-        dpy_gfx_update(s->ds, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
+        dpy_gfx_update(s->con, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
         reset_dirty(s, page_min, page_max);
     }
 }
 
 static void g364fb_draw_blank(G364State *s)
 {
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int i, w;
     uint8_t *d;
 
@@ -232,28 +234,30 @@ static void g364fb_draw_blank(G364State *s)
         return;
     }
 
-    w = s->width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
-    d = ds_get_data(s->ds);
+    w = s->width * surface_bytes_per_pixel(surface);
+    d = surface_data(surface);
     for (i = 0; i < s->height; i++) {
         memset(d, 0, w);
-        d += ds_get_linesize(s->ds);
+        d += surface_stride(surface);
     }
 
-    dpy_gfx_update(s->ds, 0, 0, s->width, s->height);
+    dpy_gfx_update(s->con, 0, 0, s->width, s->height);
     s->blanked = 1;
 }
 
 static void g364fb_update_display(void *opaque)
 {
     G364State *s = opaque;
+    DisplaySurface *surface = qemu_console_surface(s->con);
 
     qemu_flush_coalesced_mmio_buffer();
 
     if (s->width == 0 || s->height == 0)
         return;
 
-    if (s->width != ds_get_width(s->ds) || s->height != ds_get_height(s->ds)) {
-        qemu_console_resize(s->ds, s->width, s->height);
+    if (s->width != surface_width(surface) ||
+        s->height != surface_height(surface)) {
+        qemu_console_resize(s->con, s->width, s->height);
     }
 
     if (s->ctla & CTLA_FORCE_BLANK) {
@@ -413,13 +417,14 @@ static void g364fb_update_depth(G364State *s)
 
 static void g364_invalidate_cursor_position(G364State *s)
 {
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int ymin, ymax, start, end;
 
     /* invalidate only near the cursor */
     ymin = s->cursor_position & 0xfff;
     ymax = MIN(s->height, ymin + 64);
-    start = ymin * ds_get_linesize(s->ds);
-    end = (ymax + 1) * ds_get_linesize(s->ds);
+    start = ymin * surface_stride(surface);
+    end = (ymax + 1) * surface_stride(surface);
 
     memory_region_set_dirty(&s->mem_vram, start, end - start);
 }
@@ -545,9 +550,9 @@ static void g364fb_init(DeviceState *dev, G364State *s)
 {
     s->vram = g_malloc0(s->vram_size);
 
-    s->ds = graphic_console_init(g364fb_update_display,
-                                 g364fb_invalidate_display,
-                                 g364fb_screen_dump, NULL, s);
+    s->con = graphic_console_init(g364fb_update_display,
+                                  g364fb_invalidate_display,
+                                  g364fb_screen_dump, NULL, s);
 
     memory_region_init_io(&s->mem_ctrl, &g364fb_ctrl_ops, s, "ctrl", 0x180000);
     memory_region_init_ram_ptr(&s->mem_vram, "vram",
diff --git a/hw/jazz_led.c b/hw/jazz_led.c
index a418a7d..05528c7 100644
--- a/hw/jazz_led.c
+++ b/hw/jazz_led.c
@@ -36,7 +36,7 @@ typedef struct LedState {
     SysBusDevice busdev;
     MemoryRegion iomem;
     uint8_t segments;
-    DisplayState *ds;
+    QemuConsole *con;
     screen_state_t state;
 } LedState;
 
@@ -75,13 +75,15 @@ static const MemoryRegionOps led_ops = {
 /***********************************************************/
 /* jazz_led display */
 
-static void draw_horizontal_line(DisplayState *ds, int posy, int posx1, int posx2, uint32_t color)
+static void draw_horizontal_line(DisplaySurface *ds,
+                                 int posy, int posx1, int posx2,
+                                 uint32_t color)
 {
     uint8_t *d;
     int x, bpp;
 
-    bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
-    d = ds_get_data(ds) + ds_get_linesize(ds) * posy + bpp * posx1;
+    bpp = (surface_bits_per_pixel(ds) + 7) >> 3;
+    d = surface_data(ds) + surface_stride(ds) * posy + bpp * posx1;
     switch(bpp) {
         case 1:
             for (x = posx1; x <= posx2; x++) {
@@ -104,30 +106,32 @@ static void draw_horizontal_line(DisplayState *ds, int posy, int posx1, int posx
     }
 }
 
-static void draw_vertical_line(DisplayState *ds, int posx, int posy1, int posy2, uint32_t color)
+static void draw_vertical_line(DisplaySurface *ds,
+                               int posx, int posy1, int posy2,
+                               uint32_t color)
 {
     uint8_t *d;
     int y, bpp;
 
-    bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
-    d = ds_get_data(ds) + ds_get_linesize(ds) * posy1 + bpp * posx;
+    bpp = (surface_bits_per_pixel(ds) + 7) >> 3;
+    d = surface_data(ds) + surface_stride(ds) * posy1 + bpp * posx;
     switch(bpp) {
         case 1:
             for (y = posy1; y <= posy2; y++) {
                 *((uint8_t *)d) = color;
-                d += ds_get_linesize(ds);
+                d += surface_stride(ds);
             }
             break;
         case 2:
             for (y = posy1; y <= posy2; y++) {
                 *((uint16_t *)d) = color;
-                d += ds_get_linesize(ds);
+                d += surface_stride(ds);
             }
             break;
         case 4:
             for (y = posy1; y <= posy2; y++) {
                 *((uint32_t *)d) = color;
-                d += ds_get_linesize(ds);
+                d += surface_stride(ds);
             }
             break;
     }
@@ -136,24 +140,24 @@ static void draw_vertical_line(DisplayState *ds, int posx, int posy1, int posy2,
 static void jazz_led_update_display(void *opaque)
 {
     LedState *s = opaque;
-    DisplayState *ds = s->ds;
+    DisplaySurface *surface = qemu_console_surface(s->con);
     uint8_t *d1;
     uint32_t color_segment, color_led;
     int y, bpp;
 
     if (s->state & REDRAW_BACKGROUND) {
         /* clear screen */
-        bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
-        d1 = ds_get_data(ds);
-        for (y = 0; y < ds_get_height(ds); y++) {
-            memset(d1, 0x00, ds_get_width(ds) * bpp);
-            d1 += ds_get_linesize(ds);
+        bpp = (surface_bits_per_pixel(surface) + 7) >> 3;
+        d1 = surface_data(surface);
+        for (y = 0; y < surface_height(surface); y++) {
+            memset(d1, 0x00, surface_width(surface) * bpp);
+            d1 += surface_stride(surface);
         }
     }
 
     if (s->state & REDRAW_SEGMENTS) {
         /* set colors according to bpp */
-        switch (ds_get_bits_per_pixel(ds)) {
+        switch (surface_bits_per_pixel(surface)) {
             case 8:
                 color_segment = rgb_to_pixel8(0xaa, 0xaa, 0xaa);
                 color_led = rgb_to_pixel8(0x00, 0xff, 0x00);
@@ -178,26 +182,34 @@ static void jazz_led_update_display(void *opaque)
         }
 
         /* display segments */
-        draw_horizontal_line(ds, 40, 10, 40, (s->segments & 0x02) ? color_segment : 0);
-        draw_vertical_line(ds, 10, 10, 40, (s->segments & 0x04) ? color_segment : 0);
-        draw_vertical_line(ds, 10, 40, 70, (s->segments & 0x08) ? color_segment : 0);
-        draw_horizontal_line(ds, 70, 10, 40, (s->segments & 0x10) ? color_segment : 0);
-        draw_vertical_line(ds, 40, 40, 70, (s->segments & 0x20) ? color_segment : 0);
-        draw_vertical_line(ds, 40, 10, 40, (s->segments & 0x40) ? color_segment : 0);
-        draw_horizontal_line(ds, 10, 10, 40, (s->segments & 0x80) ? color_segment : 0);
+        draw_horizontal_line(surface, 40, 10, 40,
+                             (s->segments & 0x02) ? color_segment : 0);
+        draw_vertical_line(surface, 10, 10, 40,
+                           (s->segments & 0x04) ? color_segment : 0);
+        draw_vertical_line(surface, 10, 40, 70,
+                           (s->segments & 0x08) ? color_segment : 0);
+        draw_horizontal_line(surface, 70, 10, 40,
+                             (s->segments & 0x10) ? color_segment : 0);
+        draw_vertical_line(surface, 40, 40, 70,
+                           (s->segments & 0x20) ? color_segment : 0);
+        draw_vertical_line(surface, 40, 10, 40,
+                           (s->segments & 0x40) ? color_segment : 0);
+        draw_horizontal_line(surface, 10, 10, 40,
+                             (s->segments & 0x80) ? color_segment : 0);
 
         /* display led */
         if (!(s->segments & 0x01))
             color_led = 0; /* black */
-        draw_horizontal_line(ds, 68, 50, 50, color_led);
-        draw_horizontal_line(ds, 69, 49, 51, color_led);
-        draw_horizontal_line(ds, 70, 48, 52, color_led);
-        draw_horizontal_line(ds, 71, 49, 51, color_led);
-        draw_horizontal_line(ds, 72, 50, 50, color_led);
+        draw_horizontal_line(surface, 68, 50, 50, color_led);
+        draw_horizontal_line(surface, 69, 49, 51, color_led);
+        draw_horizontal_line(surface, 70, 48, 52, color_led);
+        draw_horizontal_line(surface, 71, 49, 51, color_led);
+        draw_horizontal_line(surface, 72, 50, 50, color_led);
     }
 
     s->state = REDRAW_NONE;
-    dpy_gfx_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
+    dpy_gfx_update(s->con, 0, 0,
+                   surface_width(surface), surface_height(surface));
 }
 
 static void jazz_led_invalidate_display(void *opaque)
@@ -211,15 +223,15 @@ static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
     LedState *s = opaque;
     char buf[2];
 
-    dpy_text_cursor(s->ds, -1, -1);
-    qemu_console_resize(s->ds, 2, 1);
+    dpy_text_cursor(s->con, -1, -1);
+    qemu_console_resize(s->con, 2, 1);
 
     /* TODO: draw the segments */
     snprintf(buf, 2, "%02hhx\n", s->segments);
     console_write_ch(chardata++, 0x00200100 | buf[0]);
     console_write_ch(chardata++, 0x00200100 | buf[1]);
 
-    dpy_text_update(s->ds, 0, 0, 2, 1);
+    dpy_text_update(s->con, 0, 0, 2, 1);
 }
 
 static int jazz_led_post_load(void *opaque, int version_id)
@@ -249,10 +261,10 @@ static int jazz_led_init(SysBusDevice *dev)
     memory_region_init_io(&s->iomem, &led_ops, s, "led", 1);
     sysbus_init_mmio(dev, &s->iomem);
 
-    s->ds = graphic_console_init(jazz_led_update_display,
-                                 jazz_led_invalidate_display,
-                                 NULL,
-                                 jazz_led_text_update, s);
+    s->con = graphic_console_init(jazz_led_update_display,
+                                  jazz_led_invalidate_display,
+                                  NULL,
+                                  jazz_led_text_update, s);
 
     return 0;
 }
@@ -263,7 +275,7 @@ static void jazz_led_reset(DeviceState *d)
 
     s->segments = 0;
     s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND;
-    qemu_console_resize(s->ds, 60, 80);
+    qemu_console_resize(s->con, 60, 80);
 }
 
 static void jazz_led_class_init(ObjectClass *klass, void *data)
diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c
index 85ebb85..98762ec 100644
--- a/hw/milkymist-vgafb.c
+++ b/hw/milkymist-vgafb.c
@@ -66,7 +66,7 @@ enum {
 struct MilkymistVgafbState {
     SysBusDevice busdev;
     MemoryRegion regs_region;
-    DisplayState *ds;
+    QemuConsole *con;
 
     int invalidate;
     uint32_t fb_offset;
@@ -84,6 +84,7 @@ static int vgafb_enabled(MilkymistVgafbState *s)
 static void vgafb_update_display(void *opaque)
 {
     MilkymistVgafbState *s = opaque;
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int first = 0;
     int last = 0;
     drawfn fn;
@@ -94,7 +95,7 @@ static void vgafb_update_display(void *opaque)
 
     int dest_width = s->regs[R_HRES];
 
-    switch (ds_get_bits_per_pixel(s->ds)) {
+    switch (surface_bits_per_pixel(surface)) {
     case 0:
         return;
     case 8:
@@ -121,7 +122,7 @@ static void vgafb_update_display(void *opaque)
         break;
     }
 
-    framebuffer_update_display(s->ds, sysbus_address_space(&s->busdev),
+    framebuffer_update_display(surface, sysbus_address_space(&s->busdev),
                                s->regs[R_BASEADDRESS] + s->fb_offset,
                                s->regs[R_HRES],
                                s->regs[R_VRES],
@@ -134,7 +135,7 @@ static void vgafb_update_display(void *opaque)
                                &first, &last);
 
     if (first >= 0) {
-        dpy_gfx_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1);
+        dpy_gfx_update(s->con, 0, first, s->regs[R_HRES], last - first + 1);
     }
     s->invalidate = 0;
 }
@@ -151,7 +152,7 @@ static void vgafb_resize(MilkymistVgafbState *s)
         return;
     }
 
-    qemu_console_resize(s->ds, s->regs[R_HRES], s->regs[R_VRES]);
+    qemu_console_resize(s->con, s->regs[R_HRES], s->regs[R_VRES]);
     s->invalidate = 1;
 }
 
@@ -277,9 +278,9 @@ static int milkymist_vgafb_init(SysBusDevice *dev)
             "milkymist-vgafb", R_MAX * 4);
     sysbus_init_mmio(dev, &s->regs_region);
 
-    s->ds = graphic_console_init(vgafb_update_display,
-                                 vgafb_invalidate_display,
-                                 NULL, NULL, s);
+    s->con = graphic_console_init(vgafb_update_display,
+                                  vgafb_invalidate_display,
+                                  NULL, NULL, s);
 
     return 0;
 }
diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c
index c426f3a..4f5b094 100644
--- a/hw/omap_lcdc.c
+++ b/hw/omap_lcdc.c
@@ -26,7 +26,7 @@ struct omap_lcd_panel_s {
     MemoryRegion *sysmem;
     MemoryRegion iomem;
     qemu_irq irq;
-    DisplayState *state;
+    QemuConsole *con;
 
     int plm;
     int tft;
@@ -113,14 +113,16 @@ static draw_line_func draw_line_table2[33] = {
 static void omap_update_display(void *opaque)
 {
     struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque;
+    DisplaySurface *surface = qemu_console_surface(omap_lcd->con);
     draw_line_func draw_line;
     int size, height, first, last;
     int width, linesize, step, bpp, frame_offset;
     hwaddr frame_base;
 
-    if (!omap_lcd || omap_lcd->plm == 1 ||
-                    !omap_lcd->enable || !ds_get_bits_per_pixel(omap_lcd->state))
+    if (!omap_lcd || omap_lcd->plm == 1 || !omap_lcd->enable ||
+        !surface_bits_per_pixel(surface)) {
         return;
+    }
 
     frame_offset = 0;
     if (omap_lcd->plm != 2) {
@@ -139,25 +141,25 @@ static void omap_update_display(void *opaque)
     /* Colour depth */
     switch ((omap_lcd->palette[0] >> 12) & 7) {
     case 1:
-        draw_line = draw_line_table2[ds_get_bits_per_pixel(omap_lcd->state)];
+        draw_line = draw_line_table2[surface_bits_per_pixel(surface)];
         bpp = 2;
         break;
 
     case 2:
-        draw_line = draw_line_table4[ds_get_bits_per_pixel(omap_lcd->state)];
+        draw_line = draw_line_table4[surface_bits_per_pixel(surface)];
         bpp = 4;
         break;
 
     case 3:
-        draw_line = draw_line_table8[ds_get_bits_per_pixel(omap_lcd->state)];
+        draw_line = draw_line_table8[surface_bits_per_pixel(surface)];
         bpp = 8;
         break;
 
     case 4 ... 7:
         if (!omap_lcd->tft)
-            draw_line = draw_line_table12[ds_get_bits_per_pixel(omap_lcd->state)];
+            draw_line = draw_line_table12[surface_bits_per_pixel(surface)];
         else
-            draw_line = draw_line_table16[ds_get_bits_per_pixel(omap_lcd->state)];
+            draw_line = draw_line_table16[surface_bits_per_pixel(surface)];
         bpp = 16;
         break;
 
@@ -168,10 +170,11 @@ static void omap_update_display(void *opaque)
 
     /* Resolution */
     width = omap_lcd->width;
-    if (width != ds_get_width(omap_lcd->state) ||
-            omap_lcd->height != ds_get_height(omap_lcd->state)) {
-        qemu_console_resize(omap_lcd->state,
+    if (width != surface_width(surface) ||
+        omap_lcd->height != surface_height(surface)) {
+        qemu_console_resize(omap_lcd->con,
                             omap_lcd->width, omap_lcd->height);
+        surface = qemu_console_surface(omap_lcd->con);
         omap_lcd->invalidate = 1;
     }
 
@@ -196,8 +199,9 @@ static void omap_update_display(void *opaque)
     if (omap_lcd->dma->dual)
         omap_lcd->dma->current_frame ^= 1;
 
-    if (!ds_get_bits_per_pixel(omap_lcd->state))
+    if (!surface_bits_per_pixel(surface)) {
         return;
+    }
 
     first = 0;
     height = omap_lcd->height;
@@ -210,15 +214,15 @@ static void omap_update_display(void *opaque)
     }
 
     step = width * bpp >> 3;
-    linesize = ds_get_linesize(omap_lcd->state);
-    framebuffer_update_display(omap_lcd->state, omap_lcd->sysmem,
+    linesize = surface_stride(surface);
+    framebuffer_update_display(surface, omap_lcd->sysmem,
                                frame_base, width, height,
                                step, linesize, 0,
                                omap_lcd->invalidate,
                                draw_line, omap_lcd->palette,
                                &first, &last);
     if (first >= 0) {
-        dpy_gfx_update(omap_lcd->state, 0, first, width, last - first + 1);
+        dpy_gfx_update(omap_lcd->con, 0, first, width, last - first + 1);
     }
     omap_lcd->invalidate = 0;
 }
@@ -298,12 +302,13 @@ static void omap_screen_dump(void *opaque, const char *filename, bool cswitch,
                              Error **errp)
 {
     struct omap_lcd_panel_s *omap_lcd = opaque;
+    DisplaySurface *surface = qemu_console_surface(omap_lcd->con);
 
     omap_update_display(opaque);
-    if (omap_lcd && ds_get_data(omap_lcd->state))
-        omap_ppm_save(filename, ds_get_data(omap_lcd->state),
+    if (omap_lcd && surface_data(surface))
+        omap_ppm_save(filename, surface_data(surface),
                     omap_lcd->width, omap_lcd->height,
-                    ds_get_linesize(omap_lcd->state), errp);
+                    surface_stride(surface), errp);
 }
 
 static void omap_invalidate_display(void *opaque) {
@@ -480,9 +485,9 @@ struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem,
     memory_region_init_io(&s->iomem, &omap_lcdc_ops, s, "omap.lcdc", 0x100);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
-    s->state = graphic_console_init(omap_update_display,
-                                    omap_invalidate_display,
-                                    omap_screen_dump, NULL, s);
+    s->con = graphic_console_init(omap_update_display,
+                                  omap_invalidate_display,
+                                  omap_screen_dump, NULL, s);
 
     return s;
 }
diff --git a/hw/pl110.c b/hw/pl110.c
index 924642d..fbef675 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -42,7 +42,7 @@ enum pl110_version
 typedef struct {
     SysBusDevice busdev;
     MemoryRegion iomem;
-    DisplayState *ds;
+    QemuConsole *con;
 
     int version;
     uint32_t timing[4];
@@ -129,6 +129,7 @@ static int pl110_enabled(pl110_state *s)
 static void pl110_update_display(void *opaque)
 {
     pl110_state *s = (pl110_state *)opaque;
+    DisplaySurface *surface = qemu_console_surface(s->con);
     drawfn* fntable;
     drawfn fn;
     int dest_width;
@@ -140,7 +141,7 @@ static void pl110_update_display(void *opaque)
     if (!pl110_enabled(s))
         return;
 
-    switch (ds_get_bits_per_pixel(s->ds)) {
+    switch (surface_bits_per_pixel(surface)) {
     case 0:
         return;
     case 8:
@@ -231,14 +232,14 @@ static void pl110_update_display(void *opaque)
     }
     dest_width *= s->cols;
     first = 0;
-    framebuffer_update_display(s->ds, sysbus_address_space(&s->busdev),
+    framebuffer_update_display(surface, sysbus_address_space(&s->busdev),
                                s->upbase, s->cols, s->rows,
                                src_width, dest_width, 0,
                                s->invalidate,
                                fn, s->palette,
                                &first, &last);
     if (first >= 0) {
-        dpy_gfx_update(s->ds, 0, first, s->cols, last - first + 1);
+        dpy_gfx_update(s->con, 0, first, s->cols, last - first + 1);
     }
     s->invalidate = 0;
 }
@@ -248,12 +249,13 @@ static void pl110_invalidate_display(void * opaque)
     pl110_state *s = (pl110_state *)opaque;
     s->invalidate = 1;
     if (pl110_enabled(s)) {
-        qemu_console_resize(s->ds, s->cols, s->rows);
+        qemu_console_resize(s->con, s->cols, s->rows);
     }
 }
 
 static void pl110_update_palette(pl110_state *s, int n)
 {
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int i;
     uint32_t raw;
     unsigned int r, g, b;
@@ -268,7 +270,7 @@ static void pl110_update_palette(pl110_state *s, int n)
         b = (raw & 0x1f) << 3;
         /* The I bit is ignored.  */
         raw >>= 6;
-        switch (ds_get_bits_per_pixel(s->ds)) {
+        switch (surface_bits_per_pixel(surface)) {
         case 8:
             s->palette[n] = rgb_to_pixel8(r, g, b);
             break;
@@ -291,7 +293,7 @@ static void pl110_resize(pl110_state *s, int width, int height)
 {
     if (width != s->cols || height != s->rows) {
         if (pl110_enabled(s)) {
-            qemu_console_resize(s->ds, width, height);
+            qemu_console_resize(s->con, width, height);
         }
     }
     s->cols = width;
@@ -409,7 +411,7 @@ static void pl110_write(void *opaque, hwaddr offset,
         s->cr = val;
         s->bpp = (val >> 1) & 7;
         if (pl110_enabled(s)) {
-            qemu_console_resize(s->ds, s->cols, s->rows);
+            qemu_console_resize(s->con, s->cols, s->rows);
         }
         break;
     case 10: /* LCDICR */
@@ -450,9 +452,9 @@ static int pl110_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, &s->iomem);
     sysbus_init_irq(dev, &s->irq);
     qdev_init_gpio_in(&s->busdev.qdev, pl110_mux_ctrl_set, 1);
-    s->ds = graphic_console_init(pl110_update_display,
-                                 pl110_invalidate_display,
-                                 NULL, NULL, s);
+    s->con = graphic_console_init(pl110_update_display,
+                                  pl110_invalidate_display,
+                                  NULL, NULL, s);
     return 0;
 }
 
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 6484d27..f2b0c93 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -39,7 +39,7 @@ struct PXA2xxLCDState {
     int irqlevel;
 
     int invalidated;
-    DisplayState *ds;
+    QemuConsole *con;
     drawfn *line_fn[2];
     int dest_width;
     int xres, yres;
@@ -579,6 +579,7 @@ static const MemoryRegionOps pxa2xx_lcdc_ops = {
 /* Load new palette for a given DMA channel, convert to internal format */
 static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
 {
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int i, n, format, r, g, b, alpha;
     uint32_t *dest;
     uint8_t *src;
@@ -652,7 +653,7 @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
             src += 4;
             break;
         }
-        switch (ds_get_bits_per_pixel(s->ds)) {
+        switch (surface_bits_per_pixel(surface)) {
         case 8:
             *dest = rgb_to_pixel8(r, g, b) | alpha;
             break;
@@ -676,6 +677,7 @@ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp)
 static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
                 hwaddr addr, int *miny, int *maxy)
 {
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int src_width, dest_width;
     drawfn fn = NULL;
     if (s->dest_width)
@@ -693,7 +695,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
 
     dest_width = s->xres * s->dest_width;
     *miny = 0;
-    framebuffer_update_display(s->ds, s->sysmem,
+    framebuffer_update_display(surface, s->sysmem,
                                addr, s->xres, s->yres,
                                src_width, dest_width, s->dest_width,
                                s->invalidated,
@@ -703,6 +705,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot0(PXA2xxLCDState *s,
 static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
                hwaddr addr, int *miny, int *maxy)
 {
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int src_width, dest_width;
     drawfn fn = NULL;
     if (s->dest_width)
@@ -720,7 +723,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
 
     dest_width = s->yres * s->dest_width;
     *miny = 0;
-    framebuffer_update_display(s->ds, s->sysmem,
+    framebuffer_update_display(surface, s->sysmem,
                                addr, s->xres, s->yres,
                                src_width, s->dest_width, -dest_width,
                                s->invalidated,
@@ -731,6 +734,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot90(PXA2xxLCDState *s,
 static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
                 hwaddr addr, int *miny, int *maxy)
 {
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int src_width, dest_width;
     drawfn fn = NULL;
     if (s->dest_width) {
@@ -751,7 +755,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
 
     dest_width = s->xres * s->dest_width;
     *miny = 0;
-    framebuffer_update_display(s->ds, s->sysmem,
+    framebuffer_update_display(surface, s->sysmem,
                                addr, s->xres, s->yres,
                                src_width, -dest_width, -s->dest_width,
                                s->invalidated,
@@ -761,6 +765,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot180(PXA2xxLCDState *s,
 static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
                hwaddr addr, int *miny, int *maxy)
 {
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int src_width, dest_width;
     drawfn fn = NULL;
     if (s->dest_width) {
@@ -781,7 +786,7 @@ static void pxa2xx_lcdc_dma0_redraw_rot270(PXA2xxLCDState *s,
 
     dest_width = s->yres * s->dest_width;
     *miny = 0;
-    framebuffer_update_display(s->ds, s->sysmem,
+    framebuffer_update_display(surface, s->sysmem,
                                addr, s->xres, s->yres,
                                src_width, -s->dest_width, dest_width,
                                s->invalidated,
@@ -800,9 +805,9 @@ static void pxa2xx_lcdc_resize(PXA2xxLCDState *s)
 
     if (width != s->xres || height != s->yres) {
         if (s->orientation == 90 || s->orientation == 270) {
-            qemu_console_resize(s->ds, height, width);
+            qemu_console_resize(s->con, height, width);
         } else {
-            qemu_console_resize(s->ds, width, height);
+            qemu_console_resize(s->con, width, height);
         }
         s->invalidated = 1;
         s->xres = width;
@@ -871,20 +876,20 @@ static void pxa2xx_update_display(void *opaque)
     if (miny >= 0) {
         switch (s->orientation) {
         case 0:
-            dpy_gfx_update(s->ds, 0, miny, s->xres, maxy - miny + 1);
+            dpy_gfx_update(s->con, 0, miny, s->xres, maxy - miny + 1);
             break;
         case 90:
-            dpy_gfx_update(s->ds, miny, 0, maxy - miny + 1, s->xres);
+            dpy_gfx_update(s->con, miny, 0, maxy - miny + 1, s->xres);
             break;
         case 180:
             maxy = s->yres - maxy - 1;
             miny = s->yres - miny - 1;
-            dpy_gfx_update(s->ds, 0, maxy, s->xres, miny - maxy + 1);
+            dpy_gfx_update(s->con, 0, maxy, s->xres, miny - maxy + 1);
             break;
         case 270:
             maxy = s->yres - maxy - 1;
             miny = s->yres - miny - 1;
-            dpy_gfx_update(s->ds, maxy, 0, miny - maxy + 1, s->xres);
+            dpy_gfx_update(s->con, maxy, 0, miny - maxy + 1, s->xres);
             break;
         }
     }
@@ -990,6 +995,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
                                  hwaddr base, qemu_irq irq)
 {
     PXA2xxLCDState *s;
+    DisplaySurface *surface;
 
     s = (PXA2xxLCDState *) g_malloc0(sizeof(PXA2xxLCDState));
     s->invalidated = 1;
@@ -1002,11 +1008,12 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
                           "pxa2xx-lcd-controller", 0x00100000);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
-    s->ds = graphic_console_init(pxa2xx_update_display,
-                                 pxa2xx_invalidate_display,
-                                 NULL, NULL, s);
+    s->con = graphic_console_init(pxa2xx_update_display,
+                                  pxa2xx_invalidate_display,
+                                  NULL, NULL, s);
+    surface = qemu_console_surface(s->con);
 
-    switch (ds_get_bits_per_pixel(s->ds)) {
+    switch (surface_bits_per_pixel(surface)) {
     case 0:
         s->dest_width = 0;
         break;
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 087679e..8cd9be4 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -23,11 +23,12 @@
 
 static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
 {
+    DisplaySurface *surface = qemu_console_surface(qxl->vga.con);
+    uint8_t *dst = surface_data(surface);
     uint8_t *src;
-    uint8_t *dst = ds_get_data(qxl->vga.ds);
     int len, i;
 
-    if (is_buffer_shared(qxl->vga.ds->surface)) {
+    if (is_buffer_shared(surface)) {
         return;
     }
     if (!qxl->guest_primary.data) {
@@ -125,14 +126,14 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
                 (qxl->guest_primary.surface.width,
                  qxl->guest_primary.surface.height);
         }
-        dpy_gfx_replace_surface(vga->ds, surface);
+        dpy_gfx_replace_surface(vga->con, surface);
     }
     for (i = 0; i < qxl->num_dirty_rects; i++) {
         if (qemu_spice_rect_is_empty(qxl->dirty+i)) {
             break;
         }
         qxl_blit(qxl, qxl->dirty+i);
-        dpy_gfx_update(vga->ds,
+        dpy_gfx_update(vga->con,
                        qxl->dirty[i].left, qxl->dirty[i].top,
                        qxl->dirty[i].right - qxl->dirty[i].left,
                        qxl->dirty[i].bottom - qxl->dirty[i].top);
@@ -236,7 +237,7 @@ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
         return 1;
     }
 
-    if (!dpy_cursor_define_supported(qxl->ssd.dcl.ds)) {
+    if (!dpy_cursor_define_supported(qxl->vga.con)) {
         return 0;
     }
 
diff --git a/hw/qxl.c b/hw/qxl.c
index 0939ace..b66b414 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -2063,6 +2063,7 @@ static int qxl_init_primary(PCIDevice *dev)
     PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
     VGACommonState *vga = &qxl->vga;
     PortioList *qxl_vga_port_list = g_new(PortioList, 1);
+    DisplayState *ds;
     int rc;
 
     qxl->id = 0;
@@ -2073,9 +2074,11 @@ static int qxl_init_primary(PCIDevice *dev)
     portio_list_init(qxl_vga_port_list, qxl_vga_portio_list, vga, "vga");
     portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0);
 
-    vga->ds = graphic_console_init(qxl_hw_update, qxl_hw_invalidate,
-                                   qxl_hw_screen_dump, qxl_hw_text_update, qxl);
-    qemu_spice_display_init_common(&qxl->ssd, vga->ds);
+    vga->con = graphic_console_init(qxl_hw_update, qxl_hw_invalidate,
+                                    qxl_hw_screen_dump, qxl_hw_text_update,
+                                    qxl);
+    qxl->ssd.con = vga->con,
+    qemu_spice_display_init_common(&qxl->ssd);
 
     rc = qxl_init_common(qxl);
     if (rc != 0) {
@@ -2083,7 +2086,8 @@ static int qxl_init_primary(PCIDevice *dev)
     }
 
     qxl->ssd.dcl.ops = &display_listener_ops;
-    register_displaychangelistener(vga->ds, &qxl->ssd.dcl);
+    ds = qemu_console_displaystate(vga->con);
+    register_displaychangelistener(ds, &qxl->ssd.dcl);
     return rc;
 }
 
diff --git a/hw/sm501.c b/hw/sm501.c
index 0e01911..93a06c9 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -454,7 +454,7 @@ static const uint32_t sm501_mem_local_size[] = {
 
 typedef struct SM501State {
     /* graphic console status */
-    DisplayState *ds;
+    QemuConsole *con;
 
     /* status & internal resources */
     hwaddr base;
@@ -1234,9 +1234,9 @@ static draw_hwc_line_func * draw_hwc_line_funcs[] = {
     draw_hwc_line_16bgr,
 };
 
-static inline int get_depth_index(DisplayState *s)
+static inline int get_depth_index(DisplaySurface *surface)
 {
-    switch(ds_get_bits_per_pixel(s)) {
+    switch (surface_bits_per_pixel(surface)) {
     default:
     case 8:
 	return 0;
@@ -1245,26 +1245,28 @@ static inline int get_depth_index(DisplayState *s)
     case 16:
         return 2;
     case 32:
-	if (is_surface_bgr(s->surface))
-	    return 4;
-	else
-	    return 3;
+        if (is_surface_bgr(surface)) {
+            return 4;
+        } else {
+            return 3;
+        }
     }
 }
 
 static void sm501_draw_crt(SM501State * s)
 {
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int y;
     int width = (s->dc_crt_h_total & 0x00000FFF) + 1;
     int height = (s->dc_crt_v_total & 0x00000FFF) + 1;
 
     uint8_t  * src = s->local_mem;
     int src_bpp = 0;
-    int dst_bpp = ds_get_bytes_per_pixel(s->ds) + (ds_get_bits_per_pixel(s->ds) % 8 ? 1 : 0);
+    int dst_bpp = surface_bytes_per_pixel(surface);
     uint32_t * palette = (uint32_t *)&s->dc_palette[SM501_DC_CRT_PALETTE
 						    - SM501_DC_PANEL_PALETTE];
     uint8_t hwc_palette[3 * 3];
-    int ds_depth_index = get_depth_index(s->ds);
+    int ds_depth_index = get_depth_index(surface);
     draw_line_func * draw_line = NULL;
     draw_hwc_line_func * draw_hwc_line = NULL;
     int full_update = 0;
@@ -1312,7 +1314,8 @@ static void sm501_draw_crt(SM501State * s)
 
     /* adjust console size */
     if (s->last_width != width || s->last_height != height) {
-	qemu_console_resize(s->ds, width, height);
+        qemu_console_resize(s->con, width, height);
+        surface = qemu_console_surface(s->con);
 	s->last_width = width;
 	s->last_height = height;
 	full_update = 1;
@@ -1331,7 +1334,8 @@ static void sm501_draw_crt(SM501State * s)
 
 	/* draw line and change status */
 	if (update) {
-            uint8_t * d = &(ds_get_data(s->ds)[y * width * dst_bpp]);
+            uint8_t *d = surface_data(surface);
+            d +=  y * width * dst_bpp;
 
             /* draw graphics layer */
             draw_line(d, src, width, palette);
@@ -1350,7 +1354,7 @@ static void sm501_draw_crt(SM501State * s)
 	} else {
 	    if (y_start >= 0) {
 		/* flush to display */
-                dpy_gfx_update(s->ds, 0, y_start, width, y - y_start);
+                dpy_gfx_update(s->con, 0, y_start, width, y - y_start);
 		y_start = -1;
 	    }
 	}
@@ -1361,7 +1365,7 @@ static void sm501_draw_crt(SM501State * s)
 
     /* complete flush to display */
     if (y_start >= 0)
-        dpy_gfx_update(s->ds, 0, y_start, width, y - y_start);
+        dpy_gfx_update(s->con, 0, y_start, width, y - y_start);
 
     /* clear dirty flags */
     if (page_min != ~0l) {
@@ -1441,6 +1445,6 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
     }
 
     /* create qemu graphic console */
-    s->ds = graphic_console_init(sm501_update_display, NULL,
-				 NULL, NULL, s);
+    s->con = graphic_console_init(sm501_update_display, NULL,
+                                  NULL, NULL, s);
 }
diff --git a/hw/ssd0303.c b/hw/ssd0303.c
index db50909..68d1f24 100644
--- a/hw/ssd0303.c
+++ b/hw/ssd0303.c
@@ -43,7 +43,7 @@ enum ssd0303_cmd {
 
 typedef struct {
     I2CSlave i2c;
-    DisplayState *ds;
+    QemuConsole *con;
     int row;
     int col;
     int start_line;
@@ -191,6 +191,7 @@ static void ssd0303_event(I2CSlave *i2c, enum i2c_event event)
 static void ssd0303_update_display(void *opaque)
 {
     ssd0303_state *s = (ssd0303_state *)opaque;
+    DisplaySurface *surface = qemu_console_surface(s->con);
     uint8_t *dest;
     uint8_t *src;
     int x;
@@ -204,7 +205,7 @@ static void ssd0303_update_display(void *opaque)
     if (!s->redraw)
         return;
 
-    switch (ds_get_bits_per_pixel(s->ds)) {
+    switch (surface_bits_per_pixel(surface)) {
     case 0:
         return;
     case 15:
@@ -236,7 +237,7 @@ static void ssd0303_update_display(void *opaque)
         colors[0] = colortab + dest_width;
         colors[1] = colortab;
     }
-    dest = ds_get_data(s->ds);
+    dest = surface_data(surface);
     for (y = 0; y < 16; y++) {
         line = (y + s->start_line) & 63;
         src = s->framebuffer + 132 * (line >> 3) + 36;
@@ -252,7 +253,7 @@ static void ssd0303_update_display(void *opaque)
         }
     }
     s->redraw = 0;
-    dpy_gfx_update(s->ds, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY);
+    dpy_gfx_update(s->con, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY);
 }
 
 static void ssd0303_invalidate_display(void * opaque)
@@ -287,10 +288,10 @@ static int ssd0303_init(I2CSlave *i2c)
 {
     ssd0303_state *s = FROM_I2C_SLAVE(ssd0303_state, i2c);
 
-    s->ds = graphic_console_init(ssd0303_update_display,
-                                 ssd0303_invalidate_display,
-                                 NULL, NULL, s);
-    qemu_console_resize(s->ds, 96 * MAGNIFY, 16 * MAGNIFY);
+    s->con = graphic_console_init(ssd0303_update_display,
+                                  ssd0303_invalidate_display,
+                                  NULL, NULL, s);
+    qemu_console_resize(s->con, 96 * MAGNIFY, 16 * MAGNIFY);
     return 0;
 }
 
diff --git a/hw/ssd0323.c b/hw/ssd0323.c
index 27b4151..5cf2f70 100644
--- a/hw/ssd0323.c
+++ b/hw/ssd0323.c
@@ -45,7 +45,7 @@ enum ssd0323_mode
 
 typedef struct {
     SSISlave ssidev;
-    DisplayState *ds;
+    QemuConsole *con;
 
     int cmd_len;
     int cmd;
@@ -175,6 +175,7 @@ static uint32_t ssd0323_transfer(SSISlave *dev, uint32_t data)
 static void ssd0323_update_display(void *opaque)
 {
     ssd0323_state *s = (ssd0323_state *)opaque;
+    DisplaySurface *surface = qemu_console_surface(s->con);
     uint8_t *dest;
     uint8_t *src;
     int x;
@@ -189,7 +190,7 @@ static void ssd0323_update_display(void *opaque)
     if (!s->redraw)
         return;
 
-    switch (ds_get_bits_per_pixel(s->ds)) {
+    switch (surface_bits_per_pixel(surface)) {
     case 0:
         return;
     case 15:
@@ -212,7 +213,7 @@ static void ssd0323_update_display(void *opaque)
     for (i = 0; i < 16; i++) {
         int n;
         colors[i] = p;
-        switch (ds_get_bits_per_pixel(s->ds)) {
+        switch (surface_bits_per_pixel(surface)) {
         case 15:
             n = i * 2 + (i >> 3);
             p[0] = n | (n << 5);
@@ -235,7 +236,7 @@ static void ssd0323_update_display(void *opaque)
         p += dest_width;
     }
     /* TODO: Implement row/column remapping.  */
-    dest = ds_get_data(s->ds);
+    dest = surface_data(surface);
     for (y = 0; y < 64; y++) {
         line = y;
         src = s->framebuffer + 64 * line;
@@ -260,7 +261,7 @@ static void ssd0323_update_display(void *opaque)
         }
     }
     s->redraw = 0;
-    dpy_gfx_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY);
+    dpy_gfx_update(s->con, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY);
 }
 
 static void ssd0323_invalidate_display(void * opaque)
@@ -336,10 +337,10 @@ static int ssd0323_init(SSISlave *dev)
 
     s->col_end = 63;
     s->row_end = 79;
-    s->ds = graphic_console_init(ssd0323_update_display,
-                                 ssd0323_invalidate_display,
-                                 NULL, NULL, s);
-    qemu_console_resize(s->ds, 128 * MAGNIFY, 64 * MAGNIFY);
+    s->con = graphic_console_init(ssd0323_update_display,
+                                  ssd0323_invalidate_display,
+                                  NULL, NULL, s);
+    qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY);
 
     qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1);
 
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index 0755463..79c971b 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -125,7 +125,7 @@ struct TC6393xbState {
     DeviceState *flash;
     ECCState ecc;
 
-    DisplayState *ds;
+    QemuConsole *con;
     MemoryRegion vram;
     uint16_t *vram_ptr;
     uint32_t scr_width, scr_height; /* in pixels */
@@ -433,7 +433,9 @@ static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value)
 
 static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
 {
-    switch (ds_get_bits_per_pixel(s->ds)) {
+    DisplaySurface *surface = qemu_console_surface(s->con);
+
+    switch (surface_bits_per_pixel(surface)) {
         case 8:
             tc6393xb_draw_graphic8(s);
             break;
@@ -450,34 +452,37 @@ static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
             tc6393xb_draw_graphic32(s);
             break;
         default:
-            printf("tc6393xb: unknown depth %d\n", ds_get_bits_per_pixel(s->ds));
+            printf("tc6393xb: unknown depth %d\n",
+                   surface_bits_per_pixel(surface));
             return;
     }
 
-    dpy_gfx_update(s->ds, 0, 0, s->scr_width, s->scr_height);
+    dpy_gfx_update(s->con, 0, 0, s->scr_width, s->scr_height);
 }
 
 static void tc6393xb_draw_blank(TC6393xbState *s, int full_update)
 {
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int i, w;
     uint8_t *d;
 
     if (!full_update)
         return;
 
-    w = s->scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
-    d = ds_get_data(s->ds);
+    w = s->scr_width * surface_bytes_per_pixel(surface);
+    d = surface_data(surface);
     for(i = 0; i < s->scr_height; i++) {
         memset(d, 0, w);
-        d += ds_get_linesize(s->ds);
+        d += surface_stride(surface);
     }
 
-    dpy_gfx_update(s->ds, 0, 0, s->scr_width, s->scr_height);
+    dpy_gfx_update(s->con, 0, 0, s->scr_width, s->scr_height);
 }
 
 static void tc6393xb_update_display(void *opaque)
 {
     TC6393xbState *s = opaque;
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int full_update;
 
     if (s->scr_width == 0 || s->scr_height == 0)
@@ -488,8 +493,9 @@ static void tc6393xb_update_display(void *opaque)
         s->blanked = s->blank;
         full_update = 1;
     }
-    if (s->scr_width != ds_get_width(s->ds) || s->scr_height != ds_get_height(s->ds)) {
-        qemu_console_resize(s->ds, s->scr_width, s->scr_height);
+    if (s->scr_width != surface_width(surface) ||
+        s->scr_height != surface_height(surface)) {
+        qemu_console_resize(s->con, s->scr_width, s->scr_height);
         full_update = 1;
     }
     if (s->blanked)
@@ -577,7 +583,7 @@ TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq)
     memory_region_add_subregion(sysmem, base + 0x100000, &s->vram);
     s->scr_width = 480;
     s->scr_height = 640;
-    s->ds = graphic_console_init(tc6393xb_update_display,
+    s->con = graphic_console_init(tc6393xb_update_display,
             NULL, /* invalidate */
             NULL, /* screen_dump */
             NULL, /* text_update */
diff --git a/hw/tc6393xb_template.h b/hw/tc6393xb_template.h
index 4cbbad5..154aafd 100644
--- a/hw/tc6393xb_template.h
+++ b/hw/tc6393xb_template.h
@@ -37,17 +37,18 @@
 
 static void glue(tc6393xb_draw_graphic, BITS)(TC6393xbState *s)
 {
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int i;
     uint16_t *data_buffer;
     uint8_t *data_display;
 
     data_buffer = s->vram_ptr;
-    data_display = ds_get_data(s->ds);
+    data_display = surface_data(surface);
     for(i = 0; i < s->scr_height; i++) {
 #if (BITS == 16)
         memcpy(data_display, data_buffer, s->scr_width * 2);
         data_buffer += s->scr_width;
-        data_display += ds_get_linesize(s->ds);
+        data_display += surface_stride(surface);
 #else
         int j;
         for (j = 0; j < s->scr_width; j++, data_display += BITS / 8, data_buffer++) {
diff --git a/hw/tcx.c b/hw/tcx.c
index 896407d..f1edffd 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -38,7 +38,7 @@
 typedef struct TCXState {
     SysBusDevice busdev;
     hwaddr addr;
-    DisplayState *ds;
+    QemuConsole *con;
     uint8_t *vram;
     uint32_t *vram24, *cplane;
     MemoryRegion vram_mem;
@@ -75,9 +75,11 @@ static void tcx24_set_dirty(TCXState *s)
 
 static void update_palette_entries(TCXState *s, int start, int end)
 {
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int i;
-    for(i = start; i < end; i++) {
-        switch(ds_get_bits_per_pixel(s->ds)) {
+
+    for (i = start; i < end; i++) {
+        switch (surface_bits_per_pixel(surface)) {
         default:
         case 8:
             s->palette[i] = rgb_to_pixel8(s->r[i], s->g[i], s->b[i]);
@@ -89,10 +91,11 @@ static void update_palette_entries(TCXState *s, int start, int end)
             s->palette[i] = rgb_to_pixel16(s->r[i], s->g[i], s->b[i]);
             break;
         case 32:
-            if (is_surface_bgr(s->ds->surface))
+            if (is_surface_bgr(surface)) {
                 s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]);
-            else
+            } else {
                 s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
+            }
             break;
         }
     }
@@ -151,12 +154,13 @@ static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
                                      const uint32_t *cplane,
                                      const uint32_t *s24)
 {
+    DisplaySurface *surface = qemu_console_surface(s1->con);
     int x, bgr, r, g, b;
     uint8_t val, *p8;
     uint32_t *p = (uint32_t *)d;
     uint32_t dval;
 
-    bgr = is_surface_bgr(s1->ds->surface);
+    bgr = is_surface_bgr(surface);
     for(x = 0; x < width; x++, s++, s24++) {
         if ((be32_to_cpu(*cplane++) & 0xff000000) == 0x03000000) {
             // 24-bit direct, BGR order
@@ -213,23 +217,26 @@ static inline void reset_dirty(TCXState *ts, ram_addr_t page_min,
 static void tcx_update_display(void *opaque)
 {
     TCXState *ts = opaque;
+    DisplaySurface *surface = qemu_console_surface(ts->con);
     ram_addr_t page, page_min, page_max;
     int y, y_start, dd, ds;
     uint8_t *d, *s;
     void (*f)(TCXState *s1, uint8_t *dst, const uint8_t *src, int width);
 
-    if (ds_get_bits_per_pixel(ts->ds) == 0)
+    if (surface_bits_per_pixel(surface) == 0) {
         return;
+    }
+
     page = 0;
     y_start = -1;
     page_min = -1;
     page_max = 0;
-    d = ds_get_data(ts->ds);
+    d = surface_data(surface);
     s = ts->vram;
-    dd = ds_get_linesize(ts->ds);
+    dd = surface_stride(surface);
     ds = 1024;
 
-    switch (ds_get_bits_per_pixel(ts->ds)) {
+    switch (surface_bits_per_pixel(surface)) {
     case 32:
         f = tcx_draw_line32;
         break;
@@ -269,7 +276,7 @@ static void tcx_update_display(void *opaque)
         } else {
             if (y_start >= 0) {
                 /* flush to display */
-                dpy_gfx_update(ts->ds, 0, y_start,
+                dpy_gfx_update(ts->con, 0, y_start,
                                ts->width, y - y_start);
                 y_start = -1;
             }
@@ -279,7 +286,7 @@ static void tcx_update_display(void *opaque)
     }
     if (y_start >= 0) {
         /* flush to display */
-        dpy_gfx_update(ts->ds, 0, y_start,
+        dpy_gfx_update(ts->con, 0, y_start,
                        ts->width, y - y_start);
     }
     /* reset modified pages */
@@ -293,24 +300,27 @@ static void tcx_update_display(void *opaque)
 static void tcx24_update_display(void *opaque)
 {
     TCXState *ts = opaque;
+    DisplaySurface *surface = qemu_console_surface(ts->con);
     ram_addr_t page, page_min, page_max, cpage, page24;
     int y, y_start, dd, ds;
     uint8_t *d, *s;
     uint32_t *cptr, *s24;
 
-    if (ds_get_bits_per_pixel(ts->ds) != 32)
+    if (surface_bits_per_pixel(surface) != 32) {
             return;
+    }
+
     page = 0;
     page24 = ts->vram24_offset;
     cpage = ts->cplane_offset;
     y_start = -1;
     page_min = -1;
     page_max = 0;
-    d = ds_get_data(ts->ds);
+    d = surface_data(surface);
     s = ts->vram;
     s24 = ts->vram24;
     cptr = ts->cplane;
-    dd = ds_get_linesize(ts->ds);
+    dd = surface_stride(surface);
     ds = 1024;
 
     for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE,
@@ -345,7 +355,7 @@ static void tcx24_update_display(void *opaque)
         } else {
             if (y_start >= 0) {
                 /* flush to display */
-                dpy_gfx_update(ts->ds, 0, y_start,
+                dpy_gfx_update(ts->con, 0, y_start,
                                ts->width, y - y_start);
                 y_start = -1;
             }
@@ -357,7 +367,7 @@ static void tcx24_update_display(void *opaque)
     }
     if (y_start >= 0) {
         /* flush to display */
-        dpy_gfx_update(ts->ds, 0, y_start,
+        dpy_gfx_update(ts->con, 0, y_start,
                        ts->width, y - y_start);
     }
     /* reset modified pages */
@@ -371,7 +381,7 @@ static void tcx_invalidate_display(void *opaque)
     TCXState *s = opaque;
 
     tcx_set_dirty(s);
-    qemu_console_resize(s->ds, s->width, s->height);
+    qemu_console_resize(s->con, s->width, s->height);
 }
 
 static void tcx24_invalidate_display(void *opaque)
@@ -380,7 +390,7 @@ static void tcx24_invalidate_display(void *opaque)
 
     tcx_set_dirty(s);
     tcx24_set_dirty(s);
-    qemu_console_resize(s->ds, s->width, s->height);
+    qemu_console_resize(s->con, s->width, s->height);
 }
 
 static int vmstate_tcx_post_load(void *opaque, int version_id)
@@ -558,21 +568,21 @@ static int tcx_init1(SysBusDevice *dev)
                                  &s->vram_mem, vram_offset, size);
         sysbus_init_mmio(dev, &s->vram_cplane);
 
-        s->ds = graphic_console_init(tcx24_update_display,
-                                     tcx24_invalidate_display,
-                                     tcx24_screen_dump, NULL, s);
+        s->con = graphic_console_init(tcx24_update_display,
+                                      tcx24_invalidate_display,
+                                      tcx24_screen_dump, NULL, s);
     } else {
         /* THC 8 bit (dummy) */
         memory_region_init_io(&s->thc8, &dummy_ops, s, "tcx.thc8",
                               TCX_THC_NREGS_8);
         sysbus_init_mmio(dev, &s->thc8);
 
-        s->ds = graphic_console_init(tcx_update_display,
-                                     tcx_invalidate_display,
-                                     tcx_screen_dump, NULL, s);
+        s->con = graphic_console_init(tcx_update_display,
+                                      tcx_invalidate_display,
+                                      tcx_screen_dump, NULL, s);
     }
 
-    qemu_console_resize(s->ds, s->width, s->height);
+    qemu_console_resize(s->con, s->width, s->height);
     return 0;
 }
 
diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c
index 4aa62bf..02356d4 100644
--- a/hw/vga-isa-mm.c
+++ b/hw/vga-isa-mm.c
@@ -135,8 +135,9 @@ int isa_vga_mm_init(hwaddr vram_base,
     vga_common_init(&s->vga);
     vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space);
 
-    s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate,
-                                     s->vga.screen_dump, s->vga.text_update, s);
+    s->vga.con = graphic_console_init(s->vga.update, s->vga.invalidate,
+                                      s->vga.screen_dump, s->vga.text_update,
+                                      s);
 
     vga_init_vbe(&s->vga, address_space);
     return 0;
diff --git a/hw/vga-isa.c b/hw/vga-isa.c
index ffad522..9e29321 100644
--- a/hw/vga-isa.c
+++ b/hw/vga-isa.c
@@ -62,8 +62,8 @@ static int vga_initfn(ISADevice *dev)
                                         isa_mem_base + 0x000a0000,
                                         vga_io_memory, 1);
     memory_region_set_coalescing(vga_io_memory);
-    s->ds = graphic_console_init(s->update, s->invalidate,
-                                 s->screen_dump, s->text_update, s);
+    s->con = graphic_console_init(s->update, s->invalidate,
+                                  s->screen_dump, s->text_update, s);
 
     vga_init_vbe(s, isa_address_space(dev));
     /* ROM BIOS */
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index 18018ff..05fa9bc 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -150,8 +150,8 @@ static int pci_std_vga_initfn(PCIDevice *dev)
     vga_common_init(s);
     vga_init(s, pci_address_space(dev), pci_address_space_io(dev), true);
 
-    s->ds = graphic_console_init(s->update, s->invalidate,
-                                 s->screen_dump, s->text_update, s);
+    s->con = graphic_console_init(s->update, s->invalidate,
+                                  s->screen_dump, s->text_update, s);
 
     /* XXX: VGA_RAM_SIZE must be a power of two */
     pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
diff --git a/hw/vga.c b/hw/vga.c
index 13d5066..59bfb22 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1174,9 +1174,9 @@ static int update_basic_params(VGACommonState *s)
 
 #define NB_DEPTHS 7
 
-static inline int get_depth_index(DisplayState *s)
+static inline int get_depth_index(DisplaySurface *s)
 {
-    switch(ds_get_bits_per_pixel(s)) {
+    switch (surface_bits_per_pixel(s)) {
     default:
     case 8:
         return 0;
@@ -1185,10 +1185,11 @@ static inline int get_depth_index(DisplayState *s)
     case 16:
         return 2;
     case 32:
-        if (is_surface_bgr(s->surface))
+        if (is_surface_bgr(s)) {
             return 4;
-        else
+        } else {
             return 3;
+        }
     }
 }
 
@@ -1294,6 +1295,7 @@ static rgb_to_pixel_dup_func * const rgb_to_pixel_dup_table[NB_DEPTHS] = {
  */
 static void vga_draw_text(VGACommonState *s, int full_update)
 {
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
     int cx_min, cx_max, linesize, x_incr, line, line1;
     uint32_t offset, fgcol, bgcol, v, cursor_offset;
@@ -1345,8 +1347,9 @@ static void vga_draw_text(VGACommonState *s, int full_update)
         cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
         s->last_scr_width = width * cw;
         s->last_scr_height = height * cheight;
-        qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
-        dpy_text_resize(s->ds, width, height);
+        qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
+        surface = qemu_console_surface(s->con);
+        dpy_text_resize(s->con, width, height);
         s->last_depth = 0;
         s->last_width = width;
         s->last_height = height;
@@ -1355,10 +1358,10 @@ static void vga_draw_text(VGACommonState *s, int full_update)
         full_update = 1;
     }
     s->rgb_to_pixel =
-        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
+        rgb_to_pixel_dup_table[get_depth_index(surface)];
     full_update |= update_palette16(s);
     palette = s->last_palette;
-    x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
+    x_incr = cw * surface_bytes_per_pixel(surface);
 
     if (full_update) {
         s->full_update_text = 1;
@@ -1389,15 +1392,15 @@ static void vga_draw_text(VGACommonState *s, int full_update)
         s->cursor_visible_phase = !s->cursor_visible_phase;
     }
 
-    depth_index = get_depth_index(s->ds);
+    depth_index = get_depth_index(surface);
     if (cw == 16)
         vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
     else
         vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
     vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
 
-    dest = ds_get_data(s->ds);
-    linesize = ds_get_linesize(s->ds);
+    dest = surface_data(surface);
+    linesize = surface_stride(surface);
     ch_attr_ptr = s->last_ch_attr;
     line = 0;
     offset = s->start_addr * 4;
@@ -1465,7 +1468,7 @@ static void vga_draw_text(VGACommonState *s, int full_update)
             ch_attr_ptr++;
         }
         if (cx_max != -1) {
-            dpy_gfx_update(s->ds, cx_min * cw, cy * cheight,
+            dpy_gfx_update(s->con, cx_min * cw, cy * cheight,
                            (cx_max - cx_min + 1) * cw, cheight);
         }
         dest += linesize * cheight;
@@ -1636,6 +1639,7 @@ void vga_dirty_log_stop(VGACommonState *s)
  */
 static void vga_draw_graphic(VGACommonState *s, int full_update)
 {
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int y1, y, update, linesize, y_start, double_scan, mask, depth;
     int width, height, shift_control, line_offset, bwidth, bits;
     ram_addr_t page0, page1, page_min, page_max;
@@ -1691,13 +1695,13 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
         height != s->last_height ||
         s->last_depth != depth) {
         if (depth == 32 || (depth == 16 && !byteswap)) {
-            DisplaySurface *surface;
             surface = qemu_create_displaysurface_from(disp_width,
                     height, depth, s->line_offset,
                     s->vram_ptr + (s->start_addr * 4), byteswap);
-            dpy_gfx_replace_surface(s->ds, surface);
+            dpy_gfx_replace_surface(s->con, surface);
         } else {
-            qemu_console_resize(s->ds, disp_width, height);
+            qemu_console_resize(s->con, disp_width, height);
+            surface = qemu_console_surface(s->con);
         }
         s->last_scr_width = disp_width;
         s->last_scr_height = height;
@@ -1706,18 +1710,18 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
         s->last_line_offset = s->line_offset;
         s->last_depth = depth;
         full_update = 1;
-    } else if (is_buffer_shared(s->ds->surface) &&
-               (full_update || ds_get_data(s->ds) != s->vram_ptr
+    } else if (is_buffer_shared(surface) &&
+               (full_update || surface_data(surface) != s->vram_ptr
                 + (s->start_addr * 4))) {
         DisplaySurface *surface;
         surface = qemu_create_displaysurface_from(disp_width,
                 height, depth, s->line_offset,
                 s->vram_ptr + (s->start_addr * 4), byteswap);
-        dpy_gfx_replace_surface(s->ds, surface);
+        dpy_gfx_replace_surface(s->con, surface);
     }
 
     s->rgb_to_pixel =
-        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
+        rgb_to_pixel_dup_table[get_depth_index(surface)];
 
     if (shift_control == 0) {
         full_update |= update_palette16(s);
@@ -1766,10 +1770,12 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
             break;
         }
     }
-    vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
+    vga_draw_line = vga_draw_line_table[v * NB_DEPTHS +
+                                        get_depth_index(surface)];
 
-    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
+    if (!is_buffer_shared(surface) && s->cursor_invalidate) {
         s->cursor_invalidate(s);
+    }
 
     line_offset = s->line_offset;
 #if 0
@@ -1782,8 +1788,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
     y_start = -1;
     page_min = -1;
     page_max = 0;
-    d = ds_get_data(s->ds);
-    linesize = ds_get_linesize(s->ds);
+    d = surface_data(surface);
+    linesize = surface_stride(surface);
     y1 = 0;
     for(y = 0; y < height; y++) {
         addr = addr1;
@@ -1810,7 +1816,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
                 page_min = page0;
             if (page1 > page_max)
                 page_max = page1;
-            if (!(is_buffer_shared(s->ds->surface))) {
+            if (!(is_buffer_shared(surface))) {
                 vga_draw_line(s, d, s->vram_ptr + addr, width);
                 if (s->cursor_draw_line)
                     s->cursor_draw_line(s, d, y);
@@ -1818,7 +1824,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
         } else {
             if (y_start >= 0) {
                 /* flush to display */
-                dpy_gfx_update(s->ds, 0, y_start,
+                dpy_gfx_update(s->con, 0, y_start,
                                disp_width, y - y_start);
                 y_start = -1;
             }
@@ -1839,7 +1845,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
     }
     if (y_start >= 0) {
         /* flush to display */
-        dpy_gfx_update(s->ds, 0, y_start,
+        dpy_gfx_update(s->con, 0, y_start,
                        disp_width, y - y_start);
     }
     /* reset modified pages */
@@ -1854,6 +1860,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
 
 static void vga_draw_blank(VGACommonState *s, int full_update)
 {
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int i, w, val;
     uint8_t *d;
 
@@ -1863,18 +1870,19 @@ static void vga_draw_blank(VGACommonState *s, int full_update)
         return;
 
     s->rgb_to_pixel =
-        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
-    if (ds_get_bits_per_pixel(s->ds) == 8)
+        rgb_to_pixel_dup_table[get_depth_index(surface)];
+    if (surface_bits_per_pixel(surface) == 8) {
         val = s->rgb_to_pixel(0, 0, 0);
-    else
+    } else {
         val = 0;
-    w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
-    d = ds_get_data(s->ds);
+    }
+    w = s->last_scr_width * surface_bytes_per_pixel(surface);
+    d = surface_data(surface);
     for(i = 0; i < s->last_scr_height; i++) {
         memset(d, val, w);
-        d += ds_get_linesize(s->ds);
+        d += surface_stride(surface);
     }
-    dpy_gfx_update(s->ds, 0, 0,
+    dpy_gfx_update(s->con, 0, 0,
                    s->last_scr_width, s->last_scr_height);
 }
 
@@ -1885,11 +1893,12 @@ static void vga_draw_blank(VGACommonState *s, int full_update)
 static void vga_update_display(void *opaque)
 {
     VGACommonState *s = opaque;
+    DisplaySurface *surface = qemu_console_surface(s->con);
     int full_update, graphic_mode;
 
     qemu_flush_coalesced_mmio_buffer();
 
-    if (ds_get_bits_per_pixel(s->ds) == 0) {
+    if (surface_bits_per_pixel(surface) == 0) {
         /* nothing to do */
     } else {
         full_update = 0;
@@ -2063,8 +2072,8 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
             cw != s->last_cw || cheight != s->last_ch) {
             s->last_scr_width = width * cw;
             s->last_scr_height = height * cheight;
-            qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
-            dpy_text_resize(s->ds, width, height);
+            qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
+            dpy_text_resize(s->con, width, height);
             s->last_depth = 0;
             s->last_width = width;
             s->last_height = height;
@@ -2089,11 +2098,11 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
             s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
             cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
             if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
-                dpy_text_cursor(s->ds,
+                dpy_text_cursor(s->con,
                                 TEXTMODE_X(cursor_offset),
                                 TEXTMODE_Y(cursor_offset));
             else
-                dpy_text_cursor(s->ds, -1, -1);
+                dpy_text_cursor(s->con, -1, -1);
             s->cursor_offset = cursor_offset;
             s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
             s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
@@ -2106,7 +2115,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
             for (i = 0; i < size; src ++, dst ++, i ++)
                 console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
 
-            dpy_text_update(s->ds, 0, 0, width, height);
+            dpy_text_update(s->con, 0, 0, width, height);
         } else {
             c_max = 0;
 
@@ -2129,7 +2138,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
 
             if (c_min <= c_max) {
                 i = TEXTMODE_Y(c_min);
-                dpy_text_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
+                dpy_text_update(s->con, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
             }
         }
 
@@ -2154,8 +2163,8 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
     /* Display a message */
     s->last_width = 60;
     s->last_height = height = 3;
-    dpy_text_cursor(s->ds, -1, -1);
-    dpy_text_resize(s->ds, s->last_width, height);
+    dpy_text_cursor(s->con, -1, -1);
+    dpy_text_resize(s->con, s->last_width, height);
 
     for (dst = chardata, i = 0; i < s->last_width * height; i ++)
         console_write_ch(dst ++, ' ');
@@ -2166,7 +2175,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
     for (i = 0; i < size; i ++)
         console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
 
-    dpy_text_update(s->ds, 0, 0, s->last_width, height);
+    dpy_text_update(s->con, 0, 0, s->last_width, height);
 }
 
 static uint64_t vga_mem_read(void *opaque, hwaddr addr,
@@ -2438,10 +2447,11 @@ static void vga_screen_dump(void *opaque, const char *filename, bool cswitch,
                             Error **errp)
 {
     VGACommonState *s = opaque;
+    DisplaySurface *surface = qemu_console_surface(s->con);
 
     if (cswitch) {
         vga_invalidate_display(s);
     }
     vga_hw_update();
-    ppm_save(filename, s->ds->surface, errp);
+    ppm_save(filename, surface, errp);
 }
diff --git a/hw/vga_int.h b/hw/vga_int.h
index 8d496ea..260f7d6 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -132,7 +132,7 @@ typedef struct VGACommonState {
     uint32_t vbe_bank_mask;
     int vbe_mapped;
     /* display refresh support */
-    DisplayState *ds;
+    QemuConsole *con;
     uint32_t font_offsets[2];
     int graphic_mode;
     uint8_t shift_control;
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index db2f187..5b9ce8f 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -57,9 +57,6 @@ struct vmsvga_state_s {
     int new_height;
     uint32_t guest;
     uint32_t svgaid;
-    uint32_t wred;
-    uint32_t wgreen;
-    uint32_t wblue;
     int syncing;
 
     MemoryRegion fifo_ram;
@@ -289,6 +286,7 @@ enum {
 static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
                 int x, int y, int w, int h)
 {
+    DisplaySurface *surface = qemu_console_surface(s->vga.con);
     int line;
     int bypl;
     int width;
@@ -305,11 +303,11 @@ static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
         fprintf(stderr, "%s: update w was < 0 (%d)\n", __func__, w);
         w = 0;
     }
-    if (x + w > ds_get_width(s->vga.ds)) {
+    if (x + w > surface_width(surface)) {
         fprintf(stderr, "%s: update width too large x: %d, w: %d\n",
                 __func__, x, w);
-        x = MIN(x, ds_get_width(s->vga.ds));
-        w = ds_get_width(s->vga.ds) - x;
+        x = MIN(x, surface_width(surface));
+        w = surface_width(surface) - x;
     }
 
     if (y < 0) {
@@ -321,23 +319,23 @@ static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
         fprintf(stderr, "%s: update h was < 0 (%d)\n",  __func__, h);
         h = 0;
     }
-    if (y + h > ds_get_height(s->vga.ds)) {
+    if (y + h > surface_height(surface)) {
         fprintf(stderr, "%s: update height too large y: %d, h: %d\n",
                 __func__, y, h);
-        y = MIN(y, ds_get_height(s->vga.ds));
-        h = ds_get_height(s->vga.ds) - y;
+        y = MIN(y, surface_height(surface));
+        h = surface_height(surface) - y;
     }
 
-    bypl = ds_get_linesize(s->vga.ds);
-    width = ds_get_bytes_per_pixel(s->vga.ds) * w;
-    start = ds_get_bytes_per_pixel(s->vga.ds) * x + bypl * y;
+    bypl = surface_stride(surface);
+    width = surface_bytes_per_pixel(surface) * w;
+    start = surface_bytes_per_pixel(surface) * x + bypl * y;
     src = s->vga.vram_ptr + start;
-    dst = ds_get_data(s->vga.ds) + start;
+    dst = surface_data(surface) + start;
 
     for (line = h; line > 0; line--, src += bypl, dst += bypl) {
         memcpy(dst, src, width);
     }
-    dpy_gfx_update(s->vga.ds, x, y, w, h);
+    dpy_gfx_update(s->vga.con, x, y, w, h);
 }
 
 static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s,
@@ -373,9 +371,10 @@ static inline void vmsvga_update_rect_flush(struct vmsvga_state_s *s)
 static inline void vmsvga_copy_rect(struct vmsvga_state_s *s,
                 int x0, int y0, int x1, int y1, int w, int h)
 {
+    DisplaySurface *surface = qemu_console_surface(s->vga.con);
     uint8_t *vram = s->vga.vram_ptr;
-    int bypl = ds_get_linesize(s->vga.ds);
-    int bypp = ds_get_bytes_per_pixel(s->vga.ds);
+    int bypl = surface_stride(surface);
+    int bypp = surface_bytes_per_pixel(surface);
     int width = bypp * w;
     int line = h;
     uint8_t *ptr[2];
@@ -402,8 +401,9 @@ static inline void vmsvga_copy_rect(struct vmsvga_state_s *s,
 static inline void vmsvga_fill_rect(struct vmsvga_state_s *s,
                 uint32_t c, int x, int y, int w, int h)
 {
-    int bypl = ds_get_linesize(s->vga.ds);
-    int width = ds_get_bytes_per_pixel(s->vga.ds) * w;
+    DisplaySurface *surface = qemu_console_surface(s->vga.con);
+    int bypl = surface_stride(surface);
+    int width = surface_bytes_per_pixel(surface) * w;
     int line = h;
     int column;
     uint8_t *fst;
@@ -416,14 +416,14 @@ static inline void vmsvga_fill_rect(struct vmsvga_state_s *s,
     col[2] = c >> 16;
     col[3] = c >> 24;
 
-    fst = s->vga.vram_ptr + ds_get_bytes_per_pixel(s->vga.ds) * x + bypl * y;
+    fst = s->vga.vram_ptr + surface_bytes_per_pixel(surface) * x + bypl * y;
 
     if (line--) {
         dst = fst;
         src = col;
         for (column = width; column > 0; column--) {
             *(dst++) = *(src++);
-            if (src - col == ds_get_bytes_per_pixel(s->vga.ds)) {
+            if (src - col == surface_bytes_per_pixel(surface)) {
                 src = col;
             }
         }
@@ -490,7 +490,7 @@ static inline void vmsvga_cursor_define(struct vmsvga_state_s *s,
         qc = cursor_builtin_left_ptr();
     }
 
-    dpy_cursor_define(s->vga.ds, qc);
+    dpy_cursor_define(s->vga.con, qc);
     cursor_put(qc);
 }
 #endif
@@ -720,6 +720,7 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
 {
     uint32_t caps;
     struct vmsvga_state_s *s = opaque;
+    DisplaySurface *surface = qemu_console_surface(s->vga.con);
 
     switch (s->index) {
     case SVGA_REG_ID:
@@ -729,10 +730,10 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
         return s->enable;
 
     case SVGA_REG_WIDTH:
-        return ds_get_width(s->vga.ds);
+        return surface_width(surface);
 
     case SVGA_REG_HEIGHT:
-        return ds_get_height(s->vga.ds);
+        return surface_height(surface);
 
     case SVGA_REG_MAX_WIDTH:
         return SVGA_MAX_WIDTH;
@@ -750,13 +751,13 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
         return 0x0;
 
     case SVGA_REG_RED_MASK:
-        return s->wred;
+        return surface->pf.rmask;
 
     case SVGA_REG_GREEN_MASK:
-        return s->wgreen;
+        return surface->pf.gmask;
 
     case SVGA_REG_BLUE_MASK:
-        return s->wblue;
+        return surface->pf.bmask;
 
     case SVGA_REG_BYTES_PER_LINE:
         return s->bypp * s->new_width;
@@ -785,7 +786,7 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
         caps |= SVGA_CAP_RECT_FILL;
 #endif
 #ifdef HW_MOUSE_ACCEL
-        if (dpy_cursor_define_supported(s->vga.ds)) {
+        if (dpy_cursor_define_supported(s->vga.con)) {
             caps |= SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 |
                     SVGA_CAP_CURSOR_BYPASS;
         }
@@ -947,7 +948,7 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value)
         s->cursor.on &= (value != SVGA_CURSOR_ON_HIDE);
 #ifdef HW_MOUSE_ACCEL
         if (value <= SVGA_CURSOR_ON_SHOW) {
-            dpy_mouse_set(s->vga.ds, s->cursor.x, s->cursor.y, s->cursor.on);
+            dpy_mouse_set(s->vga.con, s->cursor.x, s->cursor.y, s->cursor.on);
         }
 #endif
         break;
@@ -982,9 +983,11 @@ static void vmsvga_bios_write(void *opaque, uint32_t address, uint32_t data)
 
 static inline void vmsvga_check_size(struct vmsvga_state_s *s)
 {
-    if (s->new_width != ds_get_width(s->vga.ds) ||
-        s->new_height != ds_get_height(s->vga.ds)) {
-        qemu_console_resize(s->vga.ds, s->new_width, s->new_height);
+    DisplaySurface *surface = qemu_console_surface(s->vga.con);
+
+    if (s->new_width != surface_width(surface) ||
+        s->new_height != surface_height(surface)) {
+        qemu_console_resize(s->vga.con, s->new_width, s->new_height);
         s->invalidated = 1;
     }
 }
@@ -992,6 +995,7 @@ static inline void vmsvga_check_size(struct vmsvga_state_s *s)
 static void vmsvga_update_display(void *opaque)
 {
     struct vmsvga_state_s *s = opaque;
+    DisplaySurface *surface = qemu_console_surface(s->vga.con);
     bool dirty = false;
 
     if (!s->enable) {
@@ -1011,19 +1015,19 @@ static void vmsvga_update_display(void *opaque)
     if (memory_region_is_logging(&s->vga.vram)) {
         vga_sync_dirty_bitmap(&s->vga);
         dirty = memory_region_get_dirty(&s->vga.vram, 0,
-            ds_get_linesize(s->vga.ds) * ds_get_height(s->vga.ds),
+            surface_stride(surface) * surface_height(surface),
             DIRTY_MEMORY_VGA);
     }
     if (s->invalidated || dirty) {
         s->invalidated = 0;
-        memcpy(ds_get_data(s->vga.ds), s->vga.vram_ptr,
-               ds_get_linesize(s->vga.ds) * ds_get_height(s->vga.ds));
-        dpy_gfx_update(s->vga.ds, 0, 0,
-                   ds_get_width(s->vga.ds), ds_get_height(s->vga.ds));
+        memcpy(surface_data(surface), s->vga.vram_ptr,
+               surface_stride(surface) * surface_height(surface));
+        dpy_gfx_update(s->vga.con, 0, 0,
+                   surface_width(surface), surface_height(surface));
     }
     if (dirty) {
         memory_region_reset_dirty(&s->vga.vram, 0,
-            ds_get_linesize(s->vga.ds) * ds_get_height(s->vga.ds),
+            surface_stride(surface) * surface_height(surface),
             DIRTY_MEMORY_VGA);
     }
 }
@@ -1063,17 +1067,19 @@ static void vmsvga_screen_dump(void *opaque, const char *filename, bool cswitch,
                                Error **errp)
 {
     struct vmsvga_state_s *s = opaque;
+    DisplaySurface *surface = qemu_console_surface(s->vga.con);
+
     if (!s->enable) {
         s->vga.screen_dump(&s->vga, filename, cswitch, errp);
         return;
     }
 
-    if (ds_get_bits_per_pixel(s->vga.ds) == 32) {
+    if (surface_bits_per_pixel(surface) == 32) {
         DisplaySurface *ds = qemu_create_displaysurface_from(
-                                 ds_get_width(s->vga.ds),
-                                 ds_get_height(s->vga.ds),
+                                 surface_width(surface),
+                                 surface_height(surface),
                                  32,
-                                 ds_get_linesize(s->vga.ds),
+                                 surface_stride(surface),
                                  s->vga.vram_ptr, false);
         ppm_save(filename, ds, errp);
         g_free(ds);
@@ -1143,14 +1149,16 @@ static const VMStateDescription vmstate_vmware_vga = {
 static void vmsvga_init(struct vmsvga_state_s *s,
                         MemoryRegion *address_space, MemoryRegion *io)
 {
+    DisplaySurface *surface;
+
     s->scratch_size = SVGA_SCRATCH_SIZE;
     s->scratch = g_malloc(s->scratch_size * 4);
 
-    s->vga.ds = graphic_console_init(vmsvga_update_display,
-                                     vmsvga_invalidate_display,
-                                     vmsvga_screen_dump,
-                                     vmsvga_text_update, s);
-
+    s->vga.con = graphic_console_init(vmsvga_update_display,
+                                      vmsvga_invalidate_display,
+                                      vmsvga_screen_dump,
+                                      vmsvga_text_update, s);
+    surface = qemu_console_surface(s->vga.con);
 
     s->fifo_size = SVGA_FIFO_SIZE;
     memory_region_init_ram(&s->fifo_ram, "vmsvga.fifo", s->fifo_size);
@@ -1162,11 +1170,8 @@ static void vmsvga_init(struct vmsvga_state_s *s,
     vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga);
     /* Save some values here in case they are changed later.
      * This is suspicious and needs more though why it is needed. */
-    s->depth = ds_get_bits_per_pixel(s->vga.ds);
-    s->bypp = ds_get_bytes_per_pixel(s->vga.ds);
-    s->wred = ds_get_rmask(s->vga.ds);
-    s->wgreen = ds_get_gmask(s->vga.ds);
-    s->wblue = ds_get_bmask(s->vga.ds);
+    s->depth = surface_bits_per_pixel(surface);
+    s->bypp = surface_bytes_per_pixel(surface);
 }
 
 static uint64_t vmsvga_io_read(void *opaque, hwaddr addr, unsigned size)
diff --git a/hw/xenfb.c b/hw/xenfb.c
index 7779097..7c46a2f 100644
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -54,7 +54,7 @@
 struct common {
     struct XenDevice  xendev;  /* must be first */
     void              *page;
-    DisplayState      *ds;
+    QemuConsole       *con;
 };
 
 struct XenInput {
@@ -318,8 +318,9 @@ static void xenfb_mouse_event(void *opaque,
 			      int dx, int dy, int dz, int button_state)
 {
     struct XenInput *xenfb = opaque;
-    int dw = ds_get_width(xenfb->c.ds);
-    int dh = ds_get_height(xenfb->c.ds);
+    DisplaySurface *surface = qemu_console_surface(xenfb->c.con);
+    int dw = surface_width(surface);
+    int dh = surface_height(surface);
     int i;
 
     if (xenfb->abs_pointer_wanted)
@@ -353,16 +354,9 @@ static int input_initialise(struct XenDevice *xendev)
     struct XenInput *in = container_of(xendev, struct XenInput, c.xendev);
     int rc;
 
-    if (!in->c.ds) {
-        char *vfb = xenstore_read_str(NULL, "device/vfb");
-        if (vfb == NULL) {
-            /* there is no vfb, run vkbd on its own */
-            in->c.ds = get_displaystate();
-        } else {
-            g_free(vfb);
-            xen_be_printf(xendev, 1, "ds not set (yet)\n");
-            return -1;
-        }
+    if (!in->c.con) {
+        xen_be_printf(xendev, 1, "ds not set (yet)\n");
+        return -1;
     }
 
     rc = common_bind(&in->c);
@@ -615,12 +609,13 @@ static int xenfb_configure_fb(struct XenFB *xenfb, size_t fb_len_lim,
  */
 static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h)
 {
+    DisplaySurface *surface = qemu_console_surface(xenfb->c.con);
     int line, oops = 0;
-    int bpp = ds_get_bits_per_pixel(xenfb->c.ds);
-    int linesize = ds_get_linesize(xenfb->c.ds);
-    uint8_t *data = ds_get_data(xenfb->c.ds);
+    int bpp = surface_bits_per_pixel(surface);
+    int linesize = surface_stride(surface);
+    uint8_t *data = surface_data(surface);
 
-    if (!is_buffer_shared(xenfb->c.ds->surface)) {
+    if (!is_buffer_shared(surface)) {
         switch (xenfb->depth) {
         case 8:
             if (bpp == 16) {
@@ -648,10 +643,10 @@ static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h)
         xen_be_printf(&xenfb->c.xendev, 0, "%s: oops: convert %d -> %d bpp?\n",
                       __FUNCTION__, xenfb->depth, bpp);
 
-    dpy_gfx_update(xenfb->c.ds, x, y, w, h);
+    dpy_gfx_update(xenfb->c.con, x, y, w, h);
 }
 
-#ifdef XENFB_TYPE_REFRESH_PERIOD
+#if 0 /* def XENFB_TYPE_REFRESH_PERIOD */
 static int xenfb_queue_full(struct XenFB *xenfb)
 {
     struct xenfb_page *page = xenfb->c.page;
@@ -710,7 +705,7 @@ static void xenfb_update(void *opaque)
         return;
 
     if (xenfb->feature_update) {
-#ifdef XENFB_TYPE_REFRESH_PERIOD
+#if 0 /* XENFB_TYPE_REFRESH_PERIOD */
         struct DisplayChangeListener *l;
         int period = 99999999;
         int idle = 1;
@@ -764,10 +759,10 @@ static void xenfb_update(void *opaque)
             surface = qemu_create_displaysurface(xenfb->width, xenfb->height);
             break;
         }
-        dpy_gfx_replace_surface(xenfb->c.ds, surface);
+        dpy_gfx_replace_surface(xenfb->c.con, surface);
         xen_be_printf(&xenfb->c.xendev, 1, "update: resizing: %dx%d @ %d bpp%s\n",
                       xenfb->width, xenfb->height, xenfb->depth,
-                      is_buffer_shared(xenfb->c.ds->surface) ? " (shared)" : "");
+                      is_buffer_shared(surface) ? " (shared)" : "");
         xenfb->up_fullscreen = 1;
     }
 
@@ -1009,16 +1004,16 @@ wait_more:
 
     /* vfb */
     fb = container_of(xfb, struct XenFB, c.xendev);
-    fb->c.ds = graphic_console_init(xenfb_update,
-                                    xenfb_invalidate,
-                                    NULL,
-                                    NULL,
-                                    fb);
+    fb->c.con = graphic_console_init(xenfb_update,
+                                     xenfb_invalidate,
+                                     NULL,
+                                     NULL,
+                                     fb);
     fb->have_console = 1;
 
     /* vkbd */
     in = container_of(xin, struct XenInput, c.xendev);
-    in->c.ds = fb->c.ds;
+    in->c.con = fb->c.con;
 
     /* retry ->init() */
     xen_be_check_state(xin);
diff --git a/include/ui/console.h b/include/ui/console.h
index c32c834..92c31a9 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -223,18 +223,18 @@ void register_displaychangelistener(DisplayState *ds,
                                     DisplayChangeListener *dcl);
 void unregister_displaychangelistener(DisplayChangeListener *dcl);
 
-void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h);
-void dpy_gfx_replace_surface(DisplayState *s,
+void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h);
+void dpy_gfx_replace_surface(QemuConsole *con,
                              DisplaySurface *surface);
 void dpy_refresh(DisplayState *s);
-void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y,
+void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
                   int dst_x, int dst_y, int w, int h);
-void dpy_text_cursor(struct DisplayState *s, int x, int y);
-void dpy_text_update(DisplayState *s, int x, int y, int w, int h);
-void dpy_text_resize(DisplayState *s, int w, int h);
-void dpy_mouse_set(struct DisplayState *s, int x, int y, int on);
-void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor);
-bool dpy_cursor_define_supported(struct DisplayState *s);
+void dpy_text_cursor(QemuConsole *con, int x, int y);
+void dpy_text_update(QemuConsole *con, int x, int y, int w, int h);
+void dpy_text_resize(QemuConsole *con, int w, int h);
+void dpy_mouse_set(QemuConsole *con, int x, int y, int on);
+void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor);
+bool dpy_cursor_define_supported(QemuConsole *con);
 
 static inline int surface_stride(DisplaySurface *s)
 {
@@ -347,11 +347,11 @@ typedef void (*vga_hw_screen_dump_ptr)(void *, const char *, bool cswitch,
                                        Error **errp);
 typedef void (*vga_hw_text_update_ptr)(void *, console_ch_t *);
 
-DisplayState *graphic_console_init(vga_hw_update_ptr update,
-                                   vga_hw_invalidate_ptr invalidate,
-                                   vga_hw_screen_dump_ptr screen_dump,
-                                   vga_hw_text_update_ptr text_update,
-                                   void *opaque);
+QemuConsole *graphic_console_init(vga_hw_update_ptr update,
+                                  vga_hw_invalidate_ptr invalidate,
+                                  vga_hw_screen_dump_ptr screen_dump,
+                                  vga_hw_text_update_ptr text_update,
+                                  void *opaque);
 
 void vga_hw_update(void);
 void vga_hw_invalidate(void);
@@ -362,9 +362,11 @@ int is_fixedsize_console(void);
 void text_consoles_set_display(DisplayState *ds);
 void console_select(unsigned int index);
 void console_color_init(DisplayState *ds);
-void qemu_console_resize(DisplayState *ds, int width, int height);
-void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
+void qemu_console_resize(QemuConsole *con, int width, int height);
+void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
                        int dst_x, int dst_y, int w, int h);
+DisplaySurface *qemu_console_surface(QemuConsole *con);
+DisplayState *qemu_console_displaystate(QemuConsole *console);
 
 typedef CharDriverState *(VcHandler)(ChardevVC *vc);
 
diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h
index a9e1e09..7a20fc4 100644
--- a/include/ui/spice-display.h
+++ b/include/ui/spice-display.h
@@ -71,6 +71,7 @@ typedef struct SimpleSpiceDisplay SimpleSpiceDisplay;
 typedef struct SimpleSpiceUpdate SimpleSpiceUpdate;
 
 struct SimpleSpiceDisplay {
+    QemuConsole *con;
     DisplaySurface *ds;
     DisplayChangeListener dcl;
     void *buf;
@@ -113,7 +114,7 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd);
 void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd);
 void qemu_spice_vm_change_state_handler(void *opaque, int running,
                                         RunState state);
-void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds);
+void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd);
 
 void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
                                int x, int y, int w, int h);
diff --git a/ui/console.c b/ui/console.c
index d690e1c..d5ec271 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -664,7 +664,7 @@ static void console_refresh(QemuConsole *s)
             }
         }
         console_show_cursor(s, 1);
-        dpy_gfx_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
+        dpy_gfx_update(s, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
     }
 }
 
@@ -1101,10 +1101,10 @@ void console_select(unsigned int index)
         if (ds->have_gfx) {
             DisplaySurface *surface;
             surface = qemu_create_displaysurface(s->g_width, s->g_height);
-            dpy_gfx_replace_surface(ds, surface);
+            dpy_gfx_replace_surface(s, surface);
         }
         if (ds->have_text) {
-            dpy_text_resize(ds, s->width, s->height);
+            dpy_text_resize(s, s->width, s->height);
         }
         if (s->cursor_timer) {
             qemu_mod_timer(s->cursor_timer,
@@ -1129,7 +1129,7 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
     }
     console_show_cursor(s, 1);
     if (s->ds->have_gfx && s->update_x0 < s->update_x1) {
-        dpy_gfx_update(s->ds, s->update_x0, s->update_y0,
+        dpy_gfx_update(s, s->update_x0, s->update_y0,
                        s->update_x1 - s->update_x0,
                        s->update_y1 - s->update_y0);
     }
@@ -1239,7 +1239,7 @@ static void text_console_update(void *opaque, console_ch_t *chardata)
                                 (s->cells[src].t_attrib.fgcol << 12) |
                                 (s->cells[src].t_attrib.bgcol << 8) |
                                 (s->cells[src].t_attrib.bold << 21));
-        dpy_text_update(s->ds, s->text_x[0], s->text_y[0],
+        dpy_text_update(s, s->text_x[0], s->text_y[0],
                         s->text_x[1] - s->text_x[0], i - s->text_y[0]);
         s->text_x[0] = s->width;
         s->text_y[0] = s->height;
@@ -1247,23 +1247,11 @@ static void text_console_update(void *opaque, console_ch_t *chardata)
         s->text_y[1] = 0;
     }
     if (s->cursor_invalidate) {
-        dpy_text_cursor(s->ds, s->x, s->y);
+        dpy_text_cursor(s, s->x, s->y);
         s->cursor_invalidate = 0;
     }
 }
 
-static QemuConsole *get_graphic_console(DisplayState *ds)
-{
-    int i;
-    QemuConsole *s;
-    for (i = 0; i < nb_consoles; i++) {
-        s = consoles[i];
-        if (s->console_type == GRAPHIC_CONSOLE && s->ds == ds)
-            return s;
-    }
-    return NULL;
-}
-
 static QemuConsole *new_console(DisplayState *ds, console_type_t console_type)
 {
     QemuConsole *s;
@@ -1385,8 +1373,9 @@ void unregister_displaychangelistener(DisplayChangeListener *dcl)
     gui_setup_refresh(ds);
 }
 
-void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h)
+void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h)
 {
+    DisplayState *s = con->ds;
     struct DisplayChangeListener *dcl;
     int width = pixman_image_get_width(s->surface->image);
     int height = pixman_image_get_height(s->surface->image);
@@ -1405,9 +1394,10 @@ void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h)
     }
 }
 
-void dpy_gfx_replace_surface(DisplayState *s,
+void dpy_gfx_replace_surface(QemuConsole *con,
                              DisplaySurface *surface)
 {
+    DisplayState *s = con->ds;
     DisplaySurface *old_surface = s->surface;
     struct DisplayChangeListener *dcl;
 
@@ -1430,9 +1420,10 @@ void dpy_refresh(DisplayState *s)
     }
 }
 
-void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y,
-                             int dst_x, int dst_y, int w, int h)
+void dpy_gfx_copy(QemuConsole *con, int src_x, int src_y,
+                  int dst_x, int dst_y, int w, int h)
 {
+    DisplayState *s = con->ds;
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_gfx_copy) {
@@ -1443,8 +1434,9 @@ void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y,
     }
 }
 
-void dpy_text_cursor(struct DisplayState *s, int x, int y)
+void dpy_text_cursor(QemuConsole *con, int x, int y)
 {
+    DisplayState *s = con->ds;
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_text_cursor) {
@@ -1453,8 +1445,9 @@ void dpy_text_cursor(struct DisplayState *s, int x, int y)
     }
 }
 
-void dpy_text_update(DisplayState *s, int x, int y, int w, int h)
+void dpy_text_update(QemuConsole *con, int x, int y, int w, int h)
 {
+    DisplayState *s = con->ds;
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_text_update) {
@@ -1463,8 +1456,9 @@ void dpy_text_update(DisplayState *s, int x, int y, int w, int h)
     }
 }
 
-void dpy_text_resize(DisplayState *s, int w, int h)
+void dpy_text_resize(QemuConsole *con, int w, int h)
 {
+    DisplayState *s = con->ds;
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_text_resize) {
@@ -1473,8 +1467,9 @@ void dpy_text_resize(DisplayState *s, int w, int h)
     }
 }
 
-void dpy_mouse_set(struct DisplayState *s, int x, int y, int on)
+void dpy_mouse_set(QemuConsole *con, int x, int y, int on)
 {
+    DisplayState *s = con->ds;
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_mouse_set) {
@@ -1483,8 +1478,9 @@ void dpy_mouse_set(struct DisplayState *s, int x, int y, int on)
     }
 }
 
-void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor)
+void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor)
 {
+    DisplayState *s = con->ds;
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_cursor_define) {
@@ -1493,8 +1489,9 @@ void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor)
     }
 }
 
-bool dpy_cursor_define_supported(struct DisplayState *s)
+bool dpy_cursor_define_supported(QemuConsole *con)
 {
+    DisplayState *s = con->ds;
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_cursor_define) {
@@ -1507,7 +1504,6 @@ bool dpy_cursor_define_supported(struct DisplayState *s)
 static void dumb_display_init(void)
 {
     DisplayState *ds = g_malloc0(sizeof(DisplayState));
-    DisplaySurface *surface;
     int width = 640;
     int height = 480;
 
@@ -1515,8 +1511,7 @@ static void dumb_display_init(void)
         width = active_console->g_width;
         height = active_console->g_height;
     }
-    surface = qemu_create_displaysurface(width, height);
-    dpy_gfx_replace_surface(ds, surface);
+    ds->surface = qemu_create_displaysurface(width, height);
 
     register_displaystate(ds);
 }
@@ -1542,15 +1537,14 @@ DisplayState *get_displaystate(void)
     return display_state;
 }
 
-DisplayState *graphic_console_init(vga_hw_update_ptr update,
-                                   vga_hw_invalidate_ptr invalidate,
-                                   vga_hw_screen_dump_ptr screen_dump,
-                                   vga_hw_text_update_ptr text_update,
-                                   void *opaque)
+QemuConsole *graphic_console_init(vga_hw_update_ptr update,
+                                  vga_hw_invalidate_ptr invalidate,
+                                  vga_hw_screen_dump_ptr screen_dump,
+                                  vga_hw_text_update_ptr text_update,
+                                  void *opaque)
 {
     QemuConsole *s;
     DisplayState *ds;
-    DisplaySurface *surface;
 
     ds = (DisplayState *) g_malloc0(sizeof(DisplayState));
     s = new_console(ds, GRAPHIC_CONSOLE);
@@ -1560,11 +1554,10 @@ DisplayState *graphic_console_init(vga_hw_update_ptr update,
     s->hw_text_update = text_update;
     s->hw = opaque;
 
-    surface = qemu_create_displaysurface(640, 480);
-    dpy_gfx_replace_surface(ds, surface);
+    ds->surface = qemu_create_displaysurface(640, 480);
 
     register_displaystate(ds);
-    return ds;
+    return s;
 }
 
 int is_graphic_console(void)
@@ -1730,28 +1723,35 @@ void text_consoles_set_display(DisplayState *ds)
     }
 }
 
-void qemu_console_resize(DisplayState *ds, int width, int height)
+void qemu_console_resize(QemuConsole *s, int width, int height)
 {
-    QemuConsole *s = get_graphic_console(ds);
-    if (!s) return;
-
     s->g_width = width;
     s->g_height = height;
     if (is_graphic_console()) {
         DisplaySurface *surface;
         surface = qemu_create_displaysurface(width, height);
-        dpy_gfx_replace_surface(ds, surface);
+        dpy_gfx_replace_surface(s, surface);
     }
 }
 
-void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
+void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
                        int dst_x, int dst_y, int w, int h)
 {
     if (is_graphic_console()) {
-        dpy_gfx_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
+        dpy_gfx_copy(con, src_x, src_y, dst_x, dst_y, w, h);
     }
 }
 
+DisplaySurface *qemu_console_surface(QemuConsole *console)
+{
+    return console->ds->surface;
+}
+
+DisplayState *qemu_console_displaystate(QemuConsole *console)
+{
+    return console->ds;
+}
+
 PixelFormat qemu_different_endianness_pixelformat(int bpp)
 {
     PixelFormat pf;
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 2127b3f..eaab19d 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -334,7 +334,7 @@ void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
     qemu_spice_destroy_primary_surface(ssd, 0, QXL_SYNC);
 }
 
-void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds)
+void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd)
 {
     qemu_mutex_init(&ssd->lock);
     QTAILQ_INIT(&ssd->updates);
@@ -398,12 +398,14 @@ void qemu_spice_display_switch(SimpleSpiceDisplay *ssd,
 void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd)
 {
     if (ssd->cursor) {
-        dpy_cursor_define(ssd->dcl.ds, ssd->cursor);
+        assert(ssd->con);
+        dpy_cursor_define(ssd->con, ssd->cursor);
         cursor_put(ssd->cursor);
         ssd->cursor = NULL;
     }
     if (ssd->mouse_x != -1 && ssd->mouse_y != -1) {
-        dpy_mouse_set(ssd->dcl.ds, ssd->mouse_x, ssd->mouse_y, 1);
+        assert(ssd->con);
+        dpy_mouse_set(ssd->con, ssd->mouse_x, ssd->mouse_y, 1);
         ssd->mouse_x = -1;
         ssd->mouse_y = -1;
     }
@@ -613,7 +615,7 @@ void qemu_spice_display_init(DisplayState *ds)
 {
     SimpleSpiceDisplay *ssd = g_new0(SimpleSpiceDisplay, 1);
 
-    qemu_spice_display_init_common(ssd, ds);
+    qemu_spice_display_init_common(ssd);
 
     ssd->qxl.base.sif = &dpy_interface.base;
     qemu_spice_add_interface(&ssd->qxl.base);
commit bc2ed9704fff2c721e4056ab5281f0291718bfa6
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Mar 1 13:03:04 2013 +0100

    console: zap displaystate from dcl callbacks
    
    Now that nobody depends on DisplayState in DisplayChangeListener
    callbacks any more we can remove the parameter from all callbacks.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index 6ed61be..0939ace 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1865,7 +1865,6 @@ static void qxl_vm_change_state_handler(void *opaque, int running,
 /* display change listener */
 
 static void display_update(DisplayChangeListener *dcl,
-                           struct DisplayState *ds,
                            int x, int y, int w, int h)
 {
     PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl);
@@ -1876,7 +1875,6 @@ static void display_update(DisplayChangeListener *dcl,
 }
 
 static void display_switch(DisplayChangeListener *dcl,
-                           struct DisplayState *ds,
                            struct DisplaySurface *surface)
 {
     PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl);
@@ -1887,8 +1885,7 @@ static void display_switch(DisplayChangeListener *dcl,
     }
 }
 
-static void display_refresh(DisplayChangeListener *dcl,
-                            struct DisplayState *ds)
+static void display_refresh(DisplayChangeListener *dcl)
 {
     PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl);
 
diff --git a/include/ui/console.h b/include/ui/console.h
index a35b71a..c32c834 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -150,34 +150,26 @@ void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask);
 typedef struct DisplayChangeListenerOps {
     const char *dpy_name;
 
-    void (*dpy_refresh)(DisplayChangeListener *dcl,
-                        struct DisplayState *s);
+    void (*dpy_refresh)(DisplayChangeListener *dcl);
 
     void (*dpy_gfx_update)(DisplayChangeListener *dcl,
-                           struct DisplayState *s,
                            int x, int y, int w, int h);
     void (*dpy_gfx_switch)(DisplayChangeListener *dcl,
-                           struct DisplayState *s,
                            struct DisplaySurface *new_surface);
     void (*dpy_gfx_copy)(DisplayChangeListener *dcl,
-                         struct DisplayState *s, int src_x, int src_y,
+                         int src_x, int src_y,
                          int dst_x, int dst_y, int w, int h);
 
     void (*dpy_text_cursor)(DisplayChangeListener *dcl,
-                            struct DisplayState *s,
                             int x, int y);
     void (*dpy_text_resize)(DisplayChangeListener *dcl,
-                            struct DisplayState *s,
                             int w, int h);
     void (*dpy_text_update)(DisplayChangeListener *dcl,
-                            struct DisplayState *s,
                             int x, int y, int w, int h);
 
     void (*dpy_mouse_set)(DisplayChangeListener *dcl,
-                          struct DisplayState *s,
                           int x, int y, int on);
     void (*dpy_cursor_define)(DisplayChangeListener *dcl,
-                              struct DisplayState *s,
                               QEMUCursor *cursor);
 } DisplayChangeListenerOps;
 
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 9a56fb8..8e0eaa2 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -955,7 +955,6 @@ int main (int argc, const char * argv[]) {
 
 #pragma mark qemu
 static void cocoa_update(DisplayChangeListener *dcl,
-                         DisplayState *dontuse,
                          int x, int y, int w, int h)
 {
     COCOA_DEBUG("qemu_cocoa: cocoa_update\n");
@@ -974,7 +973,6 @@ static void cocoa_update(DisplayChangeListener *dcl,
 }
 
 static void cocoa_switch(DisplayChangeListener *dcl,
-                         DisplayState *dontuse,
                          DisplaySurface *surface)
 {
     COCOA_DEBUG("qemu_cocoa: cocoa_resize\n");
@@ -982,8 +980,7 @@ static void cocoa_switch(DisplayChangeListener *dcl,
     [cocoaView switchSurface:surface];
 }
 
-static void cocoa_refresh(DisplayChangeListener *dcl,
-                          DisplayState *dontuse)
+static void cocoa_refresh(DisplayChangeListener *dcl)
 {
     COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n");
 
diff --git a/ui/console.c b/ui/console.c
index 4541b2c..d690e1c 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1373,7 +1373,7 @@ void register_displaychangelistener(DisplayState *ds,
     QLIST_INSERT_HEAD(&ds->listeners, dcl, next);
     gui_setup_refresh(ds);
     if (dcl->ops->dpy_gfx_switch) {
-        dcl->ops->dpy_gfx_switch(dcl, ds, ds->surface);
+        dcl->ops->dpy_gfx_switch(dcl, ds->surface);
     }
 }
 
@@ -1400,7 +1400,7 @@ void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h)
 
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_gfx_update) {
-            dcl->ops->dpy_gfx_update(dcl, s, x, y, w, h);
+            dcl->ops->dpy_gfx_update(dcl, x, y, w, h);
         }
     }
 }
@@ -1414,7 +1414,7 @@ void dpy_gfx_replace_surface(DisplayState *s,
     s->surface = surface;
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_gfx_switch) {
-            dcl->ops->dpy_gfx_switch(dcl, s, surface);
+            dcl->ops->dpy_gfx_switch(dcl, surface);
         }
     }
     qemu_free_displaysurface(old_surface);
@@ -1425,7 +1425,7 @@ void dpy_refresh(DisplayState *s)
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_refresh) {
-            dcl->ops->dpy_refresh(dcl, s);
+            dcl->ops->dpy_refresh(dcl);
         }
     }
 }
@@ -1436,9 +1436,9 @@ void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y,
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_gfx_copy) {
-            dcl->ops->dpy_gfx_copy(dcl, s, src_x, src_y, dst_x, dst_y, w, h);
+            dcl->ops->dpy_gfx_copy(dcl, src_x, src_y, dst_x, dst_y, w, h);
         } else { /* TODO */
-            dcl->ops->dpy_gfx_update(dcl, s, dst_x, dst_y, w, h);
+            dcl->ops->dpy_gfx_update(dcl, dst_x, dst_y, w, h);
         }
     }
 }
@@ -1448,7 +1448,7 @@ void dpy_text_cursor(struct DisplayState *s, int x, int y)
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_text_cursor) {
-            dcl->ops->dpy_text_cursor(dcl, s, x, y);
+            dcl->ops->dpy_text_cursor(dcl, x, y);
         }
     }
 }
@@ -1458,7 +1458,7 @@ void dpy_text_update(DisplayState *s, int x, int y, int w, int h)
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_text_update) {
-            dcl->ops->dpy_text_update(dcl, s, x, y, w, h);
+            dcl->ops->dpy_text_update(dcl, x, y, w, h);
         }
     }
 }
@@ -1468,7 +1468,7 @@ void dpy_text_resize(DisplayState *s, int w, int h)
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_text_resize) {
-            dcl->ops->dpy_text_resize(dcl, s, w, h);
+            dcl->ops->dpy_text_resize(dcl, w, h);
         }
     }
 }
@@ -1478,7 +1478,7 @@ void dpy_mouse_set(struct DisplayState *s, int x, int y, int on)
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_mouse_set) {
-            dcl->ops->dpy_mouse_set(dcl, s, x, y, on);
+            dcl->ops->dpy_mouse_set(dcl, x, y, on);
         }
     }
 }
@@ -1488,7 +1488,7 @@ void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor)
     struct DisplayChangeListener *dcl;
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_cursor_define) {
-            dcl->ops->dpy_cursor_define(dcl, s, cursor);
+            dcl->ops->dpy_cursor_define(dcl, cursor);
         }
     }
 }
diff --git a/ui/curses.c b/ui/curses.c
index ca9856c..ff82307 100644
--- a/ui/curses.c
+++ b/ui/curses.c
@@ -42,7 +42,6 @@ static int width, height, gwidth, gheight, invalidate;
 static int px, py, sminx, sminy, smaxx, smaxy;
 
 static void curses_update(DisplayChangeListener *dcl,
-                          DisplayState *ds,
                           int x, int y, int w, int h)
 {
     chtype *line;
@@ -95,7 +94,6 @@ static void curses_calc_pad(void)
 }
 
 static void curses_resize(DisplayChangeListener *dcl,
-                          DisplayState *ds,
                           int width, int height)
 {
     if (width == gwidth && height == gheight) {
@@ -134,7 +132,6 @@ static void curses_winch_handler(int signum)
 #endif
 
 static void curses_cursor_position(DisplayChangeListener *dcl,
-                                   DisplayState *ds,
                                    int x, int y)
 {
     if (x >= 0) {
@@ -161,8 +158,7 @@ static void curses_cursor_position(DisplayChangeListener *dcl,
 
 static kbd_layout_t *kbd_layout = NULL;
 
-static void curses_refresh(DisplayChangeListener *dcl,
-                           DisplayState *ds)
+static void curses_refresh(DisplayChangeListener *dcl)
 {
     int chr, nextchr, keysym, keycode, keycode_alt;
 
@@ -195,7 +191,7 @@ static void curses_refresh(DisplayChangeListener *dcl,
             clear();
             refresh();
             curses_calc_pad();
-            curses_update(dcl, ds, 0, 0, width, height);
+            curses_update(dcl, 0, 0, width, height);
             continue;
         }
 #endif
diff --git a/ui/gtk.c b/ui/gtk.c
index d553550..305940d 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -266,7 +266,7 @@ static void gd_update_full_redraw(GtkDisplayState *s)
 /** DisplayState Callbacks **/
 
 static void gd_update(DisplayChangeListener *dcl,
-                      DisplayState *dontuse, int x, int y, int w, int h)
+                      int x, int y, int w, int h)
 {
     GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
     int x1, x2, y1, y2;
@@ -298,14 +298,12 @@ static void gd_update(DisplayChangeListener *dcl,
     gtk_widget_queue_draw_area(s->drawing_area, mx + x1, my + y1, (x2 - x1), (y2 - y1));
 }
 
-static void gd_refresh(DisplayChangeListener *dcl,
-                       DisplayState *dontuse)
+static void gd_refresh(DisplayChangeListener *dcl)
 {
     vga_hw_update();
 }
 
 static void gd_switch(DisplayChangeListener *dcl,
-                      DisplayState *dontuse,
                       DisplaySurface *surface)
 {
     GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
diff --git a/ui/sdl.c b/ui/sdl.c
index 58f16bc..8da0534 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -61,7 +61,6 @@ static int scaling_active = 0;
 static Notifier mouse_mode_notifier;
 
 static void sdl_update(DisplayChangeListener *dcl,
-                       DisplayState *dontuse,
                        int x, int y, int w, int h)
 {
     //    printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
@@ -108,7 +107,6 @@ static void do_sdl_resize(int width, int height, int bpp)
 }
 
 static void sdl_switch(DisplayChangeListener *dcl,
-                       DisplayState *dontuse,
                        DisplaySurface *new_surface)
 {
 
@@ -523,7 +521,7 @@ static void handle_keydown(SDL_Event *ev)
         case 0x16: /* 'u' key on US keyboard */
             if (scaling_active) {
                 scaling_active = 0;
-                sdl_switch(dcl, NULL, NULL);
+                sdl_switch(dcl, NULL);
                 vga_hw_invalidate();
                 vga_hw_update();
             }
@@ -763,8 +761,7 @@ static void handle_activation(SDL_Event *ev)
     }
 }
 
-static void sdl_refresh(DisplayChangeListener *dcl,
-                        DisplayState *dontuse)
+static void sdl_refresh(DisplayChangeListener *dcl)
 {
     SDL_Event ev1, *ev = &ev1;
 
@@ -779,7 +776,7 @@ static void sdl_refresh(DisplayChangeListener *dcl,
     while (SDL_PollEvent(ev)) {
         switch (ev->type) {
         case SDL_VIDEOEXPOSE:
-            sdl_update(dcl, dontuse, 0, 0, real_screen->w, real_screen->h);
+            sdl_update(dcl, 0, 0, real_screen->w, real_screen->h);
             break;
         case SDL_KEYDOWN:
             handle_keydown(ev);
@@ -815,7 +812,6 @@ static void sdl_refresh(DisplayChangeListener *dcl,
 }
 
 static void sdl_mouse_warp(DisplayChangeListener *dcl,
-                           DisplayState *ds,
                            int x, int y, int on)
 {
     if (on) {
@@ -833,7 +829,6 @@ static void sdl_mouse_warp(DisplayChangeListener *dcl,
 }
 
 static void sdl_mouse_define(DisplayChangeListener *dcl,
-                             DisplayState *ds,
                              QEMUCursor *c)
 {
     uint8_t *image, *mask;
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 5bbe23b..2127b3f 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -583,7 +583,6 @@ static const QXLInterface dpy_interface = {
 };
 
 static void display_update(DisplayChangeListener *dcl,
-                           struct DisplayState *ds,
                            int x, int y, int w, int h)
 {
     SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
@@ -591,15 +590,13 @@ static void display_update(DisplayChangeListener *dcl,
 }
 
 static void display_switch(DisplayChangeListener *dcl,
-                           struct DisplayState *ds,
                            struct DisplaySurface *surface)
 {
     SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
     qemu_spice_display_switch(ssd, surface);
 }
 
-static void display_refresh(DisplayChangeListener *dcl,
-                            struct DisplayState *ds)
+static void display_refresh(DisplayChangeListener *dcl)
 {
     SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
     qemu_spice_display_refresh(ssd);
diff --git a/ui/vnc.c b/ui/vnc.c
index f38aeda..bbe1e0f 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -430,7 +430,6 @@ static void vnc_refresh(void *opaque);
 static int vnc_refresh_server_surface(VncDisplay *vd);
 
 static void vnc_dpy_update(DisplayChangeListener *dcl,
-                           DisplayState *ds,
                            int x, int y, int w, int h)
 {
     int i;
@@ -575,7 +574,6 @@ void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y)
 }
 
 static void vnc_dpy_switch(DisplayChangeListener *dcl,
-                           DisplayState *dontuse,
                            DisplaySurface *surface)
 {
     VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
@@ -740,7 +738,6 @@ static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, i
 }
 
 static void vnc_dpy_copy(DisplayChangeListener *dcl,
-                         DisplayState *dontuse,
                          int src_x, int src_y,
                          int dst_x, int dst_y, int w, int h)
 {
@@ -814,7 +811,6 @@ static void vnc_dpy_copy(DisplayChangeListener *dcl,
 }
 
 static void vnc_mouse_set(DisplayChangeListener *dcl,
-                          DisplayState *dontuse,
                           int x, int y, int visible)
 {
     /* can we ask the client(s) to move the pointer ??? */
@@ -842,7 +838,6 @@ static int vnc_cursor_define(VncState *vs)
 }
 
 static void vnc_dpy_cursor_define(DisplayChangeListener *dcl,
-                                  DisplayState *dontuse,
                                   QEMUCursor *c)
 {
     VncDisplay *vd = vnc_display;
commit 5e00d3ac475fb4c9afa17612a908e933fe142f00
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Mar 1 12:52:06 2013 +0100

    cocoa: stop using DisplayState
    
    Rework DisplayStateListener callbacks to not use the DisplayState
    any more.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/cocoa.m b/ui/cocoa.m
index 73843f4..9a56fb8 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -264,8 +264,7 @@ static int cocoa_keycode_to_qemu(int keycode)
     BOOL isAbsoluteEnabled;
     BOOL isTabletEnabled;
 }
-- (void) resizeContentToWidth:(int)w height:(int)h displayState:(DisplayState *)ds;
-- (void) updateDataOffset:(DisplayState *)ds;
+- (void) switchSurface:(DisplaySurface *)surface;
 - (void) grabMouse;
 - (void) ungrabMouse;
 - (void) toggleFullScreen:(id)sender;
@@ -400,19 +399,19 @@ QemuCocoaView *cocoaView;
     }
 }
 
-- (void) resizeContentToWidth:(int)w height:(int)h displayState:(DisplayState *)ds
+- (void) switchSurface:(DisplaySurface *)surface
 {
-    COCOA_DEBUG("QemuCocoaView: resizeContent\n");
+    COCOA_DEBUG("QemuCocoaView: switchSurface\n");
 
     // update screenBuffer
     if (dataProviderRef)
         CGDataProviderRelease(dataProviderRef);
 
     //sync host window color space with guests
-	screen.bitsPerPixel = ds_get_bits_per_pixel(ds);
-	screen.bitsPerComponent = ds_get_bytes_per_pixel(ds) * 2;
+	screen.bitsPerPixel = surface_bits_per_pixel(surface);
+	screen.bitsPerComponent = surface_bytes_per_pixel(surface) * 2;
 
-    dataProviderRef = CGDataProviderCreateWithData(NULL, ds_get_data(ds), w * 4 * h, NULL);
+    dataProviderRef = CGDataProviderCreateWithData(NULL, surface_data(surface), w * 4 * h, NULL);
 
     // update windows
     if (isFullscreen) {
@@ -430,20 +429,6 @@ QemuCocoaView *cocoaView;
     [self setFrame:NSMakeRect(cx, cy, cw, ch)];
 }
 
-- (void) updateDataOffset:(DisplayState *)ds
-{
-    COCOA_DEBUG("QemuCocoaView: UpdateDataOffset\n");
-
-    // update screenBuffer
-    if (dataProviderRef) {
-        CGDataProviderRelease(dataProviderRef);
-    }
-
-    size_t size = ds_get_width(ds) * 4 * ds_get_height(ds);
-    dataProviderRef = CGDataProviderCreateWithData(NULL, ds_get_data(ds),
-                                                   size, NULL);
-}
-
 - (void) toggleFullScreen:(id)sender
 {
     COCOA_DEBUG("QemuCocoaView: toggleFullScreen\n");
@@ -970,7 +955,7 @@ int main (int argc, const char * argv[]) {
 
 #pragma mark qemu
 static void cocoa_update(DisplayChangeListener *dcl,
-                         DisplayState *ds,
+                         DisplayState *dontuse,
                          int x, int y, int w, int h)
 {
     COCOA_DEBUG("qemu_cocoa: cocoa_update\n");
@@ -989,16 +974,16 @@ static void cocoa_update(DisplayChangeListener *dcl,
 }
 
 static void cocoa_switch(DisplayChangeListener *dcl,
-                         DisplayState *ds,
+                         DisplayState *dontuse,
                          DisplaySurface *surface)
 {
     COCOA_DEBUG("qemu_cocoa: cocoa_resize\n");
 
-    [cocoaView resizeContentToWidth:(int)(ds_get_width(ds)) height:(int)(ds_get_height(ds)) displayState:ds];
+    [cocoaView switchSurface:surface];
 }
 
 static void cocoa_refresh(DisplayChangeListener *dcl,
-                          DisplayState *ds)
+                          DisplayState *dontuse)
 {
     COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n");
 
commit 71874c1751ebb7368eaa023a35ac919d2c1c5e4c
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 28 16:42:28 2013 +0100

    spice: stop using DisplayState
    
    Rework DisplayStateListener callbacks to not use the DisplayState
    any more.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 8a19272..087679e 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -236,7 +236,7 @@ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
         return 1;
     }
 
-    if (!dpy_cursor_define_supported(qxl->ssd.ds)) {
+    if (!dpy_cursor_define_supported(qxl->ssd.dcl.ds)) {
         return 0;
     }
 
diff --git a/hw/qxl.c b/hw/qxl.c
index fbaadde..6ed61be 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1782,7 +1782,7 @@ static void qxl_hw_screen_dump(void *opaque, const char *filename, bool cswitch,
     case QXL_MODE_COMPAT:
     case QXL_MODE_NATIVE:
         qxl_render_update(qxl);
-        ppm_save(filename, qxl->ssd.ds->surface, errp);
+        ppm_save(filename, qxl->ssd.ds, errp);
         break;
     case QXL_MODE_VGA:
         vga->screen_dump(vga, filename, cswitch, errp);
@@ -1881,6 +1881,7 @@ static void display_switch(DisplayChangeListener *dcl,
 {
     PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl);
 
+    qxl->ssd.ds = surface;
     if (qxl->mode == QXL_MODE_VGA) {
         qemu_spice_display_switch(&qxl->ssd, surface);
     }
diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h
index 82f8246..a9e1e09 100644
--- a/include/ui/spice-display.h
+++ b/include/ui/spice-display.h
@@ -71,7 +71,7 @@ typedef struct SimpleSpiceDisplay SimpleSpiceDisplay;
 typedef struct SimpleSpiceUpdate SimpleSpiceUpdate;
 
 struct SimpleSpiceDisplay {
-    DisplayState *ds;
+    DisplaySurface *ds;
     DisplayChangeListener dcl;
     void *buf;
     int bufsize;
diff --git a/ui/spice-display.c b/ui/spice-display.c
index cc2a78e..5bbe23b 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -214,10 +214,10 @@ static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd,
 static void qemu_spice_create_update(SimpleSpiceDisplay *ssd)
 {
     static const int blksize = 32;
-    int blocks = (ds_get_width(ssd->ds) + blksize - 1) / blksize;
+    int blocks = (surface_width(ssd->ds) + blksize - 1) / blksize;
     int dirty_top[blocks];
     int y, yoff, x, xoff, blk, bw;
-    int bpp = ds_get_bytes_per_pixel(ssd->ds);
+    int bpp = surface_bytes_per_pixel(ssd->ds);
     uint8_t *guest, *mirror;
 
     if (qemu_spice_rect_is_empty(&ssd->dirty)) {
@@ -225,19 +225,19 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd)
     };
 
     if (ssd->surface == NULL) {
-        ssd->surface = pixman_image_ref(ds_get_image(ssd->ds));
-        ssd->mirror  = qemu_pixman_mirror_create(ds_get_format(ssd->ds),
-                                                 ds_get_image(ssd->ds));
+        ssd->surface = pixman_image_ref(ssd->ds->image);
+        ssd->mirror  = qemu_pixman_mirror_create(ssd->ds->format,
+                                                 ssd->ds->image);
     }
 
     for (blk = 0; blk < blocks; blk++) {
         dirty_top[blk] = -1;
     }
 
-    guest = ds_get_data(ssd->ds);
+    guest = surface_data(ssd->ds);
     mirror = (void *)pixman_image_get_data(ssd->mirror);
     for (y = ssd->dirty.top; y < ssd->dirty.bottom; y++) {
-        yoff = y * ds_get_linesize(ssd->ds);
+        yoff = y * surface_stride(ssd->ds);
         for (x = ssd->dirty.left; x < ssd->dirty.right; x += blksize) {
             xoff = x * bpp;
             blk = x / blksize;
@@ -312,11 +312,11 @@ void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
     memset(&surface, 0, sizeof(surface));
 
     dprint(1, "%s: %dx%d\n", __FUNCTION__,
-           ds_get_width(ssd->ds), ds_get_height(ssd->ds));
+           surface_width(ssd->ds), surface_height(ssd->ds));
 
     surface.format     = SPICE_SURFACE_FMT_32_xRGB;
-    surface.width      = ds_get_width(ssd->ds);
-    surface.height     = ds_get_height(ssd->ds);
+    surface.width      = surface_width(ssd->ds);
+    surface.height     = surface_height(ssd->ds);
     surface.stride     = -surface.width * 4;
     surface.mouse_mode = true;
     surface.flags      = 0;
@@ -336,7 +336,6 @@ void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
 
 void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds)
 {
-    ssd->ds = ds;
     qemu_mutex_init(&ssd->lock);
     QTAILQ_INIT(&ssd->updates);
     ssd->mouse_x = -1;
@@ -383,6 +382,7 @@ void qemu_spice_display_switch(SimpleSpiceDisplay *ssd,
     }
 
     qemu_mutex_lock(&ssd->lock);
+    ssd->ds = surface;
     while ((update = QTAILQ_FIRST(&ssd->updates)) != NULL) {
         QTAILQ_REMOVE(&ssd->updates, update, next);
         qemu_spice_destroy_update(ssd, update);
@@ -398,12 +398,12 @@ void qemu_spice_display_switch(SimpleSpiceDisplay *ssd,
 void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd)
 {
     if (ssd->cursor) {
-        dpy_cursor_define(ssd->ds, ssd->cursor);
+        dpy_cursor_define(ssd->dcl.ds, ssd->cursor);
         cursor_put(ssd->cursor);
         ssd->cursor = NULL;
     }
     if (ssd->mouse_x != -1 && ssd->mouse_y != -1) {
-        dpy_mouse_set(ssd->ds, ssd->mouse_x, ssd->mouse_y, 1);
+        dpy_mouse_set(ssd->dcl.ds, ssd->mouse_x, ssd->mouse_y, 1);
         ssd->mouse_x = -1;
         ssd->mouse_y = -1;
     }
@@ -415,7 +415,7 @@ void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
     vga_hw_update();
 
     qemu_mutex_lock(&ssd->lock);
-    if (QTAILQ_EMPTY(&ssd->updates)) {
+    if (QTAILQ_EMPTY(&ssd->updates) && ssd->ds) {
         qemu_spice_create_update(ssd);
         ssd->notify++;
     }
@@ -623,8 +623,9 @@ void qemu_spice_display_init(DisplayState *ds)
     assert(ssd->worker);
 
     qemu_spice_create_host_memslot(ssd);
-    qemu_spice_create_host_primary(ssd);
 
     ssd->dcl.ops = &display_listener_ops;
     register_displaychangelistener(ds, &ssd->dcl);
+
+    qemu_spice_create_host_primary(ssd);
 }
commit 8db9bae94eadcb7d5d07af1ba0c642aafafc5498
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Mar 1 09:01:13 2013 +0100

    sdl: stop using DisplayState
    
    Rework DisplayStateListener callbacks to not use the DisplayState
    any more.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/sdl.c b/ui/sdl.c
index 85eefdf..58f16bc 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -35,6 +35,7 @@
 #include "sdl_zoom.h"
 
 static DisplayChangeListener *dcl;
+static DisplaySurface *surface;
 static SDL_Surface *real_screen;
 static SDL_Surface *guest_screen = NULL;
 static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
@@ -60,7 +61,7 @@ static int scaling_active = 0;
 static Notifier mouse_mode_notifier;
 
 static void sdl_update(DisplayChangeListener *dcl,
-                       DisplayState *ds,
+                       DisplayState *dontuse,
                        int x, int y, int w, int h)
 {
     //    printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
@@ -83,17 +84,6 @@ static void sdl_update(DisplayChangeListener *dcl,
     SDL_UpdateRect(real_screen, rec.x, rec.y, rec.w, rec.h);
 }
 
-static void sdl_setdata(DisplayChangeListener *dcl,
-                        DisplayState *ds)
-{
-    if (guest_screen != NULL) SDL_FreeSurface(guest_screen);
-
-    guest_screen = SDL_CreateRGBSurfaceFrom(ds_get_data(ds), ds_get_width(ds), ds_get_height(ds),
-                                            ds_get_bits_per_pixel(ds), ds_get_linesize(ds),
-                                            ds->surface->pf.rmask, ds->surface->pf.gmask,
-                                            ds->surface->pf.bmask, ds->surface->pf.amask);
-}
-
 static void do_sdl_resize(int width, int height, int bpp)
 {
     int flags;
@@ -118,16 +108,32 @@ static void do_sdl_resize(int width, int height, int bpp)
 }
 
 static void sdl_switch(DisplayChangeListener *dcl,
-                       DisplayState *ds,
-                       DisplaySurface *surface)
+                       DisplayState *dontuse,
+                       DisplaySurface *new_surface)
 {
+
+    /* temporary hack: allows to call sdl_switch to handle scaling changes */
+    if (new_surface) {
+        surface = new_surface;
+    }
+
     if (!scaling_active) {
-        do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
-    } else if (real_screen->format->BitsPerPixel != ds_get_bits_per_pixel(ds)) {
+        do_sdl_resize(surface_width(surface), surface_height(surface), 0);
+    } else if (real_screen->format->BitsPerPixel !=
+               surface_bits_per_pixel(surface)) {
         do_sdl_resize(real_screen->w, real_screen->h,
-                      ds_get_bits_per_pixel(ds));
+                      surface_bits_per_pixel(surface));
     }
-    sdl_setdata(dcl, ds);
+
+    if (guest_screen != NULL) {
+        SDL_FreeSurface(guest_screen);
+    }
+    guest_screen = SDL_CreateRGBSurfaceFrom
+        (surface_data(surface),
+         surface_width(surface), surface_height(surface),
+         surface_bits_per_pixel(surface), surface_stride(surface),
+         surface->pf.rmask, surface->pf.gmask,
+         surface->pf.bmask, surface->pf.amask);
 }
 
 /* generic keyboard conversion */
@@ -450,7 +456,7 @@ static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state
     kbd_mouse_event(dx, dy, dz, buttons);
 }
 
-static void sdl_scale(DisplayState *ds, int width, int height)
+static void sdl_scale(int width, int height)
 {
     int bpp = real_screen->format->BitsPerPixel;
 
@@ -461,25 +467,28 @@ static void sdl_scale(DisplayState *ds, int width, int height)
     scaling_active = 1;
 }
 
-static void toggle_full_screen(DisplayState *ds)
+static void toggle_full_screen(void)
 {
+    int width = surface_width(surface);
+    int height = surface_height(surface);
+    int bpp = surface_bits_per_pixel(surface);
+
     gui_fullscreen = !gui_fullscreen;
     if (gui_fullscreen) {
         gui_saved_width = real_screen->w;
         gui_saved_height = real_screen->h;
         gui_saved_scaling = scaling_active;
 
-        do_sdl_resize(ds_get_width(ds), ds_get_height(ds),
-                      ds_get_bits_per_pixel(ds));
+        do_sdl_resize(width, height, bpp);
         scaling_active = 0;
 
         gui_saved_grab = gui_grab;
         sdl_grab_start();
     } else {
         if (gui_saved_scaling) {
-            sdl_scale(ds, gui_saved_width, gui_saved_height);
+            sdl_scale(gui_saved_width, gui_saved_height);
         } else {
-            do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
+            do_sdl_resize(width, height, 0);
         }
         if (!gui_saved_grab || !is_graphic_console()) {
             sdl_grab_end();
@@ -489,7 +498,7 @@ static void toggle_full_screen(DisplayState *ds)
     vga_hw_update();
 }
 
-static void handle_keydown(DisplayState *ds, SDL_Event *ev)
+static void handle_keydown(SDL_Event *ev)
 {
     int mod_state;
     int keycode;
@@ -508,13 +517,13 @@ static void handle_keydown(DisplayState *ds, SDL_Event *ev)
         keycode = sdl_keyevent_to_keycode(&ev->key);
         switch (keycode) {
         case 0x21: /* 'f' key on US keyboard */
-            toggle_full_screen(ds);
+            toggle_full_screen();
             gui_keysym = 1;
             break;
         case 0x16: /* 'u' key on US keyboard */
             if (scaling_active) {
                 scaling_active = 0;
-                sdl_switch(dcl, ds, ds->surface);
+                sdl_switch(dcl, NULL, NULL);
                 vga_hw_invalidate();
                 vga_hw_update();
             }
@@ -545,9 +554,10 @@ static void handle_keydown(DisplayState *ds, SDL_Event *ev)
             if (!gui_fullscreen) {
                 int width = MAX(real_screen->w + (keycode == 0x1b ? 50 : -50),
                                 160);
-                int height = (ds_get_height(ds) * width) / ds_get_width(ds);
+                int height = (surface_height(surface) * width) /
+                    surface_width(surface);
 
-                sdl_scale(ds, width, height);
+                sdl_scale(width, height);
                 vga_hw_invalidate();
                 vga_hw_update();
                 gui_keysym = 1;
@@ -634,7 +644,7 @@ static void handle_keydown(DisplayState *ds, SDL_Event *ev)
     }
 }
 
-static void handle_keyup(DisplayState *ds, SDL_Event *ev)
+static void handle_keyup(SDL_Event *ev)
 {
     int mod_state;
 
@@ -666,7 +676,7 @@ static void handle_keyup(DisplayState *ds, SDL_Event *ev)
     }
 }
 
-static void handle_mousemotion(DisplayState *ds, SDL_Event *ev)
+static void handle_mousemotion(SDL_Event *ev)
 {
     int max_x, max_y;
 
@@ -690,7 +700,7 @@ static void handle_mousemotion(DisplayState *ds, SDL_Event *ev)
     }
 }
 
-static void handle_mousebutton(DisplayState *ds, SDL_Event *ev)
+static void handle_mousebutton(SDL_Event *ev)
 {
     int buttonstate = SDL_GetMouseState(NULL, NULL);
     SDL_MouseButtonEvent *bev;
@@ -726,7 +736,7 @@ static void handle_mousebutton(DisplayState *ds, SDL_Event *ev)
     }
 }
 
-static void handle_activation(DisplayState *ds, SDL_Event *ev)
+static void handle_activation(SDL_Event *ev)
 {
 #ifdef _WIN32
     /* Disable grab if the window no longer has the focus
@@ -754,7 +764,7 @@ static void handle_activation(DisplayState *ds, SDL_Event *ev)
 }
 
 static void sdl_refresh(DisplayChangeListener *dcl,
-                        DisplayState *ds)
+                        DisplayState *dontuse)
 {
     SDL_Event ev1, *ev = &ev1;
 
@@ -769,13 +779,13 @@ static void sdl_refresh(DisplayChangeListener *dcl,
     while (SDL_PollEvent(ev)) {
         switch (ev->type) {
         case SDL_VIDEOEXPOSE:
-            sdl_update(dcl, ds, 0, 0, real_screen->w, real_screen->h);
+            sdl_update(dcl, dontuse, 0, 0, real_screen->w, real_screen->h);
             break;
         case SDL_KEYDOWN:
-            handle_keydown(ds, ev);
+            handle_keydown(ev);
             break;
         case SDL_KEYUP:
-            handle_keyup(ds, ev);
+            handle_keyup(ev);
             break;
         case SDL_QUIT:
             if (!no_quit) {
@@ -784,17 +794,17 @@ static void sdl_refresh(DisplayChangeListener *dcl,
             }
             break;
         case SDL_MOUSEMOTION:
-            handle_mousemotion(ds, ev);
+            handle_mousemotion(ev);
             break;
         case SDL_MOUSEBUTTONDOWN:
         case SDL_MOUSEBUTTONUP:
-            handle_mousebutton(ds, ev);
+            handle_mousebutton(ev);
             break;
         case SDL_ACTIVEEVENT:
-            handle_activation(ds, ev);
+            handle_activation(ev);
             break;
         case SDL_VIDEORESIZE:
-            sdl_scale(ds, ev->resize.w, ev->resize.h);
+            sdl_scale(ev->resize.w, ev->resize.h);
             vga_hw_invalidate();
             vga_hw_update();
             break;
commit d39fa6d86d07646e3481e5c3e45a984bff590642
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 28 17:16:48 2013 +0100

    vnc: stop using DisplayState
    
    Rework DisplayStateListener callbacks to not use the DisplayState
    any more.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index 4ddea7d..e6966ae 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -123,7 +123,7 @@ static bool tight_can_send_png_rect(VncState *vs, int w, int h)
         return false;
     }
 
-    if (ds_get_bytes_per_pixel(vs->ds) == 1 ||
+    if (surface_bytes_per_pixel(vs->vd->ds) == 1 ||
         vs->client_pf.bytes_per_pixel == 1) {
         return false;
     }
@@ -301,7 +301,7 @@ tight_detect_smooth_image(VncState *vs, int w, int h)
         return 0;
     }
 
-    if (ds_get_bytes_per_pixel(vs->ds) == 1 ||
+    if (surface_bytes_per_pixel(vs->vd->ds) == 1 ||
         vs->client_pf.bytes_per_pixel == 1 ||
         w < VNC_TIGHT_DETECT_MIN_WIDTH || h < VNC_TIGHT_DETECT_MIN_HEIGHT) {
         return 0;
@@ -1184,8 +1184,9 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality)
     uint8_t *buf;
     int dy;
 
-    if (ds_get_bytes_per_pixel(vs->ds) == 1)
+    if (surface_bytes_per_pixel(vs->vd->ds) == 1) {
         return send_full_color_rect(vs, x, y, w, h);
+    }
 
     buffer_reserve(&vs->tight.jpeg, 2048);
 
diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c
index 0bfc0c5..2d3fce8 100644
--- a/ui/vnc-jobs.c
+++ b/ui/vnc-jobs.c
@@ -183,7 +183,6 @@ static void vnc_async_encoding_start(VncState *orig, VncState *local)
 {
     local->vnc_encoding = orig->vnc_encoding;
     local->features = orig->features;
-    local->ds = orig->ds;
     local->vd = orig->vd;
     local->lossy_rect = orig->lossy_rect;
     local->write_pixels = orig->write_pixels;
diff --git a/ui/vnc.c b/ui/vnc.c
index f8398c3..f38aeda 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -436,8 +436,8 @@ static void vnc_dpy_update(DisplayChangeListener *dcl,
     int i;
     VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
     struct VncSurface *s = &vd->guest;
-    int width = ds_get_width(ds);
-    int height = ds_get_height(ds);
+    int width = surface_width(vd->ds);
+    int height = surface_height(vd->ds);
 
     h += y;
 
@@ -519,17 +519,17 @@ void buffer_advance(Buffer *buf, size_t len)
 
 static void vnc_desktop_resize(VncState *vs)
 {
-    DisplayState *ds = vs->ds;
+    DisplaySurface *ds = vs->vd->ds;
 
     if (vs->csock == -1 || !vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
         return;
     }
-    if (vs->client_width == ds_get_width(ds) &&
-        vs->client_height == ds_get_height(ds)) {
+    if (vs->client_width == surface_width(ds) &&
+        vs->client_height == surface_height(ds)) {
         return;
     }
-    vs->client_width = ds_get_width(ds);
-    vs->client_height = ds_get_height(ds);
+    vs->client_width = surface_width(ds);
+    vs->client_height = surface_height(ds);
     vnc_lock_output(vs);
     vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
     vnc_write_u8(vs, 0);
@@ -575,7 +575,7 @@ void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y)
 }
 
 static void vnc_dpy_switch(DisplayChangeListener *dcl,
-                           DisplayState *ds,
+                           DisplayState *dontuse,
                            DisplaySurface *surface)
 {
     VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
@@ -585,9 +585,10 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl,
 
     /* server surface */
     qemu_pixman_image_unref(vd->server);
+    vd->ds = surface;
     vd->server = pixman_image_create_bits(VNC_SERVER_FB_FORMAT,
-                                          ds_get_width(ds),
-                                          ds_get_height(ds),
+                                          surface_width(vd->ds),
+                                          surface_height(vd->ds),
                                           NULL, 0);
 
     /* guest surface */
@@ -596,8 +597,8 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl,
         console_color_init(ds);
 #endif
     qemu_pixman_image_unref(vd->guest.fb);
-    vd->guest.fb = pixman_image_ref(ds->surface->image);
-    vd->guest.format = ds->surface->format;
+    vd->guest.fb = pixman_image_ref(surface->image);
+    vd->guest.format = surface->format;
     memset(vd->guest.dirty, 0xFF, sizeof(vd->guest.dirty));
 
     QTAILQ_FOREACH(vs, &vd->clients, next) {
@@ -739,7 +740,7 @@ static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, i
 }
 
 static void vnc_dpy_copy(DisplayChangeListener *dcl,
-                         DisplayState *ds,
+                         DisplayState *dontuse,
                          int src_x, int src_y,
                          int dst_x, int dst_y, int w, int h)
 {
@@ -813,7 +814,7 @@ static void vnc_dpy_copy(DisplayChangeListener *dcl,
 }
 
 static void vnc_mouse_set(DisplayChangeListener *dcl,
-                          DisplayState *ds,
+                          DisplayState *dontuse,
                           int x, int y, int visible)
 {
     /* can we ask the client(s) to move the pointer ??? */
@@ -841,7 +842,7 @@ static int vnc_cursor_define(VncState *vs)
 }
 
 static void vnc_dpy_cursor_define(DisplayChangeListener *dcl,
-                                  DisplayState *ds,
+                                  DisplayState *dontuse,
                                   QEMUCursor *c)
 {
     VncDisplay *vd = vnc_display;
@@ -1463,7 +1464,8 @@ static void check_pointer_type_change(Notifier *notifier, void *data)
         vnc_write_u8(vs, 0);
         vnc_write_u16(vs, 1);
         vnc_framebuffer_update(vs, absolute, 0,
-                               ds_get_width(vs->ds), ds_get_height(vs->ds),
+                               surface_width(vs->vd->ds),
+                               surface_height(vs->vd->ds),
                                VNC_ENCODING_POINTER_TYPE_CHANGE);
         vnc_unlock_output(vs);
         vnc_flush(vs);
@@ -1475,6 +1477,8 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y)
 {
     int buttons = 0;
     int dz = 0;
+    int width = surface_width(vs->vd->ds);
+    int height = surface_height(vs->vd->ds);
 
     if (button_mask & 0x01)
         buttons |= MOUSE_EVENT_LBUTTON;
@@ -1488,10 +1492,8 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y)
         dz = 1;
 
     if (vs->absolute) {
-        kbd_mouse_event(ds_get_width(vs->ds) > 1 ?
-                          x * 0x7FFF / (ds_get_width(vs->ds) - 1) : 0x4000,
-                        ds_get_height(vs->ds) > 1 ?
-                          y * 0x7FFF / (ds_get_height(vs->ds) - 1) : 0x4000,
+        kbd_mouse_event(width  > 1 ? x * 0x7FFF / (width  - 1) : 0x4000,
+                        height > 1 ? y * 0x7FFF / (height - 1) : 0x4000,
                         dz, buttons);
     } else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) {
         x -= 0x7FFF;
@@ -1781,12 +1783,15 @@ static void framebuffer_update_request(VncState *vs, int incremental,
                                        int w, int h)
 {
     int i;
-    const size_t width = ds_get_width(vs->ds) / 16;
+    const size_t width = surface_width(vs->vd->ds) / 16;
+    const size_t height = surface_height(vs->vd->ds);
 
-    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;
+    if (y_position > height) {
+        y_position = height;
+    }
+    if (y_position + h >= height) {
+        h = height - y_position;
+    }
 
     vs->need_update = 1;
     if (!incremental) {
@@ -1805,7 +1810,9 @@ static void send_ext_key_event_ack(VncState *vs)
     vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
     vnc_write_u8(vs, 0);
     vnc_write_u16(vs, 1);
-    vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds),
+    vnc_framebuffer_update(vs, 0, 0,
+                           surface_width(vs->vd->ds),
+                           surface_height(vs->vd->ds),
                            VNC_ENCODING_EXT_KEY_EVENT);
     vnc_unlock_output(vs);
     vnc_flush(vs);
@@ -1817,7 +1824,9 @@ static void send_ext_audio_ack(VncState *vs)
     vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
     vnc_write_u8(vs, 0);
     vnc_write_u16(vs, 1);
-    vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds),
+    vnc_framebuffer_update(vs, 0, 0,
+                           surface_width(vs->vd->ds),
+                           surface_height(vs->vd->ds),
                            VNC_ENCODING_AUDIO);
     vnc_unlock_output(vs);
     vnc_flush(vs);
@@ -1990,8 +1999,10 @@ static void vnc_colordepth(VncState *vs)
         vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
         vnc_write_u8(vs, 0);
         vnc_write_u16(vs, 1); /* number of rects */
-        vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), 
-                               ds_get_height(vs->ds), VNC_ENCODING_WMVi);
+        vnc_framebuffer_update(vs, 0, 0,
+                               surface_width(vs->vd->ds),
+                               surface_height(vs->vd->ds),
+                               VNC_ENCODING_WMVi);
         pixel_format_message(vs);
         vnc_unlock_output(vs);
         vnc_flush(vs);
@@ -2207,8 +2218,8 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
     }
     vnc_set_share_mode(vs, mode);
 
-    vs->client_width = ds_get_width(vs->ds);
-    vs->client_height = ds_get_height(vs->ds);
+    vs->client_width = surface_width(vs->vd->ds);
+    vs->client_height = surface_height(vs->vd->ds);
     vnc_write_u16(vs, vs->client_width);
     vnc_write_u16(vs, vs->client_height);
 
@@ -2686,7 +2697,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_ms(rt_clock, vnc_refresh, vd);
-        vnc_dpy_switch(&vd->dcl, vd->ds, vd->ds->surface);
+        vga_hw_update();
         vnc_refresh(vd);
     }
 }
@@ -2756,7 +2767,6 @@ void vnc_init_state(VncState *vs)
     vs->initialized = true;
     VncDisplay *vd = vs->vd;
 
-    vs->ds = vd->ds;
     vs->last_x = -1;
     vs->last_y = -1;
 
@@ -2843,7 +2853,6 @@ void vnc_display_init(DisplayState *ds)
     vs->lwebsock = -1;
 #endif
 
-    vs->ds = ds;
     QTAILQ_INIT(&vs->clients);
     vs->expires = TIME_MAX;
 
diff --git a/ui/vnc.h b/ui/vnc.h
index a96485b..58e002e 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -150,7 +150,7 @@ struct VncDisplay
     bool websocket;
     char *ws_display;
 #endif
-    DisplayState *ds;
+    DisplaySurface *ds;
     DisplayChangeListener dcl;
     kbd_layout_t *kbd_layout;
     int lock_key_sync;
@@ -248,7 +248,6 @@ struct VncState
 {
     int csock;
 
-    DisplayState *ds;
     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 9d9801cf803cdceaa4845fe27150b24d5ab083e6
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 28 16:10:02 2013 +0100

    gtk: stop using DisplayState
    
    Rework DisplayStateListener callbacks to not use the DisplayState
    any more.  Factor out the window size handling to a separate function,
    so the zoom callbacks can call that directly instead of abusing the
    gd_switch DisplayStateListener callback for that.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/gtk.c b/ui/gtk.c
index 967a36c..d553550 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -143,7 +143,7 @@ typedef struct GtkDisplayState
     GtkWidget *drawing_area;
     cairo_surface_t *surface;
     DisplayChangeListener dcl;
-    DisplayState *ds;
+    DisplaySurface *ds;
     int button_mask;
     int last_x;
     int last_y;
@@ -225,10 +225,48 @@ static void gd_update_caption(GtkDisplayState *s)
     g_free(title);
 }
 
+static void gd_update_windowsize(GtkDisplayState *s)
+{
+    if (!s->full_screen) {
+        GtkRequisition req;
+        double sx, sy;
+
+        if (s->free_scale) {
+            sx = s->scale_x;
+            sy = s->scale_y;
+
+            s->scale_y = 1.0;
+            s->scale_x = 1.0;
+        } else {
+            sx = 1.0;
+            sy = 1.0;
+        }
+
+        gtk_widget_set_size_request(s->drawing_area,
+                                    surface_width(s->ds) * s->scale_x,
+                                    surface_height(s->ds) * s->scale_y);
+#if GTK_CHECK_VERSION(3, 0, 0)
+        gtk_widget_get_preferred_size(s->vbox, NULL, &req);
+#else
+        gtk_widget_size_request(s->vbox, &req);
+#endif
+
+        gtk_window_resize(GTK_WINDOW(s->window),
+                          req.width * sx, req.height * sy);
+    }
+}
+
+static void gd_update_full_redraw(GtkDisplayState *s)
+{
+    int ww, wh;
+    gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
+    gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh);
+}
+
 /** DisplayState Callbacks **/
 
 static void gd_update(DisplayChangeListener *dcl,
-                      DisplayState *ds, int x, int y, int w, int h)
+                      DisplayState *dontuse, int x, int y, int w, int h)
 {
     GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
     int x1, x2, y1, y2;
@@ -244,8 +282,8 @@ static void gd_update(DisplayChangeListener *dcl,
     x2 = ceil(x * s->scale_x + w * s->scale_x);
     y2 = ceil(y * s->scale_y + h * s->scale_y);
 
-    fbw = ds_get_width(s->ds) * s->scale_x;
-    fbh = ds_get_height(s->ds) * s->scale_y;
+    fbw = surface_width(s->ds) * s->scale_x;
+    fbh = surface_height(s->ds) * s->scale_y;
 
     gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
 
@@ -261,27 +299,34 @@ static void gd_update(DisplayChangeListener *dcl,
 }
 
 static void gd_refresh(DisplayChangeListener *dcl,
-                       DisplayState *ds)
+                       DisplayState *dontuse)
 {
     vga_hw_update();
 }
 
 static void gd_switch(DisplayChangeListener *dcl,
-                      DisplayState *ds,
+                      DisplayState *dontuse,
                       DisplaySurface *surface)
 {
     GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
     cairo_format_t kind;
+    bool resized = true;
     int stride;
 
     DPRINTF("resize(width=%d, height=%d)\n",
-            ds_get_width(ds), ds_get_height(ds));
+            surface_width(surface), surface_height(surface));
 
     if (s->surface) {
         cairo_surface_destroy(s->surface);
     }
 
-    switch (ds->surface->pf.bits_per_pixel) {
+    if (s->ds &&
+        surface_width(s->ds) == surface_width(surface) &&
+        surface_height(s->ds) == surface_height(surface)) {
+        resized = false;
+    }
+    s->ds = surface;
+    switch (surface_bits_per_pixel(surface)) {
     case 8:
         kind = CAIRO_FORMAT_A8;
         break;
@@ -296,41 +341,19 @@ static void gd_switch(DisplayChangeListener *dcl,
         break;
     }
 
-    stride = cairo_format_stride_for_width(kind, ds_get_width(ds));
-    g_assert(ds_get_linesize(ds) == stride);
+    stride = cairo_format_stride_for_width(kind, surface_width(surface));
+    g_assert(surface_stride(surface) == stride);
 
-    s->surface = cairo_image_surface_create_for_data(ds_get_data(ds),
+    s->surface = cairo_image_surface_create_for_data(surface_data(surface),
                                                      kind,
-                                                     ds_get_width(ds),
-                                                     ds_get_height(ds),
-                                                     ds_get_linesize(ds));
-
-    if (!s->full_screen) {
-        GtkRequisition req;
-        double sx, sy;
-
-        if (s->free_scale) {
-            sx = s->scale_x;
-            sy = s->scale_y;
-
-            s->scale_y = 1.0;
-            s->scale_x = 1.0;
-        } else {
-            sx = 1.0;
-            sy = 1.0;
-        }
-
-        gtk_widget_set_size_request(s->drawing_area,
-                                    ds_get_width(ds) * s->scale_x,
-                                    ds_get_height(ds) * s->scale_y);
-#if GTK_CHECK_VERSION(3, 0, 0)
-        gtk_widget_get_preferred_size(s->vbox, NULL, &req);
-#else
-        gtk_widget_size_request(s->vbox, &req);
-#endif
+                                                     surface_width(surface),
+                                                     surface_height(surface),
+                                                     surface_stride(surface));
 
-        gtk_window_resize(GTK_WINDOW(s->window),
-                          req.width * sx, req.height * sy);
+    if (resized) {
+        gd_update_windowsize(s);
+    } else {
+        gd_update_full_redraw(s);
     }
 }
 
@@ -405,8 +428,8 @@ static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque)
         return FALSE;
     }
 
-    fbw = ds_get_width(s->ds);
-    fbh = ds_get_height(s->ds);
+    fbw = surface_width(s->ds);
+    fbh = surface_height(s->ds);
 
     gdk_drawable_get_size(gtk_widget_get_window(widget), &ww, &wh);
 
@@ -484,8 +507,8 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
     int fbh, fbw;
     int ww, wh;
 
-    fbw = ds_get_width(s->ds) * s->scale_x;
-    fbh = ds_get_height(s->ds) * s->scale_y;
+    fbw = surface_width(s->ds) * s->scale_x;
+    fbh = surface_height(s->ds) * s->scale_y;
 
     gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
 
@@ -501,14 +524,14 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
     y = (motion->y - my) / s->scale_y;
 
     if (x < 0 || y < 0 ||
-        x >= ds_get_width(s->ds) ||
-        y >= ds_get_height(s->ds)) {
+        x >= surface_width(s->ds) ||
+        y >= surface_height(s->ds)) {
         return TRUE;
     }
 
     if (kbd_mouse_is_absolute()) {
-        dx = x * 0x7FFF / (ds_get_width(s->ds) - 1);
-        dy = y * 0x7FFF / (ds_get_height(s->ds) - 1);
+        dx = x * 0x7FFF / (surface_width(s->ds) - 1);
+        dy = y * 0x7FFF / (surface_height(s->ds) - 1);
     } else if (s->last_x == -1 || s->last_y == -1) {
         dx = 0;
         dy = 0;
@@ -589,8 +612,8 @@ static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button,
     }
 
     if (kbd_mouse_is_absolute()) {
-        dx = s->last_x * 0x7FFF / (ds_get_width(s->ds) - 1);
-        dy = s->last_y * 0x7FFF / (ds_get_height(s->ds) - 1);
+        dx = s->last_x * 0x7FFF / (surface_width(s->ds) - 1);
+        dy = s->last_y * 0x7FFF / (surface_height(s->ds) - 1);
     } else {
         dx = 0;
         dy = 0;
@@ -719,7 +742,8 @@ static void gd_menu_full_screen(GtkMenuItem *item, void *opaque)
         gd_menu_show_tabs(GTK_MENU_ITEM(s->show_tabs_item), s);
         gtk_widget_set_size_request(s->menu_bar, -1, -1);
         gtk_widget_set_size_request(s->drawing_area,
-                                    ds_get_width(s->ds), ds_get_height(s->ds));
+                                    surface_width(s->ds),
+                                    surface_height(s->ds));
         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), FALSE);
         s->full_screen = FALSE;
         s->scale_x = 1.0;
@@ -739,7 +763,7 @@ static void gd_menu_zoom_in(GtkMenuItem *item, void *opaque)
     s->scale_x += .25;
     s->scale_y += .25;
 
-    gd_switch(&s->dcl, s->ds, s->ds->surface);
+    gd_update_windowsize(s);
 }
 
 static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque)
@@ -755,7 +779,7 @@ static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque)
     s->scale_x = MAX(s->scale_x, .25);
     s->scale_y = MAX(s->scale_y, .25);
 
-    gd_switch(&s->dcl, s->ds, s->ds->surface);
+    gd_update_windowsize(s);
 }
 
 static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque)
@@ -765,13 +789,12 @@ static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque)
     s->scale_x = 1.0;
     s->scale_y = 1.0;
 
-    gd_switch(&s->dcl, s->ds, s->ds->surface);
+    gd_update_windowsize(s);
 }
 
 static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque)
 {
     GtkDisplayState *s = opaque;
-    int ww, wh;
 
     if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->zoom_fit_item))) {
         s->free_scale = TRUE;
@@ -779,10 +802,8 @@ static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque)
         s->free_scale = FALSE;
     }
 
-    gd_switch(&s->dcl, s->ds, s->ds->surface);
-
-    gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
-    gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh);
+    gd_update_windowsize(s);
+    gd_update_full_redraw(s);
 }
 
 static void gd_grab_keyboard(GtkDisplayState *s)
@@ -1298,7 +1319,6 @@ void gtk_display_init(DisplayState *ds)
 
     gtk_init(NULL, NULL);
 
-    s->ds = ds;
     s->dcl.ops = &dcl_ops;
 
     s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
commit 626e3b34e30bc62d4f25f7aa4e23a346eba1a2c0
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 28 15:24:14 2013 +0100

    console: add surface_*() getters
    
    Add convinence wrappers to query DisplaySurface properties.
    Simliar to ds_get_*, but operating in the DisplaySurface
    not the DisplayState.
    
    With this patch in place ui frontents can stop using DisplayState
    in the rendering code paths, they can simply operate using the
    DisplaySurface passed in via dpy_gfx_switch callback.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/include/ui/console.h b/include/ui/console.h
index c8f0050..a35b71a 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -244,36 +244,66 @@ void dpy_mouse_set(struct DisplayState *s, int x, int y, int on);
 void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor);
 bool dpy_cursor_define_supported(struct DisplayState *s);
 
+static inline int surface_stride(DisplaySurface *s)
+{
+    return pixman_image_get_stride(s->image);
+}
+
+static inline void *surface_data(DisplaySurface *s)
+{
+    return pixman_image_get_data(s->image);
+}
+
+static inline int surface_width(DisplaySurface *s)
+{
+    return pixman_image_get_width(s->image);
+}
+
+static inline int surface_height(DisplaySurface *s)
+{
+    return pixman_image_get_height(s->image);
+}
+
+static inline int surface_bits_per_pixel(DisplaySurface *s)
+{
+    int bits = PIXMAN_FORMAT_BPP(s->format);
+    return bits;
+}
+
+static inline int surface_bytes_per_pixel(DisplaySurface *s)
+{
+    int bits = PIXMAN_FORMAT_BPP(s->format);
+    return (bits + 7) / 8;
+}
+
 static inline int ds_get_linesize(DisplayState *ds)
 {
-    return pixman_image_get_stride(ds->surface->image);
+    return surface_stride(ds->surface);
 }
 
 static inline uint8_t* ds_get_data(DisplayState *ds)
 {
-    return (void *)pixman_image_get_data(ds->surface->image);
+    return surface_data(ds->surface);
 }
 
 static inline int ds_get_width(DisplayState *ds)
 {
-    return pixman_image_get_width(ds->surface->image);
+    return surface_width(ds->surface);
 }
 
 static inline int ds_get_height(DisplayState *ds)
 {
-    return pixman_image_get_height(ds->surface->image);
+    return surface_height(ds->surface);
 }
 
 static inline int ds_get_bits_per_pixel(DisplayState *ds)
 {
-    int bits = PIXMAN_FORMAT_BPP(ds->surface->format);
-    return bits;
+    return surface_bits_per_pixel(ds->surface);
 }
 
 static inline int ds_get_bytes_per_pixel(DisplayState *ds)
 {
-    int bits = PIXMAN_FORMAT_BPP(ds->surface->format);
-    return (bits + 7) / 8;
+    return surface_bytes_per_pixel(ds->surface);
 }
 
 static inline pixman_format_code_t ds_get_format(DisplayState *ds)
commit c12aeb860c63ba83190f962e2f0a1c5fe18ad3a6
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 28 15:03:04 2013 +0100

    console: rework DisplaySurface handling [dcl/ui side]
    
    Replace the dpy_gfx_resize and dpy_gfx_setdata DisplayChangeListener
    callbacks with a dpy_gfx_switch callback which notifies the ui code
    when the framebuffer backing storage changes.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index 5d830f0..fbaadde 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1875,13 +1875,14 @@ static void display_update(DisplayChangeListener *dcl,
     }
 }
 
-static void display_resize(DisplayChangeListener *dcl,
-                           struct DisplayState *ds)
+static void display_switch(DisplayChangeListener *dcl,
+                           struct DisplayState *ds,
+                           struct DisplaySurface *surface)
 {
     PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl);
 
     if (qxl->mode == QXL_MODE_VGA) {
-        qemu_spice_display_resize(&qxl->ssd);
+        qemu_spice_display_switch(&qxl->ssd, surface);
     }
 }
 
@@ -1902,7 +1903,7 @@ static void display_refresh(DisplayChangeListener *dcl,
 static DisplayChangeListenerOps display_listener_ops = {
     .dpy_name        = "spice/qxl",
     .dpy_gfx_update  = display_update,
-    .dpy_gfx_resize  = display_resize,
+    .dpy_gfx_switch  = display_switch,
     .dpy_refresh     = display_refresh,
 };
 
diff --git a/include/ui/console.h b/include/ui/console.h
index 63e6e66..c8f0050 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -156,10 +156,9 @@ typedef struct DisplayChangeListenerOps {
     void (*dpy_gfx_update)(DisplayChangeListener *dcl,
                            struct DisplayState *s,
                            int x, int y, int w, int h);
-    void (*dpy_gfx_resize)(DisplayChangeListener *dcl,
-                           struct DisplayState *s);
-    void (*dpy_gfx_setdata)(DisplayChangeListener *dcl,
-                            struct DisplayState *s);
+    void (*dpy_gfx_switch)(DisplayChangeListener *dcl,
+                           struct DisplayState *s,
+                           struct DisplaySurface *new_surface);
     void (*dpy_gfx_copy)(DisplayChangeListener *dcl,
                          struct DisplayState *s, int src_x, int src_y,
                          int dst_x, int dst_y, int w, int h);
diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h
index f2752aa..82f8246 100644
--- a/include/ui/spice-display.h
+++ b/include/ui/spice-display.h
@@ -117,7 +117,8 @@ void qemu_spice_display_init_common(SimpleSpiceDisplay *ssd, DisplayState *ds);
 
 void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
                                int x, int y, int w, int h);
-void qemu_spice_display_resize(SimpleSpiceDisplay *ssd);
+void qemu_spice_display_switch(SimpleSpiceDisplay *ssd,
+                               DisplaySurface *surface);
 void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd);
 void qemu_spice_cursor_refresh_unlocked(SimpleSpiceDisplay *ssd);
 
diff --git a/ui/cocoa.m b/ui/cocoa.m
index b1fb30e..73843f4 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -988,8 +988,9 @@ static void cocoa_update(DisplayChangeListener *dcl,
     [cocoaView setNeedsDisplayInRect:rect];
 }
 
-static void cocoa_resize(DisplayChangeListener *dcl,
-                         DisplayState *ds)
+static void cocoa_switch(DisplayChangeListener *dcl,
+                         DisplayState *ds,
+                         DisplaySurface *surface)
 {
     COCOA_DEBUG("qemu_cocoa: cocoa_resize\n");
 
@@ -1023,11 +1024,6 @@ static void cocoa_refresh(DisplayChangeListener *dcl,
     vga_hw_update();
 }
 
-static void cocoa_setdata(DisplayState *ds)
-{
-    [cocoaView updateDataOffset:ds];
-}
-
 static void cocoa_cleanup(void)
 {
     COCOA_DEBUG("qemu_cocoa: cocoa_cleanup\n");
@@ -1037,8 +1033,7 @@ static void cocoa_cleanup(void)
 static const DisplayChangeListenerOps dcl_ops = {
     .dpy_name          = "cocoa",
     .dpy_gfx_update = cocoa_update;
-    .dpy_gfx_resize = cocoa_resize;
-    .dpy_gfx_setdata = cocoa_setdata;
+    .dpy_gfx_switch = cocoa_switch;
     .dpy_refresh = cocoa_refresh;
 };
 
diff --git a/ui/console.c b/ui/console.c
index c2ca9e7..4541b2c 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1372,8 +1372,8 @@ void register_displaychangelistener(DisplayState *ds,
     dcl->ds = ds;
     QLIST_INSERT_HEAD(&ds->listeners, dcl, next);
     gui_setup_refresh(ds);
-    if (dcl->ops->dpy_gfx_resize) {
-        dcl->ops->dpy_gfx_resize(dcl, ds);
+    if (dcl->ops->dpy_gfx_switch) {
+        dcl->ops->dpy_gfx_switch(dcl, ds, ds->surface);
     }
 }
 
@@ -1413,8 +1413,8 @@ void dpy_gfx_replace_surface(DisplayState *s,
 
     s->surface = surface;
     QLIST_FOREACH(dcl, &s->listeners, next) {
-        if (dcl->ops->dpy_gfx_resize) {
-            dcl->ops->dpy_gfx_resize(dcl, s);
+        if (dcl->ops->dpy_gfx_switch) {
+            dcl->ops->dpy_gfx_switch(dcl, s, surface);
         }
     }
     qemu_free_displaysurface(old_surface);
diff --git a/ui/gtk.c b/ui/gtk.c
index b21a94a..967a36c 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -266,8 +266,9 @@ static void gd_refresh(DisplayChangeListener *dcl,
     vga_hw_update();
 }
 
-static void gd_resize(DisplayChangeListener *dcl,
-                      DisplayState *ds)
+static void gd_switch(DisplayChangeListener *dcl,
+                      DisplayState *ds,
+                      DisplaySurface *surface)
 {
     GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
     cairo_format_t kind;
@@ -738,7 +739,7 @@ static void gd_menu_zoom_in(GtkMenuItem *item, void *opaque)
     s->scale_x += .25;
     s->scale_y += .25;
 
-    gd_resize(&s->dcl, s->ds);
+    gd_switch(&s->dcl, s->ds, s->ds->surface);
 }
 
 static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque)
@@ -754,7 +755,7 @@ static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque)
     s->scale_x = MAX(s->scale_x, .25);
     s->scale_y = MAX(s->scale_y, .25);
 
-    gd_resize(&s->dcl, s->ds);
+    gd_switch(&s->dcl, s->ds, s->ds->surface);
 }
 
 static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque)
@@ -764,7 +765,7 @@ static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque)
     s->scale_x = 1.0;
     s->scale_y = 1.0;
 
-    gd_resize(&s->dcl, s->ds);
+    gd_switch(&s->dcl, s->ds, s->ds->surface);
 }
 
 static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque)
@@ -778,7 +779,7 @@ static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque)
         s->free_scale = FALSE;
     }
 
-    gd_resize(&s->dcl, s->ds);
+    gd_switch(&s->dcl, s->ds, s->ds->surface);
 
     gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
     gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh);
@@ -1287,7 +1288,7 @@ static void gd_create_menus(GtkDisplayState *s)
 static const DisplayChangeListenerOps dcl_ops = {
     .dpy_name          = "gtk",
     .dpy_gfx_update    = gd_update,
-    .dpy_gfx_resize    = gd_resize,
+    .dpy_gfx_switch    = gd_switch,
     .dpy_refresh       = gd_refresh,
 };
 
diff --git a/ui/sdl.c b/ui/sdl.c
index fc4dc1b..85eefdf 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -117,8 +117,9 @@ static void do_sdl_resize(int width, int height, int bpp)
     }
 }
 
-static void sdl_resize(DisplayChangeListener *dcl,
-                       DisplayState *ds)
+static void sdl_switch(DisplayChangeListener *dcl,
+                       DisplayState *ds,
+                       DisplaySurface *surface)
 {
     if (!scaling_active) {
         do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
@@ -513,7 +514,7 @@ static void handle_keydown(DisplayState *ds, SDL_Event *ev)
         case 0x16: /* 'u' key on US keyboard */
             if (scaling_active) {
                 scaling_active = 0;
-                sdl_resize(dcl, ds);
+                sdl_switch(dcl, ds, ds->surface);
                 vga_hw_invalidate();
                 vga_hw_update();
             }
@@ -856,9 +857,8 @@ static void sdl_cleanup(void)
 static const DisplayChangeListenerOps dcl_ops = {
     .dpy_name          = "sdl",
     .dpy_gfx_update    = sdl_update,
-    .dpy_gfx_resize    = sdl_resize,
+    .dpy_gfx_switch    = sdl_switch,
     .dpy_refresh       = sdl_refresh,
-    .dpy_gfx_setdata   = sdl_setdata,
     .dpy_mouse_set     = sdl_mouse_warp,
     .dpy_cursor_define = sdl_mouse_define,
 };
diff --git a/ui/spice-display.c b/ui/spice-display.c
index b2bda23..cc2a78e 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -367,7 +367,8 @@ void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
     qemu_spice_rect_union(&ssd->dirty, &update_area);
 }
 
-void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
+void qemu_spice_display_switch(SimpleSpiceDisplay *ssd,
+                               DisplaySurface *surface)
 {
     SimpleSpiceUpdate *update;
 
@@ -589,11 +590,12 @@ static void display_update(DisplayChangeListener *dcl,
     qemu_spice_display_update(ssd, x, y, w, h);
 }
 
-static void display_resize(DisplayChangeListener *dcl,
-                           struct DisplayState *ds)
+static void display_switch(DisplayChangeListener *dcl,
+                           struct DisplayState *ds,
+                           struct DisplaySurface *surface)
 {
     SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
-    qemu_spice_display_resize(ssd);
+    qemu_spice_display_switch(ssd, surface);
 }
 
 static void display_refresh(DisplayChangeListener *dcl,
@@ -606,7 +608,7 @@ static void display_refresh(DisplayChangeListener *dcl,
 static const DisplayChangeListenerOps display_listener_ops = {
     .dpy_name        = "spice",
     .dpy_gfx_update  = display_update,
-    .dpy_gfx_resize  = display_resize,
+    .dpy_gfx_switch  = display_switch,
     .dpy_refresh     = display_refresh,
 };
 
diff --git a/ui/vnc.c b/ui/vnc.c
index a6111d6..f8398c3 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -574,8 +574,9 @@ void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y)
     return ptr;
 }
 
-static void vnc_dpy_resize(DisplayChangeListener *dcl,
-                           DisplayState *ds)
+static void vnc_dpy_switch(DisplayChangeListener *dcl,
+                           DisplayState *ds,
+                           DisplaySurface *surface)
 {
     VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
     VncState *vs;
@@ -1981,17 +1982,6 @@ static void pixel_format_message (VncState *vs) {
     vs->write_pixels = vnc_write_pixels_copy;
 }
 
-static void vnc_dpy_setdata(DisplayChangeListener *dcl,
-                            DisplayState *ds)
-{
-    VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
-
-    qemu_pixman_image_unref(vd->guest.fb);
-    vd->guest.fb = pixman_image_ref(ds->surface->image);
-    vd->guest.format = ds->surface->format;
-    vnc_dpy_update(dcl, ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
-}
-
 static void vnc_colordepth(VncState *vs)
 {
     if (vnc_has_feature(vs, VNC_FEATURE_WMVI)) {
@@ -2696,7 +2686,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_ms(rt_clock, vnc_refresh, vd);
-        vnc_dpy_resize(&vd->dcl, vd->ds);
+        vnc_dpy_switch(&vd->dcl, vd->ds, vd->ds->surface);
         vnc_refresh(vd);
     }
 }
@@ -2836,8 +2826,7 @@ static const DisplayChangeListenerOps dcl_ops = {
     .dpy_name          = "vnc",
     .dpy_gfx_copy      = vnc_dpy_copy,
     .dpy_gfx_update    = vnc_dpy_update,
-    .dpy_gfx_resize    = vnc_dpy_resize,
-    .dpy_gfx_setdata   = vnc_dpy_setdata,
+    .dpy_gfx_switch    = vnc_dpy_switch,
     .dpy_mouse_set     = vnc_mouse_set,
     .dpy_cursor_define = vnc_dpy_cursor_define,
 };
commit da229ef3b3c5709b01d62e7a6e213b31bca33d16
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 28 10:48:02 2013 +0100

    console: rework DisplaySurface handling [vga emu side]
    
    Decouple DisplaySurface allocation & deallocation from DisplayState.
    Replace dpy_gfx_resize + dpy_gfx_setdata with a dpy_gfx_replace_surface
    function.
    
    This handles the graphic hardware emulation.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
index c5bf9f9..6747c1c 100644
--- a/hw/arm/nseries.c
+++ b/hw/arm/nseries.c
@@ -1290,7 +1290,6 @@ static void n8x0_init(QEMUMachineInitArgs *args,
     MemoryRegion *sysmem = get_system_memory();
     struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s));
     int sdram_size = binfo->ram_size;
-    DisplayState *ds;
 
     s->mpu = omap2420_mpu_init(sysmem, sdram_size, args->cpu_model);
 
@@ -1370,12 +1369,6 @@ static void n8x0_init(QEMUMachineInitArgs *args,
         n800_setup_nolo_tags(nolo_tags);
         cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000);
     }
-    /* FIXME: We shouldn't really be doing this here.  The LCD controller
-       will set the size once configured, so this just sets an initial
-       size until the guest activates the display.  */
-    ds = get_displaystate();
-    ds->surface = qemu_resize_displaysurface(ds, 800, 480);
-    dpy_gfx_resize(ds);
 }
 
 static struct arm_boot_info n800_binfo = {
diff --git a/hw/arm/palm.c b/hw/arm/palm.c
index 91bc74a..baeb585 100644
--- a/hw/arm/palm.c
+++ b/hw/arm/palm.c
@@ -205,7 +205,6 @@ static void palmte_init(QEMUMachineInitArgs *args)
     static uint32_t cs2val = 0x0000e1a0;
     static uint32_t cs3val = 0xe1a0e1a0;
     int rom_size, rom_loaded = 0;
-    DisplayState *ds = get_displaystate();
     MemoryRegion *flash = g_new(MemoryRegion, 1);
     MemoryRegion *cs = g_new(MemoryRegion, 4);
 
@@ -268,12 +267,6 @@ static void palmte_init(QEMUMachineInitArgs *args)
         palmte_binfo.initrd_filename = initrd_filename;
         arm_load_kernel(mpu->cpu, &palmte_binfo);
     }
-
-    /* FIXME: We shouldn't really be doing this here.  The LCD controller
-       will set the size once configured, so this just sets an initial
-       size until the guest activates the display.  */
-    ds->surface = qemu_resize_displaysurface(ds, 320, 320);
-    dpy_gfx_resize(ds);
 }
 
 static QEMUMachine palmte_machine = {
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index d77df42..8a19272 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -98,6 +98,7 @@ static void qxl_set_rect_to_surface(PCIQXLDevice *qxl, QXLRect *area)
 static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
 {
     VGACommonState *vga = &qxl->vga;
+    DisplaySurface *surface;
     int i;
 
     if (qxl->guest_primary.resized) {
@@ -112,8 +113,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
                qxl->guest_primary.bytes_pp,
                qxl->guest_primary.bits_pp);
         if (qxl->guest_primary.qxl_stride > 0) {
-            qemu_free_displaysurface(vga->ds);
-            vga->ds->surface = qemu_create_displaysurface_from
+            surface = qemu_create_displaysurface_from
                 (qxl->guest_primary.surface.width,
                  qxl->guest_primary.surface.height,
                  qxl->guest_primary.bits_pp,
@@ -121,11 +121,11 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
                  qxl->guest_primary.data,
                  false);
         } else {
-            qemu_resize_displaysurface(vga->ds,
-                    qxl->guest_primary.surface.width,
-                    qxl->guest_primary.surface.height);
+            surface = qemu_create_displaysurface
+                (qxl->guest_primary.surface.width,
+                 qxl->guest_primary.surface.height);
         }
-        dpy_gfx_resize(vga->ds);
+        dpy_gfx_replace_surface(vga->ds, surface);
     }
     for (i = 0; i < qxl->num_dirty_rects; i++) {
         if (qemu_spice_rect_is_empty(qxl->dirty+i)) {
diff --git a/hw/vga.c b/hw/vga.c
index 2213bc1..13d5066 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1691,11 +1691,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
         height != s->last_height ||
         s->last_depth != depth) {
         if (depth == 32 || (depth == 16 && !byteswap)) {
-            qemu_free_displaysurface(s->ds);
-            s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
-                    s->line_offset,
+            DisplaySurface *surface;
+            surface = qemu_create_displaysurface_from(disp_width,
+                    height, depth, s->line_offset,
                     s->vram_ptr + (s->start_addr * 4), byteswap);
-            dpy_gfx_resize(s->ds);
+            dpy_gfx_replace_surface(s->ds, surface);
         } else {
             qemu_console_resize(s->ds, disp_width, height);
         }
@@ -1709,12 +1709,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
     } else if (is_buffer_shared(s->ds->surface) &&
                (full_update || ds_get_data(s->ds) != s->vram_ptr
                 + (s->start_addr * 4))) {
-        qemu_free_displaysurface(s->ds);
-        s->ds->surface = qemu_create_displaysurface_from(disp_width,
-                height, depth,
-                s->line_offset,
+        DisplaySurface *surface;
+        surface = qemu_create_displaysurface_from(disp_width,
+                height, depth, s->line_offset,
                 s->vram_ptr + (s->start_addr * 4), byteswap);
-        dpy_gfx_setdata(s->ds);
+        dpy_gfx_replace_surface(s->ds, surface);
     }
 
     s->rgb_to_pixel =
diff --git a/hw/xenfb.c b/hw/xenfb.c
index 3462ded..7779097 100644
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -703,6 +703,7 @@ static void xenfb_send_refresh_period(struct XenFB *xenfb, int period)
 static void xenfb_update(void *opaque)
 {
     struct XenFB *xenfb = opaque;
+    DisplaySurface *surface;
     int i;
 
     if (xenfb->c.xendev.be_state != XenbusStateConnected)
@@ -753,21 +754,20 @@ static void xenfb_update(void *opaque)
         case 16:
         case 32:
             /* console.c supported depth -> buffer can be used directly */
-            qemu_free_displaysurface(xenfb->c.ds);
-            xenfb->c.ds->surface = qemu_create_displaysurface_from
+            surface = qemu_create_displaysurface_from
                 (xenfb->width, xenfb->height, xenfb->depth,
                  xenfb->row_stride, xenfb->pixels + xenfb->offset,
                  false);
             break;
         default:
             /* we must convert stuff */
-            qemu_resize_displaysurface(xenfb->c.ds, xenfb->width, xenfb->height);
+            surface = qemu_create_displaysurface(xenfb->width, xenfb->height);
             break;
         }
+        dpy_gfx_replace_surface(xenfb->c.ds, surface);
         xen_be_printf(&xenfb->c.xendev, 1, "update: resizing: %dx%d @ %d bpp%s\n",
                       xenfb->width, xenfb->height, xenfb->depth,
                       is_buffer_shared(xenfb->c.ds->surface) ? " (shared)" : "");
-        dpy_gfx_resize(xenfb->c.ds);
         xenfb->up_fullscreen = 1;
     }
 
diff --git a/include/ui/console.h b/include/ui/console.h
index 91a1f63..63e6e66 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -210,11 +210,8 @@ DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
 PixelFormat qemu_different_endianness_pixelformat(int bpp);
 PixelFormat qemu_default_pixelformat(int bpp);
 
-DisplaySurface *qemu_create_displaysurface(DisplayState *ds,
-                                           int width, int height);
-DisplaySurface *qemu_resize_displaysurface(DisplayState *ds,
-                                           int width, int height);
-void qemu_free_displaysurface(DisplayState *ds);
+DisplaySurface *qemu_create_displaysurface(int width, int height);
+void qemu_free_displaysurface(DisplaySurface *surface);
 
 static inline int is_surface_bgr(DisplaySurface *surface)
 {
@@ -236,8 +233,8 @@ void register_displaychangelistener(DisplayState *ds,
 void unregister_displaychangelistener(DisplayChangeListener *dcl);
 
 void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h);
-void dpy_gfx_resize(DisplayState *s);
-void dpy_gfx_setdata(DisplayState *s);
+void dpy_gfx_replace_surface(DisplayState *s,
+                             DisplaySurface *surface);
 void dpy_refresh(DisplayState *s);
 void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y,
                   int dst_x, int dst_y, int w, int h);
diff --git a/trace-events b/trace-events
index cbe7ef2..406fe5f 100644
--- a/trace-events
+++ b/trace-events
@@ -958,8 +958,9 @@ dma_bdrv_cb(void *dbs, int ret) "dbs=%p ret=%d"
 dma_map_wait(void *dbs) "dbs=%p"
 
 # console.h
-displaysurface_free(void *display_state, void *display_surface) "state=%p surface=%p"
-displaysurface_resize(void *display_state, void *display_surface, int width, int height) "state=%p surface=%p %dx%d"
+displaysurface_create(void *display_surface, int w, int h) "surface=%p, %dx%d"
+displaysurface_create_from(void *display_surface, int w, int h, int bpp, int swap) "surface=%p, %dx%d, bpp %d, bswap %d"
+displaysurface_free(void *display_surface) "surface=%p"
 displaychangelistener_register(void *dcl, const char *name) "%p [ %s ]"
 displaychangelistener_unregister(void *dcl, const char *name) "%p [ %s ]"
 
diff --git a/ui/console.c b/ui/console.c
index 09f1185..c2ca9e7 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1099,8 +1099,9 @@ void console_select(unsigned int index)
         }
         active_console = s;
         if (ds->have_gfx) {
-            ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height);
-            dpy_gfx_resize(ds);
+            DisplaySurface *surface;
+            surface = qemu_create_displaysurface(s->g_width, s->g_height);
+            dpy_gfx_replace_surface(ds, surface);
         }
         if (ds->have_text) {
             dpy_text_resize(ds, s->width, s->height);
@@ -1316,34 +1317,24 @@ static void qemu_alloc_display(DisplaySurface *surface, int width, int height,
 #endif
 }
 
-DisplaySurface *qemu_create_displaysurface(DisplayState *ds,
-                                           int width, int height)
+DisplaySurface *qemu_create_displaysurface(int width, int height)
 {
     DisplaySurface *surface = g_new0(DisplaySurface, 1);
-
     int linesize = width * 4;
+
+    trace_displaysurface_create(surface, width, height);
     qemu_alloc_display(surface, width, height, linesize,
                        qemu_default_pixelformat(32), 0);
     return surface;
 }
 
-DisplaySurface *qemu_resize_displaysurface(DisplayState *ds,
-                                           int width, int height)
-{
-    int linesize = width * 4;
-
-    trace_displaysurface_resize(ds, ds->surface, width, height);
-    qemu_alloc_display(ds->surface, width, height, linesize,
-                       qemu_default_pixelformat(32), 0);
-    return ds->surface;
-}
-
 DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp,
                                                 int linesize, uint8_t *data,
                                                 bool byteswap)
 {
     DisplaySurface *surface = g_new0(DisplaySurface, 1);
 
+    trace_displaysurface_create_from(surface, width, height, bpp, byteswap);
     if (byteswap) {
         surface->pf = qemu_different_endianness_pixelformat(bpp);
     } else {
@@ -1364,14 +1355,14 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height, int bpp,
     return surface;
 }
 
-void qemu_free_displaysurface(DisplayState *ds)
+void qemu_free_displaysurface(DisplaySurface *surface)
 {
-    trace_displaysurface_free(ds, ds->surface);
-    if (ds->surface == NULL) {
+    if (surface == NULL) {
         return;
     }
-    qemu_pixman_image_unref(ds->surface->image);
-    g_free(ds->surface);
+    trace_displaysurface_free(surface);
+    qemu_pixman_image_unref(surface->image);
+    g_free(surface);
 }
 
 void register_displaychangelistener(DisplayState *ds,
@@ -1414,24 +1405,19 @@ void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h)
     }
 }
 
-void dpy_gfx_resize(DisplayState *s)
+void dpy_gfx_replace_surface(DisplayState *s,
+                             DisplaySurface *surface)
 {
+    DisplaySurface *old_surface = s->surface;
     struct DisplayChangeListener *dcl;
+
+    s->surface = surface;
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (dcl->ops->dpy_gfx_resize) {
             dcl->ops->dpy_gfx_resize(dcl, s);
         }
     }
-}
-
-void dpy_gfx_setdata(DisplayState *s)
-{
-    struct DisplayChangeListener *dcl;
-    QLIST_FOREACH(dcl, &s->listeners, next) {
-        if (dcl->ops->dpy_gfx_setdata) {
-            dcl->ops->dpy_gfx_setdata(dcl, s);
-        }
-    }
+    qemu_free_displaysurface(old_surface);
 }
 
 void dpy_refresh(DisplayState *s)
@@ -1521,6 +1507,7 @@ bool dpy_cursor_define_supported(struct DisplayState *s)
 static void dumb_display_init(void)
 {
     DisplayState *ds = g_malloc0(sizeof(DisplayState));
+    DisplaySurface *surface;
     int width = 640;
     int height = 480;
 
@@ -1528,7 +1515,9 @@ static void dumb_display_init(void)
         width = active_console->g_width;
         height = active_console->g_height;
     }
-    ds->surface = qemu_create_displaysurface(ds, width, height);
+    surface = qemu_create_displaysurface(width, height);
+    dpy_gfx_replace_surface(ds, surface);
+
     register_displaystate(ds);
 }
 
@@ -1561,22 +1550,19 @@ DisplayState *graphic_console_init(vga_hw_update_ptr update,
 {
     QemuConsole *s;
     DisplayState *ds;
+    DisplaySurface *surface;
 
     ds = (DisplayState *) g_malloc0(sizeof(DisplayState));
-    ds->surface = qemu_create_displaysurface(ds, 640, 480);
-
     s = new_console(ds, GRAPHIC_CONSOLE);
-    if (s == NULL) {
-        qemu_free_displaysurface(ds);
-        g_free(ds);
-        return NULL;
-    }
     s->hw_update = update;
     s->hw_invalidate = invalidate;
     s->hw_screen_dump = screen_dump;
     s->hw_text_update = text_update;
     s->hw = opaque;
 
+    surface = qemu_create_displaysurface(640, 480);
+    dpy_gfx_replace_surface(ds, surface);
+
     register_displaystate(ds);
     return ds;
 }
@@ -1752,8 +1738,9 @@ void qemu_console_resize(DisplayState *ds, int width, int height)
     s->g_width = width;
     s->g_height = height;
     if (is_graphic_console()) {
-        ds->surface = qemu_resize_displaysurface(ds, width, height);
-        dpy_gfx_resize(ds);
+        DisplaySurface *surface;
+        surface = qemu_create_displaysurface(width, height);
+        dpy_gfx_replace_surface(ds, surface);
     }
 }
 
commit 468dfd6de2df3cbaed8c5cc43f8fbde6f94f9dbc
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 28 10:48:36 2013 +0100

    sdl: drop dead code
    
    DisplayAllocator removal (commit
    187cd1d9f30d13f0d0ef682e4d91cfa3e4cbd472) made this a nop.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/sdl.c b/ui/sdl.c
index 5baffa0..fc4dc1b 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -458,11 +458,6 @@ static void sdl_scale(DisplayState *ds, int width, int height)
     }
     do_sdl_resize(width, height, bpp);
     scaling_active = 1;
-    if (!is_buffer_shared(ds->surface)) {
-        ds->surface = qemu_resize_displaysurface(ds, ds_get_width(ds),
-                                                 ds_get_height(ds));
-        dpy_gfx_resize(ds);
-    }
 }
 
 static void toggle_full_screen(DisplayState *ds)
commit c099e7aa0295678859d58e9e60b7619f6ae3bac8
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 28 11:08:50 2013 +0100

    qxl: better vga init in enter_vga_mode
    
    Ask the vga core to update the display.  Will trigger dpy_gfx_resize
    if needed.  More complete than just calling dpy_gfx_resize.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index 54a8d91..5d830f0 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1073,8 +1073,8 @@ static void qxl_enter_vga_mode(PCIQXLDevice *d)
     trace_qxl_enter_vga_mode(d->id);
     qemu_spice_create_host_primary(&d->ssd);
     d->mode = QXL_MODE_VGA;
-    dpy_gfx_resize(d->ssd.ds);
     vga_dirty_log_start(&d->vga);
+    vga_hw_update();
 }
 
 static void qxl_exit_vga_mode(PCIQXLDevice *d)
commit c6c06853d99127c03778fc1bf9bc2d96a05c108e
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 28 12:15:00 2013 +0100

    qxl: zap qxl0 global
    
    DisplayChangeListener is passed now to all DisplayChangeListenerOps
    callbacks, so we can use that to access the qxl state and kill the
    qxl0 global variable.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index fe1c4f1..54a8d91 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -118,8 +118,6 @@ static QXLMode qxl_modes[] = {
     QXL_MODE_EX(3200, 2400),
 };
 
-static PCIQXLDevice *qxl0;
-
 static void qxl_send_events(PCIQXLDevice *d, uint32_t events);
 static int qxl_destroy_primary(PCIQXLDevice *d, qxl_async_io async);
 static void qxl_reset_memslots(PCIQXLDevice *d);
@@ -1870,28 +1868,34 @@ static void display_update(DisplayChangeListener *dcl,
                            struct DisplayState *ds,
                            int x, int y, int w, int h)
 {
-    if (qxl0->mode == QXL_MODE_VGA) {
-        qemu_spice_display_update(&qxl0->ssd, x, y, w, h);
+    PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl);
+
+    if (qxl->mode == QXL_MODE_VGA) {
+        qemu_spice_display_update(&qxl->ssd, x, y, w, h);
     }
 }
 
 static void display_resize(DisplayChangeListener *dcl,
                            struct DisplayState *ds)
 {
-    if (qxl0->mode == QXL_MODE_VGA) {
-        qemu_spice_display_resize(&qxl0->ssd);
+    PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl);
+
+    if (qxl->mode == QXL_MODE_VGA) {
+        qemu_spice_display_resize(&qxl->ssd);
     }
 }
 
 static void display_refresh(DisplayChangeListener *dcl,
                             struct DisplayState *ds)
 {
-    if (qxl0->mode == QXL_MODE_VGA) {
-        qemu_spice_display_refresh(&qxl0->ssd);
+    PCIQXLDevice *qxl = container_of(dcl, PCIQXLDevice, ssd.dcl);
+
+    if (qxl->mode == QXL_MODE_VGA) {
+        qemu_spice_display_refresh(&qxl->ssd);
     } else {
-        qemu_mutex_lock(&qxl0->ssd.lock);
-        qemu_spice_cursor_refresh_unlocked(&qxl0->ssd);
-        qemu_mutex_unlock(&qxl0->ssd.lock);
+        qemu_mutex_lock(&qxl->ssd.lock);
+        qemu_spice_cursor_refresh_unlocked(&qxl->ssd);
+        qemu_mutex_unlock(&qxl->ssd.lock);
     }
 }
 
@@ -2074,8 +2078,6 @@ static int qxl_init_primary(PCIDevice *dev)
                                    qxl_hw_screen_dump, qxl_hw_text_update, qxl);
     qemu_spice_display_init_common(&qxl->ssd, vga->ds);
 
-    qxl0 = qxl;
-
     rc = qxl_init_common(qxl);
     if (rc != 0) {
         return rc;
commit 9c80a315b47a64043f6b91bd6f14352a455b323e
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 28 14:47:07 2013 +0100

    spice: zap sdpy global
    
    DisplayChangeListener is passed now to all DisplayChangeListenerOps
    callbacks, so we can use that to access the spice display state and
    kill the sdpy global variable.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/spice-display.c b/ui/spice-display.c
index b6528fa..b2bda23 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -581,25 +581,26 @@ static const QXLInterface dpy_interface = {
     .client_monitors_config  = interface_client_monitors_config,
 };
 
-static SimpleSpiceDisplay sdpy;
-
 static void display_update(DisplayChangeListener *dcl,
                            struct DisplayState *ds,
                            int x, int y, int w, int h)
 {
-    qemu_spice_display_update(&sdpy, x, y, w, h);
+    SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
+    qemu_spice_display_update(ssd, x, y, w, h);
 }
 
 static void display_resize(DisplayChangeListener *dcl,
                            struct DisplayState *ds)
 {
-    qemu_spice_display_resize(&sdpy);
+    SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
+    qemu_spice_display_resize(ssd);
 }
 
 static void display_refresh(DisplayChangeListener *dcl,
                             struct DisplayState *ds)
 {
-    qemu_spice_display_refresh(&sdpy);
+    SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
+    qemu_spice_display_refresh(ssd);
 }
 
 static const DisplayChangeListenerOps display_listener_ops = {
@@ -611,16 +612,17 @@ static const DisplayChangeListenerOps display_listener_ops = {
 
 void qemu_spice_display_init(DisplayState *ds)
 {
-    assert(sdpy.ds == NULL);
-    qemu_spice_display_init_common(&sdpy, ds);
+    SimpleSpiceDisplay *ssd = g_new0(SimpleSpiceDisplay, 1);
+
+    qemu_spice_display_init_common(ssd, ds);
 
-    sdpy.qxl.base.sif = &dpy_interface.base;
-    qemu_spice_add_interface(&sdpy.qxl.base);
-    assert(sdpy.worker);
+    ssd->qxl.base.sif = &dpy_interface.base;
+    qemu_spice_add_interface(&ssd->qxl.base);
+    assert(ssd->worker);
 
-    qemu_spice_create_host_memslot(&sdpy);
-    qemu_spice_create_host_primary(&sdpy);
+    qemu_spice_create_host_memslot(ssd);
+    qemu_spice_create_host_primary(ssd);
 
-    sdpy.dcl.ops = &display_listener_ops;
-    register_displaychangelistener(ds, &sdpy.dcl);
+    ssd->dcl.ops = &display_listener_ops;
+    register_displaychangelistener(ds, &ssd->dcl);
 }
commit 21ef45d71221b4577330fe3aacfb06afad91ad46
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 28 11:34:31 2013 +0100

    console: kill DisplayState->opaque
    
    It's broken by design.  There can be multiple DisplayChangeListener
    instances, so they simply can't store state in the (single) DisplayState
    struct.  Try 'qemu -display gtk -vnc :0', watch it crash & burn.
    
    With DisplayChangeListenerOps having a more sane interface now we can
    simply use the DisplayChangeListener pointer to get access to our
    private data instead.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/include/ui/console.h b/include/ui/console.h
index bf54f1e..91a1f63 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -193,7 +193,6 @@ struct DisplayChangeListener {
 
 struct DisplayState {
     struct DisplaySurface *surface;
-    void *opaque;
     struct QEMUTimer *gui_timer;
     bool have_gfx;
     bool have_text;
diff --git a/ui/gtk.c b/ui/gtk.c
index 379107f..b21a94a 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -230,7 +230,7 @@ static void gd_update_caption(GtkDisplayState *s)
 static void gd_update(DisplayChangeListener *dcl,
                       DisplayState *ds, int x, int y, int w, int h)
 {
-    GtkDisplayState *s = ds->opaque;
+    GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
     int x1, x2, y1, y2;
     int mx, my;
     int fbw, fbh;
@@ -269,7 +269,7 @@ static void gd_refresh(DisplayChangeListener *dcl,
 static void gd_resize(DisplayChangeListener *dcl,
                       DisplayState *ds)
 {
-    GtkDisplayState *s = ds->opaque;
+    GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
     cairo_format_t kind;
     int stride;
 
@@ -1297,7 +1297,6 @@ void gtk_display_init(DisplayState *ds)
 
     gtk_init(NULL, NULL);
 
-    ds->opaque = s;
     s->ds = ds;
     s->dcl.ops = &dcl_ops;
 
diff --git a/ui/vnc.c b/ui/vnc.c
index bdc3cd8..a6111d6 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -44,7 +44,6 @@ static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 };
 #include "d3des.h"
 
 static VncDisplay *vnc_display; /* needed for info vnc */
-static DisplayChangeListener *dcl;
 
 static int vnc_cursor_define(VncState *vs);
 static void vnc_release_modifiers(VncState *vs);
@@ -435,7 +434,7 @@ static void vnc_dpy_update(DisplayChangeListener *dcl,
                            int x, int y, int w, int h)
 {
     int i;
-    VncDisplay *vd = ds->opaque;
+    VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
     struct VncSurface *s = &vd->guest;
     int width = ds_get_width(ds);
     int height = ds_get_height(ds);
@@ -578,7 +577,7 @@ void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y)
 static void vnc_dpy_resize(DisplayChangeListener *dcl,
                            DisplayState *ds)
 {
-    VncDisplay *vd = ds->opaque;
+    VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
     VncState *vs;
 
     vnc_abort_display_jobs(vd);
@@ -743,7 +742,7 @@ static void vnc_dpy_copy(DisplayChangeListener *dcl,
                          int src_x, int src_y,
                          int dst_x, int dst_y, int w, int h)
 {
-    VncDisplay *vd = ds->opaque;
+    VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
     VncState *vs, *vn;
     uint8_t *src_row;
     uint8_t *dst_row;
@@ -1069,7 +1068,7 @@ void vnc_disconnect_finish(VncState *vs)
     }
 
     if (QTAILQ_EMPTY(&vs->vd->clients)) {
-        dcl->idle = 1;
+        vs->vd->dcl.idle = 1;
     }
 
     vnc_remove_timer(vs->vd);
@@ -1985,7 +1984,7 @@ static void pixel_format_message (VncState *vs) {
 static void vnc_dpy_setdata(DisplayChangeListener *dcl,
                             DisplayState *ds)
 {
-    VncDisplay *vd = ds->opaque;
+    VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
 
     qemu_pixman_image_unref(vd->guest.fb);
     vd->guest.fb = pixman_image_ref(ds->surface->image);
@@ -2697,7 +2696,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_ms(rt_clock, vnc_refresh, vd);
-        vnc_dpy_resize(dcl, vd->ds);
+        vnc_dpy_resize(&vd->dcl, vd->ds);
         vnc_refresh(vd);
     }
 }
@@ -2736,7 +2735,7 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth, bool websocket)
     }
 
     VNC_DEBUG("New client on socket %d\n", csock);
-    dcl->idle = 0;
+    vd->dcl.idle = 0;
     socket_set_nonblock(vs->csock);
 #ifdef CONFIG_VNC_WS
     if (websocket) {
@@ -2847,10 +2846,7 @@ void vnc_display_init(DisplayState *ds)
 {
     VncDisplay *vs = g_malloc0(sizeof(*vs));
 
-    dcl = g_malloc0(sizeof(DisplayChangeListener));
-
-    ds->opaque = vs;
-    dcl->idle = 1;
+    vs->dcl.idle = 1;
     vnc_display = vs;
 
     vs->lsock = -1;
@@ -2873,14 +2869,14 @@ void vnc_display_init(DisplayState *ds)
     qemu_mutex_init(&vs->mutex);
     vnc_start_worker_thread();
 
-    dcl->ops = &dcl_ops;
-    register_displaychangelistener(ds, dcl);
+    vs->dcl.ops = &dcl_ops;
+    register_displaychangelistener(ds, &vs->dcl);
 }
 
 
 static void vnc_display_close(DisplayState *ds)
 {
-    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+    VncDisplay *vs = vnc_display;
 
     if (!vs)
         return;
@@ -2911,7 +2907,7 @@ static void vnc_display_close(DisplayState *ds)
 
 static int vnc_display_disable_login(DisplayState *ds)
 {
-    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+    VncDisplay *vs = vnc_display;
 
     if (!vs) {
         return -1;
@@ -2931,7 +2927,7 @@ static int vnc_display_disable_login(DisplayState *ds)
 
 int vnc_display_password(DisplayState *ds, const char *password)
 {
-    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+    VncDisplay *vs = vnc_display;
 
     if (!vs) {
         return -EINVAL;
@@ -2957,7 +2953,7 @@ int vnc_display_password(DisplayState *ds, const char *password)
 
 int vnc_display_pw_expire(DisplayState *ds, time_t expires)
 {
-    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+    VncDisplay *vs = vnc_display;
 
     if (!vs) {
         return -EINVAL;
@@ -2969,14 +2965,14 @@ int vnc_display_pw_expire(DisplayState *ds, time_t expires)
 
 char *vnc_display_local_addr(DisplayState *ds)
 {
-    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+    VncDisplay *vs = vnc_display;
     
     return vnc_socket_local_addr("%s:%s", vs->lsock);
 }
 
 void vnc_display_open(DisplayState *ds, const char *display, Error **errp)
 {
-    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+    VncDisplay *vs = vnc_display;
     const char *options;
     int password = 0;
     int reverse = 0;
@@ -3282,7 +3278,7 @@ fail:
 
 void vnc_display_add_client(DisplayState *ds, int csock, int skipauth)
 {
-    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+    VncDisplay *vs = vnc_display;
 
     vnc_connect(vs, csock, skipauth, 0);
 }
diff --git a/ui/vnc.h b/ui/vnc.h
index 45d7686..a96485b 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -151,6 +151,7 @@ struct VncDisplay
     char *ws_display;
 #endif
     DisplayState *ds;
+    DisplayChangeListener dcl;
     kbd_layout_t *kbd_layout;
     int lock_key_sync;
     QemuMutex mutex;
commit 7c20b4a374d0016e3fce005690fb428354a56621
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Nov 13 14:51:41 2012 +0100

    console: fix displaychangelisteners interface
    
    Split callbacks into separate Ops struct.  Pass DisplayChangeListener
    pointer as first argument to all callbacks.  Uninline a bunch of
    display functions and move them from console.h to console.c
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index ef69348..fe1c4f1 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1866,21 +1866,25 @@ static void qxl_vm_change_state_handler(void *opaque, int running,
 
 /* display change listener */
 
-static void display_update(struct DisplayState *ds, int x, int y, int w, int h)
+static void display_update(DisplayChangeListener *dcl,
+                           struct DisplayState *ds,
+                           int x, int y, int w, int h)
 {
     if (qxl0->mode == QXL_MODE_VGA) {
         qemu_spice_display_update(&qxl0->ssd, x, y, w, h);
     }
 }
 
-static void display_resize(struct DisplayState *ds)
+static void display_resize(DisplayChangeListener *dcl,
+                           struct DisplayState *ds)
 {
     if (qxl0->mode == QXL_MODE_VGA) {
         qemu_spice_display_resize(&qxl0->ssd);
     }
 }
 
-static void display_refresh(struct DisplayState *ds)
+static void display_refresh(DisplayChangeListener *dcl,
+                            struct DisplayState *ds)
 {
     if (qxl0->mode == QXL_MODE_VGA) {
         qemu_spice_display_refresh(&qxl0->ssd);
@@ -1891,10 +1895,11 @@ static void display_refresh(struct DisplayState *ds)
     }
 }
 
-static DisplayChangeListener display_listener = {
+static DisplayChangeListenerOps display_listener_ops = {
+    .dpy_name        = "spice/qxl",
     .dpy_gfx_update  = display_update,
     .dpy_gfx_resize  = display_resize,
-    .dpy_refresh = display_refresh,
+    .dpy_refresh     = display_refresh,
 };
 
 static void qxl_init_ramsize(PCIQXLDevice *qxl)
@@ -2076,7 +2081,8 @@ static int qxl_init_primary(PCIDevice *dev)
         return rc;
     }
 
-    register_displaychangelistener(vga->ds, &display_listener);
+    qxl->ssd.dcl.ops = &display_listener_ops;
+    register_displaychangelistener(vga->ds, &qxl->ssd.dcl);
     return rc;
 }
 
diff --git a/include/ui/console.h b/include/ui/console.h
index a37cf65..bf54f1e 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -147,24 +147,46 @@ void cursor_set_mono(QEMUCursor *c,
 void cursor_get_mono_image(QEMUCursor *c, int foreground, uint8_t *mask);
 void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask);
 
-struct DisplayChangeListener {
-    int idle;
-    uint64_t gui_timer_interval;
-
-    void (*dpy_refresh)(struct DisplayState *s);
-
-    void (*dpy_gfx_update)(struct DisplayState *s, int x, int y, int w, int h);
-    void (*dpy_gfx_resize)(struct DisplayState *s);
-    void (*dpy_gfx_setdata)(struct DisplayState *s);
-    void (*dpy_gfx_copy)(struct DisplayState *s, int src_x, int src_y,
+typedef struct DisplayChangeListenerOps {
+    const char *dpy_name;
+
+    void (*dpy_refresh)(DisplayChangeListener *dcl,
+                        struct DisplayState *s);
+
+    void (*dpy_gfx_update)(DisplayChangeListener *dcl,
+                           struct DisplayState *s,
+                           int x, int y, int w, int h);
+    void (*dpy_gfx_resize)(DisplayChangeListener *dcl,
+                           struct DisplayState *s);
+    void (*dpy_gfx_setdata)(DisplayChangeListener *dcl,
+                            struct DisplayState *s);
+    void (*dpy_gfx_copy)(DisplayChangeListener *dcl,
+                         struct DisplayState *s, int src_x, int src_y,
                          int dst_x, int dst_y, int w, int h);
 
-    void (*dpy_text_cursor)(struct DisplayState *s, int x, int y);
-    void (*dpy_text_resize)(struct DisplayState *s, int w, int h);
-    void (*dpy_text_update)(struct DisplayState *s, int x, int y, int w, int h);
+    void (*dpy_text_cursor)(DisplayChangeListener *dcl,
+                            struct DisplayState *s,
+                            int x, int y);
+    void (*dpy_text_resize)(DisplayChangeListener *dcl,
+                            struct DisplayState *s,
+                            int w, int h);
+    void (*dpy_text_update)(DisplayChangeListener *dcl,
+                            struct DisplayState *s,
+                            int x, int y, int w, int h);
+
+    void (*dpy_mouse_set)(DisplayChangeListener *dcl,
+                          struct DisplayState *s,
+                          int x, int y, int on);
+    void (*dpy_cursor_define)(DisplayChangeListener *dcl,
+                              struct DisplayState *s,
+                              QEMUCursor *cursor);
+} DisplayChangeListenerOps;
 
-    void (*dpy_mouse_set)(struct DisplayState *s, int x, int y, int on);
-    void (*dpy_cursor_define)(struct DisplayState *s, QEMUCursor *cursor);
+struct DisplayChangeListener {
+    int idle;
+    uint64_t gui_timer_interval;
+    const DisplayChangeListenerOps *ops;
+    DisplayState *ds;
 
     QLIST_ENTRY(DisplayChangeListener) next;
 };
@@ -210,145 +232,22 @@ static inline int is_buffer_shared(DisplaySurface *surface)
 
 void gui_setup_refresh(DisplayState *ds);
 
-static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl)
-{
-    QLIST_INSERT_HEAD(&ds->listeners, dcl, next);
-    gui_setup_refresh(ds);
-    if (dcl->dpy_gfx_resize) {
-        dcl->dpy_gfx_resize(ds);
-    }
-}
-
-static inline void unregister_displaychangelistener(DisplayState *ds,
-                                                    DisplayChangeListener *dcl)
-{
-    QLIST_REMOVE(dcl, next);
-    gui_setup_refresh(ds);
-}
-
-static inline void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h)
-{
-    struct DisplayChangeListener *dcl;
-    int width = pixman_image_get_width(s->surface->image);
-    int height = pixman_image_get_height(s->surface->image);
-
-    x = MAX(x, 0);
-    y = MAX(y, 0);
-    x = MIN(x, width);
-    y = MIN(y, height);
-    w = MIN(w, width - x);
-    h = MIN(h, height - y);
-
-    QLIST_FOREACH(dcl, &s->listeners, next) {
-        if (dcl->dpy_gfx_update) {
-            dcl->dpy_gfx_update(s, x, y, w, h);
-        }
-    }
-}
-
-static inline void dpy_gfx_resize(DisplayState *s)
-{
-    struct DisplayChangeListener *dcl;
-    QLIST_FOREACH(dcl, &s->listeners, next) {
-        if (dcl->dpy_gfx_resize) {
-            dcl->dpy_gfx_resize(s);
-        }
-    }
-}
-
-static inline void dpy_gfx_setdata(DisplayState *s)
-{
-    struct DisplayChangeListener *dcl;
-    QLIST_FOREACH(dcl, &s->listeners, next) {
-        if (dcl->dpy_gfx_setdata) {
-            dcl->dpy_gfx_setdata(s);
-        }
-    }
-}
-
-static inline void dpy_refresh(DisplayState *s)
-{
-    struct DisplayChangeListener *dcl;
-    QLIST_FOREACH(dcl, &s->listeners, next) {
-        if (dcl->dpy_refresh) {
-            dcl->dpy_refresh(s);
-        }
-    }
-}
-
-static inline void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y,
-                             int dst_x, int dst_y, int w, int h)
-{
-    struct DisplayChangeListener *dcl;
-    QLIST_FOREACH(dcl, &s->listeners, next) {
-        if (dcl->dpy_gfx_copy) {
-            dcl->dpy_gfx_copy(s, src_x, src_y, dst_x, dst_y, w, h);
-        } else { /* TODO */
-            dcl->dpy_gfx_update(s, dst_x, dst_y, w, h);
-        }
-    }
-}
-
-static inline void dpy_text_cursor(struct DisplayState *s, int x, int y)
-{
-    struct DisplayChangeListener *dcl;
-    QLIST_FOREACH(dcl, &s->listeners, next) {
-        if (dcl->dpy_text_cursor) {
-            dcl->dpy_text_cursor(s, x, y);
-        }
-    }
-}
-
-static inline void dpy_text_update(DisplayState *s, int x, int y, int w, int h)
-{
-    struct DisplayChangeListener *dcl;
-    QLIST_FOREACH(dcl, &s->listeners, next) {
-        if (dcl->dpy_text_update) {
-            dcl->dpy_text_update(s, x, y, w, h);
-        }
-    }
-}
-
-static inline void dpy_text_resize(DisplayState *s, int w, int h)
-{
-    struct DisplayChangeListener *dcl;
-    QLIST_FOREACH(dcl, &s->listeners, next) {
-        if (dcl->dpy_text_resize) {
-            dcl->dpy_text_resize(s, w, h);
-        }
-    }
-}
-
-static inline void dpy_mouse_set(struct DisplayState *s, int x, int y, int on)
-{
-    struct DisplayChangeListener *dcl;
-    QLIST_FOREACH(dcl, &s->listeners, next) {
-        if (dcl->dpy_mouse_set) {
-            dcl->dpy_mouse_set(s, x, y, on);
-        }
-    }
-}
-
-static inline void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor)
-{
-    struct DisplayChangeListener *dcl;
-    QLIST_FOREACH(dcl, &s->listeners, next) {
-        if (dcl->dpy_cursor_define) {
-            dcl->dpy_cursor_define(s, cursor);
-        }
-    }
-}
-
-static inline bool dpy_cursor_define_supported(struct DisplayState *s)
-{
-    struct DisplayChangeListener *dcl;
-    QLIST_FOREACH(dcl, &s->listeners, next) {
-        if (dcl->dpy_cursor_define) {
-            return true;
-        }
-    }
-    return false;
-}
+void register_displaychangelistener(DisplayState *ds,
+                                    DisplayChangeListener *dcl);
+void unregister_displaychangelistener(DisplayChangeListener *dcl);
+
+void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h);
+void dpy_gfx_resize(DisplayState *s);
+void dpy_gfx_setdata(DisplayState *s);
+void dpy_refresh(DisplayState *s);
+void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y,
+                  int dst_x, int dst_y, int w, int h);
+void dpy_text_cursor(struct DisplayState *s, int x, int y);
+void dpy_text_update(DisplayState *s, int x, int y, int w, int h);
+void dpy_text_resize(DisplayState *s, int w, int h);
+void dpy_mouse_set(struct DisplayState *s, int x, int y, int on);
+void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor);
+bool dpy_cursor_define_supported(struct DisplayState *s);
 
 static inline int ds_get_linesize(DisplayState *ds)
 {
diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h
index 46f9530..f2752aa 100644
--- a/include/ui/spice-display.h
+++ b/include/ui/spice-display.h
@@ -72,6 +72,7 @@ typedef struct SimpleSpiceUpdate SimpleSpiceUpdate;
 
 struct SimpleSpiceDisplay {
     DisplayState *ds;
+    DisplayChangeListener dcl;
     void *buf;
     int bufsize;
     QXLWorker *worker;
diff --git a/trace-events b/trace-events
index cd73b7f..cbe7ef2 100644
--- a/trace-events
+++ b/trace-events
@@ -960,6 +960,8 @@ dma_map_wait(void *dbs) "dbs=%p"
 # console.h
 displaysurface_free(void *display_state, void *display_surface) "state=%p surface=%p"
 displaysurface_resize(void *display_state, void *display_surface, int width, int height) "state=%p surface=%p %dx%d"
+displaychangelistener_register(void *dcl, const char *name) "%p [ %s ]"
+displaychangelistener_unregister(void *dcl, const char *name) "%p [ %s ]"
 
 # vga.c
 ppm_save(const char *filename, void *display_surface) "%s surface=%p"
diff --git a/ui/cocoa.m b/ui/cocoa.m
index ca42413..b1fb30e 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -969,7 +969,9 @@ int main (int argc, const char * argv[]) {
 
 
 #pragma mark qemu
-static void cocoa_update(DisplayState *ds, int x, int y, int w, int h)
+static void cocoa_update(DisplayChangeListener *dcl,
+                         DisplayState *ds,
+                         int x, int y, int w, int h)
 {
     COCOA_DEBUG("qemu_cocoa: cocoa_update\n");
 
@@ -986,14 +988,16 @@ static void cocoa_update(DisplayState *ds, int x, int y, int w, int h)
     [cocoaView setNeedsDisplayInRect:rect];
 }
 
-static void cocoa_resize(DisplayState *ds)
+static void cocoa_resize(DisplayChangeListener *dcl,
+                         DisplayState *ds)
 {
     COCOA_DEBUG("qemu_cocoa: cocoa_resize\n");
 
     [cocoaView resizeContentToWidth:(int)(ds_get_width(ds)) height:(int)(ds_get_height(ds)) displayState:ds];
 }
 
-static void cocoa_refresh(DisplayState *ds)
+static void cocoa_refresh(DisplayChangeListener *dcl,
+                          DisplayState *ds)
 {
     COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n");
 
@@ -1030,6 +1034,14 @@ static void cocoa_cleanup(void)
     g_free(dcl);
 }
 
+static const DisplayChangeListenerOps dcl_ops = {
+    .dpy_name          = "cocoa",
+    .dpy_gfx_update = cocoa_update;
+    .dpy_gfx_resize = cocoa_resize;
+    .dpy_gfx_setdata = cocoa_setdata;
+    .dpy_refresh = cocoa_refresh;
+};
+
 void cocoa_display_init(DisplayState *ds, int full_screen)
 {
     COCOA_DEBUG("qemu_cocoa: cocoa_display_init\n");
@@ -1037,12 +1049,8 @@ void cocoa_display_init(DisplayState *ds, int full_screen)
     dcl = g_malloc0(sizeof(DisplayChangeListener));
 
     // register vga output callbacks
-    dcl->dpy_gfx_update = cocoa_update;
-    dcl->dpy_gfx_resize = cocoa_resize;
-    dcl->dpy_refresh = cocoa_refresh;
-    dcl->dpy_gfx_setdata = cocoa_setdata;
-
-	register_displaychangelistener(ds, dcl);
+    dcl->ops = &dcl_ops;
+    register_displaychangelistener(ds, dcl);
 
     // register cleanup function
     atexit(cocoa_cleanup);
diff --git a/ui/console.c b/ui/console.c
index 27e87f8..09f1185 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1374,6 +1374,150 @@ void qemu_free_displaysurface(DisplayState *ds)
     g_free(ds->surface);
 }
 
+void register_displaychangelistener(DisplayState *ds,
+                                    DisplayChangeListener *dcl)
+{
+    trace_displaychangelistener_register(dcl, dcl->ops->dpy_name);
+    dcl->ds = ds;
+    QLIST_INSERT_HEAD(&ds->listeners, dcl, next);
+    gui_setup_refresh(ds);
+    if (dcl->ops->dpy_gfx_resize) {
+        dcl->ops->dpy_gfx_resize(dcl, ds);
+    }
+}
+
+void unregister_displaychangelistener(DisplayChangeListener *dcl)
+{
+    DisplayState *ds = dcl->ds;
+    trace_displaychangelistener_unregister(dcl, dcl->ops->dpy_name);
+    QLIST_REMOVE(dcl, next);
+    gui_setup_refresh(ds);
+}
+
+void dpy_gfx_update(DisplayState *s, int x, int y, int w, int h)
+{
+    struct DisplayChangeListener *dcl;
+    int width = pixman_image_get_width(s->surface->image);
+    int height = pixman_image_get_height(s->surface->image);
+
+    x = MAX(x, 0);
+    y = MAX(y, 0);
+    x = MIN(x, width);
+    y = MIN(y, height);
+    w = MIN(w, width - x);
+    h = MIN(h, height - y);
+
+    QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (dcl->ops->dpy_gfx_update) {
+            dcl->ops->dpy_gfx_update(dcl, s, x, y, w, h);
+        }
+    }
+}
+
+void dpy_gfx_resize(DisplayState *s)
+{
+    struct DisplayChangeListener *dcl;
+    QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (dcl->ops->dpy_gfx_resize) {
+            dcl->ops->dpy_gfx_resize(dcl, s);
+        }
+    }
+}
+
+void dpy_gfx_setdata(DisplayState *s)
+{
+    struct DisplayChangeListener *dcl;
+    QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (dcl->ops->dpy_gfx_setdata) {
+            dcl->ops->dpy_gfx_setdata(dcl, s);
+        }
+    }
+}
+
+void dpy_refresh(DisplayState *s)
+{
+    struct DisplayChangeListener *dcl;
+    QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (dcl->ops->dpy_refresh) {
+            dcl->ops->dpy_refresh(dcl, s);
+        }
+    }
+}
+
+void dpy_gfx_copy(struct DisplayState *s, int src_x, int src_y,
+                             int dst_x, int dst_y, int w, int h)
+{
+    struct DisplayChangeListener *dcl;
+    QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (dcl->ops->dpy_gfx_copy) {
+            dcl->ops->dpy_gfx_copy(dcl, s, src_x, src_y, dst_x, dst_y, w, h);
+        } else { /* TODO */
+            dcl->ops->dpy_gfx_update(dcl, s, dst_x, dst_y, w, h);
+        }
+    }
+}
+
+void dpy_text_cursor(struct DisplayState *s, int x, int y)
+{
+    struct DisplayChangeListener *dcl;
+    QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (dcl->ops->dpy_text_cursor) {
+            dcl->ops->dpy_text_cursor(dcl, s, x, y);
+        }
+    }
+}
+
+void dpy_text_update(DisplayState *s, int x, int y, int w, int h)
+{
+    struct DisplayChangeListener *dcl;
+    QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (dcl->ops->dpy_text_update) {
+            dcl->ops->dpy_text_update(dcl, s, x, y, w, h);
+        }
+    }
+}
+
+void dpy_text_resize(DisplayState *s, int w, int h)
+{
+    struct DisplayChangeListener *dcl;
+    QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (dcl->ops->dpy_text_resize) {
+            dcl->ops->dpy_text_resize(dcl, s, w, h);
+        }
+    }
+}
+
+void dpy_mouse_set(struct DisplayState *s, int x, int y, int on)
+{
+    struct DisplayChangeListener *dcl;
+    QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (dcl->ops->dpy_mouse_set) {
+            dcl->ops->dpy_mouse_set(dcl, s, x, y, on);
+        }
+    }
+}
+
+void dpy_cursor_define(struct DisplayState *s, QEMUCursor *cursor)
+{
+    struct DisplayChangeListener *dcl;
+    QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (dcl->ops->dpy_cursor_define) {
+            dcl->ops->dpy_cursor_define(dcl, s, cursor);
+        }
+    }
+}
+
+bool dpy_cursor_define_supported(struct DisplayState *s)
+{
+    struct DisplayChangeListener *dcl;
+    QLIST_FOREACH(dcl, &s->listeners, next) {
+        if (dcl->ops->dpy_cursor_define) {
+            return true;
+        }
+    }
+    return false;
+}
+
 static void dumb_display_init(void)
 {
     DisplayState *ds = g_malloc0(sizeof(DisplayState));
diff --git a/ui/curses.c b/ui/curses.c
index d78e378..ca9856c 100644
--- a/ui/curses.c
+++ b/ui/curses.c
@@ -35,12 +35,15 @@
 #define FONT_HEIGHT 16
 #define FONT_WIDTH 8
 
+static DisplayChangeListener *dcl;
 static console_ch_t screen[160 * 100];
 static WINDOW *screenpad = NULL;
 static int width, height, gwidth, gheight, invalidate;
 static int px, py, sminx, sminy, smaxx, smaxy;
 
-static void curses_update(DisplayState *ds, int x, int y, int w, int h)
+static void curses_update(DisplayChangeListener *dcl,
+                          DisplayState *ds,
+                          int x, int y, int w, int h)
 {
     chtype *line;
 
@@ -91,7 +94,9 @@ static void curses_calc_pad(void)
     }
 }
 
-static void curses_resize(DisplayState *ds, int width, int height)
+static void curses_resize(DisplayChangeListener *dcl,
+                          DisplayState *ds,
+                          int width, int height)
 {
     if (width == gwidth && height == gheight) {
         return;
@@ -128,7 +133,9 @@ static void curses_winch_handler(int signum)
 #endif
 #endif
 
-static void curses_cursor_position(DisplayState *ds, int x, int y)
+static void curses_cursor_position(DisplayChangeListener *dcl,
+                                   DisplayState *ds,
+                                   int x, int y)
 {
     if (x >= 0) {
         x = sminx + x - px;
@@ -154,7 +161,8 @@ static void curses_cursor_position(DisplayState *ds, int x, int y)
 
 static kbd_layout_t *kbd_layout = NULL;
 
-static void curses_refresh(DisplayState *ds)
+static void curses_refresh(DisplayChangeListener *dcl,
+                           DisplayState *ds)
 {
     int chr, nextchr, keysym, keycode, keycode_alt;
 
@@ -187,7 +195,7 @@ static void curses_refresh(DisplayState *ds)
             clear();
             refresh();
             curses_calc_pad();
-            curses_update(ds, 0, 0, width, height);
+            curses_update(dcl, ds, 0, 0, width, height);
             continue;
         }
 #endif
@@ -323,9 +331,16 @@ static void curses_keyboard_setup(void)
     }
 }
 
+static const DisplayChangeListenerOps dcl_ops = {
+    .dpy_name        = "curses",
+    .dpy_text_update = curses_update,
+    .dpy_text_resize = curses_resize,
+    .dpy_refresh     = curses_refresh,
+    .dpy_text_cursor = curses_cursor_position,
+};
+
 void curses_display_init(DisplayState *ds, int full_screen)
 {
-    DisplayChangeListener *dcl;
 #ifndef _WIN32
     if (!isatty(1)) {
         fprintf(stderr, "We need a terminal output\n");
@@ -346,10 +361,7 @@ void curses_display_init(DisplayState *ds, int full_screen)
 #endif
 
     dcl = (DisplayChangeListener *) g_malloc0(sizeof(DisplayChangeListener));
-    dcl->dpy_text_update = curses_update;
-    dcl->dpy_text_resize = curses_resize;
-    dcl->dpy_refresh = curses_refresh;
-    dcl->dpy_text_cursor = curses_cursor_position;
+    dcl->ops = &dcl_ops;
     register_displaychangelistener(ds, dcl);
 
     invalidate = 1;
diff --git a/ui/gtk.c b/ui/gtk.c
index 794dab1..379107f 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -227,7 +227,8 @@ static void gd_update_caption(GtkDisplayState *s)
 
 /** DisplayState Callbacks **/
 
-static void gd_update(DisplayState *ds, int x, int y, int w, int h)
+static void gd_update(DisplayChangeListener *dcl,
+                      DisplayState *ds, int x, int y, int w, int h)
 {
     GtkDisplayState *s = ds->opaque;
     int x1, x2, y1, y2;
@@ -259,12 +260,14 @@ static void gd_update(DisplayState *ds, int x, int y, int w, int h)
     gtk_widget_queue_draw_area(s->drawing_area, mx + x1, my + y1, (x2 - x1), (y2 - y1));
 }
 
-static void gd_refresh(DisplayState *ds)
+static void gd_refresh(DisplayChangeListener *dcl,
+                       DisplayState *ds)
 {
     vga_hw_update();
 }
 
-static void gd_resize(DisplayState *ds)
+static void gd_resize(DisplayChangeListener *dcl,
+                      DisplayState *ds)
 {
     GtkDisplayState *s = ds->opaque;
     cairo_format_t kind;
@@ -382,7 +385,7 @@ static gboolean gd_window_close(GtkWidget *widget, GdkEvent *event,
     GtkDisplayState *s = opaque;
 
     if (!no_quit) {
-        unregister_displaychangelistener(s->ds, &s->dcl);
+        unregister_displaychangelistener(&s->dcl);
         qmp_quit(NULL);
         return FALSE;
     }
@@ -735,7 +738,7 @@ static void gd_menu_zoom_in(GtkMenuItem *item, void *opaque)
     s->scale_x += .25;
     s->scale_y += .25;
 
-    gd_resize(s->ds);
+    gd_resize(&s->dcl, s->ds);
 }
 
 static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque)
@@ -751,7 +754,7 @@ static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque)
     s->scale_x = MAX(s->scale_x, .25);
     s->scale_y = MAX(s->scale_y, .25);
 
-    gd_resize(s->ds);
+    gd_resize(&s->dcl, s->ds);
 }
 
 static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque)
@@ -761,7 +764,7 @@ static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque)
     s->scale_x = 1.0;
     s->scale_y = 1.0;
 
-    gd_resize(s->ds);
+    gd_resize(&s->dcl, s->ds);
 }
 
 static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque)
@@ -775,7 +778,7 @@ static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque)
         s->free_scale = FALSE;
     }
 
-    gd_resize(s->ds);
+    gd_resize(&s->dcl, s->ds);
 
     gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
     gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh);
@@ -1281,6 +1284,13 @@ static void gd_create_menus(GtkDisplayState *s)
     gtk_menu_shell_append(GTK_MENU_SHELL(s->menu_bar), s->view_menu_item);
 }
 
+static const DisplayChangeListenerOps dcl_ops = {
+    .dpy_name          = "gtk",
+    .dpy_gfx_update    = gd_update,
+    .dpy_gfx_resize    = gd_resize,
+    .dpy_refresh       = gd_refresh,
+};
+
 void gtk_display_init(DisplayState *ds)
 {
     GtkDisplayState *s = g_malloc0(sizeof(*s));
@@ -1289,9 +1299,7 @@ void gtk_display_init(DisplayState *ds)
 
     ds->opaque = s;
     s->ds = ds;
-    s->dcl.dpy_gfx_update = gd_update;
-    s->dcl.dpy_gfx_resize = gd_resize;
-    s->dcl.dpy_refresh = gd_refresh;
+    s->dcl.ops = &dcl_ops;
 
     s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 #if GTK_CHECK_VERSION(3, 2, 0)
diff --git a/ui/sdl.c b/ui/sdl.c
index 1657848..5baffa0 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -59,7 +59,9 @@ static SDL_PixelFormat host_format;
 static int scaling_active = 0;
 static Notifier mouse_mode_notifier;
 
-static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
+static void sdl_update(DisplayChangeListener *dcl,
+                       DisplayState *ds,
+                       int x, int y, int w, int h)
 {
     //    printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
     SDL_Rect rec;
@@ -81,7 +83,8 @@ static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
     SDL_UpdateRect(real_screen, rec.x, rec.y, rec.w, rec.h);
 }
 
-static void sdl_setdata(DisplayState *ds)
+static void sdl_setdata(DisplayChangeListener *dcl,
+                        DisplayState *ds)
 {
     if (guest_screen != NULL) SDL_FreeSurface(guest_screen);
 
@@ -114,7 +117,8 @@ static void do_sdl_resize(int width, int height, int bpp)
     }
 }
 
-static void sdl_resize(DisplayState *ds)
+static void sdl_resize(DisplayChangeListener *dcl,
+                       DisplayState *ds)
 {
     if (!scaling_active) {
         do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
@@ -122,7 +126,7 @@ static void sdl_resize(DisplayState *ds)
         do_sdl_resize(real_screen->w, real_screen->h,
                       ds_get_bits_per_pixel(ds));
     }
-    sdl_setdata(ds);
+    sdl_setdata(dcl, ds);
 }
 
 /* generic keyboard conversion */
@@ -514,7 +518,7 @@ static void handle_keydown(DisplayState *ds, SDL_Event *ev)
         case 0x16: /* 'u' key on US keyboard */
             if (scaling_active) {
                 scaling_active = 0;
-                sdl_resize(ds);
+                sdl_resize(dcl, ds);
                 vga_hw_invalidate();
                 vga_hw_update();
             }
@@ -753,7 +757,8 @@ static void handle_activation(DisplayState *ds, SDL_Event *ev)
     }
 }
 
-static void sdl_refresh(DisplayState *ds)
+static void sdl_refresh(DisplayChangeListener *dcl,
+                        DisplayState *ds)
 {
     SDL_Event ev1, *ev = &ev1;
 
@@ -768,7 +773,7 @@ static void sdl_refresh(DisplayState *ds)
     while (SDL_PollEvent(ev)) {
         switch (ev->type) {
         case SDL_VIDEOEXPOSE:
-            sdl_update(ds, 0, 0, real_screen->w, real_screen->h);
+            sdl_update(dcl, ds, 0, 0, real_screen->w, real_screen->h);
             break;
         case SDL_KEYDOWN:
             handle_keydown(ds, ev);
@@ -803,7 +808,9 @@ static void sdl_refresh(DisplayState *ds)
     }
 }
 
-static void sdl_mouse_warp(DisplayState *ds, int x, int y, int on)
+static void sdl_mouse_warp(DisplayChangeListener *dcl,
+                           DisplayState *ds,
+                           int x, int y, int on)
 {
     if (on) {
         if (!guest_cursor)
@@ -819,7 +826,9 @@ static void sdl_mouse_warp(DisplayState *ds, int x, int y, int on)
     guest_x = x, guest_y = y;
 }
 
-static void sdl_mouse_define(DisplayState *ds, QEMUCursor *c)
+static void sdl_mouse_define(DisplayChangeListener *dcl,
+                             DisplayState *ds,
+                             QEMUCursor *c)
 {
     uint8_t *image, *mask;
     int bpl;
@@ -849,6 +858,16 @@ static void sdl_cleanup(void)
     SDL_QuitSubSystem(SDL_INIT_VIDEO);
 }
 
+static const DisplayChangeListenerOps dcl_ops = {
+    .dpy_name          = "sdl",
+    .dpy_gfx_update    = sdl_update,
+    .dpy_gfx_resize    = sdl_resize,
+    .dpy_refresh       = sdl_refresh,
+    .dpy_gfx_setdata   = sdl_setdata,
+    .dpy_mouse_set     = sdl_mouse_warp,
+    .dpy_cursor_define = sdl_mouse_define,
+};
+
 void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
 {
     int flags;
@@ -917,12 +936,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
     }
 
     dcl = g_malloc0(sizeof(DisplayChangeListener));
-    dcl->dpy_gfx_update = sdl_update;
-    dcl->dpy_gfx_resize = sdl_resize;
-    dcl->dpy_refresh = sdl_refresh;
-    dcl->dpy_gfx_setdata = sdl_setdata;
-    dcl->dpy_mouse_set = sdl_mouse_warp;
-    dcl->dpy_cursor_define = sdl_mouse_define;
+    dcl->ops = &dcl_ops;
     register_displaychangelistener(ds, dcl);
 
     mouse_mode_notifier.notify = sdl_mouse_mode_change;
diff --git a/ui/spice-display.c b/ui/spice-display.c
index dc7e58d..b6528fa 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -583,25 +583,30 @@ static const QXLInterface dpy_interface = {
 
 static SimpleSpiceDisplay sdpy;
 
-static void display_update(struct DisplayState *ds, int x, int y, int w, int h)
+static void display_update(DisplayChangeListener *dcl,
+                           struct DisplayState *ds,
+                           int x, int y, int w, int h)
 {
     qemu_spice_display_update(&sdpy, x, y, w, h);
 }
 
-static void display_resize(struct DisplayState *ds)
+static void display_resize(DisplayChangeListener *dcl,
+                           struct DisplayState *ds)
 {
     qemu_spice_display_resize(&sdpy);
 }
 
-static void display_refresh(struct DisplayState *ds)
+static void display_refresh(DisplayChangeListener *dcl,
+                            struct DisplayState *ds)
 {
     qemu_spice_display_refresh(&sdpy);
 }
 
-static DisplayChangeListener display_listener = {
+static const DisplayChangeListenerOps display_listener_ops = {
+    .dpy_name        = "spice",
     .dpy_gfx_update  = display_update,
     .dpy_gfx_resize  = display_resize,
-    .dpy_refresh = display_refresh,
+    .dpy_refresh     = display_refresh,
 };
 
 void qemu_spice_display_init(DisplayState *ds)
@@ -615,5 +620,7 @@ void qemu_spice_display_init(DisplayState *ds)
 
     qemu_spice_create_host_memslot(&sdpy);
     qemu_spice_create_host_primary(&sdpy);
-    register_displaychangelistener(ds, &display_listener);
+
+    sdpy.dcl.ops = &display_listener_ops;
+    register_displaychangelistener(ds, &sdpy.dcl);
 }
diff --git a/ui/vnc.c b/ui/vnc.c
index ff4e2ae..bdc3cd8 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -430,7 +430,9 @@ static void framebuffer_update_request(VncState *vs, int incremental,
 static void vnc_refresh(void *opaque);
 static int vnc_refresh_server_surface(VncDisplay *vd);
 
-static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
+static void vnc_dpy_update(DisplayChangeListener *dcl,
+                           DisplayState *ds,
+                           int x, int y, int w, int h)
 {
     int i;
     VncDisplay *vd = ds->opaque;
@@ -573,7 +575,8 @@ void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y)
     return ptr;
 }
 
-static void vnc_dpy_resize(DisplayState *ds)
+static void vnc_dpy_resize(DisplayChangeListener *dcl,
+                           DisplayState *ds)
 {
     VncDisplay *vd = ds->opaque;
     VncState *vs;
@@ -735,7 +738,10 @@ static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, i
     vnc_flush(vs);
 }
 
-static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
+static void vnc_dpy_copy(DisplayChangeListener *dcl,
+                         DisplayState *ds,
+                         int src_x, int src_y,
+                         int dst_x, int dst_y, int w, int h)
 {
     VncDisplay *vd = ds->opaque;
     VncState *vs, *vn;
@@ -806,7 +812,9 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int
     }
 }
 
-static void vnc_mouse_set(DisplayState *ds, int x, int y, int visible)
+static void vnc_mouse_set(DisplayChangeListener *dcl,
+                          DisplayState *ds,
+                          int x, int y, int visible)
 {
     /* can we ask the client(s) to move the pointer ??? */
 }
@@ -832,7 +840,9 @@ static int vnc_cursor_define(VncState *vs)
     return -1;
 }
 
-static void vnc_dpy_cursor_define(DisplayState *ds, QEMUCursor *c)
+static void vnc_dpy_cursor_define(DisplayChangeListener *dcl,
+                                  DisplayState *ds,
+                                  QEMUCursor *c)
 {
     VncDisplay *vd = vnc_display;
     VncState *vs;
@@ -1972,14 +1982,15 @@ static void pixel_format_message (VncState *vs) {
     vs->write_pixels = vnc_write_pixels_copy;
 }
 
-static void vnc_dpy_setdata(DisplayState *ds)
+static void vnc_dpy_setdata(DisplayChangeListener *dcl,
+                            DisplayState *ds)
 {
     VncDisplay *vd = ds->opaque;
 
     qemu_pixman_image_unref(vd->guest.fb);
     vd->guest.fb = pixman_image_ref(ds->surface->image);
     vd->guest.format = ds->surface->format;
-    vnc_dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
+    vnc_dpy_update(dcl, ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
 }
 
 static void vnc_colordepth(VncState *vs)
@@ -2686,7 +2697,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_ms(rt_clock, vnc_refresh, vd);
-        vnc_dpy_resize(vd->ds);
+        vnc_dpy_resize(dcl, vd->ds);
         vnc_refresh(vd);
     }
 }
@@ -2822,6 +2833,16 @@ static void vnc_listen_websocket_read(void *opaque)
 }
 #endif /* CONFIG_VNC_WS */
 
+static const DisplayChangeListenerOps dcl_ops = {
+    .dpy_name          = "vnc",
+    .dpy_gfx_copy      = vnc_dpy_copy,
+    .dpy_gfx_update    = vnc_dpy_update,
+    .dpy_gfx_resize    = vnc_dpy_resize,
+    .dpy_gfx_setdata   = vnc_dpy_setdata,
+    .dpy_mouse_set     = vnc_mouse_set,
+    .dpy_cursor_define = vnc_dpy_cursor_define,
+};
+
 void vnc_display_init(DisplayState *ds)
 {
     VncDisplay *vs = g_malloc0(sizeof(*vs));
@@ -2852,12 +2873,7 @@ void vnc_display_init(DisplayState *ds)
     qemu_mutex_init(&vs->mutex);
     vnc_start_worker_thread();
 
-    dcl->dpy_gfx_copy = vnc_dpy_copy;
-    dcl->dpy_gfx_update = vnc_dpy_update;
-    dcl->dpy_gfx_resize = vnc_dpy_resize;
-    dcl->dpy_gfx_setdata = vnc_dpy_setdata;
-    dcl->dpy_mouse_set = vnc_mouse_set;
-    dcl->dpy_cursor_define = vnc_dpy_cursor_define;
+    dcl->ops = &dcl_ops;
     register_displaychangelistener(ds, dcl);
 }
 
diff --git a/vl.c b/vl.c
index a621aec..ce51e65 100644
--- a/vl.c
+++ b/vl.c
@@ -1639,13 +1639,13 @@ void gui_setup_refresh(DisplayState *ds)
     bool have_text = false;
 
     QLIST_FOREACH(dcl, &ds->listeners, next) {
-        if (dcl->dpy_refresh != NULL) {
+        if (dcl->ops->dpy_refresh != NULL) {
             need_timer = true;
         }
-        if (dcl->dpy_gfx_update != NULL) {
+        if (dcl->ops->dpy_gfx_update != NULL) {
             have_gfx = true;
         }
-        if (dcl->dpy_text_update != NULL) {
+        if (dcl->ops->dpy_text_update != NULL) {
             have_text = true;
         }
     }
commit c45e5b5b30ac1f5505725a7b36e68cedfce4f01f
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Feb 26 17:46:11 2013 +0100

    Switch to efi-enabled nic roms by default
    
    All PCI nics are switched to EFI-enabled roms by default.  They are
    composed from three images (legacy, efi ia32 & efi x86), so classic
    pxe booting will continue to work.
    
    Exception: eepro100 is not switched, it uses a single rom for all
    emulated eepro100 variants, then goes patch the rom header on the
    fly with the correct PCI IDs.  I doubt that will work as-is with
    the efi roms.
    
    Keep old roms for 1.4+older machine types via compat properties,
    needed because the efi-enabled roms are larger so the pci rom bar
    size would change.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/e1000.c b/hw/e1000.c
index 80b6ee3..3f18041 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1378,7 +1378,7 @@ static void e1000_class_init(ObjectClass *klass, void *data)
 
     k->init = pci_e1000_init;
     k->exit = pci_e1000_uninit;
-    k->romfile = "pxe-e1000.rom";
+    k->romfile = "efi-e1000.rom";
     k->vendor_id = PCI_VENDOR_ID_INTEL;
     k->device_id = E1000_DEVID;
     k->revision = 0x03;
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 7dadc1c..7f45831 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -766,7 +766,7 @@ static void ne2000_class_init(ObjectClass *klass, void *data)
 
     k->init = pci_ne2000_init;
     k->exit = pci_ne2000_exit;
-    k->romfile = "pxe-ne2k_pci.rom",
+    k->romfile = "efi-ne2k_pci.rom",
     k->vendor_id = PCI_VENDOR_ID_REALTEK;
     k->device_id = PCI_DEVICE_ID_REALTEK_8029;
     k->class_id = PCI_CLASS_NETWORK_ETHERNET;
diff --git a/hw/pc.h b/hw/pc.h
index dbbd8cd..8e1dd4c 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -212,7 +212,7 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
             .driver   = "ide-drive",\
             .property = "discard_granularity",\
             .value    = stringify(0),\
-	},{\
+        },{\
             .driver   = "virtio-blk-pci",\
             .property = "discard_granularity",\
             .value    = stringify(0),\
@@ -221,6 +221,26 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
             .property = "vectors",\
             /* DEV_NVECTORS_UNSPECIFIED as a uint32_t string */\
             .value    = stringify(0xFFFFFFFF),\
-	}
+        },{\
+            .driver   = "e1000",\
+            .property = "romfile",\
+            .value    = "pxe-e1000.rom",\
+        },{\
+            .driver   = "ne2k_pci",\
+            .property = "romfile",\
+            .value    = "pxe-ne2k_pci.rom",\
+        },{\
+            .driver   = "pcnet",\
+            .property = "romfile",\
+            .value    = "pxe-pcnet.rom",\
+        },{\
+            .driver   = "rtl8139",\
+            .property = "romfile",\
+            .value    = "pxe-rtl8139.rom",\
+        },{\
+            .driver   = "virtio-net-pci",\
+            .property = "romfile",\
+            .value    = "pxe-virtio.rom",\
+        }
 
 #endif
diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c
index 55f80ca..61af57e 100644
--- a/hw/pcnet-pci.c
+++ b/hw/pcnet-pci.c
@@ -351,7 +351,7 @@ static void pcnet_class_init(ObjectClass *klass, void *data)
 
     k->init = pci_pcnet_init;
     k->exit = pci_pcnet_uninit;
-    k->romfile = "pxe-pcnet.rom",
+    k->romfile = "efi-pcnet.rom",
     k->vendor_id = PCI_VENDOR_ID_AMD;
     k->device_id = PCI_DEVICE_ID_AMD_LANCE;
     k->revision = 0x10;
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 786b875..9369507 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3530,7 +3530,7 @@ static void rtl8139_class_init(ObjectClass *klass, void *data)
 
     k->init = pci_rtl8139_init;
     k->exit = pci_rtl8139_uninit;
-    k->romfile = "pxe-rtl8139.rom";
+    k->romfile = "efi-rtl8139.rom";
     k->vendor_id = PCI_VENDOR_ID_REALTEK;
     k->device_id = PCI_DEVICE_ID_REALTEK_8139;
     k->revision = RTL8139_PCI_REVID; /* >=0x20 is for 8139C+ */
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 39c1966..7826535 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -1140,7 +1140,7 @@ static void virtio_net_class_init(ObjectClass *klass, void *data)
 
     k->init = virtio_net_init_pci;
     k->exit = virtio_net_exit_pci;
-    k->romfile = "pxe-virtio.rom";
+    k->romfile = "efi-virtio.rom";
     k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
     k->device_id = PCI_DEVICE_ID_VIRTIO_NET;
     k->revision = VIRTIO_PCI_ABI_VERSION;
commit 8a24d3cb9be9bca2b77a4e9eb1a62ed735af712e
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Mar 4 10:19:29 2013 +0100

    Add efi rom binaries
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/pc-bios/efi-e1000.rom b/pc-bios/efi-e1000.rom
new file mode 100644
index 0000000..7dfcea3
Binary files /dev/null and b/pc-bios/efi-e1000.rom differ
diff --git a/pc-bios/efi-eepro100.rom b/pc-bios/efi-eepro100.rom
new file mode 100644
index 0000000..e5134a2
Binary files /dev/null and b/pc-bios/efi-eepro100.rom differ
diff --git a/pc-bios/efi-ne2k_pci.rom b/pc-bios/efi-ne2k_pci.rom
new file mode 100644
index 0000000..8aa11c3
Binary files /dev/null and b/pc-bios/efi-ne2k_pci.rom differ
diff --git a/pc-bios/efi-pcnet.rom b/pc-bios/efi-pcnet.rom
new file mode 100644
index 0000000..200b5d2
Binary files /dev/null and b/pc-bios/efi-pcnet.rom differ
diff --git a/pc-bios/efi-rtl8139.rom b/pc-bios/efi-rtl8139.rom
new file mode 100644
index 0000000..8bcd3c7
Binary files /dev/null and b/pc-bios/efi-rtl8139.rom differ
diff --git a/pc-bios/efi-virtio.rom b/pc-bios/efi-virtio.rom
new file mode 100644
index 0000000..25c5c69
Binary files /dev/null and b/pc-bios/efi-virtio.rom differ
commit 2f3f430d7cca3f67ef9b539dbc008d71eb6a3bd0
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Feb 26 16:45:58 2013 +0100

    Add Makefile rules to build nic rom binaries with efi support
    
    "make -C roms efirom" will build rom binaries with EFI support.
    They are composed from three images: legacy bios, efi ia32
    and efi x64.  So netbooting via SeaBIOS will continue to work
    like it does today, and additionally we get network support
    for EFI.  This target needs the EfiRom utility (shipped with
    edk2) somewhere in the $PATH.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/roms/Makefile b/roms/Makefile
index be33652..3dc5609 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -2,18 +2,29 @@
 vgabios_variants := stdvga cirrus vmware qxl
 pxerom_variants  := e1000 eepro100 ne2k_pci pcnet rtl8139 virtio
 
-pxe-rom-e1000    : VID := 8086
-pxe-rom-e1000    : DID := 100e
-pxe-rom-eepro100 : VID := 8086
-pxe-rom-eepro100 : DID := 1209
-pxe-rom-ne2k_pci : VID := 1050
-pxe-rom-ne2k_pci : DID := 0940
-pxe-rom-pcnet    : VID := 1022
-pxe-rom-pcnet    : DID := 2000
-pxe-rom-rtl8139  : VID := 10ec
-pxe-rom-rtl8139  : DID := 8139
-pxe-rom-virtio   : VID := 1af4
-pxe-rom-virtio   : DID := 1000
+pxe-rom-e1000    efi-rom-e1000    : VID := 8086
+pxe-rom-e1000    efi-rom-e1000    : DID := 100e
+pxe-rom-eepro100 efi-rom-eepro100 : VID := 8086
+pxe-rom-eepro100 efi-rom-eepro100 : DID := 1209
+pxe-rom-ne2k_pci efi-rom-ne2k_pci : VID := 1050
+pxe-rom-ne2k_pci efi-rom-ne2k_pci : DID := 0940
+pxe-rom-pcnet    efi-rom-pcnet    : VID := 1022
+pxe-rom-pcnet    efi-rom-pcnet    : DID := 2000
+pxe-rom-rtl8139  efi-rom-rtl8139  : VID := 10ec
+pxe-rom-rtl8139  efi-rom-rtl8139  : DID := 8139
+pxe-rom-virtio   efi-rom-virtio   : VID := 1af4
+pxe-rom-virtio   efi-rom-virtio   : DID := 1000
+
+#
+# EfiRom utility is shipped with edk2 / tianocore, in BaseTools/
+#
+# We need that to combine multiple images (legacy bios,
+# efi ia32, efi x64) into a single rom binary.
+#
+# We try to find it in the path.  You can also pass the location on
+# the command line, i.e. "make EFIROM=/path/to/EfiRom efirom"
+#
+EFIROM ?= $(shell which EfiRom 2>/dev/null)
 
 default:
 	@echo "nothing is build by default"
@@ -22,6 +33,8 @@ default:
 	@echo "  seavgabios     -- update vgabios binaries (seabios)"
 	@echo "  lgplvgabios    -- update vgabios binaries (lgpl)"
 	@echo "  pxerom         -- update nic roms (bios only)"
+	@echo "  efirom         -- update nic roms (bios+efi, this needs"
+	@echo "                    the EfiRom utility from edk2 / tianocore)"
 
 bios: config.seabios
 	sh configure-seabios.sh $<
@@ -47,3 +60,15 @@ pxerom: $(patsubst %,pxe-rom-%,$(pxerom_variants))
 pxe-rom-%:
 	make -C ipxe/src bin/$(VID)$(DID).rom
 	cp ipxe/src/bin/$(VID)$(DID).rom ../pc-bios/pxe-$*.rom
+
+efirom: $(patsubst %,efi-rom-%,$(pxerom_variants))
+
+efi-rom-%:
+	make -C ipxe/src bin/$(VID)$(DID).rom
+	make -C ipxe/src bin-i386-efi/$(VID)$(DID).efidrv
+	make -C ipxe/src bin-x86_64-efi/$(VID)$(DID).efidrv
+	$(EFIROM) -f "0x$(VID)" -i "0x$(DID)" -l 0x02 \
+		-b ipxe/src/bin/$(VID)$(DID).rom \
+		-ec ipxe/src/bin-i386-efi/$(VID)$(DID).efidrv \
+		-ec ipxe/src/bin-x86_64-efi/$(VID)$(DID).efidrv \
+		-o ../pc-bios/efi-$*.rom
commit c3d8dab3298c64267411fb470e3d1e18871a359b
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 28 09:14:12 2013 +0100

    Update ipxe submodule to latest master
    
    Needed for efi support.
    
    ipxe is grown a bit, so *not* recompiling the (non-efi) pxe roms
    because that would make some pxe roms larger than 64k, which in
    turn would be a guest-visible change because the rom bar size
    grows from 64k to 128k.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/roms/ipxe b/roms/ipxe
index 7aee315..09c5109 160000
--- a/roms/ipxe
+++ b/roms/ipxe
@@ -1 +1 @@
-Subproject commit 7aee315f61aaf1be6d2fff26339f28a1137231a5
+Subproject commit 09c5109b8585178172c7608de8d52e9d9af0b680
commit 2397edd7354ebbcebf3cd55dc3c0b1fe7621794b
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Feb 8 16:35:08 2013 +0100

    Add Makefile rules to build nic rom binaries
    
    "make -C roms pxerom" will build the ipxe roms and update
    the binaries in pc-bios/, i.e. it basically documents how
    the build process of our current nic roms works.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/roms/Makefile b/roms/Makefile
index 5e645bc..be33652 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -1,5 +1,19 @@
 
 vgabios_variants := stdvga cirrus vmware qxl
+pxerom_variants  := e1000 eepro100 ne2k_pci pcnet rtl8139 virtio
+
+pxe-rom-e1000    : VID := 8086
+pxe-rom-e1000    : DID := 100e
+pxe-rom-eepro100 : VID := 8086
+pxe-rom-eepro100 : DID := 1209
+pxe-rom-ne2k_pci : VID := 1050
+pxe-rom-ne2k_pci : DID := 0940
+pxe-rom-pcnet    : VID := 1022
+pxe-rom-pcnet    : DID := 2000
+pxe-rom-rtl8139  : VID := 10ec
+pxe-rom-rtl8139  : DID := 8139
+pxe-rom-virtio   : VID := 1af4
+pxe-rom-virtio   : DID := 1000
 
 default:
 	@echo "nothing is build by default"
@@ -7,6 +21,7 @@ default:
 	@echo "  bios           -- update bios.bin (seabios)"
 	@echo "  seavgabios     -- update vgabios binaries (seabios)"
 	@echo "  lgplvgabios    -- update vgabios binaries (lgpl)"
+	@echo "  pxerom         -- update nic roms (bios only)"
 
 bios: config.seabios
 	sh configure-seabios.sh $<
@@ -26,3 +41,9 @@ lgplvgabios: $(patsubst %,lgplvgabios-%,$(vgabios_variants))
 lgplvgabios-%:
 	make -C vgabios vgabios-$*.bin
 	cp vgabios/VGABIOS-lgpl-latest.$*.bin ../pc-bios/vgabios-$*.bin
+
+pxerom: $(patsubst %,pxe-rom-%,$(pxerom_variants))
+
+pxe-rom-%:
+	make -C ipxe/src bin/$(VID)$(DID).rom
+	cp ipxe/src/bin/$(VID)$(DID).rom ../pc-bios/pxe-$*.rom
commit 225dc991b03f0f034aa348f5cf499de9d0979107
Author: Cornelia Huck <cornelia.huck at de.ibm.com>
Date:   Fri Mar 15 10:57:40 2013 +0100

    s390: Fix cpu refactoring fallout.
    
    Commit 259186a7 "cpu: Move halted and interrupt_request fields to CPUState"
    seems to have missed one instance in target-s390x/kvm.c:
    
    /home/cohuck/git/qemu/target-s390x/kvm.c: In function ‘kvm_arch_process_async_events’:
    /home/cohuck/git/qemu/target-s390x/kvm.c:319: error: ‘CPUS390XState’ has no member named ‘halted’
    /home/cohuck/git/qemu/target-s390x/kvm.c:320: warning: control reaches end of non-void function
    make[1]: *** [target-s390x/kvm.o] Error 1
    
    Let's just switch to cs->halted.
    
    Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Acked-by: Alexander Graf <agraf at suse.de>
    Acked-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 8f111ae..644f484 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -315,8 +315,7 @@ void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run)
 
 int kvm_arch_process_async_events(CPUState *cs)
 {
-    S390CPU *cpu = S390_CPU(cs);
-    return cpu->env.halted;
+    return cs->halted;
 }
 
 void kvm_s390_interrupt_internal(S390CPU *cpu, int type, uint32_t parm,
commit 7fb7377594887db99a2100adcddf3bd6394ef540
Merge: 8b758d0 f8b9fe2
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Mar 17 17:44:47 2013 +0000

    Merge branch 'arm-devs.next' of git://git.linaro.org/people/pmaydell/qemu-arm
    
    * 'arm-devs.next' of git://git.linaro.org/people/pmaydell/qemu-arm:
      xilinx_spips: QOM styling fixes
      xilinx_spips: Add missing dual-bus snoop commands
      xilinx_spips: Fix bus setup conditional check
      xilinx_spips: Set unused IRQs to NULL
      xilinx_zynq: added pl330 to machine model
      pl330: Initial version
      iov: Factor out hexdumper
      hw/vexpress: Set reset values for daughterboard oscillators
      hw/arm_sysctl: Implement SYS_CFG_OSC function
      hw/vexpress: Pass voltage sensor properties to sysctl device
      hw/arm_sysctl: Implement SYS_CFG_VOLT
      qdev: Implement (variable length) array properties
      hw/arm_sysctl: Convert from qdev init to instance_init
      hw/arm_sysctl: Implement SYS_CFG_DVIMODE as a no-op
      hw/arm_sysctl: Implement SYS_CFG_MUXFPGA writes as a no-op
      hw/arm_sysctl: Handle SYS_CFGCTRL in a more structured way
      hw/vexpress: Pass proc_id via VEDBoardInfo

commit 0402a5d65ec004df5345d1f736e2ddaa7aee6665
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Mar 6 14:58:59 2013 +0200

    qdev: DEVICE_DELETED event
    
    libvirt has a long-standing bug: when removing the device,
    it can request removal but does not know when the
    removal completes. Add an event so we can fix this in a robust way.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt
index b2698e4..24cf3e8 100644
--- a/QMP/qmp-events.txt
+++ b/QMP/qmp-events.txt
@@ -136,6 +136,22 @@ Example:
 Note: The "ready to complete" status is always reset by a BLOCK_JOB_ERROR
 event.
 
+DEVICE_DELETED
+-----------------
+
+Emitted whenever the device removal completion is acknowledged
+by the guest.
+At this point, it's safe to reuse the specified device ID.
+Device removal can be initiated by the guest or by HMP/QMP commands.
+
+Data:
+
+- "device": device name (json-string, optional)
+
+{ "event": "DEVICE_DELETED",
+  "data": { "device": "virtio-net-pci-0" },
+  "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
+
 DEVICE_TRAY_MOVED
 -----------------
 
diff --git a/hw/qdev.c b/hw/qdev.c
index 0b20280..5e8a89c 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -30,6 +30,8 @@
 #include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
 #include "qapi/visitor.h"
+#include "qapi/qmp/qjson.h"
+#include "monitor/monitor.h"
 
 int qdev_hotplug = 0;
 static bool qdev_hot_added = false;
@@ -761,6 +763,7 @@ static void device_unparent(Object *obj)
     DeviceState *dev = DEVICE(obj);
     DeviceClass *dc = DEVICE_GET_CLASS(dev);
     BusState *bus;
+    QObject *event_data;
 
     while (dev->num_child_bus) {
         bus = QLIST_FIRST(&dev->child_bus);
@@ -779,6 +782,14 @@ static void device_unparent(Object *obj)
         object_unref(OBJECT(dev->parent_bus));
         dev->parent_bus = NULL;
     }
+
+    if (dev->id) {
+        event_data = qobject_from_jsonf("{ 'device': %s }", dev->id);
+    } else {
+        event_data = qobject_from_jsonf("{ }");
+    }
+    monitor_protocol_event(QEVENT_DEVICE_DELETED, event_data);
+    qobject_decref(event_data);
 }
 
 static void device_class_init(ObjectClass *class, void *data)
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index 87fb49c..b868760 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -39,6 +39,7 @@ typedef enum MonitorEvent {
     QEVENT_BLOCK_JOB_CANCELLED,
     QEVENT_BLOCK_JOB_ERROR,
     QEVENT_BLOCK_JOB_READY,
+    QEVENT_DEVICE_DELETED,
     QEVENT_DEVICE_TRAY_MOVED,
     QEVENT_SUSPEND,
     QEVENT_SUSPEND_DISK,
diff --git a/monitor.c b/monitor.c
index 112e920..2fdfb79 100644
--- a/monitor.c
+++ b/monitor.c
@@ -458,6 +458,7 @@ static const char *monitor_event_names[] = {
     [QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED",
     [QEVENT_BLOCK_JOB_ERROR] = "BLOCK_JOB_ERROR",
     [QEVENT_BLOCK_JOB_READY] = "BLOCK_JOB_READY",
+    [QEVENT_DEVICE_DELETED] = "DEVICE_DELETED",
     [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED",
     [QEVENT_SUSPEND] = "SUSPEND",
     [QEVENT_SUSPEND_DISK] = "SUSPEND_DISK",
diff --git a/qapi-schema.json b/qapi-schema.json
index fdaa9da..080dc39 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2354,7 +2354,9 @@
 # Notes: When this command completes, the device may not be removed from the
 #        guest.  Hot removal is an operation that requires guest cooperation.
 #        This command merely requests that the guest begin the hot removal
-#        process.
+#        process.  Completion of the device removal process is signaled with a
+#        DEVICE_DELETED event. Guest reset will automatically complete removal
+#        for all devices.
 #
 # Since: 0.14.0
 ##
commit 8b758d0568a986d58c254b3c209691c82e0f82a1
Author: Petar Jovanovic <petar.jovanovic at imgtec.com>
Date:   Fri Mar 15 18:56:19 2013 +0100

    target-mips: fix rndrashift_short_acc and code for EXTR_ instructions
    
    Fix for rndrashift_short_acc to set correct value to higher 64 bits.
    This change also corrects conditions when bit 23 of the DSPControl register
    is set.
    
    The existing test files have been extended with several examples that
    trigger the issues. One bug/example in the test file for EXTR_RS_W has been
    found and reported by Klaus Peichl.
    
    Signed-off-by: Petar Jovanovic <petar.jovanovic at imgtec.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 472be35..c7df595 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -517,13 +517,8 @@ static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
 
     acc = ((int64_t)env->active_tc.HI[ac] << 32) |
           ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
-    if (shift == 0) {
-        p[0] = acc << 1;
-        p[1] = (acc >> 63) & 0x01;
-    } else {
-        p[0] = acc >> (shift - 1);
-        p[1] = 0;
-    }
+    p[0] = (shift == 0) ? (acc << 1) : (acc >> (shift - 1));
+    p[1] = (acc >> 63) & 0x01;
 }
 
 /* 128 bits long. p[0] is LO, p[1] is HI */
@@ -3161,8 +3156,8 @@ target_ulong helper_extr_w(target_ulong ac, target_ulong shift,
         tempDL[1] += 1;
     }
 
-    if ((!(tempDL[1] == 0 && (tempDL[0] & MIPSDSP_LHI) == 0x00)) &&
-        (!(tempDL[1] == 1 && (tempDL[0] & MIPSDSP_LHI) == MIPSDSP_LHI))) {
+    if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
         set_DSPControl_overflow_flag(1, 23, env);
     }
 
@@ -3187,8 +3182,8 @@ target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift,
         tempDL[1] += 1;
     }
 
-    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
-        (tempDL[1] != 1 && (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+    if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
         set_DSPControl_overflow_flag(1, 23, env);
     }
 
@@ -3214,9 +3209,9 @@ target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift,
     }
     tempI = tempDL[0] >> 1;
 
-    if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
-        (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
-        temp64 = tempDL[1];
+    if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
+        ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+        temp64 = tempDL[1] & 0x01;
         if (temp64 == 0) {
             tempI = 0x7FFFFFFF;
         } else {
diff --git a/tests/tcg/mips/mips32-dsp/extr_r_w.c b/tests/tcg/mips/mips32-dsp/extr_r_w.c
index 02e0224..489c193 100644
--- a/tests/tcg/mips/mips32-dsp/extr_r_w.c
+++ b/tests/tcg/mips/mips32-dsp/extr_r_w.c
@@ -67,5 +67,28 @@ int main()
     assert(dsp == 0);
     assert(result == rt);
 
+    /* Clear dspcontrol */
+    dsp = 0;
+    __asm
+        ("wrdsp %0\n\t"
+         :
+         : "r"(dsp)
+        );
+
+    ach = 0xFFFFFFFF;
+    acl = 0xFFFFFFFF;
+    result = 0;
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extr_r.w %0, $ac1, 0x1F\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(ach), "r"(acl)
+         );
+    dsp = (dsp >> 23) & 0x01;
+    assert(dsp == 0);
+    assert(result == rt);
+
     return 0;
 }
diff --git a/tests/tcg/mips/mips32-dsp/extr_rs_w.c b/tests/tcg/mips/mips32-dsp/extr_rs_w.c
index c3a22ee..f9d2ed6 100644
--- a/tests/tcg/mips/mips32-dsp/extr_rs_w.c
+++ b/tests/tcg/mips/mips32-dsp/extr_rs_w.c
@@ -67,5 +67,51 @@ int main()
     assert(dsp == 0);
     assert(result == rt);
 
+    /* Clear dspcontrol */
+    dsp = 0;
+    __asm
+        ("wrdsp %0\n\t"
+         :
+         : "r"(dsp)
+        );
+
+    ach = 0x80000000;
+    acl = 0x00000000;
+    result = 0x80000000;
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extr_rs.w %0, $ac1, 0x1F\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(ach), "r"(acl)
+        );
+    dsp = (dsp >> 23) & 0x01;
+    assert(dsp == 1);
+    assert(result == rt);
+
+    /* Clear dspcontrol */
+    dsp = 0;
+    __asm
+        ("wrdsp %0\n\t"
+         :
+         : "r"(dsp)
+        );
+
+    ach = 0xFFFFFFFF;
+    acl = 0xFFFFFFFF;
+    result = 0;
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extr_rs.w %0, $ac1, 0x1F\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(ach), "r"(acl)
+         );
+    dsp = (dsp >> 23) & 0x01;
+    assert(dsp == 0);
+    assert(result == rt);
+
     return 0;
 }
diff --git a/tests/tcg/mips/mips32-dsp/extr_w.c b/tests/tcg/mips/mips32-dsp/extr_w.c
index bd6b0b9..cf92614 100644
--- a/tests/tcg/mips/mips32-dsp/extr_w.c
+++ b/tests/tcg/mips/mips32-dsp/extr_w.c
@@ -67,5 +67,28 @@ int main()
     assert(dsp == 0);
     assert(result == rt);
 
+    /* Clear dspcontrol */
+    dsp = 0;
+    __asm
+        ("wrdsp %0\n\t"
+         :
+         : "r"(dsp)
+        );
+
+    ach = 0xFFFFFFFF;
+    acl = 0xFFFFFFFF;
+    result = 0xFFFFFFFF;
+    __asm
+        ("mthi %2, $ac1\n\t"
+         "mtlo %3, $ac1\n\t"
+         "extr.w %0, $ac1, 0x1F\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rt), "=r"(dsp)
+         : "r"(ach), "r"(acl)
+         );
+    dsp = (dsp >> 23) & 0x01;
+    assert(dsp == 0);
+    assert(result == rt);
+
     return 0;
 }
commit f8b9fe249a706bfed61e0bb66c73394553696382
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Fri Mar 15 16:41:59 2013 +0000

    xilinx_spips: QOM styling fixes
    
    Few fixes for the latest QOM styling guides.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: de9daeee6c142e8b57ad042fd680cedcdc94d2fc.1362373359.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c
index 3183f7a..b2397f4 100644
--- a/hw/xilinx_spips.c
+++ b/hw/xilinx_spips.c
@@ -154,6 +154,11 @@ typedef struct {
     hwaddr lqspi_cached_addr;
 } XilinxSPIPS;
 
+#define TYPE_XILINX_SPIPS "xilinx,spips"
+
+#define XILINX_SPIPS(obj) \
+     OBJECT_CHECK(XilinxSPIPS, (obj), TYPE_XILINX_SPIPS)
+
 static inline int num_effective_busses(XilinxSPIPS *s)
 {
     return (s->regs[R_LQSPI_CFG] & LQSPI_CFG_SEP_BUS &&
@@ -210,7 +215,7 @@ static void xilinx_spips_update_ixr(XilinxSPIPS *s)
 
 static void xilinx_spips_reset(DeviceState *d)
 {
-    XilinxSPIPS *s = DO_UPCAST(XilinxSPIPS, busdev.qdev, d);
+    XilinxSPIPS *s = XILINX_SPIPS(d);
 
     int i;
     for (i = 0; i < R_MAX; i++) {
@@ -500,9 +505,10 @@ static const MemoryRegionOps lqspi_ops = {
     }
 };
 
-static int xilinx_spips_init(SysBusDevice *dev)
+static void xilinx_spips_realize(DeviceState *dev, Error **errp)
 {
-    XilinxSPIPS *s = FROM_SYSBUS(typeof(*s), dev);
+    XilinxSPIPS *s = XILINX_SPIPS(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     int i;
 
     DB_PRINT("inited device model\n");
@@ -511,31 +517,29 @@ static int xilinx_spips_init(SysBusDevice *dev)
     for (i = 0; i < s->num_busses; ++i) {
         char bus_name[16];
         snprintf(bus_name, 16, "spi%d", i);
-        s->spi[i] = ssi_create_bus(&dev->qdev, bus_name);
+        s->spi[i] = ssi_create_bus(dev, bus_name);
     }
 
     s->cs_lines = g_new0(qemu_irq, s->num_cs * s->num_busses);
     ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[0]);
     ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[1]);
-    sysbus_init_irq(dev, &s->irq);
+    sysbus_init_irq(sbd, &s->irq);
     for (i = 0; i < s->num_cs * s->num_busses; ++i) {
-        sysbus_init_irq(dev, &s->cs_lines[i]);
+        sysbus_init_irq(sbd, &s->cs_lines[i]);
     }
 
     memory_region_init_io(&s->iomem, &spips_ops, s, "spi", R_MAX*4);
-    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_mmio(sbd, &s->iomem);
 
     memory_region_init_io(&s->mmlqspi, &lqspi_ops, s, "lqspi",
                           (1 << LQSPI_ADDRESS_BITS) * 2);
-    sysbus_init_mmio(dev, &s->mmlqspi);
+    sysbus_init_mmio(sbd, &s->mmlqspi);
 
     s->irqline = -1;
     s->lqspi_cached_addr = ~0ULL;
 
     fifo8_create(&s->rx_fifo, RXFF_A);
     fifo8_create(&s->tx_fifo, TXFF_A);
-
-    return 0;
 }
 
 static int xilinx_spips_post_load(void *opaque, int version_id)
@@ -569,16 +573,15 @@ static Property xilinx_spips_properties[] = {
 static void xilinx_spips_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
 
-    sdc->init = xilinx_spips_init;
+    dc->realize = xilinx_spips_realize;
     dc->reset = xilinx_spips_reset;
     dc->props = xilinx_spips_properties;
     dc->vmsd = &vmstate_xilinx_spips;
 }
 
 static const TypeInfo xilinx_spips_info = {
-    .name  = "xilinx,spips",
+    .name  = TYPE_XILINX_SPIPS,
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size  = sizeof(XilinxSPIPS),
     .class_init = xilinx_spips_class_init,
commit 08a9635b68757e18a6a8bf8569353b40bb6c1fd1
Author: Nathan Rossi <nathan.rossi at xilinx.com>
Date:   Fri Mar 15 16:41:59 2013 +0000

    xilinx_spips: Add missing dual-bus snoop commands
    
    Added additional commands to the switch to check for when snooping commands in
    dual bus mode setups. Cleaned up code to use an enum.
    
    Signed-off-by: Nathan Rossi <nathan.rossi at xilinx.com>
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 848c116c711dab0af10729a487968384aadd9faf.1362373359.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c
index efa1449..3183f7a 100644
--- a/hw/xilinx_spips.c
+++ b/hw/xilinx_spips.c
@@ -115,6 +115,19 @@
 #define SNOOP_NONE 0xFE
 #define SNOOP_STRIPING 0
 
+typedef enum {
+    READ = 0x3,
+    FAST_READ = 0xb,
+    DOR = 0x3b,
+    QOR = 0x6b,
+    DIOR = 0xbb,
+    QIOR = 0xeb,
+
+    PP = 0x2,
+    DPP = 0xa2,
+    QPP = 0x32,
+} FlashCMD;
+
 typedef struct {
     SysBusDevice busdev;
     MemoryRegion iomem;
@@ -251,15 +264,19 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
         switch (s->snoop_state) {
         case (SNOOP_CHECKING):
             switch (tx) { /* new instruction code */
-            case 0x0b: /* dual/quad output read DOR/QOR */
-            case 0x6b:
-                s->snoop_state = 4;
+            case READ: /* 3 address bytes, no dummy bytes/cycles */
+            case PP:
+            case DPP:
+            case QPP:
+                s->snoop_state = 3;
                 break;
-            /* FIXME: these vary between vendor - set to spansion */
-            case 0xbb: /* high performance dual read DIOR */
+            case FAST_READ: /* 3 address bytes, 1 dummy byte */
+            case DOR:
+            case QOR:
+            case DIOR: /* FIXME: these vary between vendor - set to spansion */
                 s->snoop_state = 4;
                 break;
-            case 0xeb: /* high performance quad read QIOR */
+            case QIOR: /* 3 address bytes, 2 dummy bytes */
                 s->snoop_state = 6;
                 break;
             default:
commit e0891bd8bfd3349fc3fecde30e51900059f53f11
Author: Nathan Rossi <nathan.rossi at xilinx.com>
Date:   Fri Mar 15 16:41:59 2013 +0000

    xilinx_spips: Fix bus setup conditional check
    
    The R_LQPSI_CFG register has the LQSPI_CFG_SEP_BUS and LQSPI_CFG_TWO_MEM bits.
    
    Signed-off-by: Nathan Rossi <nathan.rossi at xilinx.com>
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: d76c8e364c80a42352ae4f0661aff2cd17ad32a4.1362373359.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c
index 853f4e0..efa1449 100644
--- a/hw/xilinx_spips.c
+++ b/hw/xilinx_spips.c
@@ -143,8 +143,8 @@ typedef struct {
 
 static inline int num_effective_busses(XilinxSPIPS *s)
 {
-    return (s->regs[R_LQSPI_STS] & LQSPI_CFG_SEP_BUS &&
-            s->regs[R_LQSPI_STS] & LQSPI_CFG_TWO_MEM) ? s->num_busses : 1;
+    return (s->regs[R_LQSPI_CFG] & LQSPI_CFG_SEP_BUS &&
+            s->regs[R_LQSPI_CFG] & LQSPI_CFG_TWO_MEM) ? s->num_busses : 1;
 }
 
 static void xilinx_spips_update_cs_lines(XilinxSPIPS *s)
commit 2790cd911e563f7fec7eeb7856b7f5f54437cc0a
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Fri Mar 15 16:41:58 2013 +0000

    xilinx_spips: Set unused IRQs to NULL
    
    Unused CS lines should init to 0 to avoid segfaulting when accessing an
    unattached QSPI controller.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: c1e45198032106e69e8fe9339fc2e6348d524fcd.1362373359.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c
index 6c21b96..853f4e0 100644
--- a/hw/xilinx_spips.c
+++ b/hw/xilinx_spips.c
@@ -497,7 +497,7 @@ static int xilinx_spips_init(SysBusDevice *dev)
         s->spi[i] = ssi_create_bus(&dev->qdev, bus_name);
     }
 
-    s->cs_lines = g_new(qemu_irq, s->num_cs * s->num_busses);
+    s->cs_lines = g_new0(qemu_irq, s->num_cs * s->num_busses);
     ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[0]);
     ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[1]);
     sysbus_init_irq(dev, &s->irq);
commit 7451afb67136275f2461f2d23139f2abed1f15b3
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Fri Mar 15 16:41:58 2013 +0000

    xilinx_zynq: added pl330 to machine model
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 5bc295bd2aa50dfe573f428574dbd7d8add7b3f8.1361853677.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index f78c47e..6f36286 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -35,6 +35,10 @@
 
 #define IRQ_OFFSET 32 /* pic interrupts start from index 32 */
 
+static const int dma_irqs[8] = {
+    46, 47, 48, 49, 72, 73, 74, 75
+};
+
 static struct arm_boot_info zynq_binfo = {};
 
 static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
@@ -196,6 +200,26 @@ static void zynq_init(QEMUMachineInitArgs *args)
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000);
     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]);
 
+    dev = qdev_create(NULL, "pl330");
+    qdev_prop_set_uint8(dev, "num_chnls",  8);
+    qdev_prop_set_uint8(dev, "num_periph_req",  4);
+    qdev_prop_set_uint8(dev, "num_events",  16);
+
+    qdev_prop_set_uint8(dev, "data_width",  64);
+    qdev_prop_set_uint8(dev, "wr_cap",  8);
+    qdev_prop_set_uint8(dev, "wr_q_dep",  16);
+    qdev_prop_set_uint8(dev, "rd_cap",  8);
+    qdev_prop_set_uint8(dev, "rd_q_dep",  16);
+    qdev_prop_set_uint16(dev, "data_buffer_dep",  256);
+
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, 0xF8003000);
+    sysbus_connect_irq(busdev, 0, pic[45-IRQ_OFFSET]); /* abort irq line */
+    for (n = 0; n < 8; ++n) { /* event irqs */
+        sysbus_connect_irq(busdev, n + 1, pic[dma_irqs[n] - IRQ_OFFSET]);
+    }
+
     zynq_binfo.ram_size = ram_size;
     zynq_binfo.kernel_filename = kernel_filename;
     zynq_binfo.kernel_cmdline = kernel_cmdline;
commit 06a1cea5f631f6ac69f85ae07bb47ef47b88f5f7
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Fri Mar 15 16:41:58 2013 +0000

    pl330: Initial version
    
    Device model for Primecell PL330 DMA controller.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Kirill Batuzov <batuzovk at ispras.ru>
    Tested-by: Igor Mitsyanko <i.mitsyanko at samsung.com>
    Reviewed-by: Igor Mitsyanko <i.mitsyanko at samsung.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 098aac26233d7334bed2bca4f06f539638ca6d24.1361853677.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 68b2045..ab87035 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -42,6 +42,7 @@ CONFIG_PL110=y
 CONFIG_PL181=y
 CONFIG_PL190=y
 CONFIG_PL310=y
+CONFIG_PL330=y
 CONFIG_CADENCE=y
 CONFIG_XGMAC=y
 
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index eb7eb31..11812c6 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -98,6 +98,7 @@ common-obj-$(CONFIG_PL110) += pl110.o
 common-obj-$(CONFIG_PL181) += pl181.o
 common-obj-$(CONFIG_PL190) += pl190.o
 common-obj-$(CONFIG_PL310) += arm_l2x0.o
+common-obj-$(CONFIG_PL330) += pl330.o
 common-obj-$(CONFIG_VERSATILE_PCI) += versatile_pci.o
 common-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o
 common-obj-$(CONFIG_CADENCE) += cadence_uart.o
diff --git a/hw/pl330.c b/hw/pl330.c
new file mode 100644
index 0000000..1a04773
--- /dev/null
+++ b/hw/pl330.c
@@ -0,0 +1,1654 @@
+/*
+ * ARM PrimeCell PL330 DMA Controller
+ *
+ * Copyright (c) 2009 Samsung Electronics.
+ * Contributed by Kirill Batuzov <batuzovk at ispras.ru>
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite at petalogix.com)
+ * Copyright (c) 2012 PetaLogix Pty Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 or later.
+ *
+ * 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 "qemu/timer.h"
+#include "sysemu/dma.h"
+
+#ifndef PL330_ERR_DEBUG
+#define PL330_ERR_DEBUG 0
+#endif
+
+#define DB_PRINT_L(lvl, fmt, args...) do {\
+    if (PL330_ERR_DEBUG >= lvl) {\
+        fprintf(stderr, "PL330: %s:" fmt, __func__, ## args);\
+    } \
+} while (0);
+
+#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
+
+#define PL330_PERIPH_NUM            32
+#define PL330_MAX_BURST_LEN         128
+#define PL330_INSN_MAXSIZE          6
+
+#define PL330_FIFO_OK               0
+#define PL330_FIFO_STALL            1
+#define PL330_FIFO_ERR              (-1)
+
+#define PL330_FAULT_UNDEF_INSTR             (1 <<  0)
+#define PL330_FAULT_OPERAND_INVALID         (1 <<  1)
+#define PL330_FAULT_DMAGO_ERR               (1 <<  4)
+#define PL330_FAULT_EVENT_ERR               (1 <<  5)
+#define PL330_FAULT_CH_PERIPH_ERR           (1 <<  6)
+#define PL330_FAULT_CH_RDWR_ERR             (1 <<  7)
+#define PL330_FAULT_ST_DATA_UNAVAILABLE     (1 << 12)
+#define PL330_FAULT_FIFOEMPTY_ERR           (1 << 13)
+#define PL330_FAULT_INSTR_FETCH_ERR         (1 << 16)
+#define PL330_FAULT_DATA_WRITE_ERR          (1 << 17)
+#define PL330_FAULT_DATA_READ_ERR           (1 << 18)
+#define PL330_FAULT_DBG_INSTR               (1 << 30)
+#define PL330_FAULT_LOCKUP_ERR              (1 << 31)
+
+#define PL330_UNTAGGED              0xff
+
+#define PL330_SINGLE                0x0
+#define PL330_BURST                 0x1
+
+#define PL330_WATCHDOG_LIMIT        1024
+
+/* IOMEM mapped registers */
+#define PL330_REG_DSR               0x000
+#define PL330_REG_DPC               0x004
+#define PL330_REG_INTEN             0x020
+#define PL330_REG_INT_EVENT_RIS     0x024
+#define PL330_REG_INTMIS            0x028
+#define PL330_REG_INTCLR            0x02C
+#define PL330_REG_FSRD              0x030
+#define PL330_REG_FSRC              0x034
+#define PL330_REG_FTRD              0x038
+#define PL330_REG_FTR_BASE          0x040
+#define PL330_REG_CSR_BASE          0x100
+#define PL330_REG_CPC_BASE          0x104
+#define PL330_REG_CHANCTRL          0x400
+#define PL330_REG_DBGSTATUS         0xD00
+#define PL330_REG_DBGCMD            0xD04
+#define PL330_REG_DBGINST0          0xD08
+#define PL330_REG_DBGINST1          0xD0C
+#define PL330_REG_CR0_BASE          0xE00
+#define PL330_REG_PERIPH_ID         0xFE0
+
+#define PL330_IOMEM_SIZE    0x1000
+
+#define CFG_BOOT_ADDR 2
+#define CFG_INS 3
+#define CFG_PNS 4
+#define CFG_CRD 5
+
+static const uint32_t pl330_id[] = {
+    0x30, 0x13, 0x24, 0x00, 0x0D, 0xF0, 0x05, 0xB1
+};
+
+/* DMA channel states as they are described in PL330 Technical Reference Manual
+ * Most of them will not be used in emulation.
+ */
+typedef enum  {
+    pl330_chan_stopped = 0,
+    pl330_chan_executing = 1,
+    pl330_chan_cache_miss = 2,
+    pl330_chan_updating_pc = 3,
+    pl330_chan_waiting_event = 4,
+    pl330_chan_at_barrier = 5,
+    pl330_chan_queue_busy = 6,
+    pl330_chan_waiting_periph = 7,
+    pl330_chan_killing = 8,
+    pl330_chan_completing = 9,
+    pl330_chan_fault_completing = 14,
+    pl330_chan_fault = 15,
+} PL330ChanState;
+
+typedef struct PL330State PL330State;
+
+typedef struct PL330Chan {
+    uint32_t src;
+    uint32_t dst;
+    uint32_t pc;
+    uint32_t control;
+    uint32_t status;
+    uint32_t lc[2];
+    uint32_t fault_type;
+    uint32_t watchdog_timer;
+
+    bool ns;
+    uint8_t request_flag;
+    uint8_t wakeup;
+    uint8_t wfp_sbp;
+
+    uint8_t state;
+    uint8_t stall;
+
+    bool is_manager;
+    PL330State *parent;
+    uint8_t tag;
+} PL330Chan;
+
+static const VMStateDescription vmstate_pl330_chan = {
+    .name = "pl330_chan",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(src, PL330Chan),
+        VMSTATE_UINT32(dst, PL330Chan),
+        VMSTATE_UINT32(pc, PL330Chan),
+        VMSTATE_UINT32(control, PL330Chan),
+        VMSTATE_UINT32(status, PL330Chan),
+        VMSTATE_UINT32_ARRAY(lc, PL330Chan, 2),
+        VMSTATE_UINT32(fault_type, PL330Chan),
+        VMSTATE_UINT32(watchdog_timer, PL330Chan),
+        VMSTATE_BOOL(ns, PL330Chan),
+        VMSTATE_UINT8(request_flag, PL330Chan),
+        VMSTATE_UINT8(wakeup, PL330Chan),
+        VMSTATE_UINT8(wfp_sbp, PL330Chan),
+        VMSTATE_UINT8(state, PL330Chan),
+        VMSTATE_UINT8(stall, PL330Chan),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+typedef struct PL330Fifo {
+    uint8_t *buf;
+    uint8_t *tag;
+    uint32_t head;
+    uint32_t num;
+    uint32_t buf_size;
+} PL330Fifo;
+
+static const VMStateDescription vmstate_pl330_fifo = {
+    .name = "pl330_chan",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_VBUFFER_UINT32(buf, PL330Fifo, 1, NULL, 0, buf_size),
+        VMSTATE_VBUFFER_UINT32(tag, PL330Fifo, 1, NULL, 0, buf_size),
+        VMSTATE_UINT32(head, PL330Fifo),
+        VMSTATE_UINT32(num, PL330Fifo),
+        VMSTATE_UINT32(buf_size, PL330Fifo),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+typedef struct PL330QueueEntry {
+    uint32_t addr;
+    uint32_t len;
+    uint8_t n;
+    bool inc;
+    bool z;
+    uint8_t tag;
+    uint8_t seqn;
+} PL330QueueEntry;
+
+static const VMStateDescription vmstate_pl330_queue_entry = {
+    .name = "pl330_queue_entry",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(addr, PL330QueueEntry),
+        VMSTATE_UINT32(len, PL330QueueEntry),
+        VMSTATE_UINT8(n, PL330QueueEntry),
+        VMSTATE_BOOL(inc, PL330QueueEntry),
+        VMSTATE_BOOL(z, PL330QueueEntry),
+        VMSTATE_UINT8(tag, PL330QueueEntry),
+        VMSTATE_UINT8(seqn, PL330QueueEntry),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+typedef struct PL330Queue {
+    PL330State *parent;
+    PL330QueueEntry *queue;
+    uint32_t queue_size;
+} PL330Queue;
+
+static const VMStateDescription vmstate_pl330_queue = {
+    .name = "pl330_queue",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT_VARRAY_UINT32(queue, PL330Queue, queue_size, 1,
+                                 vmstate_pl330_queue_entry, PL330QueueEntry),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+struct PL330State {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq irq_abort;
+    qemu_irq *irq;
+
+    /* Config registers. cfg[5] = CfgDn. */
+    uint32_t cfg[6];
+#define EVENT_SEC_STATE 3
+#define PERIPH_SEC_STATE 4
+    /* cfg 0 bits and pieces */
+    uint32_t num_chnls;
+    uint8_t num_periph_req;
+    uint8_t num_events;
+    uint8_t mgr_ns_at_rst;
+    /* cfg 1 bits and pieces */
+    uint8_t i_cache_len;
+    uint8_t num_i_cache_lines;
+    /* CRD bits and pieces */
+    uint8_t data_width;
+    uint8_t wr_cap;
+    uint8_t wr_q_dep;
+    uint8_t rd_cap;
+    uint8_t rd_q_dep;
+    uint16_t data_buffer_dep;
+
+    PL330Chan manager;
+    PL330Chan *chan;
+    PL330Fifo fifo;
+    PL330Queue read_queue;
+    PL330Queue write_queue;
+    uint8_t *lo_seqn;
+    uint8_t *hi_seqn;
+    QEMUTimer *timer; /* is used for restore dma. */
+
+    uint32_t inten;
+    uint32_t int_status;
+    uint32_t ev_status;
+    uint32_t dbg[2];
+    uint8_t debug_status;
+    uint8_t num_faulting;
+    uint8_t periph_busy[PL330_PERIPH_NUM];
+
+};
+
+#define TYPE_PL330 "pl330"
+#define PL330(obj) OBJECT_CHECK(PL330State, (obj), TYPE_PL330)
+
+static const VMStateDescription vmstate_pl330 = {
+    .name = "pl330",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT(manager, PL330State, 0, vmstate_pl330_chan, PL330Chan),
+        VMSTATE_STRUCT_VARRAY_UINT32(chan, PL330State, num_chnls, 0,
+                                     vmstate_pl330_chan, PL330Chan),
+        VMSTATE_VBUFFER_UINT32(lo_seqn, PL330State, 1, NULL, 0, num_chnls),
+        VMSTATE_VBUFFER_UINT32(hi_seqn, PL330State, 1, NULL, 0, num_chnls),
+        VMSTATE_STRUCT(fifo, PL330State, 0, vmstate_pl330_fifo, PL330Fifo),
+        VMSTATE_STRUCT(read_queue, PL330State, 0, vmstate_pl330_queue,
+                       PL330Queue),
+        VMSTATE_STRUCT(write_queue, PL330State, 0, vmstate_pl330_queue,
+                       PL330Queue),
+        VMSTATE_TIMER(timer, PL330State),
+        VMSTATE_UINT32(inten, PL330State),
+        VMSTATE_UINT32(int_status, PL330State),
+        VMSTATE_UINT32(ev_status, PL330State),
+        VMSTATE_UINT32_ARRAY(dbg, PL330State, 2),
+        VMSTATE_UINT8(debug_status, PL330State),
+        VMSTATE_UINT8(num_faulting, PL330State),
+        VMSTATE_UINT8_ARRAY(periph_busy, PL330State, PL330_PERIPH_NUM),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+typedef struct PL330InsnDesc {
+    /* OPCODE of the instruction */
+    uint8_t opcode;
+    /* Mask so we can select several sibling instructions, such as
+       DMALD, DMALDS and DMALDB */
+    uint8_t opmask;
+    /* Size of instruction in bytes */
+    uint8_t size;
+    /* Interpreter */
+    void (*exec)(PL330Chan *, uint8_t opcode, uint8_t *args, int len);
+} PL330InsnDesc;
+
+
+/* MFIFO Implementation
+ *
+ * MFIFO is implemented as a cyclic buffer of BUF_SIZE size. Tagged bytes are
+ * stored in this buffer. Data is stored in BUF field, tags - in the
+ * corresponding array elements of TAG field.
+ */
+
+/* Initialize queue. */
+
+static void pl330_fifo_init(PL330Fifo *s, uint32_t size)
+{
+    s->buf = g_malloc0(size);
+    s->tag = g_malloc0(size);
+    s->buf_size = size;
+}
+
+/* Cyclic increment */
+
+static inline int pl330_fifo_inc(PL330Fifo *s, int x)
+{
+    return (x + 1) % s->buf_size;
+}
+
+/* Number of empty bytes in MFIFO */
+
+static inline int pl330_fifo_num_free(PL330Fifo *s)
+{
+    return s->buf_size - s->num;
+}
+
+/* Push LEN bytes of data stored in BUF to MFIFO and tag it with TAG.
+ * Zero returned on success, PL330_FIFO_STALL if there is no enough free
+ * space in MFIFO to store requested amount of data. If push was unsuccessful
+ * no data is stored to MFIFO.
+ */
+
+static int pl330_fifo_push(PL330Fifo *s, uint8_t *buf, int len, uint8_t tag)
+{
+    int i;
+
+    if (s->buf_size - s->num < len) {
+        return PL330_FIFO_STALL;
+    }
+    for (i = 0; i < len; i++) {
+        int push_idx = (s->head + s->num + i) % s->buf_size;
+        s->buf[push_idx] = buf[i];
+        s->tag[push_idx] = tag;
+    }
+    s->num += len;
+    return PL330_FIFO_OK;
+}
+
+/* Get LEN bytes of data from MFIFO and store it to BUF. Tag value of each
+ * byte is verified. Zero returned on success, PL330_FIFO_ERR on tag mismatch
+ * and PL330_FIFO_STALL if there is no enough data in MFIFO. If get was
+ * unsuccessful no data is removed from MFIFO.
+ */
+
+static int pl330_fifo_get(PL330Fifo *s, uint8_t *buf, int len, uint8_t tag)
+{
+    int i;
+
+    if (s->num < len) {
+        return PL330_FIFO_STALL;
+    }
+    for (i = 0; i < len; i++) {
+        if (s->tag[s->head] == tag) {
+            int get_idx = (s->head + i) % s->buf_size;
+            buf[i] = s->buf[get_idx];
+        } else { /* Tag mismatch - Rollback transaction */
+            return PL330_FIFO_ERR;
+        }
+    }
+    s->head = (s->head + len) % s->buf_size;
+    s->num -= len;
+    return PL330_FIFO_OK;
+}
+
+/* Reset MFIFO. This completely erases all data in it. */
+
+static inline void pl330_fifo_reset(PL330Fifo *s)
+{
+    s->head = 0;
+    s->num = 0;
+}
+
+/* Return tag of the first byte stored in MFIFO. If MFIFO is empty
+ * PL330_UNTAGGED is returned.
+ */
+
+static inline uint8_t pl330_fifo_tag(PL330Fifo *s)
+{
+    return (!s->num) ? PL330_UNTAGGED : s->tag[s->head];
+}
+
+/* Returns non-zero if tag TAG is present in fifo or zero otherwise */
+
+static int pl330_fifo_has_tag(PL330Fifo *s, uint8_t tag)
+{
+    int i, n;
+
+    i = s->head;
+    for (n = 0; n < s->num; n++) {
+        if (s->tag[i] == tag) {
+            return 1;
+        }
+        i = pl330_fifo_inc(s, i);
+    }
+    return 0;
+}
+
+/* Remove all entry tagged with TAG from MFIFO */
+
+static void pl330_fifo_tagged_remove(PL330Fifo *s, uint8_t tag)
+{
+    int i, t, n;
+
+    t = i = s->head;
+    for (n = 0; n < s->num; n++) {
+        if (s->tag[i] != tag) {
+            s->buf[t] = s->buf[i];
+            s->tag[t] = s->tag[i];
+            t = pl330_fifo_inc(s, t);
+        } else {
+            s->num = s->num - 1;
+        }
+        i = pl330_fifo_inc(s, i);
+    }
+}
+
+/* Read-Write Queue implementation
+ *
+ * A Read-Write Queue stores up to QUEUE_SIZE instructions (loads or stores).
+ * Each instruction is described by source (for loads) or destination (for
+ * stores) address ADDR, width of data to be loaded/stored LEN, number of
+ * stores/loads to be performed N, INC bit, Z bit and TAG to identify channel
+ * this instruction belongs to. Queue does not store any information about
+ * nature of the instruction: is it load or store. PL330 has different queues
+ * for loads and stores so this is already known at the top level where it
+ * matters.
+ *
+ * Queue works as FIFO for instructions with equivalent tags, but can issue
+ * instructions with different tags in arbitrary order. SEQN field attached to
+ * each instruction helps to achieve this. For each TAG queue contains
+ * instructions with consecutive SEQN values ranging from LO_SEQN[TAG] to
+ * HI_SEQN[TAG]-1 inclusive. SEQN is 8-bit unsigned integer, so SEQN=255 is
+ * followed by SEQN=0.
+ *
+ * Z bit indicates that zeroes should be stored. No MFIFO fetches are performed
+ * in this case.
+ */
+
+static void pl330_queue_reset(PL330Queue *s)
+{
+    int i;
+
+    for (i = 0; i < s->queue_size; i++) {
+        s->queue[i].tag = PL330_UNTAGGED;
+    }
+}
+
+/* Initialize queue */
+static void pl330_queue_init(PL330Queue *s, int size, PL330State *parent)
+{
+    s->parent = parent;
+    s->queue = g_new0(PL330QueueEntry, size);
+    s->queue_size = size;
+}
+
+/* Returns pointer to an empty slot or NULL if queue is full */
+static PL330QueueEntry *pl330_queue_find_empty(PL330Queue *s)
+{
+    int i;
+
+    for (i = 0; i < s->queue_size; i++) {
+        if (s->queue[i].tag == PL330_UNTAGGED) {
+            return &s->queue[i];
+        }
+    }
+    return NULL;
+}
+
+/* Put instruction in queue.
+ * Return value:
+ * - zero - OK
+ * - non-zero - queue is full
+ */
+
+static int pl330_queue_put_insn(PL330Queue *s, uint32_t addr,
+                                int len, int n, bool inc, bool z, uint8_t tag)
+{
+    PL330QueueEntry *entry = pl330_queue_find_empty(s);
+
+    if (!entry) {
+        return 1;
+    }
+    entry->tag = tag;
+    entry->addr = addr;
+    entry->len = len;
+    entry->n = n;
+    entry->z = z;
+    entry->inc = inc;
+    entry->seqn = s->parent->hi_seqn[tag];
+    s->parent->hi_seqn[tag]++;
+    return 0;
+}
+
+/* Returns a pointer to queue slot containing instruction which satisfies
+ *  following conditions:
+ *   - it has valid tag value (not PL330_UNTAGGED)
+ *   - if enforce_seq is set it has to be issuable without violating queue
+ *     logic (see above)
+ *   - if TAG argument is not PL330_UNTAGGED this instruction has tag value
+ *     equivalent to the argument TAG value.
+ *  If such instruction cannot be found NULL is returned.
+ */
+
+static PL330QueueEntry *pl330_queue_find_insn(PL330Queue *s, uint8_t tag,
+                                              bool enforce_seq)
+{
+    int i;
+
+    for (i = 0; i < s->queue_size; i++) {
+        if (s->queue[i].tag != PL330_UNTAGGED) {
+            if ((!enforce_seq ||
+                    s->queue[i].seqn == s->parent->lo_seqn[s->queue[i].tag]) &&
+                    (s->queue[i].tag == tag || tag == PL330_UNTAGGED ||
+                    s->queue[i].z)) {
+                return &s->queue[i];
+            }
+        }
+    }
+    return NULL;
+}
+
+/* Removes instruction from queue. */
+
+static inline void pl330_queue_remove_insn(PL330Queue *s, PL330QueueEntry *e)
+{
+    s->parent->lo_seqn[e->tag]++;
+    e->tag = PL330_UNTAGGED;
+}
+
+/* Removes all instructions tagged with TAG from queue. */
+
+static inline void pl330_queue_remove_tagged(PL330Queue *s, uint8_t tag)
+{
+    int i;
+
+    for (i = 0; i < s->queue_size; i++) {
+        if (s->queue[i].tag == tag) {
+            s->queue[i].tag = PL330_UNTAGGED;
+        }
+    }
+}
+
+/* DMA instruction execution engine */
+
+/* Moves DMA channel to the FAULT state and updates it's status. */
+
+static inline void pl330_fault(PL330Chan *ch, uint32_t flags)
+{
+    DB_PRINT("ch: %p, flags: %x\n", ch, flags);
+    ch->fault_type |= flags;
+    if (ch->state == pl330_chan_fault) {
+        return;
+    }
+    ch->state = pl330_chan_fault;
+    ch->parent->num_faulting++;
+    if (ch->parent->num_faulting == 1) {
+        DB_PRINT("abort interrupt raised\n");
+        qemu_irq_raise(ch->parent->irq_abort);
+    }
+}
+
+/*
+ * For information about instructions see PL330 Technical Reference Manual.
+ *
+ * Arguments:
+ *   CH - channel executing the instruction
+ *   OPCODE - opcode
+ *   ARGS - array of 8-bit arguments
+ *   LEN - number of elements in ARGS array
+ */
+
+static void pl330_dmaaddh(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+    uint16_t im = (((uint16_t)args[1]) << 8) | ((uint16_t)args[0]);
+    uint8_t ra = (opcode >> 1) & 1;
+
+    if (ch->is_manager) {
+        pl330_fault(ch, PL330_FAULT_UNDEF_INSTR);
+        return;
+    }
+    if (ra) {
+        ch->dst += im;
+    } else {
+        ch->src += im;
+    }
+}
+
+static void pl330_dmaend(PL330Chan *ch, uint8_t opcode,
+                         uint8_t *args, int len)
+{
+    PL330State *s = ch->parent;
+
+    if (ch->state == pl330_chan_executing && !ch->is_manager) {
+        /* Wait for all transfers to complete */
+        if (pl330_fifo_has_tag(&s->fifo, ch->tag) ||
+            pl330_queue_find_insn(&s->read_queue, ch->tag, false) != NULL ||
+            pl330_queue_find_insn(&s->write_queue, ch->tag, false) != NULL) {
+
+            ch->stall = 1;
+            return;
+        }
+    }
+    DB_PRINT("DMA ending!\n");
+    pl330_fifo_tagged_remove(&s->fifo, ch->tag);
+    pl330_queue_remove_tagged(&s->read_queue, ch->tag);
+    pl330_queue_remove_tagged(&s->write_queue, ch->tag);
+    ch->state = pl330_chan_stopped;
+}
+
+static void pl330_dmaflushp(PL330Chan *ch, uint8_t opcode,
+                                            uint8_t *args, int len)
+{
+    uint8_t periph_id;
+
+    if (args[0] & 7) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    periph_id = (args[0] >> 3) & 0x1f;
+    if (periph_id >= ch->parent->num_periph_req) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    if (ch->ns && !(ch->parent->cfg[CFG_PNS] & (1 << periph_id))) {
+        pl330_fault(ch, PL330_FAULT_CH_PERIPH_ERR);
+        return;
+    }
+    /* Do nothing */
+}
+
+static void pl330_dmago(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+    uint8_t chan_id;
+    uint8_t ns;
+    uint32_t pc;
+    PL330Chan *s;
+
+    DB_PRINT("\n");
+
+    if (!ch->is_manager) {
+        pl330_fault(ch, PL330_FAULT_UNDEF_INSTR);
+        return;
+    }
+    ns = !!(opcode & 2);
+    chan_id = args[0] & 7;
+    if ((args[0] >> 3)) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    if (chan_id >= ch->parent->num_chnls) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    pc = (((uint32_t)args[4]) << 24) | (((uint32_t)args[3]) << 16) |
+         (((uint32_t)args[2]) << 8)  | (((uint32_t)args[1]));
+    if (ch->parent->chan[chan_id].state != pl330_chan_stopped) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    if (ch->ns && !ns) {
+        pl330_fault(ch, PL330_FAULT_DMAGO_ERR);
+        return;
+    }
+    s = &ch->parent->chan[chan_id];
+    s->ns = ns;
+    s->pc = pc;
+    s->state = pl330_chan_executing;
+}
+
+static void pl330_dmald(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+    uint8_t bs = opcode & 3;
+    uint32_t size, num;
+    bool inc;
+
+    if (bs == 2) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    if ((bs == 1 && ch->request_flag == PL330_BURST) ||
+        (bs == 3 && ch->request_flag == PL330_SINGLE)) {
+        /* Perform NOP */
+        return;
+    }
+    if (bs == 1 && ch->request_flag == PL330_SINGLE) {
+        num = 1;
+    } else {
+        num = ((ch->control >> 4) & 0xf) + 1;
+    }
+    size = (uint32_t)1 << ((ch->control >> 1) & 0x7);
+    inc = !!(ch->control & 1);
+    ch->stall = pl330_queue_put_insn(&ch->parent->read_queue, ch->src,
+                                    size, num, inc, 0, ch->tag);
+    if (!ch->stall) {
+        DB_PRINT("channel:%d address:%08x size:%d num:%d %c\n",
+                 ch->tag, ch->src, size, num, inc ? 'Y' : 'N');
+        ch->src += inc ? size * num - (ch->src & (size - 1)) : 0;
+    }
+}
+
+static void pl330_dmaldp(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+    uint8_t periph_id;
+
+    if (args[0] & 7) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    periph_id = (args[0] >> 3) & 0x1f;
+    if (periph_id >= ch->parent->num_periph_req) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    if (ch->ns && !(ch->parent->cfg[CFG_PNS] & (1 << periph_id))) {
+        pl330_fault(ch, PL330_FAULT_CH_PERIPH_ERR);
+        return;
+    }
+    pl330_dmald(ch, opcode, args, len);
+}
+
+static void pl330_dmalp(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+    uint8_t lc = (opcode & 2) >> 1;
+
+    ch->lc[lc] = args[0];
+}
+
+static void pl330_dmakill(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+    if (ch->state == pl330_chan_fault ||
+        ch->state == pl330_chan_fault_completing) {
+        /* This is the only way for a channel to leave the faulting state */
+        ch->fault_type = 0;
+        ch->parent->num_faulting--;
+        if (ch->parent->num_faulting == 0) {
+            DB_PRINT("abort interrupt lowered\n");
+            qemu_irq_lower(ch->parent->irq_abort);
+        }
+    }
+    ch->state = pl330_chan_killing;
+    pl330_fifo_tagged_remove(&ch->parent->fifo, ch->tag);
+    pl330_queue_remove_tagged(&ch->parent->read_queue, ch->tag);
+    pl330_queue_remove_tagged(&ch->parent->write_queue, ch->tag);
+    ch->state = pl330_chan_stopped;
+}
+
+static void pl330_dmalpend(PL330Chan *ch, uint8_t opcode,
+                                    uint8_t *args, int len)
+{
+    uint8_t nf = (opcode & 0x10) >> 4;
+    uint8_t bs = opcode & 3;
+    uint8_t lc = (opcode & 4) >> 2;
+
+    if (bs == 2) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    if ((bs == 1 && ch->request_flag == PL330_BURST) ||
+        (bs == 3 && ch->request_flag == PL330_SINGLE)) {
+        /* Perform NOP */
+        return;
+    }
+    if (!nf || ch->lc[lc]) {
+        if (nf) {
+            ch->lc[lc]--;
+        }
+        DB_PRINT("loop reiteration\n");
+        ch->pc -= args[0];
+        ch->pc -= len + 1;
+        /* "ch->pc -= args[0] + len + 1" is incorrect when args[0] == 256 */
+    } else {
+        DB_PRINT("loop fallthrough\n");
+    }
+}
+
+
+static void pl330_dmamov(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+    uint8_t rd = args[0] & 7;
+    uint32_t im;
+
+    if ((args[0] >> 3)) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    im = (((uint32_t)args[4]) << 24) | (((uint32_t)args[3]) << 16) |
+         (((uint32_t)args[2]) << 8)  | (((uint32_t)args[1]));
+    switch (rd) {
+    case 0:
+        ch->src = im;
+        break;
+    case 1:
+        ch->control = im;
+        break;
+    case 2:
+        ch->dst = im;
+        break;
+    default:
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+}
+
+static void pl330_dmanop(PL330Chan *ch, uint8_t opcode,
+                         uint8_t *args, int len)
+{
+    /* NOP is NOP. */
+}
+
+static void pl330_dmarmb(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+   if (pl330_queue_find_insn(&ch->parent->read_queue, ch->tag, false)) {
+        ch->state = pl330_chan_at_barrier;
+        ch->stall = 1;
+        return;
+    } else {
+        ch->state = pl330_chan_executing;
+    }
+}
+
+static void pl330_dmasev(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+    uint8_t ev_id;
+
+    if (args[0] & 7) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    ev_id = (args[0] >> 3) & 0x1f;
+    if (ev_id >= ch->parent->num_events) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    if (ch->ns && !(ch->parent->cfg[CFG_INS] & (1 << ev_id))) {
+        pl330_fault(ch, PL330_FAULT_EVENT_ERR);
+        return;
+    }
+    if (ch->parent->inten & (1 << ev_id)) {
+        ch->parent->int_status |= (1 << ev_id);
+        DB_PRINT("event interrupt raised %d\n", ev_id);
+        qemu_irq_raise(ch->parent->irq[ev_id]);
+    } else {
+        ch->parent->ev_status |= (1 << ev_id);
+    }
+}
+
+static void pl330_dmast(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
+{
+    uint8_t bs = opcode & 3;
+    uint32_t size, num;
+    bool inc;
+
+    if (bs == 2) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    if ((bs == 1 && ch->request_flag == PL330_BURST) ||
+        (bs == 3 && ch->request_flag == PL330_SINGLE)) {
+        /* Perform NOP */
+        return;
+    }
+    num = ((ch->control >> 18) & 0xf) + 1;
+    size = (uint32_t)1 << ((ch->control >> 15) & 0x7);
+    inc = !!((ch->control >> 14) & 1);
+    ch->stall = pl330_queue_put_insn(&ch->parent->write_queue, ch->dst,
+                                    size, num, inc, 0, ch->tag);
+    if (!ch->stall) {
+        DB_PRINT("channel:%d address:%08x size:%d num:%d %c\n",
+                 ch->tag, ch->dst, size, num, inc ? 'Y' : 'N');
+        ch->dst += inc ? size * num - (ch->dst & (size - 1)) : 0;
+    }
+}
+
+static void pl330_dmastp(PL330Chan *ch, uint8_t opcode,
+                         uint8_t *args, int len)
+{
+    uint8_t periph_id;
+
+    if (args[0] & 7) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    periph_id = (args[0] >> 3) & 0x1f;
+    if (periph_id >= ch->parent->num_periph_req) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    if (ch->ns && !(ch->parent->cfg[CFG_PNS] & (1 << periph_id))) {
+        pl330_fault(ch, PL330_FAULT_CH_PERIPH_ERR);
+        return;
+    }
+    pl330_dmast(ch, opcode, args, len);
+}
+
+static void pl330_dmastz(PL330Chan *ch, uint8_t opcode,
+                         uint8_t *args, int len)
+{
+    uint32_t size, num;
+    bool inc;
+
+    num = ((ch->control >> 18) & 0xf) + 1;
+    size = (uint32_t)1 << ((ch->control >> 15) & 0x7);
+    inc = !!((ch->control >> 14) & 1);
+    ch->stall = pl330_queue_put_insn(&ch->parent->write_queue, ch->dst,
+                                    size, num, inc, 1, ch->tag);
+    if (inc) {
+        ch->dst += size * num;
+    }
+}
+
+static void pl330_dmawfe(PL330Chan *ch, uint8_t opcode,
+                         uint8_t *args, int len)
+{
+    uint8_t ev_id;
+    int i;
+
+    if (args[0] & 5) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    ev_id = (args[0] >> 3) & 0x1f;
+    if (ev_id >= ch->parent->num_events) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    if (ch->ns && !(ch->parent->cfg[CFG_INS] & (1 << ev_id))) {
+        pl330_fault(ch, PL330_FAULT_EVENT_ERR);
+        return;
+    }
+    ch->wakeup = ev_id;
+    ch->state = pl330_chan_waiting_event;
+    if (~ch->parent->inten & ch->parent->ev_status & 1 << ev_id) {
+        ch->state = pl330_chan_executing;
+        /* If anyone else is currently waiting on the same event, let them
+         * clear the ev_status so they pick up event as well
+         */
+        for (i = 0; i < ch->parent->num_chnls; ++i) {
+            PL330Chan *peer = &ch->parent->chan[i];
+            if (peer->state == pl330_chan_waiting_event &&
+                    peer->wakeup == ev_id) {
+                return;
+            }
+        }
+        ch->parent->ev_status &= ~(1 << ev_id);
+    } else {
+        ch->stall = 1;
+    }
+}
+
+static void pl330_dmawfp(PL330Chan *ch, uint8_t opcode,
+                         uint8_t *args, int len)
+{
+    uint8_t bs = opcode & 3;
+    uint8_t periph_id;
+
+    if (args[0] & 7) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    periph_id = (args[0] >> 3) & 0x1f;
+    if (periph_id >= ch->parent->num_periph_req) {
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+    if (ch->ns && !(ch->parent->cfg[CFG_PNS] & (1 << periph_id))) {
+        pl330_fault(ch, PL330_FAULT_CH_PERIPH_ERR);
+        return;
+    }
+    switch (bs) {
+    case 0: /* S */
+        ch->request_flag = PL330_SINGLE;
+        ch->wfp_sbp = 0;
+        break;
+    case 1: /* P */
+        ch->request_flag = PL330_BURST;
+        ch->wfp_sbp = 2;
+        break;
+    case 2: /* B */
+        ch->request_flag = PL330_BURST;
+        ch->wfp_sbp = 1;
+        break;
+    default:
+        pl330_fault(ch, PL330_FAULT_OPERAND_INVALID);
+        return;
+    }
+
+    if (ch->parent->periph_busy[periph_id]) {
+        ch->state = pl330_chan_waiting_periph;
+        ch->stall = 1;
+    } else if (ch->state == pl330_chan_waiting_periph) {
+        ch->state = pl330_chan_executing;
+    }
+}
+
+static void pl330_dmawmb(PL330Chan *ch, uint8_t opcode,
+                         uint8_t *args, int len)
+{
+    if (pl330_queue_find_insn(&ch->parent->write_queue, ch->tag, false)) {
+        ch->state = pl330_chan_at_barrier;
+        ch->stall = 1;
+        return;
+    } else {
+        ch->state = pl330_chan_executing;
+    }
+}
+
+/* NULL terminated array of the instruction descriptions. */
+static const PL330InsnDesc insn_desc[] = {
+    { .opcode = 0x54, .opmask = 0xFD, .size = 3, .exec = pl330_dmaaddh, },
+    { .opcode = 0x00, .opmask = 0xFF, .size = 1, .exec = pl330_dmaend, },
+    { .opcode = 0x35, .opmask = 0xFF, .size = 2, .exec = pl330_dmaflushp, },
+    { .opcode = 0xA0, .opmask = 0xFD, .size = 6, .exec = pl330_dmago, },
+    { .opcode = 0x04, .opmask = 0xFC, .size = 1, .exec = pl330_dmald, },
+    { .opcode = 0x25, .opmask = 0xFD, .size = 2, .exec = pl330_dmaldp, },
+    { .opcode = 0x20, .opmask = 0xFD, .size = 2, .exec = pl330_dmalp, },
+    /* dmastp  must be before dmalpend in this list, because their maps
+     * are overlapping
+     */
+    { .opcode = 0x29, .opmask = 0xFD, .size = 2, .exec = pl330_dmastp, },
+    { .opcode = 0x28, .opmask = 0xE8, .size = 2, .exec = pl330_dmalpend, },
+    { .opcode = 0x01, .opmask = 0xFF, .size = 1, .exec = pl330_dmakill, },
+    { .opcode = 0xBC, .opmask = 0xFF, .size = 6, .exec = pl330_dmamov, },
+    { .opcode = 0x18, .opmask = 0xFF, .size = 1, .exec = pl330_dmanop, },
+    { .opcode = 0x12, .opmask = 0xFF, .size = 1, .exec = pl330_dmarmb, },
+    { .opcode = 0x34, .opmask = 0xFF, .size = 2, .exec = pl330_dmasev, },
+    { .opcode = 0x08, .opmask = 0xFC, .size = 1, .exec = pl330_dmast, },
+    { .opcode = 0x0C, .opmask = 0xFF, .size = 1, .exec = pl330_dmastz, },
+    { .opcode = 0x36, .opmask = 0xFF, .size = 2, .exec = pl330_dmawfe, },
+    { .opcode = 0x30, .opmask = 0xFC, .size = 2, .exec = pl330_dmawfp, },
+    { .opcode = 0x13, .opmask = 0xFF, .size = 1, .exec = pl330_dmawmb, },
+    { .opcode = 0x00, .opmask = 0x00, .size = 0, .exec = NULL, }
+};
+
+/* Instructions which can be issued via debug registers. */
+static const PL330InsnDesc debug_insn_desc[] = {
+    { .opcode = 0xA0, .opmask = 0xFD, .size = 6, .exec = pl330_dmago, },
+    { .opcode = 0x01, .opmask = 0xFF, .size = 1, .exec = pl330_dmakill, },
+    { .opcode = 0x34, .opmask = 0xFF, .size = 2, .exec = pl330_dmasev, },
+    { .opcode = 0x00, .opmask = 0x00, .size = 0, .exec = NULL, }
+};
+
+static inline const PL330InsnDesc *pl330_fetch_insn(PL330Chan *ch)
+{
+    uint8_t opcode;
+    int i;
+
+    dma_memory_read(&dma_context_memory, ch->pc, &opcode, 1);
+    for (i = 0; insn_desc[i].size; i++) {
+        if ((opcode & insn_desc[i].opmask) == insn_desc[i].opcode) {
+            return &insn_desc[i];
+        }
+    }
+    return NULL;
+}
+
+static inline void pl330_exec_insn(PL330Chan *ch, const PL330InsnDesc *insn)
+{
+    uint8_t buf[PL330_INSN_MAXSIZE];
+
+    assert(insn->size <= PL330_INSN_MAXSIZE);
+    dma_memory_read(&dma_context_memory, ch->pc, buf, insn->size);
+    insn->exec(ch, buf[0], &buf[1], insn->size - 1);
+}
+
+static inline void pl330_update_pc(PL330Chan *ch,
+                                   const PL330InsnDesc *insn)
+{
+    ch->pc += insn->size;
+}
+
+/* Try to execute current instruction in channel CH. Number of executed
+   instructions is returned (0 or 1). */
+static int pl330_chan_exec(PL330Chan *ch)
+{
+    const PL330InsnDesc *insn;
+
+    if (ch->state != pl330_chan_executing &&
+            ch->state != pl330_chan_waiting_periph &&
+            ch->state != pl330_chan_at_barrier &&
+            ch->state != pl330_chan_waiting_event) {
+        DB_PRINT("%d\n", ch->state);
+        return 0;
+    }
+    ch->stall = 0;
+    insn = pl330_fetch_insn(ch);
+    if (!insn) {
+        DB_PRINT("pl330 undefined instruction\n");
+        pl330_fault(ch, PL330_FAULT_UNDEF_INSTR);
+        return 0;
+    }
+    pl330_exec_insn(ch, insn);
+    if (!ch->stall) {
+        pl330_update_pc(ch, insn);
+        ch->watchdog_timer = 0;
+        return 1;
+    /* WDT only active in exec state */
+    } else if (ch->state == pl330_chan_executing) {
+        ch->watchdog_timer++;
+        if (ch->watchdog_timer >= PL330_WATCHDOG_LIMIT) {
+            pl330_fault(ch, PL330_FAULT_LOCKUP_ERR);
+        }
+    }
+    return 0;
+}
+
+/* Try to execute 1 instruction in each channel, one instruction from read
+   queue and one instruction from write queue. Number of successfully executed
+   instructions is returned. */
+static int pl330_exec_cycle(PL330Chan *channel)
+{
+    PL330State *s = channel->parent;
+    PL330QueueEntry *q;
+    int i;
+    int num_exec = 0;
+    int fifo_res = 0;
+    uint8_t buf[PL330_MAX_BURST_LEN];
+
+    /* Execute one instruction in each channel */
+    num_exec += pl330_chan_exec(channel);
+
+    /* Execute one instruction from read queue */
+    q = pl330_queue_find_insn(&s->read_queue, PL330_UNTAGGED, true);
+    if (q != NULL && q->len <= pl330_fifo_num_free(&s->fifo)) {
+        int len = q->len - (q->addr & (q->len - 1));
+
+        dma_memory_read(&dma_context_memory, q->addr, buf, len);
+        if (PL330_ERR_DEBUG > 1) {
+            DB_PRINT("PL330 read from memory @%08x (size = %08x):\n",
+                      q->addr, len);
+            hexdump((char *)buf, stderr, "", len);
+        }
+        fifo_res = pl330_fifo_push(&s->fifo, buf, len, q->tag);
+        if (fifo_res == PL330_FIFO_OK) {
+            if (q->inc) {
+                q->addr += len;
+            }
+            q->n--;
+            if (!q->n) {
+                pl330_queue_remove_insn(&s->read_queue, q);
+            }
+            num_exec++;
+        }
+    }
+
+    /* Execute one instruction from write queue. */
+    q = pl330_queue_find_insn(&s->write_queue, pl330_fifo_tag(&s->fifo), true);
+    if (q != NULL) {
+        int len = q->len - (q->addr & (q->len - 1));
+
+        if (q->z) {
+            for (i = 0; i < len; i++) {
+                buf[i] = 0;
+            }
+        } else {
+            fifo_res = pl330_fifo_get(&s->fifo, buf, len, q->tag);
+        }
+        if (fifo_res == PL330_FIFO_OK || q->z) {
+            dma_memory_write(&dma_context_memory, q->addr, buf, len);
+            if (PL330_ERR_DEBUG > 1) {
+                DB_PRINT("PL330 read from memory @%08x (size = %08x):\n",
+                         q->addr, len);
+                hexdump((char *)buf, stderr, "", len);
+            }
+            if (q->inc) {
+                q->addr += len;
+            }
+            num_exec++;
+        } else if (fifo_res == PL330_FIFO_STALL) {
+            pl330_fault(&channel->parent->chan[q->tag],
+                                PL330_FAULT_FIFOEMPTY_ERR);
+        }
+        q->n--;
+        if (!q->n) {
+            pl330_queue_remove_insn(&s->write_queue, q);
+        }
+    }
+
+    return num_exec;
+}
+
+static int pl330_exec_channel(PL330Chan *channel)
+{
+    int insr_exec = 0;
+
+    /* TODO: Is it all right to execute everything or should we do per-cycle
+       simulation? */
+    while (pl330_exec_cycle(channel)) {
+        insr_exec++;
+    }
+
+    /* Detect deadlock */
+    if (channel->state == pl330_chan_executing) {
+        pl330_fault(channel, PL330_FAULT_LOCKUP_ERR);
+    }
+    /* Situation when one of the queues has deadlocked but all channels
+     * have finished their programs should be impossible.
+     */
+
+    return insr_exec;
+}
+
+static inline void pl330_exec(PL330State *s)
+{
+    DB_PRINT("\n");
+    int i, insr_exec;
+    do {
+        insr_exec = pl330_exec_channel(&s->manager);
+
+        for (i = 0; i < s->num_chnls; i++) {
+            insr_exec += pl330_exec_channel(&s->chan[i]);
+        }
+    } while (insr_exec);
+}
+
+static void pl330_exec_cycle_timer(void *opaque)
+{
+    PL330State *s = (PL330State *)opaque;
+    pl330_exec(s);
+}
+
+/* Stop or restore dma operations */
+
+static void pl330_dma_stop_irq(void *opaque, int irq, int level)
+{
+    PL330State *s = (PL330State *)opaque;
+
+    if (s->periph_busy[irq] != level) {
+        s->periph_busy[irq] = level;
+        qemu_mod_timer(s->timer, qemu_get_clock_ns(vm_clock));
+    }
+}
+
+static void pl330_debug_exec(PL330State *s)
+{
+    uint8_t args[5];
+    uint8_t opcode;
+    uint8_t chan_id;
+    int i;
+    PL330Chan *ch;
+    const PL330InsnDesc *insn;
+
+    s->debug_status = 1;
+    chan_id = (s->dbg[0] >>  8) & 0x07;
+    opcode  = (s->dbg[0] >> 16) & 0xff;
+    args[0] = (s->dbg[0] >> 24) & 0xff;
+    args[1] = (s->dbg[1] >>  0) & 0xff;
+    args[2] = (s->dbg[1] >>  8) & 0xff;
+    args[3] = (s->dbg[1] >> 16) & 0xff;
+    args[4] = (s->dbg[1] >> 24) & 0xff;
+    DB_PRINT("chan id: %d\n", chan_id);
+    if (s->dbg[0] & 1) {
+        ch = &s->chan[chan_id];
+    } else {
+        ch = &s->manager;
+    }
+    insn = NULL;
+    for (i = 0; debug_insn_desc[i].size; i++) {
+        if ((opcode & debug_insn_desc[i].opmask) == debug_insn_desc[i].opcode) {
+            insn = &debug_insn_desc[i];
+        }
+    }
+    if (!insn) {
+        pl330_fault(ch, PL330_FAULT_UNDEF_INSTR | PL330_FAULT_DBG_INSTR);
+        return ;
+    }
+    ch->stall = 0;
+    insn->exec(ch, opcode, args, insn->size - 1);
+    if (ch->fault_type) {
+        ch->fault_type |= PL330_FAULT_DBG_INSTR;
+    }
+    if (ch->stall) {
+        qemu_log_mask(LOG_UNIMP, "pl330: stall of debug instruction not "
+                      "implemented\n");
+    }
+    s->debug_status = 0;
+}
+
+/* IOMEM mapped registers */
+
+static void pl330_iomem_write(void *opaque, hwaddr offset,
+                              uint64_t value, unsigned size)
+{
+    PL330State *s = (PL330State *) opaque;
+    uint32_t i;
+
+    DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, (unsigned)value);
+
+    switch (offset) {
+    case PL330_REG_INTEN:
+        s->inten = value;
+        break;
+    case PL330_REG_INTCLR:
+        for (i = 0; i < s->num_events; i++) {
+            if (s->int_status & s->inten & value & (1 << i)) {
+                DB_PRINT("event interrupt lowered %d\n", i);
+                qemu_irq_lower(s->irq[i]);
+            }
+        }
+        s->ev_status &= ~(value & s->inten);
+        s->int_status &= ~(value & s->inten);
+        break;
+    case PL330_REG_DBGCMD:
+        if ((value & 3) == 0) {
+            pl330_debug_exec(s);
+            pl330_exec(s);
+        } else {
+            qemu_log_mask(LOG_GUEST_ERROR, "pl330: write of illegal value %u "
+                          "for offset " TARGET_FMT_plx "\n", (unsigned)value,
+                          offset);
+        }
+        break;
+    case PL330_REG_DBGINST0:
+        DB_PRINT("s->dbg[0] = %08x\n", (unsigned)value);
+        s->dbg[0] = value;
+        break;
+    case PL330_REG_DBGINST1:
+        DB_PRINT("s->dbg[1] = %08x\n", (unsigned)value);
+        s->dbg[1] = value;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad write offset " TARGET_FMT_plx
+                      "\n", offset);
+        break;
+    }
+}
+
+static inline uint32_t pl330_iomem_read_imp(void *opaque,
+        hwaddr offset)
+{
+    PL330State *s = (PL330State *)opaque;
+    int chan_id;
+    int i;
+    uint32_t res;
+
+    if (offset >= PL330_REG_PERIPH_ID && offset < PL330_REG_PERIPH_ID + 32) {
+        return pl330_id[(offset - PL330_REG_PERIPH_ID) >> 2];
+    }
+    if (offset >= PL330_REG_CR0_BASE && offset < PL330_REG_CR0_BASE + 24) {
+        return s->cfg[(offset - PL330_REG_CR0_BASE) >> 2];
+    }
+    if (offset >= PL330_REG_CHANCTRL && offset < PL330_REG_DBGSTATUS) {
+        offset -= PL330_REG_CHANCTRL;
+        chan_id = offset >> 5;
+        if (chan_id >= s->num_chnls) {
+            qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad read offset "
+                          TARGET_FMT_plx "\n", offset);
+            return 0;
+        }
+        switch (offset & 0x1f) {
+        case 0x00:
+            return s->chan[chan_id].src;
+        case 0x04:
+            return s->chan[chan_id].dst;
+        case 0x08:
+            return s->chan[chan_id].control;
+        case 0x0C:
+            return s->chan[chan_id].lc[0];
+        case 0x10:
+            return s->chan[chan_id].lc[1];
+        default:
+            qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad read offset "
+                          TARGET_FMT_plx "\n", offset);
+            return 0;
+        }
+    }
+    if (offset >= PL330_REG_CSR_BASE && offset < 0x400) {
+        offset -= PL330_REG_CSR_BASE;
+        chan_id = offset >> 3;
+        if (chan_id >= s->num_chnls) {
+            qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad read offset "
+                          TARGET_FMT_plx "\n", offset);
+            return 0;
+        }
+        switch ((offset >> 2) & 1) {
+        case 0x0:
+            res = (s->chan[chan_id].ns << 21) |
+                    (s->chan[chan_id].wakeup << 4) |
+                    (s->chan[chan_id].state) |
+                    (s->chan[chan_id].wfp_sbp << 14);
+            return res;
+        case 0x1:
+            return s->chan[chan_id].pc;
+        default:
+            qemu_log_mask(LOG_GUEST_ERROR, "pl330: read error\n");
+            return 0;
+        }
+    }
+    if (offset >= PL330_REG_FTR_BASE && offset < 0x100) {
+        offset -= PL330_REG_FTR_BASE;
+        chan_id = offset >> 2;
+        if (chan_id >= s->num_chnls) {
+            qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad read offset "
+                          TARGET_FMT_plx "\n", offset);
+            return 0;
+        }
+        return s->chan[chan_id].fault_type;
+    }
+    switch (offset) {
+    case PL330_REG_DSR:
+        return (s->manager.ns << 9) | (s->manager.wakeup << 4) |
+            (s->manager.state & 0xf);
+    case PL330_REG_DPC:
+        return s->manager.pc;
+    case PL330_REG_INTEN:
+        return s->inten;
+    case PL330_REG_INT_EVENT_RIS:
+        return s->ev_status;
+    case PL330_REG_INTMIS:
+        return s->int_status;
+    case PL330_REG_INTCLR:
+        /* Documentation says that we can't read this register
+         * but linux kernel does it
+         */
+        return 0;
+    case PL330_REG_FSRD:
+        return s->manager.state ? 1 : 0;
+    case PL330_REG_FSRC:
+        res = 0;
+        for (i = 0; i < s->num_chnls; i++) {
+            if (s->chan[i].state == pl330_chan_fault ||
+                s->chan[i].state == pl330_chan_fault_completing) {
+                res |= 1 << i;
+            }
+        }
+        return res;
+    case PL330_REG_FTRD:
+        return s->manager.fault_type;
+    case PL330_REG_DBGSTATUS:
+        return s->debug_status;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "pl330: bad read offset "
+                      TARGET_FMT_plx "\n", offset);
+    }
+    return 0;
+}
+
+static uint64_t pl330_iomem_read(void *opaque, hwaddr offset,
+        unsigned size)
+{
+    int ret = pl330_iomem_read_imp(opaque, offset);
+    DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, ret);
+    return ret;
+}
+
+static const MemoryRegionOps pl330_ops = {
+    .read = pl330_iomem_read,
+    .write = pl330_iomem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    }
+};
+
+/* Controller logic and initialization */
+
+static void pl330_chan_reset(PL330Chan *ch)
+{
+    ch->src = 0;
+    ch->dst = 0;
+    ch->pc = 0;
+    ch->state = pl330_chan_stopped;
+    ch->watchdog_timer = 0;
+    ch->stall = 0;
+    ch->control = 0;
+    ch->status = 0;
+    ch->fault_type = 0;
+}
+
+static void pl330_reset(DeviceState *d)
+{
+    int i;
+    PL330State *s = PL330(d);
+
+    s->inten = 0;
+    s->int_status = 0;
+    s->ev_status = 0;
+    s->debug_status = 0;
+    s->num_faulting = 0;
+    s->manager.ns = s->mgr_ns_at_rst;
+    pl330_fifo_reset(&s->fifo);
+    pl330_queue_reset(&s->read_queue);
+    pl330_queue_reset(&s->write_queue);
+
+    for (i = 0; i < s->num_chnls; i++) {
+        pl330_chan_reset(&s->chan[i]);
+    }
+    for (i = 0; i < s->num_periph_req; i++) {
+        s->periph_busy[i] = 0;
+    }
+
+    qemu_del_timer(s->timer);
+}
+
+static void pl330_realize(DeviceState *dev, Error **errp)
+{
+    int i;
+    PL330State *s = PL330(dev);
+
+    sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq_abort);
+    memory_region_init_io(&s->iomem, &pl330_ops, s, "dma", PL330_IOMEM_SIZE);
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
+
+    s->timer = qemu_new_timer_ns(vm_clock, pl330_exec_cycle_timer, s);
+
+    s->cfg[0] = (s->mgr_ns_at_rst ? 0x4 : 0) |
+                (s->num_periph_req > 0 ? 1 : 0) |
+                ((s->num_chnls - 1) & 0x7) << 4 |
+                ((s->num_periph_req - 1) & 0x1f) << 12 |
+                ((s->num_events - 1) & 0x1f) << 17;
+
+    switch (s->i_cache_len) {
+    case (4):
+        s->cfg[1] |= 2;
+        break;
+    case (8):
+        s->cfg[1] |= 3;
+        break;
+    case (16):
+        s->cfg[1] |= 4;
+        break;
+    case (32):
+        s->cfg[1] |= 5;
+        break;
+    default:
+        error_setg(errp, "Bad value for i-cache_len property: %d\n",
+                   s->i_cache_len);
+        return;
+    }
+    s->cfg[1] |= ((s->num_i_cache_lines - 1) & 0xf) << 4;
+
+    s->chan = g_new0(PL330Chan, s->num_chnls);
+    s->hi_seqn = g_new0(uint8_t, s->num_chnls);
+    s->lo_seqn = g_new0(uint8_t, s->num_chnls);
+    for (i = 0; i < s->num_chnls; i++) {
+        s->chan[i].parent = s;
+        s->chan[i].tag = (uint8_t)i;
+    }
+    s->manager.parent = s;
+    s->manager.tag = s->num_chnls;
+    s->manager.is_manager = true;
+
+    s->irq = g_new0(qemu_irq, s->num_events);
+    for (i = 0; i < s->num_events; i++) {
+        sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]);
+    }
+
+    qdev_init_gpio_in(dev, pl330_dma_stop_irq, PL330_PERIPH_NUM);
+
+    switch (s->data_width) {
+    case (32):
+        s->cfg[CFG_CRD] |= 0x2;
+        break;
+    case (64):
+        s->cfg[CFG_CRD] |= 0x3;
+        break;
+    case (128):
+        s->cfg[CFG_CRD] |= 0x4;
+        break;
+    default:
+        error_setg(errp, "Bad value for data_width property: %d\n",
+                   s->data_width);
+        return;
+    }
+
+    s->cfg[CFG_CRD] |= ((s->wr_cap - 1) & 0x7) << 4 |
+                    ((s->wr_q_dep - 1) & 0xf) << 8 |
+                    ((s->rd_cap - 1) & 0x7) << 12 |
+                    ((s->rd_q_dep - 1) & 0xf) << 16 |
+                    ((s->data_buffer_dep - 1) & 0x1ff) << 20;
+
+    pl330_queue_init(&s->read_queue, s->rd_q_dep, s);
+    pl330_queue_init(&s->write_queue, s->wr_q_dep, s);
+    pl330_fifo_init(&s->fifo, s->data_buffer_dep);
+}
+
+static Property pl330_properties[] = {
+    /* CR0 */
+    DEFINE_PROP_UINT32("num_chnls", PL330State, num_chnls, 8),
+    DEFINE_PROP_UINT8("num_periph_req", PL330State, num_periph_req, 4),
+    DEFINE_PROP_UINT8("num_events", PL330State, num_events, 16),
+    DEFINE_PROP_UINT8("mgr_ns_at_rst", PL330State, mgr_ns_at_rst, 0),
+    /* CR1 */
+    DEFINE_PROP_UINT8("i-cache_len", PL330State, i_cache_len, 4),
+    DEFINE_PROP_UINT8("num_i-cache_lines", PL330State, num_i_cache_lines, 8),
+    /* CR2-4 */
+    DEFINE_PROP_UINT32("boot_addr", PL330State, cfg[CFG_BOOT_ADDR], 0),
+    DEFINE_PROP_UINT32("INS", PL330State, cfg[CFG_INS], 0),
+    DEFINE_PROP_UINT32("PNS", PL330State, cfg[CFG_PNS], 0),
+    /* CRD */
+    DEFINE_PROP_UINT8("data_width", PL330State, data_width, 64),
+    DEFINE_PROP_UINT8("wr_cap", PL330State, wr_cap, 8),
+    DEFINE_PROP_UINT8("wr_q_dep", PL330State, wr_q_dep, 16),
+    DEFINE_PROP_UINT8("rd_cap", PL330State, rd_cap, 8),
+    DEFINE_PROP_UINT8("rd_q_dep", PL330State, rd_q_dep, 16),
+    DEFINE_PROP_UINT16("data_buffer_dep", PL330State, data_buffer_dep, 256),
+
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pl330_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = pl330_realize;
+    dc->reset = pl330_reset;
+    dc->props = pl330_properties;
+    dc->vmsd = &vmstate_pl330;
+}
+
+static const TypeInfo pl330_type_info = {
+    .name           = TYPE_PL330,
+    .parent         = TYPE_SYS_BUS_DEVICE,
+    .instance_size  = sizeof(PL330State),
+    .class_init      = pl330_class_init,
+};
+
+static void pl330_register_types(void)
+{
+    type_register_static(&pl330_type_info);
+}
+
+type_init(pl330_register_types)
commit 6ff66f50f0999c3455c39de68fc2d2949963c796
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Fri Mar 15 16:41:58 2013 +0000

    iov: Factor out hexdumper
    
    Factor out the hexdumper functionality from iov for all to use. Useful for
    creating verbose debug printfery that dumps packet data.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: faaac219c55ea586d3f748befaf5a2788fd271b8.1361853677.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/include/qemu-common.h b/include/qemu-common.h
index 5e13708..7754ee2 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -442,4 +442,10 @@ int64_t pow2floor(int64_t value);
 int uleb128_encode_small(uint8_t *out, uint32_t n);
 int uleb128_decode_small(const uint8_t *in, uint32_t *n);
 
+/*
+ * Hexdump a buffer to a file. An optional string prefix is added to every line
+ */
+
+void hexdump(const char *buf, FILE *fp, const char *prefix, size_t size);
+
 #endif
diff --git a/util/Makefile.objs b/util/Makefile.objs
index cad5ce8..557bda7 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -9,3 +9,4 @@ util-obj-y += error.o qemu-error.o
 util-obj-$(CONFIG_POSIX) += compatfd.o
 util-obj-y += iov.o aes.o qemu-config.o qemu-sockets.o uri.o notify.o
 util-obj-y += qemu-option.o qemu-progress.o
+util-obj-y += hexdump.o
diff --git a/util/hexdump.c b/util/hexdump.c
new file mode 100644
index 0000000..0d0efc8
--- /dev/null
+++ b/util/hexdump.c
@@ -0,0 +1,37 @@
+/*
+ * Helper to hexdump a buffer
+ *
+ * Copyright (c) 2013 Red Hat, Inc.
+ * Copyright (c) 2013 Gerd Hoffmann <kraxel at redhat.com>
+ * Copyright (c) 2013 Peter Crosthwaite <peter.crosthwaite at xilinx.com>
+ * Copyright (c) 2013 Xilinx, Inc
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "qemu-common.h"
+
+void hexdump(const char *buf, FILE *fp, const char *prefix, size_t size)
+{
+    unsigned int b;
+
+    for (b = 0; b < size; b++) {
+        if ((b % 16) == 0) {
+            fprintf(fp, "%s: %04x:", prefix, b);
+        }
+        if ((b % 4) == 0) {
+            fprintf(fp, " ");
+        }
+        fprintf(fp, " %02x", (unsigned char)buf[b]);
+        if ((b % 16) == 15) {
+            fprintf(fp, "\n");
+        }
+    }
+    if ((b % 16) != 0) {
+        fprintf(fp, "\n");
+    }
+}
diff --git a/util/iov.c b/util/iov.c
index fbe675d..9dae318 100644
--- a/util/iov.c
+++ b/util/iov.c
@@ -201,32 +201,18 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
 void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt,
                  FILE *fp, const char *prefix, size_t limit)
 {
-    unsigned int i, v, b;
-    uint8_t *c;
-
-    c = iov[0].iov_base;
-    for (i = 0, v = 0, b = 0; b < limit; i++, b++) {
-        if (i == iov[v].iov_len) {
-            i = 0; v++;
-            if (v == iov_cnt) {
-                break;
-            }
-            c = iov[v].iov_base;
-        }
-        if ((b % 16) == 0) {
-            fprintf(fp, "%s: %04x:", prefix, b);
-        }
-        if ((b % 4) == 0) {
-            fprintf(fp, " ");
-        }
-        fprintf(fp, " %02x", c[i]);
-        if ((b % 16) == 15) {
-            fprintf(fp, "\n");
-        }
-    }
-    if ((b % 16) != 0) {
-        fprintf(fp, "\n");
+    int v;
+    size_t size = 0;
+    char *buf;
+
+    for (v = 0; v < iov_cnt; v++) {
+        size += iov[v].iov_len;
     }
+    size = size > limit ? limit : size;
+    buf = g_malloc(size);
+    iov_to_buf(iov, iov_cnt, 0, buf, size);
+    hexdump(buf, fp, prefix, size);
+    g_free(buf);
 }
 
 unsigned iov_copy(struct iovec *dst_iov, unsigned int dst_iov_cnt,
commit 9c7d489379c2a2923b4805d337dfd54f2f432449
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 16:41:58 2013 +0000

    hw/vexpress: Set reset values for daughterboard oscillators
    
    Set the reset values for the VExpress daughterboard oscillators
    via the new sysctl properties.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index a2dc759..2e1a5d0 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -156,6 +156,8 @@ struct VEDBoardInfo {
     uint32_t proc_id;
     uint32_t num_voltage_sensors;
     const uint32_t *voltages;
+    uint32_t num_clocks;
+    const uint32_t *clocks;
     DBoardInitFn *init;
 };
 
@@ -260,6 +262,13 @@ static const uint32_t a9_voltages[] = {
     3300000, /* VCC3V3 : 3.3V : local board supply for misc external logic */
 };
 
+/* Reset values for daughterboard oscillators (in Hz) */
+static const uint32_t a9_clocks[] = {
+    45000000, /* AMBA AXI ACLK: 45MHz */
+    23750000, /* daughterboard CLCD clock: 23.75MHz */
+    66670000, /* Test chip reference clock: 66.67MHz */
+};
+
 static const VEDBoardInfo a9_daughterboard = {
     .motherboard_map = motherboard_legacy_map,
     .loader_start = 0x60000000,
@@ -267,6 +276,8 @@ static const VEDBoardInfo a9_daughterboard = {
     .proc_id = 0x0c000191,
     .num_voltage_sensors = ARRAY_SIZE(a9_voltages),
     .voltages = a9_voltages,
+    .num_clocks = ARRAY_SIZE(a9_clocks),
+    .clocks = a9_clocks,
     .init = a9_daughterboard_init,
 };
 
@@ -358,6 +369,18 @@ static const uint32_t a15_voltages[] = {
     900000, /* Vcore: 0.9V : CPU core voltage */
 };
 
+static const uint32_t a15_clocks[] = {
+    60000000, /* OSCCLK0: 60MHz : CPU_CLK reference */
+    0, /* OSCCLK1: reserved */
+    0, /* OSCCLK2: reserved */
+    0, /* OSCCLK3: reserved */
+    40000000, /* OSCCLK4: 40MHz : external AXI master clock */
+    23750000, /* OSCCLK5: 23.75MHz : HDLCD PLL reference */
+    50000000, /* OSCCLK6: 50MHz : static memory controller clock */
+    60000000, /* OSCCLK7: 60MHz : SYSCLK reference */
+    40000000, /* OSCCLK8: 40MHz : DDR2 PLL reference */
+};
+
 static const VEDBoardInfo a15_daughterboard = {
     .motherboard_map = motherboard_aseries_map,
     .loader_start = 0x80000000,
@@ -365,6 +388,8 @@ static const VEDBoardInfo a15_daughterboard = {
     .proc_id = 0x14000237,
     .num_voltage_sensors = ARRAY_SIZE(a15_voltages),
     .voltages = a15_voltages,
+    .num_clocks = ARRAY_SIZE(a15_clocks),
+    .clocks = a15_clocks,
     .init = a15_daughterboard_init,
 };
 
@@ -400,6 +425,13 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
         qdev_prop_set_uint32(sysctl, propname, daughterboard->voltages[i]);
         g_free(propname);
     }
+    qdev_prop_set_uint32(sysctl, "len-db-clock",
+                         daughterboard->num_clocks);
+    for (i = 0; i < daughterboard->num_clocks; i++) {
+        char *propname = g_strdup_printf("db-clock[%d]", i);
+        qdev_prop_set_uint32(sysctl, propname, daughterboard->clocks[i]);
+        g_free(propname);
+    }
     qdev_init_nofail(sysctl);
     sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, map[VE_SYSREGS]);
 
commit 1f81f94bebc2f8c4b32a89910d071099a67dc44d
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 16:41:57 2013 +0000

    hw/arm_sysctl: Implement SYS_CFG_OSC function
    
    Implement the SYS_CFG_OSC function. Since the idea of
    programmable clock rates doesn't make much sense for QEMU,
    we simply allow the clock rate to be read back as written.
    The number and value of the daughterboard oscillators varies
    between daughterboards, so we provide an array property to
    allow their reset values to be configured.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index e2f00d3..25fc6ea 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -35,13 +35,17 @@ typedef struct {
     uint32_t sys_cfgctrl;
     uint32_t sys_cfgstat;
     uint32_t sys_clcd;
+    uint32_t mb_clock[6];
+    uint32_t *db_clock;
     uint32_t db_num_vsensors;
     uint32_t *db_voltage;
+    uint32_t db_num_clocks;
+    uint32_t *db_clock_reset;
 } arm_sysctl_state;
 
 static const VMStateDescription vmstate_arm_sysctl = {
     .name = "realview_sysctl",
-    .version_id = 3,
+    .version_id = 4,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(leds, arm_sysctl_state),
@@ -56,6 +60,9 @@ static const VMStateDescription vmstate_arm_sysctl = {
         VMSTATE_UINT32_V(sys_cfgctrl, arm_sysctl_state, 2),
         VMSTATE_UINT32_V(sys_cfgstat, arm_sysctl_state, 2),
         VMSTATE_UINT32_V(sys_clcd, arm_sysctl_state, 3),
+        VMSTATE_UINT32_ARRAY_V(mb_clock, arm_sysctl_state, 6, 4),
+        VMSTATE_VARRAY_UINT32(db_clock, arm_sysctl_state, db_num_clocks,
+                              4, vmstate_info_uint32, uint32_t),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -79,6 +86,7 @@ static int board_id(arm_sysctl_state *s)
 static void arm_sysctl_reset(DeviceState *d)
 {
     arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, SYS_BUS_DEVICE(d));
+    int i;
 
     s->leds = 0;
     s->lockval = 0;
@@ -86,6 +94,17 @@ static void arm_sysctl_reset(DeviceState *d)
     s->cfgdata2 = 0;
     s->flags = 0;
     s->resetlevel = 0;
+    /* Motherboard oscillators (in Hz) */
+    s->mb_clock[0] = 50000000; /* Static memory clock: 50MHz */
+    s->mb_clock[1] = 23750000; /* motherboard CLCD clock: 23.75MHz */
+    s->mb_clock[2] = 24000000; /* IO FPGA peripheral clock: 24MHz */
+    s->mb_clock[3] = 24000000; /* IO FPGA reserved clock: 24MHz */
+    s->mb_clock[4] = 24000000; /* System bus global clock: 24MHz */
+    s->mb_clock[5] = 24000000; /* IO FPGA reserved clock: 24MHz */
+    /* Daughterboard oscillators: reset from property values */
+    for (i = 0; i < s->db_num_clocks; i++) {
+        s->db_clock[i] = s->db_clock_reset[i];
+    }
     if (board_id(s) == BOARD_ID_VEXPRESS) {
         /* On VExpress this register will RAZ/WI */
         s->sys_clcd = 0;
@@ -251,6 +270,18 @@ static bool vexpress_cfgctrl_read(arm_sysctl_state *s, unsigned int dcc,
             return true;
         }
         break;
+    case SYS_CFG_OSC:
+        if (site == SYS_CFG_SITE_MB && device < sizeof(s->mb_clock)) {
+            /* motherboard clock */
+            *val = s->mb_clock[device];
+            return true;
+        }
+        if (site == SYS_CFG_SITE_DB1 && device < s->db_num_clocks) {
+            /* daughterboard clock */
+            *val = s->db_clock[device];
+            return true;
+        }
+        break;
     default:
         break;
     }
@@ -287,6 +318,18 @@ static bool vexpress_cfgctrl_write(arm_sysctl_state *s, unsigned int dcc,
     }
 
     switch (function) {
+    case SYS_CFG_OSC:
+        if (site == SYS_CFG_SITE_MB && device < sizeof(s->mb_clock)) {
+            /* motherboard clock */
+            s->mb_clock[device] = val;
+            return true;
+        }
+        if (site == SYS_CFG_SITE_DB1 && device < s->db_num_clocks) {
+            /* daughterboard clock */
+            s->db_clock[device] = val;
+            return true;
+        }
+        break;
     case SYS_CFG_MUXFPGA:
         if (site == SYS_CFG_SITE_MB && device == 0) {
             /* Select whether video output comes from motherboard
@@ -552,11 +595,19 @@ static void arm_sysctl_init(Object *obj)
     qdev_init_gpio_out(dev, &s->pl110_mux_ctrl, 1);
 }
 
+static void arm_sysctl_realize(DeviceState *d, Error **errp)
+{
+    arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, SYS_BUS_DEVICE(d));
+    s->db_clock = g_new0(uint32_t, s->db_num_clocks);
+}
+
 static void arm_sysctl_finalize(Object *obj)
 {
     SysBusDevice *dev = SYS_BUS_DEVICE(obj);
     arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev);
     g_free(s->db_voltage);
+    g_free(s->db_clock);
+    g_free(s->db_clock_reset);
 }
 
 static Property arm_sysctl_properties[] = {
@@ -565,6 +616,9 @@ static Property arm_sysctl_properties[] = {
     /* Daughterboard power supply voltages (as reported via SYS_CFG) */
     DEFINE_PROP_ARRAY("db-voltage", arm_sysctl_state, db_num_vsensors,
                       db_voltage, qdev_prop_uint32, uint32_t),
+    /* Daughterboard clock reset values (as reported via SYS_CFG) */
+    DEFINE_PROP_ARRAY("db-clock", arm_sysctl_state, db_num_clocks,
+                      db_clock_reset, qdev_prop_uint32, uint32_t),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -572,6 +626,7 @@ static void arm_sysctl_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
+    dc->realize = arm_sysctl_realize;
     dc->reset = arm_sysctl_reset;
     dc->vmsd = &vmstate_arm_sysctl;
     dc->props = arm_sysctl_properties;
commit 31410948bc1c8001098b076caf35aab8a5cf063d
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 16:41:57 2013 +0000

    hw/vexpress: Pass voltage sensor properties to sysctl device
    
    Pass voltage sensor properties to the sysctl device. Since
    these are daughterboard specific, we specify them via the
    VEDBoardInfo structure.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1359985476-29380-9-git-send-email-peter.maydell at linaro.org

diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index 47a844f..a2dc759 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -154,6 +154,8 @@ struct VEDBoardInfo {
     hwaddr loader_start;
     const hwaddr gic_cpu_if_addr;
     uint32_t proc_id;
+    uint32_t num_voltage_sensors;
+    const uint32_t *voltages;
     DBoardInitFn *init;
 };
 
@@ -246,11 +248,25 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
     sysbus_create_varargs("l2x0", 0x1e00a000, NULL);
 }
 
+/* Voltage values for SYS_CFG_VOLT daughterboard registers;
+ * values are in microvolts.
+ */
+static const uint32_t a9_voltages[] = {
+    1000000, /* VD10 : 1.0V : SoC internal logic voltage */
+    1000000, /* VD10_S2 : 1.0V : PL310, L2 cache, RAM, non-PL310 logic */
+    1000000, /* VD10_S3 : 1.0V : Cortex-A9, cores, MPEs, SCU, PL310 logic */
+    1800000, /* VCC1V8 : 1.8V : DDR2 SDRAM, test chip DDR2 I/O supply */
+    900000, /* DDR2VTT : 0.9V : DDR2 SDRAM VTT termination voltage */
+    3300000, /* VCC3V3 : 3.3V : local board supply for misc external logic */
+};
+
 static const VEDBoardInfo a9_daughterboard = {
     .motherboard_map = motherboard_legacy_map,
     .loader_start = 0x60000000,
     .gic_cpu_if_addr = 0x1e000100,
     .proc_id = 0x0c000191,
+    .num_voltage_sensors = ARRAY_SIZE(a9_voltages),
+    .voltages = a9_voltages,
     .init = a9_daughterboard_init,
 };
 
@@ -338,11 +354,17 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
     /* 0x7ffd0000: PL354 static memory controller: not modelled */
 }
 
+static const uint32_t a15_voltages[] = {
+    900000, /* Vcore: 0.9V : CPU core voltage */
+};
+
 static const VEDBoardInfo a15_daughterboard = {
     .motherboard_map = motherboard_aseries_map,
     .loader_start = 0x80000000,
     .gic_cpu_if_addr = 0x2c002000,
     .proc_id = 0x14000237,
+    .num_voltage_sensors = ARRAY_SIZE(a15_voltages),
+    .voltages = a15_voltages,
     .init = a15_daughterboard_init,
 };
 
@@ -358,6 +380,7 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
     MemoryRegion *vram = g_new(MemoryRegion, 1);
     MemoryRegion *sram = g_new(MemoryRegion, 1);
     const hwaddr *map = daughterboard->motherboard_map;
+    int i;
 
     daughterboard->init(daughterboard, args->ram_size, args->cpu_model, pic);
 
@@ -370,6 +393,13 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
     sysctl = qdev_create(NULL, "realview_sysctl");
     qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
     qdev_prop_set_uint32(sysctl, "proc_id", daughterboard->proc_id);
+    qdev_prop_set_uint32(sysctl, "len-db-voltage",
+                         daughterboard->num_voltage_sensors);
+    for (i = 0; i < daughterboard->num_voltage_sensors; i++) {
+        char *propname = g_strdup_printf("db-voltage[%d]", i);
+        qdev_prop_set_uint32(sysctl, propname, daughterboard->voltages[i]);
+        g_free(propname);
+    }
     qdev_init_nofail(sysctl);
     sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, map[VE_SYSREGS]);
 
commit 8bd4824a6122292060a318741595927e0d05ff5e
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 16:41:57 2013 +0000

    hw/arm_sysctl: Implement SYS_CFG_VOLT
    
    Implement the SYS_CFG_VOLT registers which return the voltage
    of various supplies on motherboard and daughterboard. Since
    QEMU implements a perfectly stable power supply these registers
    always return a constant value. The number and value of the
    daughterboard voltages is dependent on the specific daughterboard,
    so we use a property array to allow the board to configure them
    appropriately.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index 7c94b78..e2f00d3 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -35,6 +35,8 @@ typedef struct {
     uint32_t sys_cfgctrl;
     uint32_t sys_cfgstat;
     uint32_t sys_clcd;
+    uint32_t db_num_vsensors;
+    uint32_t *db_voltage;
 } arm_sysctl_state;
 
 static const VMStateDescription vmstate_arm_sysctl = {
@@ -236,6 +238,19 @@ static bool vexpress_cfgctrl_read(arm_sysctl_state *s, unsigned int dcc,
     }
 
     switch (function) {
+    case SYS_CFG_VOLT:
+        if (site == SYS_CFG_SITE_DB1 && device < s->db_num_vsensors) {
+            *val = s->db_voltage[device];
+            return true;
+        }
+        if (site == SYS_CFG_SITE_MB && device == 0) {
+            /* There is only one motherboard voltage sensor:
+             * VIO : 3.3V : bus voltage between mother and daughterboard
+             */
+            *val = 3300000;
+            return true;
+        }
+        break;
     default:
         break;
     }
@@ -537,9 +552,19 @@ static void arm_sysctl_init(Object *obj)
     qdev_init_gpio_out(dev, &s->pl110_mux_ctrl, 1);
 }
 
+static void arm_sysctl_finalize(Object *obj)
+{
+    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+    arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev);
+    g_free(s->db_voltage);
+}
+
 static Property arm_sysctl_properties[] = {
     DEFINE_PROP_UINT32("sys_id", arm_sysctl_state, sys_id, 0),
     DEFINE_PROP_UINT32("proc_id", arm_sysctl_state, proc_id, 0),
+    /* Daughterboard power supply voltages (as reported via SYS_CFG) */
+    DEFINE_PROP_ARRAY("db-voltage", arm_sysctl_state, db_num_vsensors,
+                      db_voltage, qdev_prop_uint32, uint32_t),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -557,6 +582,7 @@ static const TypeInfo arm_sysctl_info = {
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(arm_sysctl_state),
     .instance_init = arm_sysctl_init,
+    .instance_finalize = arm_sysctl_finalize,
     .class_init    = arm_sysctl_class_init,
 };
 
commit 0be6bfac6262900425c10847de513ee2490078d3
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 16:41:57 2013 +0000

    qdev: Implement (variable length) array properties
    
    Add support for declaring array properties for qdev devices.
    These work by defining an initial static property 'len-arrayname'
    which the user of the device should set to the desired size
    of the array. When this property is set, memory is allocated
    for the array elements, and dynamic properties "arrayname[0]",
    "arrayname[1]"... are created so the user of the device can
    then set the values of the individual array elements.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/qdev-core.h b/hw/qdev-core.h
index 2486f36..547fbc7 100644
--- a/hw/qdev-core.h
+++ b/hw/qdev-core.h
@@ -175,6 +175,9 @@ struct Property {
     uint8_t      bitnr;
     uint8_t      qtype;
     int64_t      defval;
+    int          arrayoffset;
+    PropertyInfo *arrayinfo;
+    int          arrayfieldsize;
 };
 
 struct PropertyInfo {
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 0307a78..247ca6c 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -779,6 +779,110 @@ PropertyInfo qdev_prop_pci_host_devaddr = {
     .set = set_pci_host_devaddr,
 };
 
+/* --- support for array properties --- */
+
+/* Used as an opaque for the object properties we add for each
+ * array element. Note that the struct Property must be first
+ * in the struct so that a pointer to this works as the opaque
+ * for the underlying element's property hooks as well as for
+ * our own release callback.
+ */
+typedef struct {
+    struct Property prop;
+    char *propname;
+    ObjectPropertyRelease *release;
+} ArrayElementProperty;
+
+/* object property release callback for array element properties:
+ * we call the underlying element's property release hook, and
+ * then free the memory we allocated when we added the property.
+ */
+static void array_element_release(Object *obj, const char *name, void *opaque)
+{
+    ArrayElementProperty *p = opaque;
+    if (p->release) {
+        p->release(obj, name, opaque);
+    }
+    g_free(p->propname);
+    g_free(p);
+}
+
+static void set_prop_arraylen(Object *obj, Visitor *v, void *opaque,
+                              const char *name, Error **errp)
+{
+    /* Setter for the property which defines the length of a
+     * variable-sized property array. As well as actually setting the
+     * array-length field in the device struct, we have to create the
+     * array itself and dynamically add the corresponding properties.
+     */
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    uint32_t *alenptr = qdev_get_prop_ptr(dev, prop);
+    void **arrayptr = (void *)dev + prop->arrayoffset;
+    void *eltptr;
+    const char *arrayname;
+    int i;
+
+    if (dev->realized) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+    if (*alenptr) {
+        error_setg(errp, "array size property %s may not be set more than once",
+                   name);
+        return;
+    }
+    visit_type_uint32(v, alenptr, name, errp);
+    if (error_is_set(errp)) {
+        return;
+    }
+    if (!*alenptr) {
+        return;
+    }
+
+    /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;
+     * strip it off so we can get the name of the array itself.
+     */
+    assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
+                   strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
+    arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);
+
+    /* Note that it is the responsibility of the individual device's deinit
+     * to free the array proper.
+     */
+    *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
+    for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
+        char *propname = g_strdup_printf("%s[%d]", arrayname, i);
+        ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1);
+        arrayprop->release = prop->arrayinfo->release;
+        arrayprop->propname = propname;
+        arrayprop->prop.info = prop->arrayinfo;
+        arrayprop->prop.name = propname;
+        /* This ugly piece of pointer arithmetic sets up the offset so
+         * that when the underlying get/set hooks call qdev_get_prop_ptr
+         * they get the right answer despite the array element not actually
+         * being inside the device struct.
+         */
+        arrayprop->prop.offset = eltptr - (void *)dev;
+        assert(qdev_get_prop_ptr(dev, &arrayprop->prop) == eltptr);
+        object_property_add(obj, propname,
+                            arrayprop->prop.info->name,
+                            arrayprop->prop.info->get,
+                            arrayprop->prop.info->set,
+                            array_element_release,
+                            arrayprop, errp);
+        if (error_is_set(errp)) {
+            return;
+        }
+    }
+}
+
+PropertyInfo qdev_prop_arraylen = {
+    .name = "uint32",
+    .get = get_uint32,
+    .set = set_prop_arraylen,
+};
+
 /* --- public helpers --- */
 
 static Property *qdev_prop_walk(Property *props, const char *name)
diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h
index 0b0465c..c9bb246 100644
--- a/hw/qdev-properties.h
+++ b/hw/qdev-properties.h
@@ -26,6 +26,7 @@ extern PropertyInfo qdev_prop_vlan;
 extern PropertyInfo qdev_prop_pci_devfn;
 extern PropertyInfo qdev_prop_blocksize;
 extern PropertyInfo qdev_prop_pci_host_devaddr;
+extern PropertyInfo qdev_prop_arraylen;
 
 #define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
         .name      = (_name),                                    \
@@ -51,6 +52,44 @@ extern PropertyInfo qdev_prop_pci_host_devaddr;
         .defval    = (bool)_defval,                              \
         }
 
+#define PROP_ARRAY_LEN_PREFIX "len-"
+
+/**
+ * DEFINE_PROP_ARRAY:
+ * @_name: name of the array
+ * @_state: name of the device state structure type
+ * @_field: uint32_t field in @_state to hold the array length
+ * @_arrayfield: field in @_state (of type '@_arraytype *') which
+ *               will point to the array
+ * @_arrayprop: PropertyInfo defining what property the array elements have
+ * @_arraytype: C type of the array elements
+ *
+ * Define device properties for a variable-length array _name.  A
+ * static property "len-arrayname" is defined. When the device creator
+ * sets this property to the desired length of array, further dynamic
+ * properties "arrayname[0]", "arrayname[1]", ...  are defined so the
+ * device creator can set the array element values. Setting the
+ * "len-arrayname" property more than once is an error.
+ *
+ * When the array length is set, the @_field member of the device
+ * struct is set to the array length, and @_arrayfield is set to point
+ * to (zero-initialised) memory allocated for the array.  For a zero
+ * length array, @_field will be set to 0 and @_arrayfield to NULL.
+ * It is the responsibility of the device deinit code to free the
+ * @_arrayfield memory.
+ */
+#define DEFINE_PROP_ARRAY(_name, _state, _field,                        \
+                          _arrayfield, _arrayprop, _arraytype) {        \
+        .name = (PROP_ARRAY_LEN_PREFIX _name),                          \
+        .info = &(qdev_prop_arraylen),                                  \
+        .offset = offsetof(_state, _field)                              \
+            + type_check(uint32_t, typeof_field(_state, _field)),       \
+        .qtype = QTYPE_QINT,                                            \
+        .arrayinfo = &(_arrayprop),                                     \
+        .arrayfieldsize = sizeof(_arraytype),                           \
+        .arrayoffset = offsetof(_state, _arrayfield),                   \
+        }
+
 #define DEFINE_PROP_UINT8(_n, _s, _f, _d)                       \
     DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
 #define DEFINE_PROP_UINT16(_n, _s, _f, _d)                      \
commit 1f56f50ac484653fe996c37ac894418a34f92b89
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 16:41:56 2013 +0000

    hw/arm_sysctl: Convert from qdev init to instance_init
    
    Convert this device from old-style qdev init to an instance_init
    function. We don't need a realize function yet, though.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index 840bfad..7c94b78 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -525,15 +525,16 @@ static void arm_sysctl_gpio_set(void *opaque, int line, int level)
     }
 }
 
-static int arm_sysctl_init(SysBusDevice *dev)
+static void arm_sysctl_init(Object *obj)
 {
-    arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev);
+    DeviceState *dev = DEVICE(obj);
+    SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+    arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, sd);
 
     memory_region_init_io(&s->iomem, &arm_sysctl_ops, s, "arm-sysctl", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    qdev_init_gpio_in(&s->busdev.qdev, arm_sysctl_gpio_set, 2);
-    qdev_init_gpio_out(&s->busdev.qdev, &s->pl110_mux_ctrl, 1);
-    return 0;
+    sysbus_init_mmio(sd, &s->iomem);
+    qdev_init_gpio_in(dev, arm_sysctl_gpio_set, 2);
+    qdev_init_gpio_out(dev, &s->pl110_mux_ctrl, 1);
 }
 
 static Property arm_sysctl_properties[] = {
@@ -545,9 +546,7 @@ static Property arm_sysctl_properties[] = {
 static void arm_sysctl_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
-    k->init = arm_sysctl_init;
     dc->reset = arm_sysctl_reset;
     dc->vmsd = &vmstate_arm_sysctl;
     dc->props = arm_sysctl_properties;
@@ -557,6 +556,7 @@ static const TypeInfo arm_sysctl_info = {
     .name          = "realview_sysctl",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(arm_sysctl_state),
+    .instance_init = arm_sysctl_init,
     .class_init    = arm_sysctl_class_init,
 };
 
commit 291155cbc54212a451d0b899a01b6e3e14ed9135
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 16:41:56 2013 +0000

    hw/arm_sysctl: Implement SYS_CFG_DVIMODE as a no-op
    
    SYS_CFG_DVIMODE allows the guest to select whether the
    output DVI signal is VGA, SVGA, XGA, SGA or UXGA. Since
    this makes no difference to QEMU, implement writes as a
    no-op so Linux doesn't complain.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index a6e5ed4..840bfad 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -295,6 +295,14 @@ static bool vexpress_cfgctrl_write(arm_sysctl_state *s, unsigned int dcc,
             return true;
         }
         break;
+    case SYS_CFG_DVIMODE:
+        if (site == SYS_CFG_SITE_MB && device == 0) {
+            /* Selecting DVI mode is meaningless for QEMU: we will
+             * always display the output correctly according to the
+             * pixel height/width programmed into the CLCD controller.
+             */
+            return true;
+        }
     default:
         break;
     }
commit 8ff05c9842e28888b936dbd960f6416cee5addb6
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 16:41:56 2013 +0000

    hw/arm_sysctl: Implement SYS_CFG_MUXFPGA writes as a no-op
    
    SYS_CFG_MUXFPGA allows the guest to select whether the
    video output should come from the motherboard's LCD
    controller or the daughterboard's one. Since QEMU doesn't
    currently support selecting the video output like this,
    implement as a no-op, so Linux doesn't complain about
    the register not being implemented.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index 05a3200..a6e5ed4 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -272,6 +272,17 @@ static bool vexpress_cfgctrl_write(arm_sysctl_state *s, unsigned int dcc,
     }
 
     switch (function) {
+    case SYS_CFG_MUXFPGA:
+        if (site == SYS_CFG_SITE_MB && device == 0) {
+            /* Select whether video output comes from motherboard
+             * or daughterboard: log and ignore as QEMU doesn't
+             * support this.
+             */
+            qemu_log_mask(LOG_UNIMP, "arm_sysctl: selection of video output "
+                          "not supported, ignoring\n");
+            return true;
+        }
+        break;
     case SYS_CFG_SHUTDOWN:
         if (site == SYS_CFG_SITE_MB && device == 0) {
             qemu_system_shutdown_request();
commit 71538323358d77f6472d66a30e948a1c23bd9e87
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 16:41:56 2013 +0000

    hw/arm_sysctl: Handle SYS_CFGCTRL in a more structured way
    
    The SYS_CFGCTRL register consists of separate fields
    for DCC, function, site, position and device, as well
    as a read/write bit. Refactor the code handling SYS_CFGCTRL
    writes to make it easier to add support for functions
    like SYS_CFG_OSC which support multiple device fields.
    We also pull the handling out into its own function for
    clarity, as there are potentially a lot of implementable
    subfunctions.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index a46f8d4..05a3200 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -9,6 +9,7 @@
 
 #include "hw/hw.h"
 #include "qemu/timer.h"
+#include "qemu/bitops.h"
 #include "hw/sysbus.h"
 #include "hw/primecell.h"
 #include "sysemu/sysemu.h"
@@ -191,6 +192,110 @@ static uint64_t arm_sysctl_read(void *opaque, hwaddr offset,
     }
 }
 
+/* SYS_CFGCTRL functions */
+#define SYS_CFG_OSC 1
+#define SYS_CFG_VOLT 2
+#define SYS_CFG_AMP 3
+#define SYS_CFG_TEMP 4
+#define SYS_CFG_RESET 5
+#define SYS_CFG_SCC 6
+#define SYS_CFG_MUXFPGA 7
+#define SYS_CFG_SHUTDOWN 8
+#define SYS_CFG_REBOOT 9
+#define SYS_CFG_DVIMODE 11
+#define SYS_CFG_POWER 12
+#define SYS_CFG_ENERGY 13
+
+/* SYS_CFGCTRL site field values */
+#define SYS_CFG_SITE_MB 0
+#define SYS_CFG_SITE_DB1 1
+#define SYS_CFG_SITE_DB2 2
+
+/**
+ * vexpress_cfgctrl_read:
+ * @s: arm_sysctl_state pointer
+ * @dcc, @function, @site, @position, @device: split out values from
+ * SYS_CFGCTRL register
+ * @val: pointer to where to put the read data on success
+ *
+ * Handle a VExpress SYS_CFGCTRL register read. On success, return true and
+ * write the read value to *val. On failure, return false (and val may
+ * or may not be written to).
+ */
+static bool vexpress_cfgctrl_read(arm_sysctl_state *s, unsigned int dcc,
+                                  unsigned int function, unsigned int site,
+                                  unsigned int position, unsigned int device,
+                                  uint32_t *val)
+{
+    /* We don't support anything other than DCC 0, board stack position 0
+     * or sites other than motherboard/daughterboard:
+     */
+    if (dcc != 0 || position != 0 ||
+        (site != SYS_CFG_SITE_MB && site != SYS_CFG_SITE_DB1)) {
+        goto cfgctrl_unimp;
+    }
+
+    switch (function) {
+    default:
+        break;
+    }
+
+cfgctrl_unimp:
+    qemu_log_mask(LOG_UNIMP,
+                  "arm_sysctl: Unimplemented SYS_CFGCTRL read of function "
+                  "0x%x DCC 0x%x site 0x%x position 0x%x device 0x%x\n",
+                  function, dcc, site, position, device);
+    return false;
+}
+
+/**
+ * vexpress_cfgctrl_write:
+ * @s: arm_sysctl_state pointer
+ * @dcc, @function, @site, @position, @device: split out values from
+ * SYS_CFGCTRL register
+ * @val: data to write
+ *
+ * Handle a VExpress SYS_CFGCTRL register write. On success, return true.
+ * On failure, return false.
+ */
+static bool vexpress_cfgctrl_write(arm_sysctl_state *s, unsigned int dcc,
+                                   unsigned int function, unsigned int site,
+                                   unsigned int position, unsigned int device,
+                                   uint32_t val)
+{
+    /* We don't support anything other than DCC 0, board stack position 0
+     * or sites other than motherboard/daughterboard:
+     */
+    if (dcc != 0 || position != 0 ||
+        (site != SYS_CFG_SITE_MB && site != SYS_CFG_SITE_DB1)) {
+        goto cfgctrl_unimp;
+    }
+
+    switch (function) {
+    case SYS_CFG_SHUTDOWN:
+        if (site == SYS_CFG_SITE_MB && device == 0) {
+            qemu_system_shutdown_request();
+            return true;
+        }
+        break;
+    case SYS_CFG_REBOOT:
+        if (site == SYS_CFG_SITE_MB && device == 0) {
+            qemu_system_reset_request();
+            return true;
+        }
+        break;
+    default:
+        break;
+    }
+
+cfgctrl_unimp:
+    qemu_log_mask(LOG_UNIMP,
+                  "arm_sysctl: Unimplemented SYS_CFGCTRL write of function "
+                  "0x%x DCC 0x%x site 0x%x position 0x%x device 0x%x\n",
+                  function, dcc, site, position, device);
+    return false;
+}
+
 static void arm_sysctl_write(void *opaque, hwaddr offset,
                              uint64_t val, unsigned size)
 {
@@ -322,17 +427,33 @@ static void arm_sysctl_write(void *opaque, hwaddr offset,
         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 */
+        /* Undefined bits [19:18] are RAZ/WI, and writing to
+         * the start bit just triggers the action; it always reads
+         * as zero.
+         */
+        s->sys_cfgctrl = val & ~((3 << 18) | (1 << 31));
+        if (val & (1 << 31)) {
+            /* Start bit set -- actually do something */
+            unsigned int dcc = extract32(s->sys_cfgctrl, 26, 4);
+            unsigned int function = extract32(s->sys_cfgctrl, 20, 6);
+            unsigned int site = extract32(s->sys_cfgctrl, 16, 2);
+            unsigned int position = extract32(s->sys_cfgctrl, 12, 4);
+            unsigned int device = extract32(s->sys_cfgctrl, 0, 12);
+            s->sys_cfgstat = 1;            /* complete */
+            if (s->sys_cfgctrl & (1 << 30)) {
+                if (!vexpress_cfgctrl_write(s, dcc, function, site, position,
+                                            device, s->sys_cfgdata)) {
+                    s->sys_cfgstat |= 2;        /* error */
+                }
+            } else {
+                uint32_t val;
+                if (!vexpress_cfgctrl_read(s, dcc, function, site, position,
+                                           device, &val)) {
+                    s->sys_cfgstat |= 2;        /* error */
+                } else {
+                    s->sys_cfgdata = val;
+                }
+            }
         }
         s->sys_cfgctrl &= ~(1 << 31);
         return;
commit cdef10bb9373c2c22c517a4deef2363c7ebd5d48
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 16:41:56 2013 +0000

    hw/vexpress: Pass proc_id via VEDBoardInfo
    
    Pass the daughterboard-specific proc_id property to the code that
    creates the sysctl device via the VEDBoardInfo struct, rather than
    by having the daughterboard init function write to a uint32_t*
    argument. This is a cleaner way to pass the info around, and
    is in line with the way we are going to handle voltage and
    oscillator initialization.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index 02922c3..47a844f 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -147,19 +147,20 @@ typedef struct VEDBoardInfo VEDBoardInfo;
 typedef void DBoardInitFn(const VEDBoardInfo *daughterboard,
                           ram_addr_t ram_size,
                           const char *cpu_model,
-                          qemu_irq *pic, uint32_t *proc_id);
+                          qemu_irq *pic);
 
 struct VEDBoardInfo {
     const hwaddr *motherboard_map;
     hwaddr loader_start;
     const hwaddr gic_cpu_if_addr;
+    uint32_t proc_id;
     DBoardInitFn *init;
 };
 
 static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
                                   ram_addr_t ram_size,
                                   const char *cpu_model,
-                                  qemu_irq *pic, uint32_t *proc_id)
+                                  qemu_irq *pic)
 {
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
@@ -175,8 +176,6 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
         cpu_model = "cortex-a9";
     }
 
-    *proc_id = 0x0c000191;
-
     for (n = 0; n < smp_cpus; n++) {
         ARMCPU *cpu = cpu_arm_init(cpu_model);
         if (!cpu) {
@@ -251,13 +250,14 @@ static const VEDBoardInfo a9_daughterboard = {
     .motherboard_map = motherboard_legacy_map,
     .loader_start = 0x60000000,
     .gic_cpu_if_addr = 0x1e000100,
+    .proc_id = 0x0c000191,
     .init = a9_daughterboard_init,
 };
 
 static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
                                    ram_addr_t ram_size,
                                    const char *cpu_model,
-                                   qemu_irq *pic, uint32_t *proc_id)
+                                   qemu_irq *pic)
 {
     int n;
     MemoryRegion *sysmem = get_system_memory();
@@ -271,8 +271,6 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
         cpu_model = "cortex-a15";
     }
 
-    *proc_id = 0x14000237;
-
     for (n = 0; n < smp_cpus; n++) {
         ARMCPU *cpu;
         qemu_irq *irqp;
@@ -344,6 +342,7 @@ static const VEDBoardInfo a15_daughterboard = {
     .motherboard_map = motherboard_aseries_map,
     .loader_start = 0x80000000,
     .gic_cpu_if_addr = 0x2c002000,
+    .proc_id = 0x14000237,
     .init = a15_daughterboard_init,
 };
 
@@ -352,7 +351,6 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
 {
     DeviceState *dev, *sysctl, *pl041;
     qemu_irq pic[64];
-    uint32_t proc_id;
     uint32_t sys_id;
     DriveInfo *dinfo;
     ram_addr_t vram_size, sram_size;
@@ -361,8 +359,7 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
     MemoryRegion *sram = g_new(MemoryRegion, 1);
     const hwaddr *map = daughterboard->motherboard_map;
 
-    daughterboard->init(daughterboard, args->ram_size, args->cpu_model,
-                        pic, &proc_id);
+    daughterboard->init(daughterboard, args->ram_size, args->cpu_model, pic);
 
     /* Motherboard peripherals: the wiring is the same but the
      * addresses vary between the legacy and A-Series memory maps.
@@ -372,7 +369,7 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
 
     sysctl = qdev_create(NULL, "realview_sysctl");
     qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
-    qdev_prop_set_uint32(sysctl, "proc_id", proc_id);
+    qdev_prop_set_uint32(sysctl, "proc_id", daughterboard->proc_id);
     qdev_init_nofail(sysctl);
     sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, map[VE_SYSREGS]);
 
commit b1999e87b4d42305419329cae459e1b43f706d96
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 13:57:28 2013 +1100

    Fix TAGS creation
    
    Currently the Makefile creates TAGS for emacs with the command:
        find "$(SRC_PATH)" -name '*.[hc]' -print0 | xargs -0 etags
    That works only if xargs ends up invoking etags just once.  If xargs runs
    etags several times, as it will if there are enough files, then the later
    invocations will overwrite the output from the earlier invocations.  This
    patch uses the etags --append option to fix the bug.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Message-id: 1363057048-21534-1-git-send-email-david at gibson.dropbear.id.au
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index 12c7662..6915178 100644
--- a/Makefile
+++ b/Makefile
@@ -334,7 +334,8 @@ test speed: all
 
 .PHONY: TAGS
 TAGS:
-	find "$(SRC_PATH)" -name '*.[hc]' -print0 | xargs -0 etags
+	rm -f $@
+	find "$(SRC_PATH)" -name '*.[hc]' -exec etags --append {} +
 
 cscope:
 	rm -f ./cscope.*
commit dc0b0616f726956001be09e9a65a6e0b0bd939db
Merge: d4d7682 3618a09
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Mar 15 10:47:21 2013 -0500

    Merge remote-tracking branch 'stefanha/block' into staging
    
    # By Stefan Hajnoczi (14) and others
    # Via Stefan Hajnoczi
    * stefanha/block: (28 commits)
      blockdev: Fix up copyright and permission notice
      qemu-iotests: use -nographic in test case 007
      qemu-iotests: add tests for rebasing zero clusters
      dataplane: fix hang introduced by AioContext transition
      coroutine: use AioContext for CoQueue BH
      threadpool: drop global thread pool
      block: add bdrv_get_aio_context()
      aio: add a ThreadPool instance to AioContext
      threadpool: add thread_pool_new() and thread_pool_free()
      threadpool: move globals into struct ThreadPool
      main-loop: add qemu_get_aio_context()
      sheepdog: set io_flush handler in do_co_req
      sheepdog: use non-blocking fd in coroutine context
      qcow2: make is_allocated return true for zero clusters
      qcow2: drop unnecessary flush in qcow2_update_snapshot_refcount()
      qcow2: drop flush in update_cluster_refcount()
      qcow2: flush in qcow2_update_snapshot_refcount()
      qcow2: set L2 cache dependency in qcow2_alloc_bytes()
      qcow2: flush refcount cache correctly in qcow2_write_snapshots()
      qcow2: flush refcount cache correctly in alloc_refcount_block()
      ...

commit d4d7682484f339d70355b165a15f8f5e83638e40
Merge: 4f30649 2362ecc
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Mar 15 10:47:00 2013 -0500

    Merge remote-tracking branch 'cohuck/virtio-ccw-upstr' into staging
    
    # By Christian Borntraeger (1) and Cornelia Huck (1)
    # Via Cornelia Huck
    * cohuck/virtio-ccw-upstr:
      virtio-ccw: Wire up virtio-rng.
      virtio-ccw: remove qdev_unparent in unplug routing

commit 3618a094022e984d4e045c6db21aed961b7c6fc9
Author: Markus Armbruster <armbru at redhat.com>
Date:   Thu Mar 14 13:59:53 2013 +0100

    blockdev: Fix up copyright and permission notice
    
    Screwed up in commit 666daa68.  Thanks to Kevin Wolf for reminding me
    to fix this.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 7ae6198..09f76b7 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -5,6 +5,29 @@
  *
  * This work is licensed under the terms of the GNU GPL, version 2 or
  * later.  See the COPYING file in the top-level directory.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * 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 "sysemu/blockdev.h"
commit 804dd41792c8bdc0c8b34c8e580882ff8ef736d8
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Thu Mar 14 17:06:55 2013 +0100

    qemu-iotests: use -nographic in test case 007
    
    A comment explains that -nographic hangs test case 007.  This is no
    longer the case so add -nographic.  This makes the test suite faster and
    more pleasant to run since no windows pop up.
    
    I am not sure exactly when -nographic starting working for this case but
    there is no fundamental reason why graphics are needed here.  Make sure
    the serial port is not on stdio, it would conflict with the monitor.
    
    Also remove unnecessary trailing whitespace on these lines.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Tested-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/tests/qemu-iotests/007 b/tests/qemu-iotests/007
index 0139264..c454f2c 100755
--- a/tests/qemu-iotests/007
+++ b/tests/qemu-iotests/007
@@ -50,10 +50,9 @@ _make_test_img 1M
 
 for i in `seq 1 10`; do
     echo "savevm $i"
-    # XXX(hch): adding -nographic would be good, but hangs the test
-    $QEMU -hda $TEST_IMG -monitor stdio >/dev/null 2>&1 <<EOF     
-savevm test-$i                                                              
-quit                                                                        
+    $QEMU -nographic -hda $TEST_IMG -serial none -monitor stdio >/dev/null 2>&1 <<EOF
+savevm test-$i
+quit
 EOF
 done
 
commit acbf30ec601b1f817febc4500025b7c4181312c4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Mar 13 15:58:13 2013 +0100

    qemu-iotests: add tests for rebasing zero clusters
    
    If zero clusters are erroneously treated as unallocated, "qemu-img rebase"
    will copy the backing file's contents onto the cluster.
    
    The bug existed also in image streaming, but since the root cause was in
    qcow2's is_allocated implementation it is enough to test it with qemu-img.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/tests/qemu-iotests/050 b/tests/qemu-iotests/050
new file mode 100755
index 0000000..05793e2
--- /dev/null
+++ b/tests/qemu-iotests/050
@@ -0,0 +1,75 @@
+#!/bin/bash
+#
+# Test qemu-img rebase with zero clusters
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=pbonzini at redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+_cleanup()
+{
+    _cleanup_test_img
+    rm -f $TEST_IMG.old
+    rm -f $TEST_IMG.new
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt qcow2 qed
+_supported_proto file
+_supported_os Linux
+
+if test "$IMGFMT" = qcow2 && test $IMGOPTS = ""; then
+  IMGOPTS=compat=1.1
+fi
+
+echo
+echo "== Creating images =="
+
+size=10M
+_make_test_img $size
+$QEMU_IO -c "write -P 0x40 0 1048576" $TEST_IMG | _filter_qemu_io
+mv $TEST_IMG $TEST_IMG.old
+
+_make_test_img $size
+$QEMU_IO -c "write -P 0x5a 0 1048576" $TEST_IMG | _filter_qemu_io
+mv $TEST_IMG $TEST_IMG.new
+
+_make_test_img -b $TEST_IMG.old $size
+$QEMU_IO -c "write -z 0 1048576" $TEST_IMG | _filter_qemu_io
+
+echo
+echo "== Rebasing the image =="
+
+$QEMU_IMG rebase -b $TEST_IMG.new $TEST_IMG
+$QEMU_IO -c "read -P 0x00 0 1048576" $TEST_IMG | _filter_qemu_io
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/050.out b/tests/qemu-iotests/050.out
new file mode 100644
index 0000000..3f5f7e1
--- /dev/null
+++ b/tests/qemu-iotests/050.out
@@ -0,0 +1,17 @@
+QA output created by 050
+
+== Creating images ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=10485760 
+wrote 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=10485760 
+wrote 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=10485760 backing_file='TEST_DIR/t.IMGFMT.old' 
+wrote 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== Rebasing the image ==
+read 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index fcf57e0..1d7e4f3 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -56,3 +56,4 @@
 047 rw auto
 048 img auto quick
 049 rw auto
+050 rw auto backing quick
commit 485e3ce88e8af0e5311dd626f399b3a1e0846dd6
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Mar 13 15:14:15 2013 +0100

    dataplane: fix hang introduced by AioContext transition
    
    The bug is that the EventNotifiers do have a NULL io_flush callback.
    Because _none_ of the callbacks on the dataplane AioContext have such a
    callback, aio_poll will simply do nothing.  Fixed by adding the callbacks:
    the ioeventfd will always be polled (this can change in the future to
    pause/resume the processing during live snapshots or similar operations);
    the ioqueue will be polled if there are outstanding requests.
    
    I must admit I have screwed up my testing somehow, because commit
    2c20e71 does not work even if cherry-picked on top of 1.4.0, and this
    patch fixes it there as well.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/dataplane/virtio-blk.c b/hw/dataplane/virtio-blk.c
index dfe5f9b..1242d61 100644
--- a/hw/dataplane/virtio-blk.c
+++ b/hw/dataplane/virtio-blk.c
@@ -263,6 +263,11 @@ static int process_request(IOQueue *ioq, struct iovec iov[],
     }
 }
 
+static int flush_true(EventNotifier *e)
+{
+    return true;
+}
+
 static void handle_notify(EventNotifier *e)
 {
     VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane,
@@ -342,6 +347,14 @@ static void handle_notify(EventNotifier *e)
     }
 }
 
+static int flush_io(EventNotifier *e)
+{
+    VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane,
+                                           io_notifier);
+
+    return s->num_reqs > 0;
+}
+
 static void handle_io(EventNotifier *e)
 {
     VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane,
@@ -472,7 +485,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
         exit(1);
     }
     s->host_notifier = *virtio_queue_get_host_notifier(vq);
-    aio_set_event_notifier(s->ctx, &s->host_notifier, handle_notify, NULL);
+    aio_set_event_notifier(s->ctx, &s->host_notifier, handle_notify, flush_true);
 
     /* Set up ioqueue */
     ioq_init(&s->ioqueue, s->fd, REQ_MAX);
@@ -480,7 +493,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
         ioq_put_iocb(&s->ioqueue, &s->requests[i].iocb);
     }
     s->io_notifier = *ioq_get_notifier(&s->ioqueue);
-    aio_set_event_notifier(s->ctx, &s->io_notifier, handle_io, NULL);
+    aio_set_event_notifier(s->ctx, &s->io_notifier, handle_io, flush_io);
 
     s->started = true;
     trace_virtio_blk_data_plane_start(s);
commit 28f082469650a0f4c0e37b4ccd6f9514b1a0698d
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Thu Mar 7 13:41:50 2013 +0100

    coroutine: use AioContext for CoQueue BH
    
    CoQueue uses a BH to awake coroutines that were made ready to run again
    using qemu_co_queue_next() or qemu_co_queue_restart_all().  The BH
    currently runs in the iothread AioContext and would break coroutines
    that run in a different AioContext.
    
    This is a slightly tricky problem because the lifetime of the BH exceeds
    that of the CoQueue.  This means coroutines can be awoken after CoQueue
    itself has been freed.  Also, there is no qemu_co_queue_destroy()
    function which we could use to handle freeing resources.
    
    Introducing qemu_co_queue_destroy() has a ripple effect of requiring us
    to also add qemu_co_mutex_destroy() and qemu_co_rwlock_destroy(), as
    well as updating all callers.  Avoid doing that.
    
    We also cannot switch from BH to GIdle function because aio_poll() does
    not dispatch GIdle functions.  (GIdle functions make memory management
    slightly easier because they free themselves.)
    
    Finally, I don't want to move unlock_queue and unlock_bh into
    AioContext.  That would break encapsulation - AioContext isn't supposed
    to know about CoQueue.
    
    This patch implements a different solution: each qemu_co_queue_next() or
    qemu_co_queue_restart_all() call creates a new BH and list of coroutines
    to wake up.  Callers tend to invoke qemu_co_queue_next() and
    qemu_co_queue_restart_all() occasionally after blocking I/O, so creating
    a new BH for each call shouldn't be massively inefficient.
    
    Note that this patch does not add an interface for specifying the
    AioContext.  That is left to future patches which will convert CoQueue,
    CoMutex, and CoRwlock to expose AioContext.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/include/block/coroutine.h b/include/block/coroutine.h
index c31fae3..a978162 100644
--- a/include/block/coroutine.h
+++ b/include/block/coroutine.h
@@ -104,6 +104,7 @@ bool qemu_in_coroutine(void);
  */
 typedef struct CoQueue {
     QTAILQ_HEAD(, Coroutine) entries;
+    AioContext *ctx;
 } CoQueue;
 
 /**
diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c
index 97ef01c..86efe1f 100644
--- a/qemu-coroutine-lock.c
+++ b/qemu-coroutine-lock.c
@@ -29,28 +29,36 @@
 #include "block/aio.h"
 #include "trace.h"
 
-static QTAILQ_HEAD(, Coroutine) unlock_bh_queue =
-    QTAILQ_HEAD_INITIALIZER(unlock_bh_queue);
-static QEMUBH* unlock_bh;
+/* Coroutines are awoken from a BH to allow the current coroutine to complete
+ * its flow of execution.  The BH may run after the CoQueue has been destroyed,
+ * so keep BH data in a separate heap-allocated struct.
+ */
+typedef struct {
+    QEMUBH *bh;
+    QTAILQ_HEAD(, Coroutine) entries;
+} CoQueueNextData;
 
 static void qemu_co_queue_next_bh(void *opaque)
 {
+    CoQueueNextData *data = opaque;
     Coroutine *next;
 
     trace_qemu_co_queue_next_bh();
-    while ((next = QTAILQ_FIRST(&unlock_bh_queue))) {
-        QTAILQ_REMOVE(&unlock_bh_queue, next, co_queue_next);
+    while ((next = QTAILQ_FIRST(&data->entries))) {
+        QTAILQ_REMOVE(&data->entries, next, co_queue_next);
         qemu_coroutine_enter(next, NULL);
     }
+
+    qemu_bh_delete(data->bh);
+    g_slice_free(CoQueueNextData, data);
 }
 
 void qemu_co_queue_init(CoQueue *queue)
 {
     QTAILQ_INIT(&queue->entries);
 
-    if (!unlock_bh) {
-        unlock_bh = qemu_bh_new(qemu_co_queue_next_bh, NULL);
-    }
+    /* This will be exposed to callers once there are multiple AioContexts */
+    queue->ctx = qemu_get_aio_context();
 }
 
 void coroutine_fn qemu_co_queue_wait(CoQueue *queue)
@@ -69,26 +77,39 @@ void coroutine_fn qemu_co_queue_wait_insert_head(CoQueue *queue)
     assert(qemu_in_coroutine());
 }
 
-bool qemu_co_queue_next(CoQueue *queue)
+static bool qemu_co_queue_do_restart(CoQueue *queue, bool single)
 {
     Coroutine *next;
+    CoQueueNextData *data;
+
+    if (QTAILQ_EMPTY(&queue->entries)) {
+        return false;
+    }
 
-    next = QTAILQ_FIRST(&queue->entries);
-    if (next) {
+    data = g_slice_new(CoQueueNextData);
+    data->bh = aio_bh_new(queue->ctx, qemu_co_queue_next_bh, data);
+    QTAILQ_INIT(&data->entries);
+    qemu_bh_schedule(data->bh);
+
+    while ((next = QTAILQ_FIRST(&queue->entries)) != NULL) {
         QTAILQ_REMOVE(&queue->entries, next, co_queue_next);
-        QTAILQ_INSERT_TAIL(&unlock_bh_queue, next, co_queue_next);
+        QTAILQ_INSERT_TAIL(&data->entries, next, co_queue_next);
         trace_qemu_co_queue_next(next);
-        qemu_bh_schedule(unlock_bh);
+        if (single) {
+            break;
+        }
     }
+    return true;
+}
 
-    return (next != NULL);
+bool qemu_co_queue_next(CoQueue *queue)
+{
+    return qemu_co_queue_do_restart(queue, true);
 }
 
 void qemu_co_queue_restart_all(CoQueue *queue)
 {
-    while (qemu_co_queue_next(queue)) {
-        /* Do nothing */
-    }
+    qemu_co_queue_do_restart(queue, false);
 }
 
 bool qemu_co_queue_empty(CoQueue *queue)
commit c4d9d19645a484298a67e9021060bc7c2b081d0f
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Thu Mar 7 13:41:49 2013 +0100

    threadpool: drop global thread pool
    
    Now that each AioContext has a ThreadPool and the main loop AioContext
    can be fetched with bdrv_get_aio_context(), we can eliminate the concept
    of a global thread pool from thread-pool.c.
    
    The submit functions must take a ThreadPool* argument.
    
    block/raw-posix.c and block/raw-win32.c use
    aio_get_thread_pool(bdrv_get_aio_context(bs)) to fetch the main loop's
    ThreadPool.
    
    tests/test-thread-pool.c must be updated to reflect the new
    thread_pool_submit() function prototypes.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/raw-posix.c b/block/raw-posix.c
index 4dfdf98..8a3cdbc 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -750,6 +750,7 @@ static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
         BlockDriverCompletionFunc *cb, void *opaque, int type)
 {
     RawPosixAIOData *acb = g_slice_new(RawPosixAIOData);
+    ThreadPool *pool;
 
     acb->bs = bs;
     acb->aio_type = type;
@@ -763,7 +764,8 @@ static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
     acb->aio_offset = sector_num * 512;
 
     trace_paio_submit(acb, opaque, sector_num, nb_sectors, type);
-    return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
+    pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
+    return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
 }
 
 static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
@@ -1413,6 +1415,7 @@ static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
 {
     BDRVRawState *s = bs->opaque;
     RawPosixAIOData *acb;
+    ThreadPool *pool;
 
     if (fd_open(bs) < 0)
         return NULL;
@@ -1424,7 +1427,8 @@ static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
     acb->aio_offset = 0;
     acb->aio_ioctl_buf = buf;
     acb->aio_ioctl_cmd = req;
-    return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
+    pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
+    return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
 }
 
 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
diff --git a/block/raw-win32.c b/block/raw-win32.c
index b89ac19..18e0068 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -144,6 +144,7 @@ static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile,
         BlockDriverCompletionFunc *cb, void *opaque, int type)
 {
     RawWin32AIOData *acb = g_slice_new(RawWin32AIOData);
+    ThreadPool *pool;
 
     acb->bs = bs;
     acb->hfile = hfile;
@@ -157,7 +158,8 @@ static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile,
     acb->aio_offset = sector_num * 512;
 
     trace_paio_submit(acb, opaque, sector_num, nb_sectors, type);
-    return thread_pool_submit_aio(aio_worker, acb, cb, opaque);
+    pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
+    return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
 }
 
 int qemu_ftruncate64(int fd, int64_t length)
diff --git a/include/block/thread-pool.h b/include/block/thread-pool.h
index e1453c6..32afcdd 100644
--- a/include/block/thread-pool.h
+++ b/include/block/thread-pool.h
@@ -31,9 +31,11 @@ typedef struct ThreadPool ThreadPool;
 ThreadPool *thread_pool_new(struct AioContext *ctx);
 void thread_pool_free(ThreadPool *pool);
 
-BlockDriverAIOCB *thread_pool_submit_aio(ThreadPoolFunc *func, void *arg,
-     BlockDriverCompletionFunc *cb, void *opaque);
-int coroutine_fn thread_pool_submit_co(ThreadPoolFunc *func, void *arg);
-void thread_pool_submit(ThreadPoolFunc *func, void *arg);
+BlockDriverAIOCB *thread_pool_submit_aio(ThreadPool *pool,
+        ThreadPoolFunc *func, void *arg,
+        BlockDriverCompletionFunc *cb, void *opaque);
+int coroutine_fn thread_pool_submit_co(ThreadPool *pool,
+        ThreadPoolFunc *func, void *arg);
+void thread_pool_submit(ThreadPool *pool, ThreadPoolFunc *func, void *arg);
 
 #endif
diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c
index 9998e03..22915aa 100644
--- a/tests/test-thread-pool.c
+++ b/tests/test-thread-pool.c
@@ -4,6 +4,8 @@
 #include "block/thread-pool.h"
 #include "block/block.h"
 
+static AioContext *ctx;
+static ThreadPool *pool;
 static int active;
 
 typedef struct {
@@ -38,19 +40,10 @@ static void done_cb(void *opaque, int ret)
     active--;
 }
 
-/* A non-blocking poll of the main AIO context (we cannot use aio_poll
- * because we do not know the AioContext).
- */
-static void qemu_aio_wait_nonblocking(void)
-{
-    qemu_notify_event();
-    qemu_aio_wait();
-}
-
 /* Wait until all aio and bh activity has finished */
 static void qemu_aio_wait_all(void)
 {
-    while (qemu_aio_wait()) {
+    while (aio_poll(ctx, true)) {
         /* Do nothing */
     }
 }
@@ -58,7 +51,7 @@ static void qemu_aio_wait_all(void)
 static void test_submit(void)
 {
     WorkerTestData data = { .n = 0 };
-    thread_pool_submit(worker_cb, &data);
+    thread_pool_submit(pool, worker_cb, &data);
     qemu_aio_wait_all();
     g_assert_cmpint(data.n, ==, 1);
 }
@@ -66,7 +59,8 @@ static void test_submit(void)
 static void test_submit_aio(void)
 {
     WorkerTestData data = { .n = 0, .ret = -EINPROGRESS };
-    data.aiocb = thread_pool_submit_aio(worker_cb, &data, done_cb, &data);
+    data.aiocb = thread_pool_submit_aio(pool, worker_cb, &data,
+                                        done_cb, &data);
 
     /* The callbacks are not called until after the first wait.  */
     active = 1;
@@ -84,7 +78,7 @@ static void co_test_cb(void *opaque)
     active = 1;
     data->n = 0;
     data->ret = -EINPROGRESS;
-    thread_pool_submit_co(worker_cb, data);
+    thread_pool_submit_co(pool, worker_cb, data);
 
     /* The test continues in test_submit_co, after qemu_coroutine_enter... */
 
@@ -126,12 +120,12 @@ static void test_submit_many(void)
     for (i = 0; i < 100; i++) {
         data[i].n = 0;
         data[i].ret = -EINPROGRESS;
-        thread_pool_submit_aio(worker_cb, &data[i], done_cb, &data[i]);
+        thread_pool_submit_aio(pool, worker_cb, &data[i], done_cb, &data[i]);
     }
 
     active = 100;
     while (active > 0) {
-        qemu_aio_wait();
+        aio_poll(ctx, true);
     }
     for (i = 0; i < 100; i++) {
         g_assert_cmpint(data[i].n, ==, 1);
@@ -154,7 +148,7 @@ static void test_cancel(void)
     for (i = 0; i < 100; i++) {
         data[i].n = 0;
         data[i].ret = -EINPROGRESS;
-        data[i].aiocb = thread_pool_submit_aio(long_cb, &data[i],
+        data[i].aiocb = thread_pool_submit_aio(pool, long_cb, &data[i],
                                                done_cb, &data[i]);
     }
 
@@ -162,7 +156,8 @@ static void test_cancel(void)
      * run, but do not waste too much time...
      */
     active = 100;
-    qemu_aio_wait_nonblocking();
+    aio_notify(ctx);
+    aio_poll(ctx, false);
 
     /* Wait some time for the threads to start, with some sanity
      * testing on the behavior of the scheduler...
@@ -208,11 +203,10 @@ static void test_cancel(void)
 
 int main(int argc, char **argv)
 {
-    /* These should be removed once each AioContext has its thread pool.
-     * The test should create its own AioContext.
-     */
-    qemu_init_main_loop();
-    bdrv_init();
+    int ret;
+
+    ctx = aio_context_new();
+    pool = aio_get_thread_pool(ctx);
 
     g_test_init(&argc, &argv, NULL);
     g_test_add_func("/thread-pool/submit", test_submit);
@@ -220,5 +214,9 @@ int main(int argc, char **argv)
     g_test_add_func("/thread-pool/submit-co", test_submit_co);
     g_test_add_func("/thread-pool/submit-many", test_submit_many);
     g_test_add_func("/thread-pool/cancel", test_cancel);
-    return g_test_run();
+
+    ret = g_test_run();
+
+    aio_context_unref(ctx);
+    return ret;
 }
diff --git a/thread-pool.c b/thread-pool.c
index d1e4570..0ebd4c2 100644
--- a/thread-pool.c
+++ b/thread-pool.c
@@ -78,9 +78,6 @@ struct ThreadPool {
     bool stopping;
 };
 
-/* Currently there is only one thread pool instance. */
-static ThreadPool global_pool;
-
 static void *worker_thread(void *opaque)
 {
     ThreadPool *pool = opaque;
@@ -239,10 +236,10 @@ static const AIOCBInfo thread_pool_aiocb_info = {
     .cancel             = thread_pool_cancel,
 };
 
-BlockDriverAIOCB *thread_pool_submit_aio(ThreadPoolFunc *func, void *arg,
+BlockDriverAIOCB *thread_pool_submit_aio(ThreadPool *pool,
+        ThreadPoolFunc *func, void *arg,
         BlockDriverCompletionFunc *cb, void *opaque)
 {
-    ThreadPool *pool = &global_pool;
     ThreadPoolElement *req;
 
     req = qemu_aio_get(&thread_pool_aiocb_info, NULL, cb, opaque);
@@ -278,18 +275,19 @@ static void thread_pool_co_cb(void *opaque, int ret)
     qemu_coroutine_enter(co->co, NULL);
 }
 
-int coroutine_fn thread_pool_submit_co(ThreadPoolFunc *func, void *arg)
+int coroutine_fn thread_pool_submit_co(ThreadPool *pool, ThreadPoolFunc *func,
+                                       void *arg)
 {
     ThreadPoolCo tpc = { .co = qemu_coroutine_self(), .ret = -EINPROGRESS };
     assert(qemu_in_coroutine());
-    thread_pool_submit_aio(func, arg, thread_pool_co_cb, &tpc);
+    thread_pool_submit_aio(pool, func, arg, thread_pool_co_cb, &tpc);
     qemu_coroutine_yield();
     return tpc.ret;
 }
 
-void thread_pool_submit(ThreadPoolFunc *func, void *arg)
+void thread_pool_submit(ThreadPool *pool, ThreadPoolFunc *func, void *arg)
 {
-    thread_pool_submit_aio(func, arg, NULL, NULL);
+    thread_pool_submit_aio(pool, func, arg, NULL, NULL);
 }
 
 static void thread_pool_init_one(ThreadPool *pool, AioContext *ctx)
@@ -354,10 +352,3 @@ void thread_pool_free(ThreadPool *pool)
     event_notifier_cleanup(&pool->notifier);
     g_free(pool);
 }
-
-static void thread_pool_init(void)
-{
-    thread_pool_init_one(&global_pool, NULL);
-}
-
-block_init(thread_pool_init)
commit 85d126f3ee666702ac514c66606c62d276c4341c
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Thu Mar 7 13:41:48 2013 +0100

    block: add bdrv_get_aio_context()
    
    For now bdrv_get_aio_context() is just a stub that calls
    qemu_aio_get_context() since the block layer is currently tied to the
    main loop AioContext.
    
    Add the stub now so that the block layer can begin accessing its
    AioContext.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block.c b/block.c
index 0ab164d..037e15e 100644
--- a/block.c
+++ b/block.c
@@ -4681,3 +4681,9 @@ out:
         bdrv_delete(bs);
     }
 }
+
+AioContext *bdrv_get_aio_context(BlockDriverState *bs)
+{
+    /* Currently BlockDriverState always uses the main loop AioContext */
+    return qemu_get_aio_context();
+}
diff --git a/include/block/block_int.h b/include/block/block_int.h
index baf80e3..ce0aa26 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -294,6 +294,13 @@ int get_tmp_filename(char *filename, int size);
 void bdrv_set_io_limits(BlockDriverState *bs,
                         BlockIOLimit *io_limits);
 
+/**
+ * bdrv_get_aio_context:
+ *
+ * Returns: the currently bound #AioContext
+ */
+AioContext *bdrv_get_aio_context(BlockDriverState *bs);
+
 #ifdef _WIN32
 int is_windows_drive(const char *filename);
 #endif
commit 9b34277d23a6fb15eb9513006c96d8026beeea1f
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Thu Mar 7 13:41:47 2013 +0100

    aio: add a ThreadPool instance to AioContext
    
    This patch adds a ThreadPool to AioContext.  It's possible that some
    AioContext instances will never use the ThreadPool, so defer creation
    until aio_get_thread_pool().
    
    The reason why AioContext should have the ThreadPool is because the
    ThreadPool is bound to a AioContext instance where the work item's
    callback function is invoked.  It doesn't make sense to keep the
    ThreadPool pointer anywhere other than AioContext.  For example,
    block/raw-posix.c can get its AioContext's ThreadPool and submit work.
    
    Special note about headers: I used struct ThreadPool in aio.h because
    there is a circular dependency if aio.h includes thread-pool.h.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/async.c b/async.c
index f2d47ba..90fe906 100644
--- a/async.c
+++ b/async.c
@@ -24,6 +24,7 @@
 
 #include "qemu-common.h"
 #include "block/aio.h"
+#include "block/thread-pool.h"
 #include "qemu/main-loop.h"
 
 /***********************************************************/
@@ -172,6 +173,7 @@ aio_ctx_finalize(GSource     *source)
 {
     AioContext *ctx = (AioContext *) source;
 
+    thread_pool_free(ctx->thread_pool);
     aio_set_event_notifier(ctx, &ctx->notifier, NULL, NULL);
     event_notifier_cleanup(&ctx->notifier);
     g_array_free(ctx->pollfds, TRUE);
@@ -190,6 +192,14 @@ GSource *aio_get_g_source(AioContext *ctx)
     return &ctx->source;
 }
 
+ThreadPool *aio_get_thread_pool(AioContext *ctx)
+{
+    if (!ctx->thread_pool) {
+        ctx->thread_pool = thread_pool_new(ctx);
+    }
+    return ctx->thread_pool;
+}
+
 void aio_notify(AioContext *ctx)
 {
     event_notifier_set(&ctx->notifier);
@@ -200,6 +210,7 @@ AioContext *aio_context_new(void)
     AioContext *ctx;
     ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext));
     ctx->pollfds = g_array_new(FALSE, FALSE, sizeof(GPollFD));
+    ctx->thread_pool = NULL;
     event_notifier_init(&ctx->notifier, false);
     aio_set_event_notifier(ctx, &ctx->notifier, 
                            (EventNotifierHandler *)
diff --git a/include/block/aio.h b/include/block/aio.h
index 5b54d38..1836793 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -66,6 +66,9 @@ typedef struct AioContext {
 
     /* GPollFDs for aio_poll() */
     GArray *pollfds;
+
+    /* Thread pool for performing work and receiving completion callbacks */
+    struct ThreadPool *thread_pool;
 } AioContext;
 
 /* Returns 1 if there are still outstanding AIO requests; 0 otherwise */
@@ -223,6 +226,9 @@ void aio_set_event_notifier(AioContext *ctx,
  */
 GSource *aio_get_g_source(AioContext *ctx);
 
+/* Return the ThreadPool bound to this AioContext */
+struct ThreadPool *aio_get_thread_pool(AioContext *ctx);
+
 /* Functions to operate on the main QEMU AioContext.  */
 
 bool qemu_aio_wait(void);
commit f7311ccc630d925e7351e9440b7ad8bc6f0a51de
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Thu Mar 7 13:41:46 2013 +0100

    threadpool: add thread_pool_new() and thread_pool_free()
    
    ThreadPool is tied to an AioContext through its event notifier, which
    dictates in which AioContext the work item's callback function will be
    invoked.
    
    In order to support multiple AioContexts we need to support multiple
    ThreadPool instances.
    
    This patch adds the new/free functions.  The free function deserves
    special attention because it quiesces remaining worker threads.  This
    requires a new condition variable and a "stopping" flag to let workers
    know they should terminate once idle.
    
    We never needed to do this before since the global threadpool was not
    explicitly destroyed until process termination.
    
    Also stash the AioContext pointer in ThreadPool so that we can call
    aio_set_event_notifier() in thread_pool_free().  We didn't need to hold
    onto AioContext previously since there was no free function.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/include/block/thread-pool.h b/include/block/thread-pool.h
index 200703e..e1453c6 100644
--- a/include/block/thread-pool.h
+++ b/include/block/thread-pool.h
@@ -26,6 +26,11 @@
 
 typedef int ThreadPoolFunc(void *opaque);
 
+typedef struct ThreadPool ThreadPool;
+
+ThreadPool *thread_pool_new(struct AioContext *ctx);
+void thread_pool_free(ThreadPool *pool);
+
 BlockDriverAIOCB *thread_pool_submit_aio(ThreadPoolFunc *func, void *arg,
      BlockDriverCompletionFunc *cb, void *opaque);
 int coroutine_fn thread_pool_submit_co(ThreadPoolFunc *func, void *arg);
diff --git a/thread-pool.c b/thread-pool.c
index a0aecd0..d1e4570 100644
--- a/thread-pool.c
+++ b/thread-pool.c
@@ -24,8 +24,6 @@
 #include "qemu/event_notifier.h"
 #include "block/thread-pool.h"
 
-typedef struct ThreadPool ThreadPool;
-
 static void do_spawn_thread(ThreadPool *pool);
 
 typedef struct ThreadPoolElement ThreadPoolElement;
@@ -59,8 +57,10 @@ struct ThreadPoolElement {
 
 struct ThreadPool {
     EventNotifier notifier;
+    AioContext *ctx;
     QemuMutex lock;
     QemuCond check_cancel;
+    QemuCond worker_stopped;
     QemuSemaphore sem;
     int max_threads;
     QEMUBH *new_thread_bh;
@@ -75,6 +75,7 @@ struct ThreadPool {
     int new_threads;     /* backlog of threads we need to create */
     int pending_threads; /* threads created but not running yet */
     int pending_cancellations; /* whether we need a cond_broadcast */
+    bool stopping;
 };
 
 /* Currently there is only one thread pool instance. */
@@ -88,7 +89,7 @@ static void *worker_thread(void *opaque)
     pool->pending_threads--;
     do_spawn_thread(pool);
 
-    while (1) {
+    while (!pool->stopping) {
         ThreadPoolElement *req;
         int ret;
 
@@ -99,7 +100,7 @@ static void *worker_thread(void *opaque)
             qemu_mutex_lock(&pool->lock);
             pool->idle_threads--;
         } while (ret == -1 && !QTAILQ_EMPTY(&pool->request_list));
-        if (ret == -1) {
+        if (ret == -1 || pool->stopping) {
             break;
         }
 
@@ -124,6 +125,7 @@ static void *worker_thread(void *opaque)
     }
 
     pool->cur_threads--;
+    qemu_cond_signal(&pool->worker_stopped);
     qemu_mutex_unlock(&pool->lock);
     return NULL;
 }
@@ -298,8 +300,10 @@ static void thread_pool_init_one(ThreadPool *pool, AioContext *ctx)
 
     memset(pool, 0, sizeof(*pool));
     event_notifier_init(&pool->notifier, false);
+    pool->ctx = ctx;
     qemu_mutex_init(&pool->lock);
     qemu_cond_init(&pool->check_cancel);
+    qemu_cond_init(&pool->worker_stopped);
     qemu_sem_init(&pool->sem, 0);
     pool->max_threads = 64;
     pool->new_thread_bh = aio_bh_new(ctx, spawn_thread_bh_fn, pool);
@@ -311,6 +315,46 @@ static void thread_pool_init_one(ThreadPool *pool, AioContext *ctx)
                            thread_pool_active);
 }
 
+ThreadPool *thread_pool_new(AioContext *ctx)
+{
+    ThreadPool *pool = g_new(ThreadPool, 1);
+    thread_pool_init_one(pool, ctx);
+    return pool;
+}
+
+void thread_pool_free(ThreadPool *pool)
+{
+    if (!pool) {
+        return;
+    }
+
+    assert(QLIST_EMPTY(&pool->head));
+
+    qemu_mutex_lock(&pool->lock);
+
+    /* Stop new threads from spawning */
+    qemu_bh_delete(pool->new_thread_bh);
+    pool->cur_threads -= pool->new_threads;
+    pool->new_threads = 0;
+
+    /* Wait for worker threads to terminate */
+    pool->stopping = true;
+    while (pool->cur_threads > 0) {
+        qemu_sem_post(&pool->sem);
+        qemu_cond_wait(&pool->worker_stopped, &pool->lock);
+    }
+
+    qemu_mutex_unlock(&pool->lock);
+
+    aio_set_event_notifier(pool->ctx, &pool->notifier, NULL, NULL);
+    qemu_sem_destroy(&pool->sem);
+    qemu_cond_destroy(&pool->check_cancel);
+    qemu_cond_destroy(&pool->worker_stopped);
+    qemu_mutex_destroy(&pool->lock);
+    event_notifier_cleanup(&pool->notifier);
+    g_free(pool);
+}
+
 static void thread_pool_init(void)
 {
     thread_pool_init_one(&global_pool, NULL);
commit b811203cf2fbf83e26f8e8feb2c77784259a4cbd
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Thu Mar 7 13:41:45 2013 +0100

    threadpool: move globals into struct ThreadPool
    
    Move global variables into a struct so multiple thread pools can be
    supported in the future.
    
    This patch does not change thread-pool.h interfaces.  There is still a
    global thread pool and it is not yet possible to create/destroy
    individual thread pools.  Moving the variables into a struct first makes
    later patches easier to review.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/thread-pool.c b/thread-pool.c
index e3ca64d..a0aecd0 100644
--- a/thread-pool.c
+++ b/thread-pool.c
@@ -24,7 +24,9 @@
 #include "qemu/event_notifier.h"
 #include "block/thread-pool.h"
 
-static void do_spawn_thread(void);
+typedef struct ThreadPool ThreadPool;
+
+static void do_spawn_thread(ThreadPool *pool);
 
 typedef struct ThreadPoolElement ThreadPoolElement;
 
@@ -37,6 +39,7 @@ enum ThreadState {
 
 struct ThreadPoolElement {
     BlockDriverAIOCB common;
+    ThreadPool *pool;
     ThreadPoolFunc *func;
     void *arg;
 
@@ -54,49 +57,56 @@ struct ThreadPoolElement {
     QLIST_ENTRY(ThreadPoolElement) all;
 };
 
-static EventNotifier notifier;
-static QemuMutex lock;
-static QemuCond check_cancel;
-static QemuSemaphore sem;
-static int max_threads = 64;
-static QEMUBH *new_thread_bh;
-
-/* The following variables are protected by the global mutex.  */
-static QLIST_HEAD(, ThreadPoolElement) head;
-
-/* The following variables are protected by lock.  */
-static QTAILQ_HEAD(, ThreadPoolElement) request_list;
-static int cur_threads;
-static int idle_threads;
-static int new_threads;     /* backlog of threads we need to create */
-static int pending_threads; /* threads created but not running yet */
-static int pending_cancellations; /* whether we need a cond_broadcast */
-
-static void *worker_thread(void *unused)
+struct ThreadPool {
+    EventNotifier notifier;
+    QemuMutex lock;
+    QemuCond check_cancel;
+    QemuSemaphore sem;
+    int max_threads;
+    QEMUBH *new_thread_bh;
+
+    /* The following variables are only accessed from one AioContext. */
+    QLIST_HEAD(, ThreadPoolElement) head;
+
+    /* The following variables are protected by lock.  */
+    QTAILQ_HEAD(, ThreadPoolElement) request_list;
+    int cur_threads;
+    int idle_threads;
+    int new_threads;     /* backlog of threads we need to create */
+    int pending_threads; /* threads created but not running yet */
+    int pending_cancellations; /* whether we need a cond_broadcast */
+};
+
+/* Currently there is only one thread pool instance. */
+static ThreadPool global_pool;
+
+static void *worker_thread(void *opaque)
 {
-    qemu_mutex_lock(&lock);
-    pending_threads--;
-    do_spawn_thread();
+    ThreadPool *pool = opaque;
+
+    qemu_mutex_lock(&pool->lock);
+    pool->pending_threads--;
+    do_spawn_thread(pool);
 
     while (1) {
         ThreadPoolElement *req;
         int ret;
 
         do {
-            idle_threads++;
-            qemu_mutex_unlock(&lock);
-            ret = qemu_sem_timedwait(&sem, 10000);
-            qemu_mutex_lock(&lock);
-            idle_threads--;
-        } while (ret == -1 && !QTAILQ_EMPTY(&request_list));
+            pool->idle_threads++;
+            qemu_mutex_unlock(&pool->lock);
+            ret = qemu_sem_timedwait(&pool->sem, 10000);
+            qemu_mutex_lock(&pool->lock);
+            pool->idle_threads--;
+        } while (ret == -1 && !QTAILQ_EMPTY(&pool->request_list));
         if (ret == -1) {
             break;
         }
 
-        req = QTAILQ_FIRST(&request_list);
-        QTAILQ_REMOVE(&request_list, req, reqs);
+        req = QTAILQ_FIRST(&pool->request_list);
+        QTAILQ_REMOVE(&pool->request_list, req, reqs);
         req->state = THREAD_ACTIVE;
-        qemu_mutex_unlock(&lock);
+        qemu_mutex_unlock(&pool->lock);
 
         ret = req->func(req->arg);
 
@@ -105,45 +115,47 @@ static void *worker_thread(void *unused)
         smp_wmb();
         req->state = THREAD_DONE;
 
-        qemu_mutex_lock(&lock);
-        if (pending_cancellations) {
-            qemu_cond_broadcast(&check_cancel);
+        qemu_mutex_lock(&pool->lock);
+        if (pool->pending_cancellations) {
+            qemu_cond_broadcast(&pool->check_cancel);
         }
 
-        event_notifier_set(&notifier);
+        event_notifier_set(&pool->notifier);
     }
 
-    cur_threads--;
-    qemu_mutex_unlock(&lock);
+    pool->cur_threads--;
+    qemu_mutex_unlock(&pool->lock);
     return NULL;
 }
 
-static void do_spawn_thread(void)
+static void do_spawn_thread(ThreadPool *pool)
 {
     QemuThread t;
 
     /* Runs with lock taken.  */
-    if (!new_threads) {
+    if (!pool->new_threads) {
         return;
     }
 
-    new_threads--;
-    pending_threads++;
+    pool->new_threads--;
+    pool->pending_threads++;
 
-    qemu_thread_create(&t, worker_thread, NULL, QEMU_THREAD_DETACHED);
+    qemu_thread_create(&t, worker_thread, pool, QEMU_THREAD_DETACHED);
 }
 
 static void spawn_thread_bh_fn(void *opaque)
 {
-    qemu_mutex_lock(&lock);
-    do_spawn_thread();
-    qemu_mutex_unlock(&lock);
+    ThreadPool *pool = opaque;
+
+    qemu_mutex_lock(&pool->lock);
+    do_spawn_thread(pool);
+    qemu_mutex_unlock(&pool->lock);
 }
 
-static void spawn_thread(void)
+static void spawn_thread(ThreadPool *pool)
 {
-    cur_threads++;
-    new_threads++;
+    pool->cur_threads++;
+    pool->new_threads++;
     /* If there are threads being created, they will spawn new workers, so
      * we don't spend time creating many threads in a loop holding a mutex or
      * starving the current vcpu.
@@ -151,23 +163,25 @@ static void spawn_thread(void)
      * If there are no idle threads, ask the main thread to create one, so we
      * inherit the correct affinity instead of the vcpu affinity.
      */
-    if (!pending_threads) {
-        qemu_bh_schedule(new_thread_bh);
+    if (!pool->pending_threads) {
+        qemu_bh_schedule(pool->new_thread_bh);
     }
 }
 
 static void event_notifier_ready(EventNotifier *notifier)
 {
+    ThreadPool *pool = container_of(notifier, ThreadPool, notifier);
     ThreadPoolElement *elem, *next;
 
     event_notifier_test_and_clear(notifier);
 restart:
-    QLIST_FOREACH_SAFE(elem, &head, all, next) {
+    QLIST_FOREACH_SAFE(elem, &pool->head, all, next) {
         if (elem->state != THREAD_CANCELED && elem->state != THREAD_DONE) {
             continue;
         }
         if (elem->state == THREAD_DONE) {
-            trace_thread_pool_complete(elem, elem->common.opaque, elem->ret);
+            trace_thread_pool_complete(pool, elem, elem->common.opaque,
+                                       elem->ret);
         }
         if (elem->state == THREAD_DONE && elem->common.cb) {
             QLIST_REMOVE(elem, all);
@@ -186,34 +200,36 @@ restart:
 
 static int thread_pool_active(EventNotifier *notifier)
 {
-    return !QLIST_EMPTY(&head);
+    ThreadPool *pool = container_of(notifier, ThreadPool, notifier);
+    return !QLIST_EMPTY(&pool->head);
 }
 
 static void thread_pool_cancel(BlockDriverAIOCB *acb)
 {
     ThreadPoolElement *elem = (ThreadPoolElement *)acb;
+    ThreadPool *pool = elem->pool;
 
     trace_thread_pool_cancel(elem, elem->common.opaque);
 
-    qemu_mutex_lock(&lock);
+    qemu_mutex_lock(&pool->lock);
     if (elem->state == THREAD_QUEUED &&
         /* No thread has yet started working on elem. we can try to "steal"
          * the item from the worker if we can get a signal from the
          * semaphore.  Because this is non-blocking, we can do it with
          * the lock taken and ensure that elem will remain THREAD_QUEUED.
          */
-        qemu_sem_timedwait(&sem, 0) == 0) {
-        QTAILQ_REMOVE(&request_list, elem, reqs);
+        qemu_sem_timedwait(&pool->sem, 0) == 0) {
+        QTAILQ_REMOVE(&pool->request_list, elem, reqs);
         elem->state = THREAD_CANCELED;
-        event_notifier_set(&notifier);
+        event_notifier_set(&pool->notifier);
     } else {
-        pending_cancellations++;
+        pool->pending_cancellations++;
         while (elem->state != THREAD_CANCELED && elem->state != THREAD_DONE) {
-            qemu_cond_wait(&check_cancel, &lock);
+            qemu_cond_wait(&pool->check_cancel, &pool->lock);
         }
-        pending_cancellations--;
+        pool->pending_cancellations--;
     }
-    qemu_mutex_unlock(&lock);
+    qemu_mutex_unlock(&pool->lock);
 }
 
 static const AIOCBInfo thread_pool_aiocb_info = {
@@ -224,24 +240,26 @@ static const AIOCBInfo thread_pool_aiocb_info = {
 BlockDriverAIOCB *thread_pool_submit_aio(ThreadPoolFunc *func, void *arg,
         BlockDriverCompletionFunc *cb, void *opaque)
 {
+    ThreadPool *pool = &global_pool;
     ThreadPoolElement *req;
 
     req = qemu_aio_get(&thread_pool_aiocb_info, NULL, cb, opaque);
     req->func = func;
     req->arg = arg;
     req->state = THREAD_QUEUED;
+    req->pool = pool;
 
-    QLIST_INSERT_HEAD(&head, req, all);
+    QLIST_INSERT_HEAD(&pool->head, req, all);
 
-    trace_thread_pool_submit(req, arg);
+    trace_thread_pool_submit(pool, req, arg);
 
-    qemu_mutex_lock(&lock);
-    if (idle_threads == 0 && cur_threads < max_threads) {
-        spawn_thread();
+    qemu_mutex_lock(&pool->lock);
+    if (pool->idle_threads == 0 && pool->cur_threads < pool->max_threads) {
+        spawn_thread(pool);
     }
-    QTAILQ_INSERT_TAIL(&request_list, req, reqs);
-    qemu_mutex_unlock(&lock);
-    qemu_sem_post(&sem);
+    QTAILQ_INSERT_TAIL(&pool->request_list, req, reqs);
+    qemu_mutex_unlock(&pool->lock);
+    qemu_sem_post(&pool->sem);
     return &req->common;
 }
 
@@ -272,18 +290,30 @@ void thread_pool_submit(ThreadPoolFunc *func, void *arg)
     thread_pool_submit_aio(func, arg, NULL, NULL);
 }
 
+static void thread_pool_init_one(ThreadPool *pool, AioContext *ctx)
+{
+    if (!ctx) {
+        ctx = qemu_get_aio_context();
+    }
+
+    memset(pool, 0, sizeof(*pool));
+    event_notifier_init(&pool->notifier, false);
+    qemu_mutex_init(&pool->lock);
+    qemu_cond_init(&pool->check_cancel);
+    qemu_sem_init(&pool->sem, 0);
+    pool->max_threads = 64;
+    pool->new_thread_bh = aio_bh_new(ctx, spawn_thread_bh_fn, pool);
+
+    QLIST_INIT(&pool->head);
+    QTAILQ_INIT(&pool->request_list);
+
+    aio_set_event_notifier(ctx, &pool->notifier, event_notifier_ready,
+                           thread_pool_active);
+}
+
 static void thread_pool_init(void)
 {
-    QLIST_INIT(&head);
-    event_notifier_init(&notifier, false);
-    qemu_mutex_init(&lock);
-    qemu_cond_init(&check_cancel);
-    qemu_sem_init(&sem, 0);
-    qemu_aio_set_event_notifier(&notifier, event_notifier_ready,
-                                thread_pool_active);
-
-    QTAILQ_INIT(&request_list);
-    new_thread_bh = qemu_bh_new(spawn_thread_bh_fn, NULL);
+    thread_pool_init_one(&global_pool, NULL);
 }
 
 block_init(thread_pool_init)
diff --git a/trace-events b/trace-events
index d6a847d..cd73b7f 100644
--- a/trace-events
+++ b/trace-events
@@ -115,8 +115,8 @@ virtio_blk_data_plane_complete_request(void *s, unsigned int head, int ret) "dat
 vring_setup(uint64_t physical, void *desc, void *avail, void *used) "vring physical %#"PRIx64" desc %p avail %p used %p"
 
 # thread-pool.c
-thread_pool_submit(void *req, void *opaque) "req %p opaque %p"
-thread_pool_complete(void *req, void *opaque, int ret) "req %p opaque %p ret %d"
+thread_pool_submit(void *pool, void *req, void *opaque) "pool %p req %p opaque %p"
+thread_pool_complete(void *pool, void *req, void *opaque, int ret) "pool %p req %p opaque %p ret %d"
 thread_pool_cancel(void *req, void *opaque) "req %p opaque %p"
 
 # posix-aio-compat.c
commit 5f3aa1ff4781f39e05b9892d58319a09fedc8918
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Thu Mar 7 13:41:44 2013 +0100

    main-loop: add qemu_get_aio_context()
    
    It is very useful to get the main loop AioContext, which is a static
    variable in main-loop.c.
    
    I'm not sure whether qemu_get_aio_context() will be necessary in the
    future once devices focus on using their own AioContext instead of the
    main loop AioContext, but for now it allows us to refactor code to
    support multiple AioContext while actually passing the main loop
    AioContext.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h
index 0995288..6f0200a 100644
--- a/include/qemu/main-loop.h
+++ b/include/qemu/main-loop.h
@@ -82,6 +82,11 @@ int qemu_init_main_loop(void);
 int main_loop_wait(int nonblocking);
 
 /**
+ * qemu_get_aio_context: Return the main loop's AioContext
+ */
+AioContext *qemu_get_aio_context(void);
+
+/**
  * qemu_notify_event: Force processing of pending events.
  *
  * Similar to signaling a condition variable, qemu_notify_event forces
diff --git a/main-loop.c b/main-loop.c
index 8c9b58c..eb80ff3 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -109,6 +109,11 @@ static int qemu_signal_init(void)
 
 static AioContext *qemu_aio_context;
 
+AioContext *qemu_get_aio_context(void)
+{
+    return qemu_aio_context;
+}
+
 void qemu_notify_event(void)
 {
     if (!qemu_aio_context) {
commit ed9ba7246758e3250849bfa0a055b4eb98fc5152
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date:   Tue Mar 12 16:05:43 2013 +0900

    sheepdog: set io_flush handler in do_co_req
    
    If an io_flush handler is not set, qemu_aio_wait doesn't invoke
    callbacks.
    
    Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index 27abef2..4245328 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -501,6 +501,13 @@ static void restart_co_req(void *opaque)
     qemu_coroutine_enter(co, NULL);
 }
 
+static int have_co_req(void *opaque)
+{
+    /* this handler is set only when there is a pending request, so
+     * always returns 1. */
+    return 1;
+}
+
 typedef struct SheepdogReqCo {
     int sockfd;
     SheepdogReq *hdr;
@@ -523,14 +530,14 @@ static coroutine_fn void do_co_req(void *opaque)
     unsigned int *rlen = srco->rlen;
 
     co = qemu_coroutine_self();
-    qemu_aio_set_fd_handler(sockfd, NULL, restart_co_req, NULL, co);
+    qemu_aio_set_fd_handler(sockfd, NULL, restart_co_req, have_co_req, co);
 
     ret = send_co_req(sockfd, hdr, data, wlen);
     if (ret < 0) {
         goto out;
     }
 
-    qemu_aio_set_fd_handler(sockfd, restart_co_req, NULL, NULL, co);
+    qemu_aio_set_fd_handler(sockfd, restart_co_req, NULL, have_co_req, co);
 
     ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr));
     if (ret < sizeof(*hdr)) {
@@ -553,6 +560,8 @@ static coroutine_fn void do_co_req(void *opaque)
     }
     ret = 0;
 out:
+    /* there is at most one request for this sockfd, so it is safe to
+     * set each handler to NULL. */
     qemu_aio_set_fd_handler(sockfd, NULL, NULL, NULL, NULL);
 
     srco->ret = ret;
commit 0d6db300cd95339cec6b8ab2ef46bd7cdb040959
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date:   Tue Mar 12 16:05:42 2013 +0900

    sheepdog: use non-blocking fd in coroutine context
    
    Using a blocking socket in the coroutine context reduces the chance of
    switching to other work.  This patch makes the sheepdog driver use a
    non-blocking fd always.
    
    Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index c711c28..27abef2 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -468,6 +468,8 @@ static int connect_to_sdog(BDRVSheepdogState *s)
     if (err != NULL) {
         qerror_report_err(err);
         error_free(err);
+    } else {
+        socket_set_nonblock(fd);
     }
 
     return fd;
@@ -523,7 +525,6 @@ static coroutine_fn void do_co_req(void *opaque)
     co = qemu_coroutine_self();
     qemu_aio_set_fd_handler(sockfd, NULL, restart_co_req, NULL, co);
 
-    socket_set_block(sockfd);
     ret = send_co_req(sockfd, hdr, data, wlen);
     if (ret < 0) {
         goto out;
@@ -553,7 +554,6 @@ static coroutine_fn void do_co_req(void *opaque)
     ret = 0;
 out:
     qemu_aio_set_fd_handler(sockfd, NULL, NULL, NULL, NULL);
-    socket_set_nonblock(sockfd);
 
     srco->ret = ret;
     srco->finished = true;
@@ -776,8 +776,6 @@ static int get_sheep_fd(BDRVSheepdogState *s)
         return fd;
     }
 
-    socket_set_nonblock(fd);
-
     qemu_aio_set_fd_handler(fd, co_read_response, NULL, aio_flush_request, s);
     return fd;
 }
commit 381b487d54ba18c73df9db8452028a330058c505
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Mar 6 18:02:01 2013 +0100

    qcow2: make is_allocated return true for zero clusters
    
    Otherwise, live migration of the top layer will miss zero clusters and
    let the backing file show through.  This also matches what is done in qed.
    
    QCOW2_CLUSTER_ZERO clusters are invalid in v2 image files.  Check this
    directly in qcow2_get_cluster_offset instead of replicating the test
    everywhere.
    
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index ff9ae18..d72d063 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -454,6 +454,9 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
         *cluster_offset &= L2E_COMPRESSED_OFFSET_SIZE_MASK;
         break;
     case QCOW2_CLUSTER_ZERO:
+        if (s->qcow_version < 3) {
+            return -EIO;
+        }
         c = count_contiguous_clusters(nb_clusters, s->cluster_size,
                 &l2_table[l2_index], 0,
                 QCOW_OFLAG_COMPRESSED | QCOW_OFLAG_ZERO);
diff --git a/block/qcow2.c b/block/qcow2.c
index ad43a13..1f99866 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -621,7 +621,7 @@ static int coroutine_fn qcow2_co_is_allocated(BlockDriverState *bs,
         *pnum = 0;
     }
 
-    return (cluster_offset != 0);
+    return (cluster_offset != 0) || (ret == QCOW2_CLUSTER_ZERO);
 }
 
 /* handle reading after the end of the backing file */
@@ -702,10 +702,6 @@ static coroutine_fn int qcow2_co_readv(BlockDriverState *bs, int64_t sector_num,
             break;
 
         case QCOW2_CLUSTER_ZERO:
-            if (s->qcow_version < 3) {
-                ret = -EIO;
-                goto fail;
-            }
             qemu_iovec_memset(&hd_qiov, 0, 0, 512 * cur_nr_sectors);
             break;
 
commit 3647917919dfce5f731755f0ac5955a64bc12570
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Mon Mar 4 15:02:35 2013 +0100

    qcow2: drop unnecessary flush in qcow2_update_snapshot_refcount()
    
    We already flush when the function completes.  There is no need to flush
    after every compressed cluster.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 92519ea..9bfb390 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -790,10 +790,6 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
                             if (ret < 0) {
                                 goto fail;
                             }
-
-                            /* TODO Flushing once for the whole function should
-                             * be enough */
-                            bdrv_flush(bs->file);
                         }
                         /* compressed clusters are never modified */
                         refcount = 2;
commit f9cb2860bd12e223036b61a1f5d1444e57b7efce
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Mon Mar 4 15:02:34 2013 +0100

    qcow2: drop flush in update_cluster_refcount()
    
    The update_cluster_refcount() function increments/decrements a cluster's
    refcount and then returns the new refcount value.
    
    There is no need to flush since both update_cluster_refcount() callers
    already take care of this:
    
    1. qcow2_alloc_bytes() calls update_cluster_refcount() when compressed
       sectors will be appended to an existing cluster with enough free
       space.  qcow2_alloc_bytes() already flushes so there is no need to do
       so in update_cluster_refcount().
    
    2. qcow2_update_snapshot_refcount() sets a cache dependency on refcounts
       if it needs to update L2 entries.  It also flushes before completing.
    
    Removing this flush significantly speeds up qcow2 snapshot creation:
    
      $ qemu-img create -f qcow2 test.qcow2 -o size=50G,preallocation=metadata
      $ time qemu-img snapshot -c new test.qcow2
    
    Time drops from more than 3 minutes to under 1 second.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 3d29d30..92519ea 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -532,8 +532,6 @@ static int update_cluster_refcount(BlockDriverState *bs,
         return ret;
     }
 
-    bdrv_flush(bs->file);
-
     return get_refcount(bs, cluster_index);
 }
 
commit 2154f24e4e3be4435f17fa4382032f95f19e2972
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Mon Mar 4 15:02:33 2013 +0100

    qcow2: flush in qcow2_update_snapshot_refcount()
    
    Users of qcow2_update_snapshot_refcount() do not flush consistently.
    qcow2_snapshot_create() flushes but qcow2_snapshot_goto() and
    qcow2_snapshot_delete() do not.
    
    Solve this by moving the bdrv_flush() into
    qcow2_update_snapshot_refcount().
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 4d9df5f..3d29d30 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -851,7 +851,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
         }
     }
 
-    ret = 0;
+    ret = bdrv_flush(bs);
 fail:
     if (l2_table) {
         qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index f4719d9..992a5c8 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -381,11 +381,6 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
         goto fail;
     }
 
-    ret = bdrv_flush(bs);
-    if (ret < 0) {
-        goto fail;
-    }
-
     /* Append the new snapshot to the snapshot list */
     new_snapshot_list = g_malloc((s->nb_snapshots + 1) * sizeof(QCowSnapshot));
     if (s->snapshots) {
commit c1f5bafd70a8d9366570a3de472ef108415cd631
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Mon Mar 4 15:02:32 2013 +0100

    qcow2: set L2 cache dependency in qcow2_alloc_bytes()
    
    Compressed writes use qcow2_alloc_bytes() to allocate space with byte
    granularity.  The affected clusters' refcounts will be incremented but
    we do not need to flush yet.
    
    Set a L2 cache dependency on the refcount block cache, so that the
    refcounts get written out before the L2 updates.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index e8b5d0a..4d9df5f 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -669,7 +669,11 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
         }
     }
 
-    bdrv_flush(bs->file);
+    /* The cluster refcount was incremented, either by qcow2_alloc_clusters()
+     * or explicitly by update_cluster_refcount().  Refcount blocks must be
+     * flushed before the caller's L2 table updates.
+     */
+    qcow2_cache_set_dependency(bs, s->l2_table_cache, s->refcount_block_cache);
     return offset;
 }
 
commit f6977f15561973d4a67b6aa46da88aa678c505dd
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Mon Mar 4 15:02:31 2013 +0100

    qcow2: flush refcount cache correctly in qcow2_write_snapshots()
    
    Since qcow2 metadata is cached we need to flush the caches, not just the
    underlying file.  Use bdrv_flush(bs) instead of bdrv_flush(bs->file).
    
    Also add the error return path when bdrv_flush() fails and move the
    flush after checking for qcow2_alloc_clusters() failure so that the
    qcow2_alloc_clusters() error return value takes precedence.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index eb8fcd5..f4719d9 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -180,11 +180,14 @@ static int qcow2_write_snapshots(BlockDriverState *bs)
 
     /* Allocate space for the new snapshot list */
     snapshots_offset = qcow2_alloc_clusters(bs, snapshots_size);
-    bdrv_flush(bs->file);
     offset = snapshots_offset;
     if (offset < 0) {
         return offset;
     }
+    ret = bdrv_flush(bs);
+    if (ret < 0) {
+        return ret;
+    }
 
     /* Write all snapshots to the new list */
     for(i = 0; i < s->nb_snapshots; i++) {
commit 9991923b262dc35f6dd8393ab4853edd7fc3724f
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Mon Mar 4 15:02:30 2013 +0100

    qcow2: flush refcount cache correctly in alloc_refcount_block()
    
    update_refcount() affects the refcount cache, it does not write to disk.
    Therefore bdrv_flush(bs->file) does nothing.  We need to flush the
    refcount cache in order to write out the refcount updates!
    
    While we're here also add error returns when qcow2_cache_flush() fails.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 55543ed..e8b5d0a 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -201,7 +201,10 @@ static int alloc_refcount_block(BlockDriverState *bs,
     *refcount_block = NULL;
 
     /* We write to the refcount table, so we might depend on L2 tables */
-    qcow2_cache_flush(bs, s->l2_table_cache);
+    ret = qcow2_cache_flush(bs, s->l2_table_cache);
+    if (ret < 0) {
+        return ret;
+    }
 
     /* Allocate the refcount block itself and mark it as used */
     int64_t new_block = alloc_clusters_noref(bs, s->cluster_size);
@@ -237,7 +240,10 @@ static int alloc_refcount_block(BlockDriverState *bs,
             goto fail_block;
         }
 
-        bdrv_flush(bs->file);
+        ret = qcow2_cache_flush(bs, s->refcount_block_cache);
+        if (ret < 0) {
+            goto fail_block;
+        }
 
         /* Initialize the new refcount block only after updating its refcount,
          * update_refcount uses the refcount cache itself */
commit 74c4510a3cf7c369ee524c6f8fa8a87cf08ba608
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 15 10:35:08 2013 +0100

    qcow2: Allow lazy refcounts to be enabled on the command line
    
    qcow2 images now accept a boolean lazy_refcounts options. Use it like
    this:
    
      -drive file=test.qcow2,lazy_refcounts=on
    
    If the option is specified on the command line, it overrides the default
    specified by the qcow2 header flags that were set when creating the
    image.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 56fccf9..ff9ae18 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -668,7 +668,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
     }
 
     /* Update L2 table. */
-    if (s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS) {
+    if (s->use_lazy_refcounts) {
         qcow2_mark_dirty(bs);
     }
     if (qcow2_need_accurate_refcounts(s)) {
diff --git a/block/qcow2.c b/block/qcow2.c
index f5e4269..ad43a13 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -285,11 +285,26 @@ static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result,
     return ret;
 }
 
+static QemuOptsList qcow2_runtime_opts = {
+    .name = "qcow2",
+    .head = QTAILQ_HEAD_INITIALIZER(qcow2_runtime_opts.head),
+    .desc = {
+        {
+            .name = "lazy_refcounts",
+            .type = QEMU_OPT_BOOL,
+            .help = "Postpone refcount updates",
+        },
+        { /* end of list */ }
+    },
+};
+
 static int qcow2_open(BlockDriverState *bs, QDict *options, int flags)
 {
     BDRVQcowState *s = bs->opaque;
     int len, i, ret = 0;
     QCowHeader header;
+    QemuOpts *opts;
+    Error *local_err = NULL;
     uint64_t ext_end;
 
     ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
@@ -495,6 +510,28 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags)
         }
     }
 
+    /* Enable lazy_refcounts according to image and command line options */
+    opts = qemu_opts_create_nofail(&qcow2_runtime_opts);
+    qemu_opts_absorb_qdict(opts, options, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        ret = -EINVAL;
+        goto fail;
+    }
+
+    s->use_lazy_refcounts = qemu_opt_get_bool(opts, "lazy_refcounts",
+        (s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS));
+
+    qemu_opts_del(opts);
+
+    if (s->use_lazy_refcounts && s->qcow_version < 3) {
+        qerror_report(ERROR_CLASS_GENERIC_ERROR, "Lazy refcounts require "
+            "a qcow2 image with at least qemu 1.1 compatibility level");
+        ret = -EINVAL;
+        goto fail;
+    }
+
 #ifdef DEBUG_ALLOC
     {
         BdrvCheckResult result = {0};
diff --git a/block/qcow2.h b/block/qcow2.h
index 718b52b..103abdb 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -173,6 +173,7 @@ typedef struct BDRVQcowState {
 
     int flags;
     int qcow_version;
+    bool use_lazy_refcounts;
 
     uint64_t incompatible_features;
     uint64_t compatible_features;
commit 0006383e1549b6f9b264575d124c553efca19d62
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 15 10:35:07 2013 +0100

    block: Support driver specific options in drive_init()
    
    Any non-default -drive options are now passed down to the block drivers.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index acf1c32..7ae6198 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -22,6 +22,7 @@
 #include "sysemu/arch_init.h"
 
 static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
+extern QemuOptsList qemu_common_drive_opts;
 
 static const char *const if_name[IF_COUNT] = {
     [IF_NONE] = "none",
@@ -288,7 +289,7 @@ static bool do_check_io_limits(BlockIOLimit *io_limits, Error **errp)
     return true;
 }
 
-DriveInfo *drive_init(QemuOpts *opts, BlockInterfaceType block_default_type)
+DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
 {
     const char *buf;
     const char *file = NULL;
@@ -311,10 +312,36 @@ DriveInfo *drive_init(QemuOpts *opts, BlockInterfaceType block_default_type)
     bool copy_on_read;
     int ret;
     Error *error = NULL;
+    QemuOpts *opts;
+    QDict *bs_opts;
+    const char *id;
 
     translation = BIOS_ATA_TRANSLATION_AUTO;
     media = MEDIA_DISK;
 
+    /* Check common options by copying from all_opts to opts, all other options
+     * are stored in bs_opts. */
+    id = qemu_opts_id(all_opts);
+    opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error);
+    if (error_is_set(&error)) {
+        qerror_report_err(error);
+        error_free(error);
+        return NULL;
+    }
+
+    bs_opts = qdict_new();
+    qemu_opts_to_qdict(all_opts, bs_opts);
+    qemu_opts_absorb_qdict(opts, bs_opts, &error);
+    if (error_is_set(&error)) {
+        qerror_report_err(error);
+        error_free(error);
+        return NULL;
+    }
+
+    if (id) {
+        qdict_del(bs_opts, "id");
+    }
+
     /* extract parameters */
     bus_id  = qemu_opt_get_number(opts, "bus", 0);
     unit_id = qemu_opt_get_number(opts, "unit", -1);
@@ -565,7 +592,7 @@ DriveInfo *drive_init(QemuOpts *opts, BlockInterfaceType block_default_type)
     dinfo->heads = heads;
     dinfo->secs = secs;
     dinfo->trans = translation;
-    dinfo->opts = opts;
+    dinfo->opts = all_opts;
     dinfo->refcount = 1;
     if (serial != NULL) {
         dinfo->serial = g_strdup(serial);
@@ -590,17 +617,20 @@ DriveInfo *drive_init(QemuOpts *opts, BlockInterfaceType block_default_type)
     case IF_MTD:
         break;
     case IF_VIRTIO:
+    {
         /* add virtio block device */
-        opts = qemu_opts_create_nofail(qemu_find_opts("device"));
+        QemuOpts *devopts;
+        devopts = qemu_opts_create_nofail(qemu_find_opts("device"));
         if (arch_type == QEMU_ARCH_S390X) {
-            qemu_opt_set(opts, "driver", "virtio-blk-s390");
+            qemu_opt_set(devopts, "driver", "virtio-blk-s390");
         } else {
-            qemu_opt_set(opts, "driver", "virtio-blk-pci");
+            qemu_opt_set(devopts, "driver", "virtio-blk-pci");
         }
-        qemu_opt_set(opts, "drive", dinfo->id);
+        qemu_opt_set(devopts, "drive", dinfo->id);
         if (devaddr)
-            qemu_opt_set(opts, "addr", devaddr);
+            qemu_opt_set(devopts, "addr", devaddr);
         break;
+    }
     default:
         abort();
     }
@@ -638,7 +668,9 @@ DriveInfo *drive_init(QemuOpts *opts, BlockInterfaceType block_default_type)
         error_report("warning: disabling copy_on_read on readonly drive");
     }
 
-    ret = bdrv_open(dinfo->bdrv, file, NULL, bdrv_flags, drv);
+    ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, drv);
+    bs_opts = NULL;
+
     if (ret < 0) {
         if (ret == -EMEDIUMTYPE) {
             error_report("could not open disk image %s: not in %s format",
@@ -652,9 +684,14 @@ DriveInfo *drive_init(QemuOpts *opts, BlockInterfaceType block_default_type)
 
     if (bdrv_key_required(dinfo->bdrv))
         autostart = 0;
+
+    qemu_opts_del(opts);
+
     return dinfo;
 
 err:
+    qemu_opts_del(opts);
+    QDECREF(bs_opts);
     bdrv_delete(dinfo->bdrv);
     g_free(dinfo->id);
     QTAILQ_REMOVE(&drives, dinfo, next);
@@ -1464,9 +1501,9 @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp)
     return dummy.next;
 }
 
-QemuOptsList qemu_drive_opts = {
+QemuOptsList qemu_common_drive_opts = {
     .name = "drive",
-    .head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head),
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_common_drive_opts.head),
     .desc = {
         {
             .name = "bus",
@@ -1585,3 +1622,15 @@ QemuOptsList qemu_drive_opts = {
         { /* end of list */ }
     },
 };
+
+QemuOptsList qemu_drive_opts = {
+    .name = "drive",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head),
+    .desc = {
+        /*
+         * no elements => accept any params
+         * validation will happen later
+         */
+        { /* end of list */ }
+    },
+};
commit bb44619b06c0bef20b658ff532cf850c16362ae7
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 15 10:35:06 2013 +0100

    blockdev: Keep a copy of DriveInfo.serial
    
    Pointing to a QemuOpts element is surprising and can lead to subtle
    use-after-free errors when the QemuOpts is freed after all options are
    parsed.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index d679174..acf1c32 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -191,6 +191,7 @@ static void drive_uninit(DriveInfo *dinfo)
     bdrv_delete(dinfo->bdrv);
     g_free(dinfo->id);
     QTAILQ_REMOVE(&drives, dinfo, next);
+    g_free(dinfo->serial);
     g_free(dinfo);
 }
 
@@ -566,7 +567,9 @@ DriveInfo *drive_init(QemuOpts *opts, BlockInterfaceType block_default_type)
     dinfo->trans = translation;
     dinfo->opts = opts;
     dinfo->refcount = 1;
-    dinfo->serial = serial;
+    if (serial != NULL) {
+        dinfo->serial = g_strdup(serial);
+    }
     QTAILQ_INSERT_TAIL(&drives, dinfo, next);
 
     bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
index 1fe5332..804ec88 100644
--- a/include/sysemu/blockdev.h
+++ b/include/sysemu/blockdev.h
@@ -40,7 +40,7 @@ struct DriveInfo {
     int media_cd;
     int cyls, heads, secs, trans;
     QemuOpts *opts;
-    const char *serial;
+    char *serial;
     QTAILQ_ENTRY(DriveInfo) next;
     int refcount;
 };
commit 376609cc6c03c2ffc8c323d804d27f95346cac08
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 15 10:35:05 2013 +0100

    qemu-option: Add qemu_opts_absorb_qdict()
    
    This adds a function that adds all entries of a QDict to a QemuOpts if
    the keys are known, and leaves only the rest in the QDict.
    
    This way a single QDict of -drive options can be processed in multiple
    places (generic block layer, block driver, backing file block driver,
    etc.), where each part picks the options it knows. If at the end of the
    process the QDict isn't empty, the user specified an invalid option.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/include/qemu/option.h b/include/qemu/option.h
index ba197cd..bdb6d21 100644
--- a/include/qemu/option.h
+++ b/include/qemu/option.h
@@ -149,6 +149,7 @@ void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
 QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
                                Error **errp);
 QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict);
+void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp);
 
 typedef int (*qemu_opts_loopfunc)(QemuOpts *opts, void *opaque);
 int qemu_opts_print(QemuOpts *opts, void *dummy);
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 5a1d03c..8b74bf1 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -1067,6 +1067,40 @@ QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
 }
 
 /*
+ * Adds all QDict entries to the QemuOpts that can be added and removes them
+ * from the QDict. When this function returns, the QDict contains only those
+ * entries that couldn't be added to the QemuOpts.
+ */
+void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp)
+{
+    const QDictEntry *entry, *next;
+
+    entry = qdict_first(qdict);
+
+    while (entry != NULL) {
+        Error *local_err = NULL;
+        OptsFromQDictState state = {
+            .errp = &local_err,
+            .opts = opts,
+        };
+
+        next = qdict_next(qdict, entry);
+
+        if (find_desc_by_name(opts->list->desc, entry->key)) {
+            qemu_opts_from_qdict_1(entry->key, entry->value, &state);
+            if (error_is_set(&local_err)) {
+                error_propagate(errp, local_err);
+                return;
+            } else {
+                qdict_del(qdict, entry->key);
+            }
+        }
+
+        entry = next;
+    }
+}
+
+/*
  * Convert from QemuOpts to QDict.
  * The QDict values are of type QString.
  * TODO We'll want to use types appropriate for opt->desc->type, but
commit b6ad491a4921557efc8815fe0ca5f11c6d8d587e
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 15 10:35:04 2013 +0100

    block: Add options QDict to bdrv_open_common()
    
    The options are passed down to the block drivers, which are supposed to
    remove all options they have processed. Anything that is left over in
    the end is an unknown option and results in an error.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block.c b/block.c
index 761ea86..0ab164d 100644
--- a/block.c
+++ b/block.c
@@ -665,15 +665,18 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags)
 
 /*
  * Common part for opening disk images and files
+ *
+ * Removes all processed options from *options.
  */
 static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
-    const char *filename,
+    const char *filename, QDict *options,
     int flags, BlockDriver *drv)
 {
     int ret, open_flags;
 
     assert(drv != NULL);
     assert(bs->file == NULL);
+    assert(options == NULL || bs->options != options);
 
     trace_bdrv_open_common(bs, filename, flags, drv->format_name);
 
@@ -710,7 +713,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
     } else {
         assert(file != NULL);
         bs->file = file;
-        ret = drv->bdrv_open(bs, NULL, open_flags);
+        ret = drv->bdrv_open(bs, options, open_flags);
     }
 
     if (ret < 0) {
@@ -752,7 +755,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
     }
 
     bs = bdrv_new("");
-    ret = bdrv_open_common(bs, NULL, filename, flags, drv);
+    ret = bdrv_open_common(bs, NULL, filename, NULL, flags, drv);
     if (ret < 0) {
         bdrv_delete(bs);
         return ret;
@@ -821,6 +824,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
     }
 
     bs->options = options;
+    options = qdict_clone_shallow(options);
 
     /* For snapshot=on, create a temporary qcow2 overlay */
     if (flags & BDRV_O_SNAPSHOT) {
@@ -903,7 +907,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
     }
 
     /* Open the image */
-    ret = bdrv_open_common(bs, file, filename, flags, drv);
+    ret = bdrv_open_common(bs, file, filename, options, flags, drv);
     if (ret < 0) {
         goto unlink_and_fail;
     }
@@ -917,11 +921,22 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
     if ((flags & BDRV_O_NO_BACKING) == 0) {
         ret = bdrv_open_backing_file(bs);
         if (ret < 0) {
-            bdrv_close(bs);
-            return ret;
+            goto close_and_fail;
         }
     }
 
+    /* Check if any unknown options were used */
+    if (qdict_size(options) != 0) {
+        const QDictEntry *entry = qdict_first(options);
+        qerror_report(ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by "
+            "device '%s' doesn't support the option '%s'",
+            drv->format_name, bs->device_name, entry->key);
+
+        ret = -EINVAL;
+        goto close_and_fail;
+    }
+    QDECREF(options);
+
     if (!bdrv_key_required(bs)) {
         bdrv_dev_change_media_cb(bs, true);
     }
@@ -942,8 +957,13 @@ unlink_and_fail:
     }
 fail:
     QDECREF(bs->options);
+    QDECREF(options);
     bs->options = NULL;
+    return ret;
 
+close_and_fail:
+    bdrv_close(bs);
+    QDECREF(options);
     return ret;
 }
 
commit b382bc9a1504c7f7c112881695d08293b906b88f
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 15 10:35:03 2013 +0100

    Add qdict_clone_shallow()
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
index 6d9a4be..685b2e3 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -64,4 +64,6 @@ int64_t qdict_get_try_int(const QDict *qdict, const char *key,
 int qdict_get_try_bool(const QDict *qdict, const char *key, int def_value);
 const char *qdict_get_try_str(const QDict *qdict, const char *key);
 
+QDict *qdict_clone_shallow(const QDict *src);
+
 #endif /* QDICT_H */
diff --git a/qobject/qdict.c b/qobject/qdict.c
index 7543ccc..ed381f9 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -401,6 +401,28 @@ const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry)
 }
 
 /**
+ * qdict_clone_shallow(): Clones a given QDict. Its entries are not copied, but
+ * another reference is added.
+ */
+QDict *qdict_clone_shallow(const QDict *src)
+{
+    QDict *dest;
+    QDictEntry *entry;
+    int i;
+
+    dest = qdict_new();
+
+    for (i = 0; i < QDICT_BUCKET_MAX; i++) {
+        QLIST_FOREACH(entry, &src->table[i], next) {
+            qobject_incref(entry->value);
+            qdict_put_obj(dest, entry->key, entry->value);
+        }
+    }
+
+    return dest;
+}
+
+/**
  * qentry_destroy(): Free all the memory allocated by a QDictEntry
  */
 static void qentry_destroy(QDictEntry *e)
commit de9c0cec6c823071b903ebeebf1ee70b394ff46f
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 15 10:35:02 2013 +0100

    block: Add options QDict to bdrv_open() prototype
    
    It doesn't do anything yet except storing the options QDict in the
    BlockDriverState.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block.c b/block.c
index 01cee87..761ea86 100644
--- a/block.c
+++ b/block.c
@@ -788,7 +788,8 @@ int bdrv_open_backing_file(BlockDriverState *bs)
     /* backing files always opened read-only */
     back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT);
 
-    ret = bdrv_open(bs->backing_hd, backing_filename, back_flags, back_drv);
+    ret = bdrv_open(bs->backing_hd, backing_filename, NULL,
+                    back_flags, back_drv);
     if (ret < 0) {
         bdrv_delete(bs->backing_hd);
         bs->backing_hd = NULL;
@@ -800,15 +801,28 @@ int bdrv_open_backing_file(BlockDriverState *bs)
 
 /*
  * Opens a disk image (raw, qcow2, vmdk, ...)
+ *
+ * options is a QDict of options to pass to the block drivers, or NULL for an
+ * empty set of options. The reference to the QDict belongs to the block layer
+ * after the call (even on failure), so if the caller intends to reuse the
+ * dictionary, it needs to use QINCREF() before calling bdrv_open.
  */
-int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
-              BlockDriver *drv)
+int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
+              int flags, BlockDriver *drv)
 {
     int ret;
     /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
     char tmp_filename[PATH_MAX + 1];
     BlockDriverState *file = NULL;
 
+    /* NULL means an empty set of options */
+    if (options == NULL) {
+        options = qdict_new();
+    }
+
+    bs->options = options;
+
+    /* For snapshot=on, create a temporary qcow2 overlay */
     if (flags & BDRV_O_SNAPSHOT) {
         BlockDriverState *bs1;
         int64_t total_size;
@@ -822,10 +836,10 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
 
         /* if there is a backing file, use it */
         bs1 = bdrv_new("");
-        ret = bdrv_open(bs1, filename, 0, drv);
+        ret = bdrv_open(bs1, filename, NULL, 0, drv);
         if (ret < 0) {
             bdrv_delete(bs1);
-            return ret;
+            goto fail;
         }
         total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK;
 
@@ -836,15 +850,17 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
 
         ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));
         if (ret < 0) {
-            return ret;
+            goto fail;
         }
 
         /* Real path is meaningless for protocols */
-        if (is_protocol)
+        if (is_protocol) {
             snprintf(backing_filename, sizeof(backing_filename),
                      "%s", filename);
-        else if (!realpath(filename, backing_filename))
-            return -errno;
+        } else if (!realpath(filename, backing_filename)) {
+            ret = -errno;
+            goto fail;
+        }
 
         bdrv_qcow2 = bdrv_find_format("qcow2");
         options = parse_option_parameters("", bdrv_qcow2->create_options, NULL);
@@ -859,7 +875,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
         ret = bdrv_create(bdrv_qcow2, tmp_filename, options);
         free_option_parameters(options);
         if (ret < 0) {
-            return ret;
+            goto fail;
         }
 
         filename = tmp_filename;
@@ -874,7 +890,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
 
     ret = bdrv_file_open(&file, filename, bdrv_open_flags(bs, flags));
     if (ret < 0) {
-        return ret;
+        goto fail;
     }
 
     /* Find the right image format driver */
@@ -924,6 +940,10 @@ unlink_and_fail:
     if (bs->is_temporary) {
         unlink(filename);
     }
+fail:
+    QDECREF(bs->options);
+    bs->options = NULL;
+
     return ret;
 }
 
@@ -1193,6 +1213,8 @@ void bdrv_close(BlockDriverState *bs)
         bs->valid_key = 0;
         bs->sg = 0;
         bs->growable = 0;
+        QDECREF(bs->options);
+        bs->options = NULL;
 
         if (bs->file != NULL) {
             bdrv_delete(bs->file);
@@ -4594,7 +4616,8 @@ void bdrv_img_create(const char *filename, const char *fmt,
 
             bs = bdrv_new("");
 
-            ret = bdrv_open(bs, backing_file->value.s, back_flags, backing_drv);
+            ret = bdrv_open(bs, backing_file->value.s, NULL, back_flags,
+                            backing_drv);
             if (ret < 0) {
                 error_setg_errno(errp, -ret, "Could not open '%s'",
                                  backing_file->value.s);
diff --git a/block/blkverify.c b/block/blkverify.c
index a7dd459..2086d97 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -98,7 +98,7 @@ static int blkverify_open(BlockDriverState *bs, const char *filename, int flags)
 
     /* Open the test file */
     s->test_file = bdrv_new("");
-    ret = bdrv_open(s->test_file, filename, flags, NULL);
+    ret = bdrv_open(s->test_file, filename, NULL, flags, NULL);
     if (ret < 0) {
         bdrv_delete(s->test_file);
         s->test_file = NULL;
diff --git a/block/qcow2.c b/block/qcow2.c
index 4c501a5..f5e4269 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1265,7 +1265,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
      */
     BlockDriver* drv = bdrv_find_format("qcow2");
     assert(drv != NULL);
-    ret = bdrv_open(bs, filename,
+    ret = bdrv_open(bs, filename, NULL,
         BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, drv);
     if (ret < 0) {
         goto out;
diff --git a/block/vmdk.c b/block/vmdk.c
index 4a13fa6..e92104a 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1527,7 +1527,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options)
     if (backing_file) {
         char parent_filename[PATH_MAX];
         BlockDriverState *bs = bdrv_new("");
-        ret = bdrv_open(bs, backing_file, 0, NULL);
+        ret = bdrv_open(bs, backing_file, NULL, 0, NULL);
         if (ret != 0) {
             bdrv_delete(bs);
             return ret;
diff --git a/block/vvfat.c b/block/vvfat.c
index 06e6654..b8eb38a 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -2830,7 +2830,7 @@ static int enable_write_target(BDRVVVFATState *s)
         return -1;
     }
 
-    ret = bdrv_open(s->qcow, s->qcow_filename,
+    ret = bdrv_open(s->qcow, s->qcow_filename, NULL,
             BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow);
     if (ret < 0) {
 	return ret;
diff --git a/blockdev.c b/blockdev.c
index 0e67d06..d679174 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -635,7 +635,7 @@ DriveInfo *drive_init(QemuOpts *opts, BlockInterfaceType block_default_type)
         error_report("warning: disabling copy_on_read on readonly drive");
     }
 
-    ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv);
+    ret = bdrv_open(dinfo->bdrv, file, NULL, bdrv_flags, drv);
     if (ret < 0) {
         if (ret == -EMEDIUMTYPE) {
             error_report("could not open disk image %s: not in %s format",
@@ -820,7 +820,9 @@ void qmp_transaction(BlockdevActionList *dev_list, Error **errp)
 
         /* We will manually add the backing_hd field to the bs later */
         states->new_bs = bdrv_new("");
-        ret = bdrv_open(states->new_bs, new_image_file,
+        /* TODO Inherit bs->options or only take explicit options with an
+         * extended QMP command? */
+        ret = bdrv_open(states->new_bs, new_image_file, NULL,
                         flags | BDRV_O_NO_BACKING, drv);
         if (ret != 0) {
             error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file);
@@ -921,7 +923,7 @@ static void qmp_bdrv_open_encrypted(BlockDriverState *bs, const char *filename,
                                     int bdrv_flags, BlockDriver *drv,
                                     const char *password, Error **errp)
 {
-    if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) {
+    if (bdrv_open(bs, filename, NULL, bdrv_flags, drv) < 0) {
         error_set(errp, QERR_OPEN_FILE_FAILED, filename);
         return;
     }
@@ -1330,7 +1332,7 @@ void qmp_drive_mirror(const char *device, const char *target,
      * file.
      */
     target_bs = bdrv_new("");
-    ret = bdrv_open(target_bs, target, flags | BDRV_O_NO_BACKING, drv);
+    ret = bdrv_open(target_bs, target, NULL, flags | BDRV_O_NO_BACKING, drv);
 
     if (ret < 0) {
         bdrv_delete(target_bs);
diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index cc09a2f..83329e2 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -763,7 +763,7 @@ static int blk_init(struct XenDevice *xendev)
         xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
         blkdev->bs = bdrv_new(blkdev->dev);
         if (blkdev->bs) {
-            if (bdrv_open(blkdev->bs, blkdev->filename, qflags,
+            if (bdrv_open(blkdev->bs, blkdev->filename, NULL, qflags,
                         bdrv_find_whitelisted_format(blkdev->fileproto)) != 0) {
                 bdrv_delete(blkdev->bs);
                 blkdev->bs = NULL;
diff --git a/include/block/block.h b/include/block/block.h
index 0f750d7..d4f34d6 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -137,8 +137,8 @@ int bdrv_parse_cache_flags(const char *mode, int *flags);
 int bdrv_parse_discard_flags(const char *mode, int *flags);
 int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
 int bdrv_open_backing_file(BlockDriverState *bs);
-int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
-              BlockDriver *drv);
+int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
+              int flags, BlockDriver *drv);
 BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
                                     BlockDriverState *bs, int flags);
 int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 4b659fa..baf80e3 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -286,6 +286,7 @@ struct BlockDriverState {
     /* long-running background operation */
     BlockJob *job;
 
+    QDict *options;
 };
 
 int get_tmp_filename(char *filename, int size);
diff --git a/qemu-img.c b/qemu-img.c
index 471de7d..31627b0 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -276,7 +276,7 @@ static BlockDriverState *bdrv_new_open(const char *filename,
         drv = NULL;
     }
 
-    ret = bdrv_open(bs, filename, flags, drv);
+    ret = bdrv_open(bs, filename, NULL, flags, drv);
     if (ret < 0) {
         error_report("Could not open '%s': %s", filename, strerror(-ret));
         goto fail;
@@ -2156,7 +2156,7 @@ static int img_rebase(int argc, char **argv)
 
         bs_old_backing = bdrv_new("old_backing");
         bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
-        ret = bdrv_open(bs_old_backing, backing_name, BDRV_O_FLAGS,
+        ret = bdrv_open(bs_old_backing, backing_name, NULL, BDRV_O_FLAGS,
                         old_backing_drv);
         if (ret) {
             error_report("Could not open old backing file '%s'", backing_name);
@@ -2164,7 +2164,7 @@ static int img_rebase(int argc, char **argv)
         }
         if (out_baseimg[0]) {
             bs_new_backing = bdrv_new("new_backing");
-            ret = bdrv_open(bs_new_backing, out_baseimg, BDRV_O_FLAGS,
+            ret = bdrv_open(bs_new_backing, out_baseimg, NULL, BDRV_O_FLAGS,
                         new_backing_drv);
             if (ret) {
                 error_report("Could not open new backing file '%s'",
diff --git a/qemu-io.c b/qemu-io.c
index 7b3de42..79be516 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1773,7 +1773,7 @@ static int openfile(char *name, int flags, int growable)
     } else {
         bs = bdrv_new("hda");
 
-        if (bdrv_open(bs, name, flags, NULL) < 0) {
+        if (bdrv_open(bs, name, NULL, flags, NULL) < 0) {
             fprintf(stderr, "%s: can't open device %s\n", progname, name);
             bdrv_delete(bs);
             bs = NULL;
diff --git a/qemu-nbd.c b/qemu-nbd.c
index e7268d0..ca722ed 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -557,7 +557,7 @@ int main(int argc, char **argv)
 
     bs = bdrv_new("hda");
     srcpath = argv[optind];
-    if ((ret = bdrv_open(bs, srcpath, flags, NULL)) < 0) {
+    if ((ret = bdrv_open(bs, srcpath, NULL, flags, NULL)) < 0) {
         errno = -ret;
         err(EXIT_FAILURE, "Failed to bdrv_open '%s'", argv[optind]);
     }
commit 1a86938f04b1abfd28e053b8c6f4b8ed9e4ffe08
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Mar 15 10:35:01 2013 +0100

    block: Add options QDict to .bdrv_open()
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block.c b/block.c
index 124a9eb..01cee87 100644
--- a/block.c
+++ b/block.c
@@ -710,7 +710,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
     } else {
         assert(file != NULL);
         bs->file = file;
-        ret = drv->bdrv_open(bs, open_flags);
+        ret = drv->bdrv_open(bs, NULL, open_flags);
     }
 
     if (ret < 0) {
@@ -3190,7 +3190,7 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
     if (bs->file) {
         drv->bdrv_close(bs);
         ret = bdrv_snapshot_goto(bs->file, snapshot_id);
-        open_ret = drv->bdrv_open(bs, bs->open_flags);
+        open_ret = drv->bdrv_open(bs, NULL, bs->open_flags);
         if (open_ret < 0) {
             bdrv_delete(bs->file);
             bs->drv = NULL;
diff --git a/block/bochs.c b/block/bochs.c
index a6eb33d..d7078c0 100644
--- a/block/bochs.c
+++ b/block/bochs.c
@@ -108,7 +108,7 @@ static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename)
     return 0;
 }
 
-static int bochs_open(BlockDriverState *bs, int flags)
+static int bochs_open(BlockDriverState *bs, QDict *options, int flags)
 {
     BDRVBochsState *s = bs->opaque;
     int i;
diff --git a/block/cloop.c b/block/cloop.c
index 8fe13e9..6ea7cf4 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -53,7 +53,7 @@ static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
     return 0;
 }
 
-static int cloop_open(BlockDriverState *bs, int flags)
+static int cloop_open(BlockDriverState *bs, QDict *options, int flags)
 {
     BDRVCloopState *s = bs->opaque;
     uint32_t offsets_size, max_compressed_block_size = 1, i;
diff --git a/block/cow.c b/block/cow.c
index 4baf904..d73e08c 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -58,7 +58,7 @@ static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)
         return 0;
 }
 
-static int cow_open(BlockDriverState *bs, int flags)
+static int cow_open(BlockDriverState *bs, QDict *options, int flags)
 {
     BDRVCowState *s = bs->opaque;
     struct cow_header_v2 cow_header;
diff --git a/block/dmg.c b/block/dmg.c
index 6d85801..c1066df 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -85,7 +85,7 @@ static int read_uint32(BlockDriverState *bs, int64_t offset, uint32_t *result)
     return 0;
 }
 
-static int dmg_open(BlockDriverState *bs, int flags)
+static int dmg_open(BlockDriverState *bs, QDict *options, int flags)
 {
     BDRVDMGState *s = bs->opaque;
     uint64_t info_begin,info_end,last_in_offset,last_out_offset;
diff --git a/block/parallels.c b/block/parallels.c
index 8688f6c..18b3ac0 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -68,7 +68,7 @@ static int parallels_probe(const uint8_t *buf, int buf_size, const char *filenam
     return 0;
 }
 
-static int parallels_open(BlockDriverState *bs, int flags)
+static int parallels_open(BlockDriverState *bs, QDict *options, int flags)
 {
     BDRVParallelsState *s = bs->opaque;
     int i;
diff --git a/block/qcow.c b/block/qcow.c
index a7135ee..f6750a5 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -92,7 +92,7 @@ static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
         return 0;
 }
 
-static int qcow_open(BlockDriverState *bs, int flags)
+static int qcow_open(BlockDriverState *bs, QDict *options, int flags)
 {
     BDRVQcowState *s = bs->opaque;
     int len, i, shift, ret;
diff --git a/block/qcow2.c b/block/qcow2.c
index 7610e56..4c501a5 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -285,7 +285,7 @@ static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result,
     return ret;
 }
 
-static int qcow2_open(BlockDriverState *bs, int flags)
+static int qcow2_open(BlockDriverState *bs, QDict *options, int flags)
 {
     BDRVQcowState *s = bs->opaque;
     int len, i, ret = 0;
@@ -912,7 +912,7 @@ static void qcow2_invalidate_cache(BlockDriverState *bs)
     qcow2_close(bs);
 
     memset(s, 0, sizeof(BDRVQcowState));
-    qcow2_open(bs, flags);
+    qcow2_open(bs, NULL, flags);
 
     if (crypt_method) {
         s->crypt_method = crypt_method;
diff --git a/block/qed.c b/block/qed.c
index b8515e5..46e12b3 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -373,7 +373,7 @@ static void bdrv_qed_rebind(BlockDriverState *bs)
     s->bs = bs;
 }
 
-static int bdrv_qed_open(BlockDriverState *bs, int flags)
+static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags)
 {
     BDRVQEDState *s = bs->opaque;
     QEDHeader le_header;
@@ -1526,7 +1526,7 @@ static void bdrv_qed_invalidate_cache(BlockDriverState *bs)
 
     bdrv_qed_close(bs);
     memset(s, 0, sizeof(BDRVQEDState));
-    bdrv_qed_open(bs, bs->open_flags);
+    bdrv_qed_open(bs, NULL, bs->open_flags);
 }
 
 static int bdrv_qed_check(BlockDriverState *bs, BdrvCheckResult *result,
diff --git a/block/raw.c b/block/raw.c
index 75812db..ce10422 100644
--- a/block/raw.c
+++ b/block/raw.c
@@ -3,7 +3,7 @@
 #include "block/block_int.h"
 #include "qemu/module.h"
 
-static int raw_open(BlockDriverState *bs, int flags)
+static int raw_open(BlockDriverState *bs, QDict *options, int flags)
 {
     bs->sg = bs->file->sg;
     return 0;
diff --git a/block/vdi.c b/block/vdi.c
index 87c691b..2662d89 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -364,7 +364,7 @@ static int vdi_probe(const uint8_t *buf, int buf_size, const char *filename)
     return result;
 }
 
-static int vdi_open(BlockDriverState *bs, int flags)
+static int vdi_open(BlockDriverState *bs, QDict *options, int flags)
 {
     BDRVVdiState *s = bs->opaque;
     VdiHeader header;
diff --git a/block/vmdk.c b/block/vmdk.c
index aef1abc..4a13fa6 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -723,7 +723,7 @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
     return vmdk_parse_extents(buf, bs, bs->file->filename);
 }
 
-static int vmdk_open(BlockDriverState *bs, int flags)
+static int vmdk_open(BlockDriverState *bs, QDict *options, int flags)
 {
     int ret;
     BDRVVmdkState *s = bs->opaque;
diff --git a/block/vpc.c b/block/vpc.c
index 82229ef..3cad52e 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -155,7 +155,7 @@ static int vpc_probe(const uint8_t *buf, int buf_size, const char *filename)
     return 0;
 }
 
-static int vpc_open(BlockDriverState *bs, int flags)
+static int vpc_open(BlockDriverState *bs, QDict *options, int flags)
 {
     BDRVVPCState *s = bs->opaque;
     int i;
diff --git a/include/block/block_int.h b/include/block/block_int.h
index eaad53e..4b659fa 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -82,7 +82,7 @@ struct BlockDriver {
     void (*bdrv_reopen_commit)(BDRVReopenState *reopen_state);
     void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state);
 
-    int (*bdrv_open)(BlockDriverState *bs, int flags);
+    int (*bdrv_open)(BlockDriverState *bs, QDict *options, int flags);
     int (*bdrv_file_open)(BlockDriverState *bs, const char *filename, int flags);
     int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
                      uint8_t *buf, int nb_sectors);
commit 4f306496183d81aed4b43762cf3bfd6e054de767
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Fri Mar 15 15:04:39 2013 +1000

    qga/main.c: Don't use g_key_file_get/set_int64
    
    These functions don't exist until glib version 2.26. QEMU is currently only
    mandating glib 2.12.
    
    This patch replaces the functions with g_key_file_get/set_integer.
    
    Unbreaks the build on Ubuntu 10.04 and RHEL 5.6.
    
    Regression was introduced by 39097daf15c42243742667607d2cad2c9dc4f764
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 1363323879-682-1-git-send-email-peter.crosthwaite at xilinx.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qga/main.c b/qga/main.c
index 99346e1..74ef788 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -755,7 +755,7 @@ static void persistent_state_from_keyfile(GAPersistentState *pstate,
 
     if (g_key_file_has_key(keyfile, "global", "fd_counter", NULL)) {
         pstate->fd_counter =
-            g_key_file_get_int64(keyfile, "global", "fd_counter", NULL);
+            g_key_file_get_integer(keyfile, "global", "fd_counter", NULL);
     }
 }
 
@@ -765,7 +765,7 @@ static void persistent_state_to_keyfile(const GAPersistentState *pstate,
     g_assert(pstate);
     g_assert(keyfile);
 
-    g_key_file_set_int64(keyfile, "global", "fd_counter", pstate->fd_counter);
+    g_key_file_set_integer(keyfile, "global", "fd_counter", pstate->fd_counter);
 }
 
 static gboolean write_persistent_state(const GAPersistentState *pstate,
commit 139a4b63e3dd002de79d8c0a7c04fcc5bbeb1307
Merge: 3d34a41 344bf1e
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Mar 14 14:54:37 2013 -0500

    Merge remote-tracking branch 'kraxel/chardev.5' into staging
    
    * kraxel/chardev.5:
      spice-qemu-char: Remove dead debugging code
      spice-qemu-char: Fix name parameter issues after qapi-ifying
      qemu-char.c: fix waiting for telnet connection message
      Revert "hmp: Disable chardev-add and chardev-remove"
      chardev: add udp support to qapi
      chardev: add memory (ringbuf) support to qapi
      chardev: add vc support to qapi
      chardev: add spice support to qapi
      chardev: add pipe support to qapi
      chardev: add console support to qapi
      chardev: switch pty init to qapi
      chardev: switch parallel init to qapi
      chardev: switch serial/tty init to qapi
      chardev: add stdio support to qapi
      chardev: switch file init to qapi
      chardev: add braille support to qapi
      chardev: add msmouse support to qapi
      chardev: switch null init to qapi
      chardev: add mux chardev support to qapi
      chardev: add support for qapi-based chardev initialization
    
    Conflicts:
    	ui/console.c
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

commit 3d34a4110c58bba120bc3d7c96c4b9571994c2a8
Merge: 0ec4a8e 0ad6773
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Mar 14 14:50:58 2013 -0500

    Merge remote-tracking branch 'afaerber/qom-cpu' into staging
    
    # By Andreas Färber (16) and Igor Mammedov (1)
    # Via Andreas Färber
    * afaerber/qom-cpu:
      target-lm32: Update VMStateDescription to LM32CPU
      target-arm: Override do_interrupt for ARMv7-M profile
      cpu: Replace do_interrupt() by CPUClass::do_interrupt method
      cpu: Pass CPUState to cpu_interrupt()
      exec: Pass CPUState to cpu_reset_interrupt()
      cpu: Move halted and interrupt_request fields to CPUState
      target-cris/helper.c: Update Coding Style
      target-i386: Update VMStateDescription to X86CPU
      cpu: Introduce cpu_class_set_vmsd()
      cpu: Register VMStateDescription through CPUState
      stubs: Add a vmstate_dummy struct for CONFIG_USER_ONLY
      vmstate: Make vmstate_register() static inline
      target-sh4: Move PVR/PRR/CVR into SuperHCPUClass
      target-sh4: Introduce SuperHCPU subclasses
      cpus: Replace open-coded CPU loop in qmp_memsave() with qemu_get_cpu()
      monitor: Use qemu_get_cpu() in monitor_set_cpu()
      cpu: Fix qemu_get_cpu() to return NULL if CPU not found

commit 0ec4a8e63ce5244cdb2aa8ef93427898e3f6631b
Merge: 6582d3e cbb65fc
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Mar 14 14:50:30 2013 -0500

    Merge remote-tracking branch 'mdroth/qga-pull-3-11-2013' into staging
    
    # By Laszlo Ersek (3) and others
    # Via Michael Roth
    * mdroth/qga-pull-3-11-2013:
      qga: implement qmp_guest_set_vcpus() for Linux with sysfs
      qga: implement qmp_guest_get_vcpus() for Linux with sysfs
      qga: introduce guest-get-vcpus / guest-set-vcpus with stubs
      qga: add guest-set-time command
      qga: add guest-get-time command
      qemu-ga: use key-value store to avoid recycling fd handles after restart
      qemu-ga: make guest-sync-delimited available during fsfreeze
      qemu-ga: fix confusing GAChannelMethod comparison
      qga: cast to int for DWORD type

commit 6582d3e8be98cf8171489793e094aee94a1276ce
Merge: c69b30e e9a970a
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Mar 14 14:50:21 2013 -0500

    Merge remote-tracking branch 'riku/linux-user-for-upstream' into staging
    
    # By Peter Maydell (5) and others
    # Via Riku Voipio
    * riku/linux-user-for-upstream:
      linux-user/syscall.c: Don't warn about unimplemented get_robust_list
      linux-user: Implement accept4
      linux-user: Implement sendfile and sendfile64
      linux-user: make bogus negative iovec lengths fail EINVAL
      linux-user: Fix layout of usage table to account for option text
      linux-user: Add more sparc syscall numbers
      linux-user: Support setgroups syscall with no groups
      linux-user: fix futex strace of FUTEX_CLOCK_REALTIME
      linux-user/syscall.c: handle FUTEX_WAIT_BITSET in do_futex
      linux-user: improve print_fcntl()
      linux-user: Add Alpha socket constants

commit 344bf1e935163d8a4c3cce3ec4c636e1ebd035ce
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Mar 13 14:59:44 2013 +0100

    spice-qemu-char: Remove dead debugging code
    
    Since commit d62e5f7036a018b2ad09f17ebd481bd28953d783
    "chardev: add spice support to qapi"
    
    It is impossible to set the debug parameter, so all the dprintf calls
    are essentially nops. Since we've not needed the debug parameter in ages this
    is not a problem, if it later turns out we do need some more debugging options
    we can add more trace-points.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index a94f76b..8a9236d 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -8,14 +8,6 @@
 
 #include "qemu/osdep.h"
 
-#define dprintf(_scd, _level, _fmt, ...)                                \
-    do {                                                                \
-        static unsigned __dprintf_counter = 0;                          \
-        if (_scd->debug >= _level) {                                    \
-            fprintf(stderr, "scd: %3d: " _fmt, ++__dprintf_counter, ## __VA_ARGS__);\
-        }                                                               \
-    } while (0)
-
 typedef struct SpiceCharDriver {
     CharDriverState*      chr;
     SpiceCharDeviceInstance     sin;
@@ -24,7 +16,6 @@ typedef struct SpiceCharDriver {
     uint8_t               *buffer;
     uint8_t               *datapos;
     ssize_t               bufsize, datalen;
-    uint32_t              debug;
     QLIST_ENTRY(SpiceCharDriver) next;
 } SpiceCharDriver;
 
@@ -49,7 +40,6 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
         p += last_out;
     }
 
-    dprintf(scd, 3, "%s: %zu/%zd\n", __func__, out, len + out);
     trace_spice_vmc_write(out, len + out);
     return out;
 }
@@ -59,7 +49,6 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
     SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
     int bytes = MIN(len, scd->datalen);
 
-    dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen);
     if (bytes > 0) {
         memcpy(buf, scd->datapos, bytes);
         scd->datapos += bytes;
@@ -84,11 +73,9 @@ static void vmc_event(SpiceCharDeviceInstance *sin, uint8_t event)
         chr_event = CHR_EVENT_BREAK;
         break;
     default:
-        dprintf(scd, 2, "%s: unknown %d\n", __func__, event);
         return;
     }
 
-    dprintf(scd, 2, "%s: %d\n", __func__, event);
     trace_spice_vmc_event(chr_event);
     qemu_chr_be_event(scd->chr, chr_event);
 }
@@ -141,7 +128,6 @@ static void vmc_register_interface(SpiceCharDriver *scd)
     if (scd->active) {
         return;
     }
-    dprintf(scd, 1, "%s\n", __func__);
     scd->sin.base.sif = &vmc_interface.base;
     qemu_spice_add_interface(&scd->sin.base);
     scd->active = true;
@@ -153,7 +139,6 @@ static void vmc_unregister_interface(SpiceCharDriver *scd)
     if (!scd->active) {
         return;
     }
-    dprintf(scd, 1, "%s\n", __func__);
     spice_server_remove_interface(&scd->sin.base);
     scd->active = false;
     trace_spice_vmc_unregister_interface(scd);
@@ -164,7 +149,6 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     SpiceCharDriver *s = chr->opaque;
 
-    dprintf(s, 2, "%s: %d\n", __func__, len);
     vmc_register_interface(s);
     assert(s->datalen == 0);
     if (s->bufsize < len) {
@@ -182,7 +166,6 @@ static void spice_chr_close(struct CharDriverState *chr)
 {
     SpiceCharDriver *s = chr->opaque;
 
-    printf("%s\n", __func__);
     vmc_unregister_interface(s);
     QLIST_REMOVE(s, next);
 
commit 5e9b473a3d7fbb915df4b3f5487e5056762087f8
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Mar 13 10:41:31 2013 +0100

    spice-qemu-char: Fix name parameter issues after qapi-ifying
    
    The strings passed in through the qapi calls are dynamic memory, since
    we want to have them stick around longer then just the call to
    qemu_chr_open_spice_* we need to strdup them.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index 0c92ca8..a94f76b 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -185,6 +185,11 @@ static void spice_chr_close(struct CharDriverState *chr)
     printf("%s\n", __func__);
     vmc_unregister_interface(s);
     QLIST_REMOVE(s, next);
+
+    g_free((char *)s->sin.subtype);
+#if SPICE_SERVER_VERSION >= 0x000c02
+    g_free((char *)s->sin.portname);
+#endif
     g_free(s);
 }
 
@@ -226,7 +231,7 @@ static CharDriverState *chr_open(const char *subtype)
     s = g_malloc0(sizeof(SpiceCharDriver));
     s->chr = chr;
     s->active = false;
-    s->sin.subtype = subtype;
+    s->sin.subtype = g_strdup(subtype);
     chr->opaque = s;
     chr->chr_write = spice_chr_write;
     chr->chr_close = spice_chr_close;
@@ -284,7 +289,7 @@ CharDriverState *qemu_chr_open_spice_port(const char *name)
 
     chr = chr_open("port");
     s = chr->opaque;
-    s->sin.portname = name;
+    s->sin.portname = g_strdup(name);
 
     return chr;
 }
commit c69b30e8301a49cd198d54bb740a0c9adcd2a34a
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Mar 13 12:21:04 2013 -0500

    gtk: fix vc initialization
    
        commit 01f45d986fb0b7c2d4f0466efe3cde9708f325be
        Author: Anthony Liguori <aliguori at us.ibm.com>
        Date:   Tue Mar 5 23:21:32 2013 +0530
    
           qemu-char: move text console init to console.c
    
    Broke vc initialization for GTK.  It's a simple typo.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/console.c b/ui/console.c
index 83a6fa3..0f96177 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1742,7 +1742,7 @@ PixelFormat qemu_default_pixelformat(int bpp)
 
 static void register_types(void)
 {
-    register_char_driver("vc", text_console_init);
+    register_char_driver("vc", vc_init);
 }
 
 type_init(register_types);
commit e5545854dd1e2e3507b210ac0c1cbfca69ff0fcb
Author: Igor Mitsyanko <i.mitsyanko at gmail.com>
Date:   Sun Mar 10 17:58:05 2013 +0400

    qemu-char.c: fix waiting for telnet connection message
    
    Current colon position in "waiting for telnet connection" message template
    produces messages like:
    QEMU waiting for connection on: telnet::127.0.0.16666,server
    
    After moving a colon to the right, we will get a correct messages like:
    QEMU waiting for connection on: telnet:127.0.0.1:6666,server
    
    Signed-off-by: Igor Mitsyanko <i.mitsyanko at gmail.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/qemu-char.c b/qemu-char.c
index 7e13757..e633797 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2656,7 +2656,7 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
         s->do_nodelay = do_nodelay;
         getnameinfo((struct sockaddr *) &ss, ss_len, host, sizeof(host),
                     serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV);
-        snprintf(chr->filename, 256, "%s:%s:%s%s%s%s",
+        snprintf(chr->filename, 256, "%s:%s%s%s:%s%s",
                  is_telnet ? "telnet" : "tcp",
                  left, host, right, serv,
                  is_listen ? ",server" : "");
commit 46920825402d38a4111cca8099d1261f8f80c03c
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 28 08:46:10 2013 +0100

    Revert "hmp: Disable chardev-add and chardev-remove"
    
    This reverts commit 8a14952c9d2f5fa2b3caa6dc286b62ed5d26bca7.

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 4bda3fe..df44906 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1522,38 +1522,37 @@ passed since 1970, i.e. unix epoch.
 @end table
 ETEXI
 
-HXCOMM Disabled for now, because it isn't built on top of QMP's chardev-add
-HXCOMM     {
-HXCOMM         .name       = "chardev-add",
-HXCOMM         .args_type  = "args:s",
-HXCOMM         .params     = "args",
-HXCOMM         .help       = "add chardev",
-HXCOMM         .mhandler.cmd = hmp_chardev_add,
-HXCOMM     },
-HXCOMM
-HXCOMM STEXI
-HXCOMM @item chardev_add args
-HXCOMM @findex chardev_add
-HXCOMM
-HXCOMM chardev_add accepts the same parameters as the -chardev command line switch.
-HXCOMM
-HXCOMM ETEXI
-HXCOMM
-HXCOMM     {
-HXCOMM         .name       = "chardev-remove",
-HXCOMM         .args_type  = "id:s",
-HXCOMM         .params     = "id",
-HXCOMM         .help       = "remove chardev",
-HXCOMM         .mhandler.cmd = hmp_chardev_remove,
-HXCOMM     },
-HXCOMM
-HXCOMM STEXI
-HXCOMM @item chardev_remove id
-HXCOMM @findex chardev_remove
-HXCOMM
-HXCOMM Removes the chardev @var{id}.
-HXCOMM
-HXCOMM ETEXI
+    {
+        .name       = "chardev-add",
+        .args_type  = "args:s",
+        .params     = "args",
+        .help       = "add chardev",
+        .mhandler.cmd = hmp_chardev_add,
+    },
+
+STEXI
+ at item chardev_add args
+ at findex chardev_add
+
+chardev_add accepts the same parameters as the -chardev command line switch.
+
+ETEXI
+
+    {
+        .name       = "chardev-remove",
+        .args_type  = "id:s",
+        .params     = "id",
+        .help       = "remove chardev",
+        .mhandler.cmd = hmp_chardev_remove,
+    },
+
+STEXI
+ at item chardev_remove id
+ at findex chardev_remove
+
+Removes the chardev @var{id}.
+
+ETEXI
 
     {
         .name       = "info",
commit 3ecc059dcd06a79495d1bf171ef7f193eff79e98
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Feb 27 14:10:47 2013 +0100

    chardev: add udp support to qapi
    
    This patch adds 'udp' support to qapi.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index c5cee4b..ae5c21c 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -71,6 +71,7 @@ SocketAddress *socket_parse(const char *str, Error **errp);
 int socket_connect(SocketAddress *addr, Error **errp,
                    NonBlockingConnectHandler *callback, void *opaque);
 int socket_listen(SocketAddress *addr, Error **errp);
+int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp);
 
 /* Old, ipv4 only bits.  Don't use for new code. */
 int parse_host_port(struct sockaddr_in *saddr, const char *str);
diff --git a/qapi-schema.json b/qapi-schema.json
index 8d371f1..fdaa9da 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3166,7 +3166,7 @@
 ##
 # @ChardevSocket:
 #
-# Configuration info for socket chardevs.
+# Configuration info for (stream) socket chardevs.
 #
 # @addr: socket address to listen on (server=true)
 #        or connect to (server=false)
@@ -3185,6 +3185,19 @@
                                      '*telnet'  : 'bool' } }
 
 ##
+# @ChardevDgram:
+#
+# Configuration info for datagram socket chardevs.
+#
+# @remote: remote address
+# @local: #optional local address
+#
+# Since: 1.5
+##
+{ 'type': 'ChardevDgram', 'data': { 'remote' : 'SocketAddress',
+                                    '*local' : 'SocketAddress' } }
+
+##
 # @ChardevMux:
 #
 # Configuration info for mux chardevs.
@@ -3272,6 +3285,7 @@
                                        'parallel': 'ChardevHostdev',
                                        'pipe'   : 'ChardevHostdev',
                                        'socket' : 'ChardevSocket',
+                                       'dgram'  : 'ChardevDgram',
                                        'pty'    : 'ChardevDummy',
                                        'null'   : 'ChardevDummy',
                                        'mux'    : 'ChardevMux',
diff --git a/qemu-char.c b/qemu-char.c
index eb2045a..7e13757 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2261,21 +2261,14 @@ static void udp_chr_close(CharDriverState *chr)
     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
-static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
+static CharDriverState *qemu_chr_open_udp_fd(int fd)
 {
     CharDriverState *chr = NULL;
     NetCharDriver *s = NULL;
-    Error *local_err = NULL;
-    int fd = -1;
 
     chr = g_malloc0(sizeof(CharDriverState));
     s = g_malloc0(sizeof(NetCharDriver));
 
-    fd = inet_dgram_opts(opts, &local_err);
-    if (fd < 0) {
-        goto return_err;
-    }
-
     s->fd = fd;
     s->chan = io_channel_from_socket(s->fd);
     s->bufcnt = 0;
@@ -2285,18 +2278,18 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
     chr->chr_update_read_handler = udp_chr_update_read_handler;
     chr->chr_close = udp_chr_close;
     return chr;
+}
 
-return_err:
-    if (local_err) {
-        qerror_report_err(local_err);
-        error_free(local_err);
-    }
-    g_free(chr);
-    g_free(s);
-    if (fd >= 0) {
-        closesocket(fd);
+static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
+{
+    Error *local_err = NULL;
+    int fd = -1;
+
+    fd = inet_dgram_opts(opts, &local_err);
+    if (fd < 0) {
+        return NULL;
     }
-    return NULL;
+    return qemu_chr_open_udp_fd(fd);
 }
 
 /***********************************************************/
@@ -3679,6 +3672,18 @@ static CharDriverState *qmp_chardev_open_socket(ChardevSocket *sock,
                                    is_telnet, is_waitconnect, errp);
 }
 
+static CharDriverState *qmp_chardev_open_dgram(ChardevDgram *dgram,
+                                               Error **errp)
+{
+    int fd;
+
+    fd = socket_dgram(dgram->remote, dgram->local, errp);
+    if (error_is_set(errp)) {
+        return NULL;
+    }
+    return qemu_chr_open_udp_fd(fd);
+}
+
 ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
                                Error **errp)
 {
@@ -3708,6 +3713,9 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
     case CHARDEV_BACKEND_KIND_SOCKET:
         chr = qmp_chardev_open_socket(backend->socket, errp);
         break;
+    case CHARDEV_BACKEND_KIND_DGRAM:
+        chr = qmp_chardev_open_dgram(backend->dgram, errp);
+        break;
 #ifdef HAVE_CHARDEV_TTY
     case CHARDEV_BACKEND_KIND_PTY:
         chr = qemu_chr_open_pty(id, ret);
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 3f12296..83e4e08 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -949,6 +949,31 @@ int socket_listen(SocketAddress *addr, Error **errp)
     return fd;
 }
 
+int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp)
+{
+    QemuOpts *opts;
+    int fd;
+
+    opts = qemu_opts_create_nofail(&dummy_opts);
+    switch (remote->kind) {
+    case SOCKET_ADDRESS_KIND_INET:
+        qemu_opt_set(opts, "host", remote->inet->host);
+        qemu_opt_set(opts, "port", remote->inet->port);
+        if (local) {
+            qemu_opt_set(opts, "localaddr", local->inet->host);
+            qemu_opt_set(opts, "localport", local->inet->port);
+        }
+        fd = inet_dgram_opts(opts, errp);
+        break;
+
+    default:
+        error_setg(errp, "socket type unsupported for datagram");
+        return -1;
+    }
+    qemu_opts_del(opts);
+    return fd;
+}
+
 #ifdef _WIN32
 static void socket_cleanup(void)
 {
commit 1da48c658a26d0c1444d05d8d3a545d311e01026
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Feb 26 16:21:11 2013 +0100

    chardev: add memory (ringbuf) support to qapi
    
    This patch adds 'memory' support to qapi and also switches over
    the memory chardev initialization to the new qapi code path.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/qapi-schema.json b/qapi-schema.json
index 4ee5650..8d371f1 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3248,6 +3248,17 @@
                                  '*rows'   : 'int' } }
 
 ##
+# @ChardevRingbuf:
+#
+# Configuration info for memory chardevs
+#
+# @size: #optional Ringbuffer size, must be power of two, default is 65536
+#
+# Since: 1.5
+##
+{ 'type': 'ChardevRingbuf', 'data': { '*size'  : 'int' } }
+
+##
 # @ChardevBackend:
 #
 # Configuration info for the new chardev backend.
@@ -3270,7 +3281,8 @@
                                        'console': 'ChardevDummy',
                                        'spicevmc' : 'ChardevSpiceChannel',
                                        'spiceport' : 'ChardevSpicePort',
-                                       'vc'     : 'ChardevVC' } }
+                                       'vc'     : 'ChardevVC',
+                                       'memory' : 'ChardevRingbuf' } }
 
 ##
 # @ChardevReturn:
diff --git a/qemu-char.c b/qemu-char.c
index 2d62ee9..eb2045a 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2884,7 +2884,8 @@ static void ringbuf_chr_close(struct CharDriverState *chr)
     chr->opaque = NULL;
 }
 
-static CharDriverState *qemu_chr_open_ringbuf(QemuOpts *opts)
+static CharDriverState *qemu_chr_open_ringbuf(ChardevRingbuf *opts,
+                                              Error **errp)
 {
     CharDriverState *chr;
     RingBufCharDriver *d;
@@ -2892,14 +2893,11 @@ static CharDriverState *qemu_chr_open_ringbuf(QemuOpts *opts)
     chr = g_malloc0(sizeof(CharDriverState));
     d = g_malloc(sizeof(*d));
 
-    d->size = qemu_opt_get_size(opts, "size", 0);
-    if (d->size == 0) {
-        d->size = 65536;
-    }
+    d->size = opts->has_size ? opts->size : 65536;
 
     /* The size must be power of 2 */
     if (d->size & (d->size - 1)) {
-        error_report("size of ringbuf device must be power of two");
+        error_setg(errp, "size of ringbuf chardev must be power of two");
         goto fail;
     }
 
@@ -3201,6 +3199,20 @@ static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend,
     backend->pipe->device = g_strdup(device);
 }
 
+static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend,
+                                   Error **errp)
+{
+    int val;
+
+    backend->memory = g_new0(ChardevRingbuf, 1);
+
+    val = qemu_opt_get_number(opts, "size", 0);
+    if (val != 0) {
+        backend->memory->has_size = true;
+        backend->memory->size = val;
+    }
+}
+
 typedef struct CharDriver {
     const char *name;
     /* old, pre qapi */
@@ -3740,6 +3752,9 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
     case CHARDEV_BACKEND_KIND_VC:
         chr = vc_init(backend->vc);
         break;
+    case CHARDEV_BACKEND_KIND_MEMORY:
+        chr = qemu_chr_open_ringbuf(backend->memory, errp);
+        break;
     default:
         error_setg(errp, "unknown chardev backend (%d)", backend->kind);
         break;
@@ -3782,7 +3797,8 @@ static void register_types(void)
     register_char_driver_qapi("null", CHARDEV_BACKEND_KIND_NULL, NULL);
     register_char_driver("socket", qemu_chr_open_socket);
     register_char_driver("udp", qemu_chr_open_udp);
-    register_char_driver("memory", qemu_chr_open_ringbuf);
+    register_char_driver_qapi("memory", CHARDEV_BACKEND_KIND_MEMORY,
+                              qemu_chr_parse_ringbuf);
     register_char_driver_qapi("file", CHARDEV_BACKEND_KIND_FILE,
                               qemu_chr_parse_file_out);
     register_char_driver_qapi("stdio", CHARDEV_BACKEND_KIND_STDIO,
commit 702ec69cc1aa87a1e53d1b066a38a9eb0fa7845b
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Feb 25 15:52:32 2013 +0100

    chardev: add vc support to qapi
    
    This patch adds 'vc' support to qapi and also switches over the
    vc chardev initialization to the new qapi code path.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/include/ui/console.h b/include/ui/console.h
index c42bca6..a37cf65 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -450,9 +450,9 @@ void qemu_console_resize(DisplayState *ds, int width, int height);
 void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
                        int dst_x, int dst_y, int w, int h);
 
-typedef CharDriverState *(VcHandler)(QemuOpts *);
+typedef CharDriverState *(VcHandler)(ChardevVC *vc);
 
-CharDriverState *vc_init(QemuOpts *opts);
+CharDriverState *vc_init(ChardevVC *vc);
 void register_vc_handler(VcHandler *handler);
 
 /* sdl.c */
diff --git a/qapi-schema.json b/qapi-schema.json
index dad4d4a..4ee5650 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3231,6 +3231,23 @@
 { 'type': 'ChardevSpicePort', 'data': { 'fqdn'  : 'str' } }
 
 ##
+# @ChardevVC:
+#
+# Configuration info for virtual console chardevs.
+#
+# @width:  console width,  in pixels
+# @height: console height, in pixels
+# @cols:   console width,  in chars
+# @rows:   console height, in chars
+#
+# Since: 1.5
+##
+{ 'type': 'ChardevVC', 'data': { '*width'  : 'int',
+                                 '*height' : 'int',
+                                 '*cols'   : 'int',
+                                 '*rows'   : 'int' } }
+
+##
 # @ChardevBackend:
 #
 # Configuration info for the new chardev backend.
@@ -3252,7 +3269,8 @@
                                        'stdio'  : 'ChardevStdio',
                                        'console': 'ChardevDummy',
                                        'spicevmc' : 'ChardevSpiceChannel',
-                                       'spiceport' : 'ChardevSpicePort' } }
+                                       'spiceport' : 'ChardevSpicePort',
+                                       'vc'     : 'ChardevVC' } }
 
 ##
 # @ChardevReturn:
diff --git a/qemu-char.c b/qemu-char.c
index f133747..2d62ee9 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3737,6 +3737,9 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
         chr = qemu_chr_open_spice_port(backend->spiceport->fqdn);
         break;
 #endif
+    case CHARDEV_BACKEND_KIND_VC:
+        chr = vc_init(backend->vc);
+        break;
     default:
         error_setg(errp, "unknown chardev backend (%d)", backend->kind);
         break;
diff --git a/ui/console.c b/ui/console.c
index 83a6fa3..27e87f8 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1537,22 +1537,26 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
         chr->init(chr);
 }
 
-static CharDriverState *text_console_init(QemuOpts *opts)
+static CharDriverState *text_console_init(ChardevVC *vc)
 {
     CharDriverState *chr;
     QemuConsole *s;
-    unsigned width;
-    unsigned height;
+    unsigned width = 0;
+    unsigned height = 0;
 
     chr = g_malloc0(sizeof(CharDriverState));
 
-    width = qemu_opt_get_number(opts, "width", 0);
-    if (width == 0)
-        width = qemu_opt_get_number(opts, "cols", 0) * FONT_WIDTH;
+    if (vc->has_width) {
+        width = vc->width;
+    } else if (vc->has_cols) {
+        width = vc->cols * FONT_WIDTH;
+    }
 
-    height = qemu_opt_get_number(opts, "height", 0);
-    if (height == 0)
-        height = qemu_opt_get_number(opts, "rows", 0) * FONT_HEIGHT;
+    if (vc->has_height) {
+        height = vc->height;
+    } else if (vc->has_rows) {
+        height = vc->rows * FONT_HEIGHT;
+    }
 
     if (width == 0 || height == 0) {
         s = new_console(NULL, TEXT_CONSOLE);
@@ -1575,9 +1579,9 @@ static CharDriverState *text_console_init(QemuOpts *opts)
 
 static VcHandler *vc_handler = text_console_init;
 
-CharDriverState *vc_init(QemuOpts *opts)
+CharDriverState *vc_init(ChardevVC *vc)
 {
-    return vc_handler(opts);
+    return vc_handler(vc);
 }
 
 void register_vc_handler(VcHandler *handler)
@@ -1740,9 +1744,42 @@ PixelFormat qemu_default_pixelformat(int bpp)
     return pf;
 }
 
+static void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend,
+                              Error **errp)
+{
+    int val;
+
+    backend->vc = g_new0(ChardevVC, 1);
+
+    val = qemu_opt_get_number(opts, "width", 0);
+    if (val != 0) {
+        backend->vc->has_width = true;
+        backend->vc->width = val;
+    }
+
+    val = qemu_opt_get_number(opts, "height", 0);
+    if (val != 0) {
+        backend->vc->has_height = true;
+        backend->vc->height = val;
+    }
+
+    val = qemu_opt_get_number(opts, "cols", 0);
+    if (val != 0) {
+        backend->vc->has_cols = true;
+        backend->vc->cols = val;
+    }
+
+    val = qemu_opt_get_number(opts, "rows", 0);
+    if (val != 0) {
+        backend->vc->has_rows = true;
+        backend->vc->rows = val;
+    }
+}
+
 static void register_types(void)
 {
-    register_char_driver("vc", text_console_init);
+    register_char_driver_qapi("vc", CHARDEV_BACKEND_KIND_VC,
+                              qemu_chr_parse_vc);
 }
 
 type_init(register_types);
diff --git a/ui/gtk.c b/ui/gtk.c
index 544593e..794dab1 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -991,7 +991,7 @@ static int gd_vc_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 static int nb_vcs;
 static CharDriverState *vcs[MAX_VCS];
 
-static CharDriverState *gd_vc_handler(QemuOpts *opts)
+static CharDriverState *gd_vc_handler(ChardevVC *unused)
 {
     CharDriverState *chr;
 
commit cd153e2aa2f0ec39c04c2b732ebebfc6d4766986
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Feb 25 12:39:06 2013 +0100

    chardev: add spice support to qapi
    
    This patch adds 'spicevmc' and 'spiceport' support to qapi and also
    switches over the spice chardev initialization to the new qapi code
    path.

diff --git a/include/ui/qemu-spice.h b/include/ui/qemu-spice.h
index 5a78fd7..eba6d77 100644
--- a/include/ui/qemu-spice.h
+++ b/include/ui/qemu-spice.h
@@ -44,10 +44,13 @@ int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
 void do_info_spice_print(Monitor *mon, const QObject *data);
 void do_info_spice(Monitor *mon, QObject **ret_data);
 
-CharDriverState *qemu_chr_open_spice(QemuOpts *opts);
+CharDriverState *qemu_chr_open_spice_vmc(const char *type);
 #if SPICE_SERVER_VERSION >= 0x000c02
-CharDriverState *qemu_chr_open_spice_port(QemuOpts *opts);
+CharDriverState *qemu_chr_open_spice_port(const char *name);
 void qemu_spice_register_ports(void);
+#else
+static inline CharDriverState *qemu_chr_open_spice_port(const char *name)
+{ return NULL; }
 #endif
 
 #else  /* CONFIG_SPICE */
diff --git a/qapi-schema.json b/qapi-schema.json
index 7ea32ed..dad4d4a 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3209,6 +3209,28 @@
 { 'type': 'ChardevStdio', 'data': { '*signal' : 'bool' } }
 
 ##
+# @ChardevSpiceChannel:
+#
+# Configuration info for spice vm channel chardevs.
+#
+# @type: kind of channel (for example vdagent).
+#
+# Since: 1.5
+##
+{ 'type': 'ChardevSpiceChannel', 'data': { 'type'  : 'str' } }
+
+##
+# @ChardevSpicePort:
+#
+# Configuration info for spice port chardevs.
+#
+# @fqdn: name of the channel (see docs/spice-port-fqdn.txt)
+#
+# Since: 1.5
+##
+{ 'type': 'ChardevSpicePort', 'data': { 'fqdn'  : 'str' } }
+
+##
 # @ChardevBackend:
 #
 # Configuration info for the new chardev backend.
@@ -3228,7 +3250,9 @@
                                        'msmouse': 'ChardevDummy',
                                        'braille': 'ChardevDummy',
                                        'stdio'  : 'ChardevStdio',
-                                       'console': 'ChardevDummy' } }
+                                       'console': 'ChardevDummy',
+                                       'spicevmc' : 'ChardevSpiceChannel',
+                                       'spiceport' : 'ChardevSpicePort' } }
 
 ##
 # @ChardevReturn:
diff --git a/qemu-char.c b/qemu-char.c
index 427901c..f133747 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3729,6 +3729,14 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
         chr = qemu_chr_open_win_con();
         break;
 #endif
+#ifdef CONFIG_SPICE
+    case CHARDEV_BACKEND_KIND_SPICEVMC:
+        chr = qemu_chr_open_spice_vmc(backend->spicevmc->type);
+        break;
+    case CHARDEV_BACKEND_KIND_SPICEPORT:
+        chr = qemu_chr_open_spice_port(backend->spiceport->fqdn);
+        break;
+#endif
     default:
         error_setg(errp, "unknown chardev backend (%d)", backend->kind);
         break;
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index aea3d24..0c92ca8 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -217,16 +217,14 @@ static void print_allowed_subtypes(void)
     fprintf(stderr, "\n");
 }
 
-static CharDriverState *chr_open(QemuOpts *opts, const char *subtype)
+static CharDriverState *chr_open(const char *subtype)
 {
     CharDriverState *chr;
     SpiceCharDriver *s;
-    uint32_t debug = qemu_opt_get_number(opts, "debug", 0);
 
     chr = g_malloc0(sizeof(CharDriverState));
     s = g_malloc0(sizeof(SpiceCharDriver));
     s->chr = chr;
-    s->debug = debug;
     s->active = false;
     s->sin.subtype = subtype;
     chr->opaque = s;
@@ -240,35 +238,32 @@ static CharDriverState *chr_open(QemuOpts *opts, const char *subtype)
     return chr;
 }
 
-CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
+CharDriverState *qemu_chr_open_spice_vmc(const char *type)
 {
     CharDriverState *chr;
-    const char *name = qemu_opt_get(opts, "name");
     const char **psubtype = spice_server_char_device_recognized_subtypes();
-    const char *subtype = NULL;
 
-    if (name == NULL) {
+    if (type == NULL) {
         fprintf(stderr, "spice-qemu-char: missing name parameter\n");
         print_allowed_subtypes();
         return NULL;
     }
-    for(;*psubtype != NULL; ++psubtype) {
-        if (strcmp(name, *psubtype) == 0) {
-            subtype = *psubtype;
+    for (; *psubtype != NULL; ++psubtype) {
+        if (strcmp(type, *psubtype) == 0) {
             break;
         }
     }
-    if (subtype == NULL) {
-        fprintf(stderr, "spice-qemu-char: unsupported name: %s\n", name);
+    if (*psubtype == NULL) {
+        fprintf(stderr, "spice-qemu-char: unsupported type: %s\n", type);
         print_allowed_subtypes();
         return NULL;
     }
 
-    chr = chr_open(opts, subtype);
+    chr = chr_open(type);
 
 #if SPICE_SERVER_VERSION < 0x000901
     /* See comment in vmc_state() */
-    if (strcmp(subtype, "vdagent") == 0) {
+    if (strcmp(type, "vdagent") == 0) {
         qemu_chr_generic_open(chr);
     }
 #endif
@@ -277,18 +272,17 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
 }
 
 #if SPICE_SERVER_VERSION >= 0x000c02
-CharDriverState *qemu_chr_open_spice_port(QemuOpts *opts)
+CharDriverState *qemu_chr_open_spice_port(const char *name)
 {
     CharDriverState *chr;
     SpiceCharDriver *s;
-    const char *name = qemu_opt_get(opts, "name");
 
     if (name == NULL) {
         fprintf(stderr, "spice-qemu-char: missing name parameter\n");
         return NULL;
     }
 
-    chr = chr_open(opts, "port");
+    chr = chr_open("port");
     s = chr->opaque;
     s->sin.portname = name;
 
@@ -308,12 +302,38 @@ void qemu_spice_register_ports(void)
 }
 #endif
 
+static void qemu_chr_parse_spice_vmc(QemuOpts *opts, ChardevBackend *backend,
+                                     Error **errp)
+{
+    const char *name = qemu_opt_get(opts, "name");
+
+    if (name == NULL) {
+        error_setg(errp, "chardev: spice channel: no name given");
+        return;
+    }
+    backend->spicevmc = g_new0(ChardevSpiceChannel, 1);
+    backend->spicevmc->type = g_strdup(name);
+}
+
+static void qemu_chr_parse_spice_port(QemuOpts *opts, ChardevBackend *backend,
+                                      Error **errp)
+{
+    const char *name = qemu_opt_get(opts, "name");
+
+    if (name == NULL) {
+        error_setg(errp, "chardev: spice port: no name given");
+        return;
+    }
+    backend->spiceport = g_new0(ChardevSpicePort, 1);
+    backend->spiceport->fqdn = g_strdup(name);
+}
+
 static void register_types(void)
 {
-    register_char_driver("spicevmc", qemu_chr_open_spice);
-#if SPICE_SERVER_VERSION >= 0x000c02
-    register_char_driver("spiceport", qemu_chr_open_spice_port);
-#endif
+    register_char_driver_qapi("spicevmc", CHARDEV_BACKEND_KIND_SPICEVMC,
+                              qemu_chr_parse_spice_vmc);
+    register_char_driver_qapi("spiceport", CHARDEV_BACKEND_KIND_SPICEPORT,
+                              qemu_chr_parse_spice_port);
 }
 
 type_init(register_types);
commit 548cbb36f415d6086f5252309ab5aa7634497ab5
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Feb 25 11:50:55 2013 +0100

    chardev: add pipe support to qapi
    
    This patch adds 'pipe' support to qapi and also switches over the
    pipe chardev initialization to the new qapi code path.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/qapi-schema.json b/qapi-schema.json
index 70c2c07..7ea32ed 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3153,7 +3153,7 @@
 ##
 # @ChardevHostdev:
 #
-# Configuration info for device chardevs.
+# Configuration info for device and pipe chardevs.
 #
 # @device: The name of the special file for the device,
 #          i.e. /dev/ttyS0 on Unix or COM1: on Windows
@@ -3220,6 +3220,7 @@
 { 'union': 'ChardevBackend', 'data': { 'file'   : 'ChardevFile',
                                        'serial' : 'ChardevHostdev',
                                        'parallel': 'ChardevHostdev',
+                                       'pipe'   : 'ChardevHostdev',
                                        'socket' : 'ChardevSocket',
                                        'pty'    : 'ChardevDummy',
                                        'null'   : 'ChardevDummy',
diff --git a/qemu-char.c b/qemu-char.c
index c3d4420..427901c 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -841,11 +841,11 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
     return chr;
 }
 
-static CharDriverState *qemu_chr_open_pipe(QemuOpts *opts)
+static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts)
 {
     int fd_in, fd_out;
     char filename_in[256], filename_out[256];
-    const char *filename = qemu_opt_get(opts, "path");
+    const char *filename = opts->device;
 
     if (filename == NULL) {
         fprintf(stderr, "chardev: pipe: no filename given\n");
@@ -1917,9 +1917,9 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
 }
 
 
-static CharDriverState *qemu_chr_open_win_pipe(QemuOpts *opts)
+static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts)
 {
-    const char *filename = qemu_opt_get(opts, "path");
+    const char *filename = opts->device;
     CharDriverState *chr;
     WinCharState *s;
 
@@ -3188,6 +3188,19 @@ static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend,
     backend->parallel->device = g_strdup(device);
 }
 
+static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend,
+                                Error **errp)
+{
+    const char *device = qemu_opt_get(opts, "path");
+
+    if (device == NULL) {
+        error_setg(errp, "chardev: pipe: no device path given");
+        return;
+    }
+    backend->pipe = g_new0(ChardevHostdev, 1);
+    backend->pipe->device = g_strdup(device);
+}
+
 typedef struct CharDriver {
     const char *name;
     /* old, pre qapi */
@@ -3677,6 +3690,9 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
     case CHARDEV_BACKEND_KIND_PARALLEL:
         chr = qmp_chardev_open_parallel(backend->parallel, errp);
         break;
+    case CHARDEV_BACKEND_KIND_PIPE:
+        chr = qemu_chr_open_pipe(backend->pipe);
+        break;
     case CHARDEV_BACKEND_KIND_SOCKET:
         chr = qmp_chardev_open_socket(backend->socket, errp);
         break;
@@ -3770,11 +3786,8 @@ static void register_types(void)
                               qemu_chr_parse_parallel);
     register_char_driver_qapi("pty", CHARDEV_BACKEND_KIND_PTY, NULL);
     register_char_driver_qapi("console", CHARDEV_BACKEND_KIND_CONSOLE, NULL);
-#ifdef _WIN32
-    register_char_driver("pipe", qemu_chr_open_win_pipe);
-#else
-    register_char_driver("pipe", qemu_chr_open_pipe);
-#endif
+    register_char_driver_qapi("pipe", CHARDEV_BACKEND_KIND_PIPE,
+                              qemu_chr_parse_pipe);
 }
 
 type_init(register_types);
commit d9ac374f0def9a65340c1768c08e3271f4d7798d
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Feb 25 11:48:06 2013 +0100

    chardev: add console support to qapi
    
    This patch adds 'console' support to qapi and also switches over the
    console chardev initialization to the new qapi code path.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/qapi-schema.json b/qapi-schema.json
index 68150b7..70c2c07 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3226,7 +3226,8 @@
                                        'mux'    : 'ChardevMux',
                                        'msmouse': 'ChardevDummy',
                                        'braille': 'ChardevDummy',
-                                       'stdio'  : 'ChardevStdio' } }
+                                       'stdio'  : 'ChardevStdio',
+                                       'console': 'ChardevDummy' } }
 
 ##
 # @ChardevReturn:
diff --git a/qemu-char.c b/qemu-char.c
index 158b81e..c3d4420 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1952,7 +1952,7 @@ static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
     return chr;
 }
 
-static CharDriverState *qemu_chr_open_win_con(QemuOpts *opts)
+static CharDriverState *qemu_chr_open_win_con(void)
 {
     return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE));
 }
@@ -3708,6 +3708,11 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
     case CHARDEV_BACKEND_KIND_STDIO:
         chr = qemu_chr_open_stdio(backend->stdio);
         break;
+#ifdef _WIN32
+    case CHARDEV_BACKEND_KIND_CONSOLE:
+        chr = qemu_chr_open_win_con();
+        break;
+#endif
     default:
         error_setg(errp, "unknown chardev backend (%d)", backend->kind);
         break;
@@ -3764,9 +3769,9 @@ static void register_types(void)
     register_char_driver_qapi("parport", CHARDEV_BACKEND_KIND_PARALLEL,
                               qemu_chr_parse_parallel);
     register_char_driver_qapi("pty", CHARDEV_BACKEND_KIND_PTY, NULL);
+    register_char_driver_qapi("console", CHARDEV_BACKEND_KIND_CONSOLE, NULL);
 #ifdef _WIN32
     register_char_driver("pipe", qemu_chr_open_win_pipe);
-    register_char_driver("console", qemu_chr_open_win_con);
 #else
     register_char_driver("pipe", qemu_chr_open_pipe);
 #endif
commit e68c5958668596a5023e30ddf8368410878f7682
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Feb 25 10:16:46 2013 +0100

    chardev: switch pty init to qapi
    
    This patch switches over the pty chardev initialization
    to the new qapi code path.
    
    Bonus: Taking QemuOpts out of the loop allows some nice
    cleanups along the way.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/qemu-char.c b/qemu-char.c
index d8ac86b..158b81e 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1157,13 +1157,13 @@ static void pty_chr_close(struct CharDriverState *chr)
     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
-static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
+static CharDriverState *qemu_chr_open_pty(const char *id,
+                                          ChardevReturn *ret)
 {
     CharDriverState *chr;
     PtyCharDriver *s;
     struct termios tty;
-    const char *label;
-    int master_fd, slave_fd, len;
+    int master_fd, slave_fd;
 #if defined(__OpenBSD__) || defined(__DragonFly__)
     char pty_name[PATH_MAX];
 #define q_ptsname(x) pty_name
@@ -1184,17 +1184,12 @@ static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
 
     chr = g_malloc0(sizeof(CharDriverState));
 
-    len = strlen(q_ptsname(master_fd)) + 5;
-    chr->filename = g_malloc(len);
-    snprintf(chr->filename, len, "pty:%s", q_ptsname(master_fd));
-    qemu_opt_set(opts, "path", q_ptsname(master_fd));
+    chr->filename = g_strdup_printf("pty:%s", q_ptsname(master_fd));
+    ret->pty = g_strdup(q_ptsname(master_fd));
+    ret->has_pty = true;
 
-    label = qemu_opts_id(opts);
-    fprintf(stderr, "char device redirected to %s%s%s%s\n",
-            q_ptsname(master_fd),
-            label ? " (label " : "",
-            label ? label      : "",
-            label ? ")"        : "");
+    fprintf(stderr, "char device redirected to %s (label %s)\n",
+            q_ptsname(master_fd), id);
 
     s = g_malloc0(sizeof(PtyCharDriver));
     chr->opaque = s;
@@ -3687,16 +3682,8 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
         break;
 #ifdef HAVE_CHARDEV_TTY
     case CHARDEV_BACKEND_KIND_PTY:
-    {
-        /* qemu_chr_open_pty sets "path" in opts */
-        QemuOpts *opts;
-        opts = qemu_opts_create_nofail(qemu_find_opts("chardev"));
-        chr = qemu_chr_open_pty(opts);
-        ret->pty = g_strdup(qemu_opt_get(opts, "path"));
-        ret->has_pty = true;
-        qemu_opts_del(opts);
+        chr = qemu_chr_open_pty(id, ret);
         break;
-    }
 #endif
     case CHARDEV_BACKEND_KIND_NULL:
         chr = qemu_chr_open_null();
@@ -3776,15 +3763,13 @@ static void register_types(void)
                               qemu_chr_parse_parallel);
     register_char_driver_qapi("parport", CHARDEV_BACKEND_KIND_PARALLEL,
                               qemu_chr_parse_parallel);
+    register_char_driver_qapi("pty", CHARDEV_BACKEND_KIND_PTY, NULL);
 #ifdef _WIN32
     register_char_driver("pipe", qemu_chr_open_win_pipe);
     register_char_driver("console", qemu_chr_open_win_con);
 #else
     register_char_driver("pipe", qemu_chr_open_pipe);
 #endif
-#ifdef HAVE_CHARDEV_TTY
-    register_char_driver("pty", qemu_chr_open_pty);
-#endif
 }
 
 type_init(register_types);
commit dc3750976914b0900446e6a5434919a0fa2ba028
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Feb 22 16:17:01 2013 +0100

    chardev: switch parallel init to qapi
    
    This patch switches over the parallel chardev initialization
    to the new qapi code path.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/qemu-char.c b/qemu-char.c
index 3033c2d..d8ac86b 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3145,22 +3145,6 @@ fail:
     return NULL;
 }
 
-#ifdef HAVE_CHARDEV_PARPORT
-
-static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
-{
-    const char *filename = qemu_opt_get(opts, "path");
-    int fd;
-
-    fd = qemu_open(filename, O_RDWR);
-    if (fd < 0) {
-        return NULL;
-    }
-    return qemu_chr_open_pp_fd(fd);
-}
-
-#endif
-
 static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend,
                                     Error **errp)
 {
@@ -3196,6 +3180,19 @@ static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
     backend->serial->device = g_strdup(device);
 }
 
+static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend,
+                                    Error **errp)
+{
+    const char *device = qemu_opt_get(opts, "path");
+
+    if (device == NULL) {
+        error_setg(errp, "chardev: parallel: no device path given");
+        return;
+    }
+    backend->parallel = g_new0(ChardevHostdev, 1);
+    backend->parallel->device = g_strdup(device);
+}
+
 typedef struct CharDriver {
     const char *name;
     /* old, pre qapi */
@@ -3775,6 +3772,10 @@ static void register_types(void)
                               qemu_chr_parse_serial);
     register_char_driver_qapi("tty", CHARDEV_BACKEND_KIND_SERIAL,
                               qemu_chr_parse_serial);
+    register_char_driver_qapi("parallel", CHARDEV_BACKEND_KIND_PARALLEL,
+                              qemu_chr_parse_parallel);
+    register_char_driver_qapi("parport", CHARDEV_BACKEND_KIND_PARALLEL,
+                              qemu_chr_parse_parallel);
 #ifdef _WIN32
     register_char_driver("pipe", qemu_chr_open_win_pipe);
     register_char_driver("console", qemu_chr_open_win_con);
@@ -3784,10 +3785,6 @@ static void register_types(void)
 #ifdef HAVE_CHARDEV_TTY
     register_char_driver("pty", qemu_chr_open_pty);
 #endif
-#ifdef HAVE_CHARDEV_PARPORT
-    register_char_driver("parallel", qemu_chr_open_pp);
-    register_char_driver("parport", qemu_chr_open_pp);
-#endif
 }
 
 type_init(register_types);
commit 0f1cb51da7112fa62c6cde62f546714a2c672f54
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Feb 22 15:48:05 2013 +0100

    chardev: switch serial/tty init to qapi
    
    This patch switches over the serial chardev initialization
    to the new qapi code path.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/qemu-char.c b/qemu-char.c
index 85ffd8e..3033c2d 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1419,18 +1419,6 @@ static CharDriverState *qemu_chr_open_tty_fd(int fd)
     chr->chr_close = qemu_chr_close_tty;
     return chr;
 }
-
-static CharDriverState *qemu_chr_open_tty(QemuOpts *opts)
-{
-    const char *filename = qemu_opt_get(opts, "path");
-    int fd;
-
-    TFR(fd = qemu_open(filename, O_RDWR | O_NONBLOCK));
-    if (fd < 0) {
-        return NULL;
-    }
-    return qemu_chr_open_tty_fd(fd);
-}
 #endif /* __linux__ || __sun__ */
 
 #if defined(__linux__)
@@ -1855,11 +1843,6 @@ static CharDriverState *qemu_chr_open_win_path(const char *filename)
     return chr;
 }
 
-static CharDriverState *qemu_chr_open_win(QemuOpts *opts)
-{
-    return qemu_chr_open_win_path(qemu_opt_get(opts, "path"));
-}
-
 static int win_chr_pipe_poll(void *opaque)
 {
     CharDriverState *chr = opaque;
@@ -3200,6 +3183,19 @@ static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,
         qemu_opt_get_bool(opts, "signal", display_type != DT_NOGRAPHIC);
 }
 
+static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
+                                  Error **errp)
+{
+    const char *device = qemu_opt_get(opts, "path");
+
+    if (device == NULL) {
+        error_setg(errp, "chardev: serial/tty: no device path given");
+        return;
+    }
+    backend->serial = g_new0(ChardevHostdev, 1);
+    backend->serial->device = g_strdup(device);
+}
+
 typedef struct CharDriver {
     const char *name;
     /* old, pre qapi */
@@ -3775,16 +3771,17 @@ static void register_types(void)
                               qemu_chr_parse_file_out);
     register_char_driver_qapi("stdio", CHARDEV_BACKEND_KIND_STDIO,
                               qemu_chr_parse_stdio);
+    register_char_driver_qapi("serial", CHARDEV_BACKEND_KIND_SERIAL,
+                              qemu_chr_parse_serial);
+    register_char_driver_qapi("tty", CHARDEV_BACKEND_KIND_SERIAL,
+                              qemu_chr_parse_serial);
 #ifdef _WIN32
     register_char_driver("pipe", qemu_chr_open_win_pipe);
     register_char_driver("console", qemu_chr_open_win_con);
-    register_char_driver("serial", qemu_chr_open_win);
 #else
     register_char_driver("pipe", qemu_chr_open_pipe);
 #endif
 #ifdef HAVE_CHARDEV_TTY
-    register_char_driver("tty", qemu_chr_open_tty);
-    register_char_driver("serial", qemu_chr_open_tty);
     register_char_driver("pty", qemu_chr_open_pty);
 #endif
 #ifdef HAVE_CHARDEV_PARPORT
commit 7c358031eac9a41c215900020acf8600d33138aa
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 21 12:34:58 2013 +0100

    chardev: add stdio support to qapi
    
    This patch adds 'stdio' support to qapi and also switches over the
    stdio chardev initialization to the new qapi code path.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/qapi-schema.json b/qapi-schema.json
index 3c5c0fb..68150b7 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3196,6 +3196,19 @@
 { 'type': 'ChardevMux', 'data': { 'chardev' : 'str' } }
 
 ##
+# @ChardevStdio:
+#
+# Configuration info for stdio chardevs.
+#
+# @signal: #optional Allow signals (such as SIGINT triggered by ^C)
+#          be delivered to qemu.  Default: true in -nographic mode,
+#          false otherwise.
+#
+# Since: 1.5
+##
+{ 'type': 'ChardevStdio', 'data': { '*signal' : 'bool' } }
+
+##
 # @ChardevBackend:
 #
 # Configuration info for the new chardev backend.
@@ -3212,7 +3225,8 @@
                                        'null'   : 'ChardevDummy',
                                        'mux'    : 'ChardevMux',
                                        'msmouse': 'ChardevDummy',
-                                       'braille': 'ChardevDummy' } }
+                                       'braille': 'ChardevDummy',
+                                       'stdio'  : 'ChardevStdio' } }
 
 ##
 # @ChardevReturn:
diff --git a/qemu-char.c b/qemu-char.c
index 4b9caca..85ffd8e 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -908,7 +908,7 @@ static void qemu_chr_close_stdio(struct CharDriverState *chr)
     fd_chr_close(chr);
 }
 
-static CharDriverState *qemu_chr_open_stdio(QemuOpts *opts)
+static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
 {
     CharDriverState *chr;
 
@@ -924,8 +924,10 @@ static CharDriverState *qemu_chr_open_stdio(QemuOpts *opts)
     chr = qemu_chr_open_fd(0, 1);
     chr->chr_close = qemu_chr_close_stdio;
     chr->chr_set_echo = qemu_chr_set_echo_stdio;
-    stdio_allow_signal = qemu_opt_get_bool(opts, "signal",
-                                           display_type != DT_NOGRAPHIC);
+    stdio_allow_signal = display_type != DT_NOGRAPHIC;
+    if (opts->has_signal) {
+        stdio_allow_signal = opts->signal;
+    }
     qemu_chr_fe_set_echo(chr, false);
 
     return chr;
@@ -2114,7 +2116,7 @@ static void win_stdio_close(CharDriverState *chr)
     g_free(chr);
 }
 
-static CharDriverState *qemu_chr_open_win_stdio(QemuOpts *opts)
+static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
 {
     CharDriverState   *chr;
     WinStdioCharState *stdio;
@@ -3189,6 +3191,15 @@ static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend,
     backend->file->out = g_strdup(path);
 }
 
+static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,
+                                 Error **errp)
+{
+    backend->stdio = g_new0(ChardevStdio, 1);
+    backend->stdio->has_signal = true;
+    backend->stdio->signal =
+        qemu_opt_get_bool(opts, "signal", display_type != DT_NOGRAPHIC);
+}
+
 typedef struct CharDriver {
     const char *name;
     /* old, pre qapi */
@@ -3714,6 +3725,9 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
         chr = chr_baum_init();
         break;
 #endif
+    case CHARDEV_BACKEND_KIND_STDIO:
+        chr = qemu_chr_open_stdio(backend->stdio);
+        break;
     default:
         error_setg(errp, "unknown chardev backend (%d)", backend->kind);
         break;
@@ -3759,14 +3773,14 @@ static void register_types(void)
     register_char_driver("memory", qemu_chr_open_ringbuf);
     register_char_driver_qapi("file", CHARDEV_BACKEND_KIND_FILE,
                               qemu_chr_parse_file_out);
+    register_char_driver_qapi("stdio", CHARDEV_BACKEND_KIND_STDIO,
+                              qemu_chr_parse_stdio);
 #ifdef _WIN32
     register_char_driver("pipe", qemu_chr_open_win_pipe);
     register_char_driver("console", qemu_chr_open_win_con);
     register_char_driver("serial", qemu_chr_open_win);
-    register_char_driver("stdio", qemu_chr_open_win_stdio);
 #else
     register_char_driver("pipe", qemu_chr_open_pipe);
-    register_char_driver("stdio", qemu_chr_open_stdio);
 #endif
 #ifdef HAVE_CHARDEV_TTY
     register_char_driver("tty", qemu_chr_open_tty);
commit 846e2e49388aa42e030af3d5dd60a6009b80a369
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 21 12:07:14 2013 +0100

    chardev: switch file init to qapi
    
    This patch switches over the 'file' chardev initialization
    to the new qapi code path.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/qemu-char.c b/qemu-char.c
index 1692aa8..4b9caca 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -841,18 +841,6 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
     return chr;
 }
 
-static CharDriverState *qemu_chr_open_file_out(QemuOpts *opts)
-{
-    int fd_out;
-
-    TFR(fd_out = qemu_open(qemu_opt_get(opts, "path"),
-                      O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666));
-    if (fd_out < 0) {
-        return NULL;
-    }
-    return qemu_chr_open_fd(-1, fd_out);
-}
-
 static CharDriverState *qemu_chr_open_pipe(QemuOpts *opts)
 {
     int fd_in, fd_out;
@@ -1989,20 +1977,6 @@ static CharDriverState *qemu_chr_open_win_con(QemuOpts *opts)
     return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE));
 }
 
-static CharDriverState *qemu_chr_open_win_file_out(QemuOpts *opts)
-{
-    const char *file_out = qemu_opt_get(opts, "path");
-    HANDLE fd_out;
-
-    fd_out = CreateFile(file_out, GENERIC_WRITE, FILE_SHARE_READ, NULL,
-                        OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
-    if (fd_out == INVALID_HANDLE_VALUE) {
-        return NULL;
-    }
-
-    return qemu_chr_open_win_file(fd_out);
-}
-
 static int win_stdio_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     HANDLE  hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
@@ -3202,6 +3176,19 @@ static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
 
 #endif
 
+static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend,
+                                    Error **errp)
+{
+    const char *path = qemu_opt_get(opts, "path");
+
+    if (path == NULL) {
+        error_setg(errp, "chardev: file: no filename given");
+        return;
+    }
+    backend->file = g_new0(ChardevFile, 1);
+    backend->file->out = g_strdup(path);
+}
+
 typedef struct CharDriver {
     const char *name;
     /* old, pre qapi */
@@ -3770,14 +3757,14 @@ static void register_types(void)
     register_char_driver("socket", qemu_chr_open_socket);
     register_char_driver("udp", qemu_chr_open_udp);
     register_char_driver("memory", qemu_chr_open_ringbuf);
+    register_char_driver_qapi("file", CHARDEV_BACKEND_KIND_FILE,
+                              qemu_chr_parse_file_out);
 #ifdef _WIN32
-    register_char_driver("file", qemu_chr_open_win_file_out);
     register_char_driver("pipe", qemu_chr_open_win_pipe);
     register_char_driver("console", qemu_chr_open_win_con);
     register_char_driver("serial", qemu_chr_open_win);
     register_char_driver("stdio", qemu_chr_open_win_stdio);
 #else
-    register_char_driver("file", qemu_chr_open_file_out);
     register_char_driver("pipe", qemu_chr_open_pipe);
     register_char_driver("stdio", qemu_chr_open_stdio);
 #endif
commit 2d57286da6e57aacf3b2d0d3354d543ed100a485
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 21 12:56:10 2013 +0100

    chardev: add braille support to qapi
    
    This patch adds 'braille' support to qapi and also switches over
    the braille chardev initialization to the new qapi code path.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/backends/baum.c b/backends/baum.c
index 9063aea..d7d658c 100644
--- a/backends/baum.c
+++ b/backends/baum.c
@@ -561,7 +561,7 @@ static void baum_close(struct CharDriverState *chr)
     g_free(baum);
 }
 
-static CharDriverState *chr_baum_init(QemuOpts *opts)
+CharDriverState *chr_baum_init(void)
 {
     BaumDriverState *baum;
     CharDriverState *chr;
@@ -627,7 +627,7 @@ fail_handle:
 
 static void register_types(void)
 {
-    register_char_driver("braille", chr_baum_init);
+    register_char_driver_qapi("braille", CHARDEV_BACKEND_KIND_BRAILLE, NULL);
 }
 
 type_init(register_types);
diff --git a/include/char/char.h b/include/char/char.h
index 80e8e30..d6a0351 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -264,4 +264,7 @@ CharDriverState *qemu_char_get_next_serial(void);
 /* msmouse */
 CharDriverState *qemu_chr_open_msmouse(void);
 
+/* baum.c */
+CharDriverState *chr_baum_init(void);
+
 #endif
diff --git a/qapi-schema.json b/qapi-schema.json
index 86c04dc..3c5c0fb 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3211,7 +3211,8 @@
                                        'pty'    : 'ChardevDummy',
                                        'null'   : 'ChardevDummy',
                                        'mux'    : 'ChardevMux',
-                                       'msmouse': 'ChardevDummy' } }
+                                       'msmouse': 'ChardevDummy',
+                                       'braille': 'ChardevDummy' } }
 
 ##
 # @ChardevReturn:
diff --git a/qemu-char.c b/qemu-char.c
index e860ba3..1692aa8 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3722,6 +3722,11 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
     case CHARDEV_BACKEND_KIND_MSMOUSE:
         chr = qemu_chr_open_msmouse();
         break;
+#ifdef CONFIG_BRLAPI
+    case CHARDEV_BACKEND_KIND_BRAILLE:
+        chr = chr_baum_init();
+        break;
+#endif
     default:
         error_setg(errp, "unknown chardev backend (%d)", backend->kind);
         break;
commit f5a51cab2afd1124f0988081207d506fbec629b4
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 21 11:58:44 2013 +0100

    chardev: add msmouse support to qapi
    
    This patch adds 'msmouse' support to qapi and also switches over
    the msmouse chardev initialization to the new qapi code path.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/backends/msmouse.c b/backends/msmouse.c
index 407ec87..61052fe 100644
--- a/backends/msmouse.c
+++ b/backends/msmouse.c
@@ -63,7 +63,7 @@ static void msmouse_chr_close (struct CharDriverState *chr)
     g_free (chr);
 }
 
-static CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts)
+CharDriverState *qemu_chr_open_msmouse(void)
 {
     CharDriverState *chr;
 
@@ -78,7 +78,7 @@ static CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts)
 
 static void register_types(void)
 {
-    register_char_driver("msmouse", qemu_chr_open_msmouse);
+    register_char_driver_qapi("msmouse", CHARDEV_BACKEND_KIND_MSMOUSE, NULL);
 }
 
 type_init(register_types);
diff --git a/include/char/char.h b/include/char/char.h
index afe0024..80e8e30 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -261,4 +261,7 @@ size_t qemu_chr_mem_osize(const CharDriverState *chr);
 
 CharDriverState *qemu_char_get_next_serial(void);
 
+/* msmouse */
+CharDriverState *qemu_chr_open_msmouse(void);
+
 #endif
diff --git a/qapi-schema.json b/qapi-schema.json
index 4ad92b0..86c04dc 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3210,7 +3210,8 @@
                                        'socket' : 'ChardevSocket',
                                        'pty'    : 'ChardevDummy',
                                        'null'   : 'ChardevDummy',
-                                       'mux'    : 'ChardevMux' } }
+                                       'mux'    : 'ChardevMux',
+                                       'msmouse': 'ChardevDummy' } }
 
 ##
 # @ChardevReturn:
diff --git a/qemu-char.c b/qemu-char.c
index e6f67d8..e860ba3 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3719,6 +3719,9 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
         }
         chr = qemu_chr_open_mux(base);
         break;
+    case CHARDEV_BACKEND_KIND_MSMOUSE:
+        chr = qemu_chr_open_msmouse();
+        break;
     default:
         error_setg(errp, "unknown chardev backend (%d)", backend->kind);
         break;
commit 80dca9e643d11b54f1b9bafbaefeadfb1099e023
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 21 11:41:26 2013 +0100

    chardev: switch null init to qapi
    
    This patch switches over the 'null' chardev initialization
    to the new qapi code path.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/qemu-char.c b/qemu-char.c
index 0dc3802..e6f67d8 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -217,7 +217,7 @@ static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
     return len;
 }
 
-static CharDriverState *qemu_chr_open_null(QemuOpts *opts)
+static CharDriverState *qemu_chr_open_null(void)
 {
     CharDriverState *chr;
 
@@ -3708,7 +3708,7 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
     }
 #endif
     case CHARDEV_BACKEND_KIND_NULL:
-        chr = qemu_chr_open_null(NULL);
+        chr = qemu_chr_open_null();
         break;
     case CHARDEV_BACKEND_KIND_MUX:
         base = qemu_chr_find(backend->mux->chardev);
@@ -3758,7 +3758,7 @@ void qmp_chardev_remove(const char *id, Error **errp)
 
 static void register_types(void)
 {
-    register_char_driver("null", qemu_chr_open_null);
+    register_char_driver_qapi("null", CHARDEV_BACKEND_KIND_NULL, NULL);
     register_char_driver("socket", qemu_chr_open_socket);
     register_char_driver("udp", qemu_chr_open_udp);
     register_char_driver("memory", qemu_chr_open_ringbuf);
commit edb2fb3cc8b85ab956f366fc036ac12853984dae
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 21 16:16:42 2013 +0100

    chardev: add mux chardev support to qapi
    
    This adds mux chardev support to the qapi and also makes the qapi-based
    chardev creation path handle the "mux=on" option correctly.

diff --git a/qapi-schema.json b/qapi-schema.json
index 4494e53..4ad92b0 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3185,6 +3185,17 @@
                                      '*telnet'  : 'bool' } }
 
 ##
+# @ChardevMux:
+#
+# Configuration info for mux chardevs.
+#
+# @chardev: name of the base chardev.
+#
+# Since: 1.5
+##
+{ 'type': 'ChardevMux', 'data': { 'chardev' : 'str' } }
+
+##
 # @ChardevBackend:
 #
 # Configuration info for the new chardev backend.
@@ -3198,7 +3209,8 @@
                                        'parallel': 'ChardevHostdev',
                                        'socket' : 'ChardevSocket',
                                        'pty'    : 'ChardevDummy',
-                                       'null'   : 'ChardevDummy' } }
+                                       'null'   : 'ChardevDummy',
+                                       'mux'    : 'ChardevMux' } }
 
 ##
 # @ChardevReturn:
diff --git a/qemu-char.c b/qemu-char.c
index c2e198e..0dc3802 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3273,6 +3273,11 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
         ChardevBackend *backend = g_new0(ChardevBackend, 1);
         ChardevReturn *ret = NULL;
         const char *id = qemu_opts_id(opts);
+        const char *bid = NULL;
+
+        if (qemu_opt_get_bool(opts, "mux", 0)) {
+            bid = g_strdup_printf("%s-base", id);
+        }
 
         chr = NULL;
         backend->kind = cd->kind;
@@ -3282,10 +3287,24 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
                 goto qapi_out;
             }
         }
-        ret = qmp_chardev_add(qemu_opts_id(opts), backend, errp);
+        ret = qmp_chardev_add(bid ? bid : id, backend, errp);
         if (error_is_set(errp)) {
             goto qapi_out;
         }
+
+        if (bid) {
+            qapi_free_ChardevBackend(backend);
+            qapi_free_ChardevReturn(ret);
+            backend = g_new0(ChardevBackend, 1);
+            backend->mux = g_new0(ChardevMux, 1);
+            backend->kind = CHARDEV_BACKEND_KIND_MUX;
+            backend->mux->chardev = g_strdup(bid);
+            ret = qmp_chardev_add(id, backend, errp);
+            if (error_is_set(errp)) {
+                goto qapi_out;
+            }
+        }
+
         chr = qemu_chr_find(id);
 
     qapi_out:
@@ -3653,7 +3672,7 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
                                Error **errp)
 {
     ChardevReturn *ret = g_new0(ChardevReturn, 1);
-    CharDriverState *chr = NULL;
+    CharDriverState *base, *chr = NULL;
 
     chr = qemu_chr_find(id);
     if (chr) {
@@ -3691,6 +3710,15 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
     case CHARDEV_BACKEND_KIND_NULL:
         chr = qemu_chr_open_null(NULL);
         break;
+    case CHARDEV_BACKEND_KIND_MUX:
+        base = qemu_chr_find(backend->mux->chardev);
+        if (base == NULL) {
+            error_setg(errp, "mux: base chardev %s not found",
+                       backend->mux->chardev);
+            break;
+        }
+        chr = qemu_chr_open_mux(base);
+        break;
     default:
         error_setg(errp, "unknown chardev backend (%d)", backend->kind);
         break;
@@ -3701,7 +3729,8 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
     }
     if (chr) {
         chr->label = g_strdup(id);
-        chr->avail_connections = 1;
+        chr->avail_connections =
+            (backend->kind == CHARDEV_BACKEND_KIND_MUX) ? MAX_MUX : 1;
         QTAILQ_INSERT_TAIL(&chardevs, chr, next);
         return ret;
     } else {
commit 2c5f488293c7d0cd095635c74157c2526e2c4947
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 21 11:39:12 2013 +0100

    chardev: add support for qapi-based chardev initialization
    
    This patch add support for a new way to initialize chardev devices.
    Instead of calling a initialization function with a QemuOpts we will
    now create a (qapi) ChardevBackend, optionally call a function to
    fill ChardevBackend from QemuOpts, then go create the chardev using
    the new qapi code path which is also used by chardev-add.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/include/char/char.h b/include/char/char.h
index 2e24270..afe0024 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -245,6 +245,8 @@ CharDriverState *qemu_chr_find(const char *name);
 QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
 
 void register_char_driver(const char *name, CharDriverState *(*open)(QemuOpts *));
+void register_char_driver_qapi(const char *name, int kind,
+        void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp));
 
 /* add an eventfd to the qemu devices that are polled */
 CharDriverState *qemu_chr_open_eventfd(int eventfd);
diff --git a/qemu-char.c b/qemu-char.c
index 83787c7..c2e198e 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3204,7 +3204,11 @@ static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
 
 typedef struct CharDriver {
     const char *name;
+    /* old, pre qapi */
     CharDriverState *(*open)(QemuOpts *opts);
+    /* new, qapi-based */
+    int kind;
+    void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp);
 } CharDriver;
 
 static GSList *backends;
@@ -3220,6 +3224,19 @@ void register_char_driver(const char *name, CharDriverState *(*open)(QemuOpts *)
     backends = g_slist_append(backends, s);
 }
 
+void register_char_driver_qapi(const char *name, int kind,
+        void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp))
+{
+    CharDriver *s;
+
+    s = g_malloc0(sizeof(*s));
+    s->name = g_strdup(name);
+    s->kind = kind;
+    s->parse = parse;
+
+    backends = g_slist_append(backends, s);
+}
+
 CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
                                     void (*init)(struct CharDriverState *s),
                                     Error **errp)
@@ -3251,6 +3268,32 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
         return NULL;
     }
 
+    if (!cd->open) {
+        /* using new, qapi init */
+        ChardevBackend *backend = g_new0(ChardevBackend, 1);
+        ChardevReturn *ret = NULL;
+        const char *id = qemu_opts_id(opts);
+
+        chr = NULL;
+        backend->kind = cd->kind;
+        if (cd->parse) {
+            cd->parse(opts, backend, errp);
+            if (error_is_set(errp)) {
+                goto qapi_out;
+            }
+        }
+        ret = qmp_chardev_add(qemu_opts_id(opts), backend, errp);
+        if (error_is_set(errp)) {
+            goto qapi_out;
+        }
+        chr = qemu_chr_find(id);
+
+    qapi_out:
+        qapi_free_ChardevBackend(backend);
+        qapi_free_ChardevReturn(ret);
+        return chr;
+    }
+
     chr = cd->open(opts);
     if (!chr) {
         error_setg(errp, "chardev: opening backend \"%s\" failed",
commit 8ca761f661a7cc972bc6bcf938feca6c538100f0
Author: Peter Feiner <peter at gridcentric.ca>
Date:   Mon Mar 4 13:54:25 2013 -0500

    exec: make -mem-path filenames deterministic
    
    Adds ramblocks' names to their backing files when using -mem-path.  Eases
    introspection and debugging.
    
    Signed-off-by: Peter Feiner <peter at gridcentric.ca>
    Message-id: 1362423265-15855-1-git-send-email-peter at gridcentric.ca
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/exec.c b/exec.c
index 46a2830..f84e095 100644
--- a/exec.c
+++ b/exec.c
@@ -844,6 +844,8 @@ static void *file_ram_alloc(RAMBlock *block,
                             const char *path)
 {
     char *filename;
+    char *sanitized_name;
+    char *c;
     void *area;
     int fd;
 #ifdef MAP_POPULATE
@@ -865,7 +867,16 @@ static void *file_ram_alloc(RAMBlock *block,
         return NULL;
     }
 
-    filename = g_strdup_printf("%s/qemu_back_mem.XXXXXX", path);
+    /* Make name safe to use with mkstemp by replacing '/' with '_'. */
+    sanitized_name = g_strdup(block->mr->name);
+    for (c = sanitized_name; *c != '\0'; c++) {
+        if (*c == '/')
+            *c = '_';
+    }
+
+    filename = g_strdup_printf("%s/qemu_back_mem.%s.XXXXXX", path,
+                               sanitized_name);
+    g_free(sanitized_name);
 
     fd = mkstemp(filename);
     if (fd < 0) {
commit 4524051c32190c1dc13ec2ccd122fd120dbed736
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Mar 8 11:42:24 2013 +0100

    Add search path support for qemu data files.
    
    This patch allows to specify multiple directories where qemu should look
    for data files.  To implement that the behavior of the -L switch is
    slightly different now:  Instead of replacing the data directory the
    path specified will be appended to the data directory list.  So when
    specifiying -L multiple times all directories specified will be checked,
    in the order they are specified on the command line, instead of just the
    last one.
    
    Additionally the default paths are always appended to the directory
    data list.  This allows to specify a incomplete directory (such as the
    seabios out/ directory) via -L.  Anything not found there will be loaded
    from the default paths, so you don't have to create a symlink farm for
    all the rom blobs.
    
    For trouble-shooting a tracepoint has been added, logging which blob
    has been loaded from which location.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Message-id: 1362739344-8068-1-git-send-email-kraxel at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/trace-events b/trace-events
index 8389d83..d6a847d 100644
--- a/trace-events
+++ b/trace-events
@@ -473,6 +473,7 @@ scsi_request_sense(int target, int lun, int tag) "target %d lun %d tag %d"
 
 # vl.c
 vm_state_notify(int running, int reason) "running %d reason %d"
+load_file(const char *name, const char *path) "name %s location %s"
 
 # block/qcow2.c
 qcow2_writev_start_req(void *co, int64_t sector, int nb_sectors) "co %p sector %" PRIx64 " nb_sectors %d"
diff --git a/vl.c b/vl.c
index 3822d99..a621aec 100644
--- a/vl.c
+++ b/vl.c
@@ -179,7 +179,8 @@ int main(int argc, char **argv)
 #define MAX_VIRTIO_CONSOLES 1
 #define MAX_SCLP_CONSOLES 1
 
-static const char *data_dir;
+static const char *data_dir[16];
+static int data_dir_idx;
 const char *bios_name = NULL;
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 DisplayType display_type = DT_DEFAULT;
@@ -2276,14 +2277,16 @@ static int balloon_parse(const char *arg)
 
 char *qemu_find_file(int type, const char *name)
 {
-    int len;
+    int i;
     const char *subdir;
     char *buf;
 
     /* Try the name as a straight path first */
     if (access(name, R_OK) == 0) {
+        trace_load_file(name, name);
         return g_strdup(name);
     }
+
     switch (type) {
     case QEMU_FILE_TYPE_BIOS:
         subdir = "";
@@ -2294,14 +2297,16 @@ char *qemu_find_file(int type, const char *name)
     default:
         abort();
     }
-    len = strlen(data_dir) + strlen(name) + strlen(subdir) + 2;
-    buf = g_malloc0(len);
-    snprintf(buf, len, "%s/%s%s", data_dir, subdir, name);
-    if (access(buf, R_OK)) {
+
+    for (i = 0; i < data_dir_idx; i++) {
+        buf = g_strdup_printf("%s/%s%s", data_dir[i], subdir, name);
+        if (access(buf, R_OK) == 0) {
+            trace_load_file(name, buf);
+            return buf;
+        }
         g_free(buf);
-        return NULL;
     }
-    return buf;
+    return NULL;
 }
 
 static int device_help_func(QemuOpts *opts, void *opaque)
@@ -3285,7 +3290,9 @@ int main(int argc, char **argv, char **envp)
                 add_device_config(DEV_GDB, optarg);
                 break;
             case QEMU_OPTION_L:
-                data_dir = optarg;
+                if (data_dir_idx < ARRAY_SIZE(data_dir)) {
+                    data_dir[data_dir_idx++] = optarg;
+                }
                 break;
             case QEMU_OPTION_bios:
                 bios_name = optarg;
@@ -3925,12 +3932,15 @@ int main(int argc, char **argv, char **envp)
 
     /* If no data_dir is specified then try to find it relative to the
        executable path.  */
-    if (!data_dir) {
-        data_dir = os_find_datadir(argv[0]);
+    if (data_dir_idx < ARRAY_SIZE(data_dir)) {
+        data_dir[data_dir_idx] = os_find_datadir(argv[0]);
+        if (data_dir[data_dir_idx] != NULL) {
+            data_dir_idx++;
+        }
     }
     /* If all else fails use the install path specified when building. */
-    if (!data_dir) {
-        data_dir = CONFIG_QEMU_DATADIR;
+    if (data_dir_idx < ARRAY_SIZE(data_dir)) {
+        data_dir[data_dir_idx++] = CONFIG_QEMU_DATADIR;
     }
 
     /*
commit 1272ec881440bf579c9d3c9cd0745b2551ce6a7f
Author: Stefan Berger <stefanb at linux.vnet.ibm.com>
Date:   Wed Feb 27 12:47:55 2013 -0500

    Build TPM passthrough for i386 and x86_64 targets
    
    Build the TPM passthrough driver only for i386 and x86_64 targets
    using the default-configs files for those targets with softmmu.
    
    Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
    Reviewed-by: Corey Bryant <coreyb at linux.vnet.ibm.com>
    Reviewed-by: Joel Schopp <jschopp at linux.vnet.ibm.com>
    Message-id: 1361987275-26289-8-git-send-email-stefanb at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index f70594d..df9e126 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -27,3 +27,4 @@ CONFIG_APPLESMC=y
 CONFIG_I8259=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_TPM_TIS=y
+CONFIG_TPM_PASSTHROUGH=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 66c4855..ab3cd5f 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -27,3 +27,4 @@ CONFIG_APPLESMC=y
 CONFIG_I8259=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_TPM_TIS=y
+CONFIG_TPM_PASSTHROUGH=y
commit 92dcc234ec1f266fb5d59bed77d66320c2c75965
Author: Stefan Berger <stefanb at linux.vnet.ibm.com>
Date:   Wed Feb 27 12:47:54 2013 -0500

    Add support for cancelling of a TPM command
    
    This patch adds support for cancelling an executing TPM command.
    In Linux for example a user can cancel a command through the TPM's
    sysfs 'cancel' entry using
    
    echo "1" > /sysfs/class/misc/tpm0/device/cancel
    
    This patch propagates the cancellation of a command inside a VM
    to the host TPM's sysfs entry.
    It also uses the possibility to cancel the command before QEMU VM
    shutdown or reboot, which helps in preventing QEMU from hanging while
    waiting for the completion of the command.
    To relieve higher layers or users from having to determine the TPM's
    cancel sysfs entry, the driver searches for the entry in well known
    locations.
    
    Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
    Reviewed-by: Corey Bryant <coreyb at linux.vnet.ibm.com>
    Reviewed-by: Joel Schopp <jschopp at linux.vnet.ibm.com>
    Message-id: 1361987275-26289-7-git-send-email-stefanb at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index 0be16b4..30fb85d 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2221,8 +2221,10 @@ DEFHEADING()
 DEFHEADING(TPM device options:)
 
 DEF("tpmdev", HAS_ARG, QEMU_OPTION_tpmdev, \
-    "-tpmdev passthrough,id=id[,path=path]\n"
-    "                use path to provide path to a character device; default is /dev/tpm0\n",
+    "-tpmdev passthrough,id=id[,path=path][,cancel-path=path]\n"
+    "                use path to provide path to a character device; default is /dev/tpm0\n"
+    "                use cancel-path to provide path to TPM's cancel sysfs entry; if\n"
+    "                not provided it will be searched for in /sys/class/misc/tpm?/device\n",
     QEMU_ARCH_ALL)
 STEXI
 
@@ -2244,7 +2246,7 @@ Use 'help' to print all available TPM backend types.
 qemu -tpmdev help
 @end example
 
- at item -tpmdev passthrough, id=@var{id}, path=@var{path}
+ at item -tpmdev passthrough, id=@var{id}, path=@var{path}, cancel-path=@var{cancel-path}
 
 (Linux-host only) Enable access to the host's TPM using the passthrough
 driver.
@@ -2253,6 +2255,11 @@ driver.
 a Linux host this would be @code{/dev/tpm0}.
 @option{path} is optional and by default @code{/dev/tpm0} is used.
 
+ at option{cancel-path} specifies the path to the host TPM device's sysfs
+entry allowing for cancellation of an ongoing TPM command.
+ at option{cancel-path} is optional and by default QEMU will search for the
+sysfs entry to use.
+
 Some notes about using the host's TPM with the passthrough driver:
 
 The TPM device accessed by the passthrough driver must not be
diff --git a/tpm/tpm_passthrough.c b/tpm/tpm_passthrough.c
index 760e18f..24aff4d 100644
--- a/tpm/tpm_passthrough.c
+++ b/tpm/tpm_passthrough.c
@@ -22,6 +22,8 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>
  */
 
+#include <dirent.h>
+
 #include "qemu-common.h"
 #include "qapi/error.h"
 #include "qemu/sockets.h"
@@ -57,11 +59,18 @@ struct TPMPassthruState {
 
     char *tpm_dev;
     int tpm_fd;
+    bool tpm_executing;
+    bool tpm_op_canceled;
+    int cancel_fd;
     bool had_startup_error;
 };
 
 #define TPM_PASSTHROUGH_DEFAULT_DEVICE "/dev/tpm0"
 
+/* functions */
+
+static void tpm_passthrough_cancel_cmd(TPMBackend *tb);
+
 static int tpm_passthrough_unix_write(int fd, const uint8_t *buf, uint32_t len)
 {
     return send_all(fd, buf, len);
@@ -79,25 +88,36 @@ static uint32_t tpm_passthrough_get_size_from_buffer(const uint8_t *buf)
     return be32_to_cpu(resp->len);
 }
 
-static int tpm_passthrough_unix_tx_bufs(int tpm_fd,
+static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
                                         const uint8_t *in, uint32_t in_len,
                                         uint8_t *out, uint32_t out_len)
 {
     int ret;
 
-    ret = tpm_passthrough_unix_write(tpm_fd, in, in_len);
+    tpm_pt->tpm_op_canceled = false;
+    tpm_pt->tpm_executing = true;
+
+    ret = tpm_passthrough_unix_write(tpm_pt->tpm_fd, in, in_len);
     if (ret != in_len) {
-        error_report("tpm_passthrough: error while transmitting data "
-                     "to TPM: %s (%i)\n",
-                     strerror(errno), errno);
+        if (!tpm_pt->tpm_op_canceled ||
+            (tpm_pt->tpm_op_canceled && errno != ECANCELED)) {
+            error_report("tpm_passthrough: error while transmitting data "
+                         "to TPM: %s (%i)\n",
+                         strerror(errno), errno);
+        }
         goto err_exit;
     }
 
-    ret = tpm_passthrough_unix_read(tpm_fd, out, out_len);
+    tpm_pt->tpm_executing = false;
+
+    ret = tpm_passthrough_unix_read(tpm_pt->tpm_fd, out, out_len);
     if (ret < 0) {
-        error_report("tpm_passthrough: error while reading data from "
-                     "TPM: %s (%i)\n",
-                     strerror(errno), errno);
+        if (!tpm_pt->tpm_op_canceled ||
+            (tpm_pt->tpm_op_canceled && errno != ECANCELED)) {
+            error_report("tpm_passthrough: error while reading data from "
+                         "TPM: %s (%i)\n",
+                         strerror(errno), errno);
+        }
     } else if (ret < sizeof(struct tpm_resp_hdr) ||
                tpm_passthrough_get_size_from_buffer(out) != ret) {
         ret = -1;
@@ -110,13 +130,15 @@ err_exit:
         tpm_write_fatal_error_response(out, out_len);
     }
 
+    tpm_pt->tpm_executing = false;
+
     return ret;
 }
 
-static int tpm_passthrough_unix_transfer(int tpm_fd,
+static int tpm_passthrough_unix_transfer(TPMPassthruState *tpm_pt,
                                          const TPMLocality *locty_data)
 {
-    return tpm_passthrough_unix_tx_bufs(tpm_fd,
+    return tpm_passthrough_unix_tx_bufs(tpm_pt,
                                         locty_data->w_buffer.buffer,
                                         locty_data->w_offset,
                                         locty_data->r_buffer.buffer,
@@ -134,7 +156,7 @@ static void tpm_passthrough_worker_thread(gpointer data,
 
     switch (cmd) {
     case TPM_BACKEND_CMD_PROCESS_CMD:
-        tpm_passthrough_unix_transfer(tpm_pt->tpm_fd,
+        tpm_passthrough_unix_transfer(tpm_pt,
                                       thr_parms->tpm_state->locty_data);
 
         thr_parms->recv_data_callback(thr_parms->tpm_state,
@@ -172,6 +194,8 @@ static void tpm_passthrough_reset(TPMBackend *tb)
 
     DPRINTF("tpm_passthrough: CALL TO TPM_RESET!\n");
 
+    tpm_passthrough_cancel_cmd(tb);
+
     tpm_backend_thread_end(&tpm_pt->tbt);
 
     tpm_pt->had_startup_error = false;
@@ -221,7 +245,29 @@ static void tpm_passthrough_deliver_request(TPMBackend *tb)
 
 static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
 {
-    /* cancelling an ongoing command is known not to work with some TPMs */
+    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+    int n;
+
+    /*
+     * As of Linux 3.7 the tpm_tis driver does not properly cancel
+     * commands on all TPM manufacturers' TPMs.
+     * Only cancel if we're busy so we don't cancel someone else's
+     * command, e.g., a command executed on the host.
+     */
+    if (tpm_pt->tpm_executing) {
+        if (tpm_pt->cancel_fd >= 0) {
+            n = write(tpm_pt->cancel_fd, "-", 1);
+            if (n != 1) {
+                error_report("Canceling TPM command failed: %s\n",
+                             strerror(errno));
+            } else {
+                tpm_pt->tpm_op_canceled = true;
+            }
+        } else {
+            error_report("Cannot cancel TPM command due to missing "
+                         "TPM sysfs cancel entry");
+        }
+    }
 }
 
 static const char *tpm_passthrough_create_desc(void)
@@ -281,10 +327,98 @@ static int tpm_passthrough_test_tpmdev(int fd)
     return 0;
 }
 
+/*
+ * Check whether the given base path, e.g.,  /sys/class/misc/tpm0/device,
+ * is the sysfs directory of a TPM. A TPM sysfs directory should be uniquely
+ * recognizable by the file entries 'pcrs' and 'cancel'.
+ * Upon success 'true' is returned and the basebath buffer has '/cancel'
+ * appended.
+ */
+static bool tpm_passthrough_check_sysfs_cancel(char *basepath, size_t bufsz)
+{
+    char path[PATH_MAX];
+    struct stat statbuf;
+
+    snprintf(path, sizeof(path), "%s/pcrs", basepath);
+    if (stat(path, &statbuf) == -1 || !S_ISREG(statbuf.st_mode)) {
+        return false;
+    }
+
+    snprintf(path, sizeof(path), "%s/cancel", basepath);
+    if (stat(path, &statbuf) == -1 || !S_ISREG(statbuf.st_mode)) {
+        return false;
+    }
+
+    strncpy(basepath, path, bufsz);
+
+    return true;
+}
+
+/*
+ * Unless path or file descriptor set has been provided by user,
+ * determine the sysfs cancel file following kernel documentation
+ * in Documentation/ABI/stable/sysfs-class-tpm.
+ */
+static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb)
+{
+    int fd = -1;
+    unsigned int idx;
+    DIR *pnp_dir;
+    char path[PATH_MAX];
+    struct dirent entry, *result;
+    int len;
+
+    if (tb->cancel_path) {
+        fd = qemu_open(tb->cancel_path, O_WRONLY);
+        if (fd < 0) {
+            error_report("Could not open TPM cancel path : %s",
+                         strerror(errno));
+        }
+        return fd;
+    }
+
+    snprintf(path, sizeof(path), "/sys/class/misc");
+    pnp_dir = opendir(path);
+    if (pnp_dir != NULL) {
+        while (readdir_r(pnp_dir, &entry, &result) == 0 &&
+               result != NULL) {
+            /*
+             * only allow /sys/class/misc/tpm%u type of paths
+             */
+            if (sscanf(entry.d_name, "tpm%u%n", &idx, &len) < 1 ||
+                len <= strlen("tpm") ||
+                len != strlen(entry.d_name)) {
+                continue;
+            }
+
+            snprintf(path, sizeof(path), "/sys/class/misc/%s/device",
+                     entry.d_name);
+            if (!tpm_passthrough_check_sysfs_cancel(path, sizeof(path))) {
+                continue;
+            }
+
+            fd = qemu_open(path, O_WRONLY);
+            break;
+        }
+        closedir(pnp_dir);
+    }
+
+    if (fd >= 0) {
+        tb->cancel_path = g_strdup(path);
+    }
+
+    return fd;
+}
+
 static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
 {
     const char *value;
 
+    value = qemu_opt_get(opts, "cancel-path");
+    if (value) {
+        tb->cancel_path = g_strdup(value);
+    }
+
     value = qemu_opt_get(opts, "path");
     if (!value) {
         value = TPM_PASSTHROUGH_DEFAULT_DEVICE;
@@ -339,6 +473,11 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
         goto err_exit;
     }
 
+    tb->s.tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tb);
+    if (tb->s.tpm_pt->cancel_fd < 0) {
+        goto err_exit;
+    }
+
     return tb;
 
 err_exit:
@@ -353,12 +492,16 @@ static void tpm_passthrough_destroy(TPMBackend *tb)
 {
     TPMPassthruState *tpm_pt = tb->s.tpm_pt;
 
+    tpm_passthrough_cancel_cmd(tb);
+
     tpm_backend_thread_end(&tpm_pt->tbt);
 
     qemu_close(tpm_pt->tpm_fd);
+    qemu_close(tb->s.tpm_pt->cancel_fd);
 
     g_free(tb->id);
     g_free(tb->path);
+    g_free(tb->cancel_path);
     g_free(tb->s.tpm_pt->tpm_dev);
     g_free(tb->s.tpm_pt);
     g_free(tb);
diff --git a/vl.c b/vl.c
index 0c6c2bf..3822d99 100644
--- a/vl.c
+++ b/vl.c
@@ -503,6 +503,11 @@ static QemuOptsList qemu_tpmdev_opts = {
             .help = "Type of TPM backend",
         },
         {
+            .name = "cancel-path",
+            .type = QEMU_OPT_STRING,
+            .help = "Sysfs file entry for canceling TPM commands",
+        },
+        {
             .name = "path",
             .type = QEMU_OPT_STRING,
             .help = "Path to TPM device on the host",
commit 4549a8b7ee3c47155c09582f31086f7d0ba61fc4
Author: Stefan Berger <stefanb at linux.vnet.ibm.com>
Date:   Wed Feb 27 12:47:53 2013 -0500

    Add a TPM Passthrough backend driver implementation
    
    This patch is based of off version 9 of Stefan Berger's patch series
      "QEMU Trusted Platform Module (TPM) integration"
    and adds a new backend driver for it.
    
    This patch adds a passthrough backend driver for passing commands sent to the
    emulated TPM device directly to a TPM device opened on the host machine.
    Thus it is possible to use a hardware TPM device in a system running on QEMU,
    providing the ability to access a TPM in a special state (e.g. after a Trusted
    Boot).
    
    This functionality is being used in the acTvSM Trusted Virtualization Platform
    which is available on [1].
    
    Usage example:
      qemu-system-x86_64 -tpmdev passthrough,id=tpm0,path=/dev/tpm0 \
                         -device tpm-tis,tpmdev=tpm0 \
                         -cdrom test.iso -boot d
    
    Some notes about the host TPM:
    The TPM needs to be enabled and activated. If that's not the case one
    has to go through the BIOS/UEFI and enable and activate that TPM for TPM
    commands to work as expected.
    It may be necessary to boot the kernel using tpm_tis.force=1 in the boot
    command line or 'modprobe tpm_tis force=1' in case of using it as a module.
    
    Regards,
    Andreas Niederl, Stefan Berger
    
    [1] http://trustedjava.sourceforge.net/
    
    Signed-off-by: Andreas Niederl <andreas.niederl at iaik.tugraz.at>
    Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
    Reviewed-by: Corey Bryant <coreyb at linux.vnet.ibm.com>
    Reviewed-by: Joel Schopp <jschopp at linux.vnet.ibm.com>
    Message-id: 1361987275-26289-6-git-send-email-stefanb at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index 6125bf7..c5cee4b 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -38,6 +38,7 @@ int socket_set_nodelay(int fd);
 void socket_set_block(int fd);
 void socket_set_nonblock(int fd);
 int send_all(int fd, const void *buf, int len1);
+int recv_all(int fd, void *buf, int len1, bool single_read);
 
 /* callback function for nonblocking connect
  * valid fd on success, negative error code on failure
diff --git a/qemu-char.c b/qemu-char.c
index 04aa589..83787c7 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -533,6 +533,30 @@ int send_all(int fd, const void *_buf, int len1)
     }
     return len1 - len;
 }
+
+int recv_all(int fd, void *_buf, int len1, bool single_read)
+{
+    int ret, len;
+    uint8_t *buf = _buf;
+
+    len = len1;
+    while ((len > 0) && (ret = read(fd, buf, len)) != 0) {
+        if (ret < 0) {
+            if (errno != EINTR && errno != EAGAIN) {
+                return -1;
+            }
+            continue;
+        } else {
+            if (single_read) {
+                return ret;
+            }
+            buf += ret;
+            len -= ret;
+        }
+    }
+    return len1 - len;
+}
+
 #endif /* !_WIN32 */
 
 typedef struct IOWatchPoll
diff --git a/qemu-options.hx b/qemu-options.hx
index 291932f..0be16b4 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2221,7 +2221,8 @@ DEFHEADING()
 DEFHEADING(TPM device options:)
 
 DEF("tpmdev", HAS_ARG, QEMU_OPTION_tpmdev, \
-    "-tpmdev [<type>],id=str[,option][,option][,...]\n",
+    "-tpmdev passthrough,id=id[,path=path]\n"
+    "                use path to provide path to a character device; default is /dev/tpm0\n",
     QEMU_ARCH_ALL)
 STEXI
 
@@ -2231,6 +2232,7 @@ The general form of a TPM device option is:
 @item -tpmdev @var{backend} ,id=@var{id} [, at var{options}]
 @findex -tpmdev
 Backend type must be:
+ at option{passthrough}.
 
 The specific backend type will determine the applicable options.
 The @code{-tpmdev} option requires a @code{-device} option.
@@ -2242,6 +2244,38 @@ Use 'help' to print all available TPM backend types.
 qemu -tpmdev help
 @end example
 
+ at item -tpmdev passthrough, id=@var{id}, path=@var{path}
+
+(Linux-host only) Enable access to the host's TPM using the passthrough
+driver.
+
+ at option{path} specifies the path to the host's TPM device, i.e., on
+a Linux host this would be @code{/dev/tpm0}.
+ at option{path} is optional and by default @code{/dev/tpm0} is used.
+
+Some notes about using the host's TPM with the passthrough driver:
+
+The TPM device accessed by the passthrough driver must not be
+used by any other application on the host.
+
+Since the host's firmware (BIOS/UEFI) has already initialized the TPM,
+the VM's firmware (BIOS/UEFI) will not be able to initialize the
+TPM again and may therefore not show a TPM-specific menu that would
+otherwise allow the user to configure the TPM, e.g., allow the user to
+enable/disable or activate/deactivate the TPM.
+Further, if TPM ownership is released from within a VM then the host's TPM
+will get disabled and deactivated. To enable and activate the
+TPM again afterwards, the host has to be rebooted and the user is
+required to enter the firmware's menu to enable and activate the TPM.
+If the TPM is left disabled and/or deactivated most TPM commands will fail.
+
+To create a passthrough TPM use the following two options:
+ at example
+-tpmdev passthrough,id=tpm0 -device tpm-tis,tpmdev=tpm0
+ at end example
+Note that the @code{-tpmdev} id is @code{tpm0} and is referenced by
+ at code{tpmdev=tpm0} in the device option.
+
 @end table
 
 ETEXI
diff --git a/tpm/Makefile.objs b/tpm/Makefile.objs
index 94ad2e7..8676824 100644
--- a/tpm/Makefile.objs
+++ b/tpm/Makefile.objs
@@ -1,4 +1,6 @@
 common-obj-y = tpm.o
 ifeq ($(CONFIG_TPM),y)
+common-obj-y += tpm_backend.o
 common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o
+common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o
 endif
diff --git a/tpm/tpm.c b/tpm/tpm.c
index 0273549..ffd2495 100644
--- a/tpm/tpm.c
+++ b/tpm/tpm.c
@@ -61,6 +61,20 @@ static bool tpm_model_is_registered(enum TpmModel model)
     return false;
 }
 
+/*
+ * Write an error message in the given output buffer.
+ */
+void tpm_write_fatal_error_response(uint8_t *out, uint32_t out_len)
+{
+    if (out_len >= sizeof(struct tpm_resp_hdr)) {
+        struct tpm_resp_hdr *resp = (struct tpm_resp_hdr *)out;
+
+        resp->tag = cpu_to_be16(TPM_TAG_RSP_COMMAND);
+        resp->len = cpu_to_be32(sizeof(struct tpm_resp_hdr));
+        resp->errcode = cpu_to_be32(TPM_FAIL);
+    }
+}
+
 const TPMDriverOps *tpm_get_backend_driver(const char *type)
 {
     int i;
diff --git a/tpm/tpm_backend.c b/tpm/tpm_backend.c
new file mode 100644
index 0000000..4144ef7
--- /dev/null
+++ b/tpm/tpm_backend.c
@@ -0,0 +1,58 @@
+/*
+ *  common TPM backend driver functions
+ *
+ *  Copyright (c) 2012-2013 IBM Corporation
+ *  Authors:
+ *    Stefan Berger <stefanb at us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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 "tpm/tpm.h"
+#include "qemu/thread.h"
+#include "tpm_backend.h"
+
+void tpm_backend_thread_deliver_request(TPMBackendThread *tbt)
+{
+   g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_PROCESS_CMD, NULL);
+}
+
+void tpm_backend_thread_create(TPMBackendThread *tbt,
+                               GFunc func, gpointer user_data)
+{
+    if (!tbt->pool) {
+        tbt->pool = g_thread_pool_new(func, user_data, 1, TRUE, NULL);
+        g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_INIT, NULL);
+    }
+}
+
+void tpm_backend_thread_end(TPMBackendThread *tbt)
+{
+    if (tbt->pool) {
+        g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_END, NULL);
+        g_thread_pool_free(tbt->pool, FALSE, TRUE);
+        tbt->pool = NULL;
+    }
+}
+
+void tpm_backend_thread_tpm_reset(TPMBackendThread *tbt,
+                                  GFunc func, gpointer user_data)
+{
+    if (!tbt->pool) {
+        tpm_backend_thread_create(tbt, func, user_data);
+    } else {
+        g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_TPM_RESET,
+                           NULL);
+    }
+}
diff --git a/tpm/tpm_backend.h b/tpm/tpm_backend.h
new file mode 100644
index 0000000..05d94d0
--- /dev/null
+++ b/tpm/tpm_backend.h
@@ -0,0 +1,45 @@
+/*
+ *  common TPM backend driver functions
+ *
+ *  Copyright (c) 2012-2013 IBM Corporation
+ *  Authors:
+ *    Stefan Berger <stefanb at us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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 TPM_TPM_BACKEND_H
+#define TPM_TPM_BACKEND_H
+
+#include <glib.h>
+
+typedef struct TPMBackendThread {
+    GThreadPool *pool;
+} TPMBackendThread;
+
+void tpm_backend_thread_deliver_request(TPMBackendThread *tbt);
+void tpm_backend_thread_create(TPMBackendThread *tbt,
+                               GFunc func, gpointer user_data);
+void tpm_backend_thread_end(TPMBackendThread *tbt);
+void tpm_backend_thread_tpm_reset(TPMBackendThread *tbt,
+                                  GFunc func, gpointer user_data);
+
+typedef enum TPMBackendCmd {
+    TPM_BACKEND_CMD_INIT = 1,
+    TPM_BACKEND_CMD_PROCESS_CMD,
+    TPM_BACKEND_CMD_END,
+    TPM_BACKEND_CMD_TPM_RESET,
+} TPMBackendCmd;
+
+#endif /* TPM_TPM_BACKEND_H */
diff --git a/tpm/tpm_int.h b/tpm/tpm_int.h
index d5358ad..f705643 100644
--- a/tpm/tpm_int.h
+++ b/tpm/tpm_int.h
@@ -18,6 +18,8 @@
 struct TPMDriverOps;
 typedef struct TPMDriverOps TPMDriverOps;
 
+typedef struct TPMPassthruState TPMPassthruState;
+
 typedef struct TPMBackend {
     char *id;
     enum TpmModel fe_model;
@@ -25,6 +27,10 @@ typedef struct TPMBackend {
     char *cancel_path;
     const TPMDriverOps *ops;
 
+    union {
+        TPMPassthruState *tpm_pt;
+    } s;
+
     QLIST_ENTRY(TPMBackend) list;
 } TPMBackend;
 
@@ -74,10 +80,37 @@ struct TPMDriverOps {
     bool (*get_tpm_established_flag)(TPMBackend *t);
 };
 
+struct tpm_req_hdr {
+    uint16_t tag;
+    uint32_t len;
+    uint32_t ordinal;
+} QEMU_PACKED;
+
+struct tpm_resp_hdr {
+    uint16_t tag;
+    uint32_t len;
+    uint32_t errcode;
+} QEMU_PACKED;
+
+#define TPM_TAG_RQU_COMMAND       0xc1
+#define TPM_TAG_RQU_AUTH1_COMMAND 0xc2
+#define TPM_TAG_RQU_AUTH2_COMMAND 0xc3
+
+#define TPM_TAG_RSP_COMMAND       0xc4
+#define TPM_TAG_RSP_AUTH1_COMMAND 0xc5
+#define TPM_TAG_RSP_AUTH2_COMMAND 0xc6
+
+#define TPM_FAIL                  9
+
+#define TPM_ORD_GetTicks          0xf1
+
 TPMBackend *qemu_find_tpm(const char *id);
 int tpm_register_model(enum TpmModel model);
 int tpm_register_driver(const TPMDriverOps *tdo);
 void tpm_display_backend_drivers(void);
 const TPMDriverOps *tpm_get_backend_driver(const char *type);
+void tpm_write_fatal_error_response(uint8_t *out, uint32_t out_len);
+
+extern const TPMDriverOps tpm_passthrough_driver;
 
 #endif /* TPM_TPM_INT_H */
diff --git a/tpm/tpm_passthrough.c b/tpm/tpm_passthrough.c
new file mode 100644
index 0000000..760e18f
--- /dev/null
+++ b/tpm/tpm_passthrough.c
@@ -0,0 +1,387 @@
+/*
+ *  passthrough TPM driver
+ *
+ *  Copyright (c) 2010 - 2013 IBM Corporation
+ *  Authors:
+ *    Stefan Berger <stefanb at us.ibm.com>
+ *
+ *  Copyright (C) 2011 IAIK, Graz University of Technology
+ *    Author: Andreas Niederl
+ *
+ * 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 "qemu-common.h"
+#include "qapi/error.h"
+#include "qemu/sockets.h"
+#include "tpm_int.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "tpm_tis.h"
+#include "tpm_backend.h"
+
+/* #define DEBUG_TPM */
+
+#ifdef DEBUG_TPM
+#define DPRINTF(fmt, ...) \
+    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+    do { } while (0)
+#endif
+
+/* data structures */
+
+typedef struct TPMPassthruThreadParams {
+    TPMState *tpm_state;
+
+    TPMRecvDataCB *recv_data_callback;
+    TPMBackend *tb;
+} TPMPassthruThreadParams;
+
+struct TPMPassthruState {
+    TPMBackendThread tbt;
+
+    TPMPassthruThreadParams tpm_thread_params;
+
+    char *tpm_dev;
+    int tpm_fd;
+    bool had_startup_error;
+};
+
+#define TPM_PASSTHROUGH_DEFAULT_DEVICE "/dev/tpm0"
+
+static int tpm_passthrough_unix_write(int fd, const uint8_t *buf, uint32_t len)
+{
+    return send_all(fd, buf, len);
+}
+
+static int tpm_passthrough_unix_read(int fd, uint8_t *buf, uint32_t len)
+{
+    return recv_all(fd, buf, len, true);
+}
+
+static uint32_t tpm_passthrough_get_size_from_buffer(const uint8_t *buf)
+{
+    struct tpm_resp_hdr *resp = (struct tpm_resp_hdr *)buf;
+
+    return be32_to_cpu(resp->len);
+}
+
+static int tpm_passthrough_unix_tx_bufs(int tpm_fd,
+                                        const uint8_t *in, uint32_t in_len,
+                                        uint8_t *out, uint32_t out_len)
+{
+    int ret;
+
+    ret = tpm_passthrough_unix_write(tpm_fd, in, in_len);
+    if (ret != in_len) {
+        error_report("tpm_passthrough: error while transmitting data "
+                     "to TPM: %s (%i)\n",
+                     strerror(errno), errno);
+        goto err_exit;
+    }
+
+    ret = tpm_passthrough_unix_read(tpm_fd, out, out_len);
+    if (ret < 0) {
+        error_report("tpm_passthrough: error while reading data from "
+                     "TPM: %s (%i)\n",
+                     strerror(errno), errno);
+    } else if (ret < sizeof(struct tpm_resp_hdr) ||
+               tpm_passthrough_get_size_from_buffer(out) != ret) {
+        ret = -1;
+        error_report("tpm_passthrough: received invalid response "
+                     "packet from TPM\n");
+    }
+
+err_exit:
+    if (ret < 0) {
+        tpm_write_fatal_error_response(out, out_len);
+    }
+
+    return ret;
+}
+
+static int tpm_passthrough_unix_transfer(int tpm_fd,
+                                         const TPMLocality *locty_data)
+{
+    return tpm_passthrough_unix_tx_bufs(tpm_fd,
+                                        locty_data->w_buffer.buffer,
+                                        locty_data->w_offset,
+                                        locty_data->r_buffer.buffer,
+                                        locty_data->r_buffer.size);
+}
+
+static void tpm_passthrough_worker_thread(gpointer data,
+                                          gpointer user_data)
+{
+    TPMPassthruThreadParams *thr_parms = user_data;
+    TPMPassthruState *tpm_pt = thr_parms->tb->s.tpm_pt;
+    TPMBackendCmd cmd = (TPMBackendCmd)data;
+
+    DPRINTF("tpm_passthrough: processing command type %d\n", cmd);
+
+    switch (cmd) {
+    case TPM_BACKEND_CMD_PROCESS_CMD:
+        tpm_passthrough_unix_transfer(tpm_pt->tpm_fd,
+                                      thr_parms->tpm_state->locty_data);
+
+        thr_parms->recv_data_callback(thr_parms->tpm_state,
+                                      thr_parms->tpm_state->locty_number);
+        break;
+    case TPM_BACKEND_CMD_INIT:
+    case TPM_BACKEND_CMD_END:
+    case TPM_BACKEND_CMD_TPM_RESET:
+        /* nothing to do */
+        break;
+    }
+}
+
+/*
+ * Start the TPM (thread). If it had been started before, then terminate
+ * and start it again.
+ */
+static int tpm_passthrough_startup_tpm(TPMBackend *tb)
+{
+    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+
+    /* terminate a running TPM */
+    tpm_backend_thread_end(&tpm_pt->tbt);
+
+    tpm_backend_thread_create(&tpm_pt->tbt,
+                              tpm_passthrough_worker_thread,
+                              &tb->s.tpm_pt->tpm_thread_params);
+
+    return 0;
+}
+
+static void tpm_passthrough_reset(TPMBackend *tb)
+{
+    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+
+    DPRINTF("tpm_passthrough: CALL TO TPM_RESET!\n");
+
+    tpm_backend_thread_end(&tpm_pt->tbt);
+
+    tpm_pt->had_startup_error = false;
+}
+
+static int tpm_passthrough_init(TPMBackend *tb, TPMState *s,
+                                TPMRecvDataCB *recv_data_cb)
+{
+    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+
+    tpm_pt->tpm_thread_params.tpm_state = s;
+    tpm_pt->tpm_thread_params.recv_data_callback = recv_data_cb;
+    tpm_pt->tpm_thread_params.tb = tb;
+
+    return 0;
+}
+
+static bool tpm_passthrough_get_tpm_established_flag(TPMBackend *tb)
+{
+    return false;
+}
+
+static bool tpm_passthrough_get_startup_error(TPMBackend *tb)
+{
+    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+
+    return tpm_pt->had_startup_error;
+}
+
+static size_t tpm_passthrough_realloc_buffer(TPMSizedBuffer *sb)
+{
+    size_t wanted_size = 4096; /* Linux tpm.c buffer size */
+
+    if (sb->size != wanted_size) {
+        sb->buffer = g_realloc(sb->buffer, wanted_size);
+        sb->size = wanted_size;
+    }
+    return sb->size;
+}
+
+static void tpm_passthrough_deliver_request(TPMBackend *tb)
+{
+    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+
+    tpm_backend_thread_deliver_request(&tpm_pt->tbt);
+}
+
+static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
+{
+    /* cancelling an ongoing command is known not to work with some TPMs */
+}
+
+static const char *tpm_passthrough_create_desc(void)
+{
+    return "Passthrough TPM backend driver";
+}
+
+/*
+ * A basic test of a TPM device. We expect a well formatted response header
+ * (error response is fine) within one second.
+ */
+static int tpm_passthrough_test_tpmdev(int fd)
+{
+    struct tpm_req_hdr req = {
+        .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
+        .len = cpu_to_be32(sizeof(req)),
+        .ordinal = cpu_to_be32(TPM_ORD_GetTicks),
+    };
+    struct tpm_resp_hdr *resp;
+    fd_set readfds;
+    int n;
+    struct timeval tv = {
+        .tv_sec = 1,
+        .tv_usec = 0,
+    };
+    unsigned char buf[1024];
+
+    n = write(fd, &req, sizeof(req));
+    if (n < 0) {
+        return errno;
+    }
+    if (n != sizeof(req)) {
+        return EFAULT;
+    }
+
+    FD_ZERO(&readfds);
+    FD_SET(fd, &readfds);
+
+    /* wait for a second */
+    n = select(fd + 1, &readfds, NULL, NULL, &tv);
+    if (n != 1) {
+        return errno;
+    }
+
+    n = read(fd, &buf, sizeof(buf));
+    if (n < sizeof(struct tpm_resp_hdr)) {
+        return EFAULT;
+    }
+
+    resp = (struct tpm_resp_hdr *)buf;
+    /* check the header */
+    if (be16_to_cpu(resp->tag) != TPM_TAG_RSP_COMMAND ||
+        be32_to_cpu(resp->len) != n) {
+        return EBADMSG;
+    }
+
+    return 0;
+}
+
+static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
+{
+    const char *value;
+
+    value = qemu_opt_get(opts, "path");
+    if (!value) {
+        value = TPM_PASSTHROUGH_DEFAULT_DEVICE;
+    }
+
+    tb->s.tpm_pt->tpm_dev = g_strdup(value);
+
+    tb->path = g_strdup(tb->s.tpm_pt->tpm_dev);
+
+    tb->s.tpm_pt->tpm_fd = qemu_open(tb->s.tpm_pt->tpm_dev, O_RDWR);
+    if (tb->s.tpm_pt->tpm_fd < 0) {
+        error_report("Cannot access TPM device using '%s': %s\n",
+                     tb->s.tpm_pt->tpm_dev, strerror(errno));
+        goto err_free_parameters;
+    }
+
+    if (tpm_passthrough_test_tpmdev(tb->s.tpm_pt->tpm_fd)) {
+        error_report("'%s' is not a TPM device.\n",
+                     tb->s.tpm_pt->tpm_dev);
+        goto err_close_tpmdev;
+    }
+
+    return 0;
+
+ err_close_tpmdev:
+    qemu_close(tb->s.tpm_pt->tpm_fd);
+    tb->s.tpm_pt->tpm_fd = -1;
+
+ err_free_parameters:
+    g_free(tb->path);
+    tb->path = NULL;
+
+    g_free(tb->s.tpm_pt->tpm_dev);
+    tb->s.tpm_pt->tpm_dev = NULL;
+
+    return 1;
+}
+
+static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
+{
+    TPMBackend *tb;
+
+    tb = g_new0(TPMBackend, 1);
+    tb->s.tpm_pt = g_new0(TPMPassthruState, 1);
+    tb->id = g_strdup(id);
+    /* let frontend set the fe_model to proper value */
+    tb->fe_model = -1;
+
+    tb->ops = &tpm_passthrough_driver;
+
+    if (tpm_passthrough_handle_device_opts(opts, tb)) {
+        goto err_exit;
+    }
+
+    return tb;
+
+err_exit:
+    g_free(tb->id);
+    g_free(tb->s.tpm_pt);
+    g_free(tb);
+
+    return NULL;
+}
+
+static void tpm_passthrough_destroy(TPMBackend *tb)
+{
+    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+
+    tpm_backend_thread_end(&tpm_pt->tbt);
+
+    qemu_close(tpm_pt->tpm_fd);
+
+    g_free(tb->id);
+    g_free(tb->path);
+    g_free(tb->s.tpm_pt->tpm_dev);
+    g_free(tb->s.tpm_pt);
+    g_free(tb);
+}
+
+const TPMDriverOps tpm_passthrough_driver = {
+    .type                     = TPM_TYPE_PASSTHROUGH,
+    .desc                     = tpm_passthrough_create_desc,
+    .create                   = tpm_passthrough_create,
+    .destroy                  = tpm_passthrough_destroy,
+    .init                     = tpm_passthrough_init,
+    .startup_tpm              = tpm_passthrough_startup_tpm,
+    .realloc_buffer           = tpm_passthrough_realloc_buffer,
+    .reset                    = tpm_passthrough_reset,
+    .had_startup_error        = tpm_passthrough_get_startup_error,
+    .deliver_request          = tpm_passthrough_deliver_request,
+    .cancel_cmd               = tpm_passthrough_cancel_cmd,
+    .get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag,
+};
+
+static void tpm_passthrough_register(void)
+{
+    tpm_register_driver(&tpm_passthrough_driver);
+}
+
+type_init(tpm_passthrough_register)
commit ab214c2960e3a6d2a86b1ff53e9ba2505d173f93
Author: Stefan Berger <stefanb at linux.vnet.ibm.com>
Date:   Wed Feb 27 12:47:52 2013 -0500

    Build the TPM frontend code
    
    Build the TPM frontend code that has been added so far.
    
    Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
    Reviewed-by: Corey Bryant <coreyb at linux.vnet.ibm.com>
    Reviewed-by: Joel Schopp <jschopp at linux.vnet.ibm.com>
    Message-id: 1361987275-26289-5-git-send-email-stefanb at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index 84317c6..a382ff2 100755
--- a/configure
+++ b/configure
@@ -228,6 +228,7 @@ glusterfs=""
 virtio_blk_data_plane=""
 gtk=""
 gtkabi="2.0"
+tpm="no"
 
 # parse CC options first
 for opt do
@@ -905,6 +906,8 @@ for opt do
   ;;
   --with-gtkabi=*) gtkabi="$optarg"
   ;;
+  --enable-tpm) tpm="yes"
+  ;;
   *) echo "ERROR: unknown option $opt"; show_help="yes"
   ;;
   esac
@@ -1160,6 +1163,7 @@ echo "  --enable-glusterfs       enable GlusterFS backend"
 echo "  --disable-glusterfs      disable GlusterFS backend"
 echo "  --enable-gcov            enable test coverage analysis with gcov"
 echo "  --gcov=GCOV              use specified gcov [$gcov_tool]"
+echo "  --enable-tpm             enable TPM support"
 echo ""
 echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
@@ -3420,6 +3424,7 @@ echo "GlusterFS support $glusterfs"
 echo "virtio-blk-data-plane $virtio_blk_data_plane"
 echo "gcov              $gcov_tool"
 echo "gcov enabled      $gcov"
+echo "TPM support       $tpm"
 
 if test "$sdl_too_old" = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -4329,6 +4334,12 @@ if test "$gprof" = "yes" ; then
   fi
 fi
 
+if test "$tpm" = "yes"; then
+  if test "$target_softmmu" = "yes" ; then
+    echo "CONFIG_TPM=y" >> $config_host_mak
+  fi
+fi
+
 if test "$ARCH" = "tci"; then
   linker_script=""
 else
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 1b23025..f70594d 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -26,3 +26,4 @@ CONFIG_HPET=y
 CONFIG_APPLESMC=y
 CONFIG_I8259=y
 CONFIG_PFLASH_CFI01=y
+CONFIG_TPM_TIS=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 3392f5a..66c4855 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -26,3 +26,4 @@ CONFIG_HPET=y
 CONFIG_APPLESMC=y
 CONFIG_I8259=y
 CONFIG_PFLASH_CFI01=y
+CONFIG_TPM_TIS=y
diff --git a/tpm/Makefile.objs b/tpm/Makefile.objs
index dffb567..94ad2e7 100644
--- a/tpm/Makefile.objs
+++ b/tpm/Makefile.objs
@@ -1 +1,4 @@
 common-obj-y = tpm.o
+ifeq ($(CONFIG_TPM),y)
+common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o
+endif
commit 8db7c4152188a13b4de6fbab158d61e5dd50e7ec
Author: Stefan Berger <stefanb at linux.vnet.ibm.com>
Date:   Wed Feb 27 12:47:51 2013 -0500

    Add a debug register
    
    This patch uses the possibility to add a vendor-specific register and
    adds a debug register useful for dumping the TIS's internal state. This
    register is only active in a debug build (#define DEBUG_TIS).
    
    Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
    Reviewed-by: Corey Bryant <coreyb at linux.vnet.ibm.com>
    Reviewed-by: Joel Schopp <jschopp at linux.vnet.ibm.com>
    Message-id: 1361987275-26289-4-git-send-email-stefanb at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/tpm/tpm_tis.c b/tpm/tpm_tis.c
index 5386e18..e93825e 100644
--- a/tpm/tpm_tis.c
+++ b/tpm/tpm_tis.c
@@ -52,6 +52,9 @@
 #define TPM_TIS_REG_DID_VID               0xf00
 #define TPM_TIS_REG_RID                   0xf04
 
+/* vendor-specific registers */
+#define TPM_TIS_REG_DEBUG                 0xf90
+
 #define TPM_TIS_STS_VALID                 (1 << 7)
 #define TPM_TIS_STS_COMMAND_READY         (1 << 6)
 #define TPM_TIS_STS_TPM_GO                (1 << 5)
@@ -105,6 +108,11 @@
 
 #define TPM_TIS_NO_DATA_BYTE  0xff
 
+/* local prototypes */
+
+static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
+                                  unsigned size);
+
 /* utility functions */
 
 static uint8_t tpm_tis_locality_from_addr(hwaddr addr)
@@ -346,6 +354,63 @@ static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty)
     return ret;
 }
 
+#ifdef DEBUG_TIS
+static void tpm_tis_dump_state(void *opaque, hwaddr addr)
+{
+    static const unsigned regs[] = {
+        TPM_TIS_REG_ACCESS,
+        TPM_TIS_REG_INT_ENABLE,
+        TPM_TIS_REG_INT_VECTOR,
+        TPM_TIS_REG_INT_STATUS,
+        TPM_TIS_REG_INTF_CAPABILITY,
+        TPM_TIS_REG_STS,
+        TPM_TIS_REG_DID_VID,
+        TPM_TIS_REG_RID,
+        0xfff};
+    int idx;
+    uint8_t locty = tpm_tis_locality_from_addr(addr);
+    hwaddr base = addr & ~0xfff;
+    TPMState *s = opaque;
+    TPMTISEmuState *tis = &s->s.tis;
+
+    DPRINTF("tpm_tis: active locality      : %d\n"
+            "tpm_tis: state of locality %d : %d\n"
+            "tpm_tis: register dump:\n",
+            tis->active_locty,
+            locty, tis->loc[locty].state);
+
+    for (idx = 0; regs[idx] != 0xfff; idx++) {
+        DPRINTF("tpm_tis: 0x%04x : 0x%08x\n", regs[idx],
+                (uint32_t)tpm_tis_mmio_read(opaque, base + regs[idx], 4));
+    }
+
+    DPRINTF("tpm_tis: read offset   : %d\n"
+            "tpm_tis: result buffer : ",
+            tis->loc[locty].r_offset);
+    for (idx = 0;
+         idx < tpm_tis_get_size_from_buffer(&tis->loc[locty].r_buffer);
+         idx++) {
+        DPRINTF("%c%02x%s",
+                tis->loc[locty].r_offset == idx ? '>' : ' ',
+                tis->loc[locty].r_buffer.buffer[idx],
+                ((idx & 0xf) == 0xf) ? "\ntpm_tis:                 " : "");
+    }
+    DPRINTF("\n"
+            "tpm_tis: write offset  : %d\n"
+            "tpm_tis: request buffer: ",
+            tis->loc[locty].w_offset);
+    for (idx = 0;
+         idx < tpm_tis_get_size_from_buffer(&tis->loc[locty].w_buffer);
+         idx++) {
+        DPRINTF("%c%02x%s",
+                tis->loc[locty].w_offset == idx ? '>' : ' ',
+                tis->loc[locty].w_buffer.buffer[idx],
+                ((idx & 0xf) == 0xf) ? "\ntpm_tis:                 " : "");
+    }
+    DPRINTF("\n");
+}
+#endif
+
 /*
  * Read a register of the TIS interface
  * See specs pages 33-63 for description of the registers
@@ -425,6 +490,11 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
     case TPM_TIS_REG_RID:
         val = TPM_TIS_TPM_RID;
         break;
+#ifdef DEBUG_TIS
+    case TPM_TIS_REG_DEBUG:
+        tpm_tis_dump_state(opaque, addr);
+        break;
+#endif
     }
 
     if (shift) {
commit edff867807fefd9b8cc2bfd0e88a957987225f55
Author: Stefan Berger <stefanb at linux.vnet.ibm.com>
Date:   Wed Feb 27 12:47:50 2013 -0500

    Add TPM (frontend) hardware interface (TPM TIS) to QEMU
    
    This patch adds the main code of the TPM frontend driver, the TPM TIS
    interface, to QEMU. The code is largely based on the previous implementation
    for Xen but has been significantly extended to meet the standard's
    requirements, such as the support for changing of localities and all the
    functionality of the available flags.
    
    Communication with the backend (i.e., for Xen or the libtpms-based one)
    is cleanly separated through an interface which the backend driver needs
    to implement.
    
    Whenever the frontend has collected a complete packet, it will submit
    a task to the backend, which then starts processing the command. Once
    the result has been returned, the backend invokes a callback function
    (tpm_tis_receive_cb()).
    
    Testing the proper functioning of the different flags and localities
    cannot be done from user space when running in Linux for example, since
    access to the address space of the TPM TIS interface is not possible. Also
    the Linux driver itself does not exercise all functionality. So, for
    testing there is a fairly extensive test suite as part of the SeaBIOS patches
    since from within the BIOS one can have full access to all the TPM's registers.
    
    Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
    Reviewed-by: Corey Bryant <coreyb at linux.vnet.ibm.com>
    Reviewed-by: Joel Schopp <jschopp at linux.vnet.ibm.com>
    Message-id: 1361987275-26289-3-git-send-email-stefanb at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/tpm/tpm_tis.c b/tpm/tpm_tis.c
new file mode 100644
index 0000000..5386e18
--- /dev/null
+++ b/tpm/tpm_tis.c
@@ -0,0 +1,859 @@
+/*
+ * tpm_tis.c - QEMU's TPM TIS interface emulator
+ *
+ * Copyright (C) 2006,2010-2013 IBM Corporation
+ *
+ * Authors:
+ *  Stefan Berger <stefanb at us.ibm.com>
+ *  David Safford <safford at us.ibm.com>
+ *
+ * Xen 4 support: Andrease Niederl <andreas.niederl at iaik.tugraz.at>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * Implementation of the TIS interface according to specs found at
+ * http://www.trustedcomputinggroup.org. This implementation currently
+ * supports version 1.21, revision 1.0.
+ * In the developers menu choose the PC Client section then find the TIS
+ * specification.
+ */
+
+#include "tpm_int.h"
+#include "block/block.h"
+#include "exec/address-spaces.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/pci/pci_ids.h"
+#include "tpm/tpm_tis.h"
+#include "qemu-common.h"
+
+/*#define DEBUG_TIS */
+
+#ifdef DEBUG_TIS
+#define DPRINTF(fmt, ...) \
+    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+    do { } while (0)
+#endif
+
+/* whether the STS interrupt is supported */
+#define RAISE_STS_IRQ
+
+/* tis registers */
+#define TPM_TIS_REG_ACCESS                0x00
+#define TPM_TIS_REG_INT_ENABLE            0x08
+#define TPM_TIS_REG_INT_VECTOR            0x0c
+#define TPM_TIS_REG_INT_STATUS            0x10
+#define TPM_TIS_REG_INTF_CAPABILITY       0x14
+#define TPM_TIS_REG_STS                   0x18
+#define TPM_TIS_REG_DATA_FIFO             0x24
+#define TPM_TIS_REG_DID_VID               0xf00
+#define TPM_TIS_REG_RID                   0xf04
+
+#define TPM_TIS_STS_VALID                 (1 << 7)
+#define TPM_TIS_STS_COMMAND_READY         (1 << 6)
+#define TPM_TIS_STS_TPM_GO                (1 << 5)
+#define TPM_TIS_STS_DATA_AVAILABLE        (1 << 4)
+#define TPM_TIS_STS_EXPECT                (1 << 3)
+#define TPM_TIS_STS_RESPONSE_RETRY        (1 << 1)
+
+#define TPM_TIS_BURST_COUNT_SHIFT         8
+#define TPM_TIS_BURST_COUNT(X) \
+    ((X) << TPM_TIS_BURST_COUNT_SHIFT)
+
+#define TPM_TIS_ACCESS_TPM_REG_VALID_STS  (1 << 7)
+#define TPM_TIS_ACCESS_ACTIVE_LOCALITY    (1 << 5)
+#define TPM_TIS_ACCESS_BEEN_SEIZED        (1 << 4)
+#define TPM_TIS_ACCESS_SEIZE              (1 << 3)
+#define TPM_TIS_ACCESS_PENDING_REQUEST    (1 << 2)
+#define TPM_TIS_ACCESS_REQUEST_USE        (1 << 1)
+#define TPM_TIS_ACCESS_TPM_ESTABLISHMENT  (1 << 0)
+
+#define TPM_TIS_INT_ENABLED               (1 << 31)
+#define TPM_TIS_INT_DATA_AVAILABLE        (1 << 0)
+#define TPM_TIS_INT_STS_VALID             (1 << 1)
+#define TPM_TIS_INT_LOCALITY_CHANGED      (1 << 2)
+#define TPM_TIS_INT_COMMAND_READY         (1 << 7)
+
+#define TPM_TIS_INT_POLARITY_MASK         (3 << 3)
+#define TPM_TIS_INT_POLARITY_LOW_LEVEL    (1 << 3)
+
+#ifndef RAISE_STS_IRQ
+
+#define TPM_TIS_INTERRUPTS_SUPPORTED (TPM_TIS_INT_LOCALITY_CHANGED | \
+                                      TPM_TIS_INT_DATA_AVAILABLE   | \
+                                      TPM_TIS_INT_COMMAND_READY)
+
+#else
+
+#define TPM_TIS_INTERRUPTS_SUPPORTED (TPM_TIS_INT_LOCALITY_CHANGED | \
+                                      TPM_TIS_INT_DATA_AVAILABLE   | \
+                                      TPM_TIS_INT_STS_VALID | \
+                                      TPM_TIS_INT_COMMAND_READY)
+
+#endif
+
+#define TPM_TIS_CAP_INTERRUPT_LOW_LEVEL  (1 << 4) /* support is mandatory */
+#define TPM_TIS_CAPABILITIES_SUPPORTED   (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \
+                                          TPM_TIS_INTERRUPTS_SUPPORTED)
+
+#define TPM_TIS_TPM_DID       0x0001
+#define TPM_TIS_TPM_VID       PCI_VENDOR_ID_IBM
+#define TPM_TIS_TPM_RID       0x0001
+
+#define TPM_TIS_NO_DATA_BYTE  0xff
+
+/* utility functions */
+
+static uint8_t tpm_tis_locality_from_addr(hwaddr addr)
+{
+    return (uint8_t)((addr >> TPM_TIS_LOCALITY_SHIFT) & 0x7);
+}
+
+static uint32_t tpm_tis_get_size_from_buffer(const TPMSizedBuffer *sb)
+{
+    return be32_to_cpu(*(uint32_t *)&sb->buffer[2]);
+}
+
+static void tpm_tis_show_buffer(const TPMSizedBuffer *sb, const char *string)
+{
+#ifdef DEBUG_TIS
+    uint32_t len, i;
+
+    len = tpm_tis_get_size_from_buffer(sb);
+    DPRINTF("tpm_tis: %s length = %d\n", string, len);
+    for (i = 0; i < len; i++) {
+        if (i && !(i % 16)) {
+            DPRINTF("\n");
+        }
+        DPRINTF("%.2X ", sb->buffer[i]);
+    }
+    DPRINTF("\n");
+#endif
+}
+
+/*
+ * Send a request to the TPM.
+ */
+static void tpm_tis_tpm_send(TPMState *s, uint8_t locty)
+{
+    TPMTISEmuState *tis = &s->s.tis;
+
+    tpm_tis_show_buffer(&tis->loc[locty].w_buffer, "tpm_tis: To TPM");
+
+    s->locty_number = locty;
+    s->locty_data = &tis->loc[locty];
+
+    /*
+     * w_offset serves as length indicator for length of data;
+     * it's reset when the response comes back
+     */
+    tis->loc[locty].state = TPM_TIS_STATE_EXECUTION;
+
+    s->be_driver->ops->deliver_request(s->be_driver);
+}
+
+/* raise an interrupt if allowed */
+static void tpm_tis_raise_irq(TPMState *s, uint8_t locty, uint32_t irqmask)
+{
+    TPMTISEmuState *tis = &s->s.tis;
+
+    if (!TPM_TIS_IS_VALID_LOCTY(locty)) {
+        return;
+    }
+
+    if ((tis->loc[locty].inte & TPM_TIS_INT_ENABLED) &&
+        (tis->loc[locty].inte & irqmask)) {
+        DPRINTF("tpm_tis: Raising IRQ for flag %08x\n", irqmask);
+        qemu_irq_raise(s->s.tis.irq);
+        tis->loc[locty].ints |= irqmask;
+    }
+}
+
+static uint32_t tpm_tis_check_request_use_except(TPMState *s, uint8_t locty)
+{
+    uint8_t l;
+
+    for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) {
+        if (l == locty) {
+            continue;
+        }
+        if ((s->s.tis.loc[l].access & TPM_TIS_ACCESS_REQUEST_USE)) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+static void tpm_tis_new_active_locality(TPMState *s, uint8_t new_active_locty)
+{
+    TPMTISEmuState *tis = &s->s.tis;
+    bool change = (s->s.tis.active_locty != new_active_locty);
+    bool is_seize;
+    uint8_t mask;
+
+    if (change && TPM_TIS_IS_VALID_LOCTY(s->s.tis.active_locty)) {
+        is_seize = TPM_TIS_IS_VALID_LOCTY(new_active_locty) &&
+                   tis->loc[new_active_locty].access & TPM_TIS_ACCESS_SEIZE;
+
+        if (is_seize) {
+            mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY);
+        } else {
+            mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY|
+                     TPM_TIS_ACCESS_REQUEST_USE);
+        }
+        /* reset flags on the old active locality */
+        tis->loc[s->s.tis.active_locty].access &= mask;
+
+        if (is_seize) {
+            tis->loc[tis->active_locty].access |= TPM_TIS_ACCESS_BEEN_SEIZED;
+        }
+    }
+
+    tis->active_locty = new_active_locty;
+
+    DPRINTF("tpm_tis: Active locality is now %d\n", s->s.tis.active_locty);
+
+    if (TPM_TIS_IS_VALID_LOCTY(new_active_locty)) {
+        /* set flags on the new active locality */
+        tis->loc[new_active_locty].access |= TPM_TIS_ACCESS_ACTIVE_LOCALITY;
+        tis->loc[new_active_locty].access &= ~(TPM_TIS_ACCESS_REQUEST_USE |
+                                               TPM_TIS_ACCESS_SEIZE);
+    }
+
+    if (change) {
+        tpm_tis_raise_irq(s, tis->active_locty, TPM_TIS_INT_LOCALITY_CHANGED);
+    }
+}
+
+/* abort -- this function switches the locality */
+static void tpm_tis_abort(TPMState *s, uint8_t locty)
+{
+    TPMTISEmuState *tis = &s->s.tis;
+
+    tis->loc[locty].r_offset = 0;
+    tis->loc[locty].w_offset = 0;
+
+    DPRINTF("tpm_tis: tis_abort: new active locality is %d\n", tis->next_locty);
+
+    /*
+     * Need to react differently depending on who's aborting now and
+     * which locality will become active afterwards.
+     */
+    if (tis->aborting_locty == tis->next_locty) {
+        tis->loc[tis->aborting_locty].state = TPM_TIS_STATE_READY;
+        tis->loc[tis->aborting_locty].sts = TPM_TIS_STS_COMMAND_READY;
+        tpm_tis_raise_irq(s, tis->aborting_locty, TPM_TIS_INT_COMMAND_READY);
+    }
+
+    /* locality after abort is another one than the current one */
+    tpm_tis_new_active_locality(s, tis->next_locty);
+
+    tis->next_locty = TPM_TIS_NO_LOCALITY;
+    /* nobody's aborting a command anymore */
+    tis->aborting_locty = TPM_TIS_NO_LOCALITY;
+}
+
+/* prepare aborting current command */
+static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty)
+{
+    TPMTISEmuState *tis = &s->s.tis;
+    uint8_t busy_locty;
+
+    tis->aborting_locty = locty;
+    tis->next_locty = newlocty;  /* locality after successful abort */
+
+    /*
+     * only abort a command using an interrupt if currently executing
+     * a command AND if there's a valid connection to the vTPM.
+     */
+    for (busy_locty = 0; busy_locty < TPM_TIS_NUM_LOCALITIES; busy_locty++) {
+        if (tis->loc[busy_locty].state == TPM_TIS_STATE_EXECUTION) {
+            /*
+             * request the backend to cancel. Some backends may not
+             * support it
+             */
+            s->be_driver->ops->cancel_cmd(s->be_driver);
+            return;
+        }
+    }
+
+    tpm_tis_abort(s, locty);
+}
+
+static void tpm_tis_receive_bh(void *opaque)
+{
+    TPMState *s = opaque;
+    TPMTISEmuState *tis = &s->s.tis;
+    uint8_t locty = s->locty_number;
+
+    tis->loc[locty].sts = TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE;
+    tis->loc[locty].state = TPM_TIS_STATE_COMPLETION;
+    tis->loc[locty].r_offset = 0;
+    tis->loc[locty].w_offset = 0;
+
+    if (TPM_TIS_IS_VALID_LOCTY(tis->next_locty)) {
+        tpm_tis_abort(s, locty);
+    }
+
+#ifndef RAISE_STS_IRQ
+    tpm_tis_raise_irq(s, locty, TPM_TIS_INT_DATA_AVAILABLE);
+#else
+    tpm_tis_raise_irq(s, locty,
+                      TPM_TIS_INT_DATA_AVAILABLE | TPM_TIS_INT_STS_VALID);
+#endif
+}
+
+/*
+ * Callback from the TPM to indicate that the response was received.
+ */
+static void tpm_tis_receive_cb(TPMState *s, uint8_t locty)
+{
+    TPMTISEmuState *tis = &s->s.tis;
+
+    assert(s->locty_number == locty);
+
+    qemu_bh_schedule(tis->bh);
+}
+
+/*
+ * Read a byte of response data
+ */
+static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty)
+{
+    TPMTISEmuState *tis = &s->s.tis;
+    uint32_t ret = TPM_TIS_NO_DATA_BYTE;
+    uint16_t len;
+
+    if ((tis->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {
+        len = tpm_tis_get_size_from_buffer(&tis->loc[locty].r_buffer);
+
+        ret = tis->loc[locty].r_buffer.buffer[tis->loc[locty].r_offset++];
+        if (tis->loc[locty].r_offset >= len) {
+            /* got last byte */
+            tis->loc[locty].sts = TPM_TIS_STS_VALID;
+#ifdef RAISE_STS_IRQ
+            tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID);
+#endif
+        }
+        DPRINTF("tpm_tis: tpm_tis_data_read byte 0x%02x   [%d]\n",
+                ret, tis->loc[locty].r_offset-1);
+    }
+
+    return ret;
+}
+
+/*
+ * Read a register of the TIS interface
+ * See specs pages 33-63 for description of the registers
+ */
+static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
+                                  unsigned size)
+{
+    TPMState *s = opaque;
+    TPMTISEmuState *tis = &s->s.tis;
+    uint16_t offset = addr & 0xffc;
+    uint8_t shift = (addr & 0x3) * 8;
+    uint32_t val = 0xffffffff;
+    uint8_t locty = tpm_tis_locality_from_addr(addr);
+    uint32_t avail;
+
+    if (s->be_driver->ops->had_startup_error(s->be_driver)) {
+        return val;
+    }
+
+    switch (offset) {
+    case TPM_TIS_REG_ACCESS:
+        /* never show the SEIZE flag even though we use it internally */
+        val = tis->loc[locty].access & ~TPM_TIS_ACCESS_SEIZE;
+        /* the pending flag is always calculated */
+        if (tpm_tis_check_request_use_except(s, locty)) {
+            val |= TPM_TIS_ACCESS_PENDING_REQUEST;
+        }
+        val |= !s->be_driver->ops->get_tpm_established_flag(s->be_driver);
+        break;
+    case TPM_TIS_REG_INT_ENABLE:
+        val = tis->loc[locty].inte;
+        break;
+    case TPM_TIS_REG_INT_VECTOR:
+        val = tis->irq_num;
+        break;
+    case TPM_TIS_REG_INT_STATUS:
+        val = tis->loc[locty].ints;
+        break;
+    case TPM_TIS_REG_INTF_CAPABILITY:
+        val = TPM_TIS_CAPABILITIES_SUPPORTED;
+        break;
+    case TPM_TIS_REG_STS:
+        if (tis->active_locty == locty) {
+            if ((tis->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {
+                val = TPM_TIS_BURST_COUNT(
+                       tpm_tis_get_size_from_buffer(&tis->loc[locty].r_buffer)
+                       - tis->loc[locty].r_offset) | tis->loc[locty].sts;
+            } else {
+                avail = tis->loc[locty].w_buffer.size
+                        - tis->loc[locty].w_offset;
+                /*
+                 * byte-sized reads should not return 0x00 for 0x100
+                 * available bytes.
+                 */
+                if (size == 1 && avail > 0xff) {
+                    avail = 0xff;
+                }
+                val = TPM_TIS_BURST_COUNT(avail) | tis->loc[locty].sts;
+            }
+        }
+        break;
+    case TPM_TIS_REG_DATA_FIFO:
+        if (tis->active_locty == locty) {
+            switch (tis->loc[locty].state) {
+            case TPM_TIS_STATE_COMPLETION:
+                val = tpm_tis_data_read(s, locty);
+                break;
+            default:
+                val = TPM_TIS_NO_DATA_BYTE;
+                break;
+            }
+        }
+        break;
+    case TPM_TIS_REG_DID_VID:
+        val = (TPM_TIS_TPM_DID << 16) | TPM_TIS_TPM_VID;
+        break;
+    case TPM_TIS_REG_RID:
+        val = TPM_TIS_TPM_RID;
+        break;
+    }
+
+    if (shift) {
+        val >>= shift;
+    }
+
+    DPRINTF("tpm_tis:  read.%u(%08x) = %08x\n", size, (int)addr, (uint32_t)val);
+
+    return val;
+}
+
+/*
+ * Write a value to a register of the TIS interface
+ * See specs pages 33-63 for description of the registers
+ */
+static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
+                                      uint64_t val, unsigned size,
+                                      bool hw_access)
+{
+    TPMState *s = opaque;
+    TPMTISEmuState *tis = &s->s.tis;
+    uint16_t off = addr & 0xfff;
+    uint8_t locty = tpm_tis_locality_from_addr(addr);
+    uint8_t active_locty, l;
+    int c, set_new_locty = 1;
+    uint16_t len;
+
+    DPRINTF("tpm_tis: write.%u(%08x) = %08x\n", size, (int)addr, (uint32_t)val);
+
+    if (locty == 4 && !hw_access) {
+        DPRINTF("tpm_tis: Access to locality 4 only allowed from hardware\n");
+        return;
+    }
+
+    if (s->be_driver->ops->had_startup_error(s->be_driver)) {
+        return;
+    }
+
+    switch (off) {
+    case TPM_TIS_REG_ACCESS:
+
+        if ((val & TPM_TIS_ACCESS_SEIZE)) {
+            val &= ~(TPM_TIS_ACCESS_REQUEST_USE |
+                     TPM_TIS_ACCESS_ACTIVE_LOCALITY);
+        }
+
+        active_locty = tis->active_locty;
+
+        if ((val & TPM_TIS_ACCESS_ACTIVE_LOCALITY)) {
+            /* give up locality if currently owned */
+            if (tis->active_locty == locty) {
+                DPRINTF("tpm_tis: Releasing locality %d\n", locty);
+
+                uint8_t newlocty = TPM_TIS_NO_LOCALITY;
+                /* anybody wants the locality ? */
+                for (c = TPM_TIS_NUM_LOCALITIES - 1; c >= 0; c--) {
+                    if ((tis->loc[c].access & TPM_TIS_ACCESS_REQUEST_USE)) {
+                        DPRINTF("tpm_tis: Locality %d requests use.\n", c);
+                        newlocty = c;
+                        break;
+                    }
+                }
+                DPRINTF("tpm_tis: TPM_TIS_ACCESS_ACTIVE_LOCALITY: "
+                        "Next active locality: %d\n",
+                        newlocty);
+
+                if (TPM_TIS_IS_VALID_LOCTY(newlocty)) {
+                    set_new_locty = 0;
+                    tpm_tis_prep_abort(s, locty, newlocty);
+                } else {
+                    active_locty = TPM_TIS_NO_LOCALITY;
+                }
+            } else {
+                /* not currently the owner; clear a pending request */
+                tis->loc[locty].access &= ~TPM_TIS_ACCESS_REQUEST_USE;
+            }
+        }
+
+        if ((val & TPM_TIS_ACCESS_BEEN_SEIZED)) {
+            tis->loc[locty].access &= ~TPM_TIS_ACCESS_BEEN_SEIZED;
+        }
+
+        if ((val & TPM_TIS_ACCESS_SEIZE)) {
+            /*
+             * allow seize if a locality is active and the requesting
+             * locality is higher than the one that's active
+             * OR
+             * allow seize for requesting locality if no locality is
+             * active
+             */
+            while ((TPM_TIS_IS_VALID_LOCTY(tis->active_locty) &&
+                    locty > tis->active_locty) ||
+                    !TPM_TIS_IS_VALID_LOCTY(tis->active_locty)) {
+                bool higher_seize = FALSE;
+
+                /* already a pending SEIZE ? */
+                if ((tis->loc[locty].access & TPM_TIS_ACCESS_SEIZE)) {
+                    break;
+                }
+
+                /* check for ongoing seize by a higher locality */
+                for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES; l++) {
+                    if ((tis->loc[l].access & TPM_TIS_ACCESS_SEIZE)) {
+                        higher_seize = TRUE;
+                        break;
+                    }
+                }
+
+                if (higher_seize) {
+                    break;
+                }
+
+                /* cancel any seize by a lower locality */
+                for (l = 0; l < locty - 1; l++) {
+                    tis->loc[l].access &= ~TPM_TIS_ACCESS_SEIZE;
+                }
+
+                tis->loc[locty].access |= TPM_TIS_ACCESS_SEIZE;
+                DPRINTF("tpm_tis: TPM_TIS_ACCESS_SEIZE: "
+                        "Locality %d seized from locality %d\n",
+                        locty, tis->active_locty);
+                DPRINTF("tpm_tis: TPM_TIS_ACCESS_SEIZE: Initiating abort.\n");
+                set_new_locty = 0;
+                tpm_tis_prep_abort(s, tis->active_locty, locty);
+                break;
+            }
+        }
+
+        if ((val & TPM_TIS_ACCESS_REQUEST_USE)) {
+            if (tis->active_locty != locty) {
+                if (TPM_TIS_IS_VALID_LOCTY(tis->active_locty)) {
+                    tis->loc[locty].access |= TPM_TIS_ACCESS_REQUEST_USE;
+                } else {
+                    /* no locality active -> make this one active now */
+                    active_locty = locty;
+                }
+            }
+        }
+
+        if (set_new_locty) {
+            tpm_tis_new_active_locality(s, active_locty);
+        }
+
+        break;
+    case TPM_TIS_REG_INT_ENABLE:
+        if (tis->active_locty != locty) {
+            break;
+        }
+
+        tis->loc[locty].inte = (val & (TPM_TIS_INT_ENABLED |
+                                       TPM_TIS_INT_POLARITY_MASK |
+                                       TPM_TIS_INTERRUPTS_SUPPORTED));
+        break;
+    case TPM_TIS_REG_INT_VECTOR:
+        /* hard wired -- ignore */
+        break;
+    case TPM_TIS_REG_INT_STATUS:
+        if (tis->active_locty != locty) {
+            break;
+        }
+
+        /* clearing of interrupt flags */
+        if (((val & TPM_TIS_INTERRUPTS_SUPPORTED)) &&
+            (tis->loc[locty].ints & TPM_TIS_INTERRUPTS_SUPPORTED)) {
+            tis->loc[locty].ints &= ~val;
+            if (tis->loc[locty].ints == 0) {
+                qemu_irq_lower(tis->irq);
+                DPRINTF("tpm_tis: Lowering IRQ\n");
+            }
+        }
+        tis->loc[locty].ints &= ~(val & TPM_TIS_INTERRUPTS_SUPPORTED);
+        break;
+    case TPM_TIS_REG_STS:
+        if (tis->active_locty != locty) {
+            break;
+        }
+
+        val &= (TPM_TIS_STS_COMMAND_READY | TPM_TIS_STS_TPM_GO |
+                TPM_TIS_STS_RESPONSE_RETRY);
+
+        if (val == TPM_TIS_STS_COMMAND_READY) {
+            switch (tis->loc[locty].state) {
+
+            case TPM_TIS_STATE_READY:
+                tis->loc[locty].w_offset = 0;
+                tis->loc[locty].r_offset = 0;
+            break;
+
+            case TPM_TIS_STATE_IDLE:
+                tis->loc[locty].sts = TPM_TIS_STS_COMMAND_READY;
+                tis->loc[locty].state = TPM_TIS_STATE_READY;
+                tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY);
+            break;
+
+            case TPM_TIS_STATE_EXECUTION:
+            case TPM_TIS_STATE_RECEPTION:
+                /* abort currently running command */
+                DPRINTF("tpm_tis: %s: Initiating abort.\n",
+                        __func__);
+                tpm_tis_prep_abort(s, locty, locty);
+            break;
+
+            case TPM_TIS_STATE_COMPLETION:
+                tis->loc[locty].w_offset = 0;
+                tis->loc[locty].r_offset = 0;
+                /* shortcut to ready state with C/R set */
+                tis->loc[locty].state = TPM_TIS_STATE_READY;
+                if (!(tis->loc[locty].sts & TPM_TIS_STS_COMMAND_READY)) {
+                    tis->loc[locty].sts   = TPM_TIS_STS_COMMAND_READY;
+                    tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY);
+                }
+                tis->loc[locty].sts &= ~(TPM_TIS_STS_DATA_AVAILABLE);
+            break;
+
+            }
+        } else if (val == TPM_TIS_STS_TPM_GO) {
+            switch (tis->loc[locty].state) {
+            case TPM_TIS_STATE_RECEPTION:
+                if ((tis->loc[locty].sts & TPM_TIS_STS_EXPECT) == 0) {
+                    tpm_tis_tpm_send(s, locty);
+                }
+                break;
+            default:
+                /* ignore */
+                break;
+            }
+        } else if (val == TPM_TIS_STS_RESPONSE_RETRY) {
+            switch (tis->loc[locty].state) {
+            case TPM_TIS_STATE_COMPLETION:
+                tis->loc[locty].r_offset = 0;
+                tis->loc[locty].sts = TPM_TIS_STS_VALID |
+                                      TPM_TIS_STS_DATA_AVAILABLE;
+                break;
+            default:
+                /* ignore */
+                break;
+            }
+        }
+        break;
+    case TPM_TIS_REG_DATA_FIFO:
+        /* data fifo */
+        if (tis->active_locty != locty) {
+            break;
+        }
+
+        if (tis->loc[locty].state == TPM_TIS_STATE_IDLE ||
+            tis->loc[locty].state == TPM_TIS_STATE_EXECUTION ||
+            tis->loc[locty].state == TPM_TIS_STATE_COMPLETION) {
+            /* drop the byte */
+        } else {
+            DPRINTF("tpm_tis: Byte to send to TPM: %02x\n", (uint8_t)val);
+            if (tis->loc[locty].state == TPM_TIS_STATE_READY) {
+                tis->loc[locty].state = TPM_TIS_STATE_RECEPTION;
+                tis->loc[locty].sts = TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID;
+            }
+
+            if ((tis->loc[locty].sts & TPM_TIS_STS_EXPECT)) {
+                if (tis->loc[locty].w_offset < tis->loc[locty].w_buffer.size) {
+                    tis->loc[locty].w_buffer.
+                        buffer[tis->loc[locty].w_offset++] = (uint8_t)val;
+                } else {
+                    tis->loc[locty].sts = TPM_TIS_STS_VALID;
+                }
+            }
+
+            /* check for complete packet */
+            if (tis->loc[locty].w_offset > 5 &&
+                (tis->loc[locty].sts & TPM_TIS_STS_EXPECT)) {
+                /* we have a packet length - see if we have all of it */
+#ifdef RAISE_STS_IRQ
+                bool needIrq = !(tis->loc[locty].sts & TPM_TIS_STS_VALID);
+#endif
+                len = tpm_tis_get_size_from_buffer(&tis->loc[locty].w_buffer);
+                if (len > tis->loc[locty].w_offset) {
+                    tis->loc[locty].sts = TPM_TIS_STS_EXPECT |
+                                          TPM_TIS_STS_VALID;
+                } else {
+                    /* packet complete */
+                    tis->loc[locty].sts = TPM_TIS_STS_VALID;
+                }
+#ifdef RAISE_STS_IRQ
+                if (needIrq) {
+                    tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID);
+                }
+#endif
+            }
+        }
+        break;
+    }
+}
+
+static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
+                               uint64_t val, unsigned size)
+{
+    return tpm_tis_mmio_write_intern(opaque, addr, val, size, false);
+}
+
+static const MemoryRegionOps tpm_tis_memory_ops = {
+    .read = tpm_tis_mmio_read,
+    .write = tpm_tis_mmio_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+static int tpm_tis_do_startup_tpm(TPMState *s)
+{
+    return s->be_driver->ops->startup_tpm(s->be_driver);
+}
+
+/*
+ * This function is called when the machine starts, resets or due to
+ * S3 resume.
+ */
+static void tpm_tis_reset(DeviceState *dev)
+{
+    TPMState *s = TPM(dev);
+    TPMTISEmuState *tis = &s->s.tis;
+    int c;
+
+    s->be_driver->ops->reset(s->be_driver);
+
+    tis->active_locty = TPM_TIS_NO_LOCALITY;
+    tis->next_locty = TPM_TIS_NO_LOCALITY;
+    tis->aborting_locty = TPM_TIS_NO_LOCALITY;
+
+    for (c = 0; c < TPM_TIS_NUM_LOCALITIES; c++) {
+        tis->loc[c].access = TPM_TIS_ACCESS_TPM_REG_VALID_STS;
+        tis->loc[c].sts = 0;
+        tis->loc[c].inte = TPM_TIS_INT_POLARITY_LOW_LEVEL;
+        tis->loc[c].ints = 0;
+        tis->loc[c].state = TPM_TIS_STATE_IDLE;
+
+        tis->loc[c].w_offset = 0;
+        s->be_driver->ops->realloc_buffer(&tis->loc[c].w_buffer);
+        tis->loc[c].r_offset = 0;
+        s->be_driver->ops->realloc_buffer(&tis->loc[c].r_buffer);
+    }
+
+    tpm_tis_do_startup_tpm(s);
+}
+
+static const VMStateDescription vmstate_tpm_tis = {
+    .name = "tpm",
+    .unmigratable = 1,
+};
+
+static Property tpm_tis_properties[] = {
+    DEFINE_PROP_UINT32("irq", TPMState,
+                       s.tis.irq_num, TPM_TIS_IRQ),
+    DEFINE_PROP_STRING("tpmdev", TPMState, backend),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void tpm_tis_realizefn(DeviceState *dev, Error **errp)
+{
+    TPMState *s = TPM(dev);
+    TPMTISEmuState *tis = &s->s.tis;
+
+    s->be_driver = qemu_find_tpm(s->backend);
+    if (!s->be_driver) {
+        error_setg(errp, "tpm_tis: backend driver with id %s could not be "
+                   "found", s->backend);
+        return;
+    }
+
+    s->be_driver->fe_model = TPM_MODEL_TPM_TIS;
+
+    if (s->be_driver->ops->init(s->be_driver, s, tpm_tis_receive_cb)) {
+        error_setg(errp, "tpm_tis: backend driver with id %s could not be "
+                   "initialized", s->backend);
+        return;
+    }
+
+    if (tis->irq_num > 15) {
+        error_setg(errp, "tpm_tis: IRQ %d for TPM TIS is outside valid range "
+                   "of 0 to 15.\n", tis->irq_num);
+        return;
+    }
+
+    tis->bh = qemu_bh_new(tpm_tis_receive_bh, s);
+
+    isa_init_irq(&s->busdev, &tis->irq, tis->irq_num);
+}
+
+static void tpm_tis_initfn(Object *obj)
+{
+    ISADevice *dev = ISA_DEVICE(obj);
+    TPMState *s = TPM(obj);
+
+    memory_region_init_io(&s->mmio, &tpm_tis_memory_ops, s, "tpm-tis-mmio",
+                          TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT);
+    memory_region_add_subregion(isa_address_space(dev), TPM_TIS_ADDR_BASE,
+                                &s->mmio);
+}
+
+static void tpm_tis_uninitfn(Object *obj)
+{
+    TPMState *s = TPM(obj);
+
+    memory_region_del_subregion(get_system_memory(), &s->mmio);
+    memory_region_destroy(&s->mmio);
+}
+
+static void tpm_tis_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = tpm_tis_realizefn;
+    dc->props = tpm_tis_properties;
+    dc->reset = tpm_tis_reset;
+    dc->vmsd  = &vmstate_tpm_tis;
+}
+
+static const TypeInfo tpm_tis_info = {
+    .name = TYPE_TPM_TIS,
+    .parent = TYPE_ISA_DEVICE,
+    .instance_size = sizeof(TPMState),
+    .instance_init = tpm_tis_initfn,
+    .instance_finalize = tpm_tis_uninitfn,
+    .class_init  = tpm_tis_class_init,
+};
+
+static void tpm_tis_register(void)
+{
+    type_register_static(&tpm_tis_info);
+    tpm_register_model(TPM_MODEL_TPM_TIS);
+}
+
+type_init(tpm_tis_register)
commit d1a0cf738dab24fbfd8e9225b7f3df43dcfafc06
Author: Stefan Berger <stefanb at linux.vnet.ibm.com>
Date:   Wed Feb 27 12:47:49 2013 -0500

    Support for TPM command line options
    
    This patch adds support for TPM command line options.
    The command line options supported here are
    
    ./qemu-... -tpmdev passthrough,path=<path to TPM device>,id=<id>
               -device tpm-tis,tpmdev=<id>,id=<other id>
    
    and
    
    ./qemu-... -tpmdev help
    
    where the latter works similar to -soundhw help and shows a list of
    available TPM backends (for example 'passthrough').
    
    Using the type parameter, the backend is chosen, i.e., 'passthrough' for the
    passthrough driver. The interpretation of the other parameters along
    with determining whether enough parameters were provided is pushed into
    the backend driver, which needs to implement the interface function
    'create' and return a TPMDriverOpts structure if the VM can be started or
    'NULL' if not enough or bad parameters were provided.
    
    Monitor support for 'info tpm' has been added. It for example prints the
    following:
    
    (qemu) info tpm
    TPM devices:
     tpm0: model=tpm-tis
      \ tpm0: type=passthrough,path=/dev/tpm0,cancel-path=/sys/devices/pnp0/00:09/cancel
    
    Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
    Reviewed-by: Corey Bryant <coreyb at linux.vnet.ibm.com>
    Reviewed-by: Joel Schopp <jschopp at linux.vnet.ibm.com>
    Message-id: 1361987275-26289-2-git-send-email-stefanb at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile.objs b/Makefile.objs
index 8c90b92..f99841c 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -74,6 +74,7 @@ common-obj-y += bt-host.o bt-vhci.o
 
 common-obj-y += dma-helpers.o
 common-obj-y += vl.o
+common-obj-y += tpm/
 
 common-obj-$(CONFIG_SLIRP) += slirp/
 
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 69c707d..4bda3fe 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1642,6 +1642,8 @@ show device tree
 show qdev device model list
 @item info roms
 show roms
+ at item info tpm
+show the TPM device
 @end table
 ETEXI
 
diff --git a/hmp.c b/hmp.c
index 2f47a8a..b0a861c 100644
--- a/hmp.c
+++ b/hmp.c
@@ -607,6 +607,50 @@ void hmp_info_block_jobs(Monitor *mon, const QDict *qdict)
     }
 }
 
+void hmp_info_tpm(Monitor *mon, const QDict *qdict)
+{
+    TPMInfoList *info_list, *info;
+    Error *err = NULL;
+    unsigned int c = 0;
+    TPMPassthroughOptions *tpo;
+
+    info_list = qmp_query_tpm(&err);
+    if (err) {
+        monitor_printf(mon, "TPM device not supported\n");
+        error_free(err);
+        return;
+    }
+
+    if (info_list) {
+        monitor_printf(mon, "TPM device:\n");
+    }
+
+    for (info = info_list; info; info = info->next) {
+        TPMInfo *ti = info->value;
+        monitor_printf(mon, " tpm%d: model=%s\n",
+                       c, TpmModel_lookup[ti->model]);
+
+        monitor_printf(mon, "  \\ %s: type=%s",
+                       ti->id, TpmType_lookup[ti->type]);
+
+        switch (ti->tpm_options->kind) {
+        case TPM_TYPE_OPTIONS_KIND_TPM_PASSTHROUGH_OPTIONS:
+            tpo = ti->tpm_options->tpm_passthrough_options;
+            monitor_printf(mon, "%s%s%s%s",
+                           tpo->has_path ? ",path=" : "",
+                           tpo->has_path ? tpo->path : "",
+                           tpo->has_cancel_path ? ",cancel-path=" : "",
+                           tpo->has_cancel_path ? tpo->cancel_path : "");
+            break;
+        case TPM_TYPE_OPTIONS_KIND_MAX:
+            break;
+        }
+        monitor_printf(mon, "\n");
+        c++;
+    }
+    qapi_free_TPMInfoList(info_list);
+}
+
 void hmp_quit(Monitor *mon, const QDict *qdict)
 {
     monitor_suspend(mon);
diff --git a/hmp.h b/hmp.h
index 30b3c20..95fe76e 100644
--- a/hmp.h
+++ b/hmp.h
@@ -36,6 +36,7 @@ void hmp_info_spice(Monitor *mon, const QDict *qdict);
 void hmp_info_balloon(Monitor *mon, const QDict *qdict);
 void hmp_info_pci(Monitor *mon, const QDict *qdict);
 void hmp_info_block_jobs(Monitor *mon, const QDict *qdict);
+void hmp_info_tpm(Monitor *mon, const QDict *qdict);
 void hmp_quit(Monitor *mon, const QDict *qdict);
 void hmp_stop(Monitor *mon, const QDict *qdict);
 void hmp_system_reset(Monitor *mon, const QDict *qdict);
diff --git a/include/tpm/tpm.h b/include/tpm/tpm.h
new file mode 100644
index 0000000..cc8f20e
--- /dev/null
+++ b/include/tpm/tpm.h
@@ -0,0 +1,21 @@
+/*
+ * Public TPM functions
+ *
+ * Copyright (C) 2011-2013 IBM Corporation
+ *
+ * Authors:
+ *  Stefan Berger    <stefanb 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 QEMU_TPM_H
+#define QEMU_TPM_H
+
+#include "qemu/option.h"
+
+int tpm_config_parse(QemuOptsList *opts_list, const char *optarg);
+int tpm_init(void);
+void tpm_cleanup(void);
+
+#endif /* QEMU_TPM_H */
diff --git a/monitor.c b/monitor.c
index c48530b..1b5acf8 100644
--- a/monitor.c
+++ b/monitor.c
@@ -47,6 +47,7 @@
 #include "migration/migration.h"
 #include "sysemu/kvm.h"
 #include "qemu/acl.h"
+#include "tpm/tpm.h"
 #include "qapi/qmp/qint.h"
 #include "qapi/qmp/qfloat.h"
 #include "qapi/qmp/qlist.h"
@@ -2722,6 +2723,13 @@ static mon_cmd_t info_cmds[] = {
         .mhandler.cmd = do_trace_print_events,
     },
     {
+        .name       = "tpm",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show the TPM device",
+        .mhandler.cmd = hmp_info_tpm,
+    },
+    {
         .name       = NULL,
     },
 };
diff --git a/qapi-schema.json b/qapi-schema.json
index 28b070f..4494e53 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3240,3 +3240,107 @@
 # Since: 1.4
 ##
 { 'command': 'chardev-remove', 'data': {'id': 'str'} }
+
+##
+# @TpmModel:
+#
+# An enumeration of TPM models
+#
+# @tpm-tis: TPM TIS model
+#
+# Since: 1.5
+##
+{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }
+
+##
+# @query-tpm-models:
+#
+# Return a list of supported TPM models
+#
+# Returns: a list of TpmModel
+#
+# Since: 1.5
+##
+{ 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
+
+##
+# @TpmType:
+#
+# An enumeration of TPM types
+#
+# @passthrough: TPM passthrough type
+#
+# Since: 1.5
+##
+{ 'enum': 'TpmType', 'data': [ 'passthrough' ] }
+
+##
+# @query-tpm-types:
+#
+# Return a list of supported TPM types
+#
+# Returns: a list of TpmType
+#
+# Since: 1.5
+##
+{ 'command': 'query-tpm-types', 'returns': ['TpmType'] }
+
+##
+# @TPMPassthroughOptions:
+#
+# Information about the TPM passthrough type
+#
+# @path: #optional string describing the path used for accessing the TPM device
+#
+# @cancel-path: #optional string showing the TPM's sysfs cancel file
+#               for cancellation of TPM commands while they are executing
+#
+# Since: 1.5
+##
+{ 'type': 'TPMPassthroughOptions', 'data': { '*path' : 'str',
+                                             '*cancel-path' : 'str'} }
+
+##
+# @TpmTypeOptions:
+#
+# A union referencing different TPM backend types' configuration options
+#
+# @tpm-passthough-options: TPMPassthroughOptions describing the TPM
+#                          passthrough configuration options
+#
+# Since: 1.5
+##
+{ 'union': 'TpmTypeOptions',
+   'data': { 'tpm-passthrough-options' : 'TPMPassthroughOptions' } }
+
+##
+# @TpmInfo:
+#
+# Information about the TPM
+#
+# @id: The Id of the TPM
+#
+# @model: The TPM frontend model
+#
+# @type: The TPM (backend) type being used
+#
+# @tpm-options: The TPM (backend) type configuration options
+#
+# Since: 1.5
+##
+{ 'type': 'TPMInfo',
+  'data': {'id': 'str',
+           'model': 'TpmModel',
+           'type': 'TpmType',
+           'tpm-options': 'TpmTypeOptions' } }
+
+##
+# @query-tpm:
+#
+# Return information about the TPM device
+#
+# Returns: @TPMInfo on success
+#
+# Since: 1.5
+##
+{ 'command': 'query-tpm', 'returns': ['TPMInfo'] }
diff --git a/qemu-options.hx b/qemu-options.hx
index cd76f2a..291932f 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2217,6 +2217,39 @@ STEXI
 ETEXI
 DEFHEADING()
 
+#ifdef CONFIG_TPM
+DEFHEADING(TPM device options:)
+
+DEF("tpmdev", HAS_ARG, QEMU_OPTION_tpmdev, \
+    "-tpmdev [<type>],id=str[,option][,option][,...]\n",
+    QEMU_ARCH_ALL)
+STEXI
+
+The general form of a TPM device option is:
+ at table @option
+
+ at item -tpmdev @var{backend} ,id=@var{id} [, at var{options}]
+ at findex -tpmdev
+Backend type must be:
+
+The specific backend type will determine the applicable options.
+The @code{-tpmdev} option requires a @code{-device} option.
+
+Options to each backend are described below.
+
+Use 'help' to print all available TPM backend types.
+ at example
+qemu -tpmdev help
+ at end example
+
+ at end table
+
+ETEXI
+
+DEFHEADING()
+
+#endif
+
 DEFHEADING(Linux/Multiboot boot specific:)
 STEXI
 
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 95022e2..b370060 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2716,6 +2716,24 @@ EQMP
     },
 
     {
+        .name       = "query-tpm",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_tpm,
+    },
+
+    {
+        .name       = "query-tpm-models",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_tpm_models,
+    },
+
+    {
+        .name       = "query-tpm-types",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_tpm_types,
+    },
+
+    {
         .name       = "chardev-add",
         .args_type  = "id:s,backend:q",
         .mhandler.cmd_new = qmp_marshal_input_chardev_add,
diff --git a/tpm/Makefile.objs b/tpm/Makefile.objs
new file mode 100644
index 0000000..dffb567
--- /dev/null
+++ b/tpm/Makefile.objs
@@ -0,0 +1 @@
+common-obj-y = tpm.o
diff --git a/tpm/tpm.c b/tpm/tpm.c
new file mode 100644
index 0000000..0273549
--- /dev/null
+++ b/tpm/tpm.c
@@ -0,0 +1,343 @@
+/*
+ * TPM configuration
+ *
+ * Copyright (C) 2011-2013 IBM Corporation
+ *
+ * Authors:
+ *  Stefan Berger    <stefanb 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.
+ *
+ * Based on net.c
+ */
+#include "config-host.h"
+
+#include "monitor/monitor.h"
+#include "qapi/qmp/qerror.h"
+#include "tpm_int.h"
+#include "tpm/tpm.h"
+#include "qemu/config-file.h"
+#include "qmp-commands.h"
+
+static QLIST_HEAD(, TPMBackend) tpm_backends =
+    QLIST_HEAD_INITIALIZER(tpm_backends);
+
+
+#define TPM_MAX_MODELS      1
+#define TPM_MAX_DRIVERS     1
+
+static TPMDriverOps const *be_drivers[TPM_MAX_DRIVERS] = {
+    NULL,
+};
+
+static enum TpmModel tpm_models[TPM_MAX_MODELS] = {
+    -1,
+};
+
+int tpm_register_model(enum TpmModel model)
+{
+    int i;
+
+    for (i = 0; i < TPM_MAX_MODELS; i++) {
+        if (tpm_models[i] == -1) {
+            tpm_models[i] = model;
+            return 0;
+        }
+    }
+    error_report("Could not register TPM model");
+    return 1;
+}
+
+static bool tpm_model_is_registered(enum TpmModel model)
+{
+    int i;
+
+    for (i = 0; i < TPM_MAX_MODELS; i++) {
+        if (tpm_models[i] == model) {
+            return true;
+        }
+    }
+    return false;
+}
+
+const TPMDriverOps *tpm_get_backend_driver(const char *type)
+{
+    int i;
+
+    for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
+        if (!strcmp(TpmType_lookup[be_drivers[i]->type], type)) {
+            return be_drivers[i];
+        }
+    }
+
+    return NULL;
+}
+
+#ifdef CONFIG_TPM
+
+int tpm_register_driver(const TPMDriverOps *tdo)
+{
+    int i;
+
+    for (i = 0; i < TPM_MAX_DRIVERS; i++) {
+        if (!be_drivers[i]) {
+            be_drivers[i] = tdo;
+            return 0;
+        }
+    }
+    error_report("Could not register TPM driver");
+    return 1;
+}
+
+/*
+ * Walk the list of available TPM backend drivers and display them on the
+ * screen.
+ */
+void tpm_display_backend_drivers(void)
+{
+    int i;
+
+    fprintf(stderr, "Supported TPM types (choose only one):\n");
+
+    for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
+        fprintf(stderr, "%12s   %s\n",
+                TpmType_lookup[be_drivers[i]->type], be_drivers[i]->desc());
+    }
+    fprintf(stderr, "\n");
+}
+
+/*
+ * Find the TPM with the given Id
+ */
+TPMBackend *qemu_find_tpm(const char *id)
+{
+    TPMBackend *drv;
+
+    if (id) {
+        QLIST_FOREACH(drv, &tpm_backends, list) {
+            if (!strcmp(drv->id, id)) {
+                return drv;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+static int configure_tpm(QemuOpts *opts)
+{
+    const char *value;
+    const char *id;
+    const TPMDriverOps *be;
+    TPMBackend *drv;
+
+    if (!QLIST_EMPTY(&tpm_backends)) {
+        error_report("Only one TPM is allowed.\n");
+        return 1;
+    }
+
+    id = qemu_opts_id(opts);
+    if (id == NULL) {
+        qerror_report(QERR_MISSING_PARAMETER, "id");
+        return 1;
+    }
+
+    value = qemu_opt_get(opts, "type");
+    if (!value) {
+        qerror_report(QERR_MISSING_PARAMETER, "type");
+        tpm_display_backend_drivers();
+        return 1;
+    }
+
+    be = tpm_get_backend_driver(value);
+    if (be == NULL) {
+        qerror_report(QERR_INVALID_PARAMETER_VALUE, "type",
+                      "a TPM backend type");
+        tpm_display_backend_drivers();
+        return 1;
+    }
+
+    drv = be->create(opts, id);
+    if (!drv) {
+        return 1;
+    }
+
+    QLIST_INSERT_HEAD(&tpm_backends, drv, list);
+
+    return 0;
+}
+
+static int tpm_init_tpmdev(QemuOpts *opts, void *dummy)
+{
+    return configure_tpm(opts);
+}
+
+/*
+ * Walk the list of TPM backend drivers that are in use and call their
+ * destroy function to have them cleaned up.
+ */
+void tpm_cleanup(void)
+{
+    TPMBackend *drv, *next;
+
+    QLIST_FOREACH_SAFE(drv, &tpm_backends, list, next) {
+        QLIST_REMOVE(drv, list);
+        drv->ops->destroy(drv);
+    }
+}
+
+/*
+ * Initialize the TPM. Process the tpmdev command line options describing the
+ * TPM backend.
+ */
+int tpm_init(void)
+{
+    if (qemu_opts_foreach(qemu_find_opts("tpmdev"),
+                          tpm_init_tpmdev, NULL, 1) != 0) {
+        return -1;
+    }
+
+    atexit(tpm_cleanup);
+
+    return 0;
+}
+
+/*
+ * Parse the TPM configuration options.
+ * To display all available TPM backends the user may use '-tpmdev help'
+ */
+int tpm_config_parse(QemuOptsList *opts_list, const char *optarg)
+{
+    QemuOpts *opts;
+
+    if (!strcmp(optarg, "help")) {
+        tpm_display_backend_drivers();
+        return -1;
+    }
+    opts = qemu_opts_parse(opts_list, optarg, 1);
+    if (!opts) {
+        return -1;
+    }
+    return 0;
+}
+
+#endif /* CONFIG_TPM */
+
+static const TPMDriverOps *tpm_driver_find_by_type(enum TpmType type)
+{
+    int i;
+
+    for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
+        if (be_drivers[i]->type == type) {
+            return be_drivers[i];
+        }
+    }
+    return NULL;
+}
+
+static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv)
+{
+    TPMInfo *res = g_new0(TPMInfo, 1);
+    TPMPassthroughOptions *tpo;
+
+    res->id = g_strdup(drv->id);
+    res->model = drv->fe_model;
+    res->type = drv->ops->type;
+    res->tpm_options = g_new0(TpmTypeOptions, 1);
+
+    switch (res->type) {
+    case TPM_TYPE_PASSTHROUGH:
+        res->tpm_options->kind = TPM_TYPE_OPTIONS_KIND_TPM_PASSTHROUGH_OPTIONS;
+        tpo = g_new0(TPMPassthroughOptions, 1);
+        res->tpm_options->tpm_passthrough_options = tpo;
+        if (drv->path) {
+            tpo->path = g_strdup(drv->path);
+            tpo->has_path = true;
+        }
+        if (drv->cancel_path) {
+            tpo->cancel_path = g_strdup(drv->cancel_path);
+            tpo->has_cancel_path = true;
+        }
+        break;
+    case TPM_TYPE_MAX:
+        break;
+    }
+
+    return res;
+}
+
+/*
+ * Walk the list of active TPM backends and collect information about them
+ * following the schema description in qapi-schema.json.
+ */
+TPMInfoList *qmp_query_tpm(Error **errp)
+{
+    TPMBackend *drv;
+    TPMInfoList *info, *head = NULL, *cur_item = NULL;
+
+    QLIST_FOREACH(drv, &tpm_backends, list) {
+        if (!tpm_model_is_registered(drv->fe_model)) {
+            continue;
+        }
+        info = g_new0(TPMInfoList, 1);
+        info->value = qmp_query_tpm_inst(drv);
+
+        if (!cur_item) {
+            head = cur_item = info;
+        } else {
+            cur_item->next = info;
+            cur_item = info;
+        }
+    }
+
+    return head;
+}
+
+TpmTypeList *qmp_query_tpm_types(Error **errp)
+{
+    unsigned int i = 0;
+    TpmTypeList *head = NULL, *prev = NULL, *cur_item;
+
+    for (i = 0; i < TPM_TYPE_MAX; i++) {
+        if (!tpm_driver_find_by_type(i)) {
+            continue;
+        }
+        cur_item = g_new0(TpmTypeList, 1);
+        cur_item->value = i;
+
+        if (prev) {
+            prev->next = cur_item;
+        }
+        if (!head) {
+            head = cur_item;
+        }
+        prev = cur_item;
+    }
+
+    return head;
+}
+
+TpmModelList *qmp_query_tpm_models(Error **errp)
+{
+    unsigned int i = 0;
+    TpmModelList *head = NULL, *prev = NULL, *cur_item;
+
+    for (i = 0; i < TPM_MODEL_MAX; i++) {
+        if (!tpm_model_is_registered(i)) {
+            continue;
+        }
+        cur_item = g_new0(TpmModelList, 1);
+        cur_item->value = i;
+
+        if (prev) {
+            prev->next = cur_item;
+        }
+        if (!head) {
+            head = cur_item;
+        }
+        prev = cur_item;
+    }
+
+    return head;
+}
diff --git a/tpm/tpm_int.h b/tpm/tpm_int.h
new file mode 100644
index 0000000..d5358ad
--- /dev/null
+++ b/tpm/tpm_int.h
@@ -0,0 +1,83 @@
+/*
+ * TPM configuration
+ *
+ * Copyright (C) 2011-2013 IBM Corporation
+ *
+ * Authors:
+ *  Stefan Berger    <stefanb 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 TPM_TPM_INT_H
+#define TPM_TPM_INT_H
+
+#include "exec/memory.h"
+#include "tpm/tpm_tis.h"
+
+struct TPMDriverOps;
+typedef struct TPMDriverOps TPMDriverOps;
+
+typedef struct TPMBackend {
+    char *id;
+    enum TpmModel fe_model;
+    char *path;
+    char *cancel_path;
+    const TPMDriverOps *ops;
+
+    QLIST_ENTRY(TPMBackend) list;
+} TPMBackend;
+
+/* overall state of the TPM interface */
+typedef struct TPMState {
+    ISADevice busdev;
+    MemoryRegion mmio;
+
+    union {
+        TPMTISEmuState tis;
+    } s;
+
+    uint8_t     locty_number;
+    TPMLocality *locty_data;
+
+    char *backend;
+    TPMBackend *be_driver;
+} TPMState;
+
+#define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS)
+
+typedef void (TPMRecvDataCB)(TPMState *, uint8_t locty);
+
+struct TPMDriverOps {
+    enum TpmType type;
+    /* get a descriptive text of the backend to display to the user */
+    const char *(*desc)(void);
+
+    TPMBackend *(*create)(QemuOpts *opts, const char *id);
+    void (*destroy)(TPMBackend *t);
+
+    /* initialize the backend */
+    int (*init)(TPMBackend *t, TPMState *s, TPMRecvDataCB *datacb);
+    /* start up the TPM on the backend */
+    int (*startup_tpm)(TPMBackend *t);
+    /* returns true if nothing will ever answer TPM requests */
+    bool (*had_startup_error)(TPMBackend *t);
+
+    size_t (*realloc_buffer)(TPMSizedBuffer *sb);
+
+    void (*deliver_request)(TPMBackend *t);
+
+    void (*reset)(TPMBackend *t);
+
+    void (*cancel_cmd)(TPMBackend *t);
+
+    bool (*get_tpm_established_flag)(TPMBackend *t);
+};
+
+TPMBackend *qemu_find_tpm(const char *id);
+int tpm_register_model(enum TpmModel model);
+int tpm_register_driver(const TPMDriverOps *tdo);
+void tpm_display_backend_drivers(void);
+const TPMDriverOps *tpm_get_backend_driver(const char *type);
+
+#endif /* TPM_TPM_INT_H */
diff --git a/tpm/tpm_tis.h b/tpm/tpm_tis.h
new file mode 100644
index 0000000..0c8df80
--- /dev/null
+++ b/tpm/tpm_tis.h
@@ -0,0 +1,80 @@
+/*
+ * tpm_tis.h - QEMU's TPM TIS interface emulator
+ *
+ * Copyright (C) 2006, 2010-2013 IBM Corporation
+ *
+ * Authors:
+ *  Stefan Berger <stefanb at us.ibm.com>
+ *  David Safford <safford 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.
+ *
+ * Implementation of the TIS interface according to specs found at
+ * http://www.trustedcomputinggroup.org
+ *
+ */
+#ifndef TPM_TPM_TIS_H
+#define TPM_TPM_TIS_H
+
+#include "hw/isa.h"
+#include "qemu-common.h"
+
+#define TPM_TIS_ADDR_BASE           0xFED40000
+
+#define TPM_TIS_NUM_LOCALITIES      5     /* per spec */
+#define TPM_TIS_LOCALITY_SHIFT      12
+#define TPM_TIS_NO_LOCALITY         0xff
+
+#define TPM_TIS_IS_VALID_LOCTY(x)   ((x) < TPM_TIS_NUM_LOCALITIES)
+
+#define TPM_TIS_IRQ                 5
+
+#define TPM_TIS_BUFFER_MAX          4096
+
+#define TYPE_TPM_TIS                "tpm-tis"
+
+
+typedef struct TPMSizedBuffer {
+    uint32_t size;
+    uint8_t  *buffer;
+} TPMSizedBuffer;
+
+typedef enum {
+    TPM_TIS_STATE_IDLE = 0,
+    TPM_TIS_STATE_READY,
+    TPM_TIS_STATE_COMPLETION,
+    TPM_TIS_STATE_EXECUTION,
+    TPM_TIS_STATE_RECEPTION,
+} TPMTISState;
+
+/* locality data  -- all fields are persisted */
+typedef struct TPMLocality {
+    TPMTISState state;
+    uint8_t access;
+    uint8_t sts;
+    uint32_t inte;
+    uint32_t ints;
+
+    uint16_t w_offset;
+    uint16_t r_offset;
+    TPMSizedBuffer w_buffer;
+    TPMSizedBuffer r_buffer;
+} TPMLocality;
+
+typedef struct TPMTISEmuState {
+    QEMUBH *bh;
+    uint32_t offset;
+    uint8_t buf[TPM_TIS_BUFFER_MAX];
+
+    uint8_t active_locty;
+    uint8_t aborting_locty;
+    uint8_t next_locty;
+
+    TPMLocality loc[TPM_TIS_NUM_LOCALITIES];
+
+    qemu_irq irq;
+    uint32_t irq_num;
+} TPMTISEmuState;
+
+#endif /* TPM_TPM_TIS_H */
diff --git a/vl.c b/vl.c
index 154f7ba..0c6c2bf 100644
--- a/vl.c
+++ b/vl.c
@@ -139,6 +139,7 @@ int main(int argc, char **argv)
 #include "sysemu/blockdev.h"
 #include "hw/block-common.h"
 #include "migration/block.h"
+#include "tpm/tpm.h"
 #include "sysemu/dma.h"
 #include "audio/audio.h"
 #include "migration/migration.h"
@@ -491,6 +492,25 @@ static QemuOptsList qemu_object_opts = {
     },
 };
 
+static QemuOptsList qemu_tpmdev_opts = {
+    .name = "tpmdev",
+    .implied_opt_name = "type",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_tpmdev_opts.head),
+    .desc = {
+        {
+            .name = "type",
+            .type = QEMU_OPT_STRING,
+            .help = "Type of TPM backend",
+        },
+        {
+            .name = "path",
+            .type = QEMU_OPT_STRING,
+            .help = "Path to TPM device on the host",
+        },
+        { /* end of list */ }
+    },
+};
+
 const char *qemu_get_vm_name(void)
 {
     return qemu_name;
@@ -2868,6 +2888,7 @@ int main(int argc, char **argv, char **envp)
     qemu_add_opts(&qemu_sandbox_opts);
     qemu_add_opts(&qemu_add_fd_opts);
     qemu_add_opts(&qemu_object_opts);
+    qemu_add_opts(&qemu_tpmdev_opts);
 
     runstate_init();
 
@@ -3231,6 +3252,13 @@ int main(int argc, char **argv, char **envp)
                 }
                 break;
             }
+#ifdef CONFIG_TPM
+            case QEMU_OPTION_tpmdev:
+                if (tpm_config_parse(qemu_find_opts("tpmdev"), optarg) < 0) {
+                    exit(1);
+                }
+                break;
+#endif
             case QEMU_OPTION_mempath:
                 mem_path = optarg;
                 break;
@@ -4108,6 +4136,12 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
+#ifdef CONFIG_TPM
+    if (tpm_init() < 0) {
+        exit(1);
+    }
+#endif
+
     /* init the bluetooth world */
     if (foreach_device_config(DEV_BT, bt_parse))
         exit(1);
@@ -4353,6 +4387,9 @@ int main(int argc, char **argv, char **envp)
     bdrv_close_all();
     pause_all_vcpus();
     res_free();
+#ifdef CONFIG_TPM
+    tpm_cleanup();
+#endif
 
     return 0;
 }
commit 2362ecc5c6f4073f7f4c9c3f45c335aa8a2261bb
Author: Cornelia Huck <cornelia.huck at de.ibm.com>
Date:   Mon Mar 4 13:06:56 2013 +0100

    virtio-ccw: Wire up virtio-rng.
    
    Make virtio-rng devices available for s390-ccw-virtio machines.
    
    Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com>

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 06b9641..d4361f6 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -642,6 +642,30 @@ static int virtio_ccw_scsi_exit(VirtioCcwDevice *dev)
     return virtio_ccw_exit(dev);
 }
 
+static int virtio_ccw_rng_init(VirtioCcwDevice *dev)
+{
+    VirtIODevice *vdev;
+
+    if (dev->rng.rng == NULL) {
+        dev->rng.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM));
+        object_property_add_child(OBJECT(dev), "default-backend",
+                                  OBJECT(dev->rng.default_backend), NULL);
+        object_property_set_link(OBJECT(dev), OBJECT(dev->rng.default_backend),
+                                 "rng", NULL);
+    }
+    vdev = virtio_rng_init((DeviceState *)dev, &dev->rng);
+    if (!vdev) {
+        return -1;
+    }
+    return virtio_ccw_device_init(dev, vdev);
+}
+
+static int virtio_ccw_rng_exit(VirtioCcwDevice *dev)
+{
+    virtio_rng_exit(dev->vdev);
+    return virtio_ccw_exit(dev);
+}
+
 /* DeviceState to VirtioCcwDevice. Note: used on datapath,
  * be careful and test performance if you change this.
  */
@@ -831,6 +855,41 @@ static const TypeInfo virtio_ccw_scsi = {
     .class_init    = virtio_ccw_scsi_class_init,
 };
 
+static void virtio_ccw_rng_initfn(Object *obj)
+{
+    VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(obj);
+
+    object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
+                             (Object **)&dev->rng.rng, NULL);
+}
+
+static Property virtio_ccw_rng_properties[] = {
+    DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
+    DEFINE_VIRTIO_COMMON_FEATURES(VirtioCcwDevice, host_features[0]),
+    DEFINE_PROP_UINT64("max-bytes", VirtioCcwDevice, rng.max_bytes, INT64_MAX),
+    DEFINE_PROP_UINT32("period", VirtioCcwDevice, rng.period_ms, 1 << 16),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_ccw_rng_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
+
+    k->init = virtio_ccw_rng_init;
+    k->exit = virtio_ccw_rng_exit;
+    dc->reset = virtio_ccw_reset;
+    dc->props = virtio_ccw_rng_properties;
+}
+
+static const TypeInfo virtio_ccw_rng = {
+    .name          = "virtio-rng-ccw",
+    .parent        = TYPE_VIRTIO_CCW_DEVICE,
+    .instance_size = sizeof(VirtioCcwDevice),
+    .instance_init = virtio_ccw_rng_initfn,
+    .class_init    = virtio_ccw_rng_class_init,
+};
+
 static int virtio_ccw_busdev_init(DeviceState *dev)
 {
     VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
@@ -953,6 +1012,7 @@ static void virtio_ccw_register(void)
     type_register_static(&virtio_ccw_net);
     type_register_static(&virtio_ccw_balloon);
     type_register_static(&virtio_ccw_scsi);
+    type_register_static(&virtio_ccw_rng);
     type_register_static(&virtual_css_bridge_info);
 }
 
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 48474b3..88c46c0 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -16,6 +16,7 @@
 #include <hw/virtio-net.h>
 #include <hw/virtio-serial.h>
 #include <hw/virtio-scsi.h>
+#include <hw/virtio-rng.h>
 #include <hw/virtio-bus.h>
 
 #define VIRTUAL_CSSID 0xfe
@@ -77,6 +78,7 @@ struct VirtioCcwDevice {
     virtio_serial_conf serial;
     virtio_net_conf net;
     VirtIOSCSIConf scsi;
+    VirtIORNGConf rng;
     VirtioBusState bus;
     /* Guest provided values: */
     hwaddr indicators;
commit b8a205f2ed222a5d24bf7e8346919abee861d026
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Wed Feb 20 13:02:07 2013 +0100

    virtio-ccw: remove qdev_unparent in unplug routing
    
    This patch fixes unplugging a virtio-ccw device. We no
    longer need to do that in virtio-ccw since common code does now
    proper handling.
    
    Signed-off-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Signed-off-by: Jens Freimann <jfrei at linux.vnet.ibm.com>
    Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com>

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index a9cf703..06b9641 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -865,7 +865,6 @@ static int virtio_ccw_busdev_unplug(DeviceState *dev)
 
     css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0);
 
-    object_unparent(OBJECT(dev));
     qdev_free(dev);
     return 0;
 }
commit 0ad6773f1151c9e172b0b714aada78655dda4cf4
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Feb 2 13:45:29 2013 +0100

    target-lm32: Update VMStateDescription to LM32CPU
    
    Add a vmstate_lm32_cpu referencing the previous VMStateDescription as a
    sub-struct and hook it up to CPUClass::vmsd. Drop cpu_{save,load}().
    
    Acked-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-lm32/cpu-qom.h b/target-lm32/cpu-qom.h
index 3ba86b7..9571860 100644
--- a/target-lm32/cpu-qom.h
+++ b/target-lm32/cpu-qom.h
@@ -71,6 +71,10 @@ static inline LM32CPU *lm32_env_get_cpu(CPULM32State *env)
 
 #define ENV_OFFSET offsetof(LM32CPU, env)
 
+#ifndef CONFIG_USER_ONLY
+extern const struct VMStateDescription vmstate_lm32_cpu;
+#endif
+
 void lm32_cpu_do_interrupt(CPUState *cpu);
 
 #endif
diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
index a4692b7..bbb7fbf 100644
--- a/target-lm32/cpu.c
+++ b/target-lm32/cpu.c
@@ -85,6 +85,7 @@ static void lm32_cpu_class_init(ObjectClass *oc, void *data)
     cc->reset = lm32_cpu_reset;
 
     cc->do_interrupt = lm32_cpu_do_interrupt;
+    cpu_class_set_vmsd(cc, &vmstate_lm32_cpu);
 }
 
 static const TypeInfo lm32_cpu_type_info = {
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index 1be9778..fd50b53 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -211,8 +211,6 @@ static inline CPULM32State *cpu_init(const char *cpu_model)
 #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(CPULM32State *env, target_ulong address, int rw,
                               int mmu_idx);
 #define cpu_handle_mmu_fault cpu_lm32_handle_mmu_fault
diff --git a/target-lm32/machine.c b/target-lm32/machine.c
index 6802e81..9e0919c 100644
--- a/target-lm32/machine.c
+++ b/target-lm32/machine.c
@@ -1,9 +1,9 @@
 #include "hw/hw.h"
 #include "hw/boards.h"
 
-static const VMStateDescription vmstate_cpu = {
-    .name = "cpu",
-    .version_id = CPU_SAVE_VERSION,
+static const VMStateDescription vmstate_env = {
+    .name = "env",
+    .version_id = 1,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField[]) {
@@ -22,12 +22,13 @@ static const VMStateDescription vmstate_cpu = {
     }
 };
 
-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);
-}
+const VMStateDescription vmstate_lm32_cpu = {
+    .name = "cpu",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_STRUCT(env, LM32CPU, 1, vmstate_env, CPULM32State),
+        VMSTATE_END_OF_LIST()
+    }
+};
commit e6f010cc27177c97596455b2e2b589bd19b2a486
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Feb 2 12:33:14 2013 +0100

    target-arm: Override do_interrupt for ARMv7-M profile
    
    Enable ARMCPUInfo to specify a custom class_init functions.
    Introduce arm_v7m_class_init() and use it for "cortex-m3" model.
    
    Instead of forwarding from arm_cpu_do_interrupt() to do_interrupt_v7m(),
    override CPUClass::do_interrupt with arm_v7m_cpu_do_interrupt()
    in arm_v7m_class_init().
    
    Acked-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index eeecc92..2589550 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -114,5 +114,6 @@ static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
 void register_cp_regs_for_features(ARMCPU *cpu);
 
 void arm_cpu_do_interrupt(CPUState *cpu);
+void arm_v7m_cpu_do_interrupt(CPUState *cpu);
 
 #endif
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index aeaa3b7..a1e9093 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -412,6 +412,15 @@ static void cortex_m3_initfn(Object *obj)
     cpu->midr = 0x410fc231;
 }
 
+static void arm_v7m_class_init(ObjectClass *oc, void *data)
+{
+#ifndef CONFIG_USER_ONLY
+    CPUClass *cc = CPU_CLASS(oc);
+
+    cc->do_interrupt = arm_v7m_cpu_do_interrupt;
+#endif
+}
+
 static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
     { .name = "L2LOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 0,
       .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
@@ -752,6 +761,7 @@ static void arm_any_initfn(Object *obj)
 typedef struct ARMCPUInfo {
     const char *name;
     void (*initfn)(Object *obj);
+    void (*class_init)(ObjectClass *oc, void *data);
 } ARMCPUInfo;
 
 static const ARMCPUInfo arm_cpus[] = {
@@ -766,7 +776,8 @@ static const ARMCPUInfo arm_cpus[] = {
     { .name = "arm1136",     .initfn = arm1136_initfn },
     { .name = "arm1176",     .initfn = arm1176_initfn },
     { .name = "arm11mpcore", .initfn = arm11mpcore_initfn },
-    { .name = "cortex-m3",   .initfn = cortex_m3_initfn },
+    { .name = "cortex-m3",   .initfn = cortex_m3_initfn,
+                             .class_init = arm_v7m_class_init },
     { .name = "cortex-a8",   .initfn = cortex_a8_initfn },
     { .name = "cortex-a9",   .initfn = cortex_a9_initfn },
     { .name = "cortex-a15",  .initfn = cortex_a15_initfn },
@@ -812,6 +823,7 @@ static void cpu_register(const ARMCPUInfo *info)
         .instance_size = sizeof(ARMCPU),
         .instance_init = info->initfn,
         .class_size = sizeof(ARMCPUClass),
+        .class_init = info->class_init,
     };
 
     type_info.name = g_strdup_printf("%s-" TYPE_ARM_CPU, info->name);
diff --git a/target-arm/helper.c b/target-arm/helper.c
index b4cbb87..fd055e8 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1725,8 +1725,10 @@ static void do_v7m_exception_exit(CPUARMState *env)
        pointer.  */
 }
 
-static void do_interrupt_v7m(CPUARMState *env)
+void arm_v7m_cpu_do_interrupt(CPUState *cs)
 {
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
     uint32_t xpsr = xpsr_read(env);
     uint32_t lr;
     uint32_t addr;
@@ -1811,10 +1813,8 @@ void arm_cpu_do_interrupt(CPUState *cs)
     int new_mode;
     uint32_t offset;
 
-    if (IS_M(env)) {
-        do_interrupt_v7m(env);
-        return;
-    }
+    assert(!IS_M(env));
+
     /* TODO: Vectored interrupt controller.  */
     switch (env->exception_index) {
     case EXCP_UDEF:
commit 97a8ea5a3ae7938cb54fd4dc19d3a413024bc6c0
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Feb 2 10:57:51 2013 +0100

    cpu: Replace do_interrupt() by CPUClass::do_interrupt method
    
    This removes a global per-target function and thus takes us one step
    closer to compiling multiple targets into one executable.
    
    It will also allow to override the interrupt handling for certain CPU
    families.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/cpu-exec.c b/cpu-exec.c
index c9e1a82..94fedc5 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -198,6 +198,10 @@ volatile sig_atomic_t exit_request;
 int cpu_exec(CPUArchState *env)
 {
     CPUState *cpu = ENV_GET_CPU(env);
+#if !(defined(CONFIG_USER_ONLY) && \
+      (defined(TARGET_M68K) || defined(TARGET_PPC) || defined(TARGET_S390X)))
+    CPUClass *cc = CPU_GET_CLASS(cpu);
+#endif
     int ret, interrupt_request;
     TranslationBlock *tb;
     uint8_t *tc_ptr;
@@ -265,12 +269,12 @@ int cpu_exec(CPUArchState *env)
                        which will be handled outside the cpu execution
                        loop */
 #if defined(TARGET_I386)
-                    do_interrupt(env);
+                    cc->do_interrupt(cpu);
 #endif
                     ret = env->exception_index;
                     break;
 #else
-                    do_interrupt(env);
+                    cc->do_interrupt(cpu);
                     env->exception_index = -1;
 #endif
                 }
@@ -380,7 +384,7 @@ int cpu_exec(CPUArchState *env)
                     if ((interrupt_request & CPU_INTERRUPT_HARD)
                         && (env->ie & IE_IE)) {
                         env->exception_index = EXCP_IRQ;
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #elif defined(TARGET_MICROBLAZE)
@@ -389,7 +393,7 @@ int cpu_exec(CPUArchState *env)
                         && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
                         && !(env->iflags & (D_FLAG | IMM_FLAG))) {
                         env->exception_index = EXCP_IRQ;
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #elif defined(TARGET_MIPS)
@@ -398,7 +402,7 @@ int cpu_exec(CPUArchState *env)
                         /* Raise it */
                         env->exception_index = EXCP_EXT_INTERRUPT;
                         env->error_code = 0;
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #elif defined(TARGET_OPENRISC)
@@ -414,7 +418,7 @@ int cpu_exec(CPUArchState *env)
                         }
                         if (idx >= 0) {
                             env->exception_index = idx;
-                            do_interrupt(env);
+                            cc->do_interrupt(cpu);
                             next_tb = 0;
                         }
                     }
@@ -429,7 +433,7 @@ int cpu_exec(CPUArchState *env)
                                   cpu_pil_allowed(env, pil)) ||
                                   type != TT_EXTINT) {
                                 env->exception_index = env->interrupt_index;
-                                do_interrupt(env);
+                                cc->do_interrupt(cpu);
                                 next_tb = 0;
                             }
                         }
@@ -438,7 +442,7 @@ int cpu_exec(CPUArchState *env)
                     if (interrupt_request & CPU_INTERRUPT_FIQ
                         && !(env->uncached_cpsr & CPSR_F)) {
                         env->exception_index = EXCP_FIQ;
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
                     /* ARMv7-M interrupt return works by loading a magic value
@@ -454,19 +458,19 @@ int cpu_exec(CPUArchState *env)
                         && ((IS_M(env) && env->regs[15] < 0xfffffff0)
                             || !(env->uncached_cpsr & CPSR_I))) {
                         env->exception_index = EXCP_IRQ;
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #elif defined(TARGET_UNICORE32)
                     if (interrupt_request & CPU_INTERRUPT_HARD
                         && !(env->uncached_asr & ASR_I)) {
                         env->exception_index = UC32_EXCP_INTR;
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #elif defined(TARGET_SH4)
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #elif defined(TARGET_ALPHA)
@@ -497,7 +501,7 @@ int cpu_exec(CPUArchState *env)
                         if (idx >= 0) {
                             env->exception_index = idx;
                             env->error_code = 0;
-                            do_interrupt(env);
+                            cc->do_interrupt(cpu);
                             next_tb = 0;
                         }
                     }
@@ -506,7 +510,7 @@ int cpu_exec(CPUArchState *env)
                         && (env->pregs[PR_CCS] & I_FLAG)
                         && !env->locked_irq) {
                         env->exception_index = EXCP_IRQ;
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
                     if (interrupt_request & CPU_INTERRUPT_NMI) {
@@ -518,7 +522,7 @@ int cpu_exec(CPUArchState *env)
                         }
                         if ((env->pregs[PR_CCS] & m_flag_archval)) {
                             env->exception_index = EXCP_NMI;
-                            do_interrupt(env);
+                            cc->do_interrupt(cpu);
                             next_tb = 0;
                         }
                     }
@@ -538,13 +542,13 @@ int cpu_exec(CPUArchState *env)
 #elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
                         (env->psw.mask & PSW_MASK_EXT)) {
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #elif defined(TARGET_XTENSA)
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
                         env->exception_index = EXC_IRQ;
-                        do_interrupt(env);
+                        cc->do_interrupt(cpu);
                         next_tb = 0;
                     }
 #endif
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 2e08135..3664a1b 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -44,6 +44,7 @@ typedef struct CPUState CPUState;
  * @class_by_name: Callback to map -cpu command line model name to an
  * instantiatable CPU type.
  * @reset: Callback to reset the #CPUState to its initial state.
+ * @do_interrupt: Callback for interrupt handling.
  * @vmsd: State description for migration.
  *
  * Represents a CPU family or model.
@@ -56,6 +57,7 @@ typedef struct CPUClass {
     ObjectClass *(*class_by_name)(const char *cpu_model);
 
     void (*reset)(CPUState *cpu);
+    void (*do_interrupt)(CPUState *cpu);
 
     const struct VMStateDescription *vmsd;
 } CPUClass;
diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h
index 252bd14..32ee286 100644
--- a/target-alpha/cpu-qom.h
+++ b/target-alpha/cpu-qom.h
@@ -74,4 +74,6 @@ static inline AlphaCPU *alpha_env_get_cpu(CPUAlphaState *env)
 
 #define ENV_OFFSET offsetof(AlphaCPU, env)
 
+void alpha_cpu_do_interrupt(CPUState *cpu);
+
 #endif
diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c
index cec9989..cad1716 100644
--- a/target-alpha/cpu.c
+++ b/target-alpha/cpu.c
@@ -263,6 +263,7 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
     dc->realize = alpha_cpu_realizefn;
 
     cc->class_by_name = alpha_cpu_class_by_name;
+    cc->do_interrupt = alpha_cpu_do_interrupt;
 }
 
 static const TypeInfo alpha_cpu_type_info = {
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 90f78ac..2156a1e 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -449,7 +449,6 @@ int cpu_alpha_signal_handler(int host_signum, void *pinfo,
 int cpu_alpha_handle_mmu_fault (CPUAlphaState *env, uint64_t address, int rw,
                                 int mmu_idx);
 #define cpu_handle_mmu_fault cpu_alpha_handle_mmu_fault
-void do_interrupt (CPUAlphaState *env);
 void do_restore_state(CPUAlphaState *, uintptr_t retaddr);
 void QEMU_NORETURN dynamic_excp(CPUAlphaState *, uintptr_t, int, int);
 void QEMU_NORETURN arith_excp(CPUAlphaState *, uintptr_t, int, uint64_t);
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 22c9c6e..5741ec2 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -345,8 +345,10 @@ int cpu_alpha_handle_mmu_fault(CPUAlphaState *env, target_ulong addr, int rw,
 }
 #endif /* USER_ONLY */
 
-void do_interrupt (CPUAlphaState *env)
+void alpha_cpu_do_interrupt(CPUState *cs)
 {
+    AlphaCPU *cpu = ALPHA_CPU(cs);
+    CPUAlphaState *env = &cpu->env;
     int i = env->exception_index;
 
     if (qemu_loglevel_mask(CPU_LOG_INT)) {
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index 7539727..eeecc92 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -113,4 +113,6 @@ static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
 
 void register_cp_regs_for_features(ARMCPU *cpu);
 
+void arm_cpu_do_interrupt(CPUState *cpu);
+
 #endif
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 5dfcb74..aeaa3b7 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -802,6 +802,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
     cc->reset = arm_cpu_reset;
 
     cc->class_by_name = arm_cpu_class_by_name;
+    cc->do_interrupt = arm_cpu_do_interrupt;
 }
 
 static void cpu_register(const ARMCPUInfo *info)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 957866c..2b97221 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -236,7 +236,6 @@ ARMCPU *cpu_arm_init(const char *cpu_model);
 void arm_translate_init(void);
 void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu);
 int cpu_arm_exec(CPUARMState *s);
-void do_interrupt(CPUARMState *);
 int bank_number(int mode);
 void switch_mode(CPUARMState *, int);
 uint32_t do_arm_semihosting(CPUARMState *env);
diff --git a/target-arm/helper.c b/target-arm/helper.c
index f839726..b4cbb87 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1567,8 +1567,11 @@ uint32_t HELPER(rbit)(uint32_t x)
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt (CPUARMState *env)
+void arm_cpu_do_interrupt(CPUState *cs)
 {
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+
     env->exception_index = -1;
 }
 
@@ -1799,9 +1802,10 @@ static void do_interrupt_v7m(CPUARMState *env)
 }
 
 /* Handle a CPU exception.  */
-void do_interrupt(CPUARMState *env)
+void arm_cpu_do_interrupt(CPUState *cs)
 {
-    CPUState *cs;
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
     uint32_t addr;
     uint32_t mask;
     int new_mode;
@@ -1908,7 +1912,6 @@ void do_interrupt(CPUARMState *env)
     }
     env->regs[14] = env->regs[15] + offset;
     env->regs[15] = addr;
-    cs = CPU(arm_env_get_cpu(env));
     cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
 
diff --git a/target-cris/cpu-qom.h b/target-cris/cpu-qom.h
index 11e5286..deea1d8 100644
--- a/target-cris/cpu-qom.h
+++ b/target-cris/cpu-qom.h
@@ -73,4 +73,6 @@ static inline CRISCPU *cris_env_get_cpu(CPUCRISState *env)
 
 #define ENV_OFFSET offsetof(CRISCPU, env)
 
+void cris_cpu_do_interrupt(CPUState *cpu);
+
 #endif
diff --git a/target-cris/cpu.c b/target-cris/cpu.c
index 7974be3..95cbf39 100644
--- a/target-cris/cpu.c
+++ b/target-cris/cpu.c
@@ -243,6 +243,7 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
     cc->reset = cris_cpu_reset;
 
     cc->class_by_name = cris_cpu_class_by_name;
+    cc->do_interrupt = cris_cpu_do_interrupt;
 }
 
 static const TypeInfo cris_cpu_type_info = {
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index 2fc7c5c..dbd7d36 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -175,7 +175,6 @@ typedef struct CPUCRISState {
 
 CRISCPU *cpu_cris_init(const char *cpu_model);
 int cpu_cris_exec(CPUCRISState *s);
-void do_interrupt(CPUCRISState *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.  */
diff --git a/target-cris/helper.c b/target-cris/helper.c
index 885f67f..e1ef7bc 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -36,8 +36,11 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt(CPUCRISState *env)
+void cris_cpu_do_interrupt(CPUState *cs)
 {
+    CRISCPU *cpu = CRIS_CPU(cs);
+    CPUCRISState *env = &cpu->env;
+
     env->exception_index = -1;
     env->pregs[PR_ERP] = env->pc;
 }
@@ -162,9 +165,10 @@ static void do_interruptv10(CPUCRISState *env)
                   env->pregs[PR_ERP]);
 }
 
-void do_interrupt(CPUCRISState *env)
+void cris_cpu_do_interrupt(CPUState *cs)
 {
-    D(CPUState *cs = CPU(cris_env_get_cpu(env)));
+    CRISCPU *cpu = CRIS_CPU(cs);
+    CPUCRISState *env = &cpu->env;
     int ex_vec = -1;
 
     if (env->pregs[PR_VR] < 32) {
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index 83c5318..08f9eb6 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -80,4 +80,10 @@ static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
 extern const struct VMStateDescription vmstate_x86_cpu;
 #endif
 
+/**
+ * x86_cpu_do_interrupt:
+ * @cpu: vCPU the interrupt is to be handled by.
+ */
+void x86_cpu_do_interrupt(CPUState *cpu);
+
 #endif
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 2bdbf1b..a0640db 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2251,6 +2251,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
     xcc->parent_reset = cc->reset;
     cc->reset = x86_cpu_reset;
 
+    cc->do_interrupt = x86_cpu_do_interrupt;
     cpu_class_set_vmsd(cc, &vmstate_x86_cpu);
 }
 
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index bf6e210..48f41ca 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -1252,8 +1252,7 @@ void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type,
                                    uint64_t param);
 void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1);
 
-/* op_helper.c */
-void do_interrupt(CPUX86State *env);
+/* seg_helper.c */
 void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw);
 
 void do_smm_enter(CPUX86State *env1);
diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c
index 3247dee..906e4f3 100644
--- a/target-i386/seg_helper.c
+++ b/target-i386/seg_helper.c
@@ -1231,8 +1231,11 @@ static void do_interrupt_all(CPUX86State *env, int intno, int is_int,
 #endif
 }
 
-void do_interrupt(CPUX86State *env)
+void x86_cpu_do_interrupt(CPUState *cs)
 {
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
+
 #if defined(CONFIG_USER_ONLY)
     /* if user mode only, we simulate a fake exception
        which will be handled outside the cpu execution
diff --git a/target-lm32/cpu-qom.h b/target-lm32/cpu-qom.h
index c0b6ce5..3ba86b7 100644
--- a/target-lm32/cpu-qom.h
+++ b/target-lm32/cpu-qom.h
@@ -71,4 +71,6 @@ static inline LM32CPU *lm32_env_get_cpu(CPULM32State *env)
 
 #define ENV_OFFSET offsetof(LM32CPU, env)
 
+void lm32_cpu_do_interrupt(CPUState *cpu);
+
 #endif
diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
index a2badb5..a4692b7 100644
--- a/target-lm32/cpu.c
+++ b/target-lm32/cpu.c
@@ -83,6 +83,8 @@ static void lm32_cpu_class_init(ObjectClass *oc, void *data)
 
     lcc->parent_reset = cc->reset;
     cc->reset = lm32_cpu_reset;
+
+    cc->do_interrupt = lm32_cpu_do_interrupt;
 }
 
 static const TypeInfo lm32_cpu_type_info = {
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index d81f103..1be9778 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -189,7 +189,6 @@ struct CPULM32State {
 LM32CPU *cpu_lm32_init(const char *cpu_model);
 void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf);
 int cpu_lm32_exec(CPULM32State *s);
-void do_interrupt(CPULM32State *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.  */
diff --git a/target-lm32/helper.c b/target-lm32/helper.c
index 47ae7e7..a0a8399 100644
--- a/target-lm32/helper.c
+++ b/target-lm32/helper.c
@@ -42,8 +42,11 @@ hwaddr cpu_get_phys_page_debug(CPULM32State *env, target_ulong addr)
     return addr & TARGET_PAGE_MASK;
 }
 
-void do_interrupt(CPULM32State *env)
+void lm32_cpu_do_interrupt(CPUState *cs)
 {
+    LM32CPU *cpu = LM32_CPU(cs);
+    CPULM32State *env = &cpu->env;
+
     qemu_log_mask(CPU_LOG_INT,
             "exception at pc=%x type=%x\n", env->pc, env->exception_index);
 
diff --git a/target-m68k/cpu-qom.h b/target-m68k/cpu-qom.h
index f4c33b2..846aa74 100644
--- a/target-m68k/cpu-qom.h
+++ b/target-m68k/cpu-qom.h
@@ -70,4 +70,6 @@ static inline M68kCPU *m68k_env_get_cpu(CPUM68KState *env)
 
 #define ENV_OFFSET offsetof(M68kCPU, env)
 
+void m68k_cpu_do_interrupt(CPUState *cpu);
+
 #endif
diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index f5a1098..3c65b4e 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -186,6 +186,7 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
     cc->reset = m68k_cpu_reset;
 
     cc->class_by_name = m68k_cpu_class_by_name;
+    cc->do_interrupt = m68k_cpu_do_interrupt;
     dc->vmsd = &vmstate_m68k_cpu;
 }
 
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index bb2fbd6..c90c40c 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -119,7 +119,6 @@ void m68k_tcg_init(void);
 void m68k_cpu_init_gdb(M68kCPU *cpu);
 M68kCPU *cpu_m68k_init(const char *cpu_model);
 int cpu_m68k_exec(CPUM68KState *s);
-void do_interrupt(CPUM68KState *env1);
 void do_interrupt_m68k_hardirq(CPUM68KState *env1);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index e11f34b..30f7d8b 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -21,8 +21,11 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt(CPUM68KState *env)
+void m68k_cpu_do_interrupt(CPUState *cs)
 {
+    M68kCPU *cpu = M68K_CPU(cs);
+    CPUM68KState *env = &cpu->env;
+
     env->exception_index = -1;
 }
 
@@ -149,8 +152,11 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
     env->pc = cpu_ldl_kernel(env, env->vbr + vector);
 }
 
-void do_interrupt(CPUM68KState *env)
+void m68k_cpu_do_interrupt(CPUState *cs)
 {
+    M68kCPU *cpu = M68K_CPU(cs);
+    CPUM68KState *env = &cpu->env;
+
     do_interrupt_all(env, 0);
 }
 
diff --git a/target-microblaze/cpu-qom.h b/target-microblaze/cpu-qom.h
index a0248a5..aa51cf6 100644
--- a/target-microblaze/cpu-qom.h
+++ b/target-microblaze/cpu-qom.h
@@ -70,4 +70,6 @@ static inline MicroBlazeCPU *mb_env_get_cpu(CPUMBState *env)
 
 #define ENV_OFFSET offsetof(MicroBlazeCPU, env)
 
+void mb_cpu_do_interrupt(CPUState *cs);
+
 #endif
diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
index 81359db..0f4293d 100644
--- a/target-microblaze/cpu.c
+++ b/target-microblaze/cpu.c
@@ -131,6 +131,7 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
     mcc->parent_reset = cc->reset;
     cc->reset = mb_cpu_reset;
 
+    cc->do_interrupt = mb_cpu_do_interrupt;
     dc->vmsd = &vmstate_mb_cpu;
 }
 
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 7548aa9..1813939 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -275,7 +275,6 @@ struct CPUMBState {
 void mb_tcg_init(void);
 MicroBlazeCPU *cpu_mb_init(const char *cpu_model);
 int cpu_mb_exec(CPUMBState *s);
-void do_interrupt(CPUMBState *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.  */
diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c
index 97aedc5..a0416d0 100644
--- a/target-microblaze/helper.c
+++ b/target-microblaze/helper.c
@@ -26,8 +26,11 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt (CPUMBState *env)
+void mb_cpu_do_interrupt(CPUState *cs)
 {
+    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
+    CPUMBState *env = &cpu->env;
+
     env->exception_index = -1;
     env->res_addr = RES_ADDR_NONE;
     env->regs[14] = env->sregs[SR_PC];
@@ -109,8 +112,10 @@ int cpu_mb_handle_mmu_fault (CPUMBState *env, target_ulong address, int rw,
     return r;
 }
 
-void do_interrupt(CPUMBState *env)
+void mb_cpu_do_interrupt(CPUState *cs)
 {
+    MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
+    CPUMBState *env = &cpu->env;
     uint32_t t;
 
     /* IMM flag cannot propagate across a branch and into the dslot.  */
diff --git a/target-mips/cpu-qom.h b/target-mips/cpu-qom.h
index c6bcddf..32e3cad 100644
--- a/target-mips/cpu-qom.h
+++ b/target-mips/cpu-qom.h
@@ -74,4 +74,6 @@ static inline MIPSCPU *mips_env_get_cpu(CPUMIPSState *env)
 
 #define ENV_OFFSET offsetof(MIPSCPU, env)
 
+void mips_cpu_do_interrupt(CPUState *cpu);
+
 #endif
diff --git a/target-mips/cpu.c b/target-mips/cpu.c
index 4d62031..5315f7b 100644
--- a/target-mips/cpu.c
+++ b/target-mips/cpu.c
@@ -78,6 +78,8 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
 
     mcc->parent_reset = cc->reset;
     cc->reset = mips_cpu_reset;
+
+    cc->do_interrupt = mips_cpu_do_interrupt;
 }
 
 static const TypeInfo mips_cpu_type_info = {
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 22b0497..cedf03d 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -663,7 +663,6 @@ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level);
 int cpu_mips_handle_mmu_fault (CPUMIPSState *env, target_ulong address, int rw,
                                int mmu_idx);
 #define cpu_handle_mmu_fault cpu_mips_handle_mmu_fault
-void do_interrupt (CPUMIPSState *env);
 #if !defined(CONFIG_USER_ONLY)
 void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra);
 hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address,
diff --git a/target-mips/helper.c b/target-mips/helper.c
index e877b8d..3a54acf 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -396,10 +396,11 @@ static void set_hflags_for_handler (CPUMIPSState *env)
 }
 #endif
 
-void do_interrupt (CPUMIPSState *env)
+void mips_cpu_do_interrupt(CPUState *cs)
 {
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
 #if !defined(CONFIG_USER_ONLY)
-    MIPSCPU *cpu = mips_env_get_cpu(env);
     target_ulong offset;
     int cause = -1;
     const char *name;
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
index 72d5e8d..ffe14f3 100644
--- a/target-openrisc/cpu.c
+++ b/target-openrisc/cpu.c
@@ -148,6 +148,7 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
     cc->reset = openrisc_cpu_reset;
 
     cc->class_by_name = openrisc_cpu_class_by_name;
+    cc->do_interrupt = openrisc_cpu_do_interrupt;
 }
 
 static void cpu_register(const OpenRISCCPUInfo *info)
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 64370a3..b9c55ba 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -346,7 +346,7 @@ OpenRISCCPU *cpu_openrisc_init(const char *cpu_model);
 
 void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
 int cpu_openrisc_exec(CPUOpenRISCState *s);
-void do_interrupt(CPUOpenRISCState *env);
+void openrisc_cpu_do_interrupt(CPUState *cpu);
 void openrisc_translate_init(void);
 int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env,
                                   target_ulong address,
diff --git a/target-openrisc/interrupt.c b/target-openrisc/interrupt.c
index 7f2c025..16ef4b3 100644
--- a/target-openrisc/interrupt.c
+++ b/target-openrisc/interrupt.c
@@ -25,8 +25,10 @@
 #include "hw/loader.h"
 #endif
 
-void do_interrupt(CPUOpenRISCState *env)
+void openrisc_cpu_do_interrupt(CPUState *cs)
 {
+    OpenRISCCPU *cpu = OPENRISC_CPU(cs);
+    CPUOpenRISCState *env = &cpu->env;
 #ifndef CONFIG_USER_ONLY
     if (env->flags & D_FLAG) { /* Delay Slot insn */
         env->flags &= ~D_FLAG;
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index 2bf0ab6..09bfae3 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -95,4 +95,6 @@ static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)
 
 PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr);
 
+void ppc_cpu_do_interrupt(CPUState *cpu);
+
 #endif
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 1b31b1d..6886666 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1133,7 +1133,6 @@ int cpu_ppc_signal_handler (int host_signum, void *pinfo,
 int cpu_ppc_handle_mmu_fault (CPUPPCState *env, target_ulong address, int rw,
                               int mmu_idx);
 #define cpu_handle_mmu_fault cpu_ppc_handle_mmu_fault
-void do_interrupt (CPUPPCState *env);
 void ppc_hw_interrupt (CPUPPCState *env);
 
 #if !defined(CONFIG_USER_ONLY)
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index d176734..4a0fc6d 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -38,8 +38,11 @@ void (*cpu_ppc_hypercall)(PowerPCCPU *);
 /*****************************************************************************/
 /* Exception processing */
 #if defined(CONFIG_USER_ONLY)
-void do_interrupt(CPUPPCState *env)
+void ppc_cpu_do_interrupt(CPUState *cs)
 {
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
+
     env->exception_index = POWERPC_EXCP_NONE;
     env->error_code = 0;
 }
@@ -654,9 +657,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
     }
 }
 
-void do_interrupt(CPUPPCState *env)
+void ppc_cpu_do_interrupt(CPUState *cs)
 {
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
 
     powerpc_excp(cpu, env->excp_model, env->exception_index);
 }
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 09ad4ba..15eebe9 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8427,6 +8427,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
     cc->reset = ppc_cpu_reset;
 
     cc->class_by_name = ppc_cpu_class_by_name;
+    cc->do_interrupt = ppc_cpu_do_interrupt;
 }
 
 static const TypeInfo ppc_cpu_type_info = {
diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h
index f6e5145..34d45c2 100644
--- a/target-s390x/cpu-qom.h
+++ b/target-s390x/cpu-qom.h
@@ -71,4 +71,6 @@ static inline S390CPU *s390_env_get_cpu(CPUS390XState *env)
 
 #define ENV_OFFSET offsetof(S390CPU, env)
 
+void s390_cpu_do_interrupt(CPUState *cpu);
+
 #endif
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index 738a0ad..23fe51f 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -169,6 +169,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
     scc->parent_reset = cc->reset;
     cc->reset = s390_cpu_reset;
 
+    cc->do_interrupt = s390_cpu_do_interrupt;
     dc->vmsd = &vmstate_s390_cpu;
 }
 
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 642e661..e351005 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -315,7 +315,6 @@ static inline int get_ilen(uint8_t opc)
 S390CPU *cpu_s390x_init(const char *cpu_model);
 void s390x_translate_init(void);
 int cpu_s390x_exec(CPUS390XState *s);
-void do_interrupt (CPUS390XState *env);
 
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 2cb8dc8..b425054 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -86,8 +86,11 @@ S390CPU *cpu_s390x_init(const char *cpu_model)
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt(CPUS390XState *env)
+void s390_cpu_do_interrupt(CPUState *cs)
 {
+    S390CPU *cpu = S390_CPU(cs);
+    CPUS390XState *env = &cpu->env;
+
     env->exception_index = -1;
 }
 
@@ -737,10 +740,10 @@ static void do_mchk_interrupt(CPUS390XState *env)
     load_psw(env, mask, addr);
 }
 
-void do_interrupt(CPUS390XState *env)
+void s390_cpu_do_interrupt(CPUState *cs)
 {
-    S390CPU *cpu = s390_env_get_cpu(env);
-    CPUState *cs;
+    S390CPU *cpu = S390_CPU(cs);
+    CPUS390XState *env = &cpu->env;
 
     qemu_log_mask(CPU_LOG_INT, "%s: %d at pc=%" PRIx64 "\n",
                   __func__, env->exception_index, env->psw.addr);
@@ -799,7 +802,6 @@ void do_interrupt(CPUS390XState *env)
     env->exception_index = -1;
 
     if (!env->pending_int) {
-        cs = CPU(s390_env_get_cpu(env));
         cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
     }
 }
diff --git a/target-sh4/cpu-qom.h b/target-sh4/cpu-qom.h
index 29628c8..f8c80d3 100644
--- a/target-sh4/cpu-qom.h
+++ b/target-sh4/cpu-qom.h
@@ -83,4 +83,6 @@ static inline SuperHCPU *sh_env_get_cpu(CPUSH4State *env)
 
 #define ENV_OFFSET offsetof(SuperHCPU, env)
 
+void superh_cpu_do_interrupt(CPUState *cpu);
+
 #endif
diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c
index 5251aa0..898aecd 100644
--- a/target-sh4/cpu.c
+++ b/target-sh4/cpu.c
@@ -273,6 +273,7 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data)
     cc->reset = superh_cpu_reset;
 
     cc->class_by_name = superh_cpu_class_by_name;
+    cc->do_interrupt = superh_cpu_do_interrupt;
     dc->vmsd = &vmstate_sh_cpu;
 }
 
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 4966355..fd7da92 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -196,7 +196,6 @@ int cpu_sh4_signal_handler(int host_signum, void *pinfo,
 int cpu_sh4_handle_mmu_fault(CPUSH4State * env, target_ulong address, int rw,
                              int mmu_idx);
 #define cpu_handle_mmu_fault cpu_sh4_handle_mmu_fault
-void do_interrupt(CPUSH4State * env);
 
 void sh4_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 #if !defined(CONFIG_USER_ONLY)
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index fd4efee..0a9cb3a 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -31,9 +31,12 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt (CPUSH4State *env)
+void superh_cpu_do_interrupt(CPUState *cs)
 {
-  env->exception_index = -1;
+    SuperHCPU *cpu = SUPERH_CPU(cs);
+    CPUSH4State *env = &cpu->env;
+
+    env->exception_index = -1;
 }
 
 int cpu_sh4_handle_mmu_fault(CPUSH4State * env, target_ulong address, int rw,
@@ -78,9 +81,10 @@ int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr)
 #define MMU_DADDR_ERROR_READ     (-12)
 #define MMU_DADDR_ERROR_WRITE    (-13)
 
-void do_interrupt(CPUSH4State *env)
+void superh_cpu_do_interrupt(CPUState *cs)
 {
-    CPUState *cs = CPU(sh_env_get_cpu(env));
+    SuperHCPU *cpu = SUPERH_CPU(cs);
+    CPUSH4State *env = &cpu->env;
     int do_irq = cs->interrupt_request & CPU_INTERRUPT_HARD;
     int do_exp, irq_vector = env->exception_index;
 
diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h
index efeeca0..d4fe89e 100644
--- a/target-sparc/cpu-qom.h
+++ b/target-sparc/cpu-qom.h
@@ -75,4 +75,6 @@ static inline SPARCCPU *sparc_env_get_cpu(CPUSPARCState *env)
 
 #define ENV_OFFSET offsetof(SPARCCPU, env)
 
+void sparc_cpu_do_interrupt(CPUState *cpu);
+
 #endif
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index 50def61..ab1adfd 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -891,6 +891,8 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
 
     scc->parent_reset = cc->reset;
     cc->reset = sparc_cpu_reset;
+
+    cc->do_interrupt = sparc_cpu_do_interrupt;
 }
 
 static const TypeInfo sparc_cpu_type_info = {
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 8a2f8df..6fa7778 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -553,7 +553,6 @@ int cpu_cwp_dec(CPUSPARCState *env1, int cwp);
 void cpu_set_cwp(CPUSPARCState *env1, int new_cwp);
 
 /* int_helper.c */
-void do_interrupt(CPUSPARCState *env);
 void leon3_irq_manager(CPUSPARCState *env, void *irq_manager, int intno);
 
 /* sun4m.c, sun4u.c */
diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c
index c35f522..7221460 100644
--- a/target-sparc/int32_helper.c
+++ b/target-sparc/int32_helper.c
@@ -58,8 +58,10 @@ static const char * const excp_names[0x80] = {
 };
 #endif
 
-void do_interrupt(CPUSPARCState *env)
+void sparc_cpu_do_interrupt(CPUState *cs)
 {
+    SPARCCPU *cpu = SPARC_CPU(cs);
+    CPUSPARCState *env = &cpu->env;
     int cwp, intno = env->exception_index;
 
     /* Compute PSR before exposing state.  */
diff --git a/target-sparc/int64_helper.c b/target-sparc/int64_helper.c
index df37aa1..f411884 100644
--- a/target-sparc/int64_helper.c
+++ b/target-sparc/int64_helper.c
@@ -59,8 +59,10 @@ static const char * const excp_names[0x80] = {
 };
 #endif
 
-void do_interrupt(CPUSPARCState *env)
+void sparc_cpu_do_interrupt(CPUState *cs)
 {
+    SPARCCPU *cpu = SPARC_CPU(cs);
+    CPUSPARCState *env = &cpu->env;
     int intno = env->exception_index;
     trap_state *tsptr;
 
diff --git a/target-unicore32/cpu-qom.h b/target-unicore32/cpu-qom.h
index c6590bd..ba4dee4 100644
--- a/target-unicore32/cpu-qom.h
+++ b/target-unicore32/cpu-qom.h
@@ -60,4 +60,6 @@ static inline UniCore32CPU *uc32_env_get_cpu(CPUUniCore32State *env)
 
 #define ENV_OFFSET offsetof(UniCore32CPU, env)
 
+void uc32_cpu_do_interrupt(CPUState *cpu);
+
 #endif
diff --git a/target-unicore32/cpu.c b/target-unicore32/cpu.c
index b7024c8..66a1a74 100644
--- a/target-unicore32/cpu.c
+++ b/target-unicore32/cpu.c
@@ -132,6 +132,7 @@ static void uc32_cpu_class_init(ObjectClass *oc, void *data)
     dc->realize = uc32_cpu_realizefn;
 
     cc->class_by_name = uc32_cpu_class_by_name;
+    cc->do_interrupt = uc32_cpu_do_interrupt;
     dc->vmsd = &vmstate_uc32_cpu;
 }
 
diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h
index 58f1f20..5b2b9d1 100644
--- a/target-unicore32/cpu.h
+++ b/target-unicore32/cpu.h
@@ -176,7 +176,6 @@ static inline void cpu_get_tb_cpu_state(CPUUniCore32State *env, target_ulong *pc
 }
 
 void uc32_translate_init(void);
-void do_interrupt(CPUUniCore32State *);
 void switch_mode(CPUUniCore32State *, int);
 
 static inline bool cpu_has_work(CPUState *cpu)
diff --git a/target-unicore32/helper.c b/target-unicore32/helper.c
index 7eeb9bc..61eb2c3 100644
--- a/target-unicore32/helper.c
+++ b/target-unicore32/helper.c
@@ -242,8 +242,11 @@ void switch_mode(CPUUniCore32State *env, int mode)
     }
 }
 
-void do_interrupt(CPUUniCore32State *env)
+void uc32_cpu_do_interrupt(CPUState *cs)
 {
+    UniCore32CPU *cpu = UNICORE32_CPU(cs);
+    CPUUniCore32State *env = &cpu->env;
+
     cpu_abort(env, "NO interrupt in user mode\n");
 }
 
diff --git a/target-unicore32/softmmu.c b/target-unicore32/softmmu.c
index 1c4c7f5..eadaeb1 100644
--- a/target-unicore32/softmmu.c
+++ b/target-unicore32/softmmu.c
@@ -72,9 +72,10 @@ void switch_mode(CPUUniCore32State *env, int mode)
 }
 
 /* Handle a CPU exception.  */
-void do_interrupt(CPUUniCore32State *env)
+void uc32_cpu_do_interrupt(CPUState *cs)
 {
-    CPUState *cs = CPU(uc32_env_get_cpu(env));
+    UniCore32CPU *cpu = UNICORE32_CPU(cs);
+    CPUUniCore32State *env = &cpu->env;
     uint32_t addr;
     int new_mode;
 
diff --git a/target-xtensa/cpu-qom.h b/target-xtensa/cpu-qom.h
index c78136b..af0ce28 100644
--- a/target-xtensa/cpu-qom.h
+++ b/target-xtensa/cpu-qom.h
@@ -80,4 +80,6 @@ static inline XtensaCPU *xtensa_env_get_cpu(const CPUXtensaState *env)
 
 #define ENV_OFFSET offsetof(XtensaCPU, env)
 
+void xtensa_cpu_do_interrupt(CPUState *cpu);
+
 #endif
diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
index 785e56d..6e93dd8 100644
--- a/target-xtensa/cpu.c
+++ b/target-xtensa/cpu.c
@@ -101,6 +101,7 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
     xcc->parent_reset = cc->reset;
     cc->reset = xtensa_cpu_reset;
 
+    cc->do_interrupt = xtensa_cpu_do_interrupt;
     dc->vmsd = &vmstate_xtensa_cpu;
 }
 
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index dece224..6c9fc35 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -388,7 +388,6 @@ void xtensa_translate_init(void);
 void xtensa_breakpoint_handler(CPUXtensaState *env);
 int cpu_xtensa_exec(CPUXtensaState *s);
 void xtensa_register_core(XtensaConfigList *node);
-void do_interrupt(CPUXtensaState *s);
 void check_interrupts(CPUXtensaState *s);
 void xtensa_irq_init(CPUXtensaState *env);
 void *xtensa_get_extint(CPUXtensaState *env, unsigned extint);
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index a8a6493..6f613c66 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -178,8 +178,11 @@ static void handle_interrupt(CPUXtensaState *env)
     }
 }
 
-void do_interrupt(CPUXtensaState *env)
+void xtensa_cpu_do_interrupt(CPUState *cs)
 {
+    XtensaCPU *cpu = XTENSA_CPU(cs);
+    CPUXtensaState *env = &cpu->env;
+
     if (env->exception_index == EXC_IRQ) {
         qemu_log_mask(CPU_LOG_INT,
                 "%s(EXC_IRQ) level = %d, cintlevel = %d, "
commit c3affe5670e5d0df8a7e06f1d6e80853633146df
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Jan 18 15:03:43 2013 +0100

    cpu: Pass CPUState to cpu_interrupt()
    
    Move it to qom/cpu.h to avoid issues with include order.
    
    Change pc_acpi_smi_interrupt() opaque to X86CPU.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/cpus.c b/cpus.c
index 8d47bfd..e919dd7 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1309,7 +1309,7 @@ void qmp_inject_nmi(Error **errp)
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
         if (!env->apic_state) {
-            cpu_interrupt(env, CPU_INTERRUPT_NMI);
+            cpu_interrupt(CPU(x86_env_get_cpu(env)), CPU_INTERRUPT_NMI);
         } else {
             apic_deliver_nmi(env->apic_state);
         }
diff --git a/exec.c b/exec.c
index ae5a4b4..c5e65a9 100644
--- a/exec.c
+++ b/exec.c
@@ -1467,7 +1467,7 @@ static void check_watchpoint(int offset, int len_mask, int flags)
         /* We re-entered the check after replacing the TB. Now raise
          * the debug interrupt so that is will trigger after the
          * current instruction. */
-        cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
+        cpu_interrupt(ENV_GET_CPU(env), CPU_INTERRUPT_DEBUG);
         return;
     }
     vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index 7bfde57..770dc8c 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -62,10 +62,9 @@ static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
 {
     /* If there are any non-masked interrupts, tell the cpu.  */
     if (cpu != NULL) {
-        CPUAlphaState *env = &cpu->env;
         CPUState *cs = CPU(cpu);
         if (req) {
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
         } else {
             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
         }
@@ -359,11 +358,10 @@ static void cchip_write(void *opaque, hwaddr addr,
             for (i = 0; i < 4; ++i) {
                 AlphaCPU *cpu = s->cchip.cpu[i];
                 if (cpu != NULL) {
-                    CPUAlphaState *env = &cpu->env;
                     CPUState *cs = CPU(cpu);
                     /* IPI can be either cleared or set by the write.  */
                     if (newval & (1 << (i + 8))) {
-                        cpu_interrupt(env, CPU_INTERRUPT_SMP);
+                        cpu_interrupt(cs, CPU_INTERRUPT_SMP);
                     } else {
                         cpu_reset_interrupt(cs, CPU_INTERRUPT_SMP);
                     }
@@ -687,7 +685,7 @@ static void typhoon_set_timer_irq(void *opaque, int irq, int level)
                 /* Set the ITI bit for this cpu.  */
                 s->cchip.misc |= 1 << (i + 4);
                 /* And signal the interrupt.  */
-                cpu_interrupt(&cpu->env, CPU_INTERRUPT_TIMER);
+                cpu_interrupt(CPU(cpu), CPU_INTERRUPT_TIMER);
             }
         }
     }
@@ -700,7 +698,7 @@ static void typhoon_alarm_timer(void *opaque)
 
     /* Set the ITI bit for this cpu.  */
     s->cchip.misc |= 1 << (cpu + 4);
-    cpu_interrupt(&s->cchip.cpu[cpu]->env, CPU_INTERRUPT_TIMER);
+    cpu_interrupt(CPU(s->cchip.cpu[cpu]), CPU_INTERRUPT_TIMER);
 }
 
 PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
diff --git a/hw/apic.c b/hw/apic.c
index cc9236a..d2395f0 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -151,15 +151,15 @@ static void apic_local_deliver(APICCommonState *s, int vector)
 
     switch ((lvt >> 8) & 7) {
     case APIC_DM_SMI:
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_SMI);
+        cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_SMI);
         break;
 
     case APIC_DM_NMI:
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_NMI);
+        cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_NMI);
         break;
 
     case APIC_DM_EXTINT:
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HARD);
         break;
 
     case APIC_DM_FIXED:
@@ -248,20 +248,20 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask,
 
         case APIC_DM_SMI:
             foreach_apic(apic_iter, deliver_bitmask,
-                cpu_interrupt(&apic_iter->cpu->env, CPU_INTERRUPT_SMI)
+                cpu_interrupt(CPU(apic_iter->cpu), CPU_INTERRUPT_SMI)
             );
             return;
 
         case APIC_DM_NMI:
             foreach_apic(apic_iter, deliver_bitmask,
-                cpu_interrupt(&apic_iter->cpu->env, CPU_INTERRUPT_NMI)
+                cpu_interrupt(CPU(apic_iter->cpu), CPU_INTERRUPT_NMI)
             );
             return;
 
         case APIC_DM_INIT:
             /* normal INIT IPI sent to processors */
             foreach_apic(apic_iter, deliver_bitmask,
-                         cpu_interrupt(&apic_iter->cpu->env,
+                         cpu_interrupt(CPU(apic_iter->cpu),
                                        CPU_INTERRUPT_INIT)
             );
             return;
@@ -363,15 +363,16 @@ static int apic_irq_pending(APICCommonState *s)
 /* signal the CPU if an irq is pending */
 static void apic_update_irq(APICCommonState *s)
 {
-    CPUState *cpu = CPU(s->cpu);
+    CPUState *cpu;
 
     if (!(s->spurious_vec & APIC_SV_ENABLE)) {
         return;
     }
+    cpu = CPU(s->cpu);
     if (!qemu_cpu_is_self(cpu)) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_POLL);
+        cpu_interrupt(cpu, CPU_INTERRUPT_POLL);
     } else if (apic_irq_pending(s) > 0) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cpu, CPU_INTERRUPT_HARD);
     }
 }
 
@@ -478,7 +479,7 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
 static void apic_startup(APICCommonState *s, int vector_num)
 {
     s->sipi_vector = vector_num;
-    cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_SIPI);
+    cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI);
 }
 
 void apic_sipi(DeviceState *d)
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
index 7afd590..3245c62 100644
--- a/hw/arm/omap1.c
+++ b/hw/arm/omap1.c
@@ -1523,7 +1523,7 @@ static inline void omap_clkm_idlect1_update(struct omap_mpu_state_s *s,
     omap_clk clk;
 
     if (value & (1 << 11)) {                            /* SETARM_IDLE */
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
+        cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HALT);
     }
     if (!(value & (1 << 10)))				/* WKUP_MODE */
         qemu_system_shutdown_request();	/* XXX: disable wakeup from IRQ */
@@ -3759,7 +3759,7 @@ void omap_mpu_wakeup(void *opaque, int irq, int req)
     CPUState *cpu = CPU(mpu->cpu);
 
     if (cpu->halted) {
-        cpu_interrupt(&mpu->cpu->env, CPU_INTERRUPT_EXITTB);
+        cpu_interrupt(cpu, CPU_INTERRUPT_EXITTB);
     }
 }
 
diff --git a/hw/arm/pic_cpu.c b/hw/arm/pic_cpu.c
index 95f5bf1..3a3f065 100644
--- a/hw/arm/pic_cpu.c
+++ b/hw/arm/pic_cpu.c
@@ -15,20 +15,19 @@
 static void arm_pic_cpu_handler(void *opaque, int irq, int level)
 {
     ARMCPU *cpu = opaque;
-    CPUARMState *env = &cpu->env;
     CPUState *cs = CPU(cpu);
 
     switch (irq) {
     case ARM_PIC_CPU_IRQ:
         if (level) {
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
         } else {
             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
         }
         break;
     case ARM_PIC_CPU_FIQ:
         if (level) {
-            cpu_interrupt(env, CPU_INTERRUPT_FIQ);
+            cpu_interrupt(cs, CPU_INTERRUPT_FIQ);
         } else {
             cpu_reset_interrupt(cs, CPU_INTERRUPT_FIQ);
         }
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index c0f50c9..7467cca 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -263,14 +263,14 @@ static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
     case 1:
         /* Idle */
         if (!(s->cm_regs[CCCR >> 2] & (1 << 31))) { /* CPDIS */
-            cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
+            cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HALT);
             break;
         }
         /* Fall through.  */
 
     case 2:
         /* Deep-Idle */
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
+        cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HALT);
         s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
         goto message;
 
@@ -301,7 +301,8 @@ static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
 #endif
 
         /* Suspend */
-        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
+        cpu_interrupt(CPU(arm_env_get_cpu(cpu_single_env)),
+                      CPU_INTERRUPT_HALT);
 
         goto message;
 
diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c
index d2da928..55ebcd7 100644
--- a/hw/arm/pxa2xx_gpio.c
+++ b/hw/arm/pxa2xx_gpio.c
@@ -120,7 +120,7 @@ static void pxa2xx_gpio_set(void *opaque, int line, int level)
 
     /* Wake-up GPIOs */
     if (cpu->halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
+        cpu_interrupt(cpu, CPU_INTERRUPT_EXITTB);
     }
 }
 
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
index b45b371..25e9089 100644
--- a/hw/arm/pxa2xx_pic.c
+++ b/hw/arm/pxa2xx_pic.c
@@ -52,7 +52,7 @@ static void pxa2xx_pic_update(void *opaque)
         mask[0] = s->int_pending[0] & (s->int_enabled[0] | s->int_idle);
         mask[1] = s->int_pending[1] & (s->int_enabled[1] | s->int_idle);
         if (mask[0] || mask[1]) {
-            cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
+            cpu_interrupt(cpu, CPU_INTERRUPT_EXITTB);
         }
     }
 
@@ -60,13 +60,13 @@ static void pxa2xx_pic_update(void *opaque)
     mask[1] = s->int_pending[1] & s->int_enabled[1];
 
     if ((mask[0] & s->is_fiq[0]) || (mask[1] & s->is_fiq[1])) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
+        cpu_interrupt(cpu, CPU_INTERRUPT_FIQ);
     } else {
         cpu_reset_interrupt(cpu, CPU_INTERRUPT_FIQ);
     }
 
     if ((mask[0] & ~s->is_fiq[0]) || (mask[1] & ~s->is_fiq[1])) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cpu, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD);
     }
diff --git a/hw/cris/pic_cpu.c b/hw/cris/pic_cpu.c
index afd0df8..85c68c0 100644
--- a/hw/cris/pic_cpu.c
+++ b/hw/cris/pic_cpu.c
@@ -31,12 +31,11 @@
 static void cris_pic_cpu_handler(void *opaque, int irq, int level)
 {
     CRISCPU *cpu = opaque;
-    CPUCRISState *env = &cpu->env;
     CPUState *cs = CPU(cpu);
     int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
 
     if (level) {
-        cpu_interrupt(env, type);
+        cpu_interrupt(cs, type);
     } else {
         cpu_reset_interrupt(cs, type);
     }
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index c731bdc..ed7d9ba 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -192,7 +192,7 @@ static void pic_irq_request(void *opaque, int irq, int level)
     } else {
         CPUState *cs = CPU(x86_env_get_cpu(env));
         if (level) {
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
         } else {
             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
         }
@@ -856,10 +856,10 @@ DeviceState *cpu_get_current_apic(void)
 
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
 {
-    CPUX86State *s = opaque;
+    X86CPU *cpu = opaque;
 
     if (level) {
-        cpu_interrupt(s, CPU_INTERRUPT_SMI);
+        cpu_interrupt(CPU(cpu), CPU_INTERRUPT_SMI);
     }
 }
 
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 0ee3b3b..0abc9f1 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -205,7 +205,8 @@ static void pc_init1(MemoryRegion *system_memory,
     if (pci_enabled && acpi_enabled) {
         i2c_bus *smbus;
 
-        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
+        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt,
+                                     x86_env_get_cpu(first_cpu), 1);
         /* TODO: Populate SPD eeprom data.  */
         smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
                               gsi[9], *smi_irq,
diff --git a/hw/lm32/lm32_boards.c b/hw/lm32/lm32_boards.c
index 538c203..db92948 100644
--- a/hw/lm32/lm32_boards.c
+++ b/hw/lm32/lm32_boards.c
@@ -42,11 +42,10 @@ typedef struct {
 static void cpu_irq_handler(void *opaque, int irq, int level)
 {
     LM32CPU *cpu = opaque;
-    CPULM32State *env = &cpu->env;
     CPUState *cs = CPU(cpu);
 
     if (level) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
index 9ff6d28..b347cf9 100644
--- a/hw/lm32/milkymist.c
+++ b/hw/lm32/milkymist.c
@@ -47,11 +47,10 @@ typedef struct {
 static void cpu_irq_handler(void *opaque, int irq, int level)
 {
     LM32CPU *cpu = opaque;
-    CPULM32State *env = &cpu->env;
     CPUState *cs = CPU(cpu);
 
     if (level) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
index 0ca0a59..ff0a309 100644
--- a/hw/lpc_ich9.c
+++ b/hw/lpc_ich9.c
@@ -381,7 +381,7 @@ static void ich9_apm_ctrl_changed(uint32_t val, void *arg)
 
     /* SMI_EN = PMBASE + 30. SMI control and enable register */
     if (lpc->pm.smi_en & ICH9_PMIO_SMI_EN_APMC_EN) {
-        cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI);
+        cpu_interrupt(CPU(x86_env_get_cpu(first_cpu)), CPU_INTERRUPT_SMI);
     }
 }
 
diff --git a/hw/microblaze/pic_cpu.c b/hw/microblaze/pic_cpu.c
index 4756850..6248de9 100644
--- a/hw/microblaze/pic_cpu.c
+++ b/hw/microblaze/pic_cpu.c
@@ -30,12 +30,11 @@
 static void microblaze_pic_cpu_handler(void *opaque, int irq, int level)
 {
     MicroBlazeCPU *cpu = opaque;
-    CPUMBState *env = &cpu->env;
     CPUState *cs = CPU(cpu);
     int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
 
     if (level) {
-        cpu_interrupt(env, type);
+        cpu_interrupt(cs, type);
     } else {
         cpu_reset_interrupt(cs, type);
     }
diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
index 3a78999..0e5e866 100644
--- a/hw/mips/mips_int.c
+++ b/hw/mips/mips_int.c
@@ -40,7 +40,7 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
     }
 
     if (env->CP0_Cause & CP0Ca_IP_mask) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
diff --git a/hw/openrisc/pic_cpu.c b/hw/openrisc/pic_cpu.c
index 7e4f9e0..ca0b7c1 100644
--- a/hw/openrisc/pic_cpu.c
+++ b/hw/openrisc/pic_cpu.c
@@ -41,7 +41,7 @@ static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
 
     for (i = 0; i < 32; i++) {
         if ((cpu->env.picsr && (1 << i)) && (cpu->env.picmr && (1 << i))) {
-            cpu_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
         } else {
             cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
             cpu->env.picsr &= ~(1 << i);
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index ae2ed70..85bc821 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -58,7 +58,7 @@ void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
 
     if (level) {
         env->pending_interrupts |= 1 << n_IRQ;
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         env->pending_interrupts &= ~(1 << n_IRQ);
         if (env->pending_interrupts == 0) {
@@ -137,7 +137,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
             /* Level sensitive - active low */
             if (level) {
                 LOG_IRQ("%s: reset the CPU\n", __func__);
-                cpu_interrupt(env, CPU_INTERRUPT_RESET);
+                cpu_interrupt(cs, CPU_INTERRUPT_RESET);
             }
             break;
         case PPC6xx_INPUT_SRESET:
@@ -219,7 +219,7 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
         case PPC970_INPUT_HRESET:
             /* Level sensitive - active low */
             if (level) {
-                cpu_interrupt(env, CPU_INTERRUPT_RESET);
+                cpu_interrupt(cs, CPU_INTERRUPT_RESET);
             }
             break;
         case PPC970_INPUT_SRESET:
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 8465f6d..56bae8f 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1776,7 +1776,7 @@ void ppc40x_core_reset(PowerPCCPU *cpu)
     target_ulong dbsr;
 
     printf("Reset PowerPC core\n");
-    cpu_interrupt(env, CPU_INTERRUPT_RESET);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_RESET);
     dbsr = env->spr[SPR_40x_DBSR];
     dbsr &= ~0x00000300;
     dbsr |= 0x00000100;
@@ -1789,7 +1789,7 @@ void ppc40x_chip_reset(PowerPCCPU *cpu)
     target_ulong dbsr;
 
     printf("Reset PowerPC chip\n");
-    cpu_interrupt(env, CPU_INTERRUPT_RESET);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_RESET);
     /* XXX: TODO reset all internal peripherals */
     dbsr = env->spr[SPR_40x_DBSR];
     dbsr &= ~0x00000300;
diff --git a/hw/sh_intc.c b/hw/sh_intc.c
index 9790314..29e3d8f 100644
--- a/hw/sh_intc.c
+++ b/hw/sh_intc.c
@@ -45,8 +45,9 @@ void sh_intc_toggle_source(struct intc_source *source,
         CPUState *cpu = CPU(sh_env_get_cpu(first_cpu));
         if (source->pending) {
             source->parent->pending++;
-	    if (source->parent->pending == 1)
-                cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD);
+            if (source->parent->pending == 1) {
+                cpu_interrupt(cpu, CPU_INTERRUPT_HARD);
+            }
         } else {
             source->parent->pending--;
             if (source->parent->pending == 0) {
diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
index b1fbde0..bf06bf4 100644
--- a/hw/sparc/leon3.c
+++ b/hw/sparc/leon3.c
@@ -83,8 +83,9 @@ static void leon3_set_pil_in(void *opaque, uint32_t pil_in)
 
                 env->interrupt_index = TT_EXTINT | i;
                 if (old_interrupt != env->interrupt_index) {
+                    cs = CPU(sparc_env_get_cpu(env));
                     trace_leon3_set_irq(i);
-                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+                    cpu_interrupt(cs, CPU_INTERRUPT_HARD);
                 }
                 break;
             }
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index a1822f1..2f214da 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -242,8 +242,9 @@ void cpu_check_irqs(CPUSPARCState *env)
 
                 env->interrupt_index = TT_EXTINT | i;
                 if (old_interrupt != env->interrupt_index) {
+                    cs = CPU(sparc_env_get_cpu(env));
                     trace_sun4m_cpu_interrupt(i);
-                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+                    cpu_interrupt(cs, CPU_INTERRUPT_HARD);
                 }
                 break;
             }
@@ -306,8 +307,10 @@ static void secondary_cpu_reset(void *opaque)
 
 static void cpu_halt_signal(void *opaque, int irq, int level)
 {
-    if (level && cpu_single_env)
-        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
+    if (level && cpu_single_env) {
+        cpu_interrupt(CPU(sparc_env_get_cpu(cpu_single_env)),
+                      CPU_INTERRUPT_HALT);
+    }
 }
 
 static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 817c23c..4c39cf6 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -299,7 +299,7 @@ void cpu_check_irqs(CPUSPARCState *env)
                     env->interrupt_index = new_interrupt;
                     CPUIRQ_DPRINTF("Set CPU IRQ %d old=%x new=%x\n", i,
                                    old_interrupt, new_interrupt);
-                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+                    cpu_interrupt(cs, CPU_INTERRUPT_HARD);
                 }
                 break;
             }
@@ -339,7 +339,7 @@ static void cpu_set_ivec_irq(void *opaque, int irq, int level)
             env->ivec_data[0] = (0x1f << 6) | irq;
             env->ivec_data[1] = 0;
             env->ivec_data[2] = 0;
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
         }
     } else {
         if (env->ivec_status & 0x20) {
diff --git a/hw/unicore32/puv3.c b/hw/unicore32/puv3.c
index 6e87c41..78ab13f 100644
--- a/hw/unicore32/puv3.c
+++ b/hw/unicore32/puv3.c
@@ -27,12 +27,11 @@
 static void puv3_intc_cpu_handler(void *opaque, int irq, int level)
 {
     UniCore32CPU *cpu = opaque;
-    CPUUniCore32State *env = &cpu->env;
     CPUState *cs = CPU(cpu);
 
     assert(irq == 0);
     if (level) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
diff --git a/hw/xtensa/pic_cpu.c b/hw/xtensa/pic_cpu.c
index fd590c6..7f015ff 100644
--- a/hw/xtensa/pic_cpu.c
+++ b/hw/xtensa/pic_cpu.c
@@ -66,7 +66,7 @@ void check_interrupts(CPUXtensaState *env)
     for (level = env->config->nlevel; level > minlevel; --level) {
         if (env->config->level_mask[level] & int_set_enabled) {
             env->pending_irq_level = level;
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
             qemu_log_mask(CPU_LOG_INT,
                     "%s level = %d, cintlevel = %d, "
                     "pc = %08x, a0 = %08x, ps = %08x, "
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 5218a53..e9c3717 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -421,19 +421,6 @@ DECLARE_TLS(CPUArchState *,cpu_single_env);
      | CPU_INTERRUPT_TGT_EXT_3   \
      | CPU_INTERRUPT_TGT_EXT_4)
 
-#ifndef CONFIG_USER_ONLY
-typedef void (*CPUInterruptHandler)(CPUArchState *, int);
-
-extern CPUInterruptHandler cpu_interrupt_handler;
-
-static inline void cpu_interrupt(CPUArchState *s, int mask)
-{
-    cpu_interrupt_handler(s, mask);
-}
-#else /* USER_ONLY */
-void cpu_interrupt(CPUArchState *env, int mask);
-#endif /* USER_ONLY */
-
 void cpu_exit(CPUArchState *s);
 
 /* Breakpoint/watchpoint flags */
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index b83ba6f..2e08135 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -221,6 +221,30 @@ void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data);
  */
 CPUState *qemu_get_cpu(int index);
 
+#ifndef CONFIG_USER_ONLY
+
+typedef void (*CPUInterruptHandler)(CPUState *, int);
+
+extern CPUInterruptHandler cpu_interrupt_handler;
+
+/**
+ * cpu_interrupt:
+ * @cpu: The CPU to set an interrupt on.
+ * @mask: The interupts to set.
+ *
+ * Invokes the interrupt handler.
+ */
+static inline void cpu_interrupt(CPUState *cpu, int mask)
+{
+    cpu_interrupt_handler(cpu, mask);
+}
+
+#else /* USER_ONLY */
+
+void cpu_interrupt(CPUState *cpu, int mask);
+
+#endif /* USER_ONLY */
+
 /**
  * cpu_reset_interrupt:
  * @cpu: The CPU to clear the interrupt on.
diff --git a/kvm-all.c b/kvm-all.c
index 2b761e0..9b433d3 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -826,10 +826,8 @@ static MemoryListener kvm_io_listener = {
     .priority = 10,
 };
 
-static void kvm_handle_interrupt(CPUArchState *env, int mask)
+static void kvm_handle_interrupt(CPUState *cpu, int mask)
 {
-    CPUState *cpu = ENV_GET_CPU(env);
-
     cpu->interrupt_request |= mask;
 
     if (!qemu_cpu_is_self(cpu)) {
diff --git a/target-arm/helper.c b/target-arm/helper.c
index d7e22dd..f839726 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -764,7 +764,7 @@ static int omap_wfi_write(CPUARMState *env, const ARMCPRegInfo *ri,
                           uint64_t value)
 {
     /* Wait-for-interrupt (deprecated) */
-    cpu_interrupt(env, CPU_INTERRUPT_HALT);
+    cpu_interrupt(CPU(arm_env_get_cpu(env)), CPU_INTERRUPT_HALT);
     return 0;
 }
 
diff --git a/target-i386/helper.c b/target-i386/helper.c
index b49a0fc..9449a0c 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -389,7 +389,7 @@ void x86_cpu_set_a20(X86CPU *cpu, int a20_state)
 #endif
         /* if the cpu is currently executing code, we must unlink it and
            all the potentially executing TB */
-        cpu_interrupt(env, CPU_INTERRUPT_EXITTB);
+        cpu_interrupt(CPU(cpu), CPU_INTERRUPT_EXITTB);
 
         /* when a20 is changed, all the MMU mappings are invalid, so
            we must flush everything */
@@ -1169,7 +1169,7 @@ static void do_inject_x86_mce(void *data)
         banks[3] = params->misc;
         cenv->mcg_status = params->mcg_status;
         banks[1] = params->status;
-        cpu_interrupt(cenv, CPU_INTERRUPT_MCE);
+        cpu_interrupt(cpu, CPU_INTERRUPT_MCE);
     } else if (!(banks[1] & MCI_STATUS_VAL)
                || !(banks[1] & MCI_STATUS_UC)) {
         if (banks[1] & MCI_STATUS_VAL) {
@@ -1241,7 +1241,7 @@ void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
     if (kvm_enabled()) {
         env->tpr_access_type = access;
 
-        cpu_interrupt(env, CPU_INTERRUPT_TPR);
+        cpu_interrupt(CPU(x86_env_get_cpu(env)), CPU_INTERRUPT_TPR);
     } else {
         cpu_restore_state(env, env->mem_io_pc);
 
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index d9c8374..54fa419 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -318,7 +318,7 @@ void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
     env->pending_level = level;
     env->pending_vector = vector;
     if (level) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
     } else {
         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index d568188..3fa0d00 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -523,12 +523,12 @@ static bool mips_vpe_is_wfi(MIPSCPU *c)
     return cpu->halted && mips_vpe_active(env);
 }
 
-static inline void mips_vpe_wake(CPUMIPSState *c)
+static inline void mips_vpe_wake(MIPSCPU *c)
 {
     /* Dont set ->halted = 0 directly, let it be done via cpu_has_work
        because there might be other conditions that state that c should
        be sleeping.  */
-    cpu_interrupt(c, CPU_INTERRUPT_WAKE);
+    cpu_interrupt(CPU(c), CPU_INTERRUPT_WAKE);
 }
 
 static inline void mips_vpe_sleep(MIPSCPU *cpu)
@@ -547,7 +547,7 @@ static inline void mips_tc_wake(MIPSCPU *cpu, int tc)
 
     /* FIXME: TC reschedule.  */
     if (mips_vpe_active(c) && !mips_vpe_is_wfi(cpu)) {
-        mips_vpe_wake(c);
+        mips_vpe_wake(cpu);
     }
 }
 
@@ -1725,7 +1725,7 @@ target_ulong helper_evpe(CPUMIPSState *env)
             && !mips_vpe_is_wfi(other_cpu)) {
             /* Enable the VPE.  */
             other_cpu_env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
-            mips_vpe_wake(other_cpu_env); /* And wake it up.  */
+            mips_vpe_wake(other_cpu); /* And wake it up.  */
         }
         other_cpu_env = other_cpu_env->next_cpu;
     } while (other_cpu_env);
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 79ce7bf..d176734 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -991,7 +991,7 @@ void helper_msgsnd(target_ulong rb)
     for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
         if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
             cenv->pending_interrupts |= 1 << irq;
-            cpu_interrupt(cenv, CPU_INTERRUPT_HARD);
+            cpu_interrupt(CPU(ppc_env_get_cpu(cenv)), CPU_INTERRUPT_HARD);
         }
     }
 }
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index db263bf..642e661 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -992,7 +992,7 @@ static inline void cpu_inject_ext(S390CPU *cpu, uint32_t code, uint32_t param,
     env->ext_queue[env->ext_index].param64 = param64;
 
     env->pending_int |= INTERRUPT_EXT;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
 }
 
 static inline void cpu_inject_io(S390CPU *cpu, uint16_t subchannel_id,
@@ -1016,7 +1016,7 @@ static inline void cpu_inject_io(S390CPU *cpu, uint16_t subchannel_id,
     env->io_queue[env->io_index[isc]][isc].word = io_int_word;
 
     env->pending_int |= INTERRUPT_IO;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
 }
 
 static inline void cpu_inject_crw_mchk(S390CPU *cpu)
@@ -1034,7 +1034,7 @@ static inline void cpu_inject_crw_mchk(S390CPU *cpu)
     env->mchk_queue[env->mchk_index].type = 1;
 
     env->pending_int |= INTERRUPT_MCHK;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
 }
 
 static inline bool cpu_has_work(CPUState *cpu)
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index c88a587..2cb8dc8 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -57,7 +57,7 @@ void s390x_tod_timer(void *opaque)
     CPUS390XState *env = &cpu->env;
 
     env->pending_int |= INTERRUPT_TOD;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
 }
 
 void s390x_cpu_timer(void *opaque)
@@ -66,7 +66,7 @@ void s390x_cpu_timer(void *opaque)
     CPUS390XState *env = &cpu->env;
 
     env->pending_int |= INTERRUPT_CPUTIMER;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
 }
 #endif
 
diff --git a/translate-all.c b/translate-all.c
index f0c7d1e..1f3237e 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1077,8 +1077,8 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
             tb_phys_invalidate(tb, -1);
             if (cpu != NULL) {
                 cpu->current_tb = saved_tb;
-                if (env && cpu->interrupt_request && cpu->current_tb) {
-                    cpu_interrupt(env, cpu->interrupt_request);
+                if (cpu->interrupt_request && cpu->current_tb) {
+                    cpu_interrupt(cpu, cpu->interrupt_request);
                 }
             }
         }
@@ -1382,9 +1382,9 @@ void tb_check_watchpoint(CPUArchState *env)
 
 #ifndef CONFIG_USER_ONLY
 /* mask must never be zero, except for A20 change call */
-static void tcg_handle_interrupt(CPUArchState *env, int mask)
+static void tcg_handle_interrupt(CPUState *cpu, int mask)
 {
-    CPUState *cpu = ENV_GET_CPU(env);
+    CPUArchState *env = cpu->env_ptr;
     int old_mask;
 
     old_mask = cpu->interrupt_request;
@@ -1552,10 +1552,8 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
 
 #else /* CONFIG_USER_ONLY */
 
-void cpu_interrupt(CPUArchState *env, int mask)
+void cpu_interrupt(CPUState *cpu, int mask)
 {
-    CPUState *cpu = ENV_GET_CPU(env);
-
     cpu->interrupt_request |= mask;
     cpu->tcg_exit_req = 1;
 }
commit d8ed887bdcd29ce2e967f8b15a6a2b6dcaa11cd5
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu Jan 17 22:30:20 2013 +0100

    exec: Pass CPUState to cpu_reset_interrupt()
    
    Move it to qom/cpu.c to avoid build failures depending on include order
    of cpu-qom.h and exec/cpu-all.h.
    
    Change opaques of various ..._irq_handler() functions to the
    appropriate CPU type to facilitate using cpu_reset_interrupt().
    
    Fix Coding Style issues while at it (missing braces, indentation).
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/exec.c b/exec.c
index 4462edf..ae5a4b4 100644
--- a/exec.c
+++ b/exec.c
@@ -492,13 +492,6 @@ void cpu_single_step(CPUArchState *env, int enabled)
 #endif
 }
 
-void cpu_reset_interrupt(CPUArchState *env, int mask)
-{
-    CPUState *cpu = ENV_GET_CPU(env);
-
-    cpu->interrupt_request &= ~mask;
-}
-
 void cpu_exit(CPUArchState *env)
 {
     CPUState *cpu = ENV_GET_CPU(env);
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index 95571ff..7bfde57 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -63,10 +63,11 @@ static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
     /* If there are any non-masked interrupts, tell the cpu.  */
     if (cpu != NULL) {
         CPUAlphaState *env = &cpu->env;
+        CPUState *cs = CPU(cpu);
         if (req) {
             cpu_interrupt(env, CPU_INTERRUPT_HARD);
         } else {
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
         }
     }
 }
@@ -359,16 +360,17 @@ static void cchip_write(void *opaque, hwaddr addr,
                 AlphaCPU *cpu = s->cchip.cpu[i];
                 if (cpu != NULL) {
                     CPUAlphaState *env = &cpu->env;
+                    CPUState *cs = CPU(cpu);
                     /* IPI can be either cleared or set by the write.  */
                     if (newval & (1 << (i + 8))) {
                         cpu_interrupt(env, CPU_INTERRUPT_SMP);
                     } else {
-                        cpu_reset_interrupt(env, CPU_INTERRUPT_SMP);
+                        cpu_reset_interrupt(cs, CPU_INTERRUPT_SMP);
                     }
 
                     /* ITI can only be cleared by the write.  */
                     if ((newval & (1 << (i + 4))) == 0) {
-                        cpu_reset_interrupt(env, CPU_INTERRUPT_TIMER);
+                        cpu_reset_interrupt(cs, CPU_INTERRUPT_TIMER);
                     }
                 }
             }
diff --git a/hw/apic.c b/hw/apic.c
index 8eddba0..cc9236a 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -187,7 +187,7 @@ void apic_deliver_pic_intr(DeviceState *d, int level)
             reset_bit(s->irr, lvt & 0xff);
             /* fall through */
         case APIC_DM_EXTINT:
-            cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+            cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_HARD);
             break;
         }
     }
@@ -485,7 +485,7 @@ void apic_sipi(DeviceState *d)
 {
     APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
 
-    cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_SIPI);
+    cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI);
 
     if (!s->wait_for_sipi)
         return;
diff --git a/hw/arm/pic_cpu.c b/hw/arm/pic_cpu.c
index 8223600..95f5bf1 100644
--- a/hw/arm/pic_cpu.c
+++ b/hw/arm/pic_cpu.c
@@ -16,19 +16,22 @@ static void arm_pic_cpu_handler(void *opaque, int irq, int level)
 {
     ARMCPU *cpu = opaque;
     CPUARMState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
     switch (irq) {
     case ARM_PIC_CPU_IRQ:
-        if (level)
+        if (level) {
             cpu_interrupt(env, CPU_INTERRUPT_HARD);
-        else
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        } else {
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+        }
         break;
     case ARM_PIC_CPU_FIQ:
-        if (level)
+        if (level) {
             cpu_interrupt(env, CPU_INTERRUPT_FIQ);
-        else
-            cpu_reset_interrupt(env, CPU_INTERRUPT_FIQ);
+        } else {
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_FIQ);
+        }
         break;
     default:
         hw_error("arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
index b55ce47..b45b371 100644
--- a/hw/arm/pxa2xx_pic.c
+++ b/hw/arm/pxa2xx_pic.c
@@ -62,13 +62,13 @@ static void pxa2xx_pic_update(void *opaque)
     if ((mask[0] & s->is_fiq[0]) || (mask[1] & s->is_fiq[1])) {
         cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
     } else {
-        cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
+        cpu_reset_interrupt(cpu, CPU_INTERRUPT_FIQ);
     }
 
     if ((mask[0] & ~s->is_fiq[0]) || (mask[1] & ~s->is_fiq[1])) {
         cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
     } else {
-        cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+        cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD);
     }
 }
 
diff --git a/hw/cris/pic_cpu.c b/hw/cris/pic_cpu.c
index 7f50471..afd0df8 100644
--- a/hw/cris/pic_cpu.c
+++ b/hw/cris/pic_cpu.c
@@ -30,16 +30,19 @@
 
 static void cris_pic_cpu_handler(void *opaque, int irq, int level)
 {
-    CPUCRISState *env = (CPUCRISState *)opaque;
+    CRISCPU *cpu = opaque;
+    CPUCRISState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
     int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
 
-    if (level)
+    if (level) {
         cpu_interrupt(env, type);
-    else
-        cpu_reset_interrupt(env, type);
+    } else {
+        cpu_reset_interrupt(cs, type);
+    }
 }
 
 qemu_irq *cris_pic_init_cpu(CPUCRISState *env)
 {
-    return qemu_allocate_irqs(cris_pic_cpu_handler, env, 2);
+    return qemu_allocate_irqs(cris_pic_cpu_handler, cris_env_get_cpu(env), 2);
 }
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 309bb83..c731bdc 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -190,10 +190,12 @@ static void pic_irq_request(void *opaque, int irq, int level)
             env = env->next_cpu;
         }
     } else {
-        if (level)
+        CPUState *cs = CPU(x86_env_get_cpu(env));
+        if (level) {
             cpu_interrupt(env, CPU_INTERRUPT_HARD);
-        else
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        } else {
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+        }
     }
 }
 
diff --git a/hw/lm32/lm32_boards.c b/hw/lm32/lm32_boards.c
index 1ce466a..538c203 100644
--- a/hw/lm32/lm32_boards.c
+++ b/hw/lm32/lm32_boards.c
@@ -41,12 +41,14 @@ typedef struct {
 
 static void cpu_irq_handler(void *opaque, int irq, int level)
 {
-    CPULM32State *env = opaque;
+    LM32CPU *cpu = opaque;
+    CPULM32State *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
     if (level) {
         cpu_interrupt(env, CPU_INTERRUPT_HARD);
     } else {
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
 }
 
@@ -117,7 +119,7 @@ static void lm32_evr_init(QEMUMachineInitArgs *args)
                           0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
 
     /* create irq lines */
-    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
+    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, cpu, 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);
diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
index fd36de5..9ff6d28 100644
--- a/hw/lm32/milkymist.c
+++ b/hw/lm32/milkymist.c
@@ -46,12 +46,14 @@ typedef struct {
 
 static void cpu_irq_handler(void *opaque, int irq, int level)
 {
-    CPULM32State *env = opaque;
+    LM32CPU *cpu = opaque;
+    CPULM32State *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
     if (level) {
         cpu_interrupt(env, CPU_INTERRUPT_HARD);
     } else {
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
 }
 
@@ -123,7 +125,7 @@ milkymist_init(QEMUMachineInitArgs *args)
                           0x00, 0x89, 0x00, 0x1d, 1);
 
     /* create irq lines */
-    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
+    cpu_irq = qemu_allocate_irqs(cpu_irq_handler, cpu, 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);
diff --git a/hw/microblaze/pic_cpu.c b/hw/microblaze/pic_cpu.c
index d4743ab..4756850 100644
--- a/hw/microblaze/pic_cpu.c
+++ b/hw/microblaze/pic_cpu.c
@@ -29,16 +29,20 @@
 
 static void microblaze_pic_cpu_handler(void *opaque, int irq, int level)
 {
-    CPUMBState *env = (CPUMBState *)opaque;
+    MicroBlazeCPU *cpu = opaque;
+    CPUMBState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
     int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
 
-    if (level)
+    if (level) {
         cpu_interrupt(env, type);
-    else
-        cpu_reset_interrupt(env, type);
+    } else {
+        cpu_reset_interrupt(cs, type);
+    }
 }
 
 qemu_irq *microblaze_pic_init_cpu(CPUMBState *env)
 {
-    return qemu_allocate_irqs(microblaze_pic_cpu_handler, env, 2);
+    return qemu_allocate_irqs(microblaze_pic_cpu_handler, mb_env_get_cpu(env),
+                              2);
 }
diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
index ddd3b1b..3a78999 100644
--- a/hw/mips/mips_int.c
+++ b/hw/mips/mips_int.c
@@ -26,7 +26,9 @@
 
 static void cpu_mips_irq_request(void *opaque, int irq, int level)
 {
-    CPUMIPSState *env = (CPUMIPSState *)opaque;
+    MIPSCPU *cpu = opaque;
+    CPUMIPSState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
     if (irq < 0 || irq > 7)
         return;
@@ -40,7 +42,7 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
     if (env->CP0_Cause & CP0Ca_IP_mask) {
         cpu_interrupt(env, CPU_INTERRUPT_HARD);
     } else {
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
 }
 
@@ -49,7 +51,7 @@ void cpu_mips_irq_init_cpu(CPUMIPSState *env)
     qemu_irq *qi;
     int i;
 
-    qi = qemu_allocate_irqs(cpu_mips_irq_request, env, 8);
+    qi = qemu_allocate_irqs(cpu_mips_irq_request, mips_env_get_cpu(env), 8);
     for (i = 0; i < 8; i++) {
         env->irq[i] = qi[i];
     }
diff --git a/hw/openrisc/pic_cpu.c b/hw/openrisc/pic_cpu.c
index 931511e..7e4f9e0 100644
--- a/hw/openrisc/pic_cpu.c
+++ b/hw/openrisc/pic_cpu.c
@@ -25,6 +25,7 @@
 static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
 {
     OpenRISCCPU *cpu = (OpenRISCCPU *)opaque;
+    CPUState *cs = CPU(cpu);
     int i;
     uint32_t irq_bit = 1 << irq;
 
@@ -42,7 +43,7 @@ static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
         if ((cpu->env.picsr && (1 << i)) && (cpu->env.picmr && (1 << i))) {
             cpu_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
         } else {
-            cpu_reset_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
             cpu->env.picsr &= ~(1 << i);
         }
     }
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index b2d7fe8..ae2ed70 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -52,6 +52,7 @@ static void cpu_ppc_tb_start (CPUPPCState *env);
 
 void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
 {
+    CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
     unsigned int old_pending = env->pending_interrupts;
 
@@ -60,8 +61,9 @@ void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
         cpu_interrupt(env, CPU_INTERRUPT_HARD);
     } else {
         env->pending_interrupts &= ~(1 << n_IRQ);
-        if (env->pending_interrupts == 0)
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        if (env->pending_interrupts == 0) {
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+        }
     }
 
     if (old_pending != env->pending_interrupts) {
diff --git a/hw/sh_intc.c b/hw/sh_intc.c
index 9e64e4d..9790314 100644
--- a/hw/sh_intc.c
+++ b/hw/sh_intc.c
@@ -42,15 +42,16 @@ void sh_intc_toggle_source(struct intc_source *source,
         pending_changed = 1;
 
     if (pending_changed) {
+        CPUState *cpu = CPU(sh_env_get_cpu(first_cpu));
         if (source->pending) {
             source->parent->pending++;
 	    if (source->parent->pending == 1)
                 cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD);
-	}
-	else {
+        } else {
             source->parent->pending--;
-	    if (source->parent->pending == 0)
-                cpu_reset_interrupt(first_cpu, CPU_INTERRUPT_HARD);
+            if (source->parent->pending == 0) {
+                cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD);
+            }
 	}
     }
 
diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
index a9167e6..b1fbde0 100644
--- a/hw/sparc/leon3.c
+++ b/hw/sparc/leon3.c
@@ -67,6 +67,7 @@ void leon3_irq_ack(void *irq_manager, int intno)
 static void leon3_set_pil_in(void *opaque, uint32_t pil_in)
 {
     CPUSPARCState *env = (CPUSPARCState *)opaque;
+    CPUState *cs;
 
     assert(env != NULL);
 
@@ -89,9 +90,10 @@ static void leon3_set_pil_in(void *opaque, uint32_t pil_in)
             }
         }
     } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
+        cs = CPU(sparc_env_get_cpu(env));
         trace_leon3_reset_irq(env->interrupt_index & 15);
         env->interrupt_index = 0;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
 }
 
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index a7e6966..a1822f1 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -230,6 +230,8 @@ void sun4m_irq_info(Monitor *mon, const QDict *qdict)
 
 void cpu_check_irqs(CPUSPARCState *env)
 {
+    CPUState *cs;
+
     if (env->pil_in && (env->interrupt_index == 0 ||
                         (env->interrupt_index & ~15) == TT_EXTINT)) {
         unsigned int i;
@@ -247,9 +249,10 @@ void cpu_check_irqs(CPUSPARCState *env)
             }
         }
     } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
+        cs = CPU(sparc_env_get_cpu(env));
         trace_sun4m_cpu_reset_interrupt(env->interrupt_index & 15);
         env->interrupt_index = 0;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
 }
 
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index ae3c95b..817c23c 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -276,7 +276,7 @@ void cpu_check_irqs(CPUSPARCState *env)
             CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n",
                            env->interrupt_index);
             env->interrupt_index = 0;
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
         }
         return;
     }
@@ -309,7 +309,7 @@ void cpu_check_irqs(CPUSPARCState *env)
                        "current interrupt %x\n",
                        pil, env->pil_in, env->softint, env->interrupt_index);
         env->interrupt_index = 0;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
 }
 
@@ -344,8 +344,9 @@ static void cpu_set_ivec_irq(void *opaque, int irq, int level)
     } else {
         if (env->ivec_status & 0x20) {
             CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq);
+            cs = CPU(cpu);
             env->ivec_status &= ~0x20;
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
         }
     }
 }
diff --git a/hw/unicore32/puv3.c b/hw/unicore32/puv3.c
index f9d0c2b..6e87c41 100644
--- a/hw/unicore32/puv3.c
+++ b/hw/unicore32/puv3.c
@@ -26,13 +26,15 @@
 
 static void puv3_intc_cpu_handler(void *opaque, int irq, int level)
 {
-    CPUUniCore32State *env = opaque;
+    UniCore32CPU *cpu = opaque;
+    CPUUniCore32State *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
     assert(irq == 0);
     if (level) {
         cpu_interrupt(env, CPU_INTERRUPT_HARD);
     } else {
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
     }
 }
 
@@ -44,7 +46,8 @@ static void puv3_soc_init(CPUUniCore32State *env)
     int i;
 
     /* Initialize interrupt controller */
-    cpu_intc = qemu_allocate_irqs(puv3_intc_cpu_handler, env, 1);
+    cpu_intc = qemu_allocate_irqs(puv3_intc_cpu_handler,
+                                  uc32_env_get_cpu(env), 1);
     dev = sysbus_create_simple("puv3_intc", PUV3_INTC_BASE, *cpu_intc);
     for (i = 0; i < PUV3_IRQS_NR; i++) {
         irqs[i] = qdev_get_gpio_in(dev, i);
diff --git a/hw/xtensa/pic_cpu.c b/hw/xtensa/pic_cpu.c
index 12f66b6..fd590c6 100644
--- a/hw/xtensa/pic_cpu.c
+++ b/hw/xtensa/pic_cpu.c
@@ -80,7 +80,7 @@ void check_interrupts(CPUXtensaState *env)
         }
     }
     env->pending_irq_level = 0;
-    cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
 }
 
 static void xtensa_set_irq(void *opaque, int irq, int active)
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 249e046..5218a53 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -434,8 +434,6 @@ static inline void cpu_interrupt(CPUArchState *s, int mask)
 void cpu_interrupt(CPUArchState *env, int mask);
 #endif /* USER_ONLY */
 
-void cpu_reset_interrupt(CPUArchState *env, int mask);
-
 void cpu_exit(CPUArchState *s);
 
 /* Breakpoint/watchpoint flags */
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 23c80b9..b83ba6f 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -221,5 +221,14 @@ void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data);
  */
 CPUState *qemu_get_cpu(int index);
 
+/**
+ * cpu_reset_interrupt:
+ * @cpu: The CPU to clear the interrupt on.
+ * @mask: The interrupt mask to clear.
+ *
+ * Resets interrupts on the vCPU @cpu.
+ */
+void cpu_reset_interrupt(CPUState *cpu, int mask);
+
 
 #endif
diff --git a/qom/cpu.c b/qom/cpu.c
index 0aa9be7..e242dcb 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -21,6 +21,11 @@
 #include "qom/cpu.h"
 #include "qemu-common.h"
 
+void cpu_reset_interrupt(CPUState *cpu, int mask)
+{
+    cpu->interrupt_request &= ~mask;
+}
+
 void cpu_reset(CPUState *cpu)
 {
     CPUClass *klass = CPU_GET_CLASS(cpu);
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 1bae3ab..d9c8374 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -312,14 +312,16 @@ int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw,
    simplicitly we calculate it when the interrupt is signalled.  */
 void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
 {
+    CPUState *cs = CPU(cpu);
     CPUM68KState *env = &cpu->env;
 
     env->pending_level = level;
     env->pending_vector = vector;
-    if (level)
+    if (level) {
         cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    else
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+    }
 }
 
 #endif
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 3ab4356..d568188 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -534,12 +534,11 @@ static inline void mips_vpe_wake(CPUMIPSState *c)
 static inline void mips_vpe_sleep(MIPSCPU *cpu)
 {
     CPUState *cs = CPU(cpu);
-    CPUMIPSState *c = &cpu->env;
 
     /* The VPE was shut off, really go to bed.
        Reset any old _WAKE requests.  */
     cs->halted = 1;
-    cpu_reset_interrupt(c, CPU_INTERRUPT_WAKE);
+    cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
 }
 
 static inline void mips_tc_wake(MIPSCPU *cpu, int tc)
@@ -2104,7 +2103,7 @@ void helper_wait(CPUMIPSState *env)
     CPUState *cs = CPU(mips_env_get_cpu(env));
 
     cs->halted = 1;
-    cpu_reset_interrupt(env, CPU_INTERRUPT_WAKE);
+    cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
     helper_raise_exception(env, EXCP_HLT);
 }
 
commit 259186a7d2f7184efc96ae99bc5658e6159f53ad
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu Jan 17 18:51:17 2013 +0100

    cpu: Move halted and interrupt_request fields to CPUState
    
    Both fields are used in VMState, thus need to be moved together.
    Explicitly zero them on reset since they were located before
    breakpoints.
    
    Pass PowerPCCPU to kvmppc_handle_halt().
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/cpu-exec.c b/cpu-exec.c
index 9092145..c9e1a82 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -203,12 +203,12 @@ int cpu_exec(CPUArchState *env)
     uint8_t *tc_ptr;
     tcg_target_ulong next_tb;
 
-    if (env->halted) {
+    if (cpu->halted) {
         if (!cpu_has_work(cpu)) {
             return EXCP_HALTED;
         }
 
-        env->halted = 0;
+        cpu->halted = 0;
     }
 
     cpu_single_env = env;
@@ -278,14 +278,14 @@ int cpu_exec(CPUArchState *env)
 
             next_tb = 0; /* force lookup of first TB */
             for(;;) {
-                interrupt_request = env->interrupt_request;
+                interrupt_request = cpu->interrupt_request;
                 if (unlikely(interrupt_request)) {
                     if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
                         /* Mask out external interrupts for this step. */
                         interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
                     }
                     if (interrupt_request & CPU_INTERRUPT_DEBUG) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
+                        cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
                         env->exception_index = EXCP_DEBUG;
                         cpu_loop_exit(env);
                     }
@@ -293,8 +293,8 @@ int cpu_exec(CPUArchState *env)
     defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
     defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
                     if (interrupt_request & CPU_INTERRUPT_HALT) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
-                        env->halted = 1;
+                        cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;
+                        cpu->halted = 1;
                         env->exception_index = EXCP_HLT;
                         cpu_loop_exit(env);
                     }
@@ -302,7 +302,7 @@ int cpu_exec(CPUArchState *env)
 #if defined(TARGET_I386)
 #if !defined(CONFIG_USER_ONLY)
                     if (interrupt_request & CPU_INTERRUPT_POLL) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_POLL;
+                        cpu->interrupt_request &= ~CPU_INTERRUPT_POLL;
                         apic_poll_irq(env->apic_state);
                     }
 #endif
@@ -319,17 +319,17 @@ int cpu_exec(CPUArchState *env)
                             !(env->hflags & HF_SMM_MASK)) {
                             cpu_svm_check_intercept_param(env, SVM_EXIT_SMI,
                                                           0);
-                            env->interrupt_request &= ~CPU_INTERRUPT_SMI;
+                            cpu->interrupt_request &= ~CPU_INTERRUPT_SMI;
                             do_smm_enter(env);
                             next_tb = 0;
                         } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
                                    !(env->hflags2 & HF2_NMI_MASK)) {
-                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
+                            cpu->interrupt_request &= ~CPU_INTERRUPT_NMI;
                             env->hflags2 |= HF2_NMI_MASK;
                             do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
                             next_tb = 0;
                         } else if (interrupt_request & CPU_INTERRUPT_MCE) {
-                            env->interrupt_request &= ~CPU_INTERRUPT_MCE;
+                            cpu->interrupt_request &= ~CPU_INTERRUPT_MCE;
                             do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);
                             next_tb = 0;
                         } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
@@ -341,7 +341,8 @@ int cpu_exec(CPUArchState *env)
                             int intno;
                             cpu_svm_check_intercept_param(env, SVM_EXIT_INTR,
                                                           0);
-                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
+                            cpu->interrupt_request &= ~(CPU_INTERRUPT_HARD |
+                                                        CPU_INTERRUPT_VIRQ);
                             intno = cpu_get_pic_interrupt(env);
                             qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
                             do_interrupt_x86_hardirq(env, intno, 1);
@@ -359,7 +360,7 @@ int cpu_exec(CPUArchState *env)
                             intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
                             qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
                             do_interrupt_x86_hardirq(env, intno, 1);
-                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
+                            cpu->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
                             next_tb = 0;
 #endif
                         }
@@ -370,8 +371,9 @@ int cpu_exec(CPUArchState *env)
                     }
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
                         ppc_hw_interrupt(env);
-                        if (env->pending_interrupts == 0)
-                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+                        if (env->pending_interrupts == 0) {
+                            cpu->interrupt_request &= ~CPU_INTERRUPT_HARD;
+                        }
                         next_tb = 0;
                     }
 #elif defined(TARGET_LM32)
@@ -548,8 +550,8 @@ int cpu_exec(CPUArchState *env)
 #endif
                    /* Don't use the cached interrupt_request value,
                       do_interrupt may have updated the EXITTB flag. */
-                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
+                    if (cpu->interrupt_request & CPU_INTERRUPT_EXITTB) {
+                        cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
                         /* ensure that no TB jump will be modified as
                            the program flow was changed */
                         next_tb = 0;
diff --git a/cpus.c b/cpus.c
index 46355c1..8d47bfd 100644
--- a/cpus.c
+++ b/cpus.c
@@ -72,7 +72,7 @@ static bool cpu_thread_is_idle(CPUArchState *env)
     if (cpu->stopped || !runstate_is_running()) {
         return true;
     }
-    if (!env->halted || qemu_cpu_has_work(cpu) ||
+    if (!cpu->halted || qemu_cpu_has_work(cpu) ||
         kvm_async_interrupts_enabled()) {
         return false;
     }
@@ -1198,7 +1198,7 @@ CpuInfoList *qmp_query_cpus(Error **errp)
         info->value = g_malloc0(sizeof(*info->value));
         info->value->CPU = cpu->cpu_index;
         info->value->current = (env == first_cpu);
-        info->value->halted = env->halted;
+        info->value->halted = cpu->halted;
         info->value->thread_id = cpu->thread_id;
 #if defined(TARGET_I386)
         info->value->has_pc = true;
diff --git a/exec.c b/exec.c
index 254ae62..4462edf 100644
--- a/exec.c
+++ b/exec.c
@@ -223,12 +223,12 @@ void cpu_exec_init_all(void)
 
 static int cpu_common_post_load(void *opaque, int version_id)
 {
-    CPUArchState *env = opaque;
+    CPUState *cpu = opaque;
 
     /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
        version_id is increased. */
-    env->interrupt_request &= ~0x01;
-    tlb_flush(env, 1);
+    cpu->interrupt_request &= ~0x01;
+    tlb_flush(cpu->env_ptr, 1);
 
     return 0;
 }
@@ -240,8 +240,8 @@ static const VMStateDescription vmstate_cpu_common = {
     .minimum_version_id_old = 1,
     .post_load = cpu_common_post_load,
     .fields      = (VMStateField []) {
-        VMSTATE_UINT32(halted, CPUArchState),
-        VMSTATE_UINT32(interrupt_request, CPUArchState),
+        VMSTATE_UINT32(halted, CPUState),
+        VMSTATE_UINT32(interrupt_request, CPUState),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -293,7 +293,7 @@ void cpu_exec_init(CPUArchState *env)
 #if defined(CONFIG_USER_ONLY)
     cpu_list_unlock();
 #endif
-    vmstate_register(NULL, cpu_index, &vmstate_cpu_common, env);
+    vmstate_register(NULL, cpu_index, &vmstate_cpu_common, cpu);
 #if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
     register_savevm(NULL, "cpu", cpu_index, CPU_SAVE_VERSION,
                     cpu_save, cpu_load, env);
@@ -494,7 +494,9 @@ void cpu_single_step(CPUArchState *env, int enabled)
 
 void cpu_reset_interrupt(CPUArchState *env, int mask)
 {
-    env->interrupt_request &= ~mask;
+    CPUState *cpu = ENV_GET_CPU(env);
+
+    cpu->interrupt_request &= ~mask;
 }
 
 void cpu_exit(CPUArchState *env)
diff --git a/gdbstub.c b/gdbstub.c
index e414ad9..43b7d4d 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2408,7 +2408,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
                 cpu_synchronize_state(env);
                 len = snprintf((char *)mem_buf, sizeof(mem_buf),
                                "CPU#%d [%s]", cpu->cpu_index,
-                               env->halted ? "halted " : "running");
+                               cpu->halted ? "halted " : "running");
                 memtohex(buf, mem_buf, len);
                 put_packet(s, buf);
             }
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
index 6f0a8ca..7afd590 100644
--- a/hw/arm/omap1.c
+++ b/hw/arm/omap1.c
@@ -1721,6 +1721,7 @@ static uint64_t omap_clkdsp_read(void *opaque, hwaddr addr,
                                  unsigned size)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    CPUState *cpu = CPU(s->cpu);
 
     if (size != 2) {
         return omap_badwidth_read16(opaque, addr);
@@ -1737,8 +1738,9 @@ static uint64_t omap_clkdsp_read(void *opaque, hwaddr addr,
         return s->clkm.dsp_rstct2;
 
     case 0x18:	/* DSP_SYSST */
+        cpu = CPU(s->cpu);
         return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start |
-                (s->cpu->env.halted << 6);      /* Quite useless... */
+                (cpu->halted << 6);      /* Quite useless... */
     }
 
     OMAP_BAD_REG(addr);
@@ -3754,8 +3756,9 @@ static void omap_setup_dsp_mapping(MemoryRegion *system_memory,
 void omap_mpu_wakeup(void *opaque, int irq, int req)
 {
     struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
+    CPUState *cpu = CPU(mpu->cpu);
 
-    if (mpu->cpu->env.halted) {
+    if (cpu->halted) {
         cpu_interrupt(&mpu->cpu->env, CPU_INTERRUPT_EXITTB);
     }
 }
diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c
index eef8411..d2da928 100644
--- a/hw/arm/pxa2xx_gpio.c
+++ b/hw/arm/pxa2xx_gpio.c
@@ -93,6 +93,7 @@ static const int pxa2xx_gpio_wake[PXA2XX_GPIO_BANKS] = {
 static void pxa2xx_gpio_set(void *opaque, int line, int level)
 {
     PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
+    CPUState *cpu = CPU(s->cpu);
     int bank;
     uint32_t mask;
 
@@ -118,7 +119,7 @@ static void pxa2xx_gpio_set(void *opaque, int line, int level)
         pxa2xx_gpio_irq_update(s);
 
     /* Wake-up GPIOs */
-    if (s->cpu->env.halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
+    if (cpu->halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
         cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
     }
 }
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
index 145fc78..b55ce47 100644
--- a/hw/arm/pxa2xx_pic.c
+++ b/hw/arm/pxa2xx_pic.c
@@ -46,8 +46,9 @@ static void pxa2xx_pic_update(void *opaque)
 {
     uint32_t mask[2];
     PXA2xxPICState *s = (PXA2xxPICState *) opaque;
+    CPUState *cpu = CPU(s->cpu);
 
-    if (s->cpu->env.halted) {
+    if (cpu->halted) {
         mask[0] = s->int_pending[0] & (s->int_enabled[0] | s->int_idle);
         mask[1] = s->int_pending[1] & (s->int_enabled[1] | s->int_idle);
         if (mask[0] || mask[1]) {
diff --git a/hw/i386/xen_machine_pv.c b/hw/i386/xen_machine_pv.c
index a8177b6..37ba34e 100644
--- a/hw/i386/xen_machine_pv.c
+++ b/hw/i386/xen_machine_pv.c
@@ -36,7 +36,7 @@ static void xen_init_pv(QEMUMachineInitArgs *args)
     const char *kernel_cmdline = args->kernel_cmdline;
     const char *initrd_filename = args->initrd_filename;
     X86CPU *cpu;
-    CPUX86State *env;
+    CPUState *cs;
     DriveInfo *dinfo;
     int i;
 
@@ -49,8 +49,8 @@ static void xen_init_pv(QEMUMachineInitArgs *args)
 #endif
     }
     cpu = cpu_x86_init(cpu_model);
-    env = &cpu->env;
-    env->halted = 1;
+    cs = CPU(cpu);
+    cs->halted = 1;
 
     /* Initialize backend core & drivers */
     if (xen_be_init() != 0) {
diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c
index f6c877f..4144b34 100644
--- a/hw/openrisc/cputimer.c
+++ b/hw/openrisc/cputimer.c
@@ -73,8 +73,10 @@ static void openrisc_timer_cb(void *opaque)
 
     if ((cpu->env.ttmr & TTMR_IE) &&
          qemu_timer_expired(cpu->env.timer, qemu_get_clock_ns(vm_clock))) {
+        CPUState *cs = CPU(cpu);
+
         cpu->env.ttmr |= TTMR_IP;
-        cpu->env.interrupt_request |= CPU_INTERRUPT_TIMER;
+        cs->interrupt_request |= CPU_INTERRUPT_TIMER;
     }
 
     switch (cpu->env.ttmr & TTMR_M) {
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 451682c..fef9c5d 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -420,26 +420,28 @@ static void mmubooke_create_initial_mapping(CPUPPCState *env)
 static void ppce500_cpu_reset_sec(void *opaque)
 {
     PowerPCCPU *cpu = opaque;
+    CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
 
-    cpu_reset(CPU(cpu));
+    cpu_reset(cs);
 
     /* Secondary CPU starts in halted state for now. Needs to change when
        implementing non-kernel boot. */
-    env->halted = 1;
+    cs->halted = 1;
     env->exception_index = EXCP_HLT;
 }
 
 static void ppce500_cpu_reset(void *opaque)
 {
     PowerPCCPU *cpu = opaque;
+    CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
     struct boot_info *bi = env->load_info;
 
-    cpu_reset(CPU(cpu));
+    cpu_reset(cs);
 
     /* Set initial guest state. */
-    env->halted = 0;
+    cs->halted = 0;
     env->gpr[1] = (16<<20) - 8;
     env->gpr[3] = bi->dt_base;
     env->nip = bi->entry;
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index c9437fc..b2d7fe8 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -72,7 +72,7 @@ void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
 
     LOG_IRQ("%s: %p n_IRQ %d level %d => pending %08" PRIx32
                 "req %08x\n", __func__, env, n_IRQ, level,
-                env->pending_interrupts, env->interrupt_request);
+                env->pending_interrupts, CPU(cpu)->interrupt_request);
 }
 
 /* PowerPC 6xx / 7xx internal IRQ controller */
@@ -87,6 +87,8 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
     cur_level = (env->irq_input_state >> pin) & 1;
     /* Don't generate spurious events */
     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        CPUState *cs = CPU(cpu);
+
         switch (pin) {
         case PPC6xx_INPUT_TBEN:
             /* Level sensitive - active high */
@@ -126,7 +128,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
             /* XXX: Note that the only way to restart the CPU is to reset it */
             if (level) {
                 LOG_IRQ("%s: stop the CPU\n", __func__);
-                env->halted = 1;
+                cs->halted = 1;
             }
             break;
         case PPC6xx_INPUT_HRESET:
@@ -174,6 +176,8 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
     cur_level = (env->irq_input_state >> pin) & 1;
     /* Don't generate spurious events */
     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        CPUState *cs = CPU(cpu);
+
         switch (pin) {
         case PPC970_INPUT_INT:
             /* Level sensitive - active high */
@@ -203,11 +207,11 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
             /* XXX: TODO: relay the signal to CKSTP_OUT pin */
             if (level) {
                 LOG_IRQ("%s: stop the CPU\n", __func__);
-                env->halted = 1;
+                cs->halted = 1;
             } else {
                 LOG_IRQ("%s: restart the CPU\n", __func__);
-                env->halted = 0;
-                qemu_cpu_kick(CPU(cpu));
+                cs->halted = 0;
+                qemu_cpu_kick(cs);
             }
             break;
         case PPC970_INPUT_HRESET:
@@ -295,6 +299,8 @@ static void ppc40x_set_irq(void *opaque, int pin, int level)
     cur_level = (env->irq_input_state >> pin) & 1;
     /* Don't generate spurious events */
     if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        CPUState *cs = CPU(cpu);
+
         switch (pin) {
         case PPC40x_INPUT_RESET_SYS:
             if (level) {
@@ -332,11 +338,11 @@ static void ppc40x_set_irq(void *opaque, int pin, int level)
             /* Level sensitive - active low */
             if (level) {
                 LOG_IRQ("%s: stop the CPU\n", __func__);
-                env->halted = 1;
+                cs->halted = 1;
             } else {
                 LOG_IRQ("%s: restart the CPU\n", __func__);
-                env->halted = 0;
-                qemu_cpu_kick(CPU(cpu));
+                cs->halted = 0;
+                qemu_cpu_kick(cs);
             }
             break;
         case PPC40x_INPUT_DEBUG:
diff --git a/hw/ppc/ppce500_spin.c b/hw/ppc/ppce500_spin.c
index d904fbe..1290d37 100644
--- a/hw/ppc/ppce500_spin.c
+++ b/hw/ppc/ppce500_spin.c
@@ -112,7 +112,7 @@ static void spin_kick(void *data)
     map_start = ldq_p(&curspin->addr) & ~(map_size - 1);
     mmubooke_create_initial_mapping(env, 0, map_start, map_size);
 
-    env->halted = 0;
+    cpu->halted = 0;
     env->exception_index = -1;
     cpu->stopped = false;
     qemu_cpu_kick(cpu);
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index fd24113..f355a9b 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -617,6 +617,8 @@ static void spapr_reset_htab(sPAPREnvironment *spapr)
 
 static void ppc_spapr_reset(void)
 {
+    CPUState *first_cpu_cpu;
+
     /* Reset the hash table & recalc the RMA */
     spapr_reset_htab(spapr);
 
@@ -627,9 +629,10 @@ static void ppc_spapr_reset(void)
                        spapr->rtas_size);
 
     /* Set up the entry state */
+    first_cpu_cpu = CPU(first_cpu);
     first_cpu->gpr[3] = spapr->fdt_addr;
     first_cpu->gpr[5] = 0;
-    first_cpu->halted = 0;
+    first_cpu_cpu->halted = 0;
     first_cpu->nip = spapr->entry_point;
 
 }
@@ -637,14 +640,15 @@ static void ppc_spapr_reset(void)
 static void spapr_cpu_reset(void *opaque)
 {
     PowerPCCPU *cpu = opaque;
+    CPUState *cs = CPU(cpu);
     CPUPPCState *env = &cpu->env;
 
-    cpu_reset(CPU(cpu));
+    cpu_reset(cs);
 
     /* All CPUs start halted.  CPU0 is unhalted from the machine level
      * reset code and the rest are explicitly started up by the guest
      * using an RTAS call */
-    env->halted = 1;
+    cs->halted = 1;
 
     env->spr[SPR_HIOR] = 0;
 
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 77c052f..dd72743 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -543,7 +543,7 @@ static target_ulong h_cede(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     env->msr |= (1ULL << MSR_EE);
     hreg_compute_hflags(env);
     if (!cpu_has_work(cs)) {
-        env->halted = 1;
+        cs->halted = 1;
         env->exception_index = EXCP_HLT;
         cs->exit_request = 1;
     }
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 5ec787f..a24e853 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -145,7 +145,7 @@ static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr,
             continue;
         }
 
-        if (env->halted) {
+        if (cpu->halted) {
             rtas_st(rets, 1, 0);
         } else {
             rtas_st(rets, 1, 2);
@@ -184,7 +184,7 @@ static void rtas_start_cpu(sPAPREnvironment *spapr,
             continue;
         }
 
-        if (!env->halted) {
+        if (!cpu->halted) {
             rtas_st(rets, 0, -1);
             return;
         }
@@ -197,7 +197,7 @@ static void rtas_start_cpu(sPAPREnvironment *spapr,
         env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
         env->nip = start;
         env->gpr[3] = r3;
-        env->halted = 0;
+        cpu->halted = 0;
 
         qemu_cpu_kick(cpu);
 
diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c
index e25c330..ca275bd 100644
--- a/hw/s390x/s390-virtio.c
+++ b/hw/s390x/s390-virtio.c
@@ -132,23 +132,25 @@ static unsigned s390_running_cpus;
 
 void s390_add_running_cpu(S390CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUS390XState *env = &cpu->env;
 
-    if (env->halted) {
+    if (cs->halted) {
         s390_running_cpus++;
-        env->halted = 0;
+        cs->halted = 0;
         env->exception_index = -1;
     }
 }
 
 unsigned s390_del_running_cpu(S390CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUS390XState *env = &cpu->env;
 
-    if (env->halted == 0) {
+    if (cs->halted == 0) {
         assert(s390_running_cpus >= 1);
         s390_running_cpus--;
-        env->halted = 1;
+        cs->halted = 1;
         env->exception_index = EXCP_HLT;
     }
     return s390_running_cpus;
@@ -183,11 +185,13 @@ void s390_init_cpus(const char *cpu_model, uint8_t *storage_keys)
 
     for (i = 0; i < smp_cpus; i++) {
         S390CPU *cpu;
+        CPUState *cs;
 
         cpu = cpu_s390x_init(cpu_model);
+        cs = CPU(cpu);
 
         ipi_states[i] = cpu;
-        cpu->env.halted = 1;
+        cs->halted = 1;
         cpu->env.exception_index = EXCP_HLT;
         cpu->env.storage_keys = storage_keys;
     }
diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
index f58061f..a9167e6 100644
--- a/hw/sparc/leon3.c
+++ b/hw/sparc/leon3.c
@@ -49,11 +49,12 @@ typedef struct ResetData {
 static void main_cpu_reset(void *opaque)
 {
     ResetData *s   = (ResetData *)opaque;
+    CPUState *cpu = CPU(s->cpu);
     CPUSPARCState  *env = &s->cpu->env;
 
-    cpu_reset(CPU(s->cpu));
+    cpu_reset(cpu);
 
-    env->halted = 0;
+    cpu->halted = 0;
     env->pc     = s->entry;
     env->npc    = s->entry + 4;
 }
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 37bd041..a7e6966 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -256,10 +256,11 @@ void cpu_check_irqs(CPUSPARCState *env)
 static void cpu_kick_irq(SPARCCPU *cpu)
 {
     CPUSPARCState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
-    env->halted = 0;
+    cs->halted = 0;
     cpu_check_irqs(env);
-    qemu_cpu_kick(CPU(cpu));
+    qemu_cpu_kick(cs);
 }
 
 static void cpu_set_irq(void *opaque, int irq, int level)
@@ -285,19 +286,19 @@ static void dummy_cpu_set_irq(void *opaque, int irq, int level)
 static void main_cpu_reset(void *opaque)
 {
     SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
-    cpu_reset(CPU(cpu));
-    env->halted = 0;
+    cpu_reset(cs);
+    cs->halted = 0;
 }
 
 static void secondary_cpu_reset(void *opaque)
 {
     SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
-    cpu_reset(CPU(cpu));
-    env->halted = 1;
+    cpu_reset(cs);
+    cs->halted = 1;
 }
 
 static void cpu_halt_signal(void *opaque, int irq, int level)
@@ -826,6 +827,7 @@ static const TypeInfo ram_info = {
 static void cpu_devinit(const char *cpu_model, unsigned int id,
                         uint64_t prom_addr, qemu_irq **cpu_irqs)
 {
+    CPUState *cs;
     SPARCCPU *cpu;
     CPUSPARCState *env;
 
@@ -841,7 +843,8 @@ static void cpu_devinit(const char *cpu_model, unsigned int id,
         qemu_register_reset(main_cpu_reset, cpu);
     } else {
         qemu_register_reset(secondary_cpu_reset, cpu);
-        env->halted = 1;
+        cs = CPU(cpu);
+        cs->halted = 1;
     }
     *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, cpu, MAX_PILS);
     env->prom_addr = prom_addr;
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 51ffa1c..ae3c95b 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -254,6 +254,7 @@ static uint64_t sun4u_load_kernel(const char *kernel_filename,
 
 void cpu_check_irqs(CPUSPARCState *env)
 {
+    CPUState *cs;
     uint32_t pil = env->pil_in |
                   (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));
 
@@ -261,6 +262,7 @@ void cpu_check_irqs(CPUSPARCState *env)
     if (env->ivec_status & 0x20) {
         return;
     }
+    cs = CPU(sparc_env_get_cpu(env));
     /* check if TM or SM in SOFTINT are set
        setting these also causes interrupt 14 */
     if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) {
@@ -270,7 +272,7 @@ void cpu_check_irqs(CPUSPARCState *env)
     /* The bit corresponding to psrpil is (1<< psrpil), the next bit
        is (2 << psrpil). */
     if (pil < (2 << env->psrpil)){
-        if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+        if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
             CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n",
                            env->interrupt_index);
             env->interrupt_index = 0;
@@ -302,7 +304,7 @@ void cpu_check_irqs(CPUSPARCState *env)
                 break;
             }
         }
-    } else if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+    } else if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
         CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x "
                        "current interrupt %x\n",
                        pil, env->pil_in, env->softint, env->interrupt_index);
@@ -313,22 +315,25 @@ void cpu_check_irqs(CPUSPARCState *env)
 
 static void cpu_kick_irq(SPARCCPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUSPARCState *env = &cpu->env;
 
-    env->halted = 0;
+    cs->halted = 0;
     cpu_check_irqs(env);
-    qemu_cpu_kick(CPU(cpu));
+    qemu_cpu_kick(cs);
 }
 
 static void cpu_set_ivec_irq(void *opaque, int irq, int level)
 {
     SPARCCPU *cpu = opaque;
     CPUSPARCState *env = &cpu->env;
+    CPUState *cs;
 
     if (level) {
         if (!(env->ivec_status & 0x20)) {
             CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
-            env->halted = 0;
+            cs = CPU(cpu);
+            cs->halted = 0;
             env->interrupt_index = TT_IVEC;
             env->ivec_status |= 0x20;
             env->ivec_data[0] = (0x1f << 6) | irq;
diff --git a/hw/xtensa/pic_cpu.c b/hw/xtensa/pic_cpu.c
index f485a14..12f66b6 100644
--- a/hw/xtensa/pic_cpu.c
+++ b/hw/xtensa/pic_cpu.c
@@ -47,6 +47,7 @@ void xtensa_advance_ccount(CPUXtensaState *env, uint32_t d)
 
 void check_interrupts(CPUXtensaState *env)
 {
+    CPUState *cs = CPU(xtensa_env_get_cpu(env));
     int minlevel = xtensa_get_cintlevel(env);
     uint32_t int_set_enabled = env->sregs[INTSET] & env->sregs[INTENABLE];
     int level;
@@ -54,7 +55,7 @@ void check_interrupts(CPUXtensaState *env)
     /* If the CPU is halted advance CCOUNT according to the vm_clock time
      * elapsed since the moment when it was advanced last time.
      */
-    if (env->halted) {
+    if (cs->halted) {
         int64_t now = qemu_get_clock_ns(vm_clock);
 
         xtensa_advance_ccount(env,
@@ -127,11 +128,12 @@ static void xtensa_ccompare_cb(void *opaque)
 {
     XtensaCPU *cpu = opaque;
     CPUXtensaState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
 
-    if (env->halted) {
+    if (cs->halted) {
         env->halt_clock = qemu_get_clock_ns(vm_clock);
         xtensa_advance_ccount(env, env->wake_ccount - env->sregs[CCOUNT]);
-        if (!cpu_has_work(CPU(cpu))) {
+        if (!cpu_has_work(cs)) {
             env->sregs[CCOUNT] = env->wake_ccount + 1;
             xtensa_rearm_ccompare_timer(env);
         }
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index 3dc9656..0ae967a 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -156,8 +156,6 @@ typedef struct CPUWatchpoint {
                             accessed */                                 \
     target_ulong mem_io_vaddr; /* target virtual addr at which the      \
                                      memory was accessed */             \
-    uint32_t halted; /* Nonzero if the CPU is in suspend state */       \
-    uint32_t interrupt_request;                                         \
     CPU_COMMON_TLB                                                      \
     struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE];           \
     /* buffer for temporaries in the code generator */                  \
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 90c5f45..23c80b9 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -72,6 +72,8 @@ struct kvm_run;
  * @host_tid: Host thread ID.
  * @running: #true if CPU is currently running (usermode).
  * @created: Indicates whether the CPU thread has been successfully created.
+ * @interrupt_request: Indicates a pending interrupt request.
+ * @halted: Nonzero if the CPU is in suspended state.
  * @stop: Indicates a pending stop request.
  * @stopped: Indicates the CPU has been artificially stopped.
  * @tcg_exit_req: Set to force TCG to stop executing linked TBs for this
@@ -106,6 +108,7 @@ struct CPUState {
     bool stopped;
     volatile sig_atomic_t exit_request;
     volatile sig_atomic_t tcg_exit_req;
+    uint32_t interrupt_request;
 
     void *env_ptr; /* CPUArchState */
     struct TranslationBlock *current_tb;
@@ -117,6 +120,7 @@ struct CPUState {
 
     /* TODO Move common fields from CPUArchState here. */
     int cpu_index; /* used by alpha TCG */
+    uint32_t halted; /* used by alpha, cris, ppc TCG */
 };
 
 
diff --git a/kvm-all.c b/kvm-all.c
index 4decfdc..2b761e0 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -830,7 +830,7 @@ static void kvm_handle_interrupt(CPUArchState *env, int mask)
 {
     CPUState *cpu = ENV_GET_CPU(env);
 
-    env->interrupt_request |= mask;
+    cpu->interrupt_request |= mask;
 
     if (!qemu_cpu_is_self(cpu)) {
         qemu_cpu_kick(cpu);
diff --git a/qom/cpu.c b/qom/cpu.c
index 0a2194d..0aa9be7 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -33,7 +33,9 @@ void cpu_reset(CPUState *cpu)
 static void cpu_common_reset(CPUState *cpu)
 {
     cpu->exit_request = 0;
+    cpu->interrupt_request = 0;
     cpu->current_tb = NULL;
+    cpu->halted = 0;
 }
 
 ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index f1db651..90f78ac 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -517,8 +517,6 @@ static inline void cpu_set_tls(CPUAlphaState *env, target_ulong newtls)
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUAlphaState *env = &ALPHA_CPU(cpu)->env;
-
     /* Here we are checking to see if the CPU should wake up from HALT.
        We will have gotten into this state only for WTINT from PALmode.  */
     /* ??? I'm not sure how the IPL state works with WTINT to keep a CPU
@@ -526,7 +524,7 @@ static inline bool cpu_has_work(CPUState *cpu)
        assume that if a CPU really wants to stay asleep, it will mask
        interrupts at the chipset level, which will prevent these bits
        from being set in the first place.  */
-    return env->interrupt_request & (CPU_INTERRUPT_HARD
+    return cpu->interrupt_request & (CPU_INTERRUPT_HARD
                                      | CPU_INTERRUPT_TIMER
                                      | CPU_INTERRUPT_SMP
                                      | CPU_INTERRUPT_MCHK);
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 657f5e1..4db16db 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1686,7 +1686,8 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
     case 253:
         /* WAIT */
         tmp = tcg_const_i64(1);
-        tcg_gen_st32_i64(tmp, cpu_env, offsetof(CPUAlphaState, halted));
+        tcg_gen_st32_i64(tmp, cpu_env, -offsetof(AlphaCPU, env) +
+                                       offsetof(CPUState, halted));
         return gen_excp(ctx, EXCP_HLT, 0);
 
     case 252:
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index c28a0d9..957866c 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -722,9 +722,7 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUARMState *env = &ARM_CPU(cpu)->env;
-
-    return env->interrupt_request &
+    return cpu->interrupt_request &
         (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
 }
 
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 6cad936..d7e22dd 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1801,6 +1801,7 @@ static void do_interrupt_v7m(CPUARMState *env)
 /* Handle a CPU exception.  */
 void do_interrupt(CPUARMState *env)
 {
+    CPUState *cs;
     uint32_t addr;
     uint32_t mask;
     int new_mode;
@@ -1907,7 +1908,8 @@ void do_interrupt(CPUARMState *env)
     }
     env->regs[14] = env->regs[15] + offset;
     env->regs[15] = addr;
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+    cs = CPU(arm_env_get_cpu(env));
+    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
 
 /* Check section/page access permissions.
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index a522313..a918e5b 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -218,8 +218,10 @@ uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift)
 
 void HELPER(wfi)(CPUARMState *env)
 {
+    CPUState *cs = CPU(arm_env_get_cpu(env));
+
     env->exception_index = EXCP_HLT;
-    env->halted = 1;
+    cs->halted = 1;
     cpu_loop_exit(env);
 }
 
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index ebf2d40..2fc7c5c 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -289,9 +289,7 @@ void cris_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUCRISState *env = &CRIS_CPU(cpu)->env;
-
-    return env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
+    return cpu->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
 }
 
 #include "exec/exec-all.h"
diff --git a/target-cris/helper.c b/target-cris/helper.c
index de04143..885f67f 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -66,6 +66,7 @@ static void cris_shift_ccs(CPUCRISState *env)
 int cpu_cris_handle_mmu_fault(CPUCRISState *env, target_ulong address, int rw,
                               int mmu_idx)
 {
+    D(CPUState *cpu = CPU(cris_env_get_cpu(env)));
     struct cris_mmu_result res;
     int prot, miss;
     int r = -1;
@@ -99,7 +100,7 @@ int cpu_cris_handle_mmu_fault(CPUCRISState *env, target_ulong address, int rw,
     }
     if (r > 0) {
         D_LOG("%s returns %d irqreq=%x addr=%x phy=%x vec=%x pc=%x\n",
-              __func__, r, env->interrupt_request, address, res.phy,
+              __func__, r, cpu->interrupt_request, address, res.phy,
               res.bf_vec, env->pc);
     }
     return r;
@@ -107,11 +108,12 @@ int cpu_cris_handle_mmu_fault(CPUCRISState *env, target_ulong address, int rw,
 
 static void do_interruptv10(CPUCRISState *env)
 {
+    D(CPUState *cs = CPU(cris_env_get_cpu(env)));
     int ex_vec = -1;
 
     D_LOG("exception index=%d interrupt_req=%d\n",
           env->exception_index,
-          env->interrupt_request);
+          cs->interrupt_request);
 
     assert(!(env->pregs[PR_CCS] & PFIX_FLAG));
     switch (env->exception_index) {
@@ -162,6 +164,7 @@ static void do_interruptv10(CPUCRISState *env)
 
 void do_interrupt(CPUCRISState *env)
 {
+    D(CPUState *cs = CPU(cris_env_get_cpu(env)));
     int ex_vec = -1;
 
     if (env->pregs[PR_VR] < 32) {
@@ -170,7 +173,7 @@ void do_interrupt(CPUCRISState *env)
 
     D_LOG("exception index=%d interrupt_req=%d\n",
           env->exception_index,
-          env->interrupt_request);
+          cs->interrupt_request);
 
     switch (env->exception_index) {
     case EXCP_BREAK:
diff --git a/target-cris/translate.c b/target-cris/translate.c
index ec71ef4..dbcb811 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -2888,7 +2888,8 @@ static int dec_rfe_etc(CPUCRISState *env, DisasContext *dc)
     cris_cc_mask(dc, 0);
 
     if (dc->op2 == 15) {
-        t_gen_mov_env_TN(halted, tcg_const_tl(1));
+        tcg_gen_st_i32(tcg_const_i32(1), cpu_env,
+                       -offsetof(CRISCPU, env) + offsetof(CPUState, halted));
         tcg_gen_movi_tl(env_pc, dc->pc + 2);
         t_gen_raise_exception(EXCP_HLT);
         return 2;
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 8ff2fff..2bdbf1b 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2014,7 +2014,7 @@ static void x86_cpu_reset(CPUState *s)
         apic_designate_bsp(env->apic_state);
     }
 
-    env->halted = !cpu_is_bsp(cpu);
+    s->halted = !cpu_is_bsp(cpu);
 #endif
 }
 
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 0c1c5c5..bf6e210 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -967,6 +967,7 @@ static inline void cpu_x86_load_seg_cache(CPUX86State *env,
 static inline void cpu_x86_load_seg_cache_sipi(X86CPU *cpu,
                                                int sipi_vector)
 {
+    CPUState *cs = CPU(cpu);
     CPUX86State *env = &cpu->env;
 
     env->eip = 0;
@@ -974,7 +975,7 @@ static inline void cpu_x86_load_seg_cache_sipi(X86CPU *cpu,
                            sipi_vector << 12,
                            env->segs[R_CS].limit,
                            env->segs[R_CS].flags);
-    env->halted = 0;
+    cs->halted = 0;
 }
 
 int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
@@ -1166,17 +1167,18 @@ static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp)
 #include "hw/apic.h"
 #endif
 
-static inline bool cpu_has_work(CPUState *cpu)
+static inline bool cpu_has_work(CPUState *cs)
 {
-    CPUX86State *env = &X86_CPU(cpu)->env;
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
 
-    return ((env->interrupt_request & (CPU_INTERRUPT_HARD |
-                                       CPU_INTERRUPT_POLL)) &&
+    return ((cs->interrupt_request & (CPU_INTERRUPT_HARD |
+                                      CPU_INTERRUPT_POLL)) &&
             (env->eflags & IF_MASK)) ||
-           (env->interrupt_request & (CPU_INTERRUPT_NMI |
-                                      CPU_INTERRUPT_INIT |
-                                      CPU_INTERRUPT_SIPI |
-                                      CPU_INTERRUPT_MCE));
+           (cs->interrupt_request & (CPU_INTERRUPT_NMI |
+                                     CPU_INTERRUPT_INIT |
+                                     CPU_INTERRUPT_SIPI |
+                                     CPU_INTERRUPT_MCE));
 }
 
 #include "exec/exec-all.h"
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 82a731c..b49a0fc 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -182,6 +182,7 @@ done:
 void cpu_dump_state(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
                     int flags)
 {
+    CPUState *cs = CPU(x86_env_get_cpu(env));
     int eflags, i, nb;
     char cc_op_name[32];
     static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" };
@@ -225,7 +226,7 @@ void cpu_dump_state(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
                     (env->a20_mask >> 20) & 1,
                     (env->hflags >> HF_SMM_SHIFT) & 1,
-                    env->halted);
+                    cs->halted);
     } else
 #endif
     {
@@ -252,7 +253,7 @@ void cpu_dump_state(CPUX86State *env, FILE *f, fprintf_function cpu_fprintf,
                     (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
                     (env->a20_mask >> 20) & 1,
                     (env->hflags >> HF_SMM_SHIFT) & 1,
-                    env->halted);
+                    cs->halted);
     }
 
     for(i = 0; i < 6; i++) {
@@ -1281,12 +1282,13 @@ int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
 #if !defined(CONFIG_USER_ONLY)
 void do_cpu_init(X86CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUX86State *env = &cpu->env;
-    int sipi = env->interrupt_request & CPU_INTERRUPT_SIPI;
+    int sipi = cs->interrupt_request & CPU_INTERRUPT_SIPI;
     uint64_t pat = env->pat;
 
-    cpu_reset(CPU(cpu));
-    env->interrupt_request = sipi;
+    cpu_reset(cs);
+    cs->interrupt_request = sipi;
     env->pat = pat;
     apic_init_reset(env->apic_state);
 }
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0cf413d..df30fa6 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1460,17 +1460,18 @@ static int kvm_put_mp_state(X86CPU *cpu)
 
 static int kvm_get_mp_state(X86CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUX86State *env = &cpu->env;
     struct kvm_mp_state mp_state;
     int ret;
 
-    ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MP_STATE, &mp_state);
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_MP_STATE, &mp_state);
     if (ret < 0) {
         return ret;
     }
     env->mp_state = mp_state.mp_state;
     if (kvm_irqchip_in_kernel()) {
-        env->halted = (mp_state.mp_state == KVM_MP_STATE_HALTED);
+        cs->halted = (mp_state.mp_state == KVM_MP_STATE_HALTED);
     }
     return 0;
 }
@@ -1762,8 +1763,8 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
     int ret;
 
     /* Inject NMI */
-    if (env->interrupt_request & CPU_INTERRUPT_NMI) {
-        env->interrupt_request &= ~CPU_INTERRUPT_NMI;
+    if (cpu->interrupt_request & CPU_INTERRUPT_NMI) {
+        cpu->interrupt_request &= ~CPU_INTERRUPT_NMI;
         DPRINTF("injected NMI\n");
         ret = kvm_vcpu_ioctl(cpu, KVM_NMI);
         if (ret < 0) {
@@ -1775,18 +1776,18 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
     if (!kvm_irqchip_in_kernel()) {
         /* Force the VCPU out of its inner loop to process any INIT requests
          * or pending TPR access reports. */
-        if (env->interrupt_request &
+        if (cpu->interrupt_request &
             (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR)) {
             cpu->exit_request = 1;
         }
 
         /* Try to inject an interrupt if the guest can accept it */
         if (run->ready_for_interrupt_injection &&
-            (env->interrupt_request & CPU_INTERRUPT_HARD) &&
+            (cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
             (env->eflags & IF_MASK)) {
             int irq;
 
-            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+            cpu->interrupt_request &= ~CPU_INTERRUPT_HARD;
             irq = cpu_get_pic_interrupt(env);
             if (irq >= 0) {
                 struct kvm_interrupt intr;
@@ -1806,7 +1807,7 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
          * 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)) {
+        if ((cpu->interrupt_request & CPU_INTERRUPT_HARD)) {
             run->request_interrupt_window = 1;
         } else {
             run->request_interrupt_window = 0;
@@ -1836,11 +1837,11 @@ int kvm_arch_process_async_events(CPUState *cs)
     X86CPU *cpu = X86_CPU(cs);
     CPUX86State *env = &cpu->env;
 
-    if (env->interrupt_request & CPU_INTERRUPT_MCE) {
+    if (cs->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;
+        cs->interrupt_request &= ~CPU_INTERRUPT_MCE;
 
         kvm_cpu_synchronize_state(env);
 
@@ -1853,7 +1854,7 @@ int kvm_arch_process_async_events(CPUState *cs)
         env->exception_injected = EXCP12_MCHK;
         env->has_error_code = 0;
 
-        env->halted = 0;
+        cs->halted = 0;
         if (kvm_irqchip_in_kernel() && env->mp_state == KVM_MP_STATE_HALTED) {
             env->mp_state = KVM_MP_STATE_RUNNABLE;
         }
@@ -1863,41 +1864,42 @@ int kvm_arch_process_async_events(CPUState *cs)
         return 0;
     }
 
-    if (env->interrupt_request & CPU_INTERRUPT_POLL) {
-        env->interrupt_request &= ~CPU_INTERRUPT_POLL;
+    if (cs->interrupt_request & CPU_INTERRUPT_POLL) {
+        cs->interrupt_request &= ~CPU_INTERRUPT_POLL;
         apic_poll_irq(env->apic_state);
     }
-    if (((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+    if (((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
          (env->eflags & IF_MASK)) ||
-        (env->interrupt_request & CPU_INTERRUPT_NMI)) {
-        env->halted = 0;
+        (cs->interrupt_request & CPU_INTERRUPT_NMI)) {
+        cs->halted = 0;
     }
-    if (env->interrupt_request & CPU_INTERRUPT_INIT) {
+    if (cs->interrupt_request & CPU_INTERRUPT_INIT) {
         kvm_cpu_synchronize_state(env);
         do_cpu_init(cpu);
     }
-    if (env->interrupt_request & CPU_INTERRUPT_SIPI) {
+    if (cs->interrupt_request & CPU_INTERRUPT_SIPI) {
         kvm_cpu_synchronize_state(env);
         do_cpu_sipi(cpu);
     }
-    if (env->interrupt_request & CPU_INTERRUPT_TPR) {
-        env->interrupt_request &= ~CPU_INTERRUPT_TPR;
+    if (cs->interrupt_request & CPU_INTERRUPT_TPR) {
+        cs->interrupt_request &= ~CPU_INTERRUPT_TPR;
         kvm_cpu_synchronize_state(env);
         apic_handle_tpr_access_report(env->apic_state, env->eip,
                                       env->tpr_access_type);
     }
 
-    return env->halted;
+    return cs->halted;
 }
 
 static int kvm_handle_halt(X86CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUX86State *env = &cpu->env;
 
-    if (!((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+    if (!((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
           (env->eflags & IF_MASK)) &&
-        !(env->interrupt_request & CPU_INTERRUPT_NMI)) {
-        env->halted = 1;
+        !(cs->interrupt_request & CPU_INTERRUPT_NMI)) {
+        cs->halted = 1;
         return EXCP_HLT;
     }
 
diff --git a/target-i386/machine.c b/target-i386/machine.c
index c9984b8..b80a5f4 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -453,7 +453,7 @@ const VMStateDescription vmstate_x86_cpu = {
         VMSTATE_UINT64_V(env.pat, X86CPU, 5),
         VMSTATE_UINT32_V(env.hflags2, X86CPU, 5),
 
-        VMSTATE_UINT32_TEST(env.halted, X86CPU, version_is_5),
+        VMSTATE_UINT32_TEST(parent_obj.halted, X86CPU, version_is_5),
         VMSTATE_UINT64_V(env.vm_hsave, X86CPU, 5),
         VMSTATE_UINT64_V(env.vm_vmcb, X86CPU, 5),
         VMSTATE_UINT64_V(env.tsc_offset, X86CPU, 5),
diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c
index b6d5740..dfbc07b 100644
--- a/target-i386/misc_helper.c
+++ b/target-i386/misc_helper.c
@@ -553,20 +553,25 @@ void helper_rdmsr(CPUX86State *env)
 }
 #endif
 
-static void do_hlt(CPUX86State *env)
+static void do_hlt(X86CPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
+    CPUX86State *env = &cpu->env;
+
     env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
-    env->halted = 1;
+    cs->halted = 1;
     env->exception_index = EXCP_HLT;
     cpu_loop_exit(env);
 }
 
 void helper_hlt(CPUX86State *env, int next_eip_addend)
 {
+    X86CPU *cpu = x86_env_get_cpu(env);
+
     cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0);
     EIP += next_eip_addend;
 
-    do_hlt(env);
+    do_hlt(cpu);
 }
 
 void helper_monitor(CPUX86State *env, target_ulong ptr)
@@ -580,7 +585,8 @@ void helper_monitor(CPUX86State *env, target_ulong ptr)
 
 void helper_mwait(CPUX86State *env, int next_eip_addend)
 {
-    CPUState *cpu;
+    CPUState *cs;
+    X86CPU *cpu;
 
     if ((uint32_t)ECX != 0) {
         raise_exception(env, EXCP0D_GPF);
@@ -588,13 +594,14 @@ void helper_mwait(CPUX86State *env, int next_eip_addend)
     cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0);
     EIP += next_eip_addend;
 
-    cpu = CPU(x86_env_get_cpu(env));
+    cpu = x86_env_get_cpu(env);
+    cs = CPU(cpu);
     /* XXX: not complete but not completely erroneous */
-    if (cpu->cpu_index != 0 || env->next_cpu != NULL) {
+    if (cs->cpu_index != 0 || env->next_cpu != NULL) {
         /* more than one CPU: do not sleep because another CPU may
            wake this one */
     } else {
-        do_hlt(env);
+        do_hlt(cpu);
     }
 }
 
diff --git a/target-i386/svm_helper.c b/target-i386/svm_helper.c
index 3f246e9..c46a213 100644
--- a/target-i386/svm_helper.c
+++ b/target-i386/svm_helper.c
@@ -271,7 +271,9 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
     env->hflags2 |= HF2_GIF_MASK;
 
     if (int_ctl & V_IRQ_MASK) {
-        env->interrupt_request |= CPU_INTERRUPT_VIRQ;
+        CPUState *cs = CPU(x86_env_get_cpu(env));
+
+        cs->interrupt_request |= CPU_INTERRUPT_VIRQ;
     }
 
     /* maybe we need to inject an event */
@@ -548,6 +550,7 @@ void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param,
 /* Note: currently only 32 bits of exit_code are used */
 void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
 {
+    CPUState *cs = CPU(x86_env_get_cpu(env));
     uint32_t int_ctl;
 
     qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016"
@@ -594,7 +597,7 @@ void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
     int_ctl = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
     int_ctl &= ~(V_TPR_MASK | V_IRQ_MASK);
     int_ctl |= env->v_tpr & V_TPR_MASK;
-    if (env->interrupt_request & CPU_INTERRUPT_VIRQ) {
+    if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) {
         int_ctl |= V_IRQ_MASK;
     }
     stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl), int_ctl);
@@ -615,7 +618,7 @@ void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
     env->hflags &= ~HF_SVMI_MASK;
     env->intercept = 0;
     env->intercept_exceptions = 0;
-    env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
+    cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
     env->tsc_offset = 0;
 
     env->gdt.base  = ldq_phys(env->vm_hsave + offsetof(struct vmcb,
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index 6948d0e..d81f103 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -254,9 +254,7 @@ static inline void cpu_get_tb_cpu_state(CPULM32State *env, target_ulong *pc,
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPULM32State *env = &LM32_CPU(cpu)->env;
-
-    return env->interrupt_request & CPU_INTERRUPT_HARD;
+    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
 }
 
 #include "exec/exec-all.h"
diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c
index 53410b1..ebc94a0 100644
--- a/target-lm32/op_helper.c
+++ b/target-lm32/op_helper.c
@@ -25,7 +25,9 @@ void helper_raise_exception(CPULM32State *env, uint32_t index)
 
 void helper_hlt(CPULM32State *env)
 {
-    env->halted = 1;
+    CPUState *cs = CPU(lm32_env_get_cpu(env));
+
+    cs->halted = 1;
     env->exception_index = EXCP_HLT;
     cpu_loop_exit(env);
 }
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 2672eae..bb2fbd6 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -265,9 +265,7 @@ static inline void cpu_get_tb_cpu_state(CPUM68KState *env, target_ulong *pc,
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUM68KState *env = &M68K_CPU(cpu)->env;
-
-    return env->interrupt_request & CPU_INTERRUPT_HARD;
+    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
 }
 
 #include "exec/exec-all.h"
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 16df24c..e11f34b 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -84,6 +84,7 @@ static void do_rte(CPUM68KState *env)
 
 static void do_interrupt_all(CPUM68KState *env, int is_hw)
 {
+    CPUState *cs;
     uint32_t sp;
     uint32_t fmt;
     uint32_t retaddr;
@@ -108,7 +109,8 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
                 do_m68k_semihosting(env, env->dregs[0]);
                 return;
             }
-            env->halted = 1;
+            cs = CPU(m68k_env_get_cpu(env));
+            cs->halted = 1;
             env->exception_index = EXCP_HLT;
             cpu_loop_exit(env);
             return;
diff --git a/target-m68k/qregs.def b/target-m68k/qregs.def
index 49400c4..4235b02 100644
--- a/target-m68k/qregs.def
+++ b/target-m68k/qregs.def
@@ -8,6 +8,5 @@ DEFO32(CC_X, cc_x)
 DEFO32(DIV1, div1)
 DEFO32(DIV2, div2)
 DEFO32(EXCEPTION, exception_index)
-DEFO32(HALTED, halted)
 DEFO32(MACSR, macsr)
 DEFO32(MAC_MASK, mac_mask)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 20a86d8..32b8132 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -42,6 +42,8 @@
 #undef DEFO64
 #undef DEFF64
 
+static TCGv_i32 cpu_halted;
+
 static TCGv_ptr cpu_env;
 
 static char cpu_reg_names[3*8*3 + 5*4];
@@ -76,6 +78,10 @@ void m68k_tcg_init(void)
 #undef DEFO64
 #undef DEFF64
 
+    cpu_halted = tcg_global_mem_new_i32(TCG_AREG0,
+                                        -offsetof(M68kCPU, env) +
+                                        offsetof(CPUState, halted), "HALTED");
+
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
 
     p = cpu_reg_names;
@@ -2024,7 +2030,7 @@ DISAS_INSN(stop)
     s->pc += 2;
 
     gen_set_sr_im(s, ext, 0);
-    tcg_gen_movi_i32(QREG_HALTED, 1);
+    tcg_gen_movi_i32(cpu_halted, 1);
     gen_exception(s, s->pc, EXCP_HLT);
 }
 
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index c3dd7f6..7548aa9 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -374,9 +374,7 @@ void cpu_unassigned_access(CPUMBState *env1, hwaddr addr,
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUMBState *env = &MICROBLAZE_CPU(cpu)->env;
-
-    return env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
+    return cpu->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
 }
 
 #include "exec/exec-all.h"
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index ca63148..22b0497 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -722,7 +722,7 @@ static inline bool cpu_has_work(CPUState *cpu)
     /* It is implementation dependent if non-enabled interrupts
        wake-up the CPU, however most of the implementations only
        check for interrupts that can be taken. */
-    if ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+    if ((cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
         cpu_mips_hw_interrupts_pending(env)) {
         has_work = true;
     }
@@ -731,7 +731,7 @@ static inline bool cpu_has_work(CPUState *cpu)
     if (env->CP0_Config3 & (1 << CP0C3_MT)) {
         /* The QEMU model will issue an _WAKE request whenever the CPUs
            should be woken up.  */
-        if (env->interrupt_request & CPU_INTERRUPT_WAKE) {
+        if (cpu->interrupt_request & CPU_INTERRUPT_WAKE) {
             has_work = true;
         }
 
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 45cbb2f..3ab4356 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -515,11 +515,12 @@ void helper_sdm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
 /* SMP helpers.  */
 static bool mips_vpe_is_wfi(MIPSCPU *c)
 {
+    CPUState *cpu = CPU(c);
     CPUMIPSState *env = &c->env;
 
     /* If the VPE is halted but otherwise active, it means it's waiting for
        an interrupt.  */
-    return env->halted && mips_vpe_active(env);
+    return cpu->halted && mips_vpe_active(env);
 }
 
 static inline void mips_vpe_wake(CPUMIPSState *c)
@@ -532,11 +533,12 @@ static inline void mips_vpe_wake(CPUMIPSState *c)
 
 static inline void mips_vpe_sleep(MIPSCPU *cpu)
 {
+    CPUState *cs = CPU(cpu);
     CPUMIPSState *c = &cpu->env;
 
     /* The VPE was shut off, really go to bed.
        Reset any old _WAKE requests.  */
-    c->halted = 1;
+    cs->halted = 1;
     cpu_reset_interrupt(c, CPU_INTERRUPT_WAKE);
 }
 
@@ -2099,7 +2101,9 @@ void helper_pmon(CPUMIPSState *env, int function)
 
 void helper_wait(CPUMIPSState *env)
 {
-    env->halted = 1;
+    CPUState *cs = CPU(mips_env_get_cpu(env));
+
+    cs->halted = 1;
     cpu_reset_interrupt(env, CPU_INTERRUPT_WAKE);
     helper_raise_exception(env, EXCP_HLT);
 }
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 694f07c..b7f8203 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -16004,7 +16004,7 @@ void cpu_state_reset(CPUMIPSState *env)
             env->tcs[i].CP0_TCHalt = 1;
         }
         env->active_tc.CP0_TCHalt = 1;
-        env->halted = 1;
+        cs->halted = 1;
 
         if (cs->cpu_index == 0) {
             /* VPE0 starts up enabled.  */
@@ -16012,7 +16012,7 @@ void cpu_state_reset(CPUMIPSState *env)
             env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
 
             /* TC0 starts up unhalted.  */
-            env->halted = 0;
+            cs->halted = 0;
             env->active_tc.CP0_TCHalt = 0;
             env->tcs[0].CP0_TCHalt = 0;
             /* With thread 0 active.  */
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 4cfd1c7..64370a3 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -423,9 +423,7 @@ static inline int cpu_mmu_index(CPUOpenRISCState *env)
 #define CPU_INTERRUPT_TIMER   CPU_INTERRUPT_TGT_INT_0
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUOpenRISCState *env = &OPENRISC_CPU(cpu)->env;
-
-    return env->interrupt_request & (CPU_INTERRUPT_HARD |
+    return cpu->interrupt_request & (CPU_INTERRUPT_HARD |
                                      CPU_INTERRUPT_TIMER);
 }
 
diff --git a/target-openrisc/interrupt_helper.c b/target-openrisc/interrupt_helper.c
index a176441..844648f 100644
--- a/target-openrisc/interrupt_helper.c
+++ b/target-openrisc/interrupt_helper.c
@@ -24,6 +24,7 @@
 void HELPER(rfe)(CPUOpenRISCState *env)
 {
     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
 #ifndef CONFIG_USER_ONLY
     int need_flush_tlb = (cpu->env.sr & (SR_SM | SR_IME | SR_DME)) ^
                          (cpu->env.esr & (SR_SM | SR_IME | SR_DME));
@@ -53,5 +54,5 @@ void HELPER(rfe)(CPUOpenRISCState *env)
         tlb_flush(&cpu->env, 1);
     }
 #endif
-    cpu->env.interrupt_request |= CPU_INTERRUPT_EXITTB;
+    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c
index 3c5f45a..cccbc0e 100644
--- a/target-openrisc/sys_helper.c
+++ b/target-openrisc/sys_helper.c
@@ -31,6 +31,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
     int idx;
 
     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
 
     switch (spr) {
     case TO_SPR(0, 0): /* VR */
@@ -132,7 +133,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
                 env->ttmr = (rb & ~TTMR_IP) + ip;
             } else {    /* Clear IP bit.  */
                 env->ttmr = rb & ~TTMR_IP;
-                env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
+                cs->interrupt_request &= ~CPU_INTERRUPT_TIMER;
             }
 
             cpu_openrisc_count_update(cpu);
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 417abb0..1b31b1d 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -2217,9 +2217,10 @@ extern void (*cpu_ppc_hypercall)(PowerPCCPU *);
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUPPCState *env = &POWERPC_CPU(cpu)->env;
+    PowerPCCPU *ppc_cpu = POWERPC_CPU(cpu);
+    CPUPPCState *env = &ppc_cpu->env;
 
-    return msr_ee && (env->interrupt_request & CPU_INTERRUPT_HARD);
+    return msr_ee && (cpu->interrupt_request & CPU_INTERRUPT_HARD);
 }
 
 #include "exec/exec-all.h"
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 0a1ac86..79ce7bf 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -66,6 +66,7 @@ static inline void dump_syscall(CPUPPCState *env)
 static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
 {
     CPUPPCState *env = &cpu->env;
+    CPUState *cs;
     target_ulong msr, new_msr, vector;
     int srr0, srr1, asrr0, asrr1;
     int lpes0, lpes1, lev;
@@ -131,8 +132,9 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
                 fprintf(stderr, "Machine check while not allowed. "
                         "Entering checkstop state\n");
             }
-            env->halted = 1;
-            env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+            cs = CPU(cpu);
+            cs->halted = 1;
+            cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
         }
         if (0) {
             /* XXX: find a suitable condition to enable the hypervisor mode */
@@ -663,11 +665,12 @@ void ppc_hw_interrupt(CPUPPCState *env)
 {
     PowerPCCPU *cpu = ppc_env_get_cpu(env);
     int hdice;
-
 #if 0
+    CPUState *cs = CPU(cpu);
+
     qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
-                __func__, env, env->pending_interrupts,
-                env->interrupt_request, (int)msr_me, (int)msr_ee);
+                  __func__, env, env->pending_interrupts,
+                  cs->interrupt_request, (int)msr_me, (int)msr_ee);
 #endif
     /* External reset */
     if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
@@ -807,9 +810,12 @@ void helper_raise_exception(CPUPPCState *env, uint32_t exception)
 #if !defined(CONFIG_USER_ONLY)
 void helper_store_msr(CPUPPCState *env, target_ulong val)
 {
+    CPUState *cs;
+
     val = hreg_store_msr(env, val, 0);
     if (val != 0) {
-        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+        cs = CPU(ppc_env_get_cpu(env));
+        cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
         helper_raise_exception(env, val);
     }
 }
@@ -817,6 +823,8 @@ void helper_store_msr(CPUPPCState *env, target_ulong val)
 static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr,
                           target_ulong msrm, int keep_msrh)
 {
+    CPUState *cs = CPU(ppc_env_get_cpu(env));
+
 #if defined(TARGET_PPC64)
     if (msr_is_64bit(env, msr)) {
         nip = (uint64_t)nip;
@@ -841,7 +849,7 @@ static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr,
     /* No need to raise an exception here,
      * as rfi is always the last insn of a TB
      */
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
 
 void helper_rfi(CPUPPCState *env)
diff --git a/target-ppc/helper_regs.h b/target-ppc/helper_regs.h
index 3c98850..a6d5e2f 100644
--- a/target-ppc/helper_regs.h
+++ b/target-ppc/helper_regs.h
@@ -68,10 +68,13 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
                                  int alter_hv)
 {
     int excp;
+#if !defined(CONFIG_USER_ONLY)
+    CPUState *cs = CPU(ppc_env_get_cpu(env));
+#endif
 
     excp = 0;
     value &= env->msr_mask;
-#if !defined (CONFIG_USER_ONLY)
+#if !defined(CONFIG_USER_ONLY)
     if (!alter_hv) {
         /* mtmsr cannot alter the hypervisor state */
         value &= ~MSR_HVB;
@@ -82,7 +85,7 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
         /* Flush all tlb when changing translation mode */
         tlb_flush(env, 1);
         excp = POWERPC_EXCP_NONE;
-        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+        cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
     }
     if (unlikely((env->flags & POWERPC_FLAG_TGPR) &&
                  ((value ^ env->msr) & (1 << MSR_TGPR)))) {
@@ -96,10 +99,10 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
 #endif
     env->msr = value;
     hreg_compute_hflags(env);
-#if !defined (CONFIG_USER_ONLY)
+#if !defined(CONFIG_USER_ONLY)
     if (unlikely(msr_pow == 1)) {
         if ((*env->check_pow)(env)) {
-            env->halted = 1;
+            cs->halted = 1;
             excp = EXCP_HALTED;
         }
     }
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 9dff760..e663ff0 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -993,7 +993,7 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
      * interrupt, reset, etc) in PPC-specific env->irq_input_state. */
     if (!cap_interrupt_level &&
         run->ready_for_interrupt_injection &&
-        (env->interrupt_request & CPU_INTERRUPT_HARD) &&
+        (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
         (env->irq_input_state & (1<<PPC_INPUT_INT)))
     {
         /* For now KVM disregards the 'irq' argument. However, in the
@@ -1024,14 +1024,16 @@ void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run)
 
 int kvm_arch_process_async_events(CPUState *cs)
 {
-    PowerPCCPU *cpu = POWERPC_CPU(cs);
-    return cpu->env.halted;
+    return cs->halted;
 }
 
-static int kvmppc_handle_halt(CPUPPCState *env)
+static int kvmppc_handle_halt(PowerPCCPU *cpu)
 {
-    if (!(env->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) {
-        env->halted = 1;
+    CPUState *cs = CPU(cpu);
+    CPUPPCState *env = &cpu->env;
+
+    if (!(cs->interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) {
+        cs->halted = 1;
         env->exception_index = EXCP_HLT;
     }
 
@@ -1073,7 +1075,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
         break;
     case KVM_EXIT_HLT:
         dprintf("handle halt\n");
-        ret = kvmppc_handle_halt(env);
+        ret = kvmppc_handle_halt(cpu);
         break;
 #ifdef CONFIG_PSERIES
     case KVM_EXIT_PAPR_HCALL:
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index fa9e9e3..380a884 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3103,7 +3103,8 @@ static void gen_sync(DisasContext *ctx)
 static void gen_wait(DisasContext *ctx)
 {
     TCGv_i32 t0 = tcg_temp_new_i32();
-    tcg_gen_st_i32(t0, cpu_env, offsetof(CPUPPCState, halted));
+    tcg_gen_st_i32(t0, cpu_env,
+                   -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
     tcg_temp_free_i32(t0);
     /* Stop translation, as the CPU is supposed to sleep from now */
     gen_exception_err(ctx, EXCP_HLT, 1);
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index b746547..738a0ad 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -80,10 +80,10 @@ static void s390_cpu_reset(CPUState *s)
     env->cregs[0] = CR0_RESET;
     env->cregs[14] = CR14_RESET;
     /* set halted to 1 to make sure we can add the cpu in
-     * s390_ipl_cpu code, where env->halted is set back to 0
+     * s390_ipl_cpu code, where CPUState::halted is set back to 0
      * after incrementing the cpu counter */
 #if !defined(CONFIG_USER_ONLY)
-    env->halted = 1;
+    s->halted = 1;
 #endif
     tlb_flush(env, 1);
 }
@@ -129,10 +129,10 @@ static void s390_cpu_initfn(Object *obj)
     env->tod_basetime = 0;
     env->tod_timer = qemu_new_timer_ns(vm_clock, s390x_tod_timer, cpu);
     env->cpu_timer = qemu_new_timer_ns(vm_clock, s390x_cpu_timer, cpu);
-    /* set env->halted state to 1 to avoid decrementing the running
+    /* set CPUState::halted state to 1 to avoid decrementing the running
      * cpu counter in s390_cpu_reset to a negative number at
      * initial ipl */
-    env->halted = 1;
+    cs->halted = 1;
 #endif
     env->cpu_num = cpu_num++;
     env->ext_index = -1;
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 9cb739d..db263bf 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -1039,9 +1039,10 @@ static inline void cpu_inject_crw_mchk(S390CPU *cpu)
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUS390XState *env = &S390_CPU(cpu)->env;
+    S390CPU *s390_cpu = S390_CPU(cpu);
+    CPUS390XState *env = &s390_cpu->env;
 
-    return (env->interrupt_request & CPU_INTERRUPT_HARD) &&
+    return (cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
         (env->psw.mask & PSW_MASK_EXT);
 }
 
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 1183b45..c88a587 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -437,6 +437,7 @@ void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
 {
     if (mask & PSW_MASK_WAIT) {
         S390CPU *cpu = s390_env_get_cpu(env);
+        CPUState *cs = CPU(cpu);
         if (!(mask & (PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK))) {
             if (s390_del_running_cpu(cpu) == 0) {
 #ifndef CONFIG_USER_ONLY
@@ -444,7 +445,7 @@ void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
 #endif
             }
         }
-        env->halted = 1;
+        cs->halted = 1;
         env->exception_index = EXCP_HLT;
     }
 
@@ -739,6 +740,7 @@ static void do_mchk_interrupt(CPUS390XState *env)
 void do_interrupt(CPUS390XState *env)
 {
     S390CPU *cpu = s390_env_get_cpu(env);
+    CPUState *cs;
 
     qemu_log_mask(CPU_LOG_INT, "%s: %d at pc=%" PRIx64 "\n",
                   __func__, env->exception_index, env->psw.addr);
@@ -797,7 +799,8 @@ void do_interrupt(CPUS390XState *env)
     env->exception_index = -1;
 
     if (!env->pending_int) {
-        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+        cs = CPU(s390_env_get_cpu(env));
+        cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
     }
 }
 
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index f805778..4966355 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -369,9 +369,7 @@ static inline void cpu_get_tb_cpu_state(CPUSH4State *env, target_ulong *pc,
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUSH4State *env = &SUPERH_CPU(cpu)->env;
-
-    return env->interrupt_request & CPU_INTERRUPT_HARD;
+    return cpu->interrupt_request & CPU_INTERRUPT_HARD;
 }
 
 #include "exec/exec-all.h"
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index ddebc78..fd4efee 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -78,9 +78,10 @@ int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr)
 #define MMU_DADDR_ERROR_READ     (-12)
 #define MMU_DADDR_ERROR_WRITE    (-13)
 
-void do_interrupt(CPUSH4State * env)
+void do_interrupt(CPUSH4State *env)
 {
-    int do_irq = env->interrupt_request & CPU_INTERRUPT_HARD;
+    CPUState *cs = CPU(sh_env_get_cpu(env));
+    int do_irq = cs->interrupt_request & CPU_INTERRUPT_HARD;
     int do_exp, irq_vector = env->exception_index;
 
     /* prioritize exceptions over interrupts */
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index 09e3d23..e955e81 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -102,7 +102,9 @@ void helper_debug(CPUSH4State *env)
 
 void helper_sleep(CPUSH4State *env)
 {
-    env->halted = 1;
+    CPUState *cs = CPU(sh_env_get_cpu(env));
+
+    cs->halted = 1;
     env->in_sleep = 1;
     raise_exception(env, EXCP_HLT, 0);
 }
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index a2f2cc8..8a2f8df 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -762,9 +762,10 @@ static inline bool tb_am_enabled(int tb_flags)
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUSPARCState *env1 = &SPARC_CPU(cpu)->env;
+    SPARCCPU *sparc_cpu = SPARC_CPU(cpu);
+    CPUSPARCState *env1 = &sparc_cpu->env;
 
-    return (env1->interrupt_request & CPU_INTERRUPT_HARD) &&
+    return (cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
            cpu_interrupts_enabled(env1);
 }
 
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 58e7efe..57c20af 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -229,7 +229,9 @@ target_ulong helper_tsubcctv(CPUSPARCState *env, target_ulong src1,
 #ifndef TARGET_SPARC64
 void helper_power_down(CPUSPARCState *env)
 {
-    env->halted = 1;
+    CPUState *cs = CPU(sparc_env_get_cpu(env));
+
+    cs->halted = 1;
     env->exception_index = EXCP_HLT;
     env->pc = env->npc;
     env->npc = env->pc + 4;
diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h
index ae9a9d6..58f1f20 100644
--- a/target-unicore32/cpu.h
+++ b/target-unicore32/cpu.h
@@ -181,9 +181,7 @@ void switch_mode(CPUUniCore32State *, int);
 
 static inline bool cpu_has_work(CPUState *cpu)
 {
-    CPUUniCore32State *env = &UNICORE32_CPU(cpu)->env;
-
-    return env->interrupt_request &
+    return cpu->interrupt_request &
         (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
 }
 
diff --git a/target-unicore32/softmmu.c b/target-unicore32/softmmu.c
index fc27100..1c4c7f5 100644
--- a/target-unicore32/softmmu.c
+++ b/target-unicore32/softmmu.c
@@ -74,6 +74,7 @@ void switch_mode(CPUUniCore32State *env, int mode)
 /* Handle a CPU exception.  */
 void do_interrupt(CPUUniCore32State *env)
 {
+    CPUState *cs = CPU(uc32_env_get_cpu(env));
     uint32_t addr;
     int new_mode;
 
@@ -112,7 +113,7 @@ void do_interrupt(CPUUniCore32State *env)
     /* The PC already points to the proper instruction.  */
     env->regs[30] = env->regs[31];
     env->regs[31] = addr;
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
 
 static int get_phys_addr_ucv2(CPUUniCore32State *env, uint32_t address,
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 3813a72..1037101 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -373,6 +373,8 @@ void HELPER(dump_state)(CPUXtensaState *env)
 
 void HELPER(waiti)(CPUXtensaState *env, uint32_t pc, uint32_t intlevel)
 {
+    CPUState *cpu;
+
     env->pc = pc;
     env->sregs[PS] = (env->sregs[PS] & ~PS_INTLEVEL) |
         (intlevel << PS_INTLEVEL_SHIFT);
@@ -382,8 +384,9 @@ void HELPER(waiti)(CPUXtensaState *env, uint32_t pc, uint32_t intlevel)
         return;
     }
 
+    cpu = CPU(xtensa_env_get_cpu(env));
     env->halt_clock = qemu_get_clock_ns(vm_clock);
-    env->halted = 1;
+    cpu->halted = 1;
     if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
         xtensa_rearm_ccompare_timer(env);
     }
diff --git a/translate-all.c b/translate-all.c
index 90ea002..f0c7d1e 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1077,8 +1077,8 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
             tb_phys_invalidate(tb, -1);
             if (cpu != NULL) {
                 cpu->current_tb = saved_tb;
-                if (env && env->interrupt_request && cpu->current_tb) {
-                    cpu_interrupt(env, env->interrupt_request);
+                if (env && cpu->interrupt_request && cpu->current_tb) {
+                    cpu_interrupt(env, cpu->interrupt_request);
                 }
             }
         }
@@ -1387,8 +1387,8 @@ static void tcg_handle_interrupt(CPUArchState *env, int mask)
     CPUState *cpu = ENV_GET_CPU(env);
     int old_mask;
 
-    old_mask = env->interrupt_request;
-    env->interrupt_request |= mask;
+    old_mask = cpu->interrupt_request;
+    cpu->interrupt_request |= mask;
 
     /*
      * If called from iothread context, wake the target cpu in
@@ -1556,7 +1556,7 @@ void cpu_interrupt(CPUArchState *env, int mask)
 {
     CPUState *cpu = ENV_GET_CPU(env);
 
-    env->interrupt_request |= mask;
+    cpu->interrupt_request |= mask;
     cpu->tcg_exit_req = 1;
 }
 
diff --git a/xen-all.c b/xen-all.c
index 110f958..8c05843 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -578,16 +578,18 @@ void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
 
 static void xen_reset_vcpu(void *opaque)
 {
-    CPUArchState *env = opaque;
+    CPUState *cpu = opaque;
 
-    env->halted = 1;
+    cpu->halted = 1;
 }
 
 void xen_vcpu_init(void)
 {
     if (first_cpu != NULL) {
-        qemu_register_reset(xen_reset_vcpu, first_cpu);
-        xen_reset_vcpu(first_cpu);
+        CPUState *cpu = ENV_GET_CPU(first_cpu);
+
+        qemu_register_reset(xen_reset_vcpu, cpu);
+        xen_reset_vcpu(cpu);
     }
     /* if rtc_clock is left to default (host_clock), disable it */
     if (rtc_clock == host_clock) {
commit 21317bc222ef4cdca594b1856eea62f3dfbbfb6c
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Jan 25 17:37:28 2013 +0100

    target-cris/helper.c: Update Coding Style
    
    Reindent, add missing braces and drop/adjust whitespace.
    
    Prepares for CPUArchState-to-CPUState field movements in
    cpu_cris_handle_mmu_fault(), do_interruptv10() and do_interrupt().
    The remaining functions were so minor that they can be fixed in one go.
    
    Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-cris/helper.c b/target-cris/helper.c
index 6e75e98..de04143 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -36,19 +36,19 @@
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt (CPUCRISState *env)
+void do_interrupt(CPUCRISState *env)
 {
-	env->exception_index = -1;
-	env->pregs[PR_ERP] = env->pc;
+    env->exception_index = -1;
+    env->pregs[PR_ERP] = env->pc;
 }
 
 int cpu_cris_handle_mmu_fault(CPUCRISState * env, target_ulong address, int rw,
                               int mmu_idx)
 {
-	env->exception_index = 0xaa;
-	env->pregs[PR_EDA] = address;
-	cpu_dump_state(env, stderr, fprintf, 0);
-	return 1;
+    env->exception_index = 0xaa;
+    env->pregs[PR_EDA] = address;
+    cpu_dump_state(env, stderr, fprintf, 0);
+    return 1;
 }
 
 #else /* !CONFIG_USER_ONLY */
@@ -56,211 +56,210 @@ int cpu_cris_handle_mmu_fault(CPUCRISState * env, target_ulong address, int rw,
 
 static void cris_shift_ccs(CPUCRISState *env)
 {
-	uint32_t ccs;
-	/* Apply the ccs shift.  */
-	ccs = env->pregs[PR_CCS];
-	ccs = ((ccs & 0xc0000000) | ((ccs << 12) >> 2)) & ~0x3ff;
-	env->pregs[PR_CCS] = ccs;
+    uint32_t ccs;
+    /* Apply the ccs shift.  */
+    ccs = env->pregs[PR_CCS];
+    ccs = ((ccs & 0xc0000000) | ((ccs << 12) >> 2)) & ~0x3ff;
+    env->pregs[PR_CCS] = ccs;
 }
 
-int cpu_cris_handle_mmu_fault (CPUCRISState *env, target_ulong address, int rw,
-                               int mmu_idx)
+int cpu_cris_handle_mmu_fault(CPUCRISState *env, target_ulong address, int rw,
+                              int mmu_idx)
 {
-	struct cris_mmu_result res;
-	int prot, miss;
-	int r = -1;
-	target_ulong phy;
-
-	D(printf ("%s addr=%x pc=%x rw=%x\n", __func__, address, env->pc, rw));
-	miss = cris_mmu_translate(&res, env, address & TARGET_PAGE_MASK,
-				  rw, mmu_idx, 0);
-	if (miss)
-	{
-		if (env->exception_index == EXCP_BUSFAULT)
-			cpu_abort(env,
-				  "CRIS: Illegal recursive bus fault."
-				 "addr=%x rw=%d\n",
-				 address, rw);
-
-		env->pregs[PR_EDA] = address;
-		env->exception_index = EXCP_BUSFAULT;
-		env->fault_vector = res.bf_vec;
-		r = 1;
-	}
-	else
-	{
-		/*
-		 * Mask off the cache selection bit. The ETRAX busses do not
-		 * see the top bit.
-		 */
-		phy = res.phy & ~0x80000000;
-		prot = res.prot;
-		tlb_set_page(env, address & TARGET_PAGE_MASK, phy,
-                             prot, mmu_idx, TARGET_PAGE_SIZE);
-                r = 0;
-	}
-	if (r > 0)
-            D_LOG("%s returns %d irqreq=%x addr=%x phy=%x vec=%x pc=%x\n",
-                  __func__, r, env->interrupt_request, address, res.phy,
-                  res.bf_vec, env->pc);
-	return r;
+    struct cris_mmu_result res;
+    int prot, miss;
+    int r = -1;
+    target_ulong phy;
+
+    D(printf("%s addr=%x pc=%x rw=%x\n", __func__, address, env->pc, rw));
+    miss = cris_mmu_translate(&res, env, address & TARGET_PAGE_MASK,
+                              rw, mmu_idx, 0);
+    if (miss) {
+        if (env->exception_index == EXCP_BUSFAULT) {
+            cpu_abort(env,
+                      "CRIS: Illegal recursive bus fault."
+                      "addr=%x rw=%d\n",
+                      address, rw);
+        }
+
+        env->pregs[PR_EDA] = address;
+        env->exception_index = EXCP_BUSFAULT;
+        env->fault_vector = res.bf_vec;
+        r = 1;
+    } else {
+        /*
+         * Mask off the cache selection bit. The ETRAX busses do not
+         * see the top bit.
+         */
+        phy = res.phy & ~0x80000000;
+        prot = res.prot;
+        tlb_set_page(env, address & TARGET_PAGE_MASK, phy,
+                     prot, mmu_idx, TARGET_PAGE_SIZE);
+        r = 0;
+    }
+    if (r > 0) {
+        D_LOG("%s returns %d irqreq=%x addr=%x phy=%x vec=%x pc=%x\n",
+              __func__, r, env->interrupt_request, address, res.phy,
+              res.bf_vec, env->pc);
+    }
+    return r;
 }
 
 static void do_interruptv10(CPUCRISState *env)
 {
-	int ex_vec = -1;
-
-	D_LOG( "exception index=%d interrupt_req=%d\n",
-		   env->exception_index,
-		   env->interrupt_request);
-
-	assert(!(env->pregs[PR_CCS] & PFIX_FLAG));
-	switch (env->exception_index)
-	{
-		case EXCP_BREAK:
-			/* These exceptions are genereated by the core itself.
-			   ERP should point to the insn following the brk.  */
-			ex_vec = env->trap_vector;
-			env->pregs[PRV10_BRP] = env->pc;
-			break;
-
-		case EXCP_NMI:
-			/* NMI is hardwired to vector zero.  */
-			ex_vec = 0;
-			env->pregs[PR_CCS] &= ~M_FLAG_V10;
-			env->pregs[PRV10_BRP] = env->pc;
-			break;
-
-		case EXCP_BUSFAULT:
-                        cpu_abort(env, "Unhandled busfault");
-			break;
-
-		default:
-			/* The interrupt controller gives us the vector.  */
-			ex_vec = env->interrupt_vector;
-			/* Normal interrupts are taken between
-			   TB's.  env->pc is valid here.  */
-			env->pregs[PR_ERP] = env->pc;
-			break;
-	}
-
-	if (env->pregs[PR_CCS] & U_FLAG) {
-		/* Swap stack pointers.  */
-		env->pregs[PR_USP] = env->regs[R_SP];
-		env->regs[R_SP] = env->ksp;
-	}
-
-	/* Now that we are in kernel mode, load the handlers address.  */
-        env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
-	env->locked_irq = 1;
-	env->pregs[PR_CCS] |= F_FLAG_V10; /* set F.  */
-
-	qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n", 
-		      __func__, env->pc, ex_vec, 
-		      env->pregs[PR_CCS],
-		      env->pregs[PR_PID], 
-		      env->pregs[PR_ERP]);
+    int ex_vec = -1;
+
+    D_LOG("exception index=%d interrupt_req=%d\n",
+          env->exception_index,
+          env->interrupt_request);
+
+    assert(!(env->pregs[PR_CCS] & PFIX_FLAG));
+    switch (env->exception_index) {
+    case EXCP_BREAK:
+        /* These exceptions are genereated by the core itself.
+           ERP should point to the insn following the brk.  */
+        ex_vec = env->trap_vector;
+        env->pregs[PRV10_BRP] = env->pc;
+        break;
+
+    case EXCP_NMI:
+        /* NMI is hardwired to vector zero.  */
+        ex_vec = 0;
+        env->pregs[PR_CCS] &= ~M_FLAG_V10;
+        env->pregs[PRV10_BRP] = env->pc;
+        break;
+
+    case EXCP_BUSFAULT:
+        cpu_abort(env, "Unhandled busfault");
+        break;
+
+    default:
+        /* The interrupt controller gives us the vector.  */
+        ex_vec = env->interrupt_vector;
+        /* Normal interrupts are taken between
+           TB's.  env->pc is valid here.  */
+        env->pregs[PR_ERP] = env->pc;
+        break;
+    }
+
+    if (env->pregs[PR_CCS] & U_FLAG) {
+        /* Swap stack pointers.  */
+        env->pregs[PR_USP] = env->regs[R_SP];
+        env->regs[R_SP] = env->ksp;
+    }
+
+    /* Now that we are in kernel mode, load the handlers address.  */
+    env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
+    env->locked_irq = 1;
+    env->pregs[PR_CCS] |= F_FLAG_V10; /* set F.  */
+
+    qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
+                  __func__, env->pc, ex_vec,
+                  env->pregs[PR_CCS],
+                  env->pregs[PR_PID],
+                  env->pregs[PR_ERP]);
 }
 
 void do_interrupt(CPUCRISState *env)
 {
-	int ex_vec = -1;
-
-	if (env->pregs[PR_VR] < 32)
-		return do_interruptv10(env);
-
-	D_LOG( "exception index=%d interrupt_req=%d\n",
-		   env->exception_index,
-		   env->interrupt_request);
-
-	switch (env->exception_index)
-	{
-		case EXCP_BREAK:
-			/* These exceptions are genereated by the core itself.
-			   ERP should point to the insn following the brk.  */
-			ex_vec = env->trap_vector;
-			env->pregs[PR_ERP] = env->pc;
-			break;
-
-		case EXCP_NMI:
-			/* NMI is hardwired to vector zero.  */
-			ex_vec = 0;
-			env->pregs[PR_CCS] &= ~M_FLAG_V32;
-			env->pregs[PR_NRP] = env->pc;
-			break;
-
-		case EXCP_BUSFAULT:
-			ex_vec = env->fault_vector;
-			env->pregs[PR_ERP] = env->pc;
-			break;
-
-		default:
-			/* The interrupt controller gives us the vector.  */
-			ex_vec = env->interrupt_vector;
-			/* Normal interrupts are taken between
-			   TB's.  env->pc is valid here.  */
-			env->pregs[PR_ERP] = env->pc;
-			break;
-	}
-
-	/* Fill in the IDX field.  */
-	env->pregs[PR_EXS] = (ex_vec & 0xff) << 8;
-
-	if (env->dslot) {
-		D_LOG("excp isr=%x PC=%x ds=%d SP=%x"
-			  " ERP=%x pid=%x ccs=%x cc=%d %x\n",
-			  ex_vec, env->pc, env->dslot,
-			  env->regs[R_SP],
-			  env->pregs[PR_ERP], env->pregs[PR_PID],
-			  env->pregs[PR_CCS],
-			  env->cc_op, env->cc_mask);
-		/* We loose the btarget, btaken state here so rexec the
-		   branch.  */
-		env->pregs[PR_ERP] -= env->dslot;
-		/* Exception starts with dslot cleared.  */
-		env->dslot = 0;
-	}
+    int ex_vec = -1;
+
+    if (env->pregs[PR_VR] < 32) {
+        return do_interruptv10(env);
+    }
+
+    D_LOG("exception index=%d interrupt_req=%d\n",
+          env->exception_index,
+          env->interrupt_request);
+
+    switch (env->exception_index) {
+    case EXCP_BREAK:
+        /* These exceptions are genereated by the core itself.
+           ERP should point to the insn following the brk.  */
+        ex_vec = env->trap_vector;
+        env->pregs[PR_ERP] = env->pc;
+        break;
+
+    case EXCP_NMI:
+        /* NMI is hardwired to vector zero.  */
+        ex_vec = 0;
+        env->pregs[PR_CCS] &= ~M_FLAG_V32;
+        env->pregs[PR_NRP] = env->pc;
+        break;
+
+    case EXCP_BUSFAULT:
+        ex_vec = env->fault_vector;
+        env->pregs[PR_ERP] = env->pc;
+        break;
+
+    default:
+        /* The interrupt controller gives us the vector.  */
+        ex_vec = env->interrupt_vector;
+        /* Normal interrupts are taken between
+           TB's.  env->pc is valid here.  */
+        env->pregs[PR_ERP] = env->pc;
+        break;
+    }
+
+    /* Fill in the IDX field.  */
+    env->pregs[PR_EXS] = (ex_vec & 0xff) << 8;
+
+    if (env->dslot) {
+        D_LOG("excp isr=%x PC=%x ds=%d SP=%x"
+              " ERP=%x pid=%x ccs=%x cc=%d %x\n",
+              ex_vec, env->pc, env->dslot,
+              env->regs[R_SP],
+              env->pregs[PR_ERP], env->pregs[PR_PID],
+              env->pregs[PR_CCS],
+              env->cc_op, env->cc_mask);
+        /* We loose the btarget, btaken state here so rexec the
+           branch.  */
+        env->pregs[PR_ERP] -= env->dslot;
+        /* Exception starts with dslot cleared.  */
+        env->dslot = 0;
+    }
 	
-	if (env->pregs[PR_CCS] & U_FLAG) {
-		/* Swap stack pointers.  */
-		env->pregs[PR_USP] = env->regs[R_SP];
-		env->regs[R_SP] = env->ksp;
-	}
-
-	/* Apply the CRIS CCS shift. Clears U if set.  */
-	cris_shift_ccs(env);
-
-	/* Now that we are in kernel mode, load the handlers address.
-	   This load may not fault, real hw leaves that behaviour as
-	   undefined.  */
-        env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
-
-	/* Clear the excption_index to avoid spurios hw_aborts for recursive
-	   bus faults.  */
-	env->exception_index = -1;
-
-	D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
-		   __func__, env->pc, ex_vec,
-		   env->pregs[PR_CCS],
-		   env->pregs[PR_PID], 
-		   env->pregs[PR_ERP]);
+    if (env->pregs[PR_CCS] & U_FLAG) {
+        /* Swap stack pointers.  */
+        env->pregs[PR_USP] = env->regs[R_SP];
+        env->regs[R_SP] = env->ksp;
+    }
+
+    /* Apply the CRIS CCS shift. Clears U if set.  */
+    cris_shift_ccs(env);
+
+    /* Now that we are in kernel mode, load the handlers address.
+       This load may not fault, real hw leaves that behaviour as
+       undefined.  */
+    env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
+
+    /* Clear the excption_index to avoid spurios hw_aborts for recursive
+       bus faults.  */
+    env->exception_index = -1;
+
+    D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
+          __func__, env->pc, ex_vec,
+          env->pregs[PR_CCS],
+          env->pregs[PR_PID],
+          env->pregs[PR_ERP]);
 }
 
 hwaddr cpu_get_phys_page_debug(CPUCRISState * env, target_ulong addr)
 {
-	uint32_t phy = addr;
-	struct cris_mmu_result res;
-	int miss;
-
-	miss = cris_mmu_translate(&res, env, addr, 0, 0, 1);
-	/* If D TLB misses, try I TLB.  */
-	if (miss) {
-		miss = cris_mmu_translate(&res, env, addr, 2, 0, 1);
-	}
-
-	if (!miss)
-		phy = res.phy;
-	D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy));
-	return phy;
+    uint32_t phy = addr;
+    struct cris_mmu_result res;
+    int miss;
+
+    miss = cris_mmu_translate(&res, env, addr, 0, 0, 1);
+    /* If D TLB misses, try I TLB.  */
+    if (miss) {
+        miss = cris_mmu_translate(&res, env, addr, 2, 0, 1);
+    }
+
+    if (!miss) {
+        phy = res.phy;
+    }
+    D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy));
+    return phy;
 }
 #endif
commit f56e3a147683f0ed69d8339e497b7a36e3260c86
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Feb 2 13:38:08 2013 +0100

    target-i386: Update VMStateDescription to X86CPU
    
    Expose vmstate_cpu as vmstate_x86_cpu and hook it up to CPUClass::vmsd.
    Adapt opaques and VMState fields to X86CPU. Drop cpu_{save,load}().
    
    Reviewed-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index b7bdcb6..83c5318 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -76,4 +76,8 @@ static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
 
 #define ENV_OFFSET offsetof(X86CPU, env)
 
+#ifndef CONFIG_USER_ONLY
+extern const struct VMStateDescription vmstate_x86_cpu;
+#endif
+
 #endif
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 8fb736a..8ff2fff 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2250,6 +2250,8 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
 
     xcc->parent_reset = cc->reset;
     cc->reset = x86_cpu_reset;
+
+    cpu_class_set_vmsd(cc, &vmstate_x86_cpu);
 }
 
 static const TypeInfo x86_cpu_type_info = {
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 493dda8..0c1c5c5 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -1092,8 +1092,6 @@ static inline CPUX86State *cpu_init(const char *cpu_model)
 #define cpu_list x86_cpu_list
 #define cpudef_setup	x86_cpudef_setup
 
-#define CPU_SAVE_VERSION 12
-
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
 #define MMU_MODE1_SUFFIX _user
diff --git a/target-i386/machine.c b/target-i386/machine.c
index 8df6a6b..c9984b8 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -171,14 +171,16 @@ static const VMStateInfo vmstate_fpreg_1_no_mmx = {
 
 static bool fpregs_is_0(void *opaque, int version_id)
 {
-    CPUX86State *env = opaque;
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
 
     return (env->fpregs_format_vmstate == 0);
 }
 
 static bool fpregs_is_1_mmx(void *opaque, int version_id)
 {
-    CPUX86State *env = opaque;
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
     int guess_mmx;
 
     guess_mmx = ((env->fptag_vmstate == 0xff) &&
@@ -188,7 +190,8 @@ static bool fpregs_is_1_mmx(void *opaque, int version_id)
 
 static bool fpregs_is_1_no_mmx(void *opaque, int version_id)
 {
-    CPUX86State *env = opaque;
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
     int guess_mmx;
 
     guess_mmx = ((env->fptag_vmstate == 0xff) &&
@@ -237,7 +240,8 @@ static const VMStateInfo vmstate_hack_uint64_as_uint32 = {
 
 static void cpu_pre_save(void *opaque)
 {
-    CPUX86State *env = opaque;
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
     int i;
 
     /* FPU */
@@ -252,7 +256,8 @@ static void cpu_pre_save(void *opaque)
 
 static int cpu_post_load(void *opaque, int version_id)
 {
-    CPUX86State *env = opaque;
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
     int i;
 
     /* XXX: restore FPU round state */
@@ -275,16 +280,16 @@ static int cpu_post_load(void *opaque, int version_id)
 
 static bool async_pf_msr_needed(void *opaque)
 {
-    CPUX86State *cpu = opaque;
+    X86CPU *cpu = opaque;
 
-    return cpu->async_pf_en_msr != 0;
+    return cpu->env.async_pf_en_msr != 0;
 }
 
 static bool pv_eoi_msr_needed(void *opaque)
 {
-    CPUX86State *cpu = opaque;
+    X86CPU *cpu = opaque;
 
-    return cpu->pv_eoi_en_msr != 0;
+    return cpu->env.pv_eoi_en_msr != 0;
 }
 
 static const VMStateDescription vmstate_async_pf_msr = {
@@ -293,7 +298,7 @@ static const VMStateDescription vmstate_async_pf_msr = {
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
-        VMSTATE_UINT64(async_pf_en_msr, CPUX86State),
+        VMSTATE_UINT64(env.async_pf_en_msr, X86CPU),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -304,14 +309,15 @@ static const VMStateDescription vmstate_pv_eoi_msr = {
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
-        VMSTATE_UINT64(pv_eoi_en_msr, CPUX86State),
+        VMSTATE_UINT64(env.pv_eoi_en_msr, X86CPU),
         VMSTATE_END_OF_LIST()
     }
 };
 
 static bool fpop_ip_dp_needed(void *opaque)
 {
-    CPUX86State *env = opaque;
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
 
     return env->fpop != 0 || env->fpip != 0 || env->fpdp != 0;
 }
@@ -322,16 +328,17 @@ static const VMStateDescription vmstate_fpop_ip_dp = {
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
-        VMSTATE_UINT16(fpop, CPUX86State),
-        VMSTATE_UINT64(fpip, CPUX86State),
-        VMSTATE_UINT64(fpdp, CPUX86State),
+        VMSTATE_UINT16(env.fpop, X86CPU),
+        VMSTATE_UINT64(env.fpip, X86CPU),
+        VMSTATE_UINT64(env.fpdp, X86CPU),
         VMSTATE_END_OF_LIST()
     }
 };
 
 static bool tsc_adjust_needed(void *opaque)
 {
-    CPUX86State *env = opaque;
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
 
     return env->tsc_adjust != 0;
 }
@@ -342,14 +349,15 @@ static const VMStateDescription vmstate_msr_tsc_adjust = {
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField[]) {
-        VMSTATE_UINT64(tsc_adjust, CPUX86State),
+        VMSTATE_UINT64(env.tsc_adjust, X86CPU),
         VMSTATE_END_OF_LIST()
     }
 };
 
 static bool tscdeadline_needed(void *opaque)
 {
-    CPUX86State *env = opaque;
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
 
     return env->tsc_deadline != 0;
 }
@@ -360,14 +368,15 @@ static const VMStateDescription vmstate_msr_tscdeadline = {
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
-        VMSTATE_UINT64(tsc_deadline, CPUX86State),
+        VMSTATE_UINT64(env.tsc_deadline, X86CPU),
         VMSTATE_END_OF_LIST()
     }
 };
 
 static bool misc_enable_needed(void *opaque)
 {
-    CPUX86State *env = opaque;
+    X86CPU *cpu = opaque;
+    CPUX86State *env = &cpu->env;
 
     return env->msr_ia32_misc_enable != MSR_IA32_MISC_ENABLE_DEFAULT;
 }
@@ -378,111 +387,111 @@ static const VMStateDescription vmstate_msr_ia32_misc_enable = {
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
-        VMSTATE_UINT64(msr_ia32_misc_enable, CPUX86State),
+        VMSTATE_UINT64(env.msr_ia32_misc_enable, X86CPU),
         VMSTATE_END_OF_LIST()
     }
 };
 
-static const VMStateDescription vmstate_cpu = {
+const VMStateDescription vmstate_x86_cpu = {
     .name = "cpu",
-    .version_id = CPU_SAVE_VERSION,
+    .version_id = 12,
     .minimum_version_id = 3,
     .minimum_version_id_old = 3,
     .pre_save = cpu_pre_save,
     .post_load = cpu_post_load,
     .fields      = (VMStateField []) {
-        VMSTATE_UINTTL_ARRAY(regs, CPUX86State, CPU_NB_REGS),
-        VMSTATE_UINTTL(eip, CPUX86State),
-        VMSTATE_UINTTL(eflags, CPUX86State),
-        VMSTATE_UINT32(hflags, CPUX86State),
+        VMSTATE_UINTTL_ARRAY(env.regs, X86CPU, CPU_NB_REGS),
+        VMSTATE_UINTTL(env.eip, X86CPU),
+        VMSTATE_UINTTL(env.eflags, X86CPU),
+        VMSTATE_UINT32(env.hflags, X86CPU),
         /* FPU */
-        VMSTATE_UINT16(fpuc, CPUX86State),
-        VMSTATE_UINT16(fpus_vmstate, CPUX86State),
-        VMSTATE_UINT16(fptag_vmstate, CPUX86State),
-        VMSTATE_UINT16(fpregs_format_vmstate, CPUX86State),
-        VMSTATE_FP_REGS(fpregs, CPUX86State, 8),
-
-        VMSTATE_SEGMENT_ARRAY(segs, CPUX86State, 6),
-        VMSTATE_SEGMENT(ldt, CPUX86State),
-        VMSTATE_SEGMENT(tr, CPUX86State),
-        VMSTATE_SEGMENT(gdt, CPUX86State),
-        VMSTATE_SEGMENT(idt, CPUX86State),
-
-        VMSTATE_UINT32(sysenter_cs, CPUX86State),
+        VMSTATE_UINT16(env.fpuc, X86CPU),
+        VMSTATE_UINT16(env.fpus_vmstate, X86CPU),
+        VMSTATE_UINT16(env.fptag_vmstate, X86CPU),
+        VMSTATE_UINT16(env.fpregs_format_vmstate, X86CPU),
+        VMSTATE_FP_REGS(env.fpregs, X86CPU, 8),
+
+        VMSTATE_SEGMENT_ARRAY(env.segs, X86CPU, 6),
+        VMSTATE_SEGMENT(env.ldt, X86CPU),
+        VMSTATE_SEGMENT(env.tr, X86CPU),
+        VMSTATE_SEGMENT(env.gdt, X86CPU),
+        VMSTATE_SEGMENT(env.idt, X86CPU),
+
+        VMSTATE_UINT32(env.sysenter_cs, X86CPU),
 #ifdef TARGET_X86_64
         /* Hack: In v7 size changed from 32 to 64 bits on x86_64 */
-        VMSTATE_HACK_UINT32(sysenter_esp, CPUX86State, less_than_7),
-        VMSTATE_HACK_UINT32(sysenter_eip, CPUX86State, less_than_7),
-        VMSTATE_UINTTL_V(sysenter_esp, CPUX86State, 7),
-        VMSTATE_UINTTL_V(sysenter_eip, CPUX86State, 7),
+        VMSTATE_HACK_UINT32(env.sysenter_esp, X86CPU, less_than_7),
+        VMSTATE_HACK_UINT32(env.sysenter_eip, X86CPU, less_than_7),
+        VMSTATE_UINTTL_V(env.sysenter_esp, X86CPU, 7),
+        VMSTATE_UINTTL_V(env.sysenter_eip, X86CPU, 7),
 #else
-        VMSTATE_UINTTL(sysenter_esp, CPUX86State),
-        VMSTATE_UINTTL(sysenter_eip, CPUX86State),
+        VMSTATE_UINTTL(env.sysenter_esp, X86CPU),
+        VMSTATE_UINTTL(env.sysenter_eip, X86CPU),
 #endif
 
-        VMSTATE_UINTTL(cr[0], CPUX86State),
-        VMSTATE_UINTTL(cr[2], CPUX86State),
-        VMSTATE_UINTTL(cr[3], CPUX86State),
-        VMSTATE_UINTTL(cr[4], CPUX86State),
-        VMSTATE_UINTTL_ARRAY(dr, CPUX86State, 8),
+        VMSTATE_UINTTL(env.cr[0], X86CPU),
+        VMSTATE_UINTTL(env.cr[2], X86CPU),
+        VMSTATE_UINTTL(env.cr[3], X86CPU),
+        VMSTATE_UINTTL(env.cr[4], X86CPU),
+        VMSTATE_UINTTL_ARRAY(env.dr, X86CPU, 8),
         /* MMU */
-        VMSTATE_INT32(a20_mask, CPUX86State),
+        VMSTATE_INT32(env.a20_mask, X86CPU),
         /* XMM */
-        VMSTATE_UINT32(mxcsr, CPUX86State),
-        VMSTATE_XMM_REGS(xmm_regs, CPUX86State, CPU_NB_REGS),
+        VMSTATE_UINT32(env.mxcsr, X86CPU),
+        VMSTATE_XMM_REGS(env.xmm_regs, X86CPU, CPU_NB_REGS),
 
 #ifdef TARGET_X86_64
-        VMSTATE_UINT64(efer, CPUX86State),
-        VMSTATE_UINT64(star, CPUX86State),
-        VMSTATE_UINT64(lstar, CPUX86State),
-        VMSTATE_UINT64(cstar, CPUX86State),
-        VMSTATE_UINT64(fmask, CPUX86State),
-        VMSTATE_UINT64(kernelgsbase, CPUX86State),
+        VMSTATE_UINT64(env.efer, X86CPU),
+        VMSTATE_UINT64(env.star, X86CPU),
+        VMSTATE_UINT64(env.lstar, X86CPU),
+        VMSTATE_UINT64(env.cstar, X86CPU),
+        VMSTATE_UINT64(env.fmask, X86CPU),
+        VMSTATE_UINT64(env.kernelgsbase, X86CPU),
 #endif
-        VMSTATE_UINT32_V(smbase, CPUX86State, 4),
-
-        VMSTATE_UINT64_V(pat, CPUX86State, 5),
-        VMSTATE_UINT32_V(hflags2, CPUX86State, 5),
-
-        VMSTATE_UINT32_TEST(halted, CPUX86State, version_is_5),
-        VMSTATE_UINT64_V(vm_hsave, CPUX86State, 5),
-        VMSTATE_UINT64_V(vm_vmcb, CPUX86State, 5),
-        VMSTATE_UINT64_V(tsc_offset, CPUX86State, 5),
-        VMSTATE_UINT64_V(intercept, CPUX86State, 5),
-        VMSTATE_UINT16_V(intercept_cr_read, CPUX86State, 5),
-        VMSTATE_UINT16_V(intercept_cr_write, CPUX86State, 5),
-        VMSTATE_UINT16_V(intercept_dr_read, CPUX86State, 5),
-        VMSTATE_UINT16_V(intercept_dr_write, CPUX86State, 5),
-        VMSTATE_UINT32_V(intercept_exceptions, CPUX86State, 5),
-        VMSTATE_UINT8_V(v_tpr, CPUX86State, 5),
+        VMSTATE_UINT32_V(env.smbase, X86CPU, 4),
+
+        VMSTATE_UINT64_V(env.pat, X86CPU, 5),
+        VMSTATE_UINT32_V(env.hflags2, X86CPU, 5),
+
+        VMSTATE_UINT32_TEST(env.halted, X86CPU, version_is_5),
+        VMSTATE_UINT64_V(env.vm_hsave, X86CPU, 5),
+        VMSTATE_UINT64_V(env.vm_vmcb, X86CPU, 5),
+        VMSTATE_UINT64_V(env.tsc_offset, X86CPU, 5),
+        VMSTATE_UINT64_V(env.intercept, X86CPU, 5),
+        VMSTATE_UINT16_V(env.intercept_cr_read, X86CPU, 5),
+        VMSTATE_UINT16_V(env.intercept_cr_write, X86CPU, 5),
+        VMSTATE_UINT16_V(env.intercept_dr_read, X86CPU, 5),
+        VMSTATE_UINT16_V(env.intercept_dr_write, X86CPU, 5),
+        VMSTATE_UINT32_V(env.intercept_exceptions, X86CPU, 5),
+        VMSTATE_UINT8_V(env.v_tpr, X86CPU, 5),
         /* MTRRs */
-        VMSTATE_UINT64_ARRAY_V(mtrr_fixed, CPUX86State, 11, 8),
-        VMSTATE_UINT64_V(mtrr_deftype, CPUX86State, 8),
-        VMSTATE_MTRR_VARS(mtrr_var, CPUX86State, 8, 8),
+        VMSTATE_UINT64_ARRAY_V(env.mtrr_fixed, X86CPU, 11, 8),
+        VMSTATE_UINT64_V(env.mtrr_deftype, X86CPU, 8),
+        VMSTATE_MTRR_VARS(env.mtrr_var, X86CPU, 8, 8),
         /* KVM-related states */
-        VMSTATE_INT32_V(interrupt_injected, CPUX86State, 9),
-        VMSTATE_UINT32_V(mp_state, CPUX86State, 9),
-        VMSTATE_UINT64_V(tsc, CPUX86State, 9),
-        VMSTATE_INT32_V(exception_injected, CPUX86State, 11),
-        VMSTATE_UINT8_V(soft_interrupt, CPUX86State, 11),
-        VMSTATE_UINT8_V(nmi_injected, CPUX86State, 11),
-        VMSTATE_UINT8_V(nmi_pending, CPUX86State, 11),
-        VMSTATE_UINT8_V(has_error_code, CPUX86State, 11),
-        VMSTATE_UINT32_V(sipi_vector, CPUX86State, 11),
+        VMSTATE_INT32_V(env.interrupt_injected, X86CPU, 9),
+        VMSTATE_UINT32_V(env.mp_state, X86CPU, 9),
+        VMSTATE_UINT64_V(env.tsc, X86CPU, 9),
+        VMSTATE_INT32_V(env.exception_injected, X86CPU, 11),
+        VMSTATE_UINT8_V(env.soft_interrupt, X86CPU, 11),
+        VMSTATE_UINT8_V(env.nmi_injected, X86CPU, 11),
+        VMSTATE_UINT8_V(env.nmi_pending, X86CPU, 11),
+        VMSTATE_UINT8_V(env.has_error_code, X86CPU, 11),
+        VMSTATE_UINT32_V(env.sipi_vector, X86CPU, 11),
         /* MCE */
-        VMSTATE_UINT64_V(mcg_cap, CPUX86State, 10),
-        VMSTATE_UINT64_V(mcg_status, CPUX86State, 10),
-        VMSTATE_UINT64_V(mcg_ctl, CPUX86State, 10),
-        VMSTATE_UINT64_ARRAY_V(mce_banks, CPUX86State, MCE_BANKS_DEF *4, 10),
+        VMSTATE_UINT64_V(env.mcg_cap, X86CPU, 10),
+        VMSTATE_UINT64_V(env.mcg_status, X86CPU, 10),
+        VMSTATE_UINT64_V(env.mcg_ctl, X86CPU, 10),
+        VMSTATE_UINT64_ARRAY_V(env.mce_banks, X86CPU, MCE_BANKS_DEF * 4, 10),
         /* rdtscp */
-        VMSTATE_UINT64_V(tsc_aux, CPUX86State, 11),
+        VMSTATE_UINT64_V(env.tsc_aux, X86CPU, 11),
         /* KVM pvclock msr */
-        VMSTATE_UINT64_V(system_time_msr, CPUX86State, 11),
-        VMSTATE_UINT64_V(wall_clock_msr, CPUX86State, 11),
+        VMSTATE_UINT64_V(env.system_time_msr, X86CPU, 11),
+        VMSTATE_UINT64_V(env.wall_clock_msr, X86CPU, 11),
         /* XSAVE related fields */
-        VMSTATE_UINT64_V(xcr0, CPUX86State, 12),
-        VMSTATE_UINT64_V(xstate_bv, CPUX86State, 12),
-        VMSTATE_YMMH_REGS_VARS(ymmh_regs, CPUX86State, CPU_NB_REGS, 12),
+        VMSTATE_UINT64_V(env.xcr0, X86CPU, 12),
+        VMSTATE_UINT64_V(env.xstate_bv, X86CPU, 12),
+        VMSTATE_YMMH_REGS_VARS(env.ymmh_regs, X86CPU, CPU_NB_REGS, 12),
         VMSTATE_END_OF_LIST()
         /* The above list is not sorted /wrt version numbers, watch out! */
     },
@@ -510,13 +519,3 @@ static const VMStateDescription vmstate_cpu = {
         }
     }
 };
-
-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 ca91b15f2d2e43eba8f9a3ec5090f0a11b861ba4
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Feb 22 21:50:10 2013 +0100

    cpu: Introduce cpu_class_set_vmsd()
    
    This setter avoids redefining each VMStateDescription value to
    vmstate_dummy by not referencing the value for CONFIG_USER_ONLY.
    
    Suggested-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 5b1b0d7..90c5f45 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -138,6 +138,27 @@ void cpu_reset(CPUState *cpu);
 ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model);
 
 /**
+ * cpu_class_set_vmsd:
+ * @cc: CPU class
+ * @value: Value to set. Unused for %CONFIG_USER_ONLY.
+ *
+ * Sets #VMStateDescription for @cc.
+ *
+ * The @value argument is intentionally discarded for the non-softmmu targets
+ * to avoid linker errors or excessive preprocessor usage. If this behavior
+ * is undesired, you should assign #CPUState.vmsd directly instead.
+ */
+#ifndef CONFIG_USER_ONLY
+static inline void cpu_class_set_vmsd(CPUClass *cc,
+                                      const struct VMStateDescription *value)
+{
+    cc->vmsd = value;
+}
+#else
+#define cpu_class_set_vmsd(cc, value) ((cc)->vmsd = NULL)
+#endif
+
+/**
  * qemu_cpu_has_work:
  * @cpu: The vCPU to check.
  *
commit b170fce3dd06372f7bfec9a780ebcb1fce6d57e4
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Jan 20 20:23:22 2013 +0100

    cpu: Register VMStateDescription through CPUState
    
    In comparison to DeviceClass::vmsd, CPU VMState is split in two,
    "cpu_common" and "cpu", and uses cpu_index as instance_id instead of -1.
    Therefore add a CPU-specific CPUClass::vmsd field.
    
    Unlike the legacy CPUArchState registration, rather register CPUState.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Eduardo Habkost <ehabkost at redhat.com>

diff --git a/exec.c b/exec.c
index 0a96ddb..254ae62 100644
--- a/exec.c
+++ b/exec.c
@@ -219,7 +219,7 @@ void cpu_exec_init_all(void)
 #endif
 }
 
-#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
+#if !defined(CONFIG_USER_ONLY)
 
 static int cpu_common_post_load(void *opaque, int version_id)
 {
@@ -245,6 +245,8 @@ static const VMStateDescription vmstate_cpu_common = {
         VMSTATE_END_OF_LIST()
     }
 };
+#else
+#define vmstate_cpu_common vmstate_dummy
 #endif
 
 CPUState *qemu_get_cpu(int index)
@@ -266,6 +268,7 @@ CPUState *qemu_get_cpu(int index)
 void cpu_exec_init(CPUArchState *env)
 {
     CPUState *cpu = ENV_GET_CPU(env);
+    CPUClass *cc = CPU_GET_CLASS(cpu);
     CPUArchState **penv;
     int cpu_index;
 
@@ -290,11 +293,15 @@ void cpu_exec_init(CPUArchState *env)
 #if defined(CONFIG_USER_ONLY)
     cpu_list_unlock();
 #endif
-#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
     vmstate_register(NULL, cpu_index, &vmstate_cpu_common, env);
+#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
     register_savevm(NULL, "cpu", cpu_index, CPU_SAVE_VERSION,
                     cpu_save, cpu_load, env);
+    assert(cc->vmsd == NULL);
 #endif
+    if (cc->vmsd != NULL) {
+        vmstate_register(NULL, cpu_index, cc->vmsd, cpu);
+    }
 }
 
 #if defined(TARGET_HAS_ICE)
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index ab2657c..5b1b0d7 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -44,6 +44,7 @@ typedef struct CPUState CPUState;
  * @class_by_name: Callback to map -cpu command line model name to an
  * instantiatable CPU type.
  * @reset: Callback to reset the #CPUState to its initial state.
+ * @vmsd: State description for migration.
  *
  * Represents a CPU family or model.
  */
@@ -55,6 +56,8 @@ typedef struct CPUClass {
     ObjectClass *(*class_by_name)(const char *cpu_model);
 
     void (*reset)(CPUState *cpu);
+
+    const struct VMStateDescription *vmsd;
 } CPUClass;
 
 struct KVMState;
commit c71c3e99b8897323af8c2fe0b9851610cd148538
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon Feb 18 17:56:20 2013 +0100

    stubs: Add a vmstate_dummy struct for CONFIG_USER_ONLY
    
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 20db76f..6666d27 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -134,6 +134,10 @@ struct VMStateDescription {
     const VMStateSubsection *subsections;
 };
 
+#ifdef CONFIG_USER_ONLY
+extern const VMStateDescription vmstate_dummy;
+#endif
+
 extern const VMStateInfo vmstate_info_bool;
 
 extern const VMStateInfo vmstate_info_int8;
diff --git a/stubs/vmstate.c b/stubs/vmstate.c
index 3682af5..778bc3f 100644
--- a/stubs/vmstate.c
+++ b/stubs/vmstate.c
@@ -1,6 +1,8 @@
 #include "qemu-common.h"
 #include "migration/vmstate.h"
 
+const VMStateDescription vmstate_dummy = {};
+
 int vmstate_register_with_alias_id(DeviceState *dev,
                                    int instance_id,
                                    const VMStateDescription *vmsd,
commit d7650eab429a033c23947f20d1ae14c4d1e719a3
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon Feb 18 21:41:59 2013 +0100

    vmstate: Make vmstate_register() static inline
    
    This avoids adding a duplicate stub for CONFIG_USER_ONLY.
    
    Suggested-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index a64db94..20db76f 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -638,12 +638,20 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
                        void *opaque, int version_id);
 void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
                         void *opaque);
-int vmstate_register(DeviceState *dev, int instance_id,
-                     const VMStateDescription *vmsd, void *base);
+
 int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
                                    const VMStateDescription *vmsd,
                                    void *base, int alias_id,
                                    int required_for_version);
+
+static inline int vmstate_register(DeviceState *dev, int instance_id,
+                                   const VMStateDescription *vmsd,
+                                   void *opaque)
+{
+    return vmstate_register_with_alias_id(dev, instance_id, vmsd,
+                                          opaque, -1, 0);
+}
+
 void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
                         void *opaque);
 
diff --git a/savevm.c b/savevm.c
index 147e2d2..35c8d1e 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1423,13 +1423,6 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
     return 0;
 }
 
-int vmstate_register(DeviceState *dev, int instance_id,
-                     const VMStateDescription *vmsd, void *opaque)
-{
-    return vmstate_register_with_alias_id(dev, instance_id, vmsd,
-                                          opaque, -1, 0);
-}
-
 void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
                         void *opaque)
 {
commit b350ab758342c764a6ead6ef064b15a72c830808
Author: Andreas Färber <afaerber at suse.de>
Date:   Tue Nov 20 16:15:47 2012 +0100

    target-sh4: Move PVR/PRR/CVR into SuperHCPUClass
    
    They are never changed once initialized, and moving them to the class
    will allow to inspect them before instantiating.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/sh4/sh7750.c b/hw/sh4/sh7750.c
index 6778c94..e4d37ad 100644
--- a/hw/sh4/sh7750.c
+++ b/hw/sh4/sh7750.c
@@ -255,6 +255,7 @@ static uint32_t sh7750_mem_readw(void *opaque, hwaddr addr)
 static uint32_t sh7750_mem_readl(void *opaque, hwaddr addr)
 {
     SH7750State *s = opaque;
+    SuperHCPUClass *scc;
 
     switch (addr) {
     case SH7750_BCR1_A7:
@@ -288,11 +289,14 @@ static uint32_t sh7750_mem_readl(void *opaque, hwaddr addr)
     case SH7750_CCR_A7:
 	return s->ccr;
     case 0x1f000030:		/* Processor version */
-	return s->cpu->pvr;
+        scc = SUPERH_CPU_GET_CLASS(s->cpu);
+        return scc->pvr;
     case 0x1f000040:		/* Cache version */
-	return s->cpu->cvr;
+        scc = SUPERH_CPU_GET_CLASS(s->cpu);
+        return scc->cvr;
     case 0x1f000044:		/* Processor revision */
-	return s->cpu->prr;
+        scc = SUPERH_CPU_GET_CLASS(s->cpu);
+        return scc->prr;
     default:
 	error_access("long read", addr);
         abort();
diff --git a/target-sh4/cpu-qom.h b/target-sh4/cpu-qom.h
index 19d8b08..29628c8 100644
--- a/target-sh4/cpu-qom.h
+++ b/target-sh4/cpu-qom.h
@@ -40,6 +40,9 @@
  * @parent_realize: The parent class' realize handler.
  * @parent_reset: The parent class' reset handler.
  * @name: The name.
+ * @pvr: Processor Version Register
+ * @prr: Processor Revision Register
+ * @cvr: Cache Version Register
  *
  * A SuperH CPU model.
  */
@@ -52,6 +55,9 @@ typedef struct SuperHCPUClass {
     void (*parent_reset)(CPUState *cpu);
 
     const char *name;
+    uint32_t pvr;
+    uint32_t prr;
+    uint32_t cvr;
 } SuperHCPUClass;
 
 /**
diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c
index fba1534..5251aa0 100644
--- a/target-sh4/cpu.c
+++ b/target-sh4/cpu.c
@@ -156,9 +156,6 @@ static void sh7750r_cpu_initfn(Object *obj)
     CPUSH4State *env = &cpu->env;
 
     env->id = SH_CPU_SH7750R;
-    env->pvr = 0x00050000;
-    env->prr = 0x00000100;
-    env->cvr = 0x00110000;
     env->features = SH_FEATURE_BCR3_AND_BCR4;
 }
 
@@ -167,6 +164,9 @@ static void sh7750r_class_init(ObjectClass *oc, void *data)
     SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
 
     scc->name = "SH7750R";
+    scc->pvr = 0x00050000;
+    scc->prr = 0x00000100;
+    scc->cvr = 0x00110000;
 }
 
 static const TypeInfo sh7750r_type_info = {
@@ -182,9 +182,6 @@ static void sh7751r_cpu_initfn(Object *obj)
     CPUSH4State *env = &cpu->env;
 
     env->id = SH_CPU_SH7751R;
-    env->pvr = 0x04050005;
-    env->prr = 0x00000113;
-    env->cvr = 0x00110000; /* Neutered caches, should be 0x20480000 */
     env->features = SH_FEATURE_BCR3_AND_BCR4;
 }
 
@@ -193,6 +190,9 @@ static void sh7751r_class_init(ObjectClass *oc, void *data)
     SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
 
     scc->name = "SH7751R";
+    scc->pvr = 0x04050005;
+    scc->prr = 0x00000113;
+    scc->cvr = 0x00110000; /* Neutered caches, should be 0x20480000 */
 }
 
 static const TypeInfo sh7751r_type_info = {
@@ -208,9 +208,6 @@ static void sh7785_cpu_initfn(Object *obj)
     CPUSH4State *env = &cpu->env;
 
     env->id = SH_CPU_SH7785;
-    env->pvr = 0x10300700;
-    env->prr = 0x00000200;
-    env->cvr = 0x71440211;
     env->features = SH_FEATURE_SH4A;
 }
 
@@ -219,6 +216,9 @@ static void sh7785_class_init(ObjectClass *oc, void *data)
     SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
 
     scc->name = "SH7785";
+    scc->pvr = 0x10300700;
+    scc->prr = 0x00000200;
+    scc->cvr = 0x71440211;
 }
 
 static const TypeInfo sh7785_type_info = {
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 49dcd9e..f805778 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -179,9 +179,6 @@ typedef struct CPUSH4State {
     CPU_COMMON
 
     int id;			/* CPU model */
-    uint32_t pvr;		/* Processor Version Register */
-    uint32_t prr;		/* Processor Revision Register */
-    uint32_t cvr;		/* Cache Version Register */
 
     void *intc_handle;
     int in_sleep;		/* SR_BL ignored during sleep */
commit c1b382e77d8693955d8838c19b33aeb214724f9b
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon Nov 19 02:42:18 2012 +0100

    target-sh4: Introduce SuperHCPU subclasses
    
    Store legacy name in SuperHCPUClass for -cpu ? and for case-insensitive
    class lookup.
    
    List CPUs by iterating over TYPE_SUPERH_CPU subclasses.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-sh4/cpu-qom.h b/target-sh4/cpu-qom.h
index f4e8976..19d8b08 100644
--- a/target-sh4/cpu-qom.h
+++ b/target-sh4/cpu-qom.h
@@ -24,6 +24,10 @@
 
 #define TYPE_SUPERH_CPU "superh-cpu"
 
+#define TYPE_SH7750R_CPU "sh7750r-" TYPE_SUPERH_CPU
+#define TYPE_SH7751R_CPU "sh7751r-" TYPE_SUPERH_CPU
+#define TYPE_SH7785_CPU "sh7785-" TYPE_SUPERH_CPU
+
 #define SUPERH_CPU_CLASS(klass) \
     OBJECT_CLASS_CHECK(SuperHCPUClass, (klass), TYPE_SUPERH_CPU)
 #define SUPERH_CPU(obj) \
@@ -35,6 +39,7 @@
  * SuperHCPUClass:
  * @parent_realize: The parent class' realize handler.
  * @parent_reset: The parent class' reset handler.
+ * @name: The name.
  *
  * A SuperH CPU model.
  */
@@ -45,6 +50,8 @@ typedef struct SuperHCPUClass {
 
     DeviceRealize parent_realize;
     void (*parent_reset)(CPUState *cpu);
+
+    const char *name;
 } SuperHCPUClass;
 
 /**
diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c
index ef0e621..fba1534 100644
--- a/target-sh4/cpu.c
+++ b/target-sh4/cpu.c
@@ -54,6 +54,180 @@ static void superh_cpu_reset(CPUState *s)
     set_default_nan_mode(1, &env->fp_status);
 }
 
+typedef struct SuperHCPUListState {
+    fprintf_function cpu_fprintf;
+    FILE *file;
+} SuperHCPUListState;
+
+/* Sort alphabetically by type name. */
+static gint superh_cpu_list_compare(gconstpointer a, gconstpointer b)
+{
+    ObjectClass *class_a = (ObjectClass *)a;
+    ObjectClass *class_b = (ObjectClass *)b;
+    const char *name_a, *name_b;
+
+    name_a = object_class_get_name(class_a);
+    name_b = object_class_get_name(class_b);
+    return strcmp(name_a, name_b);
+}
+
+static void superh_cpu_list_entry(gpointer data, gpointer user_data)
+{
+    ObjectClass *oc = data;
+    SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
+    SuperHCPUListState *s = user_data;
+
+    (*s->cpu_fprintf)(s->file, "%s\n",
+                      scc->name);
+}
+
+void sh4_cpu_list(FILE *f, fprintf_function cpu_fprintf)
+{
+    SuperHCPUListState s = {
+        .cpu_fprintf = cpu_fprintf,
+        .file = f,
+    };
+    GSList *list;
+
+    list = object_class_get_list(TYPE_SUPERH_CPU, false);
+    list = g_slist_sort(list, superh_cpu_list_compare);
+    g_slist_foreach(list, superh_cpu_list_entry, &s);
+    g_slist_free(list);
+}
+
+static gint superh_cpu_name_compare(gconstpointer a, gconstpointer b)
+{
+    const SuperHCPUClass *scc = SUPERH_CPU_CLASS(a);
+    const char *name = b;
+
+    return strcasecmp(scc->name, name);
+}
+
+static ObjectClass *superh_cpu_class_by_name(const char *cpu_model)
+{
+    ObjectClass *oc;
+    GSList *list, *item;
+
+    if (cpu_model == NULL) {
+        return NULL;
+    }
+    if (strcasecmp(cpu_model, "any") == 0) {
+        return object_class_by_name(TYPE_SH7750R_CPU);
+    }
+
+    oc = object_class_by_name(cpu_model);
+    if (oc != NULL && object_class_dynamic_cast(oc, TYPE_SUPERH_CPU) != NULL
+        && !object_class_is_abstract(oc)) {
+        return oc;
+    }
+
+    oc = NULL;
+    list = object_class_get_list(TYPE_SUPERH_CPU, false);
+    item = g_slist_find_custom(list, cpu_model, superh_cpu_name_compare);
+    if (item != NULL) {
+        oc = item->data;
+    }
+    g_slist_free(list);
+    return oc;
+}
+
+SuperHCPU *cpu_sh4_init(const char *cpu_model)
+{
+    SuperHCPU *cpu;
+    CPUSH4State *env;
+    ObjectClass *oc;
+
+    oc = superh_cpu_class_by_name(cpu_model);
+    if (oc == NULL) {
+        return NULL;
+    }
+    cpu = SUPERH_CPU(object_new(object_class_get_name(oc)));
+    env = &cpu->env;
+    env->cpu_model_str = cpu_model;
+
+    object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
+
+    return cpu;
+}
+
+static void sh7750r_cpu_initfn(Object *obj)
+{
+    SuperHCPU *cpu = SUPERH_CPU(obj);
+    CPUSH4State *env = &cpu->env;
+
+    env->id = SH_CPU_SH7750R;
+    env->pvr = 0x00050000;
+    env->prr = 0x00000100;
+    env->cvr = 0x00110000;
+    env->features = SH_FEATURE_BCR3_AND_BCR4;
+}
+
+static void sh7750r_class_init(ObjectClass *oc, void *data)
+{
+    SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
+
+    scc->name = "SH7750R";
+}
+
+static const TypeInfo sh7750r_type_info = {
+    .name = TYPE_SH7750R_CPU,
+    .parent = TYPE_SUPERH_CPU,
+    .class_init = sh7750r_class_init,
+    .instance_init = sh7750r_cpu_initfn,
+};
+
+static void sh7751r_cpu_initfn(Object *obj)
+{
+    SuperHCPU *cpu = SUPERH_CPU(obj);
+    CPUSH4State *env = &cpu->env;
+
+    env->id = SH_CPU_SH7751R;
+    env->pvr = 0x04050005;
+    env->prr = 0x00000113;
+    env->cvr = 0x00110000; /* Neutered caches, should be 0x20480000 */
+    env->features = SH_FEATURE_BCR3_AND_BCR4;
+}
+
+static void sh7751r_class_init(ObjectClass *oc, void *data)
+{
+    SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
+
+    scc->name = "SH7751R";
+}
+
+static const TypeInfo sh7751r_type_info = {
+    .name = TYPE_SH7751R_CPU,
+    .parent = TYPE_SUPERH_CPU,
+    .class_init = sh7751r_class_init,
+    .instance_init = sh7751r_cpu_initfn,
+};
+
+static void sh7785_cpu_initfn(Object *obj)
+{
+    SuperHCPU *cpu = SUPERH_CPU(obj);
+    CPUSH4State *env = &cpu->env;
+
+    env->id = SH_CPU_SH7785;
+    env->pvr = 0x10300700;
+    env->prr = 0x00000200;
+    env->cvr = 0x71440211;
+    env->features = SH_FEATURE_SH4A;
+}
+
+static void sh7785_class_init(ObjectClass *oc, void *data)
+{
+    SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
+
+    scc->name = "SH7785";
+}
+
+static const TypeInfo sh7785_type_info = {
+    .name = TYPE_SH7785_CPU,
+    .parent = TYPE_SUPERH_CPU,
+    .class_init = sh7785_class_init,
+    .instance_init = sh7785_cpu_initfn,
+};
+
 static void superh_cpu_realizefn(DeviceState *dev, Error **errp)
 {
     SuperHCPU *cpu = SUPERH_CPU(dev);
@@ -98,6 +272,7 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data)
     scc->parent_reset = cc->reset;
     cc->reset = superh_cpu_reset;
 
+    cc->class_by_name = superh_cpu_class_by_name;
     dc->vmsd = &vmstate_sh_cpu;
 }
 
@@ -106,7 +281,7 @@ static const TypeInfo superh_cpu_type_info = {
     .parent = TYPE_CPU,
     .instance_size = sizeof(SuperHCPU),
     .instance_init = superh_cpu_initfn,
-    .abstract = false,
+    .abstract = true,
     .class_size = sizeof(SuperHCPUClass),
     .class_init = superh_cpu_class_init,
 };
@@ -114,6 +289,9 @@ static const TypeInfo superh_cpu_type_info = {
 static void superh_cpu_register_types(void)
 {
     type_register_static(&superh_cpu_type_info);
+    type_register_static(&sh7750r_type_info);
+    type_register_static(&sh7751r_type_info);
+    type_register_static(&sh7785_type_info);
 }
 
 type_init(superh_cpu_register_types)
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 7f300e3..14fdb8f 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -175,90 +175,6 @@ void cpu_dump_state(CPUSH4State * env, FILE * f,
     }
 }
 
-typedef struct {
-    const char *name;
-    int id;
-    uint32_t pvr;
-    uint32_t prr;
-    uint32_t cvr;
-    uint32_t features;
-} sh4_def_t;
-
-static sh4_def_t sh4_defs[] = {
-    {
-	.name = "SH7750R",
-	.id = SH_CPU_SH7750R,
-	.pvr = 0x00050000,
-	.prr = 0x00000100,
-	.cvr = 0x00110000,
-	.features = SH_FEATURE_BCR3_AND_BCR4,
-    }, {
-	.name = "SH7751R",
-	.id = SH_CPU_SH7751R,
-	.pvr = 0x04050005,
-	.prr = 0x00000113,
-	.cvr = 0x00110000,	/* Neutered caches, should be 0x20480000 */
-	.features = SH_FEATURE_BCR3_AND_BCR4,
-    }, {
-	.name = "SH7785",
-	.id = SH_CPU_SH7785,
-	.pvr = 0x10300700,
-	.prr = 0x00000200,
-	.cvr = 0x71440211,
-	.features = SH_FEATURE_SH4A,
-     },
-};
-
-static const sh4_def_t *cpu_sh4_find_by_name(const char *name)
-{
-    int i;
-
-    if (strcasecmp(name, "any") == 0)
-	return &sh4_defs[0];
-
-    for (i = 0; i < ARRAY_SIZE(sh4_defs); i++)
-	if (strcasecmp(name, sh4_defs[i].name) == 0)
-	    return &sh4_defs[i];
-
-    return NULL;
-}
-
-void sh4_cpu_list(FILE *f, fprintf_function cpu_fprintf)
-{
-    int i;
-
-    for (i = 0; i < ARRAY_SIZE(sh4_defs); i++)
-	(*cpu_fprintf)(f, "%s\n", sh4_defs[i].name);
-}
-
-static void cpu_register(CPUSH4State *env, const sh4_def_t *def)
-{
-    env->pvr = def->pvr;
-    env->prr = def->prr;
-    env->cvr = def->cvr;
-    env->id = def->id;
-}
-
-SuperHCPU *cpu_sh4_init(const char *cpu_model)
-{
-    SuperHCPU *cpu;
-    CPUSH4State *env;
-    const sh4_def_t *def;
-
-    def = cpu_sh4_find_by_name(cpu_model);
-    if (!def)
-	return NULL;
-    cpu = SUPERH_CPU(object_new(TYPE_SUPERH_CPU));
-    env = &cpu->env;
-    env->features = def->features;
-    env->cpu_model_str = cpu_model;
-    cpu_register(env, def);
-
-    object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
-
-    return cpu;
-}
-
 static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest)
 {
     TranslationBlock *tb;
commit 151d1322a3a0c865089c09aeb50f18215121921a
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Feb 15 15:41:49 2013 +0100

    cpus: Replace open-coded CPU loop in qmp_memsave() with qemu_get_cpu()
    
    No functional change, just less usages of first_cpu and next_cpu fields.
    
    env is passed to cpu_memory_rw_debug(), which in turn passes it to
    target-specific cpu_get_phys_page_debug(). Changing both would be a
    larger refactoring, so defer that by using env_ptr for now.
    
    Reviewed-by: Luiz Capitulino <lcapitulino at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/cpus.c b/cpus.c
index c4b021d..46355c1 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1241,18 +1241,13 @@ void qmp_memsave(int64_t addr, int64_t size, const char *filename,
         cpu_index = 0;
     }
 
-    for (env = first_cpu; env; env = env->next_cpu) {
-        cpu = ENV_GET_CPU(env);
-        if (cpu_index == cpu->cpu_index) {
-            break;
-        }
-    }
-
-    if (env == NULL) {
+    cpu = qemu_get_cpu(cpu_index);
+    if (cpu == NULL) {
         error_set(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
                   "a CPU number");
         return;
     }
+    env = cpu->env_ptr;
 
     f = fopen(filename, "wb");
     if (!f) {
commit 1c8bb3cc7b98ad07a028567b86fc6baa5c5a0b7a
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Feb 15 17:01:09 2013 +0100

    monitor: Use qemu_get_cpu() in monitor_set_cpu()
    
    No functional change, just a reduction of CPU loops.
    
    The mon_cpu field is left untouched for now since changing that requires
    a number of larger prerequisites, including cpu_synchronize_state() and
    mon_get_cpu().
    
    Reviewed-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/monitor.c b/monitor.c
index c48530b..ab05c49 100644
--- a/monitor.c
+++ b/monitor.c
@@ -855,17 +855,14 @@ EventInfoList *qmp_query_events(Error **errp)
 /* set the current CPU defined by the user */
 int monitor_set_cpu(int cpu_index)
 {
-    CPUArchState *env;
     CPUState *cpu;
 
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu = ENV_GET_CPU(env);
-        if (cpu->cpu_index == cpu_index) {
-            cur_mon->mon_cpu = env;
-            return 0;
-        }
+    cpu = qemu_get_cpu(cpu_index);
+    if (cpu == NULL) {
+        return -1;
     }
-    return -1;
+    cur_mon->mon_cpu = cpu->env_ptr;
+    return 0;
 }
 
 static CPUArchState *mon_get_cpu(void)
commit d76fddaeeec674cab4802b585db6c9fb3a0066dc
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Thu Mar 7 19:12:43 2013 +0100

    cpu: Fix qemu_get_cpu() to return NULL if CPU not found
    
    Commit 55e5c2850 breaks CPU not found return value, and returns
    CPU corresponding to the last non NULL env.
    Fix it by returning CPU only if env is not NULL, otherwise CPU is
    not found and function should return NULL.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>

diff --git a/exec.c b/exec.c
index 46a2830..0a96ddb 100644
--- a/exec.c
+++ b/exec.c
@@ -260,7 +260,7 @@ CPUState *qemu_get_cpu(int index)
         env = env->next_cpu;
     }
 
-    return cpu;
+    return env ? cpu : NULL;
 }
 
 void cpu_exec_init(CPUArchState *env)
commit cbb65fc27fd97a3b020df7fce9db4ce09e3956ad
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Wed Mar 6 22:59:31 2013 +0100

    qga: implement qmp_guest_set_vcpus() for Linux with sysfs
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 17cedab..d7da850 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -1245,6 +1245,32 @@ GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
     return NULL;
 }
 
+int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
+{
+    int64_t processed;
+    Error *local_err = NULL;
+
+    processed = 0;
+    while (vcpus != NULL) {
+        transfer_vcpu(vcpus->value, false, &local_err);
+        if (local_err != NULL) {
+            break;
+        }
+        ++processed;
+        vcpus = vcpus->next;
+    }
+
+    if (local_err != NULL) {
+        if (processed == 0) {
+            error_propagate(errp, local_err);
+        } else {
+            error_free(local_err);
+        }
+    }
+
+    return processed;
+}
+
 #else /* defined(__linux__) */
 
 void qmp_guest_suspend_disk(Error **err)
@@ -1274,6 +1300,12 @@ GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
     return NULL;
 }
 
+int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
+{
+    error_set(errp, QERR_UNSUPPORTED);
+    return -1;
+}
+
 #endif
 
 #if !defined(CONFIG_FSFREEZE)
@@ -1307,12 +1339,6 @@ void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
 }
 #endif
 
-int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
-{
-    error_set(errp, QERR_UNSUPPORTED);
-    return -1;
-}
-
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
commit d2baff62538d6c638c1c0d2b3fc900060a90dd78
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Wed Mar 6 22:59:30 2013 +0100

    qga: implement qmp_guest_get_vcpus() for Linux with sysfs
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 03a41a2..17cedab 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -15,6 +15,10 @@
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <sys/wait.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
 #include "qga/guest-agent-core.h"
 #include "qga-qmp-commands.h"
 #include "qapi/qmp/qerror.h"
@@ -1111,6 +1115,136 @@ error:
     return NULL;
 }
 
+#define SYSCONF_EXACT(name, err) sysconf_exact((name), #name, (err))
+
+static long sysconf_exact(int name, const char *name_str, Error **err)
+{
+    long ret;
+
+    errno = 0;
+    ret = sysconf(name);
+    if (ret == -1) {
+        if (errno == 0) {
+            error_setg(err, "sysconf(%s): value indefinite", name_str);
+        } else {
+            error_setg_errno(err, errno, "sysconf(%s)", name_str);
+        }
+    }
+    return ret;
+}
+
+/* Transfer online/offline status between @vcpu and the guest system.
+ *
+ * On input either @errp or *@errp must be NULL.
+ *
+ * In system-to- at vcpu direction, the following @vcpu fields are accessed:
+ * - R: vcpu->logical_id
+ * - W: vcpu->online
+ * - W: vcpu->can_offline
+ *
+ * In @vcpu-to-system direction, the following @vcpu fields are accessed:
+ * - R: vcpu->logical_id
+ * - R: vcpu->online
+ *
+ * Written members remain unmodified on error.
+ */
+static void transfer_vcpu(GuestLogicalProcessor *vcpu, bool sys2vcpu,
+                          Error **errp)
+{
+    char *dirpath;
+    int dirfd;
+
+    dirpath = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/",
+                              vcpu->logical_id);
+    dirfd = open(dirpath, O_RDONLY | O_DIRECTORY);
+    if (dirfd == -1) {
+        error_setg_errno(errp, errno, "open(\"%s\")", dirpath);
+    } else {
+        static const char fn[] = "online";
+        int fd;
+        int res;
+
+        fd = openat(dirfd, fn, sys2vcpu ? O_RDONLY : O_RDWR);
+        if (fd == -1) {
+            if (errno != ENOENT) {
+                error_setg_errno(errp, errno, "open(\"%s/%s\")", dirpath, fn);
+            } else if (sys2vcpu) {
+                vcpu->online = true;
+                vcpu->can_offline = false;
+            } else if (!vcpu->online) {
+                error_setg(errp, "logical processor #%" PRId64 " can't be "
+                           "offlined", vcpu->logical_id);
+            } /* otherwise pretend successful re-onlining */
+        } else {
+            unsigned char status;
+
+            res = pread(fd, &status, 1, 0);
+            if (res == -1) {
+                error_setg_errno(errp, errno, "pread(\"%s/%s\")", dirpath, fn);
+            } else if (res == 0) {
+                error_setg(errp, "pread(\"%s/%s\"): unexpected EOF", dirpath,
+                           fn);
+            } else if (sys2vcpu) {
+                vcpu->online = (status != '0');
+                vcpu->can_offline = true;
+            } else if (vcpu->online != (status != '0')) {
+                status = '0' + vcpu->online;
+                if (pwrite(fd, &status, 1, 0) == -1) {
+                    error_setg_errno(errp, errno, "pwrite(\"%s/%s\")", dirpath,
+                                     fn);
+                }
+            } /* otherwise pretend successful re-(on|off)-lining */
+
+            res = close(fd);
+            g_assert(res == 0);
+        }
+
+        res = close(dirfd);
+        g_assert(res == 0);
+    }
+
+    g_free(dirpath);
+}
+
+GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
+{
+    int64_t current;
+    GuestLogicalProcessorList *head, **link;
+    long sc_max;
+    Error *local_err = NULL;
+
+    current = 0;
+    head = NULL;
+    link = &head;
+    sc_max = SYSCONF_EXACT(_SC_NPROCESSORS_CONF, &local_err);
+
+    while (local_err == NULL && current < sc_max) {
+        GuestLogicalProcessor *vcpu;
+        GuestLogicalProcessorList *entry;
+
+        vcpu = g_malloc0(sizeof *vcpu);
+        vcpu->logical_id = current++;
+        vcpu->has_can_offline = true; /* lolspeak ftw */
+        transfer_vcpu(vcpu, true, &local_err);
+
+        entry = g_malloc0(sizeof *entry);
+        entry->value = vcpu;
+
+        *link = entry;
+        link = &entry->next;
+    }
+
+    if (local_err == NULL) {
+        /* there's no guest with zero VCPUs */
+        g_assert(head != NULL);
+        return head;
+    }
+
+    qapi_free_GuestLogicalProcessorList(head);
+    error_propagate(errp, local_err);
+    return NULL;
+}
+
 #else /* defined(__linux__) */
 
 void qmp_guest_suspend_disk(Error **err)
@@ -1134,6 +1268,12 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
     return NULL;
 }
 
+GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
+{
+    error_set(errp, QERR_UNSUPPORTED);
+    return NULL;
+}
+
 #endif
 
 #if !defined(CONFIG_FSFREEZE)
@@ -1167,12 +1307,6 @@ void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
 }
 #endif
 
-GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
-{
-    error_set(errp, QERR_UNSUPPORTED);
-    return NULL;
-}
-
 int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
 {
     error_set(errp, QERR_UNSUPPORTED);
commit 70e133a7080116340b1a8898893c6d455bd47299
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Wed Mar 6 22:59:29 2013 +0100

    qga: introduce guest-get-vcpus / guest-set-vcpus with stubs
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index c253f97..03a41a2 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -1167,6 +1167,18 @@ void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
 }
 #endif
 
+GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
+{
+    error_set(errp, QERR_UNSUPPORTED);
+    return NULL;
+}
+
+int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
+{
+    error_set(errp, QERR_UNSUPPORTED);
+    return -1;
+}
+
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 622c74d..b19be9d 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -289,6 +289,18 @@ void qmp_guest_set_time(int64_t time_ns, Error **errp)
     error_set(errp, QERR_UNSUPPORTED);
 }
 
+GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
+{
+    error_set(errp, QERR_UNSUPPORTED);
+    return NULL;
+}
+
+int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
+{
+    error_set(errp, QERR_UNSUPPORTED);
+    return -1;
+}
+
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index 437d750..dac4e6f 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -554,3 +554,75 @@
 ##
 { 'command': 'guest-network-get-interfaces',
   'returns': ['GuestNetworkInterface'] }
+
+##
+# @GuestLogicalProcessor:
+#
+# @logical-id: Arbitrary guest-specific unique identifier of the VCPU.
+#
+# @online: Whether the VCPU is enabled.
+#
+# @can-offline: Whether offlining the VCPU is possible. This member is always
+#               filled in by the guest agent when the structure is returned,
+#               and always ignored on input (hence it can be omitted then).
+#
+# Since: 1.5
+##
+{ 'type': 'GuestLogicalProcessor',
+  'data': {'logical-id': 'int',
+           'online': 'bool',
+           '*can-offline': 'bool'} }
+
+##
+# @guest-get-vcpus:
+#
+# Retrieve the list of the guest's logical processors.
+#
+# This is a read-only operation.
+#
+# Returns: The list of all VCPUs the guest knows about. Each VCPU is put on the
+# list exactly once, but their order is unspecified.
+#
+# Since: 1.5
+##
+{ 'command': 'guest-get-vcpus',
+  'returns': ['GuestLogicalProcessor'] }
+
+##
+# @guest-set-vcpus:
+#
+# Attempt to reconfigure (currently: enable/disable) logical processors inside
+# the guest.
+#
+# The input list is processed node by node in order. In each node @logical-id
+# is used to look up the guest VCPU, for which @online specifies the requested
+# state. The set of distinct @logical-id's is only required to be a subset of
+# the guest-supported identifiers. There's no restriction on list length or on
+# repeating the same @logical-id (with possibly different @online field).
+# Preferably the input list should describe a modified subset of
+# @guest-get-vcpus' return value.
+#
+# Returns: The length of the initial sublist that has been successfully
+#          processed. The guest agent maximizes this value. Possible cases:
+#
+#          0:                if the @vcpus list was empty on input. Guest state
+#                            has not been changed. Otherwise,
+#
+#          Error:            processing the first node of @vcpus failed for the
+#                            reason returned. Guest state has not been changed.
+#                            Otherwise,
+#
+#          < length(@vcpus): more than zero initial nodes have been processed,
+#                            but not the entire @vcpus list. Guest state has
+#                            changed accordingly. To retrieve the error
+#                            (assuming it persists), repeat the call with the
+#                            successfully processed initial sublist removed.
+#                            Otherwise,
+#
+#          length(@vcpus):   call successful.
+#
+# Since: 1.5
+##
+{ 'command': 'guest-set-vcpus',
+  'data':    {'vcpus': ['GuestLogicalProcessor'] },
+  'returns': 'int' }
commit a1bca57f758a1ebe2ee808aa6c94f7687f9cfdd0
Author: Lei Li <lilei at linux.vnet.ibm.com>
Date:   Tue Mar 5 17:39:12 2013 +0800

    qga: add guest-set-time command
    
    Signed-off-by: Lei Li <lilei at linux.vnet.ibm.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    
    *added stub for w32
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index c83d26d..c253f97 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -135,6 +135,61 @@ int64_t qmp_guest_get_time(Error **errp)
    return time_ns;
 }
 
+void qmp_guest_set_time(int64_t time_ns, Error **errp)
+{
+    int ret;
+    int status;
+    pid_t pid;
+    Error *local_err = NULL;
+    struct timeval tv;
+
+    /* year-2038 will overflow in case time_t is 32bit */
+    if (time_ns / 1000000000 != (time_t)(time_ns / 1000000000)) {
+        error_setg(errp, "Time %" PRId64 " is too large", time_ns);
+        return;
+    }
+
+    tv.tv_sec = time_ns / 1000000000;
+    tv.tv_usec = (time_ns % 1000000000) / 1000;
+
+    ret = settimeofday(&tv, NULL);
+    if (ret < 0) {
+        error_setg_errno(errp, errno, "Failed to set time to guest");
+        return;
+    }
+
+    /* Set the Hardware Clock to the current System Time. */
+    pid = fork();
+    if (pid == 0) {
+        setsid();
+        reopen_fd_to_null(0);
+        reopen_fd_to_null(1);
+        reopen_fd_to_null(2);
+
+        execle("/sbin/hwclock", "hwclock", "-w", NULL, environ);
+        _exit(EXIT_FAILURE);
+    } else if (pid < 0) {
+        error_setg_errno(errp, errno, "failed to create child process");
+        return;
+    }
+
+    ga_wait_child(pid, &status, &local_err);
+    if (error_is_set(&local_err)) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    if (!WIFEXITED(status)) {
+        error_setg(errp, "child process has terminated abnormally");
+        return;
+    }
+
+    if (WEXITSTATUS(status)) {
+        error_setg(errp, "hwclock failed to set hardware clock to system time");
+        return;
+    }
+}
+
 typedef struct GuestFileHandle {
     uint64_t id;
     FILE *fh;
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 3ebb856..622c74d 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -284,6 +284,11 @@ int64_t qmp_guest_get_time(Error **errp)
     return -1;
 }
 
+void qmp_guest_set_time(int64_t time_ns, Error **errp)
+{
+    error_set(errp, QERR_UNSUPPORTED);
+}
+
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index bb0f75e..437d750 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -96,6 +96,32 @@
   'returns': 'int' }
 
 ##
+# @guest-set-time:
+#
+# Set guest time.
+#
+# When a guest is paused or migrated to a file then loaded
+# from that file, the guest OS has no idea that there
+# was a big gap in the time. Depending on how long the
+# gap was, NTP might not be able to resynchronize the
+# guest.
+#
+# This command tries to set guest time to the given value,
+# then sets the Hardware Clock to the current System Time.
+# This will make it easier for a guest to resynchronize
+# without waiting for NTP.
+#
+# @time: time of nanoseconds, relative to the Epoch of
+#        1970-01-01 in UTC.
+#
+# Returns: Nothing on success.
+#
+# Since: 1.5
+##
+{ 'command': 'guest-set-time',
+  'data': { 'time': 'int' } }
+
+##
 # @GuestAgentCommandInfo:
 #
 # Information about guest agent commands.
commit 6912e6a94cb0a1d650271103efbc3ac2299e4fd0
Author: Lei Li <lilei at linux.vnet.ibm.com>
Date:   Tue Mar 5 17:39:11 2013 +0800

    qga: add guest-get-time command
    
    Signed-off-by: Lei Li <lilei at linux.vnet.ibm.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    
    *added stub for w32
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 1c2aff3..c83d26d 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -119,6 +119,22 @@ void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
     /* succeded */
 }
 
+int64_t qmp_guest_get_time(Error **errp)
+{
+   int ret;
+   qemu_timeval tq;
+   int64_t time_ns;
+
+   ret = qemu_gettimeofday(&tq);
+   if (ret < 0) {
+       error_setg_errno(errp, errno, "Failed to get time");
+       return -1;
+   }
+
+   time_ns = tq.tv_sec * 1000000000LL + tq.tv_usec * 1000;
+   return time_ns;
+}
+
 typedef struct GuestFileHandle {
     uint64_t id;
     FILE *fh;
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 7e8ecb3..3ebb856 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -278,6 +278,12 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **err)
     return NULL;
 }
 
+int64_t qmp_guest_get_time(Error **errp)
+{
+    error_set(errp, QERR_UNSUPPORTED);
+    return -1;
+}
+
 /* register init/cleanup routines for stateful command groups */
 void ga_command_state_init(GAState *s, GACommandState *cs)
 {
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index d91d903..bb0f75e 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -83,6 +83,19 @@
 { 'command': 'guest-ping' }
 
 ##
+# @guest-get-time:
+#
+# Get the information about guest time relative to the Epoch
+# of 1970-01-01 in UTC.
+#
+# Returns: Time in nanoseconds.
+#
+# Since 1.5
+##
+{ 'command': 'guest-get-time',
+  'returns': 'int' }
+
+##
 # @GuestAgentCommandInfo:
 #
 # Information about guest agent commands.
commit 39097daf15c42243742667607d2cad2c9dc4f764
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Fri Mar 1 11:40:27 2013 -0600

    qemu-ga: use key-value store to avoid recycling fd handles after restart
    
    Hosts hold on to handles provided by guest-file-open for periods that can
    span beyond the life of the qemu-ga process that issued them. Since these
    are issued starting from 0 on every restart, we run the risk of issuing
    duplicate handles after restarts/reboots.
    
    As a result, users with a stale copy of these handles may end up
    reading/writing corrupted data due to their existing handles effectively
    being re-assigned to an unexpected file or offset.
    
    We unfortunately do not issue handles as strings, but as integers, so a
    solution such as using UUIDs can't be implemented without introducing a
    new interface.
    
    As a workaround, we fix this by implementing a persistent key-value store
    that will be used to track the value of the last handle that was issued
    across restarts/reboots to avoid issuing duplicates.
    
    The store is automatically written to the same directory we currently
    set via --statedir to track fsfreeze state, and so should be applicable
    for stable releases where this flag is supported.
    
    A follow-up can use this same store for handling fsfreeze state, but
    that change is cosmetic and left out for now.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Cc: qemu-stable at nongnu.org
    
    * fixed guest_file_handle_add() return value from uint64_t to int64_t

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 7a0202e..1c2aff3 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -129,14 +129,22 @@ static struct {
     QTAILQ_HEAD(, GuestFileHandle) filehandles;
 } guest_file_state;
 
-static void guest_file_handle_add(FILE *fh)
+static int64_t guest_file_handle_add(FILE *fh, Error **errp)
 {
     GuestFileHandle *gfh;
+    int64_t handle;
+
+    handle = ga_get_fd_handle(ga_state, errp);
+    if (error_is_set(errp)) {
+        return 0;
+    }
 
     gfh = g_malloc0(sizeof(GuestFileHandle));
-    gfh->id = fileno(fh);
+    gfh->id = handle;
     gfh->fh = fh;
     QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next);
+
+    return handle;
 }
 
 static GuestFileHandle *guest_file_handle_find(int64_t id, Error **err)
@@ -158,7 +166,7 @@ int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, E
 {
     FILE *fh;
     int fd;
-    int64_t ret = -1;
+    int64_t ret = -1, handle;
 
     if (!has_mode) {
         mode = "r";
@@ -184,9 +192,14 @@ int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, E
         return -1;
     }
 
-    guest_file_handle_add(fh);
-    slog("guest-file-open, handle: %d", fd);
-    return fd;
+    handle = guest_file_handle_add(fh, err);
+    if (error_is_set(err)) {
+        fclose(fh);
+        return -1;
+    }
+
+    slog("guest-file-open, handle: %d", handle);
+    return handle;
 }
 
 void qmp_guest_file_close(int64_t handle, Error **err)
diff --git a/qga/guest-agent-core.h b/qga/guest-agent-core.h
index 3354598..624a559 100644
--- a/qga/guest-agent-core.h
+++ b/qga/guest-agent-core.h
@@ -35,6 +35,7 @@ bool ga_is_frozen(GAState *s);
 void ga_set_frozen(GAState *s);
 void ga_unset_frozen(GAState *s);
 const char *ga_fsfreeze_hook(GAState *s);
+int64_t ga_get_fd_handle(GAState *s, Error **errp);
 
 #ifndef _WIN32
 void reopen_fd_to_null(int fd);
diff --git a/qga/main.c b/qga/main.c
index ad75171..99346e1 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -15,6 +15,7 @@
 #include <stdbool.h>
 #include <glib.h>
 #include <getopt.h>
+#include <glib/gstdio.h>
 #ifndef _WIN32
 #include <syslog.h>
 #include <sys/wait.h>
@@ -30,6 +31,7 @@
 #include "qapi/qmp/qerror.h"
 #include "qapi/qmp/dispatch.h"
 #include "qga/channel.h"
+#include "qemu/bswap.h"
 #ifdef _WIN32
 #include "qga/service-win32.h"
 #include <windows.h>
@@ -53,6 +55,11 @@
 #endif
 #define QGA_SENTINEL_BYTE 0xFF
 
+typedef struct GAPersistentState {
+#define QGA_PSTATE_DEFAULT_FD_COUNTER 1000
+    int64_t fd_counter;
+} GAPersistentState;
+
 struct GAState {
     JSONMessageParser parser;
     GMainLoop *main_loop;
@@ -76,6 +83,8 @@ struct GAState {
 #ifdef CONFIG_FSFREEZE
     const char *fsfreeze_hook;
 #endif
+    const gchar *pstate_filepath;
+    GAPersistentState pstate;
 };
 
 struct GAState *ga_state;
@@ -725,6 +734,171 @@ VOID WINAPI service_main(DWORD argc, TCHAR *argv[])
 }
 #endif
 
+static void set_persistent_state_defaults(GAPersistentState *pstate)
+{
+    g_assert(pstate);
+    pstate->fd_counter = QGA_PSTATE_DEFAULT_FD_COUNTER;
+}
+
+static void persistent_state_from_keyfile(GAPersistentState *pstate,
+                                          GKeyFile *keyfile)
+{
+    g_assert(pstate);
+    g_assert(keyfile);
+    /* if any fields are missing, either because the file was tampered with
+     * by agents of chaos, or because the field wasn't present at the time the
+     * file was created, the best we can ever do is start over with the default
+     * values. so load them now, and ignore any errors in accessing key-value
+     * pairs
+     */
+    set_persistent_state_defaults(pstate);
+
+    if (g_key_file_has_key(keyfile, "global", "fd_counter", NULL)) {
+        pstate->fd_counter =
+            g_key_file_get_int64(keyfile, "global", "fd_counter", NULL);
+    }
+}
+
+static void persistent_state_to_keyfile(const GAPersistentState *pstate,
+                                        GKeyFile *keyfile)
+{
+    g_assert(pstate);
+    g_assert(keyfile);
+
+    g_key_file_set_int64(keyfile, "global", "fd_counter", pstate->fd_counter);
+}
+
+static gboolean write_persistent_state(const GAPersistentState *pstate,
+                                       const gchar *path)
+{
+    GKeyFile *keyfile = g_key_file_new();
+    GError *gerr = NULL;
+    gboolean ret = true;
+    gchar *data = NULL;
+    gsize data_len;
+
+    g_assert(pstate);
+
+    persistent_state_to_keyfile(pstate, keyfile);
+    data = g_key_file_to_data(keyfile, &data_len, &gerr);
+    if (gerr) {
+        g_critical("failed to convert persistent state to string: %s",
+                   gerr->message);
+        ret = false;
+        goto out;
+    }
+
+    g_file_set_contents(path, data, data_len, &gerr);
+    if (gerr) {
+        g_critical("failed to write persistent state to %s: %s",
+                    path, gerr->message);
+        ret = false;
+        goto out;
+    }
+
+out:
+    if (gerr) {
+        g_error_free(gerr);
+    }
+    if (keyfile) {
+        g_key_file_free(keyfile);
+    }
+    g_free(data);
+    return ret;
+}
+
+static gboolean read_persistent_state(GAPersistentState *pstate,
+                                      const gchar *path, gboolean frozen)
+{
+    GKeyFile *keyfile = NULL;
+    GError *gerr = NULL;
+    struct stat st;
+    gboolean ret = true;
+
+    g_assert(pstate);
+
+    if (stat(path, &st) == -1) {
+        /* it's okay if state file doesn't exist, but any other error
+         * indicates a permissions issue or some other misconfiguration
+         * that we likely won't be able to recover from.
+         */
+        if (errno != ENOENT) {
+            g_critical("unable to access state file at path %s: %s",
+                       path, strerror(errno));
+            ret = false;
+            goto out;
+        }
+
+        /* file doesn't exist. initialize state to default values and
+         * attempt to save now. (we could wait till later when we have
+         * modified state we need to commit, but if there's a problem,
+         * such as a missing parent directory, we want to catch it now)
+         *
+         * there is a potential scenario where someone either managed to
+         * update the agent from a version that didn't use a key store
+         * while qemu-ga thought the filesystem was frozen, or
+         * deleted the key store prior to issuing a fsfreeze, prior
+         * to restarting the agent. in this case we go ahead and defer
+         * initial creation till we actually have modified state to
+         * write, otherwise fail to recover from freeze.
+         */
+        set_persistent_state_defaults(pstate);
+        if (!frozen) {
+            ret = write_persistent_state(pstate, path);
+            if (!ret) {
+                g_critical("unable to create state file at path %s", path);
+                ret = false;
+                goto out;
+            }
+        }
+        ret = true;
+        goto out;
+    }
+
+    keyfile = g_key_file_new();
+    g_key_file_load_from_file(keyfile, path, 0, &gerr);
+    if (gerr) {
+        g_critical("error loading persistent state from path: %s, %s",
+                   path, gerr->message);
+        ret = false;
+        goto out;
+    }
+
+    persistent_state_from_keyfile(pstate, keyfile);
+
+out:
+    if (keyfile) {
+        g_key_file_free(keyfile);
+    }
+    if (gerr) {
+        g_error_free(gerr);
+    }
+
+    return ret;
+}
+
+int64_t ga_get_fd_handle(GAState *s, Error **errp)
+{
+    int64_t handle;
+
+    g_assert(s->pstate_filepath);
+    /* we blacklist commands and avoid operations that potentially require
+     * writing to disk when we're in a frozen state. this includes opening
+     * new files, so we should never get here in that situation
+     */
+    g_assert(!ga_is_frozen(s));
+
+    handle = s->pstate.fd_counter++;
+    if (s->pstate.fd_counter < 0) {
+        s->pstate.fd_counter = 0;
+    }
+    if (!write_persistent_state(&s->pstate, s->pstate_filepath)) {
+        error_setg(errp, "failed to commit persistent state to disk");
+    }
+
+    return handle;
+}
+
 int main(int argc, char **argv)
 {
     const char *sopt = "hVvdm:p:l:f:F::b:s:t:";
@@ -854,7 +1028,9 @@ int main(int argc, char **argv)
     ga_enable_logging(s);
     s->state_filepath_isfrozen = g_strdup_printf("%s/qga.state.isfrozen",
                                                  state_dir);
+    s->pstate_filepath = g_strdup_printf("%s/qga.state", state_dir);
     s->frozen = false;
+
 #ifndef _WIN32
     /* check if a previous instance of qemu-ga exited with filesystems' state
      * marked as frozen. this could be a stale value (a non-qemu-ga process
@@ -911,6 +1087,14 @@ int main(int argc, char **argv)
         }
     }
 
+    /* load persistent state from disk */
+    if (!read_persistent_state(&s->pstate,
+                               s->pstate_filepath,
+                               ga_is_frozen(s))) {
+        g_critical("failed to load persistent state");
+        goto out_bad;
+    }
+
     if (blacklist) {
         s->blacklist = blacklist;
         do {
commit c5dcb6ae23a3ed7a01bae1cd75ce02abea31db5e
Author: Michael Roth <mdroth at linux.vnet.ibm.com>
Date:   Fri Mar 1 11:49:38 2013 -0600

    qemu-ga: make guest-sync-delimited available during fsfreeze
    
    We currently maintain a whitelist of commands that are safe during
    fsfreeze. During fsfreeze, we disable all commands that aren't part of
    that whitelist.
    
    guest-sync-delimited meets the criteria for being whitelisted, and is
    also required for qemu-ga clients that rely on guest-sync-delimited for
    re-syncing the channel after a timeout.
    
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>
    Cc: qemu-stable at nongnu.org
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/qga/main.c b/qga/main.c
index db281a5..ad75171 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -85,6 +85,7 @@ static const char *ga_freeze_whitelist[] = {
     "guest-ping",
     "guest-info",
     "guest-sync",
+    "guest-sync-delimited",
     "guest-fsfreeze-status",
     "guest-fsfreeze-thaw",
     NULL
commit 9e7c23db13b23febac4ba2d22419aa8f1884929e
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Tue Feb 19 15:12:34 2013 +0100

    qemu-ga: fix confusing GAChannelMethod comparison
    
    In commit 7868e26e5930f49ca942311885776b938dcf3b77
    ("qemu-ga: add initial win32 support") support was added for qemu-ga on
    Windows using virtio-serial.  Other channel methods (ISA serial and UNIX
    domain socket) are not supported on Windows.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>

diff --git a/qga/channel-win32.c b/qga/channel-win32.c
index 16bf44a..7ed98d7 100644
--- a/qga/channel-win32.c
+++ b/qga/channel-win32.c
@@ -287,7 +287,7 @@ GIOStatus ga_channel_write_all(GAChannel *c, const char *buf, size_t size)
 static gboolean ga_channel_open(GAChannel *c, GAChannelMethod method,
                                 const gchar *path)
 {
-    if (!method == GA_CHANNEL_VIRTIO_SERIAL) {
+    if (method != GA_CHANNEL_VIRTIO_SERIAL) {
         g_critical("unsupported communication method");
         return false;
     }
commit ed2cbf74446b008f9de526a50e4b06265635120c
Author: Lei Li <lilei at linux.vnet.ibm.com>
Date:   Mon Jan 28 12:49:09 2013 +0800

    qga: cast to int for DWORD type
    
    This patch fixes a compiler warning when cross-build:
    
    qga/service-win32.c: In function 'printf_win_error':
    qga/service-win32.c:32:5: warning: format '%d' expects argument of type 'int',
                              but argument 3 has type 'DWORD' [-Wformat]
    
    Signed-off-by: Lei Li <lilei at linux.vnet.ibm.com>
    Signed-off-by: Michael Roth <mdroth at linux.vnet.ibm.com>

diff --git a/qga/service-win32.c b/qga/service-win32.c
index 0905456..843398a 100644
--- a/qga/service-win32.c
+++ b/qga/service-win32.c
@@ -29,7 +29,7 @@ static int printf_win_error(const char *text)
         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
         (char *)&message, 0,
         NULL);
-    n = printf("%s. (Error: %d) %s", text, err, message);
+    n = printf("%s. (Error: %d) %s", text, (int)err, message);
     LocalFree(message);
 
     return n;
commit fe3cc14fd83e0c8f376d849ccd0fc3433388442d
Merge: bba18e2 ee0b44a
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 11 08:30:34 2013 -0500

    Merge remote-tracking branch 'quintela/migration.next' into staging
    
    # By Paolo Bonzini (40) and others
    # Via Juan Quintela
    * quintela/migration.next: (46 commits)
      page_cache: dup memory on insert
      page_cache: fix memory leak
      Fix cache_resize to keep old entry age
      Fix page_cache leak in cache_resize
      migration: inline migrate_fd_close
      migration: eliminate s->migration_file
      migration: move contents of migration_close to migrate_fd_cleanup
      migration: move rate limiting to QEMUFile
      migration: small changes around rate-limiting
      migration: use qemu_ftell to compute bandwidth
      migration: use QEMUFile for writing outgoing migration data
      migration: use QEMUFile for migration channel lifetime
      qemu-file: simplify and export qemu_ftell
      qemu-file: add writable socket QEMUFile
      qemu-file: check exit status when closing a pipe QEMUFile
      qemu-file: fsync a writable stdio QEMUFile
      migration: merge qemu_popen_cmd with qemu_popen
      migration: use qemu_file_rate_limit consistently
      migration: remove useless qemu_file_get_error check
      migration: detect error before sleeping
      ...

commit bba18e23f7266d63734fd31045fec7794cc34a38
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 11 11:31:26 2013 +0100

    arm: fix compilation with CONFIG_FDT
    
    A conflict was resolved the wrong way when merging commit 320ba5f (build:
    always link device_tree.o into emulators if libfdt available, 2013-02-05).
    This causes a build failure for the arm-softmmu target due to multiply
    defined symbol.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1362997886-9470-1-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 2d9c69d..f5f7d0e 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -23,7 +23,6 @@ obj-y += bitbang_i2c.o marvell_88w8618_audio.o
 obj-y += framebuffer.o
 obj-y += strongarm.o
 obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
-obj-$(CONFIG_FDT) += ../device_tree.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
 
 obj-y := $(addprefix ../,$(obj-y))
commit e9a970a8316f9f86a6c800a9a90175bd593f862c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Feb 8 04:34:54 2013 +0000

    linux-user/syscall.c: Don't warn about unimplemented get_robust_list
    
    The nature of the kernel ABI for the get_robust_list and set_robust_list
    syscalls means we cannot implement them in QEMU. Make get_robust_list
    silently return ENOSYS rather than using the default "print message and
    then fail ENOSYS" code path, in the same way we already do for
    set_robust_list, and add a comment documenting why we do this.
    
    This silences warnings which were being produced for emulating
    even trivial programs like 'ls' in x86-64-on-x86-64.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 6182a27..ee82a2d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8631,7 +8631,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 
 #ifdef TARGET_NR_set_robust_list
     case TARGET_NR_set_robust_list:
-	goto unimplemented_nowarn;
+    case TARGET_NR_get_robust_list:
+        /* The ABI for supporting robust futexes has userspace pass
+         * the kernel a pointer to a linked list which is updated by
+         * userspace after the syscall; the list is walked by the kernel
+         * when the thread exits. Since the linked list in QEMU guest
+         * memory isn't a valid linked list for the host and we have
+         * no way to reliably intercept the thread-death event, we can't
+         * support these. Silently return ENOSYS so that guest userspace
+         * falls back to a non-robust futex implementation (which should
+         * be OK except in the corner case of the guest crashing while
+         * holding a mutex that is shared with another process via
+         * shared memory).
+         */
+        goto unimplemented_nowarn;
 #endif
 
 #if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
commit a94b4987e243d9afebf56a098afeddae133276b5
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Feb 8 04:35:04 2013 +0000

    linux-user: Implement accept4
    
    Implement the accept4 syscall (which is identical to accept
    but has an additional flags argument).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 77281f1..6182a27 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2004,16 +2004,30 @@ out2:
     return ret;
 }
 
-/* do_accept() Must return target values and target errnos. */
-static abi_long do_accept(int fd, abi_ulong target_addr,
-                          abi_ulong target_addrlen_addr)
+/* If we don't have a system accept4() then just call accept.
+ * The callsites to do_accept4() will ensure that they don't
+ * pass a non-zero flags argument in this config.
+ */
+#ifndef CONFIG_ACCEPT4
+static inline int accept4(int sockfd, struct sockaddr *addr,
+                          socklen_t *addrlen, int flags)
+{
+    assert(flags == 0);
+    return accept(sockfd, addr, addrlen);
+}
+#endif
+
+/* do_accept4() Must return target values and target errnos. */
+static abi_long do_accept4(int fd, abi_ulong target_addr,
+                           abi_ulong target_addrlen_addr, int flags)
 {
     socklen_t addrlen;
     void *addr;
     abi_long ret;
 
-    if (target_addr == 0)
-       return get_errno(accept(fd, NULL, NULL));
+    if (target_addr == 0) {
+        return get_errno(accept4(fd, NULL, NULL, flags));
+    }
 
     /* linux returns EINVAL if addrlen pointer is invalid */
     if (get_user_u32(addrlen, target_addrlen_addr))
@@ -2028,7 +2042,7 @@ static abi_long do_accept(int fd, abi_ulong target_addr,
 
     addr = alloca(addrlen);
 
-    ret = get_errno(accept(fd, addr, &addrlen));
+    ret = get_errno(accept4(fd, addr, &addrlen, flags));
     if (!is_error(ret)) {
         host_to_target_sockaddr(target_addr, addr, addrlen);
         if (put_user_u32(addrlen, target_addrlen_addr))
@@ -2254,7 +2268,7 @@ static abi_long do_socketcall(int num, abi_ulong vptr)
                 || get_user_ual(target_addrlen, vptr + 2 * n))
                 return -TARGET_EFAULT;
 
-            ret = do_accept(sockfd, target_addr, target_addrlen);
+            ret = do_accept4(sockfd, target_addr, target_addrlen, 0);
         }
         break;
     case SOCKOP_getsockname:
@@ -6677,7 +6691,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 #ifdef TARGET_NR_accept
     case TARGET_NR_accept:
-        ret = do_accept(arg1, arg2, arg3);
+        ret = do_accept4(arg1, arg2, arg3, 0);
+        break;
+#endif
+#ifdef TARGET_NR_accept4
+    case TARGET_NR_accept4:
+#ifdef CONFIG_ACCEPT4
+        ret = do_accept4(arg1, arg2, arg3, arg4);
+#else
+        goto unimplemented;
+#endif
         break;
 #endif
 #ifdef TARGET_NR_bind
commit a8fd1aba8584cbe68583907ce766fd8ecfe81f4b
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Feb 8 07:31:55 2013 +0000

    linux-user: Implement sendfile and sendfile64
    
    Implement the sendfile and sendfile64 syscalls. This implementation
    passes all the LTP test cases for these syscalls.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/configure b/configure
index 84317c6..a416e23 100755
--- a/configure
+++ b/configure
@@ -2760,6 +2760,20 @@ if compile_prog "" "" ; then
   epoll_pwait=yes
 fi
 
+# check for sendfile support
+sendfile=no
+cat > $TMPC << EOF
+#include <sys/sendfile.h>
+
+int main(void)
+{
+    return sendfile(0, 0, 0, 0);
+}
+EOF
+if compile_prog "" "" ; then
+  sendfile=yes
+fi
+
 # Check if tools are available to build documentation.
 if test "$docs" != "no" ; then
   if has makeinfo && has pod2man; then
@@ -3628,6 +3642,9 @@ fi
 if test "$epoll_pwait" = "yes" ; then
   echo "CONFIG_EPOLL_PWAIT=y" >> $config_host_mak
 fi
+if test "$sendfile" = "yes" ; then
+  echo "CONFIG_SENDFILE=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 bab9ab5..77281f1 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -78,6 +78,9 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
 #ifdef CONFIG_ATTR
 #include "qemu/xattr.h"
 #endif
+#ifdef CONFIG_SENDFILE
+#include <sys/sendfile.h>
+#endif
 
 #define termios host_termios
 #define winsize host_winsize
@@ -7531,8 +7534,58 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #else
         goto unimplemented;
 #endif
+
+#ifdef CONFIG_SENDFILE
+    case TARGET_NR_sendfile:
+    {
+        off_t *offp = NULL;
+        off_t off;
+        if (arg3) {
+            ret = get_user_sal(off, arg3);
+            if (is_error(ret)) {
+                break;
+            }
+            offp = &off;
+        }
+        ret = get_errno(sendfile(arg1, arg2, offp, arg4));
+        if (!is_error(ret) && arg3) {
+            abi_long ret2 = put_user_sal(off, arg3);
+            if (is_error(ret2)) {
+                ret = ret2;
+            }
+        }
+        break;
+    }
+#ifdef TARGET_NR_sendfile64
+    case TARGET_NR_sendfile64:
+    {
+        off_t *offp = NULL;
+        off_t off;
+        if (arg3) {
+            ret = get_user_s64(off, arg3);
+            if (is_error(ret)) {
+                break;
+            }
+            offp = &off;
+        }
+        ret = get_errno(sendfile(arg1, arg2, offp, arg4));
+        if (!is_error(ret) && arg3) {
+            abi_long ret2 = put_user_s64(off, arg3);
+            if (is_error(ret2)) {
+                ret = ret2;
+            }
+        }
+        break;
+    }
+#endif
+#else
     case TARGET_NR_sendfile:
+#ifdef TARGET_NR_sendfile64:
+    case TARGET_NR_sendfile64:
+#endif
         goto unimplemented;
+#endif
+
 #ifdef TARGET_NR_getpmsg
     case TARGET_NR_getpmsg:
         goto unimplemented;
commit dfae8e00f8ddeedcda24bd28f71d4fd2a9f988b8
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Feb 8 07:58:41 2013 +0000

    linux-user: make bogus negative iovec lengths fail EINVAL
    
    If the guest passes us a bogus negative length for an iovec, fail
    EINVAL rather than proceeding blindly forward. This fixes some of
    the error cases tests for readv and writev in the LTP.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 1729446..bab9ab5 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1776,7 +1776,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
         errno = 0;
         return NULL;
     }
-    if (count > IOV_MAX) {
+    if (count < 0 || count > IOV_MAX) {
         errno = EINVAL;
         return NULL;
     }
commit 63ec54d7b319824df8b60cfe25afdfb607ce3905
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Feb 14 08:46:43 2013 +0000

    linux-user: Fix layout of usage table to account for option text
    
    The linux-user usage message attempts to line up the columns in
    its table by calculating the maximum width of any item in them.
    However for the 'Argument' column it was only accounting for the
    length of the option switch (eg "-d"), not the additional example
    text (eg "item[,...]"). This currently has no adverse effects
    because the widest item in the column happens to be the argumentless
    "-singlestep" option, but improving the "-d" option help to read
    "-d item[,...]" exceeds that limit.
    
    Fix this by correctly calculating maxarglen as the width of the
    first column text including a possible option argument, and
    adjusting its uses to match.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/main.c b/linux-user/main.c
index d8b0cd6..4e92a0b 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3406,27 +3406,35 @@ static void usage(void)
            "Options and associated environment variables:\n"
            "\n");
 
-    maxarglen = maxenvlen = 0;
+    /* Calculate column widths. We must always have at least enough space
+     * for the column header.
+     */
+    maxarglen = strlen("Argument");
+    maxenvlen = strlen("Env-variable");
 
     for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
+        int arglen = strlen(arginfo->argv);
+        if (arginfo->has_arg) {
+            arglen += strlen(arginfo->example) + 1;
+        }
         if (strlen(arginfo->env) > maxenvlen) {
             maxenvlen = strlen(arginfo->env);
         }
-        if (strlen(arginfo->argv) > maxarglen) {
-            maxarglen = strlen(arginfo->argv);
+        if (arglen > maxarglen) {
+            maxarglen = arglen;
         }
     }
 
-    printf("%-*s%-*sDescription\n", maxarglen+3, "Argument",
-            maxenvlen+1, "Env-variable");
+    printf("%-*s %-*s Description\n", maxarglen+1, "Argument",
+            maxenvlen, "Env-variable");
 
     for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
         if (arginfo->has_arg) {
             printf("-%s %-*s %-*s %s\n", arginfo->argv,
-                    (int)(maxarglen-strlen(arginfo->argv)), arginfo->example,
-                    maxenvlen, arginfo->env, arginfo->help);
+                   (int)(maxarglen - strlen(arginfo->argv) - 1),
+                   arginfo->example, maxenvlen, arginfo->env, arginfo->help);
         } else {
-            printf("-%-*s %-*s %s\n", maxarglen+1, arginfo->argv,
+            printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv,
                     maxenvlen, arginfo->env,
                     arginfo->help);
         }
commit ee0b44aa9d9450e873a761ca2030b2fa3ec52eb0
Author: Peter Lieven <pl at dlhnet.de>
Date:   Mon Feb 25 19:12:04 2013 +0200

    page_cache: dup memory on insert
    
    The page cache frees all data on finish, on resize and
    if there is collision on insert. So it should be the caches
    responsibility to dup the data that is stored in the cache.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 6089c53..98e2bc6 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -293,8 +293,7 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
 
     if (!cache_is_cached(XBZRLE.cache, current_addr)) {
         if (!last_stage) {
-            cache_insert(XBZRLE.cache, current_addr,
-                         g_memdup(current_data, TARGET_PAGE_SIZE));
+            cache_insert(XBZRLE.cache, current_addr, current_data);
         }
         acct_info.xbzrle_cache_miss++;
         return -1;
diff --git a/include/migration/page_cache.h b/include/migration/page_cache.h
index 3839ac7..87894fe 100644
--- a/include/migration/page_cache.h
+++ b/include/migration/page_cache.h
@@ -57,7 +57,8 @@ bool cache_is_cached(const PageCache *cache, uint64_t addr);
 uint8_t *get_cached_data(const PageCache *cache, uint64_t addr);
 
 /**
- * cache_insert: insert the page into the cache. the previous value will be overwritten
+ * cache_insert: insert the page into the cache. the page cache
+ * will dup the data on insert. the previous value will be overwritten
  *
  * @cache pointer to the PageCache struct
  * @addr: page address
diff --git a/page_cache.c b/page_cache.c
index 809dadc..938a79c 100644
--- a/page_cache.c
+++ b/page_cache.c
@@ -159,7 +159,7 @@ void cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata)
         cache->num_items++;
     }
 
-    it->it_data = pdata;
+    it->it_data = g_memdup(pdata, cache->page_size);
     it->it_age = ++cache->max_item_age;
     it->it_addr = addr;
 }
commit 32a1c08b60a8ac0e63b54a5793a26b5e32b36618
Author: Peter Lieven <pl at dlhnet.de>
Date:   Mon Feb 25 19:12:03 2013 +0200

    page_cache: fix memory leak
    
    XBZRLE encoded migration introduced a MRU page cache
    meachnism. Unfortunately, cached items where never freed in
    case of a collision in the page cache on cache_insert().
    
    This lead to out of memory conditions during XBZRLE migration
    if the page cache was small and there where a lot of collisions
    in the cache.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/page_cache.c b/page_cache.c
index e5717d5..809dadc 100644
--- a/page_cache.c
+++ b/page_cache.c
@@ -152,6 +152,9 @@ void cache_insert(PageCache *cache, uint64_t addr, uint8_t *pdata)
     /* actual update of entry */
     it = cache_get_by_addr(cache, addr);
 
+    /* free old cached data if any */
+    g_free(it->it_data);
+
     if (!it->it_data) {
         cache->num_items++;
     }
commit a0ee2031dbf5f0183412d4b20a30cbfd404616a8
Author: Orit Wasserman <owasserm at redhat.com>
Date:   Mon Feb 25 19:12:02 2013 +0200

    Fix cache_resize to keep old entry age
    
    Instead of using cache_insert do the update itself
    
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/page_cache.c b/page_cache.c
index 748957b..e5717d5 100644
--- a/page_cache.c
+++ b/page_cache.c
@@ -192,18 +192,17 @@ int64_t cache_resize(PageCache *cache, int64_t new_num_pages)
         if (old_it->it_addr != -1) {
             /* check for collision, if there is, keep MRU page */
             new_it = cache_get_by_addr(new_cache, old_it->it_addr);
-            if (new_it->it_data) {
+            if (new_it->it_data && new_it->it_age >= old_it->it_age) {
                 /* keep the MRU page */
-                if (new_it->it_age >= old_it->it_age) {
-                    g_free(old_it->it_data);
-                } else {
-                    g_free(new_it->it_data);
-                    new_it->it_data = old_it->it_data;
-                    new_it->it_age = old_it->it_age;
-                    new_it->it_addr = old_it->it_addr;
-                }
+                g_free(old_it->it_data);
             } else {
-                cache_insert(new_cache, old_it->it_addr, old_it->it_data);
+                if (!new_it->it_data) {
+                    new_cache->num_items++;
+                }
+                g_free(new_it->it_data);
+                new_it->it_data = old_it->it_data;
+                new_it->it_age = old_it->it_age;
+                new_it->it_addr = old_it->it_addr;
             }
         }
     }
commit 0db65d624e0211a43c011579d6607a50d8f06082
Author: Orit Wasserman <owasserm at redhat.com>
Date:   Mon Feb 25 19:12:01 2013 +0200

    Fix page_cache leak in cache_resize
    
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/page_cache.c b/page_cache.c
index ba5640b..748957b 100644
--- a/page_cache.c
+++ b/page_cache.c
@@ -208,6 +208,7 @@ int64_t cache_resize(PageCache *cache, int64_t new_num_pages)
         }
     }
 
+    g_free(cache->page_cache);
     cache->page_cache = new_cache->page_cache;
     cache->max_num_items = new_cache->max_num_items;
     cache->num_items = new_cache->num_items;
commit 6f190a0641f5b06a462b62955c15c77b8fb3990c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:48 2013 +0100

    migration: inline migrate_fd_close
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 5d048ef..185d112 100644
--- a/migration.c
+++ b/migration.c
@@ -274,10 +274,10 @@ static void migrate_fd_cleanup(void *opaque)
         qemu_thread_join(&s->thread);
         qemu_mutex_lock_iothread();
 
-        migrate_fd_close(s);
+        qemu_fclose(s->file);
+        s->file = NULL;
     }
 
-    assert(s->file == NULL);
     assert(s->state != MIG_STATE_ACTIVE);
 
     if (s->state != MIG_STATE_COMPLETED) {
@@ -311,16 +311,6 @@ static void migrate_fd_cancel(MigrationState *s)
     migrate_finish_set_state(s, MIG_STATE_CANCELLED);
 }
 
-int migrate_fd_close(MigrationState *s)
-{
-    int rc = 0;
-    if (s->file != NULL) {
-        rc = qemu_fclose(s->file);
-        s->file = NULL;
-    }
-    return rc;
-}
-
 void add_migration_state_change_notifier(Notifier *notify)
 {
     notifier_list_add(&migration_state_notifiers, notify);
commit b352365f5abec075dede0222f1bc37674d64117c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:47 2013 +0100

    migration: eliminate s->migration_file
    
    The indirection is useless now.  Backends can open s->file directly.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/migration.h b/include/migration/migration.h
index ae94706..bb617fd 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -36,9 +36,7 @@ struct MigrationState
     size_t xfer_limit;
     QemuThread thread;
     QEMUBH *cleanup_bh;
-
     QEMUFile *file;
-    QEMUFile *migration_file;
 
     int state;
     MigrationParams params;
diff --git a/migration-exec.c b/migration-exec.c
index 1c539de..deab4e3 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -35,8 +35,8 @@
 
 void exec_start_outgoing_migration(MigrationState *s, const char *command, Error **errp)
 {
-    s->migration_file = qemu_popen_cmd(command, "w");
-    if (s->migration_file == NULL) {
+    s->file = qemu_popen_cmd(command, "w");
+    if (s->file == NULL) {
         error_setg_errno(errp, errno, "failed to popen the migration target");
         return;
     }
diff --git a/migration-fd.c b/migration-fd.c
index 07c758a..3d4613c 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -36,7 +36,7 @@ void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **
     if (fd == -1) {
         return;
     }
-    s->migration_file = qemu_fdopen(fd, "wb");
+    s->file = qemu_fdopen(fd, "wb");
 
     migrate_fd_connect(s);
 }
diff --git a/migration-tcp.c b/migration-tcp.c
index 5ea4f3d..b20ee58 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -35,11 +35,11 @@ static void tcp_wait_for_connect(int fd, void *opaque)
 
     if (fd < 0) {
         DPRINTF("migrate connect error\n");
-        s->migration_file = NULL;
+        s->file = NULL;
         migrate_fd_error(s);
     } else {
         DPRINTF("migrate connect success\n");
-        s->migration_file = qemu_fopen_socket(fd, "wb");
+        s->file = qemu_fopen_socket(fd, "wb");
         migrate_fd_connect(s);
     }
 }
diff --git a/migration-unix.c b/migration-unix.c
index 64bfa31..94b7022 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -35,11 +35,11 @@ static void unix_wait_for_connect(int fd, void *opaque)
 
     if (fd < 0) {
         DPRINTF("migrate connect error\n");
-        s->migration_file = NULL;
+        s->file = NULL;
         migrate_fd_error(s);
     } else {
         DPRINTF("migrate connect success\n");
-        s->migration_file = qemu_fopen_socket(fd, "wb");
+        s->file = qemu_fopen_socket(fd, "wb");
         migrate_fd_connect(s);
     }
 }
diff --git a/migration.c b/migration.c
index 64d8e46..5d048ef 100644
--- a/migration.c
+++ b/migration.c
@@ -270,9 +270,6 @@ static void migrate_fd_cleanup(void *opaque)
 
     if (s->file) {
         DPRINTF("closing file\n");
-        qemu_fclose(s->file);
-        s->file = NULL;
-
         qemu_mutex_unlock_iothread();
         qemu_thread_join(&s->thread);
         qemu_mutex_lock_iothread();
@@ -280,7 +277,7 @@ static void migrate_fd_cleanup(void *opaque)
         migrate_fd_close(s);
     }
 
-    assert(s->migration_file == NULL);
+    assert(s->file == NULL);
     assert(s->state != MIG_STATE_ACTIVE);
 
     if (s->state != MIG_STATE_COMPLETED) {
@@ -317,9 +314,9 @@ static void migrate_fd_cancel(MigrationState *s)
 int migrate_fd_close(MigrationState *s)
 {
     int rc = 0;
-    if (s->migration_file != NULL) {
-        rc = qemu_fclose(s->migration_file);
-        s->migration_file = NULL;
+    if (s->file != NULL) {
+        rc = qemu_fclose(s->file);
+        s->file = NULL;
     }
     return rc;
 }
@@ -506,39 +503,6 @@ int64_t migrate_xbzrle_cache_size(void)
 
 /* migration thread support */
 
-static int migration_put_buffer(void *opaque, const uint8_t *buf,
-                               int64_t pos, int size)
-{
-    MigrationState *s = opaque;
-    int ret;
-
-    DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos);
-
-    if (size <= 0) {
-        return size;
-    }
-
-    qemu_put_buffer(s->migration_file, buf, size);
-    ret = qemu_file_get_error(s->migration_file);
-    if (ret) {
-        return ret;
-    }
-
-    return size;
-}
-
-static int migration_close(void *opaque)
-{
-    return 0;
-}
-
-static int migration_get_fd(void *opaque)
-{
-    MigrationState *s = opaque;
-
-    return qemu_get_fd(s->migration_file);
-}
-
 static void *migration_thread(void *opaque)
 {
     MigrationState *s = opaque;
@@ -628,12 +592,6 @@ static void *migration_thread(void *opaque)
     return NULL;
 }
 
-static const QEMUFileOps migration_file_ops = {
-    .get_fd =         migration_get_fd,
-    .put_buffer =     migration_put_buffer,
-    .close =          migration_close,
-};
-
 void migrate_fd_connect(MigrationState *s)
 {
     s->state = MIG_STATE_ACTIVE;
@@ -642,7 +600,6 @@ void migrate_fd_connect(MigrationState *s)
     /* This is a best 1st approximation. ns to ms */
     s->expected_downtime = max_downtime/1000000;
     s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
-    s->file = qemu_fopen_ops(s, &migration_file_ops);
 
     qemu_file_set_rate_limit(s->file,
                              s->bandwidth_limit / XFER_LIMIT_RATIO);
commit 404a7c05bcc20c51fe1a9bf2deaeb4d6b658d3a3
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:46 2013 +0100

    migration: move contents of migration_close to migrate_fd_cleanup
    
    With this patch, the migration_file is not needed anymore.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 4b04d50..64d8e46 100644
--- a/migration.c
+++ b/migration.c
@@ -272,6 +272,12 @@ static void migrate_fd_cleanup(void *opaque)
         DPRINTF("closing file\n");
         qemu_fclose(s->file);
         s->file = NULL;
+
+        qemu_mutex_unlock_iothread();
+        qemu_thread_join(&s->thread);
+        qemu_mutex_lock_iothread();
+
+        migrate_fd_close(s);
     }
 
     assert(s->migration_file == NULL);
@@ -523,16 +529,7 @@ static int migration_put_buffer(void *opaque, const uint8_t *buf,
 
 static int migration_close(void *opaque)
 {
-    MigrationState *s = opaque;
-
-    DPRINTF("closing\n");
-
-    qemu_mutex_unlock_iothread();
-    qemu_thread_join(&s->thread);
-    qemu_mutex_lock_iothread();
-    assert(s->state != MIG_STATE_ACTIVE);
-
-    return migrate_fd_close(s);
+    return 0;
 }
 
 static int migration_get_fd(void *opaque)
commit 1964a397063967acc5ce71a2a24ed26e74824ee1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:45 2013 +0100

    migration: move rate limiting to QEMUFile
    
    Rate limiting is now simply a byte counter; client call
    qemu_file_rate_limit() manually to determine if they have to exit.
    So it is possible and simple to move the functionality to QEMUFile.
    
    This makes the remaining functionality of s->file redundant;
    in the next patch we can remove it and write directly to s->migration_file.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/docs/migration.txt b/docs/migration.txt
index f3ddd2f..0719a55 100644
--- a/docs/migration.txt
+++ b/docs/migration.txt
@@ -55,10 +55,7 @@ QEMUFile with:
 QEMUFile *qemu_fopen_ops(void *opaque,
                          QEMUFilePutBufferFunc *put_buffer,
                          QEMUFileGetBufferFunc *get_buffer,
-                         QEMUFileCloseFunc *close,
-                         QEMUFileRateLimit *rate_limit,
-                         QEMUFileSetRateLimit *set_rate_limit,
-                         QEMUFileGetRateLimit *get_rate_limit);
+                         QEMUFileCloseFunc *close);
 
 The functions have the following functionality:
 
@@ -80,24 +77,9 @@ Close a file and return an error code.
 
 typedef int (QEMUFileCloseFunc)(void *opaque);
 
-Called to determine if the file has exceeded its bandwidth allocation.  The
-bandwidth capping is a soft limit, not a hard limit.
-
-typedef int (QEMUFileRateLimit)(void *opaque);
-
-Called to change the current bandwidth allocation. This function must return
-the new actual bandwidth. It should be new_rate if everything goes OK, and
-the old rate otherwise.
-
-typedef size_t (QEMUFileSetRateLimit)(void *opaque, size_t new_rate);
-typedef size_t (QEMUFileGetRateLimit)(void *opaque);
-
 You can use any internal state that you need using the opaque void *
 pointer that is passed to all functions.
 
-The rate limiting functions are used to limit the bandwidth used by
-QEMU migration.
-
 The important functions for us are put_buffer()/get_buffer() that
 allow to write/read a buffer into the QEMUFile.
 
diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 25e8461..df81261 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -51,26 +51,11 @@ typedef int (QEMUFileCloseFunc)(void *opaque);
  */
 typedef int (QEMUFileGetFD)(void *opaque);
 
-/* Called to determine if the file has exceeded its bandwidth allocation.  The
- * bandwidth capping is a soft limit, not a hard limit.
- */
-typedef int (QEMUFileRateLimit)(void *opaque);
-
-/* Called to change the current bandwidth allocation. This function must return
- * the new actual bandwidth. It should be new_rate if everything goes ok, and
- * the old rate otherwise
- */
-typedef int64_t (QEMUFileSetRateLimit)(void *opaque, int64_t new_rate);
-typedef int64_t (QEMUFileGetRateLimit)(void *opaque);
-
 typedef struct QEMUFileOps {
     QEMUFilePutBufferFunc *put_buffer;
     QEMUFileGetBufferFunc *get_buffer;
     QEMUFileCloseFunc *close;
     QEMUFileGetFD *get_fd;
-    QEMUFileRateLimit *rate_limit;
-    QEMUFileSetRateLimit *set_rate_limit;
-    QEMUFileGetRateLimit *get_rate_limit;
 } QEMUFileOps;
 
 QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops);
@@ -109,7 +94,8 @@ unsigned int qemu_get_be32(QEMUFile *f);
 uint64_t qemu_get_be64(QEMUFile *f);
 
 int qemu_file_rate_limit(QEMUFile *f);
-int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate);
+void qemu_file_reset_rate_limit(QEMUFile *f);
+void qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate);
 int64_t qemu_file_get_rate_limit(QEMUFile *f);
 int qemu_file_get_error(QEMUFile *f);
 
diff --git a/migration.c b/migration.c
index 1f58d77..4b04d50 100644
--- a/migration.c
+++ b/migration.c
@@ -518,7 +518,6 @@ static int migration_put_buffer(void *opaque, const uint8_t *buf,
         return ret;
     }
 
-    s->bytes_xfer += size;
     return size;
 }
 
@@ -543,49 +542,6 @@ static int migration_get_fd(void *opaque)
     return qemu_get_fd(s->migration_file);
 }
 
-/*
- * The meaning of the return values is:
- *   0: We can continue sending
- *   1: Time to stop
- *   negative: There has been an error
- */
-static int migration_rate_limit(void *opaque)
-{
-    MigrationState *s = opaque;
-    int ret;
-
-    ret = qemu_file_get_error(s->file);
-    if (ret) {
-        return ret;
-    }
-
-    if (s->bytes_xfer >= s->xfer_limit) {
-        return 1;
-    }
-
-    return 0;
-}
-
-static int64_t migration_set_rate_limit(void *opaque, int64_t new_rate)
-{
-    MigrationState *s = opaque;
-    if (qemu_file_get_error(s->file)) {
-        goto out;
-    }
-
-    s->xfer_limit = new_rate;
-
-out:
-    return s->xfer_limit;
-}
-
-static int64_t migration_get_rate_limit(void *opaque)
-{
-    MigrationState *s = opaque;
-
-    return s->xfer_limit;
-}
-
 static void *migration_thread(void *opaque)
 {
     MigrationState *s = opaque;
@@ -646,7 +602,7 @@ static void *migration_thread(void *opaque)
                 s->expected_downtime = s->dirty_bytes_rate / bandwidth;
             }
 
-            s->bytes_xfer = 0;
+            qemu_file_reset_rate_limit(s->file);
             sleep_time = 0;
             initial_time = current_time;
             initial_bytes = qemu_ftell(s->file);
@@ -679,9 +635,6 @@ static const QEMUFileOps migration_file_ops = {
     .get_fd =         migration_get_fd,
     .put_buffer =     migration_put_buffer,
     .close =          migration_close,
-    .rate_limit =     migration_rate_limit,
-    .get_rate_limit = migration_get_rate_limit,
-    .set_rate_limit = migration_set_rate_limit,
 };
 
 void migrate_fd_connect(MigrationState *s)
@@ -689,10 +642,8 @@ void migrate_fd_connect(MigrationState *s)
     s->state = MIG_STATE_ACTIVE;
     trace_migrate_set_state(MIG_STATE_ACTIVE);
 
-    s->bytes_xfer = 0;
     /* This is a best 1st approximation. ns to ms */
     s->expected_downtime = max_downtime/1000000;
-
     s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
     s->file = qemu_fopen_ops(s, &migration_file_ops);
 
diff --git a/savevm.c b/savevm.c
index 1414f08..147e2d2 100644
--- a/savevm.c
+++ b/savevm.c
@@ -119,6 +119,9 @@ struct QEMUFile {
     void *opaque;
     int is_write;
 
+    int64_t bytes_xfer;
+    int64_t xfer_limit;
+
     int64_t pos; /* start of buffer when writing, end of buffer
                     when reading */
     int buf_index;
@@ -479,7 +482,6 @@ QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops)
     f->opaque = opaque;
     f->ops = ops;
     f->is_write = 0;
-
     return f;
 }
 
@@ -605,6 +607,7 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
         memcpy(f->buf + f->buf_index, buf, l);
         f->is_write = 1;
         f->buf_index += l;
+        f->bytes_xfer += l;
         buf += l;
         size -= l;
         if (f->buf_index >= IO_BUF_SIZE) {
@@ -725,28 +728,28 @@ int64_t qemu_ftell(QEMUFile *f)
 
 int qemu_file_rate_limit(QEMUFile *f)
 {
-    if (f->ops->rate_limit)
-        return f->ops->rate_limit(f->opaque);
-
+    if (qemu_file_get_error(f)) {
+        return 1;
+    }
+    if (f->xfer_limit > 0 && f->bytes_xfer > f->xfer_limit) {
+        return 1;
+    }
     return 0;
 }
 
 int64_t qemu_file_get_rate_limit(QEMUFile *f)
 {
-    if (f->ops->get_rate_limit)
-        return f->ops->get_rate_limit(f->opaque);
-
-    return 0;
+    return f->xfer_limit;
 }
 
-int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate)
+void qemu_file_set_rate_limit(QEMUFile *f, int64_t limit)
 {
-    /* any failed or completed migration keeps its state to allow probing of
-     * migration data, but has no associated file anymore */
-    if (f && f->ops->set_rate_limit)
-        return f->ops->set_rate_limit(f->opaque, new_rate);
+    f->xfer_limit = limit;
+}
 
-    return 0;
+void qemu_file_reset_rate_limit(QEMUFile *f)
+{
+    f->bytes_xfer = 0;
 }
 
 void qemu_put_be16(QEMUFile *f, unsigned int v)
commit 442773cef15092b5927851237850760345d2cf16
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:44 2013 +0100

    migration: small changes around rate-limiting
    
    This patch extracts a few small changes from the next patch, which
    are unrelated to adding generic rate-limiting functionality to
    QEMUFile.  Make migration_set_rate_limit a simple accessor, and
    use qemu_file_set_rate_limit consistently.  Also fix a typo where
    INT_MAX should have been SIZE_MAX.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 6da1746..1f58d77 100644
--- a/migration.c
+++ b/migration.c
@@ -462,10 +462,15 @@ void qmp_migrate_set_speed(int64_t value, Error **errp)
     if (value < 0) {
         value = 0;
     }
+    if (value > SIZE_MAX) {
+        value = SIZE_MAX;
+    }
 
     s = migrate_get_current();
     s->bandwidth_limit = value;
-    qemu_file_set_rate_limit(s->file, s->bandwidth_limit);
+    if (s->file) {
+        qemu_file_set_rate_limit(s->file, s->bandwidth_limit / XFER_LIMIT_RATIO);
+    }
 }
 
 void qmp_migrate_set_downtime(double value, Error **errp)
@@ -567,11 +572,8 @@ static int64_t migration_set_rate_limit(void *opaque, int64_t new_rate)
     if (qemu_file_get_error(s->file)) {
         goto out;
     }
-    if (new_rate > SIZE_MAX) {
-        new_rate = SIZE_MAX;
-    }
 
-    s->xfer_limit = new_rate / XFER_LIMIT_RATIO;
+    s->xfer_limit = new_rate;
 
 out:
     return s->xfer_limit;
@@ -614,7 +616,7 @@ static void *migration_thread(void *opaque)
                 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
                 old_vm_running = runstate_is_running();
                 vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
-                s->xfer_limit = INT_MAX;
+                qemu_file_set_rate_limit(s->file, INT_MAX);
                 qemu_savevm_state_complete(s->file);
                 qemu_mutex_unlock_iothread();
                 if (!qemu_file_get_error(s->file)) {
@@ -691,11 +693,12 @@ void migrate_fd_connect(MigrationState *s)
     /* This is a best 1st approximation. ns to ms */
     s->expected_downtime = max_downtime/1000000;
 
-    s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
-
     s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
     s->file = qemu_fopen_ops(s, &migration_file_ops);
 
+    qemu_file_set_rate_limit(s->file,
+                             s->bandwidth_limit / XFER_LIMIT_RATIO);
+
     qemu_thread_create(&s->thread, migration_thread, s,
                        QEMU_THREAD_JOINABLE);
     notifier_list_notify(&migration_state_notifiers, s);
commit be7172e22a9c3bc448894e57f6c2d1af6ffd47fd
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:43 2013 +0100

    migration: use qemu_ftell to compute bandwidth
    
    Prepare for when s->bytes_xfer will be removed.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 681a459..6da1746 100644
--- a/migration.c
+++ b/migration.c
@@ -589,6 +589,7 @@ static void *migration_thread(void *opaque)
     MigrationState *s = opaque;
     int64_t initial_time = qemu_get_clock_ms(rt_clock);
     int64_t sleep_time = 0;
+    int64_t initial_bytes = 0;
     int64_t max_size = 0;
     int64_t start_time = initial_time;
     bool old_vm_running = false;
@@ -629,7 +630,7 @@ static void *migration_thread(void *opaque)
         }
         current_time = qemu_get_clock_ms(rt_clock);
         if (current_time >= initial_time + BUFFER_DELAY) {
-            uint64_t transferred_bytes = s->bytes_xfer;
+            uint64_t transferred_bytes = qemu_ftell(s->file) - initial_bytes;
             uint64_t time_spent = current_time - initial_time - sleep_time;
             double bandwidth = transferred_bytes / time_spent;
             max_size = bandwidth * migrate_max_downtime() / 1000000;
@@ -646,6 +647,7 @@ static void *migration_thread(void *opaque)
             s->bytes_xfer = 0;
             sleep_time = 0;
             initial_time = current_time;
+            initial_bytes = qemu_ftell(s->file);
         }
         if (qemu_file_rate_limit(s->file)) {
             /* usleep expects microseconds */
commit e6a1cf21328802f3a83e84e893b8cb8a468141cc
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:42 2013 +0100

    migration: use QEMUFile for writing outgoing migration data
    
    Second, drop the file descriptor indirection, and write directly to the
    QEMUFile.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/migration.h b/include/migration/migration.h
index 1f8f305..ae94706 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -40,10 +40,6 @@ struct MigrationState
     QEMUFile *file;
     QEMUFile *migration_file;
 
-    int fd;
-    int (*get_error)(MigrationState *s);
-    int (*write)(MigrationState *s, const void *buff, size_t size);
-
     int state;
     MigrationParams params;
     int64_t total_time;
diff --git a/migration-exec.c b/migration-exec.c
index 8c3f720..1c539de 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -33,16 +33,6 @@
     do { } while (0)
 #endif
 
-static int file_errno(MigrationState *s)
-{
-    return errno;
-}
-
-static int file_write(MigrationState *s, const void * buf, size_t size)
-{
-    return write(s->fd, buf, size);
-}
-
 void exec_start_outgoing_migration(MigrationState *s, const char *command, Error **errp)
 {
     s->migration_file = qemu_popen_cmd(command, "w");
@@ -51,8 +41,6 @@ void exec_start_outgoing_migration(MigrationState *s, const char *command, Error
         return;
     }
 
-    s->get_error = file_errno;
-    s->write = file_write;
     migrate_fd_connect(s);
 }
 
diff --git a/migration-fd.c b/migration-fd.c
index 4636457..07c758a 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -30,16 +30,6 @@
     do { } while (0)
 #endif
 
-static int fd_errno(MigrationState *s)
-{
-    return errno;
-}
-
-static int fd_write(MigrationState *s, const void * buf, size_t size)
-{
-    return write(s->fd, buf, size);
-}
-
 void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp)
 {
     int fd = monitor_get_fd(cur_mon, fdname, errp);
@@ -48,8 +38,6 @@ void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **
     }
     s->migration_file = qemu_fdopen(fd, "wb");
 
-    s->get_error = fd_errno;
-    s->write = fd_write;
     migrate_fd_connect(s);
 }
 
diff --git a/migration-tcp.c b/migration-tcp.c
index 1e8e004..5ea4f3d 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -29,16 +29,6 @@
     do { } while (0)
 #endif
 
-static int socket_errno(MigrationState *s)
-{
-    return socket_error();
-}
-
-static int socket_write(MigrationState *s, const void * buf, size_t size)
-{
-    return send(s->fd, buf, size, 0);
-}
-
 static void tcp_wait_for_connect(int fd, void *opaque)
 {
     MigrationState *s = opaque;
@@ -56,8 +46,6 @@ static void tcp_wait_for_connect(int fd, void *opaque)
 
 void tcp_start_outgoing_migration(MigrationState *s, const char *host_port, Error **errp)
 {
-    s->get_error = socket_errno;
-    s->write = socket_write;
     inet_nonblocking_connect(host_port, tcp_wait_for_connect, s, errp);
 }
 
diff --git a/migration-unix.c b/migration-unix.c
index 11917f4..64bfa31 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -29,16 +29,6 @@
     do { } while (0)
 #endif
 
-static int unix_errno(MigrationState *s)
-{
-    return errno;
-}
-
-static int unix_write(MigrationState *s, const void * buf, size_t size)
-{
-    return write(s->fd, buf, size);
-}
-
 static void unix_wait_for_connect(int fd, void *opaque)
 {
     MigrationState *s = opaque;
@@ -56,8 +46,6 @@ static void unix_wait_for_connect(int fd, void *opaque)
 
 void unix_start_outgoing_migration(MigrationState *s, const char *path, Error **errp)
 {
-    s->get_error = unix_errno;
-    s->write = unix_write;
     unix_nonblocking_connect(path, unix_wait_for_connect, s, errp);
 }
 
diff --git a/migration.c b/migration.c
index 52126d8..681a459 100644
--- a/migration.c
+++ b/migration.c
@@ -301,25 +301,6 @@ void migrate_fd_error(MigrationState *s)
     notifier_list_notify(&migration_state_notifiers, s);
 }
 
-static ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
-                                     size_t size)
-{
-    ssize_t ret;
-
-    if (s->state != MIG_STATE_ACTIVE) {
-        return -EIO;
-    }
-
-    do {
-        ret = s->write(s, data, size);
-    } while (ret == -1 && ((s->get_error(s)) == EINTR));
-
-    if (ret == -1)
-        ret = -(s->get_error(s));
-
-    return ret;
-}
-
 static void migrate_fd_cancel(MigrationState *s)
 {
     DPRINTF("cancelling migration\n");
@@ -333,7 +314,6 @@ int migrate_fd_close(MigrationState *s)
     if (s->migration_file != NULL) {
         rc = qemu_fclose(s->migration_file);
         s->migration_file = NULL;
-        s->fd = -1;
     }
     return rc;
 }
@@ -519,8 +499,7 @@ static int migration_put_buffer(void *opaque, const uint8_t *buf,
                                int64_t pos, int size)
 {
     MigrationState *s = opaque;
-    ssize_t ret;
-    size_t sent;
+    int ret;
 
     DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos);
 
@@ -528,22 +507,14 @@ static int migration_put_buffer(void *opaque, const uint8_t *buf,
         return size;
     }
 
-    sent = 0;
-    while (size) {
-        ret = migrate_fd_put_buffer(s, buf, size);
-        if (ret <= 0) {
-            DPRINTF("error flushing data, %zd\n", ret);
-            return ret;
-        } else {
-            DPRINTF("flushed %zd byte(s)\n", ret);
-            sent += ret;
-            buf += ret;
-            size -= ret;
-            s->bytes_xfer += ret;
-        }
+    qemu_put_buffer(s->migration_file, buf, size);
+    ret = qemu_file_get_error(s->migration_file);
+    if (ret) {
+        return ret;
     }
 
-    return sent;
+    s->bytes_xfer += size;
+    return size;
 }
 
 static int migration_close(void *opaque)
@@ -564,7 +535,7 @@ static int migration_get_fd(void *opaque)
 {
     MigrationState *s = opaque;
 
-    return s->fd;
+    return qemu_get_fd(s->migration_file);
 }
 
 /*
@@ -721,7 +692,6 @@ void migrate_fd_connect(MigrationState *s)
     s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
 
     s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
-    s->fd = qemu_get_fd(s->migration_file);
     s->file = qemu_fopen_ops(s, &migration_file_ops);
 
     qemu_thread_create(&s->thread, migration_thread, s,
commit f8bbc1286337a8506162b5785babe6f2a7de2476
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:41 2013 +0100

    migration: use QEMUFile for migration channel lifetime
    
    As a start, use QEMUFile to store the destination and close it.
    qemu_get_fd gets a file descriptor that will be used by the write
    callbacks.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/migration.h b/include/migration/migration.h
index cec8643..1f8f305 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -38,12 +38,13 @@ struct MigrationState
     QEMUBH *cleanup_bh;
 
     QEMUFile *file;
+    QEMUFile *migration_file;
+
     int fd;
-    int state;
     int (*get_error)(MigrationState *s);
-    int (*close)(MigrationState *s);
     int (*write)(MigrationState *s, const void *buff, size_t size);
-    void *opaque;
+
+    int state;
     MigrationParams params;
     int64_t total_time;
     int64_t downtime;
diff --git a/migration-exec.c b/migration-exec.c
index a2b5f8d..8c3f720 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -43,33 +43,16 @@ static int file_write(MigrationState *s, const void * buf, size_t size)
     return write(s->fd, buf, size);
 }
 
-static int exec_close(MigrationState *s)
-{
-    int ret = 0;
-    DPRINTF("exec_close\n");
-    ret = qemu_fclose(s->opaque);
-    s->opaque = NULL;
-    s->fd = -1;
-    return ret;
-}
-
 void exec_start_outgoing_migration(MigrationState *s, const char *command, Error **errp)
 {
-    QEMUFile *f;
-    f = qemu_popen_cmd(command, "w");
-    if (f == NULL) {
+    s->migration_file = qemu_popen_cmd(command, "w");
+    if (s->migration_file == NULL) {
         error_setg_errno(errp, errno, "failed to popen the migration target");
         return;
     }
 
-    s->opaque = f;
-    s->fd = qemu_get_fd(f);
-    assert(s->fd != -1);
-
-    s->close = exec_close;
     s->get_error = file_errno;
     s->write = file_write;
-
     migrate_fd_connect(s);
 }
 
diff --git a/migration-fd.c b/migration-fd.c
index a99e0e3..4636457 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -40,45 +40,16 @@ static int fd_write(MigrationState *s, const void * buf, size_t size)
     return write(s->fd, buf, size);
 }
 
-static int fd_close(MigrationState *s)
-{
-    struct stat st;
-    int ret;
-
-    DPRINTF("fd_close\n");
-    ret = fstat(s->fd, &st);
-    if (ret == 0 && S_ISREG(st.st_mode)) {
-        /*
-         * If the file handle is a regular file make sure the
-         * data is flushed to disk before signaling success.
-         */
-        ret = fsync(s->fd);
-        if (ret != 0) {
-            ret = -errno;
-            perror("migration-fd: fsync");
-            return ret;
-        }
-    }
-    ret = close(s->fd);
-    s->fd = -1;
-    if (ret != 0) {
-        ret = -errno;
-        perror("migration-fd: close");
-    }
-    return ret;
-}
-
 void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp)
 {
-    s->fd = monitor_get_fd(cur_mon, fdname, errp);
-    if (s->fd == -1) {
+    int fd = monitor_get_fd(cur_mon, fdname, errp);
+    if (fd == -1) {
         return;
     }
+    s->migration_file = qemu_fdopen(fd, "wb");
 
     s->get_error = fd_errno;
     s->write = fd_write;
-    s->close = fd_close;
-
     migrate_fd_connect(s);
 }
 
diff --git a/migration-tcp.c b/migration-tcp.c
index 7d975b5..1e8e004 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -39,28 +39,17 @@ static int socket_write(MigrationState *s, const void * buf, size_t size)
     return send(s->fd, buf, size, 0);
 }
 
-static int tcp_close(MigrationState *s)
-{
-    int r = 0;
-    DPRINTF("tcp_close\n");
-    if (closesocket(s->fd) < 0) {
-        r = -socket_error();
-    }
-    return r;
-}
-
 static void tcp_wait_for_connect(int fd, void *opaque)
 {
     MigrationState *s = opaque;
 
     if (fd < 0) {
         DPRINTF("migrate connect error\n");
-        s->fd = -1;
+        s->migration_file = NULL;
         migrate_fd_error(s);
     } else {
         DPRINTF("migrate connect success\n");
-        s->fd = fd;
-        socket_set_block(s->fd);
+        s->migration_file = qemu_fopen_socket(fd, "wb");
         migrate_fd_connect(s);
     }
 }
@@ -69,9 +58,7 @@ void tcp_start_outgoing_migration(MigrationState *s, const char *host_port, Erro
 {
     s->get_error = socket_errno;
     s->write = socket_write;
-    s->close = tcp_close;
-
-    s->fd = inet_nonblocking_connect(host_port, tcp_wait_for_connect, s, errp);
+    inet_nonblocking_connect(host_port, tcp_wait_for_connect, s, errp);
 }
 
 static void tcp_accept_incoming_migration(void *opaque)
diff --git a/migration-unix.c b/migration-unix.c
index 4693b43..11917f4 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -39,28 +39,17 @@ static int unix_write(MigrationState *s, const void * buf, size_t size)
     return write(s->fd, buf, size);
 }
 
-static int unix_close(MigrationState *s)
-{
-    int r = 0;
-    DPRINTF("unix_close\n");
-    if (close(s->fd) < 0) {
-        r = -errno;
-    }
-    return r;
-}
-
 static void unix_wait_for_connect(int fd, void *opaque)
 {
     MigrationState *s = opaque;
 
     if (fd < 0) {
         DPRINTF("migrate connect error\n");
-        s->fd = -1;
+        s->migration_file = NULL;
         migrate_fd_error(s);
     } else {
         DPRINTF("migrate connect success\n");
-        s->fd = fd;
-        socket_set_block(s->fd);
+        s->migration_file = qemu_fopen_socket(fd, "wb");
         migrate_fd_connect(s);
     }
 }
@@ -69,9 +58,7 @@ void unix_start_outgoing_migration(MigrationState *s, const char *path, Error **
 {
     s->get_error = unix_errno;
     s->write = unix_write;
-    s->close = unix_close;
-
-    s->fd = unix_nonblocking_connect(path, unix_wait_for_connect, s, errp);
+    unix_nonblocking_connect(path, unix_wait_for_connect, s, errp);
 }
 
 static void unix_accept_incoming_migration(void *opaque)
diff --git a/migration.c b/migration.c
index f35728d..52126d8 100644
--- a/migration.c
+++ b/migration.c
@@ -274,7 +274,7 @@ static void migrate_fd_cleanup(void *opaque)
         s->file = NULL;
     }
 
-    assert(s->fd == -1);
+    assert(s->migration_file == NULL);
     assert(s->state != MIG_STATE_ACTIVE);
 
     if (s->state != MIG_STATE_COMPLETED) {
@@ -330,8 +330,9 @@ static void migrate_fd_cancel(MigrationState *s)
 int migrate_fd_close(MigrationState *s)
 {
     int rc = 0;
-    if (s->fd != -1) {
-        rc = s->close(s);
+    if (s->migration_file != NULL) {
+        rc = qemu_fclose(s->migration_file);
+        s->migration_file = NULL;
         s->fd = -1;
     }
     return rc;
@@ -720,6 +721,7 @@ void migrate_fd_connect(MigrationState *s)
     s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
 
     s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
+    s->fd = qemu_get_fd(s->migration_file);
     s->file = qemu_fopen_ops(s, &migration_file_ops);
 
     qemu_thread_create(&s->thread, migration_thread, s,
diff --git a/savevm.c b/savevm.c
index c60ace3..1414f08 100644
--- a/savevm.c
+++ b/savevm.c
@@ -400,6 +400,7 @@ QEMUFile *qemu_fopen_socket(int fd, const char *mode)
 
     s->fd = fd;
     if (mode[0] == 'w') {
+        socket_set_block(s->fd);
         s->file = qemu_fopen_ops(s, &socket_write_ops);
     } else {
         s->file = qemu_fopen_ops(s, &socket_read_ops);
commit 3f2d38faab97f4d676c41868a8243997b2aab7cb
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:40 2013 +0100

    qemu-file: simplify and export qemu_ftell
    
    Force a flush when qemu_ftell is called.  This simplifies the buffer magic
    (it also breaks qemu_ftell for input QEMUFiles, but we never use it).
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index 76c88c7..c60ace3 100644
--- a/savevm.c
+++ b/savevm.c
@@ -119,8 +119,8 @@ struct QEMUFile {
     void *opaque;
     int is_write;
 
-    int64_t buf_offset; /* start of buffer when writing, end of buffer
-                           when reading */
+    int64_t pos; /* start of buffer when writing, end of buffer
+                    when reading */
     int buf_index;
     int buf_size; /* 0 when writing */
     uint8_t buf[IO_BUF_SIZE];
@@ -505,9 +505,9 @@ static void qemu_fflush(QEMUFile *f)
         return;
     }
     if (f->is_write && f->buf_index > 0) {
-        ret = f->ops->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index);
+        ret = f->ops->put_buffer(f->opaque, f->buf, f->pos, f->buf_index);
         if (ret >= 0) {
-            f->buf_offset += f->buf_index;
+            f->pos += f->buf_index;
         }
         f->buf_index = 0;
     }
@@ -534,11 +534,11 @@ static void qemu_fill_buffer(QEMUFile *f)
     f->buf_index = 0;
     f->buf_size = pending;
 
-    len = f->ops->get_buffer(f->opaque, f->buf + pending, f->buf_offset,
+    len = f->ops->get_buffer(f->opaque, f->buf + pending, f->pos,
                         IO_BUF_SIZE - pending);
     if (len > 0) {
         f->buf_size += len;
-        f->buf_offset += len;
+        f->pos += len;
     } else if (len == 0) {
         qemu_file_set_error(f, -EIO);
     } else if (len != -EAGAIN)
@@ -718,12 +718,8 @@ int qemu_get_byte(QEMUFile *f)
 
 int64_t qemu_ftell(QEMUFile *f)
 {
-    /* buf_offset excludes buffer for writing but includes it for reading */
-    if (f->is_write) {
-        return f->buf_offset + f->buf_index;
-    } else {
-        return f->buf_offset - f->buf_size + f->buf_index;
-    }
+    qemu_fflush(f);
+    return f->pos;
 }
 
 int qemu_file_rate_limit(QEMUFile *f)
commit 0cc3f3ccc9d29acc94b995430518bda1c7c01bef
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:39 2013 +0100

    qemu-file: add writable socket QEMUFile
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 987e719..25e8461 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -76,7 +76,7 @@ typedef struct QEMUFileOps {
 QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops);
 QEMUFile *qemu_fopen(const char *filename, const char *mode);
 QEMUFile *qemu_fdopen(int fd, const char *mode);
-QEMUFile *qemu_fopen_socket(int fd);
+QEMUFile *qemu_fopen_socket(int fd, const char *mode);
 QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
 int qemu_get_fd(QEMUFile *f);
 int qemu_fclose(QEMUFile *f);
diff --git a/migration-tcp.c b/migration-tcp.c
index e78a296..7d975b5 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -95,7 +95,7 @@ static void tcp_accept_incoming_migration(void *opaque)
         goto out;
     }
 
-    f = qemu_fopen_socket(c);
+    f = qemu_fopen_socket(c, "rb");
     if (f == NULL) {
         fprintf(stderr, "could not qemu_fopen socket\n");
         goto out;
diff --git a/migration-unix.c b/migration-unix.c
index 218835a..4693b43 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -95,7 +95,7 @@ static void unix_accept_incoming_migration(void *opaque)
         goto out;
     }
 
-    f = qemu_fopen_socket(c);
+    f = qemu_fopen_socket(c, "rb");
     if (f == NULL) {
         fprintf(stderr, "could not qemu_fopen socket\n");
         goto out;
diff --git a/savevm.c b/savevm.c
index 6d6f1f1..76c88c7 100644
--- a/savevm.c
+++ b/savevm.c
@@ -198,6 +198,18 @@ static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
     return len;
 }
 
+static int socket_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
+{
+    QEMUFileSocket *s = opaque;
+    ssize_t len;
+
+    len = qemu_send_full(s->fd, buf, size, 0);
+    if (len < size) {
+        len = -socket_error();
+    }
+    return len;
+}
+
 static int socket_close(void *opaque)
 {
     QEMUFileSocket *s = opaque;
@@ -369,12 +381,29 @@ static const QEMUFileOps socket_read_ops = {
     .close =      socket_close
 };
 
-QEMUFile *qemu_fopen_socket(int fd)
+static const QEMUFileOps socket_write_ops = {
+    .get_fd =     socket_get_fd,
+    .put_buffer = socket_put_buffer,
+    .close =      socket_close
+};
+
+QEMUFile *qemu_fopen_socket(int fd, const char *mode)
 {
     QEMUFileSocket *s = g_malloc0(sizeof(QEMUFileSocket));
 
+    if (mode == NULL ||
+        (mode[0] != 'r' && mode[0] != 'w') ||
+        mode[1] != 'b' || mode[2] != 0) {
+        fprintf(stderr, "qemu_fopen: Argument validity check failed\n");
+        return NULL;
+    }
+
     s->fd = fd;
-    s->file = qemu_fopen_ops(s, &socket_read_ops);
+    if (mode[0] == 'w') {
+        s->file = qemu_fopen_ops(s, &socket_write_ops);
+    } else {
+        s->file = qemu_fopen_ops(s, &socket_read_ops);
+    }
     return s->file;
 }
 
commit 13c7b2da073ec83cb47f9582149c8d28bb038e73
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:38 2013 +0100

    qemu-file: check exit status when closing a pipe QEMUFile
    
    This is what exec_close does.  Move this to the underlying QEMUFile.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index 87d3b9c..df24400 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -9,6 +9,13 @@
 #include <sys/signal.h>
 #endif
 
+#ifndef _WIN32
+#include <sys/wait.h>
+#else
+#define WIFEXITED(x)   1
+#define WEXITSTATUS(x) (x)
+#endif
+
 #include <sys/time.h>
 
 #if defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10
diff --git a/migration-exec.c b/migration-exec.c
index 5dc7313..a2b5f8d 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -50,10 +50,6 @@ static int exec_close(MigrationState *s)
     ret = qemu_fclose(s->opaque);
     s->opaque = NULL;
     s->fd = -1;
-    if (ret >= 0 && !(WIFEXITED(ret) && WEXITSTATUS(ret) == 0)) {
-        /* close succeeded, but non-zero exit code: */
-        ret = -EIO; /* fake errno value */
-    }
     return ret;
 }
 
diff --git a/savevm.c b/savevm.c
index 1d49fde..6d6f1f1 100644
--- a/savevm.c
+++ b/savevm.c
@@ -247,6 +247,9 @@ static int stdio_pclose(void *opaque)
     ret = pclose(s->stdio_file);
     if (ret == -1) {
         ret = -errno;
+    } else if (!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) {
+        /* close succeeded, but non-zero exit code: */
+        ret = -EIO; /* fake errno value */
     }
     g_free(s);
     return ret;
commit ce39ee3184a02eca7f9529cc19b1582f6f704c70
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:37 2013 +0100

    qemu-file: fsync a writable stdio QEMUFile
    
    This is what fd_close does.  Prepare for switching to a QEMUFile.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index 38699de..1d49fde 100644
--- a/savevm.c
+++ b/savevm.c
@@ -256,6 +256,24 @@ static int stdio_fclose(void *opaque)
 {
     QEMUFileStdio *s = opaque;
     int ret = 0;
+
+    if (s->file->ops->put_buffer) {
+        int fd = fileno(s->stdio_file);
+        struct stat st;
+
+        ret = fstat(fd, &st);
+        if (ret == 0 && S_ISREG(st.st_mode)) {
+            /*
+             * If the file handle is a regular file make sure the
+             * data is flushed to disk before signaling success.
+             */
+            ret = fsync(fd);
+            if (ret != 0) {
+                ret = -errno;
+                return ret;
+            }
+        }
+    }
     if (fclose(s->stdio_file) == EOF) {
         ret = -errno;
     }
commit 817b9ed5eb300dbb434d752da416441028539a96
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:36 2013 +0100

    migration: merge qemu_popen_cmd with qemu_popen
    
    There is no reason for outgoing exec migration to do popen manually
    anymore (the reason used to be that we needed the FILE* to make it
    non-blocking).  Use qemu_popen_cmd.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 46fc11d..987e719 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -77,7 +77,6 @@ QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops);
 QEMUFile *qemu_fopen(const char *filename, const char *mode);
 QEMUFile *qemu_fdopen(int fd, const char *mode);
 QEMUFile *qemu_fopen_socket(int fd);
-QEMUFile *qemu_popen(FILE *popen_file, const char *mode);
 QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
 int qemu_get_fd(QEMUFile *f);
 int qemu_fclose(QEMUFile *f);
diff --git a/migration-exec.c b/migration-exec.c
index a051a6e..5dc7313 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -59,19 +59,17 @@ static int exec_close(MigrationState *s)
 
 void exec_start_outgoing_migration(MigrationState *s, const char *command, Error **errp)
 {
-    FILE *f;
-
-    f = popen(command, "w");
+    QEMUFile *f;
+    f = qemu_popen_cmd(command, "w");
     if (f == NULL) {
         error_setg_errno(errp, errno, "failed to popen the migration target");
         return;
     }
 
-    s->fd = fileno(f);
+    s->opaque = f;
+    s->fd = qemu_get_fd(f);
     assert(s->fd != -1);
 
-    s->opaque = qemu_popen(f, "w");
-
     s->close = exec_close;
     s->get_error = file_errno;
     s->write = file_write;
diff --git a/savevm.c b/savevm.c
index fef2ab9..38699de 100644
--- a/savevm.c
+++ b/savevm.c
@@ -275,11 +275,17 @@ static const QEMUFileOps stdio_pipe_write_ops = {
     .close =      stdio_pclose
 };
 
-QEMUFile *qemu_popen(FILE *stdio_file, const char *mode)
+QEMUFile *qemu_popen_cmd(const char *command, const char *mode)
 {
+    FILE *stdio_file;
     QEMUFileStdio *s;
 
-    if (stdio_file == NULL || mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
+    stdio_file = popen(command, mode);
+    if (stdio_file == NULL) {
+        return NULL;
+    }
+
+    if (mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
         fprintf(stderr, "qemu_popen: Argument validity check failed\n");
         return NULL;
     }
@@ -296,18 +302,6 @@ QEMUFile *qemu_popen(FILE *stdio_file, const char *mode)
     return s->file;
 }
 
-QEMUFile *qemu_popen_cmd(const char *command, const char *mode)
-{
-    FILE *popen_file;
-
-    popen_file = popen(command, mode);
-    if(popen_file == NULL) {
-        return NULL;
-    }
-
-    return qemu_popen(popen_file, mode);
-}
-
 static const QEMUFileOps stdio_file_read_ops = {
     .get_fd =     stdio_get_fd,
     .get_buffer = stdio_get_buffer,
commit a0ff044b8ea81908cd8fe5819ce33780f53f58ee
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:35 2013 +0100

    migration: use qemu_file_rate_limit consistently
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 5d99999..f35728d 100644
--- a/migration.c
+++ b/migration.c
@@ -628,7 +628,7 @@ static void *migration_thread(void *opaque)
         int64_t current_time;
         uint64_t pending_size;
 
-        if (s->bytes_xfer < s->xfer_limit) {
+        if (!qemu_file_rate_limit(s->file)) {
             DPRINTF("iterate\n");
             pending_size = qemu_savevm_state_pending(s->file, max_size);
             DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
@@ -675,7 +675,7 @@ static void *migration_thread(void *opaque)
             sleep_time = 0;
             initial_time = current_time;
         }
-        if (s->bytes_xfer >= s->xfer_limit) {
+        if (qemu_file_rate_limit(s->file)) {
             /* usleep expects microseconds */
             g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
             sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
commit db2f25309af1af0f27e0ddec4acc3b66837fa668
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:34 2013 +0100

    migration: remove useless qemu_file_get_error check
    
    migration_put_buffer is never called if there has been an error.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 414e0f9..5d99999 100644
--- a/migration.c
+++ b/migration.c
@@ -523,12 +523,6 @@ static int migration_put_buffer(void *opaque, const uint8_t *buf,
 
     DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos);
 
-    ret = qemu_file_get_error(s->file);
-    if (ret) {
-        DPRINTF("flush when error, bailing: %s\n", strerror(-ret));
-        return ret;
-    }
-
     if (size <= 0) {
         return size;
     }
commit fd45ee2c643bb3d55de5c54b50c23859ca631a9f
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:33 2013 +0100

    migration: detect error before sleeping
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 612ffa7..414e0f9 100644
--- a/migration.c
+++ b/migration.c
@@ -657,6 +657,10 @@ static void *migration_thread(void *opaque)
             }
         }
 
+        if (qemu_file_get_error(s->file)) {
+            migrate_finish_set_state(s, MIG_STATE_ERROR);
+            break;
+        }
         current_time = qemu_get_clock_ms(rt_clock);
         if (current_time >= initial_time + BUFFER_DELAY) {
             uint64_t transferred_bytes = s->bytes_xfer;
@@ -682,9 +686,6 @@ static void *migration_thread(void *opaque)
             g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
             sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
         }
-        if (qemu_file_get_error(s->file)) {
-            migrate_finish_set_state(s, MIG_STATE_ERROR);
-        }
     }
 
     qemu_mutex_lock_iothread();
commit 059f896cefb2776181e39d9ba69345bd9d07d52b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:32 2013 +0100

    migration: eliminate last_round
    
    We will go around the loop exactly once after setting last_round.
    Eliminate the variable altogether.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 861b124..612ffa7 100644
--- a/migration.c
+++ b/migration.c
@@ -626,7 +626,6 @@ static void *migration_thread(void *opaque)
     int64_t max_size = 0;
     int64_t start_time = initial_time;
     bool old_vm_running = false;
-    bool last_round = false;
 
     DPRINTF("beginning savevm\n");
     qemu_savevm_state_begin(s->file, &s->params);
@@ -650,8 +649,11 @@ static void *migration_thread(void *opaque)
                 vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
                 s->xfer_limit = INT_MAX;
                 qemu_savevm_state_complete(s->file);
-                last_round = true;
                 qemu_mutex_unlock_iothread();
+                if (!qemu_file_get_error(s->file)) {
+                    migrate_finish_set_state(s, MIG_STATE_COMPLETED);
+                    break;
+                }
             }
         }
 
@@ -675,15 +677,13 @@ static void *migration_thread(void *opaque)
             sleep_time = 0;
             initial_time = current_time;
         }
-        if (!last_round && (s->bytes_xfer >= s->xfer_limit)) {
+        if (s->bytes_xfer >= s->xfer_limit) {
             /* usleep expects microseconds */
             g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
             sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
         }
         if (qemu_file_get_error(s->file)) {
             migrate_finish_set_state(s, MIG_STATE_ERROR);
-        } else if (last_round) {
-            migrate_finish_set_state(s, MIG_STATE_COMPLETED);
         }
     }
 
@@ -695,7 +695,6 @@ static void *migration_thread(void *opaque)
         runstate_set(RUN_STATE_POSTMIGRATE);
     } else {
         if (old_vm_running) {
-            assert(last_round);
             vm_start();
         }
     }
commit 05f28b837c6bd6124abab2496ce15c07a334a5ad
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:31 2013 +0100

    qemu-file: make qemu_fflush and qemu_file_set_error private again
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 5e0c287..46fc11d 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -82,7 +82,6 @@ QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
 int qemu_get_fd(QEMUFile *f);
 int qemu_fclose(QEMUFile *f);
 int64_t qemu_ftell(QEMUFile *f);
-void qemu_fflush(QEMUFile *f);
 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
 void qemu_put_byte(QEMUFile *f, int v);
 
@@ -114,7 +113,6 @@ int qemu_file_rate_limit(QEMUFile *f);
 int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate);
 int64_t qemu_file_get_rate_limit(QEMUFile *f);
 int qemu_file_get_error(QEMUFile *f);
-void qemu_file_set_error(QEMUFile *f, int ret);
 
 static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv)
 {
diff --git a/savevm.c b/savevm.c
index ce10295..fef2ab9 100644
--- a/savevm.c
+++ b/savevm.c
@@ -443,7 +443,7 @@ int qemu_file_get_error(QEMUFile *f)
     return f->last_error;
 }
 
-void qemu_file_set_error(QEMUFile *f, int ret)
+static void qemu_file_set_error(QEMUFile *f, int ret)
 {
     if (f->last_error == 0) {
         f->last_error = ret;
@@ -453,7 +453,7 @@ void qemu_file_set_error(QEMUFile *f, int ret)
 /** Flushes QEMUFile buffer
  *
  */
-void qemu_fflush(QEMUFile *f)
+static void qemu_fflush(QEMUFile *f)
 {
     int ret = 0;
 
commit 5f496a1be3d15f192be1ab1fed3a3278fd5a91a1
Author: Juan Quintela <quintela at redhat.com>
Date:   Fri Feb 22 17:36:30 2013 +0100

    Rename buffered_ to migration_
    
    This is consistent once that we have moved everything to migration.c
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 4c8d576..861b124 100644
--- a/migration.c
+++ b/migration.c
@@ -514,7 +514,7 @@ int64_t migrate_xbzrle_cache_size(void)
 
 /* migration thread support */
 
-static int buffered_put_buffer(void *opaque, const uint8_t *buf,
+static int migration_put_buffer(void *opaque, const uint8_t *buf,
                                int64_t pos, int size)
 {
     MigrationState *s = opaque;
@@ -551,7 +551,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf,
     return sent;
 }
 
-static int buffered_close(void *opaque)
+static int migration_close(void *opaque)
 {
     MigrationState *s = opaque;
 
@@ -565,7 +565,7 @@ static int buffered_close(void *opaque)
     return migrate_fd_close(s);
 }
 
-static int buffered_get_fd(void *opaque)
+static int migration_get_fd(void *opaque)
 {
     MigrationState *s = opaque;
 
@@ -578,7 +578,7 @@ static int buffered_get_fd(void *opaque)
  *   1: Time to stop
  *   negative: There has been an error
  */
-static int buffered_rate_limit(void *opaque)
+static int migration_rate_limit(void *opaque)
 {
     MigrationState *s = opaque;
     int ret;
@@ -595,7 +595,7 @@ static int buffered_rate_limit(void *opaque)
     return 0;
 }
 
-static int64_t buffered_set_rate_limit(void *opaque, int64_t new_rate)
+static int64_t migration_set_rate_limit(void *opaque, int64_t new_rate)
 {
     MigrationState *s = opaque;
     if (qemu_file_get_error(s->file)) {
@@ -611,14 +611,14 @@ out:
     return s->xfer_limit;
 }
 
-static int64_t buffered_get_rate_limit(void *opaque)
+static int64_t migration_get_rate_limit(void *opaque)
 {
     MigrationState *s = opaque;
 
     return s->xfer_limit;
 }
 
-static void *buffered_file_thread(void *opaque)
+static void *migration_thread(void *opaque)
 {
     MigrationState *s = opaque;
     int64_t initial_time = qemu_get_clock_ms(rt_clock);
@@ -705,13 +705,13 @@ static void *buffered_file_thread(void *opaque)
     return NULL;
 }
 
-static const QEMUFileOps buffered_file_ops = {
-    .get_fd =         buffered_get_fd,
-    .put_buffer =     buffered_put_buffer,
-    .close =          buffered_close,
-    .rate_limit =     buffered_rate_limit,
-    .get_rate_limit = buffered_get_rate_limit,
-    .set_rate_limit = buffered_set_rate_limit,
+static const QEMUFileOps migration_file_ops = {
+    .get_fd =         migration_get_fd,
+    .put_buffer =     migration_put_buffer,
+    .close =          migration_close,
+    .rate_limit =     migration_rate_limit,
+    .get_rate_limit = migration_get_rate_limit,
+    .set_rate_limit = migration_set_rate_limit,
 };
 
 void migrate_fd_connect(MigrationState *s)
@@ -726,9 +726,9 @@ void migrate_fd_connect(MigrationState *s)
     s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
 
     s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
-    s->file = qemu_fopen_ops(s, &buffered_file_ops);
+    s->file = qemu_fopen_ops(s, &migration_file_ops);
 
-    qemu_thread_create(&s->thread, buffered_file_thread, s,
+    qemu_thread_create(&s->thread, migration_thread, s,
                        QEMU_THREAD_JOINABLE);
     notifier_list_notify(&migration_state_notifiers, s);
 }
commit edaae611f6df0d66a8b5a90c84123b72980c7a22
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:29 2013 +0100

    migration: yay, buffering is gone
    
    Buffering was needed because blocking writes could take a long time
    and starve other threads seeking to grab the big QEMU mutex.
    
    Now that all writes (except within _complete callbacks) are done
    outside the big QEMU mutex, we do not need buffering at all.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/migration.h b/include/migration/migration.h
index ed20bed..cec8643 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -34,9 +34,6 @@ struct MigrationState
     int64_t bandwidth_limit;
     size_t bytes_xfer;
     size_t xfer_limit;
-    uint8_t *buffer;
-    size_t buffer_size;
-    size_t buffer_capacity;
     QemuThread thread;
     QEMUBH *cleanup_bh;
 
diff --git a/migration.c b/migration.c
index e64c92d..4c8d576 100644
--- a/migration.c
+++ b/migration.c
@@ -514,73 +514,41 @@ int64_t migrate_xbzrle_cache_size(void)
 
 /* migration thread support */
 
-
-static void buffered_flush(MigrationState *s)
-{
-    size_t offset = 0;
-    ssize_t ret = 0;
-
-    DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size);
-
-    if (qemu_file_get_error(s->file)) {
-        s->buffer_size = 0;
-        return;
-    }
-    qemu_fflush(s->file);
-
-    while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) {
-        size_t to_send = MIN(s->buffer_size - offset, s->xfer_limit - s->bytes_xfer);
-        ret = migrate_fd_put_buffer(s, s->buffer + offset, to_send);
-        if (ret <= 0) {
-            DPRINTF("error flushing data, %zd\n", ret);
-            break;
-        } else {
-            DPRINTF("flushed %zd byte(s)\n", ret);
-            offset += ret;
-            s->bytes_xfer += ret;
-        }
-    }
-
-    DPRINTF("flushed %zu of %zu byte(s)\n", offset, s->buffer_size);
-    memmove(s->buffer, s->buffer + offset, s->buffer_size - offset);
-    s->buffer_size -= offset;
-
-    if (ret < 0) {
-        qemu_file_set_error(s->file, ret);
-    }
-}
-
 static int buffered_put_buffer(void *opaque, const uint8_t *buf,
                                int64_t pos, int size)
 {
     MigrationState *s = opaque;
-    ssize_t error;
+    ssize_t ret;
+    size_t sent;
 
     DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos);
 
-    error = qemu_file_get_error(s->file);
-    if (error) {
-        DPRINTF("flush when error, bailing: %s\n", strerror(-error));
-        return error;
+    ret = qemu_file_get_error(s->file);
+    if (ret) {
+        DPRINTF("flush when error, bailing: %s\n", strerror(-ret));
+        return ret;
     }
 
     if (size <= 0) {
         return size;
     }
 
-    if (size > (s->buffer_capacity - s->buffer_size)) {
-        DPRINTF("increasing buffer capacity from %zu by %zu\n",
-                s->buffer_capacity, size + 1024);
-
-        s->buffer_capacity += size + 1024;
-
-        s->buffer = g_realloc(s->buffer, s->buffer_capacity);
+    sent = 0;
+    while (size) {
+        ret = migrate_fd_put_buffer(s, buf, size);
+        if (ret <= 0) {
+            DPRINTF("error flushing data, %zd\n", ret);
+            return ret;
+        } else {
+            DPRINTF("flushed %zd byte(s)\n", ret);
+            sent += ret;
+            buf += ret;
+            size -= ret;
+            s->bytes_xfer += ret;
+        }
     }
 
-    memcpy(s->buffer + s->buffer_size, buf, size);
-    s->buffer_size += size;
-
-    return size;
+    return sent;
 }
 
 static int buffered_close(void *opaque)
@@ -712,10 +680,9 @@ static void *buffered_file_thread(void *opaque)
             g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
             sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
         }
-        buffered_flush(s);
         if (qemu_file_get_error(s->file)) {
             migrate_finish_set_state(s, MIG_STATE_ERROR);
-        } else if (last_round && s->buffer_size == 0) {
+        } else if (last_round) {
             migrate_finish_set_state(s, MIG_STATE_COMPLETED);
         }
     }
@@ -735,7 +702,6 @@ static void *buffered_file_thread(void *opaque)
     qemu_bh_schedule(s->cleanup_bh);
     qemu_mutex_unlock_iothread();
 
-    g_free(s->buffer);
     return NULL;
 }
 
@@ -754,9 +720,6 @@ void migrate_fd_connect(MigrationState *s)
     trace_migrate_set_state(MIG_STATE_ACTIVE);
 
     s->bytes_xfer = 0;
-    s->buffer = NULL;
-    s->buffer_size = 0;
-    s->buffer_capacity = 0;
     /* This is a best 1st approximation. ns to ms */
     s->expected_downtime = max_downtime/1000000;
 
diff --git a/savevm.c b/savevm.c
index 7c7774e..ce10295 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1724,6 +1724,7 @@ void qemu_savevm_state_complete(QEMUFile *f)
     }
 
     qemu_put_byte(f, QEMU_VM_EOF);
+    qemu_fflush(f);
 }
 
 uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size)
commit 9b0950375277467fd74a9075624477ae43b9bb22
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:28 2013 +0100

    migration: run setup callbacks out of big lock
    
    Only the migration_bitmap_sync() call needs the iothread lock.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 32b4378..6089c53 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -570,10 +570,6 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
     bitmap_set(migration_bitmap, 0, ram_pages);
     migration_dirty_pages = ram_pages;
 
-    qemu_mutex_lock_ramlist();
-    bytes_transferred = 0;
-    reset_ram_globals();
-
     if (migrate_use_xbzrle()) {
         XBZRLE.cache = cache_init(migrate_xbzrle_cache_size() /
                                   TARGET_PAGE_SIZE,
@@ -587,8 +583,14 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
         acct_clear();
     }
 
+    qemu_mutex_lock_iothread();
+    qemu_mutex_lock_ramlist();
+    bytes_transferred = 0;
+    reset_ram_globals();
+
     memory_global_dirty_log_start();
     migration_bitmap_sync();
+    qemu_mutex_unlock_iothread();
 
     qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
 
diff --git a/block-migration.c b/block-migration.c
index 8da5f86..2fd7699 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -583,10 +583,12 @@ static int block_save_setup(QEMUFile *f, void *opaque)
     DPRINTF("Enter save live setup submitted %d transferred %d\n",
             block_mig_state.submitted, block_mig_state.transferred);
 
+    qemu_mutex_lock_iothread();
     init_blk_migration(f);
 
     /* start track dirty blocks */
     set_dirty_tracking(1);
+    qemu_mutex_unlock_iothread();
 
     ret = flush_blks(f);
     blk_mig_reset_dirty_cursor();
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index a816ac3..a64db94 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -36,7 +36,6 @@ typedef struct SaveVMHandlers {
     void (*set_params)(const MigrationParams *params, void * opaque);
     SaveStateHandler *save_state;
 
-    int (*save_live_setup)(QEMUFile *f, void *opaque);
     void (*cancel)(void *opaque);
     int (*save_live_complete)(QEMUFile *f, void *opaque);
 
@@ -51,6 +50,7 @@ typedef struct SaveVMHandlers {
     int (*save_live_iterate)(QEMUFile *f, void *opaque);
 
     /* This runs outside the iothread lock!  */
+    int (*save_live_setup)(QEMUFile *f, void *opaque);
     uint64_t (*save_live_pending)(QEMUFile *f, void *opaque, uint64_t max_size);
 
     LoadStateHandler *load_state;
diff --git a/migration.c b/migration.c
index 92a7152..e64c92d 100644
--- a/migration.c
+++ b/migration.c
@@ -660,10 +660,8 @@ static void *buffered_file_thread(void *opaque)
     bool old_vm_running = false;
     bool last_round = false;
 
-    qemu_mutex_lock_iothread();
     DPRINTF("beginning savevm\n");
     qemu_savevm_state_begin(s->file, &s->params);
-    qemu_mutex_unlock_iothread();
 
     while (s->state == MIG_STATE_ACTIVE) {
         int64_t current_time;
diff --git a/savevm.c b/savevm.c
index e10a045..7c7774e 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1768,7 +1768,10 @@ static int qemu_savevm_state(QEMUFile *f)
         return -EINVAL;
     }
 
+    qemu_mutex_unlock_iothread();
     qemu_savevm_state_begin(f, &params);
+    qemu_mutex_lock_iothread();
+
     while (qemu_file_get_error(f) == 0) {
         if (qemu_savevm_state_iterate(f) > 0) {
             break;
commit 32c835ba3984728c22d4e73cdb595090a60f437e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:27 2013 +0100

    migration: run pending/iterate callbacks out of big lock
    
    This makes it possible to do blocking writes directly to the socket,
    with no buffer in the middle.  For RAM, only the migration_bitmap_sync()
    call needs the iothread lock.  For block migration, it is needed by
    the block layer (including bdrv_drain_all and dirty bitmap access),
    but because some code is shared between iterate and complete, all of
    mig_save_device_dirty is run with the lock taken.
    
    In the savevm case, the iterate callback runs within the big lock.
    This is annoying because it complicates the rules.  Luckily we do not
    need to do anything about it: the RAM iterate callback does not need
    the iothread lock, and block migration never runs during savevm.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 8daeafa..32b4378 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -379,6 +379,8 @@ static inline bool migration_bitmap_set_dirty(MemoryRegion *mr,
     return ret;
 }
 
+/* Needs iothread lock! */
+
 static void migration_bitmap_sync(void)
 {
     RAMBlock *block;
@@ -690,7 +692,9 @@ static uint64_t ram_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
     remaining_size = ram_save_remaining() * TARGET_PAGE_SIZE;
 
     if (remaining_size < max_size) {
+        qemu_mutex_lock_iothread();
         migration_bitmap_sync();
+        qemu_mutex_unlock_iothread();
         remaining_size = ram_save_remaining() * TARGET_PAGE_SIZE;
     }
     return remaining_size;
diff --git a/block-migration.c b/block-migration.c
index b726c6c..8da5f86 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -107,6 +107,10 @@ static void blk_mig_unlock(void)
     qemu_mutex_unlock(&block_mig_state.lock);
 }
 
+/* Must run outside of the iothread lock during the bulk phase,
+ * or the VM will stall.
+ */
+
 static void blk_send(QEMUFile *f, BlkMigBlock * blk)
 {
     int len;
@@ -226,6 +230,8 @@ static void blk_mig_read_cb(void *opaque, int ret)
     blk_mig_unlock();
 }
 
+/* Called with no lock taken.  */
+
 static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
 {
     int64_t total_sectors = bmds->total_sectors;
@@ -235,11 +241,13 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
     int nr_sectors;
 
     if (bmds->shared_base) {
+        qemu_mutex_lock_iothread();
         while (cur_sector < total_sectors &&
                !bdrv_is_allocated(bs, cur_sector, MAX_IS_ALLOCATED_SEARCH,
                                   &nr_sectors)) {
             cur_sector += nr_sectors;
         }
+        qemu_mutex_unlock_iothread();
     }
 
     if (cur_sector >= total_sectors) {
@@ -272,15 +280,19 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
     block_mig_state.submitted++;
     blk_mig_unlock();
 
+    qemu_mutex_lock_iothread();
     blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
                                 nr_sectors, blk_mig_read_cb, blk);
 
     bdrv_reset_dirty(bs, cur_sector, nr_sectors);
-    bmds->cur_sector = cur_sector + nr_sectors;
+    qemu_mutex_unlock_iothread();
 
+    bmds->cur_sector = cur_sector + nr_sectors;
     return (bmds->cur_sector >= total_sectors);
 }
 
+/* Called with iothread lock taken.  */
+
 static void set_dirty_tracking(int enable)
 {
     BlkMigDevState *bmds;
@@ -336,6 +348,8 @@ static void init_blk_migration(QEMUFile *f)
     bdrv_iterate(init_blk_migration_it, NULL);
 }
 
+/* Called with no lock taken.  */
+
 static int blk_mig_save_bulked_block(QEMUFile *f)
 {
     int64_t completed_sector_sum = 0;
@@ -382,6 +396,8 @@ static void blk_mig_reset_dirty_cursor(void)
     }
 }
 
+/* Called with iothread lock taken.  */
+
 static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
                                  int is_async)
 {
@@ -451,7 +467,9 @@ error:
     return ret;
 }
 
-/* return value:
+/* Called with iothread lock taken.
+ *
+ * return value:
  * 0: too much data for max_downtime
  * 1: few enough data for max_downtime
 */
@@ -470,6 +488,8 @@ static int blk_mig_save_dirty_block(QEMUFile *f, int is_async)
     return ret;
 }
 
+/* Called with no locks taken.  */
+
 static int flush_blks(QEMUFile *f)
 {
     BlkMigBlock *blk;
@@ -509,6 +529,8 @@ static int flush_blks(QEMUFile *f)
     return ret;
 }
 
+/* Called with iothread lock taken.  */
+
 static int64_t get_remaining_dirty(void)
 {
     BlkMigDevState *bmds;
@@ -521,6 +543,8 @@ static int64_t get_remaining_dirty(void)
     return dirty << BDRV_SECTOR_BITS;
 }
 
+/* Called with iothread lock taken.  */
+
 static void blk_mig_cleanup(void)
 {
     BlkMigDevState *bmds;
@@ -600,7 +624,12 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
             }
             ret = 0;
         } else {
+            /* Always called with iothread lock taken for
+             * simplicity, block_save_complete also calls it.
+             */
+            qemu_mutex_lock_iothread();
             ret = blk_mig_save_dirty_block(f, 1);
+            qemu_mutex_unlock_iothread();
         }
         if (ret < 0) {
             return ret;
@@ -622,6 +651,8 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
     return qemu_ftell(f) - last_ftell;
 }
 
+/* Called with iothread lock taken.  */
+
 static int block_save_complete(QEMUFile *f, void *opaque)
 {
     int ret;
@@ -665,6 +696,7 @@ static uint64_t block_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
     /* Estimate pending number of bytes to send */
     uint64_t pending;
 
+    qemu_mutex_lock_iothread();
     blk_mig_lock();
     pending = get_remaining_dirty() +
                        block_mig_state.submitted * BLOCK_SIZE +
@@ -675,6 +707,7 @@ static uint64_t block_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
         pending = BLOCK_SIZE;
     }
     blk_mig_unlock();
+    qemu_mutex_unlock_iothread();
 
     DPRINTF("Enter save live pending  %" PRIu64 "\n", pending);
     return pending;
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index fdf4e65..a816ac3 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -32,14 +32,25 @@ typedef void SaveStateHandler(QEMUFile *f, void *opaque);
 typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
 
 typedef struct SaveVMHandlers {
+    /* This runs inside the iothread lock.  */
     void (*set_params)(const MigrationParams *params, void * opaque);
     SaveStateHandler *save_state;
 
     int (*save_live_setup)(QEMUFile *f, void *opaque);
     void (*cancel)(void *opaque);
     int (*save_live_complete)(QEMUFile *f, void *opaque);
+
+    /* This runs both outside and inside the iothread lock.  */
     bool (*is_active)(void *opaque);
+
+    /* This runs outside the iothread lock in the migration case, and
+     * within the lock in the savevm case.  The callback had better only
+     * use data that is local to the migration thread or protected
+     * by other locks.
+     */
     int (*save_live_iterate)(QEMUFile *f, void *opaque);
+
+    /* This runs outside the iothread lock!  */
     uint64_t (*save_live_pending)(QEMUFile *f, void *opaque, uint64_t max_size);
 
     LoadStateHandler *load_state;
diff --git a/migration.c b/migration.c
index 729578b..92a7152 100644
--- a/migration.c
+++ b/migration.c
@@ -670,7 +670,6 @@ static void *buffered_file_thread(void *opaque)
         uint64_t pending_size;
 
         if (s->bytes_xfer < s->xfer_limit) {
-            qemu_mutex_lock_iothread();
             DPRINTF("iterate\n");
             pending_size = qemu_savevm_state_pending(s->file, max_size);
             DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
@@ -678,6 +677,7 @@ static void *buffered_file_thread(void *opaque)
                 qemu_savevm_state_iterate(s->file);
             } else {
                 DPRINTF("done iterating\n");
+                qemu_mutex_lock_iothread();
                 start_time = qemu_get_clock_ms(rt_clock);
                 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
                 old_vm_running = runstate_is_running();
@@ -685,8 +685,8 @@ static void *buffered_file_thread(void *opaque)
                 s->xfer_limit = INT_MAX;
                 qemu_savevm_state_complete(s->file);
                 last_round = true;
+                qemu_mutex_unlock_iothread();
             }
-            qemu_mutex_unlock_iothread();
         }
 
         current_time = qemu_get_clock_ms(rt_clock);
commit 8c8de19d93444536d3291e6ab83e2bcf61dd2d0c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:26 2013 +0100

    migration: reorder SaveVMHandlers members
    
    This groups together the callbacks that later will have similar
    locking rules.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 94a409b..fdf4e65 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -34,13 +34,15 @@ typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
 typedef struct SaveVMHandlers {
     void (*set_params)(const MigrationParams *params, void * opaque);
     SaveStateHandler *save_state;
+
     int (*save_live_setup)(QEMUFile *f, void *opaque);
-    int (*save_live_iterate)(QEMUFile *f, void *opaque);
+    void (*cancel)(void *opaque);
     int (*save_live_complete)(QEMUFile *f, void *opaque);
+    bool (*is_active)(void *opaque);
+    int (*save_live_iterate)(QEMUFile *f, void *opaque);
     uint64_t (*save_live_pending)(QEMUFile *f, void *opaque, uint64_t max_size);
-    void (*cancel)(void *opaque);
+
     LoadStateHandler *load_state;
-    bool (*is_active)(void *opaque);
 } SaveVMHandlers;
 
 int register_savevm(DeviceState *dev,
commit 52e850dea988585c3d693fd9cd4a4c38968d89b8
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:25 2013 +0100

    block-migration: add lock
    
    Some state is shared between the block migration code and its AIO
    callbacks.  Once block migration will run outside the iothread,
    the block migration code and the AIO callbacks will be able to
    run concurrently.  Protect the critical sections with a separate
    lock.  Do the same for completed_sectors, which can be used from
    the monitor.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/block-migration.c b/block-migration.c
index d62a8b8..b726c6c 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -54,7 +54,7 @@ typedef struct BlkMigDevState {
     int64_t cur_sector;
     int64_t cur_dirty;
 
-    /* Protected by iothread lock.  */
+    /* Protected by block migration lock.  */
     unsigned long *aio_bitmap;
     int64_t completed_sectors;
 } BlkMigDevState;
@@ -69,7 +69,7 @@ typedef struct BlkMigBlock {
     QEMUIOVector qiov;
     BlockDriverAIOCB *aiocb;
 
-    /* Protected by iothread lock.  */
+    /* Protected by block migration lock.  */
     int ret;
     QSIMPLEQ_ENTRY(BlkMigBlock) entry;
 } BlkMigBlock;
@@ -81,7 +81,7 @@ typedef struct BlkMigState {
     QSIMPLEQ_HEAD(bmds_list, BlkMigDevState) bmds_list;
     int64_t total_sector_sum;
 
-    /* Protected by iothread lock.  */
+    /* Protected by lock.  */
     QSIMPLEQ_HEAD(blk_list, BlkMigBlock) blk_list;
     int submitted;
     int read_done;
@@ -90,10 +90,23 @@ typedef struct BlkMigState {
     int transferred;
     int prev_progress;
     int bulk_completed;
+
+    /* Lock must be taken _inside_ the iothread lock.  */
+    QemuMutex lock;
 } BlkMigState;
 
 static BlkMigState block_mig_state;
 
+static void blk_mig_lock(void)
+{
+    qemu_mutex_lock(&block_mig_state.lock);
+}
+
+static void blk_mig_unlock(void)
+{
+    qemu_mutex_unlock(&block_mig_state.lock);
+}
+
 static void blk_send(QEMUFile *f, BlkMigBlock * blk)
 {
     int len;
@@ -120,9 +133,11 @@ uint64_t blk_mig_bytes_transferred(void)
     BlkMigDevState *bmds;
     uint64_t sum = 0;
 
+    blk_mig_lock();
     QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
         sum += bmds->completed_sectors;
     }
+    blk_mig_unlock();
     return sum << BDRV_SECTOR_BITS;
 }
 
@@ -142,6 +157,9 @@ uint64_t blk_mig_bytes_total(void)
     return sum << BDRV_SECTOR_BITS;
 }
 
+
+/* Called with migration lock held.  */
+
 static int bmds_aio_inflight(BlkMigDevState *bmds, int64_t sector)
 {
     int64_t chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK;
@@ -154,6 +172,8 @@ static int bmds_aio_inflight(BlkMigDevState *bmds, int64_t sector)
     }
 }
 
+/* Called with migration lock held.  */
+
 static void bmds_set_aio_inflight(BlkMigDevState *bmds, int64_t sector_num,
                              int nb_sectors, int set)
 {
@@ -188,10 +208,13 @@ static void alloc_aio_bitmap(BlkMigDevState *bmds)
     bmds->aio_bitmap = g_malloc0(bitmap_size);
 }
 
+/* Never hold migration lock when yielding to the main loop!  */
+
 static void blk_mig_read_cb(void *opaque, int ret)
 {
     BlkMigBlock *blk = opaque;
 
+    blk_mig_lock();
     blk->ret = ret;
 
     QSIMPLEQ_INSERT_TAIL(&block_mig_state.blk_list, blk, entry);
@@ -200,6 +223,7 @@ static void blk_mig_read_cb(void *opaque, int ret)
     block_mig_state.submitted--;
     block_mig_state.read_done++;
     assert(block_mig_state.submitted >= 0);
+    blk_mig_unlock();
 }
 
 static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
@@ -244,7 +268,9 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
     blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
     qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
 
+    blk_mig_lock();
     block_mig_state.submitted++;
+    blk_mig_unlock();
 
     blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
                                 nr_sectors, blk_mig_read_cb, blk);
@@ -366,8 +392,12 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
     int ret = -EIO;
 
     for (sector = bmds->cur_dirty; sector < bmds->total_sectors;) {
+        blk_mig_lock();
         if (bmds_aio_inflight(bmds, sector)) {
+            blk_mig_unlock();
             bdrv_drain_all();
+        } else {
+            blk_mig_unlock();
         }
         if (bdrv_get_dirty(bmds->bs, sector)) {
 
@@ -389,8 +419,11 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
 
                 blk->aiocb = bdrv_aio_readv(bmds->bs, sector, &blk->qiov,
                                             nr_sectors, blk_mig_read_cb, blk);
+
+                blk_mig_lock();
                 block_mig_state.submitted++;
                 bmds_set_aio_inflight(bmds, sector, nr_sectors, 1);
+                blk_mig_unlock();
             } else {
                 ret = bdrv_read(bmds->bs, sector, blk->buf, nr_sectors);
                 if (ret < 0) {
@@ -446,6 +479,7 @@ static int flush_blks(QEMUFile *f)
             __FUNCTION__, block_mig_state.submitted, block_mig_state.read_done,
             block_mig_state.transferred);
 
+    blk_mig_lock();
     while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
         if (qemu_file_rate_limit(f)) {
             break;
@@ -456,7 +490,9 @@ static int flush_blks(QEMUFile *f)
         }
 
         QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
+        blk_mig_unlock();
         blk_send(f, blk);
+        blk_mig_lock();
 
         g_free(blk->buf);
         g_free(blk);
@@ -465,6 +501,7 @@ static int flush_blks(QEMUFile *f)
         block_mig_state.transferred++;
         assert(block_mig_state.read_done >= 0);
     }
+    blk_mig_unlock();
 
     DPRINTF("%s Exit submitted %d read_done %d transferred %d\n", __FUNCTION__,
             block_mig_state.submitted, block_mig_state.read_done,
@@ -493,6 +530,7 @@ static void blk_mig_cleanup(void)
 
     set_dirty_tracking(0);
 
+    blk_mig_lock();
     while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
         QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
         bdrv_set_in_use(bmds->bs, 0);
@@ -506,6 +544,7 @@ static void blk_mig_cleanup(void)
         g_free(blk->buf);
         g_free(blk);
     }
+    blk_mig_unlock();
 }
 
 static void block_migration_cancel(void *opaque)
@@ -548,9 +587,11 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
     blk_mig_reset_dirty_cursor();
 
     /* control the rate of transfer */
+    blk_mig_lock();
     while ((block_mig_state.submitted +
             block_mig_state.read_done) * BLOCK_SIZE <
            qemu_file_get_rate_limit(f)) {
+        blk_mig_unlock();
         if (block_mig_state.bulk_completed == 0) {
             /* first finish the bulk phase */
             if (blk_mig_save_bulked_block(f) == 0) {
@@ -564,11 +605,13 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
         if (ret < 0) {
             return ret;
         }
+        blk_mig_lock();
         if (ret != 0) {
             /* no more dirty blocks */
             break;
         }
     }
+    blk_mig_unlock();
 
     ret = flush_blks(f);
     if (ret) {
@@ -595,7 +638,9 @@ static int block_save_complete(QEMUFile *f, void *opaque)
 
     /* we know for sure that save bulk is completed and
        all async read completed */
+    blk_mig_lock();
     assert(block_mig_state.submitted == 0);
+    blk_mig_unlock();
 
     do {
         ret = blk_mig_save_dirty_block(f, 0);
@@ -620,6 +665,7 @@ static uint64_t block_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
     /* Estimate pending number of bytes to send */
     uint64_t pending;
 
+    blk_mig_lock();
     pending = get_remaining_dirty() +
                        block_mig_state.submitted * BLOCK_SIZE +
                        block_mig_state.read_done * BLOCK_SIZE;
@@ -628,6 +674,7 @@ static uint64_t block_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
     if (pending == 0 && !block_mig_state.bulk_completed) {
         pending = BLOCK_SIZE;
     }
+    blk_mig_unlock();
 
     DPRINTF("Enter save live pending  %" PRIu64 "\n", pending);
     return pending;
@@ -739,6 +786,7 @@ void blk_mig_init(void)
 {
     QSIMPLEQ_INIT(&block_mig_state.bmds_list);
     QSIMPLEQ_INIT(&block_mig_state.blk_list);
+    qemu_mutex_init(&block_mig_state.lock);
 
     register_savevm_live(NULL, "block", 0, 1, &savevm_block_handlers,
                          &block_mig_state);
diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h
index 96a194b..10becb6 100644
--- a/include/qemu/atomic.h
+++ b/include/qemu/atomic.h
@@ -16,6 +16,7 @@
  */
 #define smp_wmb()   barrier()
 #define smp_rmb()   barrier()
+
 /*
  * We use GCC builtin if it's available, as that can use
  * mfence on 32 bit as well, e.g. if built with -march=pentium-m.
commit 323920c4eac01de74cf2b5e941c97ca9b2d36b7f
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:24 2013 +0100

    block-migration: document usage of state across threads
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/block-migration.c b/block-migration.c
index 9a40edd..d62a8b8 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -43,18 +43,24 @@
 #endif
 
 typedef struct BlkMigDevState {
+    /* Written during setup phase.  Can be read without a lock.  */
     BlockDriverState *bs;
-    int bulk_completed;
     int shared_base;
-    int64_t cur_sector;
-    int64_t cur_dirty;
-    int64_t completed_sectors;
     int64_t total_sectors;
     QSIMPLEQ_ENTRY(BlkMigDevState) entry;
+
+    /* Only used by migration thread.  Does not need a lock.  */
+    int bulk_completed;
+    int64_t cur_sector;
+    int64_t cur_dirty;
+
+    /* Protected by iothread lock.  */
     unsigned long *aio_bitmap;
+    int64_t completed_sectors;
 } BlkMigDevState;
 
 typedef struct BlkMigBlock {
+    /* Only used by migration thread.  */
     uint8_t *buf;
     BlkMigDevState *bmds;
     int64_t sector;
@@ -62,19 +68,26 @@ typedef struct BlkMigBlock {
     struct iovec iov;
     QEMUIOVector qiov;
     BlockDriverAIOCB *aiocb;
+
+    /* Protected by iothread lock.  */
     int ret;
     QSIMPLEQ_ENTRY(BlkMigBlock) entry;
 } BlkMigBlock;
 
 typedef struct BlkMigState {
+    /* Written during setup phase.  Can be read without a lock.  */
     int blk_enable;
     int shared_base;
     QSIMPLEQ_HEAD(bmds_list, BlkMigDevState) bmds_list;
+    int64_t total_sector_sum;
+
+    /* Protected by iothread lock.  */
     QSIMPLEQ_HEAD(blk_list, BlkMigBlock) blk_list;
     int submitted;
     int read_done;
+
+    /* Only used by migration thread.  Does not need a lock.  */
     int transferred;
-    int64_t total_sector_sum;
     int prev_progress;
     int bulk_completed;
 } BlkMigState;
commit 13197e3cbaba0ba693dd2855a32182ca584fa97e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:23 2013 +0100

    block-migration: small preparatory changes for locking
    
    Some small changes that will simplify the positioning of lock/unlock
    primitives.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/block-migration.c b/block-migration.c
index e72f322..9a40edd 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -231,9 +231,10 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
     blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
     qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
 
+    block_mig_state.submitted++;
+
     blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
                                 nr_sectors, blk_mig_read_cb, blk);
-    block_mig_state.submitted++;
 
     bdrv_reset_dirty(bs, cur_sector, nr_sectors);
     bmds->cur_sector = cur_sector + nr_sectors;
@@ -440,9 +441,10 @@ static int flush_blks(QEMUFile *f)
             ret = blk->ret;
             break;
         }
-        blk_send(f, blk);
 
         QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
+        blk_send(f, blk);
+
         g_free(blk->buf);
         g_free(blk);
 
@@ -542,15 +544,16 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
                 /* finished saving bulk on all devices */
                 block_mig_state.bulk_completed = 1;
             }
+            ret = 0;
         } else {
             ret = blk_mig_save_dirty_block(f, 1);
-            if (ret < 0) {
-                return ret;
-            }
-            if (ret != 0) {
-                /* no more dirty blocks */
-                break;
-            }
+        }
+        if (ret < 0) {
+            return ret;
+        }
+        if (ret != 0) {
+            /* no more dirty blocks */
+            break;
         }
     }
 
@@ -560,7 +563,6 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
     }
 
     qemu_put_be64(f, BLK_MIG_FLAG_EOS);
-
     return qemu_ftell(f) - last_ftell;
 }
 
@@ -603,7 +605,9 @@ static int block_save_complete(QEMUFile *f, void *opaque)
 static uint64_t block_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
 {
     /* Estimate pending number of bytes to send */
-    uint64_t pending = get_remaining_dirty() +
+    uint64_t pending;
+
+    pending = get_remaining_dirty() +
                        block_mig_state.submitted * BLOCK_SIZE +
                        block_mig_state.read_done * BLOCK_SIZE;
 
commit a55ce1c851b5802569fb00b2a645a73c03fd7c86
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:22 2013 +0100

    block-migration: remove variables that are never read
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/block-migration.c b/block-migration.c
index e6c917d..e72f322 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -50,7 +50,6 @@ typedef struct BlkMigDevState {
     int64_t cur_dirty;
     int64_t completed_sectors;
     int64_t total_sectors;
-    int64_t dirty;
     QSIMPLEQ_ENTRY(BlkMigDevState) entry;
     unsigned long *aio_bitmap;
 } BlkMigDevState;
@@ -78,7 +77,6 @@ typedef struct BlkMigState {
     int64_t total_sector_sum;
     int prev_progress;
     int bulk_completed;
-    long double prev_time_offset;
 } BlkMigState;
 
 static BlkMigState block_mig_state;
@@ -179,13 +177,10 @@ static void alloc_aio_bitmap(BlkMigDevState *bmds)
 
 static void blk_mig_read_cb(void *opaque, int ret)
 {
-    long double curr_time = qemu_get_clock_ns(rt_clock);
     BlkMigBlock *blk = opaque;
 
     blk->ret = ret;
 
-    block_mig_state.prev_time_offset = curr_time;
-
     QSIMPLEQ_INSERT_TAIL(&block_mig_state.blk_list, blk, entry);
     bmds_set_aio_inflight(blk->bmds, blk->sector, blk->nr_sectors, 0);
 
@@ -236,10 +231,6 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
     blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
     qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
 
-    if (block_mig_state.submitted == 0) {
-        block_mig_state.prev_time_offset = qemu_get_clock_ns(rt_clock);
-    }
-
     blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
                                 nr_sectors, blk_mig_read_cb, blk);
     block_mig_state.submitted++;
@@ -382,10 +373,6 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
                 blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
                 qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
 
-                if (block_mig_state.submitted == 0) {
-                    block_mig_state.prev_time_offset = qemu_get_clock_ns(rt_clock);
-                }
-
                 blk->aiocb = bdrv_aio_readv(bmds->bs, sector, &blk->qiov,
                                             nr_sectors, blk_mig_read_cb, blk);
                 block_mig_state.submitted++;
commit bb1fadc444ff967554c41d96cb9dde110e8aece9
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:21 2013 +0100

    migration: cleanup migration (including thread) in the iothread
    
    Perform final cleanup in a bottom half, and add joining the thread to
    the series of cleanup actions.
    
    migrate_fd_error remains for connection error, but it doesn't need
    to cleanup anything anymore.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/migration.h b/include/migration/migration.h
index 3e680af..ed20bed 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -38,6 +38,7 @@ struct MigrationState
     size_t buffer_size;
     size_t buffer_capacity;
     QemuThread thread;
+    QEMUBH *cleanup_bh;
 
     QEMUFile *file;
     int fd;
diff --git a/migration.c b/migration.c
index b40755f..729578b 100644
--- a/migration.c
+++ b/migration.c
@@ -261,8 +261,13 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
 
 /* shared migration helpers */
 
-static void migrate_fd_cleanup(MigrationState *s)
+static void migrate_fd_cleanup(void *opaque)
 {
+    MigrationState *s = opaque;
+
+    qemu_bh_delete(s->cleanup_bh);
+    s->cleanup_bh = NULL;
+
     if (s->file) {
         DPRINTF("closing file\n");
         qemu_fclose(s->file);
@@ -290,15 +295,10 @@ static void migrate_finish_set_state(MigrationState *s, int new_state)
 void migrate_fd_error(MigrationState *s)
 {
     DPRINTF("setting error state\n");
-    migrate_finish_set_state(s, MIG_STATE_ERROR);
-    migrate_fd_cleanup(s);
-}
-
-static void migrate_fd_completed(MigrationState *s)
-{
-    DPRINTF("setting completed state\n");
-    migrate_finish_set_state(s, MIG_STATE_COMPLETED);
-    migrate_fd_cleanup(s);
+    assert(s->file == NULL);
+    s->state = MIG_STATE_ERROR;
+    trace_migrate_set_state(MIG_STATE_ERROR);
+    notifier_list_notify(&migration_state_notifiers, s);
 }
 
 static ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
@@ -325,7 +325,6 @@ static void migrate_fd_cancel(MigrationState *s)
     DPRINTF("cancelling migration\n");
 
     migrate_finish_set_state(s, MIG_STATE_CANCELLED);
-    migrate_fd_cleanup(s);
 }
 
 int migrate_fd_close(MigrationState *s)
@@ -590,6 +589,11 @@ static int buffered_close(void *opaque)
 
     DPRINTF("closing\n");
 
+    qemu_mutex_unlock_iothread();
+    qemu_thread_join(&s->thread);
+    qemu_mutex_lock_iothread();
+    assert(s->state != MIG_STATE_ACTIVE);
+
     return migrate_fd_close(s);
 }
 
@@ -712,13 +716,9 @@ static void *buffered_file_thread(void *opaque)
         }
         buffered_flush(s);
         if (qemu_file_get_error(s->file)) {
-            qemu_mutex_lock_iothread();
-            migrate_fd_error(s);
-            qemu_mutex_unlock_iothread();
+            migrate_finish_set_state(s, MIG_STATE_ERROR);
         } else if (last_round && s->buffer_size == 0) {
-            qemu_mutex_lock_iothread();
-            migrate_fd_completed(s);
-            qemu_mutex_unlock_iothread();
+            migrate_finish_set_state(s, MIG_STATE_COMPLETED);
         }
     }
 
@@ -734,6 +734,7 @@ static void *buffered_file_thread(void *opaque)
             vm_start();
         }
     }
+    qemu_bh_schedule(s->cleanup_bh);
     qemu_mutex_unlock_iothread();
 
     g_free(s->buffer);
@@ -763,9 +764,10 @@ void migrate_fd_connect(MigrationState *s)
 
     s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
 
+    s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup, s);
     s->file = qemu_fopen_ops(s, &buffered_file_ops);
 
     qemu_thread_create(&s->thread, buffered_file_thread, s,
-                       QEMU_THREAD_DETACHED);
+                       QEMU_THREAD_JOINABLE);
     notifier_list_notify(&migration_state_notifiers, s);
 }
commit f4410a5d9926886c36d9fa9fdd969d0469d62724
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:20 2013 +0100

    migration: prepare to access s->state outside critical sections
    
    Accessing s->state outside the big QEMU lock will simplify a bit the
    locking/unlocking of the iothread lock.
    
    We need to keep the lock in migrate_fd_error and migrate_fd_completed,
    however, because they call migrate_fd_cleanup.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index b091532..b40755f 100644
--- a/migration.c
+++ b/migration.c
@@ -279,19 +279,25 @@ static void migrate_fd_cleanup(MigrationState *s)
     notifier_list_notify(&migration_state_notifiers, s);
 }
 
+static void migrate_finish_set_state(MigrationState *s, int new_state)
+{
+    if (__sync_val_compare_and_swap(&s->state, MIG_STATE_ACTIVE,
+                                    new_state) == new_state) {
+        trace_migrate_set_state(new_state);
+    }
+}
+
 void migrate_fd_error(MigrationState *s)
 {
     DPRINTF("setting error state\n");
-    s->state = MIG_STATE_ERROR;
-    trace_migrate_set_state(MIG_STATE_ERROR);
+    migrate_finish_set_state(s, MIG_STATE_ERROR);
     migrate_fd_cleanup(s);
 }
 
 static void migrate_fd_completed(MigrationState *s)
 {
     DPRINTF("setting completed state\n");
-    s->state = MIG_STATE_COMPLETED;
-    trace_migrate_set_state(MIG_STATE_COMPLETED);
+    migrate_finish_set_state(s, MIG_STATE_COMPLETED);
     migrate_fd_cleanup(s);
 }
 
@@ -316,13 +322,9 @@ static ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
 
 static void migrate_fd_cancel(MigrationState *s)
 {
-    if (s->state != MIG_STATE_ACTIVE)
-        return;
-
     DPRINTF("cancelling migration\n");
 
-    s->state = MIG_STATE_CANCELLED;
-    trace_migrate_set_state(MIG_STATE_CANCELLED);
+    migrate_finish_set_state(s, MIG_STATE_CANCELLED);
     migrate_fd_cleanup(s);
 }
 
@@ -657,12 +659,14 @@ static void *buffered_file_thread(void *opaque)
     qemu_mutex_lock_iothread();
     DPRINTF("beginning savevm\n");
     qemu_savevm_state_begin(s->file, &s->params);
+    qemu_mutex_unlock_iothread();
 
     while (s->state == MIG_STATE_ACTIVE) {
         int64_t current_time;
         uint64_t pending_size;
 
         if (s->bytes_xfer < s->xfer_limit) {
+            qemu_mutex_lock_iothread();
             DPRINTF("iterate\n");
             pending_size = qemu_savevm_state_pending(s->file, max_size);
             DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
@@ -678,8 +682,9 @@ static void *buffered_file_thread(void *opaque)
                 qemu_savevm_state_complete(s->file);
                 last_round = true;
             }
+            qemu_mutex_unlock_iothread();
         }
-        qemu_mutex_unlock_iothread();
+
         current_time = qemu_get_clock_ms(rt_clock);
         if (current_time >= initial_time + BUFFER_DELAY) {
             uint64_t transferred_bytes = s->bytes_xfer;
@@ -706,14 +711,18 @@ static void *buffered_file_thread(void *opaque)
             sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
         }
         buffered_flush(s);
-        qemu_mutex_lock_iothread();
         if (qemu_file_get_error(s->file)) {
+            qemu_mutex_lock_iothread();
             migrate_fd_error(s);
+            qemu_mutex_unlock_iothread();
         } else if (last_round && s->buffer_size == 0) {
+            qemu_mutex_lock_iothread();
             migrate_fd_completed(s);
+            qemu_mutex_unlock_iothread();
         }
     }
 
+    qemu_mutex_lock_iothread();
     if (s->state == MIG_STATE_COMPLETED) {
         int64_t end_time = qemu_get_clock_ms(rt_clock);
         s->total_time = end_time - s->total_time;
@@ -725,8 +734,8 @@ static void *buffered_file_thread(void *opaque)
             vm_start();
         }
     }
-
     qemu_mutex_unlock_iothread();
+
     g_free(s->buffer);
     return NULL;
 }
commit c09e5bb1d88ef38986bac7c6ed59dbd732cc4771
Author: Kazuya Saito <saito.kazuya at jp.fujitsu.com>
Date:   Fri Feb 22 17:36:19 2013 +0100

    migration: add migrate_set_state tracepoint
    
    Signed-off-by: Kazuya Saito <saito.kazuya at jp.fujitsu.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 9a234c7..b091532 100644
--- a/migration.c
+++ b/migration.c
@@ -23,6 +23,7 @@
 #include "migration/block.h"
 #include "qemu/thread.h"
 #include "qmp-commands.h"
+#include "trace.h"
 
 //#define DEBUG_MIGRATION
 
@@ -282,6 +283,7 @@ void migrate_fd_error(MigrationState *s)
 {
     DPRINTF("setting error state\n");
     s->state = MIG_STATE_ERROR;
+    trace_migrate_set_state(MIG_STATE_ERROR);
     migrate_fd_cleanup(s);
 }
 
@@ -289,6 +291,7 @@ static void migrate_fd_completed(MigrationState *s)
 {
     DPRINTF("setting completed state\n");
     s->state = MIG_STATE_COMPLETED;
+    trace_migrate_set_state(MIG_STATE_COMPLETED);
     migrate_fd_cleanup(s);
 }
 
@@ -319,6 +322,7 @@ static void migrate_fd_cancel(MigrationState *s)
     DPRINTF("cancelling migration\n");
 
     s->state = MIG_STATE_CANCELLED;
+    trace_migrate_set_state(MIG_STATE_CANCELLED);
     migrate_fd_cleanup(s);
 }
 
@@ -377,8 +381,9 @@ static MigrationState *migrate_init(const MigrationParams *params)
 
     s->bandwidth_limit = bandwidth_limit;
     s->state = MIG_STATE_SETUP;
-    s->total_time = qemu_get_clock_ms(rt_clock);
+    trace_migrate_set_state(MIG_STATE_SETUP);
 
+    s->total_time = qemu_get_clock_ms(rt_clock);
     return s;
 }
 
@@ -738,6 +743,8 @@ static const QEMUFileOps buffered_file_ops = {
 void migrate_fd_connect(MigrationState *s)
 {
     s->state = MIG_STATE_ACTIVE;
+    trace_migrate_set_state(MIG_STATE_ACTIVE);
+
     s->bytes_xfer = 0;
     s->buffer = NULL;
     s->buffer_size = 0;
diff --git a/trace-events b/trace-events
index 3064fc7..8389d83 100644
--- a/trace-events
+++ b/trace-events
@@ -1091,3 +1091,6 @@ css_io_interrupt(int cssid, int ssid, int schid, uint32_t intparm, uint8_t isc,
 # hw/s390x/virtio-ccw.c
 virtio_ccw_interpret_ccw(int cssid, int ssid, int schid, int cmd_code) "VIRTIO-CCW: %x.%x.%04x: interpret command %x"
 virtio_ccw_new_device(int cssid, int ssid, int schid, int devno, const char *devno_mode) "VIRTIO-CCW: add subchannel %x.%x.%04x, devno %04x (%s)"
+
+# migration.c
+migrate_set_state(int new_state) "new state %d"
commit a3fa1d78cbae2259491b17689812edcb643a3b30
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:18 2013 +0100

    migration: do not nest flushing of device data
    
    Completion of migration is currently done with a "nested" loop that
    invokes buffered_flush: migrate_fd_completed is called by
    buffered_file_thread, which calls migrate_fd_cleanup, which calls
    buffered_close (via qemu_fclose), which flushes the buffer.
    
    Simplify this, by reusing the buffered_flush call of buffered_file_thread.
    Then if qemu_savevm_state_complete was called, and the buffer is empty
    (including the QEMUFile buffer, for which we need the previous patch), we
    are done.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 18f97cf..9a234c7 100644
--- a/migration.c
+++ b/migration.c
@@ -262,41 +262,34 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
 
 static void migrate_fd_cleanup(MigrationState *s)
 {
-    int ret = 0;
-
     if (s->file) {
         DPRINTF("closing file\n");
-        ret = qemu_fclose(s->file);
+        qemu_fclose(s->file);
         s->file = NULL;
     }
 
     assert(s->fd == -1);
-    if (ret < 0 && s->state == MIG_STATE_ACTIVE) {
-        s->state = MIG_STATE_ERROR;
-    }
+    assert(s->state != MIG_STATE_ACTIVE);
 
-    if (s->state != MIG_STATE_ACTIVE) {
+    if (s->state != MIG_STATE_COMPLETED) {
         qemu_savevm_state_cancel();
     }
+
+    notifier_list_notify(&migration_state_notifiers, s);
 }
 
 void migrate_fd_error(MigrationState *s)
 {
     DPRINTF("setting error state\n");
     s->state = MIG_STATE_ERROR;
-    notifier_list_notify(&migration_state_notifiers, s);
     migrate_fd_cleanup(s);
 }
 
 static void migrate_fd_completed(MigrationState *s)
 {
     DPRINTF("setting completed state\n");
+    s->state = MIG_STATE_COMPLETED;
     migrate_fd_cleanup(s);
-    if (s->state == MIG_STATE_ACTIVE) {
-        s->state = MIG_STATE_COMPLETED;
-        runstate_set(RUN_STATE_POSTMIGRATE);
-    }
-    notifier_list_notify(&migration_state_notifiers, s);
 }
 
 static ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
@@ -326,8 +319,6 @@ static void migrate_fd_cancel(MigrationState *s)
     DPRINTF("cancelling migration\n");
 
     s->state = MIG_STATE_CANCELLED;
-    notifier_list_notify(&migration_state_notifiers, s);
-
     migrate_fd_cleanup(s);
 }
 
@@ -592,10 +583,6 @@ static int buffered_close(void *opaque)
 
     DPRINTF("closing\n");
 
-    s->xfer_limit = INT_MAX;
-    while (!qemu_file_get_error(s->file) && s->buffer_size) {
-        buffered_flush(s);
-    }
     return migrate_fd_close(s);
 }
 
@@ -658,6 +645,8 @@ static void *buffered_file_thread(void *opaque)
     int64_t initial_time = qemu_get_clock_ms(rt_clock);
     int64_t sleep_time = 0;
     int64_t max_size = 0;
+    int64_t start_time = initial_time;
+    bool old_vm_running = false;
     bool last_round = false;
 
     qemu_mutex_lock_iothread();
@@ -675,23 +664,13 @@ static void *buffered_file_thread(void *opaque)
             if (pending_size && pending_size >= max_size) {
                 qemu_savevm_state_iterate(s->file);
             } else {
-                int old_vm_running = runstate_is_running();
-                int64_t start_time, end_time;
-
                 DPRINTF("done iterating\n");
                 start_time = qemu_get_clock_ms(rt_clock);
                 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
+                old_vm_running = runstate_is_running();
                 vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
+                s->xfer_limit = INT_MAX;
                 qemu_savevm_state_complete(s->file);
-                migrate_fd_completed(s);
-                end_time = qemu_get_clock_ms(rt_clock);
-                s->total_time = end_time - s->total_time;
-                s->downtime = end_time - start_time;
-                if (s->state != MIG_STATE_COMPLETED) {
-                    if (old_vm_running) {
-                        vm_start();
-                    }
-                }
                 last_round = true;
             }
         }
@@ -725,6 +704,20 @@ static void *buffered_file_thread(void *opaque)
         qemu_mutex_lock_iothread();
         if (qemu_file_get_error(s->file)) {
             migrate_fd_error(s);
+        } else if (last_round && s->buffer_size == 0) {
+            migrate_fd_completed(s);
+        }
+    }
+
+    if (s->state == MIG_STATE_COMPLETED) {
+        int64_t end_time = qemu_get_clock_ms(rt_clock);
+        s->total_time = end_time - s->total_time;
+        s->downtime = end_time - start_time;
+        runstate_set(RUN_STATE_POSTMIGRATE);
+    } else {
+        if (old_vm_running) {
+            assert(last_round);
+            vm_start();
         }
     }
 
commit dba433c03a0f5dc22a459435dd89557886298921
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:17 2013 +0100

    migration: simplify error handling
    
    Always use qemu_file_get_error to detect errors, since that is how
    QEMUFile itself drops I/O after an error occurs.  There is no need
    to propagate and check return values all the time.
    
    Also remove the "complete" member, since we know that it is set (via
    migrate_fd_cleanup) only when the state changes.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/migration.h b/include/migration/migration.h
index d121409..3e680af 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -54,7 +54,6 @@ struct MigrationState
     int64_t dirty_bytes_rate;
     bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
     int64_t xbzrle_cache_size;
-    bool complete;
 };
 
 void process_incoming_migration(QEMUFile *f);
diff --git a/migration.c b/migration.c
index 939c3f7..18f97cf 100644
--- a/migration.c
+++ b/migration.c
@@ -525,6 +525,10 @@ static void buffered_flush(MigrationState *s)
 
     DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size);
 
+    if (qemu_file_get_error(s->file)) {
+        s->buffer_size = 0;
+        return;
+    }
     qemu_fflush(s->file);
 
     while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) {
@@ -592,7 +596,6 @@ static int buffered_close(void *opaque)
     while (!qemu_file_get_error(s->file) && s->buffer_size) {
         buffered_flush(s);
     }
-    s->complete = true;
     return migrate_fd_close(s);
 }
 
@@ -656,37 +659,21 @@ static void *buffered_file_thread(void *opaque)
     int64_t sleep_time = 0;
     int64_t max_size = 0;
     bool last_round = false;
-    int ret;
 
     qemu_mutex_lock_iothread();
     DPRINTF("beginning savevm\n");
-    ret = qemu_savevm_state_begin(s->file, &s->params);
-    qemu_mutex_unlock_iothread();
+    qemu_savevm_state_begin(s->file, &s->params);
 
-    while (ret >= 0) {
+    while (s->state == MIG_STATE_ACTIVE) {
         int64_t current_time;
         uint64_t pending_size;
 
-        qemu_mutex_lock_iothread();
-        if (s->state != MIG_STATE_ACTIVE) {
-            DPRINTF("put_ready returning because of non-active state\n");
-            qemu_mutex_unlock_iothread();
-            break;
-        }
-        if (s->complete) {
-            qemu_mutex_unlock_iothread();
-            break;
-        }
         if (s->bytes_xfer < s->xfer_limit) {
             DPRINTF("iterate\n");
             pending_size = qemu_savevm_state_pending(s->file, max_size);
             DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
             if (pending_size && pending_size >= max_size) {
-                ret = qemu_savevm_state_iterate(s->file);
-                if (ret < 0) {
-                    qemu_mutex_unlock_iothread();
-                    break;
-                }
+                qemu_savevm_state_iterate(s->file);
             } else {
                 int old_vm_running = runstate_is_running();
                 int64_t start_time, end_time;
@@ -695,13 +682,8 @@ static void *buffered_file_thread(void *opaque)
                 start_time = qemu_get_clock_ms(rt_clock);
                 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
                 vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
-                ret = qemu_savevm_state_complete(s->file);
-                if (ret < 0) {
-                    qemu_mutex_unlock_iothread();
-                    break;
-                } else {
-                    migrate_fd_completed(s);
-                }
+                qemu_savevm_state_complete(s->file);
+                migrate_fd_completed(s);
                 end_time = qemu_get_clock_ms(rt_clock);
                 s->total_time = end_time - s->total_time;
                 s->downtime = end_time - start_time;
@@ -740,12 +722,13 @@ static void *buffered_file_thread(void *opaque)
             sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
         }
         buffered_flush(s);
-        ret = qemu_file_get_error(s->file);
+        qemu_mutex_lock_iothread();
+        if (qemu_file_get_error(s->file)) {
+            migrate_fd_error(s);
+        }
     }
 
-    if (ret < 0) {
-        migrate_fd_error(s);
-    }
+    qemu_mutex_unlock_iothread();
     g_free(s->buffer);
     return NULL;
 }
@@ -770,7 +753,6 @@ void migrate_fd_connect(MigrationState *s)
     s->expected_downtime = max_downtime/1000000;
 
     s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
-    s->complete = false;
 
     s->file = qemu_fopen_ops(s, &buffered_file_ops);
 
commit 63dfbd7ee03185c181a0791958ec9c8337089b55
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:16 2013 +0100

    migration: use qemu_file_set_error
    
    Remove the return value of buffered_flush, pass it via the error code
    of s->file.  Once this is done, the error can be retrieved simply
    via migrate_fd_close's call to qemu_fclose.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index c5a7f29..939c3f7 100644
--- a/migration.c
+++ b/migration.c
@@ -518,7 +518,7 @@ int64_t migrate_xbzrle_cache_size(void)
 /* migration thread support */
 
 
-static ssize_t buffered_flush(MigrationState *s)
+static void buffered_flush(MigrationState *s)
 {
     size_t offset = 0;
     ssize_t ret = 0;
@@ -545,9 +545,8 @@ static ssize_t buffered_flush(MigrationState *s)
     s->buffer_size -= offset;
 
     if (ret < 0) {
-        return ret;
+        qemu_file_set_error(s->file, ret);
     }
-    return offset;
 }
 
 static int buffered_put_buffer(void *opaque, const uint8_t *buf,
@@ -586,25 +585,15 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf,
 static int buffered_close(void *opaque)
 {
     MigrationState *s = opaque;
-    ssize_t ret = 0;
-    int ret2;
 
     DPRINTF("closing\n");
 
     s->xfer_limit = INT_MAX;
     while (!qemu_file_get_error(s->file) && s->buffer_size) {
-        ret = buffered_flush(s);
-        if (ret < 0) {
-            break;
-        }
-    }
-
-    ret2 = migrate_fd_close(s);
-    if (ret >= 0) {
-        ret = ret2;
+        buffered_flush(s);
     }
     s->complete = true;
-    return ret;
+    return migrate_fd_close(s);
 }
 
 static int buffered_get_fd(void *opaque)
@@ -750,7 +739,8 @@ static void *buffered_file_thread(void *opaque)
             g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
             sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
         }
-        ret = buffered_flush(s);
+        buffered_flush(s);
+        ret = qemu_file_get_error(s->file);
     }
 
     if (ret < 0) {
commit f5821518ed6d49aae9fd0aa6169d2d74bb83054c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:15 2013 +0100

    migration: flush all data to fd when buffered_flush is called
    
    Including data that resided in the QEMUFile's own buffer.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 10ce9fe..c5a7f29 100644
--- a/migration.c
+++ b/migration.c
@@ -525,6 +525,8 @@ static ssize_t buffered_flush(MigrationState *s)
 
     DPRINTF("flushing %zu byte(s) of data\n", s->buffer_size);
 
+    qemu_fflush(s->file);
+
     while (s->bytes_xfer < s->xfer_limit && offset < s->buffer_size) {
         size_t to_send = MIN(s->buffer_size - offset, s->xfer_limit - s->bytes_xfer);
         ret = migrate_fd_put_buffer(s, s->buffer + offset, to_send);
commit 4eb938102b3d533e142de23e255e46da1326fc5a
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:14 2013 +0100

    qemu-file: temporarily expose qemu_file_set_error and qemu_fflush
    
    Right now, migration cannot entirely rely on QEMUFile's automatic
    drop of I/O after an error, because it does its "real" I/O outside
    the put_buffer callback.  To fix this until buffering is gone, expose
    qemu_file_set_error which we will use in buffered_flush.
    
    Similarly, buffered_flush is not a complete flush because some data may
    still reside in the QEMUFile's own buffer.  This somewhat complicates the
    process of closing the migration thread.  Again, when buffering is gone
    buffered_flush will disappear and calling qemu_fflush will not be needed;
    in the meanwhile, we expose the function for use in migration.c.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 46fc11d..5e0c287 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -82,6 +82,7 @@ QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
 int qemu_get_fd(QEMUFile *f);
 int qemu_fclose(QEMUFile *f);
 int64_t qemu_ftell(QEMUFile *f);
+void qemu_fflush(QEMUFile *f);
 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
 void qemu_put_byte(QEMUFile *f, int v);
 
@@ -113,6 +114,7 @@ int qemu_file_rate_limit(QEMUFile *f);
 int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate);
 int64_t qemu_file_get_rate_limit(QEMUFile *f);
 int qemu_file_get_error(QEMUFile *f);
+void qemu_file_set_error(QEMUFile *f, int ret);
 
 static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv)
 {
diff --git a/savevm.c b/savevm.c
index a1690b4..e10a045 100644
--- a/savevm.c
+++ b/savevm.c
@@ -443,7 +443,7 @@ int qemu_file_get_error(QEMUFile *f)
     return f->last_error;
 }
 
-static void qemu_file_set_error(QEMUFile *f, int ret)
+void qemu_file_set_error(QEMUFile *f, int ret)
 {
     if (f->last_error == 0) {
         f->last_error = ret;
@@ -453,7 +453,7 @@ static void qemu_file_set_error(QEMUFile *f, int ret)
 /** Flushes QEMUFile buffer
  *
  */
-static void qemu_fflush(QEMUFile *f)
+void qemu_fflush(QEMUFile *f)
 {
     int ret = 0;
 
commit 47c8c17af883b5bd0f147cfcec8d7ef8ff76023b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:13 2013 +0100

    migration: use qemu_file_set_error to pass error codes back to qemu_savevm_state
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index b19ec95..6578782 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -73,10 +73,10 @@ void do_info_snapshots(Monitor *mon, const QDict *qdict);
 void qemu_announce_self(void);
 
 bool qemu_savevm_state_blocked(Error **errp);
-int qemu_savevm_state_begin(QEMUFile *f,
-                            const MigrationParams *params);
+void qemu_savevm_state_begin(QEMUFile *f,
+                             const MigrationParams *params);
 int qemu_savevm_state_iterate(QEMUFile *f);
-int qemu_savevm_state_complete(QEMUFile *f);
+void qemu_savevm_state_complete(QEMUFile *f);
 void qemu_savevm_state_cancel(void);
 uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size);
 int qemu_loadvm_state(QEMUFile *f);
diff --git a/savevm.c b/savevm.c
index a681177..a1690b4 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1579,8 +1579,8 @@ bool qemu_savevm_state_blocked(Error **errp)
     return false;
 }
 
-int qemu_savevm_state_begin(QEMUFile *f,
-                            const MigrationParams *params)
+void qemu_savevm_state_begin(QEMUFile *f,
+                             const MigrationParams *params)
 {
     SaveStateEntry *se;
     int ret;
@@ -1620,11 +1620,10 @@ int qemu_savevm_state_begin(QEMUFile *f,
 
         ret = se->ops->save_live_setup(f, se->opaque);
         if (ret < 0) {
-            return ret;
+            qemu_file_set_error(f, ret);
+            break;
         }
     }
-    ret = qemu_file_get_error(f);
-    return ret;
 }
 
 /*
@@ -1658,6 +1657,9 @@ int qemu_savevm_state_iterate(QEMUFile *f)
         ret = se->ops->save_live_iterate(f, se->opaque);
         trace_savevm_section_end(se->section_id);
 
+        if (ret < 0) {
+            qemu_file_set_error(f, ret);
+        }
         if (ret <= 0) {
             /* Do not proceed to the next vmstate before this one reported
                completion of the current stage. This serializes the migration
@@ -1666,14 +1668,10 @@ int qemu_savevm_state_iterate(QEMUFile *f)
             break;
         }
     }
-    if (ret != 0) {
-        return ret;
-    }
-    ret = qemu_file_get_error(f);
     return ret;
 }
 
-int qemu_savevm_state_complete(QEMUFile *f)
+void qemu_savevm_state_complete(QEMUFile *f)
 {
     SaveStateEntry *se;
     int ret;
@@ -1697,7 +1695,8 @@ int qemu_savevm_state_complete(QEMUFile *f)
         ret = se->ops->save_live_complete(f, se->opaque);
         trace_savevm_section_end(se->section_id);
         if (ret < 0) {
-            return ret;
+            qemu_file_set_error(f, ret);
+            return;
         }
     }
 
@@ -1725,8 +1724,6 @@ int qemu_savevm_state_complete(QEMUFile *f)
     }
 
     qemu_put_byte(f, QEMU_VM_EOF);
-
-    return qemu_file_get_error(f);
 }
 
 uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size)
@@ -1771,26 +1768,21 @@ static int qemu_savevm_state(QEMUFile *f)
         return -EINVAL;
     }
 
-    ret = qemu_savevm_state_begin(f, &params);
-    if (ret < 0)
-        goto out;
-
-    do {
-        ret = qemu_savevm_state_iterate(f);
-        if (ret < 0)
-            goto out;
-    } while (ret == 0);
-
-    ret = qemu_savevm_state_complete(f);
+    qemu_savevm_state_begin(f, &params);
+    while (qemu_file_get_error(f) == 0) {
+        if (qemu_savevm_state_iterate(f) > 0) {
+            break;
+        }
+    }
 
-out:
+    ret = qemu_file_get_error(f);
     if (ret == 0) {
+        qemu_savevm_state_complete(f);
         ret = qemu_file_get_error(f);
     }
     if (ret != 0) {
         qemu_savevm_state_cancel();
     }
-
     return ret;
 }
 
commit 93bf21044c38134bc7d35577b675d9f2bdcb8419
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:12 2013 +0100

    qemu-file: pass errno from qemu_fflush via f->last_error
    
    This is done by almost all callers of qemu_fflush, move the code
    directly to qemu_fflush.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index 4302903..a681177 100644
--- a/savevm.c
+++ b/savevm.c
@@ -453,13 +453,13 @@ static void qemu_file_set_error(QEMUFile *f, int ret)
 /** Flushes QEMUFile buffer
  *
  */
-static int qemu_fflush(QEMUFile *f)
+static void qemu_fflush(QEMUFile *f)
 {
     int ret = 0;
 
-    if (!f->ops->put_buffer)
-        return 0;
-
+    if (!f->ops->put_buffer) {
+        return;
+    }
     if (f->is_write && f->buf_index > 0) {
         ret = f->ops->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index);
         if (ret >= 0) {
@@ -467,7 +467,9 @@ static int qemu_fflush(QEMUFile *f)
         }
         f->buf_index = 0;
     }
-    return ret;
+    if (ret < 0) {
+        qemu_file_set_error(f, ret);
+    }
 }
 
 static void qemu_fill_buffer(QEMUFile *f)
@@ -518,7 +520,8 @@ int qemu_get_fd(QEMUFile *f)
 int qemu_fclose(QEMUFile *f)
 {
     int ret;
-    ret = qemu_fflush(f);
+    qemu_fflush(f);
+    ret = qemu_file_get_error(f);
 
     if (f->ops->close) {
         int ret2 = f->ops->close(f->opaque);
@@ -560,9 +563,8 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
         buf += l;
         size -= l;
         if (f->buf_index >= IO_BUF_SIZE) {
-            int ret = qemu_fflush(f);
-            if (ret < 0) {
-                qemu_file_set_error(f, ret);
+            qemu_fflush(f);
+            if (qemu_file_get_error(f)) {
                 break;
             }
         }
@@ -584,10 +586,7 @@ void qemu_put_byte(QEMUFile *f, int v)
     f->buf[f->buf_index++] = v;
     f->is_write = 1;
     if (f->buf_index >= IO_BUF_SIZE) {
-        int ret = qemu_fflush(f);
-        if (ret < 0) {
-            qemu_file_set_error(f, ret);
-        }
+        qemu_fflush(f);
     }
 }
 
commit d418cf57a3e699746ef0bfa772bbe8c7e17cebb5
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:11 2013 +0100

    block-migration: remove useless calls to blk_mig_cleanup
    
    Now that the cancel callback is called consistently for all errors,
    we can avoid doing its work in the other callbacks.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/block-migration.c b/block-migration.c
index 43ab202..e6c917d 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -524,16 +524,10 @@ static int block_save_setup(QEMUFile *f, void *opaque)
     set_dirty_tracking(1);
 
     ret = flush_blks(f);
-    if (ret) {
-        blk_mig_cleanup();
-        return ret;
-    }
-
     blk_mig_reset_dirty_cursor();
-
     qemu_put_be64(f, BLK_MIG_FLAG_EOS);
 
-    return 0;
+    return ret;
 }
 
 static int block_save_iterate(QEMUFile *f, void *opaque)
@@ -546,7 +540,6 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
 
     ret = flush_blks(f);
     if (ret) {
-        blk_mig_cleanup();
         return ret;
     }
 
@@ -564,20 +557,18 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
             }
         } else {
             ret = blk_mig_save_dirty_block(f, 1);
+            if (ret < 0) {
+                return ret;
+            }
             if (ret != 0) {
                 /* no more dirty blocks */
                 break;
             }
         }
     }
-    if (ret < 0) {
-        blk_mig_cleanup();
-        return ret;
-    }
 
     ret = flush_blks(f);
     if (ret) {
-        blk_mig_cleanup();
         return ret;
     }
 
@@ -595,7 +586,6 @@ static int block_save_complete(QEMUFile *f, void *opaque)
 
     ret = flush_blks(f);
     if (ret) {
-        blk_mig_cleanup();
         return ret;
     }
 
@@ -607,12 +597,11 @@ static int block_save_complete(QEMUFile *f, void *opaque)
 
     do {
         ret = blk_mig_save_dirty_block(f, 0);
+        if (ret < 0) {
+            return ret;
+        }
     } while (ret == 0);
 
-    blk_mig_cleanup();
-    if (ret < 0) {
-        return ret;
-    }
     /* report completion */
     qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS);
 
@@ -620,6 +609,7 @@ static int block_save_complete(QEMUFile *f, void *opaque)
 
     qemu_put_be64(f, BLK_MIG_FLAG_EOS);
 
+    blk_mig_cleanup();
     return 0;
 }
 
commit 04943ebaa9e4f5f9ac080198a7b0d25c6d7ac444
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:10 2013 +0100

    migration: push qemu_savevm_state_cancel out of qemu_savevm_state_*
    
    This is useful, because it lets us keep the cancellation callbacks
    inside the big lock while pushing the others out.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index a8a53ef..4302903 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1621,17 +1621,11 @@ int qemu_savevm_state_begin(QEMUFile *f,
 
         ret = se->ops->save_live_setup(f, se->opaque);
         if (ret < 0) {
-            qemu_savevm_state_cancel();
             return ret;
         }
     }
     ret = qemu_file_get_error(f);
-    if (ret != 0) {
-        qemu_savevm_state_cancel();
-    }
-
     return ret;
-
 }
 
 /*
@@ -1677,9 +1671,6 @@ int qemu_savevm_state_iterate(QEMUFile *f)
         return ret;
     }
     ret = qemu_file_get_error(f);
-    if (ret != 0) {
-        qemu_savevm_state_cancel();
-    }
     return ret;
 }
 
@@ -1778,8 +1769,7 @@ static int qemu_savevm_state(QEMUFile *f)
     };
 
     if (qemu_savevm_state_blocked(NULL)) {
-        ret = -EINVAL;
-        goto out;
+        return -EINVAL;
     }
 
     ret = qemu_savevm_state_begin(f, &params);
@@ -1798,6 +1788,9 @@ out:
     if (ret == 0) {
         ret = qemu_file_get_error(f);
     }
+    if (ret != 0) {
+        qemu_savevm_state_cancel();
+    }
 
     return ret;
 }
commit 7a2c17216cd5ae4c22844123b8e9360d517932f8
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:09 2013 +0100

    migration: move more error handling to migrate_fd_cleanup
    
    The next patch will add more cases where qemu_savevm_state_cancel
    needs to be called; prepare for that already, the function can be
    called twice with no ill effect.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 65e8583..10ce9fe 100644
--- a/migration.c
+++ b/migration.c
@@ -260,7 +260,7 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
 
 /* shared migration helpers */
 
-static int migrate_fd_cleanup(MigrationState *s)
+static void migrate_fd_cleanup(MigrationState *s)
 {
     int ret = 0;
 
@@ -271,7 +271,13 @@ static int migrate_fd_cleanup(MigrationState *s)
     }
 
     assert(s->fd == -1);
-    return ret;
+    if (ret < 0 && s->state == MIG_STATE_ACTIVE) {
+        s->state = MIG_STATE_ERROR;
+    }
+
+    if (s->state != MIG_STATE_ACTIVE) {
+        qemu_savevm_state_cancel();
+    }
 }
 
 void migrate_fd_error(MigrationState *s)
@@ -285,9 +291,8 @@ void migrate_fd_error(MigrationState *s)
 static void migrate_fd_completed(MigrationState *s)
 {
     DPRINTF("setting completed state\n");
-    if (migrate_fd_cleanup(s) < 0) {
-        s->state = MIG_STATE_ERROR;
-    } else {
+    migrate_fd_cleanup(s);
+    if (s->state == MIG_STATE_ACTIVE) {
         s->state = MIG_STATE_COMPLETED;
         runstate_set(RUN_STATE_POSTMIGRATE);
     }
@@ -322,7 +327,6 @@ static void migrate_fd_cancel(MigrationState *s)
 
     s->state = MIG_STATE_CANCELLED;
     notifier_list_notify(&migration_state_notifiers, s);
-    qemu_savevm_state_cancel();
 
     migrate_fd_cleanup(s);
 }
commit 891518abd804401978e402d588733e282be960ad
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:08 2013 +0100

    migration: always use vm_stop_force_state
    
    vm_stop_force_state does:
    
        if (runstate_is_running()) {
            vm_stop(state);
        } else {
            runstate_set(state);
        }
    
    migration.c does:
    
        if (runstate_is_running()) {
            vm_stop(state);
        } else {
            vm_stop_force_state(state);
        }
    
    The code run is the same even if we always use vm_stop_force_state in
    migration.c.
    
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index ba8b647..65e8583 100644
--- a/migration.c
+++ b/migration.c
@@ -699,11 +699,7 @@ static void *buffered_file_thread(void *opaque)
                 DPRINTF("done iterating\n");
                 start_time = qemu_get_clock_ms(rt_clock);
                 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
-                if (old_vm_running) {
-                    vm_stop(RUN_STATE_FINISH_MIGRATE);
-                } else {
-                    vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
-                }
+                vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
                 ret = qemu_savevm_state_complete(s->file);
                 if (ret < 0) {
                     qemu_mutex_unlock_iothread();
commit 5da5aad068def65b5e278a6380192d4bfe279585
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 17:36:07 2013 +0100

    migration: simplify while loop
    
    Unify the goto around the loop, with the exit condition at the end of it.
    Both can be expressed as "while (ret >= 0)".
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 11725ae..ba8b647 100644
--- a/migration.c
+++ b/migration.c
@@ -666,14 +666,9 @@ static void *buffered_file_thread(void *opaque)
     qemu_mutex_lock_iothread();
     DPRINTF("beginning savevm\n");
     ret = qemu_savevm_state_begin(s->file, &s->params);
-    if (ret < 0) {
-        DPRINTF("failed, %d\n", ret);
-        qemu_mutex_unlock_iothread();
-        goto out;
-    }
     qemu_mutex_unlock_iothread();
 
-    while (true) {
+    while (ret >= 0) {
         int64_t current_time;
         uint64_t pending_size;
 
@@ -754,12 +749,8 @@ static void *buffered_file_thread(void *opaque)
             sleep_time += qemu_get_clock_ms(rt_clock) - current_time;
         }
         ret = buffered_flush(s);
-        if (ret < 0) {
-            break;
-        }
     }
 
-out:
     if (ret < 0) {
         migrate_fd_error(s);
     }
commit 0d95fda86b0d69fc4010f6bb37aa4fd38f1addff
Author: Dillon Amburgey <dillona at dillona.com>
Date:   Thu Jan 3 22:10:26 2013 -0500

    linux-user: Add more sparc syscall numbers
    
    Signed-off-by: Dillon Amburgey <dillona at dillona.com>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/sparc/syscall_nr.h b/linux-user/sparc/syscall_nr.h
index 061711c..534e6e9 100644
--- a/linux-user/sparc/syscall_nr.h
+++ b/linux-user/sparc/syscall_nr.h
@@ -200,6 +200,8 @@
 #define TARGET_NR__newselect         230 /* Linux Specific                              */
 #define TARGET_NR_time               231 /* Linux Specific                              */
 #define TARGET_NR_stime              233 /* Linux Specific                              */
+#define TARGET_NR_statfs64           234 /* Linux Specific                              */
+#define TARGET_NR_fstatfs64          235 /* Linux Specific                              */
 #define TARGET_NR__llseek            236 /* Linux Specific                              */
 #define TARGET_NR_mlock              237
 #define TARGET_NR_munlock            238
commit f2b79ce9dc65753c6833921dd5ef6fa59632851f
Author: Dillon Amburgey <dillona at dillona.com>
Date:   Sat Feb 2 18:04:48 2013 -0500

    linux-user: Support setgroups syscall with no groups
    
    Signed-off-by: Dillon Amburgey <dillona at dillona.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index c7fcfc0..1729446 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7680,18 +7680,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         {
             int gidsetsize = arg1;
             target_id *target_grouplist;
-            gid_t *grouplist;
+            gid_t *grouplist = NULL;
             int i;
-
-            grouplist = alloca(gidsetsize * sizeof(gid_t));
-            target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
-            if (!target_grouplist) {
-                ret = -TARGET_EFAULT;
-                goto fail;
+            if (gidsetsize) {
+                grouplist = alloca(gidsetsize * sizeof(gid_t));
+                target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
+                if (!target_grouplist) {
+                    ret = -TARGET_EFAULT;
+                    goto fail;
+                }
+                for (i = 0; i < gidsetsize; i++) {
+                    grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
+                }
+                unlock_user(target_grouplist, arg2, 0);
             }
-            for(i = 0;i < gidsetsize; i++)
-                grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
-            unlock_user(target_grouplist, arg2, 0);
             ret = get_errno(setgroups(gidsetsize, grouplist));
         }
         break;
commit bfb669f39f2ecd854992924ced20b00163509043
Author: John Rigby <john.rigby at linaro.org>
Date:   Sat Feb 23 16:14:08 2013 -0700

    linux-user: fix futex strace of FUTEX_CLOCK_REALTIME
    
    Handle same as existing FUTEX_PRIVATE_FLAG.
    
    Signed-off-by: John Rigby <john.rigby at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 9a18146..0fbae3c 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1498,6 +1498,12 @@ if( cmd == val ) { \
         cmd &= ~FUTEX_PRIVATE_FLAG;
     }
 #endif
+#ifdef FUTEX_CLOCK_REALTIME
+    if (cmd & FUTEX_CLOCK_REALTIME) {
+        gemu_log("FUTEX_CLOCK_REALTIME|");
+        cmd &= ~FUTEX_CLOCK_REALTIME;
+    }
+#endif
     print_op(FUTEX_WAIT)
     print_op(FUTEX_WAKE)
     print_op(FUTEX_FD)
commit cce246e0a21577bb2372ab3a7d6789371e087de9
Author: John Rigby <john.rigby at linaro.org>
Date:   Sat Feb 23 16:14:07 2013 -0700

    linux-user/syscall.c: handle FUTEX_WAIT_BITSET in do_futex
    
    Upstream libc has recently changed to start using
    FUTEX_WAIT_BITSET instead of FUTEX_WAIT and this
    is causing do_futex to return -TARGET_ENOSYS.
    
    Pass bitset in val3 to sys_futex which will be
    ignored by kernel for the FUTEX_WAIT case.
    
    Signed-off-by: John Rigby <john.rigby at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 19630ea..c7fcfc0 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4922,6 +4922,7 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
 #endif
     switch (base_op) {
     case FUTEX_WAIT:
+    case FUTEX_WAIT_BITSET:
         if (timeout) {
             pts = &ts;
             target_to_host_timespec(pts, timeout);
@@ -4929,7 +4930,7 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
             pts = NULL;
         }
         return get_errno(sys_futex(g2h(uaddr), op, tswap32(val),
-                         pts, NULL, 0));
+                         pts, NULL, val3));
     case FUTEX_WAKE:
         return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
     case FUTEX_FD:
commit d95ec14fd20ff69881ab26e7ebd1dab4eb851d97
Author: Laurent Vivier <Laurent at Vivier.EU>
Date:   Mon Dec 31 21:00:11 2012 +0100

    linux-user: improve print_fcntl()
    
    Signed-off-by: Laurent Vivier <laurent at vivier.eu>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 4e91a6e..9a18146 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -462,18 +462,6 @@ UNUSED static struct flags mmap_flags[] = {
     FLAG_END,
 };
 
-UNUSED static struct flags fcntl_flags[] = {
-    FLAG_TARGET(F_DUPFD),
-    FLAG_TARGET(F_GETFD),
-    FLAG_TARGET(F_SETFD),
-    FLAG_TARGET(F_GETFL),
-    FLAG_TARGET(F_SETFL),
-    FLAG_TARGET(F_GETLK),
-    FLAG_TARGET(F_SETLK),
-    FLAG_TARGET(F_SETLKW),
-    FLAG_END,
-};
-
 UNUSED static struct flags clone_flags[] = {
     FLAG_GENERIC(CLONE_VM),
     FLAG_GENERIC(CLONE_FS),
@@ -867,12 +855,85 @@ print_fcntl(const struct syscallname *name,
 {
     print_syscall_prologue(name);
     print_raw_param("%d", arg0, 0);
-    print_flags(fcntl_flags, arg1, 0);
-    /*
-     * TODO: check flags and print following argument only
-     *       when needed.
-     */
-    print_pointer(arg2, 1);
+    switch(arg1) {
+    case TARGET_F_DUPFD:
+        gemu_log("F_DUPFD,");
+        print_raw_param(TARGET_ABI_FMT_ld, arg2, 1);
+        break;
+    case TARGET_F_GETFD:
+        gemu_log("F_GETFD");
+        break;
+    case TARGET_F_SETFD:
+        gemu_log("F_SETFD,");
+        print_raw_param(TARGET_ABI_FMT_ld, arg2, 1);
+        break;
+    case TARGET_F_GETFL:
+        gemu_log("F_GETFL");
+        break;
+    case TARGET_F_SETFL:
+        gemu_log("F_SETFL,");
+        print_open_flags(arg2, 1);
+        break;
+    case TARGET_F_GETLK:
+        gemu_log("F_GETLK,");
+        print_pointer(arg2, 1);
+        break;
+    case TARGET_F_SETLK:
+        gemu_log("F_SETLK,");
+        print_pointer(arg2, 1);
+        break;
+    case TARGET_F_SETLKW:
+        gemu_log("F_SETLKW,");
+        print_pointer(arg2, 1);
+        break;
+    case TARGET_F_GETOWN:
+        gemu_log("F_GETOWN");
+        break;
+    case TARGET_F_SETOWN:
+        gemu_log("F_SETOWN,");
+        print_raw_param(TARGET_ABI_FMT_ld, arg2, 0);
+        break;
+    case TARGET_F_GETSIG:
+        gemu_log("F_GETSIG");
+        break;
+    case TARGET_F_SETSIG:
+        gemu_log("F_SETSIG,");
+        print_raw_param(TARGET_ABI_FMT_ld, arg2, 0);
+        break;
+#if TARGET_ABI_BITS == 32
+    case TARGET_F_GETLK64:
+        gemu_log("F_GETLK64,");
+        print_pointer(arg2, 1);
+        break;
+    case TARGET_F_SETLK64:
+        gemu_log("F_SETLK64,");
+        print_pointer(arg2, 1);
+        break;
+    case TARGET_F_SETLKW64:
+        gemu_log("F_SETLKW64,");
+        print_pointer(arg2, 1);
+        break;
+#endif
+    case TARGET_F_SETLEASE:
+        gemu_log("F_SETLEASE,");
+        print_raw_param(TARGET_ABI_FMT_ld, arg2, 0);
+        break;
+    case TARGET_F_GETLEASE:
+        gemu_log("F_GETLEASE");
+        break;
+    case TARGET_F_DUPFD_CLOEXEC:
+        gemu_log("F_DUPFD_CLOEXEC,");
+        print_raw_param(TARGET_ABI_FMT_ld, arg2, 1);
+        break;
+    case TARGET_F_NOTIFY:
+        gemu_log("F_NOTIFY,");
+        print_raw_param(TARGET_ABI_FMT_ld, arg2, 0);
+        break;
+    default:
+        print_raw_param(TARGET_ABI_FMT_ld, arg1, 0);
+        print_pointer(arg2, 1);
+        break;
+    }
     print_syscall_epilogue(name);
 }
 #define print_fcntl64   print_fcntl
commit ec00b51a6c3e6c515c52e6e4564d915ee1f19022
Author: Dillon Amburgey <dillona at dillona.com>
Date:   Wed Jan 2 21:06:35 2013 -0500

    linux-user: Add Alpha socket constants
    
    Without these, some networking programs will not work
    
    Signed-off-by: Dillon Amburgey <dillona at dillona.com>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/socket.h b/linux-user/socket.h
index 93d4782..339cae5 100644
--- a/linux-user/socket.h
+++ b/linux-user/socket.h
@@ -87,6 +87,75 @@
 
 	#define TARGET_SOCK_MAX (SOCK_PACKET + 1)
 
+#elif defined(TARGET_ALPHA)
+
+    /* For setsockopt(2) */
+    #define TARGET_SOL_SOCKET   0xffff
+
+    #define TARGET_SO_DEBUG 0x0001
+    #define TARGET_SO_REUSEADDR 0x0004
+    #define TARGET_SO_KEEPALIVE 0x0008
+    #define TARGET_SO_DONTROUTE 0x0010
+    #define TARGET_SO_BROADCAST 0x0020
+    #define TARGET_SO_LINGER    0x0080
+    #define TARGET_SO_OOBINLINE 0x0100
+    /* To add :#define TARGET_SO_REUSEPORT 0x0200 */
+
+    #define TARGET_SO_TYPE      0x1008
+    #define TARGET_SO_ERROR 0x1007
+    #define TARGET_SO_SNDBUF    0x1001
+    #define TARGET_SO_RCVBUF    0x1002
+    #define TARGET_SO_SNDBUFFORCE   0x100a
+    #define TARGET_SO_RCVBUFFORCE   0x100b
+    #define TARGET_SO_RCVLOWAT  0x1010
+    #define TARGET_SO_SNDLOWAT  0x1011
+    #define TARGET_SO_RCVTIMEO  0x1012
+    #define TARGET_SO_SNDTIMEO  0x1013
+    #define TARGET_SO_ACCEPTCONN    0x1014
+    #define TARGET_SO_PROTOCOL  0x1028
+    #define TARGET_SO_DOMAIN    0x1029
+
+    /* linux-specific, might as well be the same as on i386 */
+    #define TARGET_SO_NO_CHECK  11
+    #define TARGET_SO_PRIORITY  12
+    #define TARGET_SO_BSDCOMPAT 14
+
+    #define TARGET_SO_PASSCRED  17
+    #define TARGET_SO_PEERCRED  18
+    #define TARGET_SO_BINDTODEVICE 25
+
+    /* Socket filtering */
+    #define TARGET_SO_ATTACH_FILTER        26
+    #define TARGET_SO_DETACH_FILTER        27
+
+    #define TARGET_SO_PEERNAME      28
+    #define TARGET_SO_TIMESTAMP     29
+    #define TARGET_SCM_TIMESTAMP        TARGET_SO_TIMESTAMP
+
+    #define TARGET_SO_PEERSEC       30
+    #define TARGET_SO_PASSSEC       34
+    #define TARGET_SO_TIMESTAMPNS       35
+    #define TARGET_SCM_TIMESTAMPNS      TARGET_SO_TIMESTAMPNS
+
+    /* Security levels - as per NRL IPv6 - don't actually do anything */
+    #define TARGET_SO_SECURITY_AUTHENTICATION       19
+    #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 20
+    #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK       21
+
+    #define TARGET_SO_MARK          36
+
+    #define TARGET_SO_TIMESTAMPING      37
+    #define TARGET_SCM_TIMESTAMPING TARGET_SO_TIMESTAMPING
+
+    #define TARGET_SO_RXQ_OVFL             40
+
+    #define TARGET_SO_WIFI_STATUS       41
+    #define TARGET_SCM_WIFI_STATUS      TARGET_SO_WIFI_STATUS
+    #define TARGET_SO_PEEK_OFF      42
+
+    /* Instruct lower device to use last 4-bytes of skb data as FCS */
+    #define TARGET_SO_NOFCS     43
+
 #else
 
 	/* For setsockopt(2) */
commit fa3889162ff724d09eb6b6bd06ba54769100a77f
Merge: 6e72a00 a4960ef
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Sun Mar 10 20:39:17 2013 -0500

    Merge remote-tracking branch 'origin/master' into staging
    
    * origin/master: (75 commits)
      tcg: Don't make exitreq flag a local temporary
      Makefile: Add subdir dependency on config-devices-all.mak
      make_device_config.sh: Emit dependency file to directory where included
      Revert "make_device_config.sh: Fix target path in generated dependency file"
      s390/virtio-ccw: remove redundant call to blockdev_mark_auto_del
      s390/css: Fix subchannel detection
      Allow virtio-net features for legacy s390 virtio bus
      s390: virtio-ccw maintainer
      s390: simplify kvm cpu init
      pseries: Add compatible property to root of device tree
      target-ppc: Move CPU aliases out of translate_init.c
      target-ppc: Report CPU aliases for QMP
      target-ppc: List alias names alongside CPU models
      target-ppc: Make host CPU a subclass of the host's CPU model
      PPC: xnu kernel expects FLUSH to be cleared on STOP
      PPC: Fix dma interrupt
      target-ppc: Fix PPC_DUMP_SPR_ACCESS build
      target-ppc: Synchronize FPU state with KVM
      target-ppc: Add mechanism for synchronizing SPRs with KVM
      Save memory allocation in the elf loader
      ...

diff --cc hw/ppc/spapr.c
index 2709c66,0000000..fd24113
mode 100644,000000..100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@@ -1,963 -1,0 +1,964 @@@
 +/*
 + * 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/sysemu.h"
 +#include "hw/hw.h"
 +#include "elf.h"
 +#include "net/net.h"
 +#include "sysemu/blockdev.h"
 +#include "sysemu/cpus.h"
 +#include "sysemu/kvm.h"
 +#include "kvm_ppc.h"
 +
 +#include "hw/boards.h"
 +#include "hw/ppc.h"
 +#include "hw/loader.h"
 +
 +#include "hw/spapr.h"
 +#include "hw/spapr_vio.h"
 +#include "hw/spapr_pci.h"
 +#include "hw/xics.h"
 +#include "hw/pci/msi.h"
 +
 +#include "sysemu/kvm.h"
 +#include "kvm_ppc.h"
 +#include "hw/pci/pci.h"
 +
 +#include "exec/address-spaces.h"
 +#include "hw/usb.h"
 +#include "qemu/config-file.h"
 +
 +#include <libfdt.h>
 +
 +/* SLOF memory layout:
 + *
 + * SLOF raw image loaded at 0, copies its romfs right below the flat
 + * device-tree, then position SLOF itself 31M below that
 + *
 + * So we set FW_OVERHEAD to 40MB which should account for all of that
 + * and more
 + *
 + * We load our kernel at 4M, leaving space for SLOF initial image
 + */
 +#define FDT_MAX_SIZE            0x10000
 +#define RTAS_MAX_SIZE           0x10000
 +#define FW_MAX_SIZE             0x400000
 +#define FW_FILE_NAME            "slof.bin"
 +#define FW_OVERHEAD             0x2800000
 +#define KERNEL_LOAD_ADDR        FW_MAX_SIZE
 +
 +#define MIN_RMA_SLOF            128UL
 +
 +#define TIMEBASE_FREQ           512000000ULL
 +
 +#define MAX_CPUS                256
 +#define XICS_IRQS               1024
 +
 +#define PHANDLE_XICP            0x00001111
 +
 +#define HTAB_SIZE(spapr)        (1ULL << ((spapr)->htab_shift))
 +
 +sPAPREnvironment *spapr;
 +
 +int spapr_allocate_irq(int hint, bool lsi)
 +{
 +    int irq;
 +
 +    if (hint) {
 +        irq = hint;
 +        /* FIXME: we should probably check for collisions somehow */
 +    } else {
 +        irq = spapr->next_irq++;
 +    }
 +
 +    /* Configure irq type */
 +    if (!xics_get_qirq(spapr->icp, irq)) {
 +        return 0;
 +    }
 +
 +    xics_set_irq_type(spapr->icp, irq, lsi);
 +
 +    return irq;
 +}
 +
 +/* Allocate block of consequtive IRQs, returns a number of the first */
 +int spapr_allocate_irq_block(int num, bool lsi)
 +{
 +    int first = -1;
 +    int i;
 +
 +    for (i = 0; i < num; ++i) {
 +        int irq;
 +
 +        irq = spapr_allocate_irq(0, lsi);
 +        if (!irq) {
 +            return -1;
 +        }
 +
 +        if (0 == i) {
 +            first = irq;
 +        }
 +
 +        /* If the above doesn't create a consecutive block then that's
 +         * an internal bug */
 +        assert(irq == (first + i));
 +    }
 +
 +    return first;
 +}
 +
 +static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
 +{
 +    int ret = 0, offset;
 +    CPUPPCState *env;
 +    CPUState *cpu;
 +    char cpu_model[32];
 +    int smt = kvmppc_smt_threads();
 +    uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
 +
 +    assert(spapr->cpu_model);
 +
 +    for (env = first_cpu; env != NULL; env = env->next_cpu) {
 +        cpu = CPU(ppc_env_get_cpu(env));
 +        uint32_t associativity[] = {cpu_to_be32(0x5),
 +                                    cpu_to_be32(0x0),
 +                                    cpu_to_be32(0x0),
 +                                    cpu_to_be32(0x0),
 +                                    cpu_to_be32(cpu->numa_node),
 +                                    cpu_to_be32(cpu->cpu_index)};
 +
 +        if ((cpu->cpu_index % smt) != 0) {
 +            continue;
 +        }
 +
 +        snprintf(cpu_model, 32, "/cpus/%s@%x", spapr->cpu_model,
 +                 cpu->cpu_index);
 +
 +        offset = fdt_path_offset(fdt, cpu_model);
 +        if (offset < 0) {
 +            return offset;
 +        }
 +
 +        if (nb_numa_nodes > 1) {
 +            ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity,
 +                              sizeof(associativity));
 +            if (ret < 0) {
 +                return ret;
 +            }
 +        }
 +
 +        ret = fdt_setprop(fdt, offset, "ibm,pft-size",
 +                          pft_size_prop, sizeof(pft_size_prop));
 +        if (ret < 0) {
 +            return ret;
 +        }
 +    }
 +    return ret;
 +}
 +
 +
 +static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop,
 +                                     size_t maxsize)
 +{
 +    size_t maxcells = maxsize / sizeof(uint32_t);
 +    int i, j, count;
 +    uint32_t *p = prop;
 +
 +    for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
 +        struct ppc_one_seg_page_size *sps = &env->sps.sps[i];
 +
 +        if (!sps->page_shift) {
 +            break;
 +        }
 +        for (count = 0; count < PPC_PAGE_SIZES_MAX_SZ; count++) {
 +            if (sps->enc[count].page_shift == 0) {
 +                break;
 +            }
 +        }
 +        if ((p - prop) >= (maxcells - 3 - count * 2)) {
 +            break;
 +        }
 +        *(p++) = cpu_to_be32(sps->page_shift);
 +        *(p++) = cpu_to_be32(sps->slb_enc);
 +        *(p++) = cpu_to_be32(count);
 +        for (j = 0; j < count; j++) {
 +            *(p++) = cpu_to_be32(sps->enc[j].page_shift);
 +            *(p++) = cpu_to_be32(sps->enc[j].pte_enc);
 +        }
 +    }
 +
 +    return (p - prop) * sizeof(uint32_t);
 +}
 +
 +#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)
 +
 +
 +static void *spapr_create_fdt_skel(const char *cpu_model,
 +                                   hwaddr initrd_base,
 +                                   hwaddr initrd_size,
 +                                   hwaddr kernel_size,
 +                                   const char *boot_device,
 +                                   const char *kernel_cmdline,
 +                                   uint32_t epow_irq)
 +{
 +    void *fdt;
 +    CPUPPCState *env;
 +    uint32_t start_prop = cpu_to_be32(initrd_base);
 +    uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
 +    char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
 +        "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk";
 +    char qemu_hypertas_prop[] = "hcall-memop1";
 +    uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
 +    uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
 +    char *modelname;
 +    int i, smt = kvmppc_smt_threads();
 +    unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
 +
 +    fdt = g_malloc0(FDT_MAX_SIZE);
 +    _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
 +
 +    if (kernel_size) {
 +        _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR, kernel_size)));
 +    }
 +    if (initrd_size) {
 +        _FDT((fdt_add_reservemap_entry(fdt, initrd_base, initrd_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", "IBM pSeries (emulated by qemu)")));
++    _FDT((fdt_property_string(fdt, "compatible", "qemu,pseries")));
 +
 +    _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
 +    _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
 +
 +    /* /chosen */
 +    _FDT((fdt_begin_node(fdt, "chosen")));
 +
 +    /* Set Form1_affinity */
 +    _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
 +
 +    _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))));
 +    if (kernel_size) {
 +        uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
 +                              cpu_to_be64(kernel_size) };
 +
 +        _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
 +    }
 +    if (boot_device) {
 +        _FDT((fdt_property_string(fdt, "qemu,boot-device", boot_device)));
 +    }
 +    _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width)));
 +    _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height)));
 +    _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth)));
 +
 +    _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 = g_strdup(cpu_model);
 +
 +    for (i = 0; i < strlen(modelname); i++) {
 +        modelname[i] = toupper(modelname[i]);
 +    }
 +
 +    /* This is needed during FDT finalization */
 +    spapr->cpu_model = g_strdup(modelname);
 +
 +    for (env = first_cpu; env != NULL; env = env->next_cpu) {
 +        CPUState *cpu = CPU(ppc_env_get_cpu(env));
 +        int index = cpu->cpu_index;
 +        uint32_t servers_prop[smp_threads];
 +        uint32_t gservers_prop[smp_threads * 2];
 +        char *nodename;
 +        uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
 +                           0xffffffff, 0xffffffff};
 +        uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ;
 +        uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000;
 +        uint32_t page_sizes_prop[64];
 +        size_t page_sizes_prop_size;
 +
 +        if ((index % smt) != 0) {
 +            continue;
 +        }
 +
 +        nodename = g_strdup_printf("%s@%x", modelname, index);
 +
 +        _FDT((fdt_begin_node(fdt, nodename)));
 +
 +        g_free(nodename);
 +
 +        _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])));
 +        _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", tbfreq)));
 +        _FDT((fdt_property_cell(fdt, "clock-frequency", cpufreq)));
 +        _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)));
 +
 +        /* Build interrupt servers and gservers properties */
 +        for (i = 0; i < smp_threads; i++) {
 +            servers_prop[i] = cpu_to_be32(index + i);
 +            /* Hack, direct the group queues back to cpu 0 */
 +            gservers_prop[i*2] = cpu_to_be32(index + i);
 +            gservers_prop[i*2 + 1] = 0;
 +        }
 +        _FDT((fdt_property(fdt, "ibm,ppc-interrupt-server#s",
 +                           servers_prop, sizeof(servers_prop))));
 +        _FDT((fdt_property(fdt, "ibm,ppc-interrupt-gserver#s",
 +                           gservers_prop, sizeof(gservers_prop))));
 +
 +        if (env->mmu_model & POWERPC_MMU_1TSEG) {
 +            _FDT((fdt_property(fdt, "ibm,processor-segment-sizes",
 +                               segs, sizeof(segs))));
 +        }
 +
 +        /* Advertise VMX/VSX (vector extensions) if available
 +         *   0 / no property == no vector extensions
 +         *   1               == VMX / Altivec available
 +         *   2               == VSX available */
 +        if (env->insns_flags & PPC_ALTIVEC) {
 +            uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
 +
 +            _FDT((fdt_property_cell(fdt, "ibm,vmx", vmx)));
 +        }
 +
 +        /* Advertise DFP (Decimal Floating Point) if available
 +         *   0 / no property == no DFP
 +         *   1               == DFP available */
 +        if (env->insns_flags2 & PPC2_DFP) {
 +            _FDT((fdt_property_cell(fdt, "ibm,dfp", 1)));
 +        }
 +
 +        page_sizes_prop_size = create_page_sizes_prop(env, page_sizes_prop,
 +                                                      sizeof(page_sizes_prop));
 +        if (page_sizes_prop_size) {
 +            _FDT((fdt_property(fdt, "ibm,segment-page-sizes",
 +                               page_sizes_prop, page_sizes_prop_size)));
 +        }
 +
 +        _FDT((fdt_end_node(fdt)));
 +    }
 +
 +    g_free(modelname);
 +
 +    _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_property(fdt, "qemu,hypertas-functions", qemu_hypertas_prop,
 +                       sizeof(qemu_hypertas_prop))));
 +
 +    _FDT((fdt_property(fdt, "ibm,associativity-reference-points",
 +        refpoints, sizeof(refpoints))));
 +
 +    _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
 +
 +    _FDT((fdt_end_node(fdt)));
 +
 +    /* interrupt controller */
 +    _FDT((fdt_begin_node(fdt, "interrupt-controller")));
 +
 +    _FDT((fdt_property_string(fdt, "device_type",
 +                              "PowerPC-External-Interrupt-Presentation")));
 +    _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
 +    _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_property_cell(fdt, "#interrupt-cells", 2)));
 +    _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP)));
 +    _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP)));
 +
 +    _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_property_cell(fdt, "#interrupt-cells", 0x2)));
 +    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
 +
 +    _FDT((fdt_end_node(fdt)));
 +
 +    /* event-sources */
 +    spapr_events_fdt_skel(fdt, epow_irq);
 +
 +    _FDT((fdt_end_node(fdt))); /* close root node */
 +    _FDT((fdt_finish(fdt)));
 +
 +    return fdt;
 +}
 +
 +static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt)
 +{
 +    uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0),
 +                                cpu_to_be32(0x0), cpu_to_be32(0x0),
 +                                cpu_to_be32(0x0)};
 +    char mem_name[32];
 +    hwaddr node0_size, mem_start;
 +    uint64_t mem_reg_property[2];
 +    int i, off;
 +
 +    /* memory node(s) */
 +    node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size;
 +    if (spapr->rma_size > node0_size) {
 +        spapr->rma_size = node0_size;
 +    }
 +
 +    /* RMA */
 +    mem_reg_property[0] = 0;
 +    mem_reg_property[1] = cpu_to_be64(spapr->rma_size);
 +    off = fdt_add_subnode(fdt, 0, "memory at 0");
 +    _FDT(off);
 +    _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
 +    _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
 +                      sizeof(mem_reg_property))));
 +    _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
 +                      sizeof(associativity))));
 +
 +    /* RAM: Node 0 */
 +    if (node0_size > spapr->rma_size) {
 +        mem_reg_property[0] = cpu_to_be64(spapr->rma_size);
 +        mem_reg_property[1] = cpu_to_be64(node0_size - spapr->rma_size);
 +
 +        sprintf(mem_name, "memory@" TARGET_FMT_lx, spapr->rma_size);
 +        off = fdt_add_subnode(fdt, 0, mem_name);
 +        _FDT(off);
 +        _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
 +        _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
 +                          sizeof(mem_reg_property))));
 +        _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
 +                          sizeof(associativity))));
 +    }
 +
 +    /* RAM: Node 1 and beyond */
 +    mem_start = node0_size;
 +    for (i = 1; i < nb_numa_nodes; i++) {
 +        mem_reg_property[0] = cpu_to_be64(mem_start);
 +        mem_reg_property[1] = cpu_to_be64(node_mem[i]);
 +        associativity[3] = associativity[4] = cpu_to_be32(i);
 +        sprintf(mem_name, "memory@" TARGET_FMT_lx, mem_start);
 +        off = fdt_add_subnode(fdt, 0, mem_name);
 +        _FDT(off);
 +        _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
 +        _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
 +                          sizeof(mem_reg_property))));
 +        _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
 +                          sizeof(associativity))));
 +        mem_start += node_mem[i];
 +    }
 +
 +    return 0;
 +}
 +
 +static void spapr_finalize_fdt(sPAPREnvironment *spapr,
 +                               hwaddr fdt_addr,
 +                               hwaddr rtas_addr,
 +                               hwaddr rtas_size)
 +{
 +    int ret;
 +    void *fdt;
 +    sPAPRPHBState *phb;
 +
 +    fdt = g_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_memory(spapr, fdt);
 +    if (ret < 0) {
 +        fprintf(stderr, "couldn't setup memory nodes in fdt\n");
 +        exit(1);
 +    }
 +
 +    ret = spapr_populate_vdevice(spapr->vio_bus, fdt);
 +    if (ret < 0) {
 +        fprintf(stderr, "couldn't setup vio devices in fdt\n");
 +        exit(1);
 +    }
 +
 +    QLIST_FOREACH(phb, &spapr->phbs, list) {
 +        ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt);
 +    }
 +
 +    if (ret < 0) {
 +        fprintf(stderr, "couldn't setup PCI devices in fdt\n");
 +        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");
 +    }
 +
 +    /* Advertise NUMA via ibm,associativity */
 +    ret = spapr_fixup_cpu_dt(fdt, spapr);
 +    if (ret < 0) {
 +        fprintf(stderr, "Couldn't finalize CPU device tree properties\n");
 +    }
 +
 +    if (!spapr->has_graphics) {
 +        spapr_populate_chosen_stdout(fdt, spapr->vio_bus);
 +    }
 +
 +    _FDT((fdt_pack(fdt)));
 +
 +    if (fdt_totalsize(fdt) > FDT_MAX_SIZE) {
 +        hw_error("FDT too big ! 0x%x bytes (max is 0x%x)\n",
 +                 fdt_totalsize(fdt), FDT_MAX_SIZE);
 +        exit(1);
 +    }
 +
 +    cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
 +
 +    g_free(fdt);
 +}
 +
 +static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
 +{
 +    return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
 +}
 +
 +static void emulate_spapr_hypercall(PowerPCCPU *cpu)
 +{
 +    CPUPPCState *env = &cpu->env;
 +
 +    if (msr_pr) {
 +        hcall_dprintf("Hypercall made with MSR[PR]=1\n");
 +        env->gpr[3] = H_PRIVILEGE;
 +    } else {
 +        env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]);
 +    }
 +}
 +
 +static void spapr_reset_htab(sPAPREnvironment *spapr)
 +{
 +    long shift;
 +
 +    /* allocate hash page table.  For now we always make this 16mb,
 +     * later we should probably make it scale to the size of guest
 +     * RAM */
 +
 +    shift = kvmppc_reset_htab(spapr->htab_shift);
 +
 +    if (shift > 0) {
 +        /* Kernel handles htab, we don't need to allocate one */
 +        spapr->htab_shift = shift;
 +    } else {
 +        if (!spapr->htab) {
 +            /* Allocate an htab if we don't yet have one */
 +            spapr->htab = qemu_memalign(HTAB_SIZE(spapr), HTAB_SIZE(spapr));
 +        }
 +
 +        /* And clear it */
 +        memset(spapr->htab, 0, HTAB_SIZE(spapr));
 +    }
 +
 +    /* Update the RMA size if necessary */
 +    if (spapr->vrma_adjust) {
 +        spapr->rma_size = kvmppc_rma_size(ram_size, spapr->htab_shift);
 +    }
 +}
 +
 +static void ppc_spapr_reset(void)
 +{
 +    /* Reset the hash table & recalc the RMA */
 +    spapr_reset_htab(spapr);
 +
 +    qemu_devices_reset();
 +
 +    /* 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;
 +
 +}
 +
 +static void spapr_cpu_reset(void *opaque)
 +{
 +    PowerPCCPU *cpu = opaque;
 +    CPUPPCState *env = &cpu->env;
 +
 +    cpu_reset(CPU(cpu));
 +
 +    /* All CPUs start halted.  CPU0 is unhalted from the machine level
 +     * reset code and the rest are explicitly started up by the guest
 +     * using an RTAS call */
 +    env->halted = 1;
 +
 +    env->spr[SPR_HIOR] = 0;
 +
 +    env->external_htab = spapr->htab;
 +    env->htab_base = -1;
 +    env->htab_mask = HTAB_SIZE(spapr) - 1;
 +    env->spr[SPR_SDR1] = (unsigned long)spapr->htab |
 +        (spapr->htab_shift - 18);
 +}
 +
 +static void spapr_create_nvram(sPAPREnvironment *spapr)
 +{
 +    QemuOpts *machine_opts;
 +    DeviceState *dev;
 +
 +    dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
 +
 +    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
 +    if (machine_opts) {
 +        const char *drivename;
 +
 +        drivename = qemu_opt_get(machine_opts, "nvram");
 +        if (drivename) {
 +            BlockDriverState *bs;
 +
 +            bs = bdrv_find(drivename);
 +            if (!bs) {
 +                fprintf(stderr, "No such block device \"%s\" for nvram\n",
 +                        drivename);
 +                exit(1);
 +            }
 +            qdev_prop_set_drive_nofail(dev, "drive", bs);
 +        }
 +    }
 +
 +    qdev_init_nofail(dev);
 +
 +    spapr->nvram = (struct sPAPRNVRAM *)dev;
 +}
 +
 +/* Returns whether we want to use VGA or not */
 +static int spapr_vga_init(PCIBus *pci_bus)
 +{
 +    switch (vga_interface_type) {
 +    case VGA_NONE:
 +    case VGA_STD:
 +        return pci_vga_init(pci_bus) != NULL;
 +    default:
 +        fprintf(stderr, "This vga model is not supported,"
 +                "currently it only supports -vga std\n");
 +        exit(0);
 +        break;
 +    }
 +}
 +
 +/* pSeries LPAR / sPAPR hardware init */
 +static void ppc_spapr_init(QEMUMachineInitArgs *args)
 +{
 +    ram_addr_t ram_size = args->ram_size;
 +    const char *cpu_model = args->cpu_model;
 +    const char *kernel_filename = args->kernel_filename;
 +    const char *kernel_cmdline = args->kernel_cmdline;
 +    const char *initrd_filename = args->initrd_filename;
 +    const char *boot_device = args->boot_device;
 +    PowerPCCPU *cpu;
 +    CPUPPCState *env;
 +    PCIHostState *phb;
 +    int i;
 +    MemoryRegion *sysmem = get_system_memory();
 +    MemoryRegion *ram = g_new(MemoryRegion, 1);
 +    hwaddr rma_alloc_size;
 +    uint32_t initrd_base = 0;
 +    long kernel_size = 0, initrd_size = 0;
 +    long load_limit, rtas_limit, fw_size;
 +    char *filename;
 +
 +    msi_supported = true;
 +
 +    spapr = g_malloc0(sizeof(*spapr));
 +    QLIST_INIT(&spapr->phbs);
 +
 +    cpu_ppc_hypercall = emulate_spapr_hypercall;
 +
 +    /* Allocate RMA if necessary */
 +    rma_alloc_size = kvmppc_alloc_rma("ppc_spapr.rma", sysmem);
 +
 +    if (rma_alloc_size == -1) {
 +        hw_error("qemu: Unable to create RMA\n");
 +        exit(1);
 +    }
 +
 +    if (rma_alloc_size && (rma_alloc_size < ram_size)) {
 +        spapr->rma_size = rma_alloc_size;
 +    } else {
 +        spapr->rma_size = ram_size;
 +
 +        /* With KVM, we don't actually know whether KVM supports an
 +         * unbounded RMA (PR KVM) or is limited by the hash table size
 +         * (HV KVM using VRMA), so we always assume the latter
 +         *
 +         * In that case, we also limit the initial allocations for RTAS
 +         * etc... to 256M since we have no way to know what the VRMA size
 +         * is going to be as it depends on the size of the hash table
 +         * isn't determined yet.
 +         */
 +        if (kvm_enabled()) {
 +            spapr->vrma_adjust = 1;
 +            spapr->rma_size = MIN(spapr->rma_size, 0x10000000);
 +        }
 +    }
 +
 +    /* We place the device tree and RTAS just below either the top of the RMA,
 +     * or just below 2GB, whichever is lowere, so that it can be
 +     * processed with 32-bit real mode code if necessary */
 +    rtas_limit = MIN(spapr->rma_size, 0x80000000);
 +    spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE;
 +    spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE;
 +    load_limit = spapr->fdt_addr - FW_OVERHEAD;
 +
 +    /* We aim for a hash table of size 1/128 the size of RAM.  The
 +     * normal rule of thumb is 1/64 the size of RAM, but that's much
 +     * more than needed for the Linux guests we support. */
 +    spapr->htab_shift = 18; /* Minimum architected size */
 +    while (spapr->htab_shift <= 46) {
 +        if ((1ULL << (spapr->htab_shift + 7)) >= ram_size) {
 +            break;
 +        }
 +        spapr->htab_shift++;
 +    }
 +
 +    /* init CPUs */
 +    if (cpu_model == NULL) {
 +        cpu_model = kvm_enabled() ? "host" : "POWER7";
 +    }
 +    for (i = 0; i < smp_cpus; i++) {
 +        cpu = cpu_ppc_init(cpu_model);
 +        if (cpu == NULL) {
 +            fprintf(stderr, "Unable to find PowerPC CPU definition\n");
 +            exit(1);
 +        }
 +        env = &cpu->env;
 +
 +        /* Set time-base frequency to 512 MHz */
 +        cpu_ppc_tb_init(env, TIMEBASE_FREQ);
 +
 +        /* PAPR always has exception vectors in RAM not ROM */
 +        env->hreset_excp_prefix = 0;
 +
 +        /* Tell KVM that we're in PAPR mode */
 +        if (kvm_enabled()) {
 +            kvmppc_set_papr(cpu);
 +        }
 +
 +        qemu_register_reset(spapr_cpu_reset, cpu);
 +    }
 +
 +    /* allocate RAM */
 +    spapr->ram_limit = ram_size;
 +    if (spapr->ram_limit > rma_alloc_size) {
 +        ram_addr_t nonrma_base = rma_alloc_size;
 +        ram_addr_t nonrma_size = spapr->ram_limit - rma_alloc_size;
 +
 +        memory_region_init_ram(ram, "ppc_spapr.ram", nonrma_size);
 +        vmstate_register_ram_global(ram);
 +        memory_region_add_subregion(sysmem, nonrma_base, ram);
 +    }
 +
 +    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
 +    spapr->rtas_size = load_image_targphys(filename, spapr->rtas_addr,
 +                                           rtas_limit - spapr->rtas_addr);
 +    if (spapr->rtas_size < 0) {
 +        hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
 +        exit(1);
 +    }
 +    if (spapr->rtas_size > RTAS_MAX_SIZE) {
 +        hw_error("RTAS too big ! 0x%lx bytes (max is 0x%x)\n",
 +                 spapr->rtas_size, RTAS_MAX_SIZE);
 +        exit(1);
 +    }
 +    g_free(filename);
 +
 +
 +    /* Set up Interrupt Controller */
 +    spapr->icp = xics_system_init(XICS_IRQS);
 +    spapr->next_irq = XICS_IRQ_BASE;
 +
 +    /* Set up EPOW events infrastructure */
 +    spapr_events_init(spapr);
 +
 +    /* Set up IOMMU */
 +    spapr_iommu_init();
 +
 +    /* Set up VIO bus */
 +    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, serial_hds[i]);
 +        }
 +    }
 +
 +    /* We always have at least the nvram device on VIO */
 +    spapr_create_nvram(spapr);
 +
 +    /* Set up PCI */
 +    spapr_pci_rtas_init();
 +
 +    phb = spapr_create_phb(spapr, 0, "pci");
 +
 +    for (i = 0; i < nb_nics; i++) {
 +        NICInfo *nd = &nd_table[i];
 +
 +        if (!nd->model) {
 +            nd->model = g_strdup("ibmveth");
 +        }
 +
 +        if (strcmp(nd->model, "ibmveth") == 0) {
 +            spapr_vlan_create(spapr->vio_bus, nd);
 +        } else {
 +            pci_nic_init_nofail(&nd_table[i], nd->model, NULL);
 +        }
 +    }
 +
 +    for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) {
 +        spapr_vscsi_create(spapr->vio_bus);
 +    }
 +
 +    /* Graphics */
 +    if (spapr_vga_init(phb->bus)) {
 +        spapr->has_graphics = true;
 +    }
 +
 +    if (usb_enabled(spapr->has_graphics)) {
 +        pci_create_simple(phb->bus, -1, "pci-ohci");
 +        if (spapr->has_graphics) {
 +            usbdevice_create("keyboard");
 +            usbdevice_create("mouse");
 +        }
 +    }
 +
 +    if (spapr->rma_size < (MIN_RMA_SLOF << 20)) {
 +        fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
 +                "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF);
 +        exit(1);
 +    }
 +
 +    if (kernel_filename) {
 +        uint64_t lowaddr = 0;
 +
 +        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_LOAD_ADDR,
 +                                              load_limit - KERNEL_LOAD_ADDR);
 +        }
 +        if (kernel_size < 0) {
 +            fprintf(stderr, "qemu: could not load kernel '%s'\n",
 +                    kernel_filename);
 +            exit(1);
 +        }
 +
 +        /* load initrd */
 +        if (initrd_filename) {
 +            /* Try to locate the initrd in the gap between the kernel
 +             * and the firmware. Add a bit of space just in case
 +             */
 +            initrd_base = (KERNEL_LOAD_ADDR + kernel_size + 0x1ffff) & ~0xffff;
 +            initrd_size = load_image_targphys(initrd_filename, initrd_base,
 +                                              load_limit - 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;
 +        }
 +    }
 +
 +    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME);
 +    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);
 +    }
 +    g_free(filename);
 +
 +    spapr->entry_point = 0x100;
 +
 +    /* Prepare the device tree */
 +    spapr->fdt_skel = spapr_create_fdt_skel(cpu_model,
 +                                            initrd_base, initrd_size,
 +                                            kernel_size,
 +                                            boot_device, kernel_cmdline,
 +                                            spapr->epow_irq);
 +    assert(spapr->fdt_skel != NULL);
 +}
 +
 +static QEMUMachine spapr_machine = {
 +    .name = "pseries",
 +    .desc = "pSeries Logical Partition (PAPR compliant)",
 +    .init = ppc_spapr_init,
 +    .reset = ppc_spapr_reset,
 +    .block_default_type = IF_SCSI,
 +    .max_cpus = MAX_CPUS,
 +    .no_parallel = 1,
 +    .boot_order = NULL,
 +};
 +
 +static void spapr_machine_init(void)
 +{
 +    qemu_register_machine(&spapr_machine);
 +}
 +
 +machine_init(spapr_machine_init);
diff --cc hw/ppc/spapr_hcall.c
index 7b89594,0000000..77c052f
mode 100644,000000..100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@@ -1,741 -1,0 +1,772 @@@
 +#include "sysemu/sysemu.h"
 +#include "cpu.h"
 +#include "sysemu/sysemu.h"
 +#include "helper_regs.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
 +
 +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(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 +                            target_ulong opcode, target_ulong *args)
 +{
 +    CPUPPCState *env = &cpu->env;
 +    target_ulong flags = args[0];
 +    target_ulong pte_index = args[1];
 +    target_ulong pteh = args[2];
 +    target_ulong ptel = args[3];
 +    target_ulong page_shift = 12;
 +    target_ulong raddr;
 +    target_ulong i;
 +    uint8_t *hpte;
 +
 +    /* only handle 4k and 16M pages for now */
 +    if (pteh & HPTE_V_LARGE) {
 +#if 0 /* We don't support 64k pages yet */
 +        if ((ptel & 0xf000) == 0x1000) {
 +            /* 64k page */
 +        } else
 +#endif
 +        if ((ptel & 0xff000) == 0) {
 +            /* 16M page */
 +            page_shift = 24;
 +            /* lowest AVA bit must be 0 for 16M pages */
 +            if (pteh & 0x80) {
 +                return H_PARAMETER;
 +            }
 +        } else {
 +            return H_PARAMETER;
 +        }
 +    }
 +
 +    raddr = (ptel & HPTE_R_RPN) & ~((1ULL << page_shift) - 1);
 +
 +    if (raddr < spapr->ram_limit) {
 +        /* Regular RAM - should have WIMG=0010 */
 +        if ((ptel & HPTE_R_WIMG) != HPTE_R_M) {
 +            return H_PARAMETER;
 +        }
 +    } else {
 +        /* Looks like an IO address */
 +        /* FIXME: What WIMG combinations could be sensible for IO?
 +         * For now we allow WIMG=010x, but are there others? */
 +        /* FIXME: Should we check against registered IO addresses? */
 +        if ((ptel & (HPTE_R_W | HPTE_R_I | HPTE_R_M)) != HPTE_R_I) {
 +            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) {
 +                break;
 +            }
 +            hpte += HASH_PTE_SIZE_64;
 +        }
 +    } else {
 +        i = 0;
 +        hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
 +        if (ldq_p(hpte) & 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);
 +
 +    args[0] = pte_index + i;
 +    return H_SUCCESS;
 +}
 +
 +enum {
 +    REMOVE_SUCCESS = 0,
 +    REMOVE_NOT_FOUND = 1,
 +    REMOVE_PARM = 2,
 +    REMOVE_HW = 3,
 +};
 +
 +static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex,
 +                                target_ulong avpn,
 +                                target_ulong flags,
 +                                target_ulong *vp, target_ulong *rp)
 +{
 +    uint8_t *hpte;
 +    target_ulong v, r, rb;
 +
 +    if ((ptex * HASH_PTE_SIZE_64) & ~env->htab_mask) {
 +        return REMOVE_PARM;
 +    }
 +
 +    hpte = env->external_htab + (ptex * HASH_PTE_SIZE_64);
 +
 +    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)) {
 +        return REMOVE_NOT_FOUND;
 +    }
 +    *vp = v;
 +    *rp = r;
 +    stq_p(hpte, 0);
 +    rb = compute_tlbie_rb(v, r, ptex);
 +    ppc_tlb_invalidate_one(env, rb);
 +    return REMOVE_SUCCESS;
 +}
 +
 +static target_ulong h_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 +                             target_ulong opcode, target_ulong *args)
 +{
 +    CPUPPCState *env = &cpu->env;
 +    target_ulong flags = args[0];
 +    target_ulong pte_index = args[1];
 +    target_ulong avpn = args[2];
 +    int ret;
 +
 +    ret = remove_hpte(env, pte_index, avpn, flags,
 +                      &args[0], &args[1]);
 +
 +    switch (ret) {
 +    case REMOVE_SUCCESS:
 +        return H_SUCCESS;
 +
 +    case REMOVE_NOT_FOUND:
 +        return H_NOT_FOUND;
 +
 +    case REMOVE_PARM:
 +        return H_PARAMETER;
 +
 +    case REMOVE_HW:
 +        return H_HARDWARE;
 +    }
 +
 +    assert(0);
 +}
 +
 +#define H_BULK_REMOVE_TYPE             0xc000000000000000ULL
 +#define   H_BULK_REMOVE_REQUEST        0x4000000000000000ULL
 +#define   H_BULK_REMOVE_RESPONSE       0x8000000000000000ULL
 +#define   H_BULK_REMOVE_END            0xc000000000000000ULL
 +#define H_BULK_REMOVE_CODE             0x3000000000000000ULL
 +#define   H_BULK_REMOVE_SUCCESS        0x0000000000000000ULL
 +#define   H_BULK_REMOVE_NOT_FOUND      0x1000000000000000ULL
 +#define   H_BULK_REMOVE_PARM           0x2000000000000000ULL
 +#define   H_BULK_REMOVE_HW             0x3000000000000000ULL
 +#define H_BULK_REMOVE_RC               0x0c00000000000000ULL
 +#define H_BULK_REMOVE_FLAGS            0x0300000000000000ULL
 +#define   H_BULK_REMOVE_ABSOLUTE       0x0000000000000000ULL
 +#define   H_BULK_REMOVE_ANDCOND        0x0100000000000000ULL
 +#define   H_BULK_REMOVE_AVPN           0x0200000000000000ULL
 +#define H_BULK_REMOVE_PTEX             0x00ffffffffffffffULL
 +
 +#define H_BULK_REMOVE_MAX_BATCH        4
 +
 +static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 +                                  target_ulong opcode, target_ulong *args)
 +{
 +    CPUPPCState *env = &cpu->env;
 +    int i;
 +
 +    for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) {
 +        target_ulong *tsh = &args[i*2];
 +        target_ulong tsl = args[i*2 + 1];
 +        target_ulong v, r, ret;
 +
 +        if ((*tsh & H_BULK_REMOVE_TYPE) == H_BULK_REMOVE_END) {
 +            break;
 +        } else if ((*tsh & H_BULK_REMOVE_TYPE) != H_BULK_REMOVE_REQUEST) {
 +            return H_PARAMETER;
 +        }
 +
 +        *tsh &= H_BULK_REMOVE_PTEX | H_BULK_REMOVE_FLAGS;
 +        *tsh |= H_BULK_REMOVE_RESPONSE;
 +
 +        if ((*tsh & H_BULK_REMOVE_ANDCOND) && (*tsh & H_BULK_REMOVE_AVPN)) {
 +            *tsh |= H_BULK_REMOVE_PARM;
 +            return H_PARAMETER;
 +        }
 +
 +        ret = remove_hpte(env, *tsh & H_BULK_REMOVE_PTEX, tsl,
 +                          (*tsh & H_BULK_REMOVE_FLAGS) >> 26,
 +                          &v, &r);
 +
 +        *tsh |= ret << 60;
 +
 +        switch (ret) {
 +        case REMOVE_SUCCESS:
 +            *tsh |= (r & (HPTE_R_C | HPTE_R_R)) << 43;
 +            break;
 +
 +        case REMOVE_PARM:
 +            return H_PARAMETER;
 +
 +        case REMOVE_HW:
 +            return H_HARDWARE;
 +        }
 +    }
 +
 +    return H_SUCCESS;
 +}
 +
 +static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 +                              target_ulong opcode, target_ulong *args)
 +{
 +    CPUPPCState *env = &cpu->env;
 +    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);
 +
 +    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)) {
 +        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);
 +    return H_SUCCESS;
 +}
 +
++static target_ulong h_read(PowerPCCPU *cpu, sPAPREnvironment *spapr,
++                           target_ulong opcode, target_ulong *args)
++{
++    CPUPPCState *env = &cpu->env;
++    target_ulong flags = args[0];
++    target_ulong pte_index = args[1];
++    uint8_t *hpte;
++    int i, ridx, n_entries = 1;
++
++    if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
++        return H_PARAMETER;
++    }
++
++    if (flags & H_READ_4) {
++        /* Clear the two low order bits */
++        pte_index &= ~(3ULL);
++        n_entries = 4;
++    }
++
++    hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
++
++    for (i = 0, ridx = 0; i < n_entries; i++) {
++        args[ridx++] = ldq_p(hpte);
++        args[ridx++] = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
++        hpte += HASH_PTE_SIZE_64;
++    }
++
++    return H_SUCCESS;
++}
++
 +static target_ulong h_set_dabr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 +                               target_ulong opcode, target_ulong *args)
 +{
 +    /* FIXME: actually implement this */
 +    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(CPUPPCState *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_be_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_addr = vpa;
 +
 +    tmp = ldub_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET);
 +    tmp |= VPA_SHARED_PROC_VAL;
 +    stb_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET, tmp);
 +
 +    return H_SUCCESS;
 +}
 +
 +static target_ulong deregister_vpa(CPUPPCState *env, target_ulong vpa)
 +{
 +    if (env->slb_shadow_addr) {
 +        return H_RESOURCE;
 +    }
 +
 +    if (env->dtl_addr) {
 +        return H_RESOURCE;
 +    }
 +
 +    env->vpa_addr = 0;
 +    return H_SUCCESS;
 +}
 +
 +static target_ulong register_slb_shadow(CPUPPCState *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_be_phys(addr + 0x4);
 +    if (size < 0x8) {
 +        return H_PARAMETER;
 +    }
 +
 +    if ((addr / 4096) != ((addr + size - 1) / 4096)) {
 +        return H_PARAMETER;
 +    }
 +
 +    if (!env->vpa_addr) {
 +        return H_RESOURCE;
 +    }
 +
 +    env->slb_shadow_addr = addr;
 +    env->slb_shadow_size = size;
 +
 +    return H_SUCCESS;
 +}
 +
 +static target_ulong deregister_slb_shadow(CPUPPCState *env, target_ulong addr)
 +{
 +    env->slb_shadow_addr = 0;
 +    env->slb_shadow_size = 0;
 +    return H_SUCCESS;
 +}
 +
 +static target_ulong register_dtl(CPUPPCState *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_be_phys(addr + 0x4);
 +
 +    if (size < 48) {
 +        return H_PARAMETER;
 +    }
 +
 +    if (!env->vpa_addr) {
 +        return H_RESOURCE;
 +    }
 +
 +    env->dtl_addr = addr;
 +    env->dtl_size = size;
 +
 +    return H_SUCCESS;
 +}
 +
 +static target_ulong deregister_dtl(CPUPPCState *env, target_ulong addr)
 +{
 +    env->dtl_addr = 0;
 +    env->dtl_size = 0;
 +
 +    return H_SUCCESS;
 +}
 +
 +static target_ulong h_register_vpa(PowerPCCPU *cpu, 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;
 +    CPUPPCState *tenv;
 +    CPUState *tcpu;
 +
 +    tcpu = qemu_get_cpu(procno);
 +    if (!tcpu) {
 +        return H_PARAMETER;
 +    }
 +    tenv = tcpu->env_ptr;
 +
 +    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(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 +                           target_ulong opcode, target_ulong *args)
 +{
 +    CPUPPCState *env = &cpu->env;
 +    CPUState *cs = CPU(cpu);
 +
 +    env->msr |= (1ULL << MSR_EE);
 +    hreg_compute_hflags(env);
 +    if (!cpu_has_work(cs)) {
 +        env->halted = 1;
 +        env->exception_index = EXCP_HLT;
 +        cs->exit_request = 1;
 +    }
 +    return H_SUCCESS;
 +}
 +
 +static target_ulong h_rtas(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 +                           target_ulong opcode, target_ulong *args)
 +{
 +    target_ulong rtas_r3 = args[0];
 +    uint32_t token = ldl_be_phys(rtas_r3);
 +    uint32_t nargs = ldl_be_phys(rtas_r3 + 4);
 +    uint32_t nret = ldl_be_phys(rtas_r3 + 8);
 +
 +    return spapr_rtas_call(spapr, token, nargs, rtas_r3 + 12,
 +                           nret, rtas_r3 + 12 + 4*nargs);
 +}
 +
 +static target_ulong h_logical_load(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 +                                   target_ulong opcode, target_ulong *args)
 +{
 +    target_ulong size = args[0];
 +    target_ulong addr = args[1];
 +
 +    switch (size) {
 +    case 1:
 +        args[0] = ldub_phys(addr);
 +        return H_SUCCESS;
 +    case 2:
 +        args[0] = lduw_phys(addr);
 +        return H_SUCCESS;
 +    case 4:
 +        args[0] = ldl_phys(addr);
 +        return H_SUCCESS;
 +    case 8:
 +        args[0] = ldq_phys(addr);
 +        return H_SUCCESS;
 +    }
 +    return H_PARAMETER;
 +}
 +
 +static target_ulong h_logical_store(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 +                                    target_ulong opcode, target_ulong *args)
 +{
 +    target_ulong size = args[0];
 +    target_ulong addr = args[1];
 +    target_ulong val  = args[2];
 +
 +    switch (size) {
 +    case 1:
 +        stb_phys(addr, val);
 +        return H_SUCCESS;
 +    case 2:
 +        stw_phys(addr, val);
 +        return H_SUCCESS;
 +    case 4:
 +        stl_phys(addr, val);
 +        return H_SUCCESS;
 +    case 8:
 +        stq_phys(addr, val);
 +        return H_SUCCESS;
 +    }
 +    return H_PARAMETER;
 +}
 +
 +static target_ulong h_logical_memop(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 +                                    target_ulong opcode, target_ulong *args)
 +{
 +    target_ulong dst   = args[0]; /* Destination address */
 +    target_ulong src   = args[1]; /* Source address */
 +    target_ulong esize = args[2]; /* Element size (0=1,1=2,2=4,3=8) */
 +    target_ulong count = args[3]; /* Element count */
 +    target_ulong op    = args[4]; /* 0 = copy, 1 = invert */
 +    uint64_t tmp;
 +    unsigned int mask = (1 << esize) - 1;
 +    int step = 1 << esize;
 +
 +    if (count > 0x80000000) {
 +        return H_PARAMETER;
 +    }
 +
 +    if ((dst & mask) || (src & mask) || (op > 1)) {
 +        return H_PARAMETER;
 +    }
 +
 +    if (dst >= src && dst < (src + (count << esize))) {
 +            dst = dst + ((count - 1) << esize);
 +            src = src + ((count - 1) << esize);
 +            step = -step;
 +    }
 +
 +    while (count--) {
 +        switch (esize) {
 +        case 0:
 +            tmp = ldub_phys(src);
 +            break;
 +        case 1:
 +            tmp = lduw_phys(src);
 +            break;
 +        case 2:
 +            tmp = ldl_phys(src);
 +            break;
 +        case 3:
 +            tmp = ldq_phys(src);
 +            break;
 +        default:
 +            return H_PARAMETER;
 +        }
 +        if (op == 1) {
 +            tmp = ~tmp;
 +        }
 +        switch (esize) {
 +        case 0:
 +            stb_phys(dst, tmp);
 +            break;
 +        case 1:
 +            stw_phys(dst, tmp);
 +            break;
 +        case 2:
 +            stl_phys(dst, tmp);
 +            break;
 +        case 3:
 +            stq_phys(dst, tmp);
 +            break;
 +        }
 +        dst = dst + step;
 +        src = src + step;
 +    }
 +
 +    return H_SUCCESS;
 +}
 +
 +static target_ulong h_logical_icbi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 +                                   target_ulong opcode, target_ulong *args)
 +{
 +    /* Nothing to do on emulation, KVM will trap this in the kernel */
 +    return H_SUCCESS;
 +}
 +
 +static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 +                                   target_ulong opcode, target_ulong *args)
 +{
 +    /* Nothing to do on emulation, KVM will trap this in the kernel */
 +    return H_SUCCESS;
 +}
 +
 +static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
 +static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1];
 +
 +void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
 +{
 +    spapr_hcall_fn *slot;
 +
 +    if (opcode <= MAX_HCALL_OPCODE) {
 +        assert((opcode & 0x3) == 0);
 +
 +        slot = &papr_hypercall_table[opcode / 4];
 +    } else {
 +        assert((opcode >= KVMPPC_HCALL_BASE) && (opcode <= KVMPPC_HCALL_MAX));
 +
 +        slot = &kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
 +    }
 +
 +    assert(!(*slot));
 +    *slot = fn;
 +}
 +
 +target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode,
 +                             target_ulong *args)
 +{
 +    if ((opcode <= MAX_HCALL_OPCODE)
 +        && ((opcode & 0x3) == 0)) {
 +        spapr_hcall_fn fn = papr_hypercall_table[opcode / 4];
 +
 +        if (fn) {
 +            return fn(cpu, 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(cpu, spapr, opcode, args);
 +        }
 +    }
 +
 +    hcall_dprintf("Unimplemented hcall 0x" TARGET_FMT_lx "\n", opcode);
 +    return H_FUNCTION;
 +}
 +
 +static void hypercall_register_types(void)
 +{
 +    /* hcall-pft */
 +    spapr_register_hypercall(H_ENTER, h_enter);
 +    spapr_register_hypercall(H_REMOVE, h_remove);
 +    spapr_register_hypercall(H_PROTECT, h_protect);
++    spapr_register_hypercall(H_READ, h_read);
 +
 +    /* hcall-bulk */
 +    spapr_register_hypercall(H_BULK_REMOVE, h_bulk_remove);
 +
 +    /* 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);
 +
 +    /* "debugger" hcalls (also used by SLOF). Note: We do -not- differenciate
 +     * here between the "CI" and the "CACHE" variants, they will use whatever
 +     * mapping attributes qemu is using. When using KVM, the kernel will
 +     * enforce the attributes more strongly
 +     */
 +    spapr_register_hypercall(H_LOGICAL_CI_LOAD, h_logical_load);
 +    spapr_register_hypercall(H_LOGICAL_CI_STORE, h_logical_store);
 +    spapr_register_hypercall(H_LOGICAL_CACHE_LOAD, h_logical_load);
 +    spapr_register_hypercall(H_LOGICAL_CACHE_STORE, h_logical_store);
 +    spapr_register_hypercall(H_LOGICAL_ICBI, h_logical_icbi);
 +    spapr_register_hypercall(H_LOGICAL_DCBF, h_logical_dcbf);
 +    spapr_register_hypercall(KVMPPC_H_LOGICAL_MEMOP, h_logical_memop);
 +
 +    /* qemu/KVM-PPC specific hcalls */
 +    spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
 +}
 +
 +type_init(hypercall_register_types)
commit 6e72a00f909dcd093fbdd1faa2b3c8caa1697a6c
Merge: 6a245c6 7a2771d
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Sun Mar 10 19:39:07 2013 -0500

    Merge remote-tracking branch 'bonzini/hw-dirs' into staging
    
    * bonzini/hw-dirs:
      sh: move files referencing CPU to hw/sh4/
      ppc: move more files to hw/ppc
      ppc: move files referencing CPU to hw/ppc/
      m68k: move files referencing CPU to hw/m68k/
      i386: move files referencing CPU to hw/i386/
      arm: move files referencing CPU to hw/arm/
      hw: move boards and other isolated files to hw/ARCH
      ppc: express FDT dependency of pSeries and e500 boards via default-configs/
      build: always link device_tree.o into emulators if libfdt available
      hw: include hw header files with full paths
      ppc: do not use ../ in include files
      vt82c686: vt82c686 is not a PCI host bridge
      virtio-9p: remove PCI dependencies from hw/9pfs/
      virtio-9p: use CONFIG_VIRTFS, not CONFIG_LINUX
      hw: move device-hotplug.o to toplevel, compile it once
      hw: move qdev-monitor.o to toplevel directory
      hw: move fifo.[ch] to libqemuutil
      hw: move char backends to backends/
    
    Conflicts:
    	backends/baum.c
    	backends/msmouse.c
    	hw/a15mpcore.c
    	hw/arm/Makefile.objs
    	hw/arm/pic_cpu.c
    	hw/dataplane/event-poll.c
    	hw/dataplane/virtio-blk.c
    	include/char/baum.h
    	include/char/msmouse.h
    	qemu-char.c
    	vl.c
    
    Resolve conflicts caused by header movements.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --cc backends/baum.c
index 0000000,37ccca8..9063aea
mode 000000,100644..100644
--- a/backends/baum.c
+++ b/backends/baum.c
@@@ -1,0 -1,627 +1,633 @@@
+ /*
+  * QEMU Baum Braille Device
+  *
+  * Copyright (c) 2008 Samuel Thibault
+  *
+  * 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 "char/char.h"
+ #include "qemu/timer.h"
+ #include "hw/usb.h"
 -#include "char/baum.h"
+ #include <brlapi.h>
+ #include <brlapi_constants.h>
+ #include <brlapi_keycodes.h>
+ #ifdef CONFIG_SDL
+ #include <SDL_syswm.h>
+ #endif
+ 
+ #if 0
+ #define DPRINTF(fmt, ...) \
+         printf(fmt, ## __VA_ARGS__)
+ #else
+ #define DPRINTF(fmt, ...)
+ #endif
+ 
+ #define ESC 0x1B
+ 
+ #define BAUM_REQ_DisplayData		0x01
+ #define BAUM_REQ_GetVersionNumber	0x05
+ #define BAUM_REQ_GetKeys		0x08
+ #define BAUM_REQ_SetMode		0x12
+ #define BAUM_REQ_SetProtocol		0x15
+ #define BAUM_REQ_GetDeviceIdentity	0x84
+ #define BAUM_REQ_GetSerialNumber	0x8A
+ 
+ #define BAUM_RSP_CellCount		0x01
+ #define BAUM_RSP_VersionNumber		0x05
+ #define BAUM_RSP_ModeSetting		0x11
+ #define BAUM_RSP_CommunicationChannel	0x16
+ #define BAUM_RSP_PowerdownSignal	0x17
+ #define BAUM_RSP_HorizontalSensors	0x20
+ #define BAUM_RSP_VerticalSensors	0x21
+ #define BAUM_RSP_RoutingKeys		0x22
+ #define BAUM_RSP_Switches		0x23
+ #define BAUM_RSP_TopKeys		0x24
+ #define BAUM_RSP_HorizontalSensor	0x25
+ #define BAUM_RSP_VerticalSensor		0x26
+ #define BAUM_RSP_RoutingKey		0x27
+ #define BAUM_RSP_FrontKeys6		0x28
+ #define BAUM_RSP_BackKeys6		0x29
+ #define BAUM_RSP_CommandKeys		0x2B
+ #define BAUM_RSP_FrontKeys10		0x2C
+ #define BAUM_RSP_BackKeys10		0x2D
+ #define BAUM_RSP_EntryKeys		0x33
+ #define BAUM_RSP_JoyStick		0x34
+ #define BAUM_RSP_ErrorCode		0x40
+ #define BAUM_RSP_InfoBlock		0x42
+ #define BAUM_RSP_DeviceIdentity		0x84
+ #define BAUM_RSP_SerialNumber		0x8A
+ #define BAUM_RSP_BluetoothName		0x8C
+ 
+ #define BAUM_TL1 0x01
+ #define BAUM_TL2 0x02
+ #define BAUM_TL3 0x04
+ #define BAUM_TR1 0x08
+ #define BAUM_TR2 0x10
+ #define BAUM_TR3 0x20
+ 
+ #define BUF_SIZE 256
+ 
+ typedef struct {
+     CharDriverState *chr;
+ 
+     brlapi_handle_t *brlapi;
+     int brlapi_fd;
+     unsigned int x, y;
+ 
+     uint8_t in_buf[BUF_SIZE];
+     uint8_t in_buf_used;
+     uint8_t out_buf[BUF_SIZE];
+     uint8_t out_buf_used, out_buf_ptr;
+ 
+     QEMUTimer *cellCount_timer;
+ } BaumDriverState;
+ 
+ /* Let's assume NABCC by default */
+ static const uint8_t nabcc_translation[256] = {
+     [0] = ' ',
+ #ifndef BRLAPI_DOTS
+ #define BRLAPI_DOTS(d1,d2,d3,d4,d5,d6,d7,d8) \
+     ((d1?BRLAPI_DOT1:0)|\
+      (d2?BRLAPI_DOT2:0)|\
+      (d3?BRLAPI_DOT3:0)|\
+      (d4?BRLAPI_DOT4:0)|\
+      (d5?BRLAPI_DOT5:0)|\
+      (d6?BRLAPI_DOT6:0)|\
+      (d7?BRLAPI_DOT7:0)|\
+      (d8?BRLAPI_DOT8:0))
+ #endif
+     [BRLAPI_DOTS(1,0,0,0,0,0,0,0)] = 'a',
+     [BRLAPI_DOTS(1,1,0,0,0,0,0,0)] = 'b',
+     [BRLAPI_DOTS(1,0,0,1,0,0,0,0)] = 'c',
+     [BRLAPI_DOTS(1,0,0,1,1,0,0,0)] = 'd',
+     [BRLAPI_DOTS(1,0,0,0,1,0,0,0)] = 'e',
+     [BRLAPI_DOTS(1,1,0,1,0,0,0,0)] = 'f',
+     [BRLAPI_DOTS(1,1,0,1,1,0,0,0)] = 'g',
+     [BRLAPI_DOTS(1,1,0,0,1,0,0,0)] = 'h',
+     [BRLAPI_DOTS(0,1,0,1,0,0,0,0)] = 'i',
+     [BRLAPI_DOTS(0,1,0,1,1,0,0,0)] = 'j',
+     [BRLAPI_DOTS(1,0,1,0,0,0,0,0)] = 'k',
+     [BRLAPI_DOTS(1,1,1,0,0,0,0,0)] = 'l',
+     [BRLAPI_DOTS(1,0,1,1,0,0,0,0)] = 'm',
+     [BRLAPI_DOTS(1,0,1,1,1,0,0,0)] = 'n',
+     [BRLAPI_DOTS(1,0,1,0,1,0,0,0)] = 'o',
+     [BRLAPI_DOTS(1,1,1,1,0,0,0,0)] = 'p',
+     [BRLAPI_DOTS(1,1,1,1,1,0,0,0)] = 'q',
+     [BRLAPI_DOTS(1,1,1,0,1,0,0,0)] = 'r',
+     [BRLAPI_DOTS(0,1,1,1,0,0,0,0)] = 's',
+     [BRLAPI_DOTS(0,1,1,1,1,0,0,0)] = 't',
+     [BRLAPI_DOTS(1,0,1,0,0,1,0,0)] = 'u',
+     [BRLAPI_DOTS(1,1,1,0,0,1,0,0)] = 'v',
+     [BRLAPI_DOTS(0,1,0,1,1,1,0,0)] = 'w',
+     [BRLAPI_DOTS(1,0,1,1,0,1,0,0)] = 'x',
+     [BRLAPI_DOTS(1,0,1,1,1,1,0,0)] = 'y',
+     [BRLAPI_DOTS(1,0,1,0,1,1,0,0)] = 'z',
+ 
+     [BRLAPI_DOTS(1,0,0,0,0,0,1,0)] = 'A',
+     [BRLAPI_DOTS(1,1,0,0,0,0,1,0)] = 'B',
+     [BRLAPI_DOTS(1,0,0,1,0,0,1,0)] = 'C',
+     [BRLAPI_DOTS(1,0,0,1,1,0,1,0)] = 'D',
+     [BRLAPI_DOTS(1,0,0,0,1,0,1,0)] = 'E',
+     [BRLAPI_DOTS(1,1,0,1,0,0,1,0)] = 'F',
+     [BRLAPI_DOTS(1,1,0,1,1,0,1,0)] = 'G',
+     [BRLAPI_DOTS(1,1,0,0,1,0,1,0)] = 'H',
+     [BRLAPI_DOTS(0,1,0,1,0,0,1,0)] = 'I',
+     [BRLAPI_DOTS(0,1,0,1,1,0,1,0)] = 'J',
+     [BRLAPI_DOTS(1,0,1,0,0,0,1,0)] = 'K',
+     [BRLAPI_DOTS(1,1,1,0,0,0,1,0)] = 'L',
+     [BRLAPI_DOTS(1,0,1,1,0,0,1,0)] = 'M',
+     [BRLAPI_DOTS(1,0,1,1,1,0,1,0)] = 'N',
+     [BRLAPI_DOTS(1,0,1,0,1,0,1,0)] = 'O',
+     [BRLAPI_DOTS(1,1,1,1,0,0,1,0)] = 'P',
+     [BRLAPI_DOTS(1,1,1,1,1,0,1,0)] = 'Q',
+     [BRLAPI_DOTS(1,1,1,0,1,0,1,0)] = 'R',
+     [BRLAPI_DOTS(0,1,1,1,0,0,1,0)] = 'S',
+     [BRLAPI_DOTS(0,1,1,1,1,0,1,0)] = 'T',
+     [BRLAPI_DOTS(1,0,1,0,0,1,1,0)] = 'U',
+     [BRLAPI_DOTS(1,1,1,0,0,1,1,0)] = 'V',
+     [BRLAPI_DOTS(0,1,0,1,1,1,1,0)] = 'W',
+     [BRLAPI_DOTS(1,0,1,1,0,1,1,0)] = 'X',
+     [BRLAPI_DOTS(1,0,1,1,1,1,1,0)] = 'Y',
+     [BRLAPI_DOTS(1,0,1,0,1,1,1,0)] = 'Z',
+ 
+     [BRLAPI_DOTS(0,0,1,0,1,1,0,0)] = '0',
+     [BRLAPI_DOTS(0,1,0,0,0,0,0,0)] = '1',
+     [BRLAPI_DOTS(0,1,1,0,0,0,0,0)] = '2',
+     [BRLAPI_DOTS(0,1,0,0,1,0,0,0)] = '3',
+     [BRLAPI_DOTS(0,1,0,0,1,1,0,0)] = '4',
+     [BRLAPI_DOTS(0,1,0,0,0,1,0,0)] = '5',
+     [BRLAPI_DOTS(0,1,1,0,1,0,0,0)] = '6',
+     [BRLAPI_DOTS(0,1,1,0,1,1,0,0)] = '7',
+     [BRLAPI_DOTS(0,1,1,0,0,1,0,0)] = '8',
+     [BRLAPI_DOTS(0,0,1,0,1,0,0,0)] = '9',
+ 
+     [BRLAPI_DOTS(0,0,0,1,0,1,0,0)] = '.',
+     [BRLAPI_DOTS(0,0,1,1,0,1,0,0)] = '+',
+     [BRLAPI_DOTS(0,0,1,0,0,1,0,0)] = '-',
+     [BRLAPI_DOTS(1,0,0,0,0,1,0,0)] = '*',
+     [BRLAPI_DOTS(0,0,1,1,0,0,0,0)] = '/',
+     [BRLAPI_DOTS(1,1,1,0,1,1,0,0)] = '(',
+     [BRLAPI_DOTS(0,1,1,1,1,1,0,0)] = ')',
+ 
+     [BRLAPI_DOTS(1,1,1,1,0,1,0,0)] = '&',
+     [BRLAPI_DOTS(0,0,1,1,1,1,0,0)] = '#',
+ 
+     [BRLAPI_DOTS(0,0,0,0,0,1,0,0)] = ',',
+     [BRLAPI_DOTS(0,0,0,0,1,1,0,0)] = ';',
+     [BRLAPI_DOTS(1,0,0,0,1,1,0,0)] = ':',
+     [BRLAPI_DOTS(0,1,1,1,0,1,0,0)] = '!',
+     [BRLAPI_DOTS(1,0,0,1,1,1,0,0)] = '?',
+     [BRLAPI_DOTS(0,0,0,0,1,0,0,0)] = '"',
+     [BRLAPI_DOTS(0,0,1,0,0,0,0,0)] ='\'',
+     [BRLAPI_DOTS(0,0,0,1,0,0,0,0)] = '`',
+     [BRLAPI_DOTS(0,0,0,1,1,0,1,0)] = '^',
+     [BRLAPI_DOTS(0,0,0,1,1,0,0,0)] = '~',
+     [BRLAPI_DOTS(0,1,0,1,0,1,1,0)] = '[',
+     [BRLAPI_DOTS(1,1,0,1,1,1,1,0)] = ']',
+     [BRLAPI_DOTS(0,1,0,1,0,1,0,0)] = '{',
+     [BRLAPI_DOTS(1,1,0,1,1,1,0,0)] = '}',
+     [BRLAPI_DOTS(1,1,1,1,1,1,0,0)] = '=',
+     [BRLAPI_DOTS(1,1,0,0,0,1,0,0)] = '<',
+     [BRLAPI_DOTS(0,0,1,1,1,0,0,0)] = '>',
+     [BRLAPI_DOTS(1,1,0,1,0,1,0,0)] = '$',
+     [BRLAPI_DOTS(1,0,0,1,0,1,0,0)] = '%',
+     [BRLAPI_DOTS(0,0,0,1,0,0,1,0)] = '@',
+     [BRLAPI_DOTS(1,1,0,0,1,1,0,0)] = '|',
+     [BRLAPI_DOTS(1,1,0,0,1,1,1,0)] ='\\',
+     [BRLAPI_DOTS(0,0,0,1,1,1,0,0)] = '_',
+ };
+ 
+ /* The serial port can receive more of our data */
+ static void baum_accept_input(struct CharDriverState *chr)
+ {
+     BaumDriverState *baum = chr->opaque;
+     int room, first;
+ 
+     if (!baum->out_buf_used)
+         return;
+     room = qemu_chr_be_can_write(chr);
+     if (!room)
+         return;
+     if (room > baum->out_buf_used)
+         room = baum->out_buf_used;
+ 
+     first = BUF_SIZE - baum->out_buf_ptr;
+     if (room > first) {
+         qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, first);
+         baum->out_buf_ptr = 0;
+         baum->out_buf_used -= first;
+         room -= first;
+     }
+     qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, room);
+     baum->out_buf_ptr += room;
+     baum->out_buf_used -= room;
+ }
+ 
+ /* We want to send a packet */
+ static void baum_write_packet(BaumDriverState *baum, const uint8_t *buf, int len)
+ {
+     uint8_t io_buf[1 + 2 * len], *cur = io_buf;
+     int room;
+     *cur++ = ESC;
+     while (len--)
+         if ((*cur++ = *buf++) == ESC)
+             *cur++ = ESC;
+     room = qemu_chr_be_can_write(baum->chr);
+     len = cur - io_buf;
+     if (len <= room) {
+         /* Fits */
+         qemu_chr_be_write(baum->chr, io_buf, len);
+     } else {
+         int first;
+         uint8_t out;
+         /* Can't fit all, send what can be, and store the rest. */
+         qemu_chr_be_write(baum->chr, io_buf, room);
+         len -= room;
+         cur = io_buf + room;
+         if (len > BUF_SIZE - baum->out_buf_used) {
+             /* Can't even store it, drop the previous data... */
+             assert(len <= BUF_SIZE);
+             baum->out_buf_used = 0;
+             baum->out_buf_ptr = 0;
+         }
+         out = baum->out_buf_ptr;
+         baum->out_buf_used += len;
+         first = BUF_SIZE - baum->out_buf_ptr;
+         if (len > first) {
+             memcpy(baum->out_buf + out, cur, first);
+             out = 0;
+             len -= first;
+             cur += first;
+         }
+         memcpy(baum->out_buf + out, cur, len);
+     }
+ }
+ 
+ /* Called when the other end seems to have a wrong idea of our display size */
+ static void baum_cellCount_timer_cb(void *opaque)
+ {
+     BaumDriverState *baum = opaque;
+     uint8_t cell_count[] = { BAUM_RSP_CellCount, baum->x * baum->y };
+     DPRINTF("Timeout waiting for DisplayData, sending cell count\n");
+     baum_write_packet(baum, cell_count, sizeof(cell_count));
+ }
+ 
+ /* Try to interpret a whole incoming packet */
+ static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len)
+ {
+     const uint8_t *cur = buf;
+     uint8_t req = 0;
+ 
+     if (!len--)
+         return 0;
+     if (*cur++ != ESC) {
+         while (*cur != ESC) {
+             if (!len--)
+                 return 0;
+             cur++;
+         }
+         DPRINTF("Dropped %d bytes!\n", cur - buf);
+     }
+ 
+ #define EAT(c) do {\
+     if (!len--) \
+         return 0; \
+     if ((c = *cur++) == ESC) { \
+         if (!len--) \
+             return 0; \
+         if (*cur++ != ESC) { \
+             DPRINTF("Broken packet %#2x, tossing\n", req); \
+ 		if (qemu_timer_pending(baum->cellCount_timer)) { \
+                 qemu_del_timer(baum->cellCount_timer); \
+                 baum_cellCount_timer_cb(baum); \
+             } \
+             return (cur - 2 - buf); \
+         } \
+     } \
+ } while (0)
+ 
+     EAT(req);
+     switch (req) {
+     case BAUM_REQ_DisplayData:
+     {
+         uint8_t cells[baum->x * baum->y], c;
+         uint8_t text[baum->x * baum->y];
+         uint8_t zero[baum->x * baum->y];
+         int cursor = BRLAPI_CURSOR_OFF;
+         int i;
+ 
+         /* Allow 100ms to complete the DisplayData packet */
+         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);
+             cells[i] = c;
+             if ((c & (BRLAPI_DOT7|BRLAPI_DOT8))
+                     == (BRLAPI_DOT7|BRLAPI_DOT8)) {
+                 cursor = i + 1;
+                 c &= ~(BRLAPI_DOT7|BRLAPI_DOT8);
+             }
+             if (!(c = nabcc_translation[c]))
+                 c = '?';
+             text[i] = c;
+         }
+         qemu_del_timer(baum->cellCount_timer);
+ 
+         memset(zero, 0, sizeof(zero));
+ 
+         brlapi_writeArguments_t wa = {
+             .displayNumber = BRLAPI_DISPLAY_DEFAULT,
+             .regionBegin = 1,
+             .regionSize = baum->x * baum->y,
+             .text = (char *)text,
+             .textSize = baum->x * baum->y,
+             .andMask = zero,
+             .orMask = cells,
+             .cursor = cursor,
+             .charset = (char *)"ISO-8859-1",
+         };
+ 
+         if (brlapi__write(baum->brlapi, &wa) == -1)
+             brlapi_perror("baum brlapi_write");
+         break;
+     }
+     case BAUM_REQ_SetMode:
+     {
+         uint8_t mode, setting;
+         DPRINTF("SetMode\n");
+         EAT(mode);
+         EAT(setting);
+         /* ignore */
+         break;
+     }
+     case BAUM_REQ_SetProtocol:
+     {
+         uint8_t protocol;
+         DPRINTF("SetProtocol\n");
+         EAT(protocol);
+         /* ignore */
+         break;
+     }
+     case BAUM_REQ_GetDeviceIdentity:
+     {
+         uint8_t identity[17] = { BAUM_RSP_DeviceIdentity,
+             'B','a','u','m',' ','V','a','r','i','o' };
+         DPRINTF("GetDeviceIdentity\n");
+         identity[11] = '0' + baum->x / 10;
+         identity[12] = '0' + baum->x % 10;
+         baum_write_packet(baum, identity, sizeof(identity));
+         break;
+     }
+     case BAUM_REQ_GetVersionNumber:
+     {
+         uint8_t version[] = { BAUM_RSP_VersionNumber, 1 }; /* ? */
+         DPRINTF("GetVersionNumber\n");
+         baum_write_packet(baum, version, sizeof(version));
+         break;
+     }
+     case BAUM_REQ_GetSerialNumber:
+     {
+         uint8_t serial[] = { BAUM_RSP_SerialNumber,
+             '0','0','0','0','0','0','0','0' };
+         DPRINTF("GetSerialNumber\n");
+         baum_write_packet(baum, serial, sizeof(serial));
+         break;
+     }
+     case BAUM_REQ_GetKeys:
+     {
+         DPRINTF("Get%0#2x\n", req);
+         /* ignore */
+         break;
+     }
+     default:
+         DPRINTF("unrecognized request %0#2x\n", req);
+         do
+             if (!len--)
+                 return 0;
+         while (*cur++ != ESC);
+         cur--;
+         break;
+     }
+     return cur - buf;
+ }
+ 
+ /* The other end is writing some data.  Store it and try to interpret */
+ static int baum_write(CharDriverState *chr, const uint8_t *buf, int len)
+ {
+     BaumDriverState *baum = chr->opaque;
+     int tocopy, cur, eaten, orig_len = len;
+ 
+     if (!len)
+         return 0;
+     if (!baum->brlapi)
+         return len;
+ 
+     while (len) {
+         /* Complete our buffer as much as possible */
+         tocopy = len;
+         if (tocopy > BUF_SIZE - baum->in_buf_used)
+             tocopy = BUF_SIZE - baum->in_buf_used;
+ 
+         memcpy(baum->in_buf + baum->in_buf_used, buf, tocopy);
+         baum->in_buf_used += tocopy;
+         buf += tocopy;
+         len -= tocopy;
+ 
+         /* Interpret it as much as possible */
+         cur = 0;
+         while (cur < baum->in_buf_used &&
+                 (eaten = baum_eat_packet(baum, baum->in_buf + cur, baum->in_buf_used - cur)))
+             cur += eaten;
+ 
+         /* Shift the remainder */
+         if (cur) {
+             memmove(baum->in_buf, baum->in_buf + cur, baum->in_buf_used - cur);
+             baum->in_buf_used -= cur;
+         }
+ 
+         /* And continue if any data left */
+     }
+     return orig_len;
+ }
+ 
+ /* Send the key code to the other end */
+ static void baum_send_key(BaumDriverState *baum, uint8_t type, uint8_t value) {
+     uint8_t packet[] = { type, value };
+     DPRINTF("writing key %x %x\n", type, value);
+     baum_write_packet(baum, packet, sizeof(packet));
+ }
+ 
+ /* We got some data on the BrlAPI socket */
+ static void baum_chr_read(void *opaque)
+ {
+     BaumDriverState *baum = opaque;
+     brlapi_keyCode_t code;
+     int ret;
+     if (!baum->brlapi)
+         return;
+     while ((ret = brlapi__readKey(baum->brlapi, 0, &code)) == 1) {
+         DPRINTF("got key %"BRLAPI_PRIxKEYCODE"\n", code);
+         /* Emulate */
+         switch (code & BRLAPI_KEY_TYPE_MASK) {
+         case BRLAPI_KEY_TYPE_CMD:
+             switch (code & BRLAPI_KEY_CMD_BLK_MASK) {
+             case BRLAPI_KEY_CMD_ROUTE:
+                 baum_send_key(baum, BAUM_RSP_RoutingKey, (code & BRLAPI_KEY_CMD_ARG_MASK)+1);
+                 baum_send_key(baum, BAUM_RSP_RoutingKey, 0);
+                 break;
+             case 0:
+                 switch (code & BRLAPI_KEY_CMD_ARG_MASK) {
+                 case BRLAPI_KEY_CMD_FWINLT:
+                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2);
+                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                     break;
+                 case BRLAPI_KEY_CMD_FWINRT:
+                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR2);
+                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                     break;
+                 case BRLAPI_KEY_CMD_LNUP:
+                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR1);
+                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                     break;
+                 case BRLAPI_KEY_CMD_LNDN:
+                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR3);
+                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                     break;
+                 case BRLAPI_KEY_CMD_TOP:
+                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TR1);
+                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                     break;
+                 case BRLAPI_KEY_CMD_BOT:
+                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL3|BAUM_TR3);
+                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                     break;
+                 case BRLAPI_KEY_CMD_TOP_LEFT:
+                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1);
+                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                     break;
+                 case BRLAPI_KEY_CMD_BOT_LEFT:
+                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR3);
+                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                     break;
+                 case BRLAPI_KEY_CMD_HOME:
+                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1|BAUM_TR3);
+                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                     break;
+                 case BRLAPI_KEY_CMD_PREFMENU:
+                     baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TL3|BAUM_TR1);
+                     baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                     break;
+                 }
+             }
+             break;
+         case BRLAPI_KEY_TYPE_SYM:
+             break;
+         }
+     }
+     if (ret == -1 && (brlapi_errno != BRLAPI_ERROR_LIBCERR || errno != EINTR)) {
+         brlapi_perror("baum: brlapi_readKey");
+         brlapi__closeConnection(baum->brlapi);
+         g_free(baum->brlapi);
+         baum->brlapi = NULL;
+     }
+ }
+ 
+ static void baum_close(struct CharDriverState *chr)
+ {
+     BaumDriverState *baum = chr->opaque;
+ 
+     qemu_free_timer(baum->cellCount_timer);
+     if (baum->brlapi) {
+         brlapi__closeConnection(baum->brlapi);
+         g_free(baum->brlapi);
+     }
+     g_free(baum);
+ }
+ 
 -CharDriverState *chr_baum_init(QemuOpts *opts)
++static CharDriverState *chr_baum_init(QemuOpts *opts)
+ {
+     BaumDriverState *baum;
+     CharDriverState *chr;
+     brlapi_handle_t *handle;
+ #ifdef CONFIG_SDL
+     SDL_SysWMinfo info;
+ #endif
+     int tty;
+ 
+     baum = g_malloc0(sizeof(BaumDriverState));
+     baum->chr = chr = g_malloc0(sizeof(CharDriverState));
+ 
+     chr->opaque = baum;
+     chr->chr_write = baum_write;
+     chr->chr_accept_input = baum_accept_input;
+     chr->chr_close = baum_close;
+ 
+     handle = g_malloc0(brlapi_getHandleSize());
+     baum->brlapi = handle;
+ 
+     baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL);
+     if (baum->brlapi_fd == -1) {
+         brlapi_perror("baum_init: brlapi_openConnection");
+         goto fail_handle;
+     }
+ 
+     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");
+         goto fail;
+     }
+ 
+ #ifdef CONFIG_SDL
+     memset(&info, 0, sizeof(info));
+     SDL_VERSION(&info.version);
+     if (SDL_GetWMInfo(&info))
+         tty = info.info.x11.wmwindow;
+     else
+ #endif
+         tty = BRLAPI_TTY_DEFAULT;
+ 
+     if (brlapi__enterTtyMode(handle, tty, NULL) == -1) {
+         brlapi_perror("baum_init: brlapi_enterTtyMode");
+         goto fail;
+     }
+ 
+     qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
+ 
+     qemu_chr_generic_open(chr);
+ 
+     return chr;
+ 
+ fail:
+     qemu_free_timer(baum->cellCount_timer);
+     brlapi__closeConnection(handle);
+ fail_handle:
+     g_free(handle);
+     g_free(chr);
+     g_free(baum);
+     return NULL;
+ }
++
++static void register_types(void)
++{
++    register_char_driver("braille", chr_baum_init);
++}
++
++type_init(register_types);
diff --cc backends/msmouse.c
index 0000000,bf2ff2a..407ec87
mode 000000,100644..100644
--- a/backends/msmouse.c
+++ b/backends/msmouse.c
@@@ -1,0 -1,78 +1,84 @@@
+ /*
+  * QEMU Microsoft serial mouse emulation
+  *
+  * Copyright (c) 2008 Lubomir Rintel
+  *
+  * 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 <stdlib.h>
+ #include "qemu-common.h"
+ #include "char/char.h"
+ #include "ui/console.h"
 -#include "char/msmouse.h"
+ 
+ #define MSMOUSE_LO6(n) ((n) & 0x3f)
+ #define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6)
+ 
+ static void msmouse_event(void *opaque,
+                           int dx, int dy, int dz, int buttons_state)
+ {
+     CharDriverState *chr = (CharDriverState *)opaque;
+ 
+     unsigned char bytes[4] = { 0x40, 0x00, 0x00, 0x00 };
+ 
+     /* Movement deltas */
+     bytes[0] |= (MSMOUSE_HI2(dy) << 2) | MSMOUSE_HI2(dx);
+     bytes[1] |= MSMOUSE_LO6(dx);
+     bytes[2] |= MSMOUSE_LO6(dy);
+ 
+     /* Buttons */
+     bytes[0] |= (buttons_state & 0x01 ? 0x20 : 0x00);
+     bytes[0] |= (buttons_state & 0x02 ? 0x10 : 0x00);
+     bytes[3] |= (buttons_state & 0x04 ? 0x20 : 0x00);
+ 
+     /* We always send the packet of, so that we do not have to keep track
+        of previous state of the middle button. This can potentially confuse
+        some very old drivers for two button mice though. */
+     qemu_chr_be_write(chr, bytes, 4);
+ }
+ 
+ static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf, int len)
+ {
+     /* Ignore writes to mouse port */
+     return len;
+ }
+ 
+ static void msmouse_chr_close (struct CharDriverState *chr)
+ {
+     g_free (chr);
+ }
+ 
 -CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts)
++static CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts)
+ {
+     CharDriverState *chr;
+ 
+     chr = g_malloc0(sizeof(CharDriverState));
+     chr->chr_write = msmouse_chr_write;
+     chr->chr_close = msmouse_chr_close;
+ 
+     qemu_add_mouse_event_handler(msmouse_event, chr, 0, "QEMU Microsoft Mouse");
+ 
+     return chr;
+ }
++
++static void register_types(void)
++{
++    register_char_driver("msmouse", qemu_chr_open_msmouse);
++}
++
++type_init(register_types);
diff --cc hw/a15mpcore.c
index 97abe41,d973d53..648656d
--- a/hw/a15mpcore.c
+++ b/hw/a15mpcore.c
@@@ -18,8 -18,7 +18,8 @@@
   * with this program; if not, see <http://www.gnu.org/licenses/>.
   */
  
- #include "sysbus.h"
+ #include "hw/sysbus.h"
 +#include "sysemu/kvm.h"
  
  /* A15MP private memory region.  */
  
diff --cc hw/arm/Makefile.objs
index 0e7df60,aebbc86..2d9c69d
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@@ -10,28 -8,28 +8,30 @@@ obj-y += exynos4210_uart.o exynos4210_p
  obj-y += exynos4210_pmu.o exynos4210_mct.o exynos4210_fimd.o
  obj-y += exynos4210_rtc.o exynos4210_i2c.o
  obj-y += arm_mptimer.o a15mpcore.o
- obj-y += armv7m.o armv7m_nvic.o stellaris.o stellaris_enet.o
- obj-y += highbank.o
- obj-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
+ obj-y += armv7m_nvic.o stellaris_enet.o
+ obj-y += pxa2xx_timer.o pxa2xx_dma.o
  obj-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
- obj-y += gumstix.o
- obj-y += zaurus.o ide/microdrive.o spitz.o tosa.o tc6393xb.o
- obj-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o \
+ obj-y += zaurus.o ide/microdrive.o tc6393xb.o
+ obj-y += omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o \
                  omap_gpio.o omap_intc.o omap_uart.o
- obj-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
+ obj-y += omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
                  omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o omap_l4.o
- obj-y += omap_sx1.o palm.o tsc210x.o
- obj-y += nseries.o blizzard.o onenand.o cbus.o tusb6010.o usb/hcd-musb.o
- obj-y += mst_fpga.o mainstone.o
- obj-y += z2.o
- obj-y += musicpal.o bitbang_i2c.o marvell_88w8618_audio.o
+ obj-y += tsc210x.o
+ obj-y += blizzard.o onenand.o cbus.o tusb6010.o usb/hcd-musb.o
+ obj-y += mst_fpga.o
+ obj-y += bitbang_i2c.o marvell_88w8618_audio.o
  obj-y += framebuffer.o
- obj-y += vexpress.o
  obj-y += strongarm.o
- obj-y += collie.o
  obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
- obj-y += kzm.o
 +obj-$(CONFIG_FDT) += ../device_tree.o
 +obj-$(CONFIG_KVM) += kvm/arm_gic.o
  
  obj-y := $(addprefix ../,$(obj-y))
+ 
+ obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
+ obj-y += integratorcp.o kzm.o mainstone.o musicpal.o nseries.o
+ obj-y += omap_sx1.o palm.o pic_cpu.o realview.o spitz.o stellaris.o
+ obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
+ 
+ obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
+ obj-y += omap1.o omap2.o
diff --cc hw/arm/pic_cpu.c
index 0000000,a7ad893..8223600
mode 000000,100644..100644
--- a/hw/arm/pic_cpu.c
+++ b/hw/arm/pic_cpu.c
@@@ -1,0 -1,40 +1,66 @@@
+ /*
+  * Generic ARM Programmable Interrupt Controller support.
+  *
+  * Copyright (c) 2006 CodeSourcery.
+  * Written by Paul Brook
+  *
+  * This code is licensed under the LGPL
+  */
+ 
+ #include "hw/hw.h"
+ #include "hw/arm-misc.h"
++#include "sysemu/kvm.h"
+ 
+ /* Input 0 is IRQ and input 1 is FIQ.  */
+ static void arm_pic_cpu_handler(void *opaque, int irq, int level)
+ {
+     ARMCPU *cpu = opaque;
+     CPUARMState *env = &cpu->env;
+ 
+     switch (irq) {
+     case ARM_PIC_CPU_IRQ:
+         if (level)
+             cpu_interrupt(env, CPU_INTERRUPT_HARD);
+         else
+             cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+         break;
+     case ARM_PIC_CPU_FIQ:
+         if (level)
+             cpu_interrupt(env, CPU_INTERRUPT_FIQ);
+         else
+             cpu_reset_interrupt(env, CPU_INTERRUPT_FIQ);
+         break;
+     default:
+         hw_error("arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
+     }
+ }
+ 
++static void kvm_arm_pic_cpu_handler(void *opaque, int irq, int level)
++{
++#ifdef CONFIG_KVM
++    ARMCPU *cpu = opaque;
++    CPUState *cs = CPU(cpu);
++    int kvm_irq = KVM_ARM_IRQ_TYPE_CPU << KVM_ARM_IRQ_TYPE_SHIFT;
++
++    switch (irq) {
++    case ARM_PIC_CPU_IRQ:
++        kvm_irq |= KVM_ARM_IRQ_CPU_IRQ;
++        break;
++    case ARM_PIC_CPU_FIQ:
++        kvm_irq |= KVM_ARM_IRQ_CPU_FIQ;
++        break;
++    default:
++        hw_error("kvm_arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
++    }
++    kvm_irq |= cs->cpu_index << KVM_ARM_IRQ_VCPU_SHIFT;
++    kvm_set_irq(kvm_state, kvm_irq, level ? 1 : 0);
++#endif
++}
++
+ qemu_irq *arm_pic_init_cpu(ARMCPU *cpu)
+ {
++    if (kvm_enabled()) {
++        return qemu_allocate_irqs(kvm_arm_pic_cpu_handler, cpu, 2);
++    }
+     return qemu_allocate_irqs(arm_pic_cpu_handler, cpu, 2);
+ }
diff --cc hw/dataplane/virtio-blk.c
index aa9b040,8319c94..dfe5f9b
--- a/hw/dataplane/virtio-blk.c
+++ b/hw/dataplane/virtio-blk.c
@@@ -14,13 -14,15 +14,15 @@@
  
  #include "trace.h"
  #include "qemu/iov.h"
 -#include "event-poll.h"
  #include "qemu/thread.h"
+ #include "qemu/error-report.h"
  #include "vring.h"
  #include "ioq.h"
  #include "migration/migration.h"
+ #include "block/block.h"
  #include "hw/virtio-blk.h"
 -#include "virtio-blk.h"
 +#include "hw/dataplane/virtio-blk.h"
 +#include "block/aio.h"
  
  enum {
      SEG_MAX = 126,                  /* maximum number of I/O segments */
diff --cc hw/i386/pc_piix.c
index 0000000,73a8656..0ee3b3b
mode 000000,100644..100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@@ -1,0 -1,713 +1,717 @@@
+ /*
+  * QEMU PC System Emulator
+  *
+  * Copyright (c) 2003-2004 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 <glib.h>
+ 
+ #include "hw/hw.h"
+ #include "hw/pc.h"
+ #include "hw/apic.h"
+ #include "hw/pci/pci.h"
+ #include "hw/pci/pci_ids.h"
+ #include "hw/usb.h"
+ #include "net/net.h"
+ #include "hw/boards.h"
+ #include "hw/ide.h"
+ #include "sysemu/kvm.h"
+ #include "hw/kvm/clock.h"
+ #include "sysemu/sysemu.h"
+ #include "hw/sysbus.h"
+ #include "sysemu/arch_init.h"
+ #include "sysemu/blockdev.h"
+ #include "hw/smbus.h"
+ #include "hw/xen.h"
+ #include "exec/memory.h"
+ #include "exec/address-spaces.h"
+ #include "cpu.h"
+ #ifdef CONFIG_XEN
+ #  include <xen/hvm/hvm_info_table.h>
+ #endif
+ 
+ #define MAX_IDE_BUS 2
+ 
+ static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
+ static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
+ static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
+ 
+ /* PC hardware initialisation */
+ static void pc_init1(MemoryRegion *system_memory,
+                      MemoryRegion *system_io,
+                      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,
+                      int pci_enabled,
+                      int kvmclock_enabled)
+ {
+     int i;
+     ram_addr_t below_4g_mem_size, above_4g_mem_size;
+     PCIBus *pci_bus;
+     ISABus *isa_bus;
+     PCII440FXState *i440fx_state;
+     int piix3_devfn = -1;
+     qemu_irq *cpu_irq;
+     qemu_irq *gsi;
+     qemu_irq *i8259;
+     qemu_irq *smi_irq;
+     GSIState *gsi_state;
+     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+     BusState *idebus[MAX_IDE_BUS];
+     ISADevice *rtc_state;
+     ISADevice *floppy;
+     MemoryRegion *ram_memory;
+     MemoryRegion *pci_memory;
+     MemoryRegion *rom_memory;
+     void *fw_cfg = NULL;
+ 
+     pc_cpus_init(cpu_model);
+     pc_acpi_init("acpi-dsdt.aml");
+ 
+     if (kvmclock_enabled) {
+         kvmclock_create();
+     }
+ 
+     if (ram_size >= 0xe0000000 ) {
+         above_4g_mem_size = ram_size - 0xe0000000;
+         below_4g_mem_size = 0xe0000000;
+     } else {
+         above_4g_mem_size = 0;
+         below_4g_mem_size = ram_size;
+     }
+ 
+     if (pci_enabled) {
+         pci_memory = g_new(MemoryRegion, 1);
+         memory_region_init(pci_memory, "pci", INT64_MAX);
+         rom_memory = pci_memory;
+     } else {
+         pci_memory = NULL;
+         rom_memory = system_memory;
+     }
+ 
+     /* allocate ram and load rom/bios */
+     if (!xen_enabled()) {
+         fw_cfg = pc_memory_init(system_memory,
+                        kernel_filename, kernel_cmdline, initrd_filename,
+                        below_4g_mem_size, above_4g_mem_size,
+                        rom_memory, &ram_memory);
+     }
+ 
+     gsi_state = g_malloc0(sizeof(*gsi_state));
+     if (kvm_irqchip_in_kernel()) {
+         kvm_pc_setup_irq_routing(pci_enabled);
+         gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
+                                  GSI_NUM_PINS);
+     } else {
+         gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
+     }
+ 
+     if (pci_enabled) {
+         pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
+                               system_memory, system_io, ram_size,
+                               below_4g_mem_size,
+                               0x100000000ULL - below_4g_mem_size,
+                               0x100000000ULL + above_4g_mem_size,
+                               (sizeof(hwaddr) == 4
+                                ? 0
+                                : ((uint64_t)1 << 62)),
+                               pci_memory, ram_memory);
+     } else {
+         pci_bus = NULL;
+         i440fx_state = NULL;
+         isa_bus = isa_bus_new(NULL, system_io);
+         no_hpet = 1;
+     }
+     isa_bus_irqs(isa_bus, gsi);
+ 
+     if (kvm_irqchip_in_kernel()) {
+         i8259 = kvm_i8259_init(isa_bus);
+     } else if (xen_enabled()) {
+         i8259 = xen_interrupt_controller_init();
+     } else {
+         cpu_irq = pc_allocate_cpu_irq();
+         i8259 = i8259_init(isa_bus, cpu_irq[0]);
+     }
+ 
+     for (i = 0; i < ISA_NUM_IRQS; i++) {
+         gsi_state->i8259_irq[i] = i8259[i];
+     }
+     if (pci_enabled) {
+         ioapic_init_gsi(gsi_state, "i440fx");
+     }
+ 
+     pc_register_ferr_irq(gsi[13]);
+ 
+     pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
+     if (xen_enabled()) {
+         pci_create_simple(pci_bus, -1, "xen-platform");
+     }
+ 
+     /* init basic PC hardware */
+     pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled());
+ 
+     pc_nic_init(isa_bus, pci_bus);
+ 
+     ide_drive_get(hd, MAX_IDE_BUS);
+     if (pci_enabled) {
+         PCIDevice *dev;
+         if (xen_enabled()) {
+             dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
+         } else {
+             dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
+         }
+         idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
+         idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
+     } else {
+         for(i = 0; i < MAX_IDE_BUS; i++) {
+             ISADevice *dev;
+             dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
+                                ide_irq[i],
+                                hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
+             idebus[i] = qdev_get_child_bus(&dev->qdev, "ide.0");
+         }
+     }
+ 
+     audio_init(isa_bus, pci_enabled ? pci_bus : NULL);
+ 
+     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
+                  floppy, idebus[0], idebus[1], rtc_state);
+ 
+     if (pci_enabled && usb_enabled(false)) {
+         pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
+     }
+ 
+     if (pci_enabled && acpi_enabled) {
+         i2c_bus *smbus;
+ 
+         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,
+                               gsi[9], *smi_irq,
+                               kvm_enabled(), fw_cfg);
+         smbus_eeprom_init(smbus, 8, NULL, 0);
+     }
+ 
+     if (pci_enabled) {
+         pc_pci_device_init(pci_bus);
+     }
+ }
+ 
+ static void pc_init_pci(QEMUMachineInitArgs *args)
+ {
+     ram_addr_t ram_size = args->ram_size;
+     const char *cpu_model = args->cpu_model;
+     const char *kernel_filename = args->kernel_filename;
+     const char *kernel_cmdline = args->kernel_cmdline;
+     const char *initrd_filename = args->initrd_filename;
+     const char *boot_device = args->boot_device;
+     pc_init1(get_system_memory(),
+              get_system_io(),
+              ram_size, boot_device,
+              kernel_filename, kernel_cmdline,
+              initrd_filename, cpu_model, 1, 1);
+ }
+ 
+ static void pc_init_pci_1_3(QEMUMachineInitArgs *args)
+ {
+     enable_compat_apic_id_mode();
+     pc_init_pci(args);
+ }
+ 
+ /* PC machine init function for pc-0.14 to pc-1.2 */
+ static void pc_init_pci_1_2(QEMUMachineInitArgs *args)
+ {
+     disable_kvm_pv_eoi();
+     pc_init_pci_1_3(args);
+ }
+ 
+ /* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */
+ static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args)
+ {
+     ram_addr_t ram_size = args->ram_size;
+     const char *cpu_model = args->cpu_model;
+     const char *kernel_filename = args->kernel_filename;
+     const char *kernel_cmdline = args->kernel_cmdline;
+     const char *initrd_filename = args->initrd_filename;
+     const char *boot_device = args->boot_device;
+     disable_kvm_pv_eoi();
+     enable_compat_apic_id_mode();
+     pc_init1(get_system_memory(),
+              get_system_io(),
+              ram_size, boot_device,
+              kernel_filename, kernel_cmdline,
+              initrd_filename, cpu_model, 1, 0);
+ }
+ 
+ static void pc_init_isa(QEMUMachineInitArgs *args)
+ {
+     ram_addr_t ram_size = args->ram_size;
+     const char *cpu_model = args->cpu_model;
+     const char *kernel_filename = args->kernel_filename;
+     const char *kernel_cmdline = args->kernel_cmdline;
+     const char *initrd_filename = args->initrd_filename;
+     const char *boot_device = args->boot_device;
+     if (cpu_model == NULL)
+         cpu_model = "486";
+     disable_kvm_pv_eoi();
+     enable_compat_apic_id_mode();
+     pc_init1(get_system_memory(),
+              get_system_io(),
+              ram_size, boot_device,
+              kernel_filename, kernel_cmdline,
+              initrd_filename, cpu_model, 0, 1);
+ }
+ 
+ #ifdef CONFIG_XEN
+ static void pc_xen_hvm_init(QEMUMachineInitArgs *args)
+ {
+     if (xen_hvm_init() != 0) {
+         hw_error("xen hardware virtual machine initialisation failed");
+     }
+     pc_init_pci_no_kvmclock(args);
+     xen_vcpu_init();
+ }
+ #endif
+ 
+ static QEMUMachine pc_i440fx_machine_v1_5 = {
+     .name = "pc-i440fx-1.5",
+     .alias = "pc",
+     .desc = "Standard PC (i440FX + PIIX, 1996)",
+     .init = pc_init_pci,
+     .max_cpus = 255,
+     .is_default = 1,
+     DEFAULT_MACHINE_OPTIONS,
+ };
+ 
+ static QEMUMachine pc_i440fx_machine_v1_4 = {
+     .name = "pc-i440fx-1.4",
+     .desc = "Standard PC (i440FX + PIIX, 1996)",
+     .init = pc_init_pci,
+     .max_cpus = 255,
+     .compat_props = (GlobalProperty[]) {
+         PC_COMPAT_1_4,
+         { /* end of list */ }
+     },
+     DEFAULT_MACHINE_OPTIONS,
+ };
+ 
+ #define PC_COMPAT_1_3 \
+ 	PC_COMPAT_1_4, \
+         {\
+             .driver   = "usb-tablet",\
+             .property = "usb_version",\
+             .value    = stringify(1),\
+         },{\
+             .driver   = "virtio-net-pci",\
+             .property = "ctrl_mac_addr",\
+             .value    = "off",      \
+         },{ \
+             .driver   = "virtio-net-pci", \
+             .property = "mq", \
+             .value    = "off", \
++        }, {\
++            .driver   = "e1000",\
++            .property = "autonegotiation",\
++            .value    = "off",\
+         }
+ 
+ static QEMUMachine pc_machine_v1_3 = {
+     .name = "pc-1.3",
+     .desc = "Standard PC",
+     .init = pc_init_pci_1_3,
+     .max_cpus = 255,
+     .compat_props = (GlobalProperty[]) {
+         PC_COMPAT_1_3,
+         { /* end of list */ }
+     },
+     DEFAULT_MACHINE_OPTIONS,
+ };
+ 
+ #define PC_COMPAT_1_2 \
+         PC_COMPAT_1_3,\
+         {\
+             .driver   = "nec-usb-xhci",\
+             .property = "msi",\
+             .value    = "off",\
+         },{\
+             .driver   = "nec-usb-xhci",\
+             .property = "msix",\
+             .value    = "off",\
+         },{\
+             .driver   = "ivshmem",\
+             .property = "use64",\
+             .value    = "0",\
+         },{\
+             .driver   = "qxl",\
+             .property = "revision",\
+             .value    = stringify(3),\
+         },{\
+             .driver   = "qxl-vga",\
+             .property = "revision",\
+             .value    = stringify(3),\
+         },{\
+             .driver   = "VGA",\
+             .property = "mmio",\
+             .value    = "off",\
+         }
+ 
+ static QEMUMachine pc_machine_v1_2 = {
+     .name = "pc-1.2",
+     .desc = "Standard PC",
+     .init = pc_init_pci_1_2,
+     .max_cpus = 255,
+     .compat_props = (GlobalProperty[]) {
+         PC_COMPAT_1_2,
+         { /* end of list */ }
+     },
+     DEFAULT_MACHINE_OPTIONS,
+ };
+ 
+ #define PC_COMPAT_1_1 \
+         PC_COMPAT_1_2,\
+         {\
+             .driver   = "virtio-scsi-pci",\
+             .property = "hotplug",\
+             .value    = "off",\
+         },{\
+             .driver   = "virtio-scsi-pci",\
+             .property = "param_change",\
+             .value    = "off",\
+         },{\
+             .driver   = "VGA",\
+             .property = "vgamem_mb",\
+             .value    = stringify(8),\
+         },{\
+             .driver   = "vmware-svga",\
+             .property = "vgamem_mb",\
+             .value    = stringify(8),\
+         },{\
+             .driver   = "qxl-vga",\
+             .property = "vgamem_mb",\
+             .value    = stringify(8),\
+         },{\
+             .driver   = "qxl",\
+             .property = "vgamem_mb",\
+             .value    = stringify(8),\
+         },{\
+             .driver   = "virtio-blk-pci",\
+             .property = "config-wce",\
+             .value    = "off",\
+         }
+ 
+ static QEMUMachine pc_machine_v1_1 = {
+     .name = "pc-1.1",
+     .desc = "Standard PC",
+     .init = pc_init_pci_1_2,
+     .max_cpus = 255,
+     .compat_props = (GlobalProperty[]) {
+         PC_COMPAT_1_1,
+         { /* end of list */ }
+     },
+     DEFAULT_MACHINE_OPTIONS,
+ };
+ 
+ #define PC_COMPAT_1_0 \
+         PC_COMPAT_1_1,\
+         {\
+             .driver   = "pc-sysfw",\
+             .property = "rom_only",\
+             .value    = stringify(1),\
+         }, {\
+             .driver   = "isa-fdc",\
+             .property = "check_media_rate",\
+             .value    = "off",\
+         }, {\
+             .driver   = "virtio-balloon-pci",\
+             .property = "class",\
+             .value    = stringify(PCI_CLASS_MEMORY_RAM),\
+         },{\
+             .driver   = "apic",\
+             .property = "vapic",\
+             .value    = "off",\
+         },{\
+             .driver   = TYPE_USB_DEVICE,\
+             .property = "full-path",\
+             .value    = "no",\
+         }
+ 
+ static QEMUMachine pc_machine_v1_0 = {
+     .name = "pc-1.0",
+     .desc = "Standard PC",
+     .init = pc_init_pci_1_2,
+     .max_cpus = 255,
+     .compat_props = (GlobalProperty[]) {
+         PC_COMPAT_1_0,
+         { /* end of list */ }
+     },
+     .hw_version = "1.0",
+     DEFAULT_MACHINE_OPTIONS,
+ };
+ 
+ #define PC_COMPAT_0_15 \
+         PC_COMPAT_1_0
+ 
+ static QEMUMachine pc_machine_v0_15 = {
+     .name = "pc-0.15",
+     .desc = "Standard PC",
+     .init = pc_init_pci_1_2,
+     .max_cpus = 255,
+     .compat_props = (GlobalProperty[]) {
+         PC_COMPAT_0_15,
+         { /* end of list */ }
+     },
+     .hw_version = "0.15",
+     DEFAULT_MACHINE_OPTIONS,
+ };
+ 
+ #define PC_COMPAT_0_14 \
+         PC_COMPAT_0_15,\
+         {\
+             .driver   = "virtio-blk-pci",\
+             .property = "event_idx",\
+             .value    = "off",\
+         },{\
+             .driver   = "virtio-serial-pci",\
+             .property = "event_idx",\
+             .value    = "off",\
+         },{\
+             .driver   = "virtio-net-pci",\
+             .property = "event_idx",\
+             .value    = "off",\
+         },{\
+             .driver   = "virtio-balloon-pci",\
+             .property = "event_idx",\
+             .value    = "off",\
+         }
+ 
+ static QEMUMachine pc_machine_v0_14 = {
+     .name = "pc-0.14",
+     .desc = "Standard PC",
+     .init = pc_init_pci_1_2,
+     .max_cpus = 255,
+     .compat_props = (GlobalProperty[]) {
+         PC_COMPAT_0_14, 
+         {
+             .driver   = "qxl",
+             .property = "revision",
+             .value    = stringify(2),
+         },{
+             .driver   = "qxl-vga",
+             .property = "revision",
+             .value    = stringify(2),
+         },
+         { /* end of list */ }
+     },
+     .hw_version = "0.14",
+     DEFAULT_MACHINE_OPTIONS,
+ };
+ 
+ #define PC_COMPAT_0_13 \
+         PC_COMPAT_0_14,\
+         {\
+             .driver   = TYPE_PCI_DEVICE,\
+             .property = "command_serr_enable",\
+             .value    = "off",\
+         },{\
+             .driver   = "AC97",\
+             .property = "use_broken_id",\
+             .value    = stringify(1),\
+         }
+ 
+ static QEMUMachine pc_machine_v0_13 = {
+     .name = "pc-0.13",
+     .desc = "Standard PC",
+     .init = pc_init_pci_no_kvmclock,
+     .max_cpus = 255,
+     .compat_props = (GlobalProperty[]) {
+         PC_COMPAT_0_13,
+         {
+             .driver   = "virtio-9p-pci",
+             .property = "vectors",
+             .value    = stringify(0),
+         },{
+             .driver   = "VGA",
+             .property = "rombar",
+             .value    = stringify(0),
+         },{
+             .driver   = "vmware-svga",
+             .property = "rombar",
+             .value    = stringify(0),
+         },
+         { /* end of list */ }
+     },
+     .hw_version = "0.13",
+     DEFAULT_MACHINE_OPTIONS,
+ };
+ 
+ #define PC_COMPAT_0_12 \
+         PC_COMPAT_0_13,\
+         {\
+             .driver   = "virtio-serial-pci",\
+             .property = "max_ports",\
+             .value    = stringify(1),\
+         },{\
+             .driver   = "virtio-serial-pci",\
+             .property = "vectors",\
+             .value    = stringify(0),\
+         }
+ 
+ static QEMUMachine pc_machine_v0_12 = {
+     .name = "pc-0.12",
+     .desc = "Standard PC",
+     .init = pc_init_pci_no_kvmclock,
+     .max_cpus = 255,
+     .compat_props = (GlobalProperty[]) {
+         PC_COMPAT_0_12,
+         {
+             .driver   = "VGA",
+             .property = "rombar",
+             .value    = stringify(0),
+         },{
+             .driver   = "vmware-svga",
+             .property = "rombar",
+             .value    = stringify(0),
+         },
+         { /* end of list */ }
+     },
+     .hw_version = "0.12",
+     DEFAULT_MACHINE_OPTIONS,
+ };
+ 
+ #define PC_COMPAT_0_11 \
+         PC_COMPAT_0_12,\
+         {\
+             .driver   = "virtio-blk-pci",\
+             .property = "vectors",\
+             .value    = stringify(0),\
+         },{\
+             .driver   = TYPE_PCI_DEVICE,\
+             .property = "rombar",\
+             .value    = stringify(0),\
+         }
+ 
+ static QEMUMachine pc_machine_v0_11 = {
+     .name = "pc-0.11",
+     .desc = "Standard PC, qemu 0.11",
+     .init = pc_init_pci_no_kvmclock,
+     .max_cpus = 255,
+     .compat_props = (GlobalProperty[]) {
+         PC_COMPAT_0_11,
+         {
+             .driver   = "ide-drive",
+             .property = "ver",
+             .value    = "0.11",
+         },{
+             .driver   = "scsi-disk",
+             .property = "ver",
+             .value    = "0.11",
+         },
+         { /* end of list */ }
+     },
+     .hw_version = "0.11",
+     DEFAULT_MACHINE_OPTIONS,
+ };
+ 
+ static QEMUMachine pc_machine_v0_10 = {
+     .name = "pc-0.10",
+     .desc = "Standard PC, qemu 0.10",
+     .init = pc_init_pci_no_kvmclock,
+     .max_cpus = 255,
+     .compat_props = (GlobalProperty[]) {
+         PC_COMPAT_0_11,
+         {
+             .driver   = "virtio-blk-pci",
+             .property = "class",
+             .value    = stringify(PCI_CLASS_STORAGE_OTHER),
+         },{
+             .driver   = "virtio-serial-pci",
+             .property = "class",
+             .value    = stringify(PCI_CLASS_DISPLAY_OTHER),
+         },{
+             .driver   = "virtio-net-pci",
+             .property = "vectors",
+             .value    = stringify(0),
+         },{
+             .driver   = "ide-drive",
+             .property = "ver",
+             .value    = "0.10",
+         },{
+             .driver   = "scsi-disk",
+             .property = "ver",
+             .value    = "0.10",
+         },
+         { /* end of list */ }
+     },
+     .hw_version = "0.10",
+     DEFAULT_MACHINE_OPTIONS,
+ };
+ 
+ static QEMUMachine isapc_machine = {
+     .name = "isapc",
+     .desc = "ISA-only PC",
+     .init = pc_init_isa,
+     .max_cpus = 1,
+     .compat_props = (GlobalProperty[]) {
+         {
+             .driver   = "pc-sysfw",
+             .property = "rom_only",
+             .value    = stringify(1),
+         },
+         { /* end of list */ }
+     },
+     DEFAULT_MACHINE_OPTIONS,
+ };
+ 
+ #ifdef CONFIG_XEN
+ static QEMUMachine xenfv_machine = {
+     .name = "xenfv",
+     .desc = "Xen Fully-virtualized PC",
+     .init = pc_xen_hvm_init,
+     .max_cpus = HVM_MAX_VCPUS,
+     .default_machine_opts = "accel=xen",
+     DEFAULT_MACHINE_OPTIONS,
+ };
+ #endif
+ 
+ static void pc_machine_init(void)
+ {
+     qemu_register_machine(&pc_i440fx_machine_v1_5);
+     qemu_register_machine(&pc_i440fx_machine_v1_4);
+     qemu_register_machine(&pc_machine_v1_3);
+     qemu_register_machine(&pc_machine_v1_2);
+     qemu_register_machine(&pc_machine_v1_1);
+     qemu_register_machine(&pc_machine_v1_0);
+     qemu_register_machine(&pc_machine_v0_15);
+     qemu_register_machine(&pc_machine_v0_14);
+     qemu_register_machine(&pc_machine_v0_13);
+     qemu_register_machine(&pc_machine_v0_12);
+     qemu_register_machine(&pc_machine_v0_11);
+     qemu_register_machine(&pc_machine_v0_10);
+     qemu_register_machine(&isapc_machine);
+ #ifdef CONFIG_XEN
+     qemu_register_machine(&xenfv_machine);
+ #endif
+ }
+ 
+ machine_init(pc_machine_init);
commit 6a245c666d02210b8461952eccc17379fdeedd9f
Merge: 6d06368 db2d5eb
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Sun Mar 10 19:33:03 2013 -0500

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging
    
    # By Lei Li (2) and others
    # Via Stefan Hajnoczi
    * stefanha/trivial-patches:
      Fix the wrong description in qemu manual
      pci_host: Drop write-only address_space field
      rng-random: Use qemu_open / qemu_close
      configure: Require at least spice-protocol-0.12.3
      osdep: replace setsockopt by qemu_setsockopt
      lm32: remove unused function
      rtc-test: Fix test failures with recent glib
      configure: Create link to icon bitmap for out-of-tree builds

commit 6d06368d6bebad74fd16ef76a6bbea0c1cb63c9a
Merge: 44ab9ed 0c92e0e
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Sun Mar 10 19:30:45 2013 -0500

    Merge remote-tracking branch 'bonzini/scsi-next' into staging
    
    # By Paolo Bonzini (4) and Peter Lieven (2)
    # Via Paolo Bonzini
    * bonzini/scsi-next:
      scsi-disk: handle io_canceled uniformly and correctly
      scsi-disk: do not complete canceled UNMAP requests
      scsi: do not call scsi_read_data/scsi_write_data for a canceled request
      iscsi: look for pkg-config file too
      iscsi: add iscsi_truncate support
      iscsi: retry read, write, flush and unmap on unit attention check conditions

commit 44ab9ed4f859fc6f691ba433c24d354ba93f056f
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 9 09:56:04 2013 +0000

    qemu-char: fix win32 build
    
    96c6384776d631839a9c8fe02bf135f9ba22586c did not adjust
    Win32 #ifdeffery properly, breaking build in later commits. Fix.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    Tested-by: Igor Mitsyanko <i.mitsyanko at gmail.com>
    Message-id: 0ba5565b1ed44380c57d4a5fab86e9549f581ebf.1362822910.git.blauwirbel at gmail.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index b82d643..04aa589 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -535,8 +535,6 @@ int send_all(int fd, const void *_buf, int len1)
 }
 #endif /* !_WIN32 */
 
-#ifndef _WIN32
-
 typedef struct IOWatchPoll
 {
     GSource *src;
@@ -634,6 +632,7 @@ static guint io_add_watch_poll(GIOChannel *channel,
     return tag;
 }
 
+#ifndef _WIN32
 static GIOChannel *io_channel_from_fd(int fd)
 {
     GIOChannel *chan;
@@ -649,6 +648,7 @@ static GIOChannel *io_channel_from_fd(int fd)
 
     return chan;
 }
+#endif
 
 static GIOChannel *io_channel_from_socket(int fd)
 {
@@ -699,6 +699,8 @@ static int io_channel_send_all(GIOChannel *fd, const void *_buf, int len1)
     return len1 - len;
 }
 
+#ifndef _WIN32
+
 typedef struct FDCharDriver {
     CharDriverState *chr;
     GIOChannel *fd_in, *fd_out;
commit 7830cf78ac00643930503732834c00387e9e75ff
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 9 09:56:03 2013 +0000

    baum: fix build
    
    08744c98115cfa144ed3493556024e400b2e2573 removed hw/baum.h
    but did not adjust hw/baum.c, breaking build. Fix.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    Message-id: c50406bda98f8b277e8b9004a0012fa5e5c124d0.1362822910.git.blauwirbel at gmail.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/baum.c b/hw/baum.c
index d75b150..d8919d5 100644
--- a/hw/baum.c
+++ b/hw/baum.c
@@ -25,7 +25,6 @@
 #include "char/char.h"
 #include "qemu/timer.h"
 #include "usb.h"
-#include "baum.h"
 #include <brlapi.h>
 #include <brlapi_constants.h>
 #include <brlapi_keycodes.h>
commit a4960ef34829c355fdf25b8ee6b869c92393e366
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Mar 5 08:54:41 2013 -0800

    tcg: Don't make exitreq flag a local temporary
    
    The value is not actually live across basic blocks, so there's no
    need for the local property.  This eliminates storing the temporary
    to its home location at the branch.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h
index 4e3b17b..4fc7b29 100644
--- a/include/exec/gen-icount.h
+++ b/include/exec/gen-icount.h
@@ -15,7 +15,7 @@ static inline void gen_tb_start(void)
     TCGv_i32 flag;
 
     exitreq_label = gen_new_label();
-    flag = tcg_temp_local_new_i32();
+    flag = tcg_temp_new_i32();
     tcg_gen_ld_i32(flag, cpu_env,
                    offsetof(CPUState, tcg_exit_req) - ENV_OFFSET);
     tcg_gen_brcondi_i32(TCG_COND_NE, flag, 0, exitreq_label);
commit 916359f66f838481b4a37a45ab27ccd0474ae487
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu Feb 21 16:26:47 2013 +0100

    Makefile: Add subdir dependency on config-devices-all.mak
    
    What 23bf49b5eca716aaad073f2b47613434e1515cb5 really seemed to try to
    fix is that Makefile could recurse into *-softmmu/ subdirectories before
    a new *-softmmu/config-devices.mak was generated from pci.mak.
    
    Fix this by adding a dependency on config-all-devices.mak, which in turn
    has dependencies on *-softmmu/config-devices.mak.
    
    Reported-by: Gerhard Wiesinger <lists at wiesinger.com>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile b/Makefile
index ae22a0f..12c7662 100644
--- a/Makefile
+++ b/Makefile
@@ -123,6 +123,9 @@ qemu-options.def: $(SRC_PATH)/qemu-options.hx
 	$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $@")
 
 SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
+SOFTMMU_SUBDIR_RULES=$(filter %-softmmu,$(SUBDIR_RULES))
+
+$(SOFTMMU_SUBDIR_RULES): config-all-devices.mak
 
 subdir-%:
 	$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $* V="$(V)" TARGET_DIR="$*/" all,)
commit 880708013357fa5d1c077e2a4a364b65706e09e7
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu Feb 21 16:26:46 2013 +0100

    make_device_config.sh: Emit dependency file to directory where included
    
    Placing the config-devices.mak.d file alongside the config-devices.mak
    file in *-softmmu/ lead to it getting included into through
    *-softmmu/Makefile in addition to ./Makefile, leading to confusion.
    
    Instead, emit it to ./%-config-devices.mak.d, where it is included.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile b/Makefile
index 2262410..ae22a0f 100644
--- a/Makefile
+++ b/Makefile
@@ -66,7 +66,7 @@ endif
 
 SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory) BUILD_DIR=$(BUILD_DIR)
 SUBDIR_DEVICES_MAK=$(patsubst %, %/config-devices.mak, $(TARGET_DIRS))
-SUBDIR_DEVICES_MAK_DEP=$(patsubst %, %/config-devices.mak.d, $(TARGET_DIRS))
+SUBDIR_DEVICES_MAK_DEP=$(patsubst %, %-config-devices.mak.d, $(TARGET_DIRS))
 
 ifeq ($(SUBDIR_DEVICES_MAK),)
 config-all-devices.mak:
diff --git a/scripts/make_device_config.sh b/scripts/make_device_config.sh
index 28efd36..7242707 100644
--- a/scripts/make_device_config.sh
+++ b/scripts/make_device_config.sh
@@ -3,7 +3,7 @@
 # files from include directives.
 
 dest=$1.tmp
-dep=$1.d
+dep=`dirname $1`-`basename $1`.d
 src=$2
 src_dir=`dirname $src`
 all_includes=
commit 1b3048170ad0dad83186a39cbf22471fc32583ea
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu Feb 21 16:26:45 2013 +0100

    Revert "make_device_config.sh: Fix target path in generated dependency file"
    
    This reverts commit 23bf49b5eca716aaad073f2b47613434e1515cb5.
    
    While *-softmmu/config-devices.mak.d is included through *.d pattern via
    Makefile.target, the make_devices_config.sh call these dependencies are
    for is in ./Makefile. Therefore revert to original behavior.
    
    This should unbreak pci.mak dependencies not propagating.
    
    Reported-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/scripts/make_device_config.sh b/scripts/make_device_config.sh
index 81fe942..28efd36 100644
--- a/scripts/make_device_config.sh
+++ b/scripts/make_device_config.sh
@@ -25,4 +25,4 @@ done
 process_includes $src > $dest
 
 cat $src $all_includes | grep -v '^include' > $dest
-echo "`basename $1`: $all_includes" > $dep
+echo "$1: $all_includes" > $dep
commit eb839909aa22069e04e1c910fcdf7feaa5581af6
Merge: 62e1aea 8a7df84
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 9 11:02:23 2013 +0000

    Merge branch 's390-for-upstream' of git://github.com/agraf/qemu
    
    * 's390-for-upstream' of git://github.com/agraf/qemu:
      s390/virtio-ccw: remove redundant call to blockdev_mark_auto_del
      s390/css: Fix subchannel detection
      Allow virtio-net features for legacy s390 virtio bus
      s390: virtio-ccw maintainer
      s390: simplify kvm cpu init

commit 62e1aeaee4d0450222a0ea43c713b59526e3e0fe
Merge: d6258c9 d63919c
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Mar 9 11:02:07 2013 +0000

    Merge branch 'ppc-for-upstream' of git://github.com/agraf/qemu
    
    * 'ppc-for-upstream' of git://github.com/agraf/qemu: (66 commits)
      pseries: Add compatible property to root of device tree
      target-ppc: Move CPU aliases out of translate_init.c
      target-ppc: Report CPU aliases for QMP
      target-ppc: List alias names alongside CPU models
      target-ppc: Make host CPU a subclass of the host's CPU model
      PPC: xnu kernel expects FLUSH to be cleared on STOP
      PPC: Fix dma interrupt
      target-ppc: Fix PPC_DUMP_SPR_ACCESS build
      target-ppc: Synchronize FPU state with KVM
      target-ppc: Add mechanism for synchronizing SPRs with KVM
      Save memory allocation in the elf loader
      pseries: Implement h_read hcall
      target-ppc: Change "POWER7" CPU alias
      target-ppc: Fix remaining microcontroller typos among models
      target-ppc: Split model definitions out of translate_init.c
      target-ppc: Update Coding Style for CPU models
      target-ppc: Turn descriptive CPU model comments into device descriptions
      target-ppc: Turn descriptive CPU family comments into device descriptions
      target-ppc: Set remaining fields on CPU family classes
      target-ppc: Register all types for TARGET_PPCEMB
      ...

commit 8a7df84f9ff4342cae30f4e515e6ac82a0eb0bea
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Fri Feb 22 09:01:33 2013 +0000

    s390/virtio-ccw: remove redundant call to blockdev_mark_auto_del
    
    blockdev_mark_auto_del is already called in virtio-blk-exit.
    Remove the redundant call.
    
    Signed-off-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Signed-off-by: Jens Freimann <jfrei at linux.vnet.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index d92e427..a9cf703 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -585,7 +585,6 @@ static int virtio_ccw_blk_init(VirtioCcwDevice *dev)
 static int virtio_ccw_blk_exit(VirtioCcwDevice *dev)
 {
     virtio_blk_exit(dev->vdev);
-    blockdev_mark_auto_del(dev->blk.conf.bs);
     return virtio_ccw_exit(dev);
 }
 
commit 38dd7cc776bbde7edbe60ba5d0abbd156e7e0f2f
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Fri Feb 22 09:01:32 2013 +0000

    s390/css: Fix subchannel detection
    
    We have to consider the m bit to find the real channel subsystem when
    determining the last subchannel.
    
    If we fail to take this into account, removal of a subchannel in
    the middle of a big list of devices will stop device detection after
    a reboot.
    
    Signed-off-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Signed-off-by: Jens Freimann <jfrei at linux.vnet.ibm.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 85f6f22..e526a1c 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -988,15 +988,18 @@ int css_do_rchp(uint8_t cssid, uint8_t chpid)
     return 0;
 }
 
-bool css_schid_final(uint8_t cssid, uint8_t ssid, uint16_t schid)
+bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid)
 {
     SubchSet *set;
+    uint8_t real_cssid;
 
-    if (cssid > MAX_CSSID || ssid > MAX_SSID || !channel_subsys->css[cssid] ||
-        !channel_subsys->css[cssid]->sch_set[ssid]) {
+    real_cssid = (!m && (cssid == 0)) ? channel_subsys->default_cssid : cssid;
+    if (real_cssid > MAX_CSSID || ssid > MAX_SSID ||
+        !channel_subsys->css[real_cssid] ||
+        !channel_subsys->css[real_cssid]->sch_set[ssid]) {
         return true;
     }
-    set = channel_subsys->css[cssid]->sch_set[ssid];
+    set = channel_subsys->css[real_cssid]->sch_set[ssid];
     return schid > find_last_bit(set->schids_used,
                                  (MAX_SCHID + 1) / sizeof(unsigned long));
 }
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index e450db7..9cb739d 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -404,7 +404,7 @@ SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid,
 bool css_subch_visible(SubchDev *sch);
 void css_conditional_io_interrupt(SubchDev *sch);
 int css_do_stsch(SubchDev *sch, SCHIB *schib);
-bool css_schid_final(uint8_t cssid, uint8_t ssid, uint16_t schid);
+bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid);
 int css_do_msch(SubchDev *sch, SCHIB *schib);
 int css_do_xsch(SubchDev *sch);
 int css_do_csch(SubchDev *sch);
diff --git a/target-s390x/ioinst.c b/target-s390x/ioinst.c
index e3531f3..28c508d 100644
--- a/target-s390x/ioinst.c
+++ b/target-s390x/ioinst.c
@@ -316,7 +316,7 @@ int ioinst_handle_stsch(CPUS390XState *env, uint64_t reg1, uint32_t ipb)
             cc = 3;
         }
     } else {
-        if (css_schid_final(cssid, ssid, schid)) {
+        if (css_schid_final(m, cssid, ssid, schid)) {
             cc = 3; /* No more subchannels in this css/ss */
         } else {
             /* Store an empty schib. */
commit 35569cea79fd3f5ccb5b23ca024c7d3aa4d24e75
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Thu Mar 7 17:21:41 2013 +0100

    Allow virtio-net features for legacy s390 virtio bus
    
    Enable all virtio-net features for the legacy s390 virtio bus. This also fixes
    kernel BUG at /usr/src/packages/BUILD/kernel-default-3.0.58/linux-3.0/drivers/s390/kvm/kvm_virtio.c:121!
    
    Signed-off-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index 089ed92..d9b7f83 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -402,6 +402,7 @@ static const VirtIOBindings virtio_s390_bindings = {
 
 static Property s390_virtio_net_properties[] = {
     DEFINE_NIC_PROPERTIES(VirtIOS390Device, nic),
+    DEFINE_VIRTIO_NET_FEATURES(VirtIOS390Device, host_features),
     DEFINE_PROP_UINT32("x-txtimer", VirtIOS390Device,
                        net.txtimer, TX_TIMER_INTERVAL),
     DEFINE_PROP_INT32("x-txburst", VirtIOS390Device,
commit dd4ad64ada4316d2f61af0e0489e89fe620244db
Author: Cornelia Huck <cornelia.huck at de.ibm.com>
Date:   Tue Mar 5 02:22:01 2013 +0000

    s390: virtio-ccw maintainer
    
    Add myself as maintainer for virtio-ccw and the s390-ccw-virtio machine.
    
    Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    [agraf: add myself for virtio-ccw machine]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/MAINTAINERS b/MAINTAINERS
index 2439614..0ca7e1d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -454,6 +454,14 @@ M: Alexander Graf <agraf at suse.de>
 S: Maintained
 F: hw/s390-*.c
 
+S390 Virtio-ccw
+M: Cornelia Huck <cornelia.huck at de.ibm.com>
+M: Alexander Graf <agraf at suse.de>
+S: Supported
+F: hw/s390x/s390-virtio-ccw.c
+F: hw/s390x/css.[hc]
+T: git git://github.com/cohuck/qemu virtio-ccw-upstr
+
 UniCore32 Machines
 -------------
 PKUnity-3 SoC initramfs-with-busybox
@@ -565,6 +573,12 @@ M: Stefan Hajnoczi <stefanha at redhat.com>
 S: Supported
 F: hw/virtio-blk*
 
+virtio-ccw
+M: Cornelia Huck <cornelia.huck at de.ibm.com>
+S: Supported
+F: hw/s390x/virtio-ccw.[hc]
+T: git git://github.com/cohuck/qemu virtio-ccw-upstr
+
 virtio-serial
 M: Amit Shah <amit.shah at redhat.com>
 S: Supported
commit 1c9d2a1d3c63ab7cee37acdcab92aafad3d6b3fe
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Mon Feb 4 22:53:25 2013 +0000

    s390: simplify kvm cpu init
    
    There is no special code right now and the reset ioctl is done later
    on in the the reset handler anyway. Lets simplify the cpu init.
    
    Signed-off-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 3929771..8f111ae 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -103,13 +103,8 @@ unsigned long kvm_arch_vcpu_id(CPUState *cpu)
 
 int kvm_arch_init_vcpu(CPUState *cpu)
 {
-    int ret = 0;
-
-    if (kvm_vcpu_ioctl(cpu, KVM_S390_INITIAL_RESET, NULL) < 0) {
-        perror("cannot init reset vcpu");
-    }
-
-    return ret;
+    /* nothing todo yet */
+    return 0;
 }
 
 void kvm_arch_reset_vcpu(CPUState *cpu)
commit d63919c93e6fb0587632adafba82c21e55ea4396
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Mon Feb 25 19:27:12 2013 +0000

    pseries: Add compatible property to root of device tree
    
    Currently, for the pseries machine the device tree supplied by qemu to SLOF
    and from there to the guest does not include a 'compatible property' at the
    root level.  Usually that works fine, since in this case the compatible
    property doesn't really give any information not already found in the
    'device_type' or 'model' properties.
    
    However, the lack of 'compatible' confuses the bootloader install in the
    SLES11 SP2 and SLES11 SP3 installers.  This patch therefore adds a token
    'compatible' property to work around that.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr.c b/hw/spapr.c
index e88a27a..fadf70f 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -260,6 +260,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
     _FDT((fdt_begin_node(fdt, "")));
     _FDT((fdt_property_string(fdt, "device_type", "chrp")));
     _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
+    _FDT((fdt_property_string(fdt, "compatible", "qemu,pseries")));
 
     _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
     _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
commit e9a9607527746600a1af79ba63494ec596ec8584
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon Feb 25 03:43:17 2013 +0000

    target-ppc: Move CPU aliases out of translate_init.c
    
    Move array of CPU aliases to cpu-models.c, alongside model definitions.
    This requires to zero-terminate the aliases array since ARRAY_SIZE() can
    no longer be used in translate_init.c then.
    
    Suggested-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/cpu-models.c b/target-ppc/cpu-models.c
index 66408c0..20ca84e 100644
--- a/target-ppc/cpu-models.c
+++ b/target-ppc/cpu-models.c
@@ -1223,3 +1223,197 @@
                 "PA PA6T")
 #endif
 
+
+/***************************************************************************/
+/* PowerPC CPU aliases                                                     */
+
+const PowerPCCPUAlias ppc_cpu_aliases[] = {
+    { "403", "403GC" },
+    { "405", "405D4" },
+    { "405CR", "405CRc" },
+    { "405GP", "405GPd" },
+    { "405GPe", "405CRc" },
+    { "x2vp7", "x2vp4" },
+    { "x2vp50", "x2vp20" },
+
+    { "440EP", "440EPb" },
+    { "440GP", "440GPc" },
+    { "440GR", "440GRa" },
+    { "440GX", "440GXf" },
+
+    { "RCPU", "MPC5xx" },
+    /* MPC5xx microcontrollers */
+    { "MGT560", "MPC5xx" },
+    { "MPC509", "MPC5xx" },
+    { "MPC533", "MPC5xx" },
+    { "MPC534", "MPC5xx" },
+    { "MPC555", "MPC5xx" },
+    { "MPC556", "MPC5xx" },
+    { "MPC560", "MPC5xx" },
+    { "MPC561", "MPC5xx" },
+    { "MPC562", "MPC5xx" },
+    { "MPC563", "MPC5xx" },
+    { "MPC564", "MPC5xx" },
+    { "MPC565", "MPC5xx" },
+    { "MPC566", "MPC5xx" },
+
+    { "PowerQUICC", "MPC8xx" },
+    /* MPC8xx microcontrollers */
+    { "MGT823", "MPC8xx" },
+    { "MPC821", "MPC8xx" },
+    { "MPC823", "MPC8xx" },
+    { "MPC850", "MPC8xx" },
+    { "MPC852T", "MPC8xx" },
+    { "MPC855T", "MPC8xx" },
+    { "MPC857", "MPC8xx" },
+    { "MPC859", "MPC8xx" },
+    { "MPC860", "MPC8xx" },
+    { "MPC862", "MPC8xx" },
+    { "MPC866", "MPC8xx" },
+    { "MPC870", "MPC8xx" },
+    { "MPC875", "MPC8xx" },
+    { "MPC880", "MPC8xx" },
+    { "MPC885", "MPC8xx" },
+
+    /* PowerPC MPC603 microcontrollers */
+    { "MPC8240", "603" },
+
+    { "MPC52xx", "MPC5200" },
+    { "MPC5200", "MPC5200_v12" },
+    { "MPC5200B", "MPC5200B_v21" },
+
+    { "MPC82xx", "MPC8280" },
+    { "PowerQUICC-II", "MPC82xx" },
+    { "MPC8241", "G2HiP4" },
+    { "MPC8245", "G2HiP4" },
+    { "MPC8247", "G2leGP3" },
+    { "MPC8248", "G2leGP3" },
+    { "MPC8250", "MPC8250_HiP4" },
+    { "MPC8250_HiP3", "G2HiP3" },
+    { "MPC8250_HiP4", "G2HiP4" },
+    { "MPC8255", "MPC8255_HiP4" },
+    { "MPC8255_HiP3", "G2HiP3" },
+    { "MPC8255_HiP4", "G2HiP4" },
+    { "MPC8260", "MPC8260_HiP4" },
+    { "MPC8260_HiP3", "G2HiP3" },
+    { "MPC8260_HiP4", "G2HiP4" },
+    { "MPC8264", "MPC8264_HiP4" },
+    { "MPC8264_HiP3", "G2HiP3" },
+    { "MPC8264_HiP4", "G2HiP4" },
+    { "MPC8265", "MPC8265_HiP4" },
+    { "MPC8265_HiP3", "G2HiP3" },
+    { "MPC8265_HiP4", "G2HiP4" },
+    { "MPC8266", "MPC8266_HiP4" },
+    { "MPC8266_HiP3", "G2HiP3" },
+    { "MPC8266_HiP4", "G2HiP4" },
+    { "MPC8270", "G2leGP3" },
+    { "MPC8271", "G2leGP3" },
+    { "MPC8272", "G2leGP3" },
+    { "MPC8275", "G2leGP3" },
+    { "MPC8280", "G2leGP3" },
+    { "e200", "e200z6" },
+    { "e300", "e300c3" },
+    { "MPC8347", "MPC8347T" },
+    { "MPC8347A", "MPC8347AT" },
+    { "MPC8347E", "MPC8347ET" },
+    { "MPC8347EA", "MPC8347EAT" },
+    { "e500", "e500v2_v22" },
+    { "e500v1", "e500_v20" },
+    { "e500v2", "e500v2_v22" },
+    { "MPC8533", "MPC8533_v11" },
+    { "MPC8533E", "MPC8533E_v11" },
+    { "MPC8540", "MPC8540_v21" },
+    { "MPC8541", "MPC8541_v11" },
+    { "MPC8541E", "MPC8541E_v11" },
+    { "MPC8543", "MPC8543_v21" },
+    { "MPC8543E", "MPC8543E_v21" },
+    { "MPC8544", "MPC8544_v11" },
+    { "MPC8544E", "MPC8544E_v11" },
+    { "MPC8545", "MPC8545_v21" },
+    { "MPC8545E", "MPC8545E_v21" },
+    { "MPC8547E", "MPC8547E_v21" },
+    { "MPC8548", "MPC8548_v21" },
+    { "MPC8548E", "MPC8548E_v21" },
+    { "MPC8555", "MPC8555_v11" },
+    { "MPC8555E", "MPC8555E_v11" },
+    { "MPC8560", "MPC8560_v21" },
+    { "601",  "601_v2" },
+    { "601v", "601_v2" },
+    { "Vanilla", "603" },
+    { "603e", "603e_v4.1" },
+    { "Stretch", "603e" },
+    { "Vaillant", "603e7v" },
+    { "603r", "603e7t" },
+    { "Goldeneye", "603r" },
+    { "604e", "604e_v2.4" },
+    { "Sirocco", "604e" },
+    { "Mach5", "604r" },
+    { "740", "740_v3.1" },
+    { "Arthur", "740" },
+    { "750", "750_v3.1" },
+    { "Typhoon", "750" },
+    { "G3",      "750" },
+    { "Conan/Doyle", "750p" },
+    { "750cl", "750cl_v2.0" },
+    { "750cx", "750cx_v2.2" },
+    { "750cxe", "750cxe_v3.1b" },
+    { "750fx", "750fx_v2.3" },
+    { "750gx", "750gx_v1.2" },
+    { "750l", "750l_v3.2" },
+    { "LoneStar", "750l" },
+    { "745", "745_v2.8" },
+    { "755", "755_v2.8" },
+    { "Goldfinger", "755" },
+    { "7400", "7400_v2.9" },
+    { "Max", "7400" },
+    { "G4",  "7400" },
+    { "7410", "7410_v1.4" },
+    { "Nitro", "7410" },
+    { "7448", "7448_v2.1" },
+    { "7450", "7450_v2.1" },
+    { "Vger", "7450" },
+    { "7441", "7441_v2.3" },
+    { "7451", "7451_v2.3" },
+    { "7445", "7445_v3.2" },
+    { "7455", "7455_v3.2" },
+    { "Apollo6", "7455" },
+    { "7447", "7447_v1.2" },
+    { "7457", "7457_v1.2" },
+    { "Apollo7", "7457" },
+    { "7447A", "7447A_v1.2" },
+    { "7457A", "7457A_v1.2" },
+    { "Apollo7PM", "7457A_v1.0" },
+#if defined(TARGET_PPC64)
+    { "Trident", "620" },
+    { "POWER3", "630" },
+    { "Boxer", "POWER3" },
+    { "Dino",  "POWER3" },
+    { "POWER3+", "631" },
+    { "POWER7", "POWER7_v2.3" },
+    { "970fx", "970fx_v3.1" },
+    { "970mp", "970mp_v1.1" },
+    { "Apache", "RS64" },
+    { "A35",    "RS64" },
+    { "NorthStar", "RS64-II" },
+    { "A50",       "RS64-II" },
+    { "Pulsar", "RS64-III" },
+    { "IceStar", "RS64-IV" },
+    { "IStar",   "RS64-IV" },
+    { "SStar",   "RS64-IV" },
+#endif
+    { "RIOS",    "POWER" },
+    { "RSC",     "POWER" },
+    { "RSC3308", "POWER" },
+    { "RSC4608", "POWER" },
+    { "RSC2", "POWER2" },
+    { "P2SC", "POWER2" },
+
+    /* Generic PowerPCs */
+#if defined(TARGET_PPC64)
+    { "ppc64", "970fx" },
+#endif
+    { "ppc32", "604" },
+    { "ppc", "ppc32" },
+    { "default", "ppc" },
+    { NULL, NULL }
+};
diff --git a/target-ppc/cpu-models.h b/target-ppc/cpu-models.h
index edff0f4..a94f835 100644
--- a/target-ppc/cpu-models.h
+++ b/target-ppc/cpu-models.h
@@ -21,6 +21,20 @@
 #ifndef TARGET_PPC_CPU_MODELS_H
 #define TARGET_PPC_CPU_MODELS_H
 
+/**
+ * PowerPCCPUAlias:
+ * @alias: The alias name.
+ * @model: The CPU model @alias refers to.
+ *
+ * A mapping entry from CPU @alias to CPU @model.
+ */
+typedef struct PowerPCCPUAlias {
+    const char *alias;
+    const char *model;
+} PowerPCCPUAlias;
+
+extern const PowerPCCPUAlias ppc_cpu_aliases[];
+
 /*****************************************************************************/
 /* PVR definitions for most known PowerPC                                    */
 enum {
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 8ce9f7a..09ad4ba 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7181,201 +7181,6 @@ POWERPC_FAMILY(620)(ObjectClass *oc, void *data)
 #endif /* defined (TARGET_PPC64) */
 
 
-typedef struct PowerPCCPUAlias {
-    const char *alias;
-    const char *model;
-} PowerPCCPUAlias;
-
-static const PowerPCCPUAlias ppc_cpu_aliases[] = {
-    { "403", "403GC" },
-    { "405", "405D4" },
-    { "405CR", "405CRc" },
-    { "405GP", "405GPd" },
-    { "405GPe", "405CRc" },
-    { "x2vp7", "x2vp4" },
-    { "x2vp50", "x2vp20" },
-
-    { "440EP", "440EPb" },
-    { "440GP", "440GPc" },
-    { "440GR", "440GRa" },
-    { "440GX", "440GXf" },
-
-    { "RCPU", "MPC5xx" },
-    /* MPC5xx microcontrollers */
-    { "MGT560", "MPC5xx" },
-    { "MPC509", "MPC5xx" },
-    { "MPC533", "MPC5xx" },
-    { "MPC534", "MPC5xx" },
-    { "MPC555", "MPC5xx" },
-    { "MPC556", "MPC5xx" },
-    { "MPC560", "MPC5xx" },
-    { "MPC561", "MPC5xx" },
-    { "MPC562", "MPC5xx" },
-    { "MPC563", "MPC5xx" },
-    { "MPC564", "MPC5xx" },
-    { "MPC565", "MPC5xx" },
-    { "MPC566", "MPC5xx" },
-
-    { "PowerQUICC", "MPC8xx" },
-    /* MPC8xx microcontrollers */
-    { "MGT823", "MPC8xx" },
-    { "MPC821", "MPC8xx" },
-    { "MPC823", "MPC8xx" },
-    { "MPC850", "MPC8xx" },
-    { "MPC852T", "MPC8xx" },
-    { "MPC855T", "MPC8xx" },
-    { "MPC857", "MPC8xx" },
-    { "MPC859", "MPC8xx" },
-    { "MPC860", "MPC8xx" },
-    { "MPC862", "MPC8xx" },
-    { "MPC866", "MPC8xx" },
-    { "MPC870", "MPC8xx" },
-    { "MPC875", "MPC8xx" },
-    { "MPC880", "MPC8xx" },
-    { "MPC885", "MPC8xx" },
-
-    /* PowerPC MPC603 microcontrollers */
-    { "MPC8240", "603" },
-
-    { "MPC52xx", "MPC5200" },
-    { "MPC5200", "MPC5200_v12" },
-    { "MPC5200B", "MPC5200B_v21" },
-
-    { "MPC82xx", "MPC8280" },
-    { "PowerQUICC-II", "MPC82xx" },
-    { "MPC8241", "G2HiP4" },
-    { "MPC8245", "G2HiP4" },
-    { "MPC8247", "G2leGP3" },
-    { "MPC8248", "G2leGP3" },
-    { "MPC8250", "MPC8250_HiP4" },
-    { "MPC8250_HiP3", "G2HiP3" },
-    { "MPC8250_HiP4", "G2HiP4" },
-    { "MPC8255", "MPC8255_HiP4" },
-    { "MPC8255_HiP3", "G2HiP3" },
-    { "MPC8255_HiP4", "G2HiP4" },
-    { "MPC8260", "MPC8260_HiP4" },
-    { "MPC8260_HiP3", "G2HiP3" },
-    { "MPC8260_HiP4", "G2HiP4" },
-    { "MPC8264", "MPC8264_HiP4" },
-    { "MPC8264_HiP3", "G2HiP3" },
-    { "MPC8264_HiP4", "G2HiP4" },
-    { "MPC8265", "MPC8265_HiP4" },
-    { "MPC8265_HiP3", "G2HiP3" },
-    { "MPC8265_HiP4", "G2HiP4" },
-    { "MPC8266", "MPC8266_HiP4" },
-    { "MPC8266_HiP3", "G2HiP3" },
-    { "MPC8266_HiP4", "G2HiP4" },
-    { "MPC8270", "G2leGP3" },
-    { "MPC8271", "G2leGP3" },
-    { "MPC8272", "G2leGP3" },
-    { "MPC8275", "G2leGP3" },
-    { "MPC8280", "G2leGP3" },
-    { "e200", "e200z6" },
-    { "e300", "e300c3" },
-    { "MPC8347", "MPC8347T" },
-    { "MPC8347A", "MPC8347AT" },
-    { "MPC8347E", "MPC8347ET" },
-    { "MPC8347EA", "MPC8347EAT" },
-    { "e500", "e500v2_v22" },
-    { "e500v1", "e500_v20" },
-    { "e500v2", "e500v2_v22" },
-    { "MPC8533", "MPC8533_v11" },
-    { "MPC8533E", "MPC8533E_v11" },
-    { "MPC8540", "MPC8540_v21" },
-    { "MPC8541", "MPC8541_v11" },
-    { "MPC8541E", "MPC8541E_v11" },
-    { "MPC8543", "MPC8543_v21" },
-    { "MPC8543E", "MPC8543E_v21" },
-    { "MPC8544", "MPC8544_v11" },
-    { "MPC8544E", "MPC8544E_v11" },
-    { "MPC8545", "MPC8545_v21" },
-    { "MPC8545E", "MPC8545E_v21" },
-    { "MPC8547E", "MPC8547E_v21" },
-    { "MPC8548", "MPC8548_v21" },
-    { "MPC8548E", "MPC8548E_v21" },
-    { "MPC8555", "MPC8555_v11" },
-    { "MPC8555E", "MPC8555E_v11" },
-    { "MPC8560", "MPC8560_v21" },
-    { "601",  "601_v2" },
-    { "601v", "601_v2" },
-    { "Vanilla", "603" },
-    { "603e", "603e_v4.1" },
-    { "Stretch", "603e" },
-    { "Vaillant", "603e7v" },
-    { "603r", "603e7t" },
-    { "Goldeneye", "603r" },
-    { "604e", "604e_v2.4" },
-    { "Sirocco", "604e" },
-    { "Mach5", "604r" },
-    { "740", "740_v3.1" },
-    { "Arthur", "740" },
-    { "750", "750_v3.1" },
-    { "Typhoon", "750" },
-    { "G3",      "750" },
-    { "Conan/Doyle", "750p" },
-    { "750cl", "750cl_v2.0" },
-    { "750cx", "750cx_v2.2" },
-    { "750cxe", "750cxe_v3.1b" },
-    { "750fx", "750fx_v2.3" },
-    { "750gx", "750gx_v1.2" },
-    { "750l", "750l_v3.2" },
-    { "LoneStar", "750l" },
-    { "745", "745_v2.8" },
-    { "755", "755_v2.8" },
-    { "Goldfinger", "755" },
-    { "7400", "7400_v2.9" },
-    { "Max", "7400" },
-    { "G4",  "7400" },
-    { "7410", "7410_v1.4" },
-    { "Nitro", "7410" },
-    { "7448", "7448_v2.1" },
-    { "7450", "7450_v2.1" },
-    { "Vger", "7450" },
-    { "7441", "7441_v2.3" },
-    { "7451", "7451_v2.3" },
-    { "7445", "7445_v3.2" },
-    { "7455", "7455_v3.2" },
-    { "Apollo6", "7455" },
-    { "7447", "7447_v1.2" },
-    { "7457", "7457_v1.2" },
-    { "Apollo7", "7457" },
-    { "7447A", "7447A_v1.2" },
-    { "7457A", "7457A_v1.2" },
-    { "Apollo7PM", "7457A_v1.0" },
-#if defined(TARGET_PPC64)
-    { "Trident", "620" },
-    { "POWER3", "630" },
-    { "Boxer", "POWER3" },
-    { "Dino",  "POWER3" },
-    { "POWER3+", "631" },
-    { "POWER7", "POWER7_v2.3" },
-    { "970fx", "970fx_v3.1" },
-    { "970mp", "970mp_v1.1" },
-    { "Apache", "RS64" },
-    { "A35",    "RS64" },
-    { "NorthStar", "RS64-II" },
-    { "A50",       "RS64-II" },
-    { "Pulsar", "RS64-III" },
-    { "IceStar", "RS64-IV" },
-    { "IStar",   "RS64-IV" },
-    { "SStar",   "RS64-IV" },
-#endif
-    { "RIOS",    "POWER" },
-    { "RSC",     "POWER" },
-    { "RSC3308", "POWER" },
-    { "RSC4608", "POWER" },
-    { "RSC2", "POWER2" },
-    { "P2SC", "POWER2" },
-
-    /* Generic PowerPCs */
-#if defined(TARGET_PPC64)
-    { "ppc64", "970fx" },
-#endif
-    { "ppc32", "604" },
-    { "ppc", "ppc32" },
-    { "default", "ppc" },
-};
-
 /*****************************************************************************/
 /* Generic CPU instantiation routine                                         */
 static void init_ppc_proc(PowerPCCPU *cpu)
@@ -8316,7 +8121,7 @@ static ObjectClass *ppc_cpu_class_by_name(const char *name)
         }
     }
 
-    for (i = 0; i < ARRAY_SIZE(ppc_cpu_aliases); i++) {
+    for (i = 0; ppc_cpu_aliases[i].alias != NULL; i++) {
         if (strcmp(ppc_cpu_aliases[i].alias, name) == 0) {
             return ppc_cpu_class_by_name(ppc_cpu_aliases[i].model);
         }
@@ -8407,7 +8212,7 @@ static void ppc_cpu_list_entry(gpointer data, gpointer user_data)
                      strlen(typename) - strlen("-" TYPE_POWERPC_CPU));
     (*s->cpu_fprintf)(s->file, "PowerPC %-16s PVR %08x\n",
                       name, pcc->pvr);
-    for (i = 0; i < ARRAY_SIZE(ppc_cpu_aliases); i++) {
+    for (i = 0; ppc_cpu_aliases[i].alias != NULL; i++) {
         const PowerPCCPUAlias *alias = &ppc_cpu_aliases[i];
         ObjectClass *alias_oc = ppc_cpu_class_by_name(alias->model);
 
@@ -8475,7 +8280,7 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
     g_slist_foreach(list, ppc_cpu_defs_entry, &cpu_list);
     g_slist_free(list);
 
-    for (i = 0; i < ARRAY_SIZE(ppc_cpu_aliases); i++) {
+    for (i = 0; ppc_cpu_aliases[i].alias != NULL; i++) {
         const PowerPCCPUAlias *alias = &ppc_cpu_aliases[i];
         ObjectClass *oc;
         CpuDefinitionInfoList *entry;
commit 35e21d3f53068911a98014577880f76c4734f31c
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Feb 23 07:52:24 2013 +0000

    target-ppc: Report CPU aliases for QMP
    
    The QMP query-cpu-definitions implementation iterated over CPU classes
    only, which were getting less and less as aliases were extracted.
    
    Keep them in QMP as valid -cpu arguments even if not guaranteed stable.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 6fbb7b3..8ce9f7a 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8469,11 +8469,32 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
 {
     CpuDefinitionInfoList *cpu_list = NULL;
     GSList *list;
+    int i;
 
     list = object_class_get_list(TYPE_POWERPC_CPU, false);
     g_slist_foreach(list, ppc_cpu_defs_entry, &cpu_list);
     g_slist_free(list);
 
+    for (i = 0; i < ARRAY_SIZE(ppc_cpu_aliases); i++) {
+        const PowerPCCPUAlias *alias = &ppc_cpu_aliases[i];
+        ObjectClass *oc;
+        CpuDefinitionInfoList *entry;
+        CpuDefinitionInfo *info;
+
+        oc = ppc_cpu_class_by_name(alias->model);
+        if (oc == NULL) {
+            continue;
+        }
+
+        info = g_malloc0(sizeof(*info));
+        info->name = g_strdup(alias->alias);
+
+        entry = g_malloc0(sizeof(*entry));
+        entry->value = info;
+        entry->next = cpu_list;
+        cpu_list = entry;
+    }
+
     return cpu_list;
 }
 
commit 55d3d1a4d1a8dca7a0f31dc0d212d7fb219563c2
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Feb 23 07:34:28 2013 +0000

    target-ppc: List alias names alongside CPU models
    
    Revert adding a separate -cpu ? output section for aliases and list them
    per CPU subclass.
    
    Requested-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 521cdcc..6fbb7b3 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8392,6 +8392,7 @@ static void ppc_cpu_list_entry(gpointer data, gpointer user_data)
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
     const char *typename = object_class_get_name(oc);
     char *name;
+    int i;
 
 #if defined(TARGET_PPCEMB)
     if (pcc->mmu_model != POWERPC_MMU_BOOKE) {
@@ -8406,6 +8407,16 @@ static void ppc_cpu_list_entry(gpointer data, gpointer user_data)
                      strlen(typename) - strlen("-" TYPE_POWERPC_CPU));
     (*s->cpu_fprintf)(s->file, "PowerPC %-16s PVR %08x\n",
                       name, pcc->pvr);
+    for (i = 0; i < ARRAY_SIZE(ppc_cpu_aliases); i++) {
+        const PowerPCCPUAlias *alias = &ppc_cpu_aliases[i];
+        ObjectClass *alias_oc = ppc_cpu_class_by_name(alias->model);
+
+        if (alias_oc != oc) {
+            continue;
+        }
+        (*s->cpu_fprintf)(s->file, "PowerPC %-16s (alias for %s)\n",
+                          alias->alias, name);
+    }
     g_free(name);
 }
 
@@ -8416,7 +8427,6 @@ void ppc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
         .cpu_fprintf = cpu_fprintf,
     };
     GSList *list;
-    int i;
 
     list = object_class_get_list(TYPE_POWERPC_CPU, false);
     list = g_slist_sort(list, ppc_cpu_list_compare);
@@ -8427,17 +8437,6 @@ void ppc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
     cpu_fprintf(f, "\n");
     cpu_fprintf(f, "PowerPC %-16s\n", "host");
 #endif
-
-    cpu_fprintf(f, "\n");
-    for (i = 0; i < ARRAY_SIZE(ppc_cpu_aliases); i++) {
-        ObjectClass *oc = ppc_cpu_class_by_name(ppc_cpu_aliases[i].model);
-        if (oc == NULL) {
-            /* Hide aliases that point to a TODO or TODO_USER_ONLY model */
-            continue;
-        }
-        cpu_fprintf(f, "PowerPC %-16s\n",
-                    ppc_cpu_aliases[i].alias);
-    }
 }
 
 static void ppc_cpu_defs_entry(gpointer data, gpointer user_data)
commit 5ba4576b858c0d6056f59abb7e17a2b63f7905f3
Author: Andreas Färber <afaerber at suse.de>
Date:   Sat Feb 23 11:22:12 2013 +0000

    target-ppc: Make host CPU a subclass of the host's CPU model
    
    This avoids assigning individual class fields and contributors
    forgetting to add field assignments in KVM-only code.
    
    ppc_cpu_class_find_by_pvr() requires the CPU model classes to be
    registered, so defer host CPU type registration to kvm_arch_init().
    
    Only register the host CPU type if there is a class with matching PVR.
    This lets us drop error handling from instance_init.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 4451159..9dff760 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -81,6 +81,8 @@ static void kvm_kick_cpu(void *opaque)
     qemu_cpu_kick(CPU(cpu));
 }
 
+static int kvm_ppc_register_host_cpu_type(void);
+
 int kvm_arch_init(KVMState *s)
 {
     cap_interrupt_unset = kvm_check_extension(s, KVM_CAP_PPC_UNSET_IRQ);
@@ -98,6 +100,8 @@ int kvm_arch_init(KVMState *s)
                         "VM to stall at times!\n");
     }
 
+    kvm_ppc_register_host_cpu_type();
+
     return 0;
 }
 
@@ -1488,44 +1492,15 @@ static void alter_insns(uint64_t *word, uint64_t flags, bool on)
 
 static void kvmppc_host_cpu_initfn(Object *obj)
 {
-    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(obj);
-
     assert(kvm_enabled());
-
-    if (pcc->pvr != mfpvr()) {
-        fprintf(stderr, "Your host CPU is unsupported.\n"
-                "Please choose a supported model instead, see -cpu ?.\n");
-        exit(1);
-    }
 }
 
 static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
 {
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
-    uint32_t host_pvr = mfpvr();
-    PowerPCCPUClass *pvr_pcc;
     uint32_t vmx = kvmppc_get_vmx();
     uint32_t dfp = kvmppc_get_dfp();
 
-    pvr_pcc = ppc_cpu_class_by_pvr(host_pvr);
-    if (pvr_pcc != NULL) {
-        pcc->pvr          = pvr_pcc->pvr;
-        pcc->svr          = pvr_pcc->svr;
-        pcc->insns_flags  = pvr_pcc->insns_flags;
-        pcc->insns_flags2 = pvr_pcc->insns_flags2;
-        pcc->msr_mask     = pvr_pcc->msr_mask;
-        pcc->mmu_model    = pvr_pcc->mmu_model;
-        pcc->excp_model   = pvr_pcc->excp_model;
-        pcc->bus_model    = pvr_pcc->bus_model;
-        pcc->flags        = pvr_pcc->flags;
-        pcc->bfd_mach     = pvr_pcc->bfd_mach;
-#ifdef TARGET_PPC64
-        pcc->sps          = pvr_pcc->sps;
-#endif
-        pcc->init_proc    = pvr_pcc->init_proc;
-        pcc->check_pow    = pvr_pcc->check_pow;
-    }
-
     /* Now fix up the class with information we can query from the host */
 
     if (vmx != -1) {
@@ -1552,6 +1527,25 @@ int kvmppc_fixup_cpu(PowerPCCPU *cpu)
     return 0;
 }
 
+static int kvm_ppc_register_host_cpu_type(void)
+{
+    TypeInfo type_info = {
+        .name = TYPE_HOST_POWERPC_CPU,
+        .instance_init = kvmppc_host_cpu_initfn,
+        .class_init = kvmppc_host_cpu_class_init,
+    };
+    uint32_t host_pvr = mfpvr();
+    PowerPCCPUClass *pvr_pcc;
+
+    pvr_pcc = ppc_cpu_class_by_pvr(host_pvr);
+    if (pvr_pcc == NULL) {
+        return -1;
+    }
+    type_info.parent = object_class_get_name(OBJECT_CLASS(pvr_pcc));
+    type_register(&type_info);
+    return 0;
+}
+
 
 bool kvm_arch_stop_on_emulation_error(CPUState *cpu)
 {
@@ -1567,17 +1561,3 @@ int kvm_arch_on_sigbus(int code, void *addr)
 {
     return 1;
 }
-
-static const TypeInfo kvm_host_cpu_type_info = {
-    .name = TYPE_HOST_POWERPC_CPU,
-    .parent = TYPE_POWERPC_CPU,
-    .instance_init = kvmppc_host_cpu_initfn,
-    .class_init = kvmppc_host_cpu_class_init,
-};
-
-static void kvm_ppc_register_types(void)
-{
-    type_register_static(&kvm_host_cpu_type_info);
-}
-
-type_init(kvm_ppc_register_types)
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 1783c22..521cdcc 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8298,13 +8298,6 @@ static ObjectClass *ppc_cpu_class_by_name(const char *name)
     const char *p;
     int i, len;
 
-    if (strcasecmp(name, "host") == 0) {
-        if (kvm_enabled()) {
-            ret = object_class_by_name(TYPE_HOST_POWERPC_CPU);
-        }
-        return ret;
-    }
-
     /* Check if the given name is a PVR */
     len = strlen(name);
     if (len == 10 && name[0] == '0' && name[1] == 'x') {
@@ -8405,6 +8398,9 @@ static void ppc_cpu_list_entry(gpointer data, gpointer user_data)
         return;
     }
 #endif
+    if (unlikely(strcmp(typename, TYPE_HOST_POWERPC_CPU) == 0)) {
+        return;
+    }
 
     name = g_strndup(typename,
                      strlen(typename) - strlen("-" TYPE_POWERPC_CPU));
@@ -8427,6 +8423,11 @@ void ppc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
     g_slist_foreach(list, ppc_cpu_list_entry, &s);
     g_slist_free(list);
 
+#ifdef CONFIG_KVM
+    cpu_fprintf(f, "\n");
+    cpu_fprintf(f, "PowerPC %-16s\n", "host");
+#endif
+
     cpu_fprintf(f, "\n");
     for (i = 0; i < ARRAY_SIZE(ppc_cpu_aliases); i++) {
         ObjectClass *oc = ppc_cpu_class_by_name(ppc_cpu_aliases[i].model);
commit 987422bc4a4c6366ca6a7fbfa38a9920fd7ada2f
Author: Amadeusz Sławiński <amade at asmblr.net>
Date:   Thu Feb 21 07:34:11 2013 +0000

    PPC: xnu kernel expects FLUSH to be cleared on STOP
    
    otherwise it gets stuck in a loop
    so clear it when unsetting run when flush is set
    
    void
    IODBDMAStop( volatile IODBDMAChannelRegisters *registers)
    {
    
    	IOSetDBDMAChannelControl( registers,
    	IOClearDBDMAChannelControlBits( kdbdmaRun )
    		| IOSetDBDMAChannelControlBits(  kdbdmaFlush ));
    
    DBDMA: writel 0x0000000000000b00 <= 0xa0002000
    DBDMA: channel 0x16 reg 0x0
    DBDMA:     status 0x00002000
    
    	while( IOGetDBDMAChannelStatus( registers) & (
    			kdbdmaActive | kdbdmaFlush))
    		eieio();
    
    DBDMA: readl 0x0000000000000b04 => 0x00002000
    DBDMA: channel 0x16 reg 0x1
    DBDMA: readl 0x0000000000000b04 => 0x00002000
    DBDMA: channel 0x16 reg 0x1
    DBDMA: readl 0x0000000000000b04 => 0x00002000
    DBDMA: channel 0x16 reg 0x1
    DBDMA: readl 0x0000000000000b04 => 0x00002000
    DBDMA: channel 0x16 reg 0x1
    it continues to get printed
    
    }
    
    Signed-off-by: Amadeusz Sławiński <amade at asmblr.net>
    [agraf: replace tabs with spaces]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c
index b894ab2..73d74c2 100644
--- a/hw/mac_dbdma.c
+++ b/hw/mac_dbdma.c
@@ -688,6 +688,10 @@ dbdma_control_write(DBDMA_channel *ch)
     if ((ch->regs[DBDMA_STATUS] & RUN) && !(status & RUN)) {
         /* RUN is cleared */
         status &= ~(ACTIVE|DEAD);
+        if ((status & FLUSH) && ch->flush) {
+            ch->flush(&ch->io);
+            status &= ~FLUSH;
+        }
     }
 
     DBDMA_DPRINTF("    status 0x%08x\n", status);
commit e13da40448fabb0829d75b01dc57da5f44f391b3
Author: Amadeusz Sławiński <amade at asmblr.net>
Date:   Thu Feb 21 07:34:10 2013 +0000

    PPC: Fix dma interrupt
    
    In openbios (drivers/ide.c) they are set to
    
    0000000d 00000000 00000002 00000000
    0000000e 00000000 00000003 00000000
    0000000f 00000000 00000004 00000000
    (The last one seems to be not implemented in qemu)
    
    It follows convention of how they are set on real machines,
    both ide and dma ones are increased
    
    Real machine one:
    http://web.archive.org/web/20090107151044/http://penguinppc.org/historical/dev-trees-html/g4_agp_500_2.html
    00000013 00000001 0000000b 00000000
    00000014 00000001 0000000c 00000000
    00000015 00000001 0000000d 00000000
    
    Signed-off-by: Amadeusz Sławiński <amade at asmblr.net>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 065ea87..a08a6b2 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -370,7 +370,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args)
     qdev_connect_gpio_out(dev, 1, pic[0x0d]); /* IDE */
     qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE DMA */
     qdev_connect_gpio_out(dev, 3, pic[0x0e]); /* IDE */
-    qdev_connect_gpio_out(dev, 4, pic[0x02]); /* IDE DMA */
+    qdev_connect_gpio_out(dev, 4, pic[0x03]); /* IDE DMA */
     macio_init(macio, pic_mem, escc_bar);
 
     /* We only emulate 2 out of 3 IDE controllers for now */
commit edbe35e0319c15ed2f373bcca626cbb4361f87c8
Author: Andreas Färber <afaerber at suse.de>
Date:   Wed Feb 20 18:24:57 2013 +0000

    target-ppc: Fix PPC_DUMP_SPR_ACCESS build
    
    A victim of the d523dd00a7d73b28f2e99acf45a4b3f92e56e40a AREG0
    conversion, insert the missing cpu_env arguments.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 7fb314c..1783c22 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -54,7 +54,7 @@ static void spr_load_dump_spr(int sprn)
 {
 #ifdef PPC_DUMP_SPR_ACCESSES
     TCGv_i32 t0 = tcg_const_i32(sprn);
-    gen_helper_load_dump_spr(t0);
+    gen_helper_load_dump_spr(cpu_env, t0);
     tcg_temp_free_i32(t0);
 #endif
 }
@@ -69,7 +69,7 @@ static void spr_store_dump_spr(int sprn)
 {
 #ifdef PPC_DUMP_SPR_ACCESSES
     TCGv_i32 t0 = tcg_const_i32(sprn);
-    gen_helper_store_dump_spr(t0);
+    gen_helper_store_dump_spr(cpu_env, t0);
     tcg_temp_free_i32(t0);
 #endif
 }
commit 70b79849b84510604e46299672e663a703ad5a4b
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Wed Feb 20 16:41:51 2013 +0000

    target-ppc: Synchronize FPU state with KVM
    
    Currently qemu does not get and put the state of the floating point and
    vector registers to KVM.  This is obviously a problem for savevm, as well
    as possibly being problematic for debugging of FP-using guests.
    
    This patch fixes this by using new extensions to the ONE_REG interface to
    synchronize the qemu floating point state with 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.c b/target-ppc/kvm.c
index 02ab559..4451159 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -521,6 +521,132 @@ static void kvm_put_one_spr(CPUState *cs, uint64_t id, int spr)
     }
 }
 
+static int kvm_put_fp(CPUState *cs)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
+    struct kvm_one_reg reg;
+    int i;
+    int ret;
+
+    if (env->insns_flags & PPC_FLOAT) {
+        uint64_t fpscr = env->fpscr;
+        bool vsx = !!(env->insns_flags2 & PPC2_VSX);
+
+        reg.id = KVM_REG_PPC_FPSCR;
+        reg.addr = (uintptr_t)&fpscr;
+        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+        if (ret < 0) {
+            dprintf("Unable to set FPSCR to KVM: %s\n", strerror(errno));
+            return ret;
+        }
+
+        for (i = 0; i < 32; i++) {
+            uint64_t vsr[2];
+
+            vsr[0] = float64_val(env->fpr[i]);
+            vsr[1] = env->vsr[i];
+            reg.addr = (uintptr_t) &vsr;
+            reg.id = vsx ? KVM_REG_PPC_VSR(i) : KVM_REG_PPC_FPR(i);
+
+            ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+            if (ret < 0) {
+                dprintf("Unable to set %s%d to KVM: %s\n", vsx ? "VSR" : "FPR",
+                        i, strerror(errno));
+                return ret;
+            }
+        }
+    }
+
+    if (env->insns_flags & PPC_ALTIVEC) {
+        reg.id = KVM_REG_PPC_VSCR;
+        reg.addr = (uintptr_t)&env->vscr;
+        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+        if (ret < 0) {
+            dprintf("Unable to set VSCR to KVM: %s\n", strerror(errno));
+            return ret;
+        }
+
+        for (i = 0; i < 32; i++) {
+            reg.id = KVM_REG_PPC_VR(i);
+            reg.addr = (uintptr_t)&env->avr[i];
+            ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+            if (ret < 0) {
+                dprintf("Unable to set VR%d to KVM: %s\n", i, strerror(errno));
+                return ret;
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int kvm_get_fp(CPUState *cs)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
+    struct kvm_one_reg reg;
+    int i;
+    int ret;
+
+    if (env->insns_flags & PPC_FLOAT) {
+        uint64_t fpscr;
+        bool vsx = !!(env->insns_flags2 & PPC2_VSX);
+
+        reg.id = KVM_REG_PPC_FPSCR;
+        reg.addr = (uintptr_t)&fpscr;
+        ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+        if (ret < 0) {
+            dprintf("Unable to get FPSCR from KVM: %s\n", strerror(errno));
+            return ret;
+        } else {
+            env->fpscr = fpscr;
+        }
+
+        for (i = 0; i < 32; i++) {
+            uint64_t vsr[2];
+
+            reg.addr = (uintptr_t) &vsr;
+            reg.id = vsx ? KVM_REG_PPC_VSR(i) : KVM_REG_PPC_FPR(i);
+
+            ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+            if (ret < 0) {
+                dprintf("Unable to get %s%d from KVM: %s\n",
+                        vsx ? "VSR" : "FPR", i, strerror(errno));
+                return ret;
+            } else {
+                env->fpr[i] = vsr[0];
+                if (vsx) {
+                    env->vsr[i] = vsr[1];
+                }
+            }
+        }
+    }
+
+    if (env->insns_flags & PPC_ALTIVEC) {
+        reg.id = KVM_REG_PPC_VSCR;
+        reg.addr = (uintptr_t)&env->vscr;
+        ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+        if (ret < 0) {
+            dprintf("Unable to get VSCR from KVM: %s\n", strerror(errno));
+            return ret;
+        }
+
+        for (i = 0; i < 32; i++) {
+            reg.id = KVM_REG_PPC_VR(i);
+            reg.addr = (uintptr_t)&env->avr[i];
+            ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+            if (ret < 0) {
+                dprintf("Unable to get VR%d from KVM: %s\n",
+                        i, strerror(errno));
+                return ret;
+            }
+        }
+    }
+
+    return 0;
+}
+
 int kvm_arch_put_registers(CPUState *cs, int level)
 {
     PowerPCCPU *cpu = POWERPC_CPU(cs);
@@ -561,6 +687,8 @@ int kvm_arch_put_registers(CPUState *cs, int level)
     if (ret < 0)
         return ret;
 
+    kvm_put_fp(cs);
+
     if (env->tlb_dirty) {
         kvm_sw_tlb_put(cpu);
         env->tlb_dirty = false;
@@ -666,6 +794,8 @@ int kvm_arch_get_registers(CPUState *cs)
     for (i = 0;i < 32; i++)
         env->gpr[i] = regs.gpr[i];
 
+    kvm_get_fp(cs);
+
     if (cap_booke_sregs) {
         ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs);
         if (ret < 0) {
commit d67d40ea07577b0a952d3bea5a2f92edf0ee26a6
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Wed Feb 20 16:41:50 2013 +0000

    target-ppc: Add mechanism for synchronizing SPRs with KVM
    
    Currently when runing under KVM on ppc, we synchronize a certain number of
    vital SPRs to KVM through the SET_SREGS call.  This leaves out quite a lot
    of important SPRs which are maintained in KVM.  It would be helpful to
    have their contents in qemu for debugging purposes, and when we implement
    migration it will be vital, since they include important guest state that
    will need to be restored on the target.
    
    This patch sets up for synchronization of any registers supported by the
    KVM ONE_REG calls.  A new variant on spr_register() allows a ONE_REG id to
    be stored with the SPR information.  When we set/get information to KVM
    we also synchronize any SPRs so registered.
    
    For now we set this mechanism up to synchronize a handful of important
    registers that already have ONE_REG IDs, notably the DAR and DSISR.
    
    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/cpu.h b/target-ppc/cpu.h
index e4cf96c..417abb0 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -329,6 +329,12 @@ struct ppc_spr_t {
     void (*hea_write)(void *opaque, int spr_num, int gpr_num);
 #endif
     const char *name;
+#ifdef CONFIG_KVM
+    /* We (ab)use the fact that all the SPRs will have ids for the
+     * ONE_REG interface will have KVM_REG_PPC to use 0 as meaning,
+     * don't sync this */
+    uint64_t one_reg_id;
+#endif
 };
 
 /* Altivec registers (128 bits) */
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index a89c3cf..02ab559 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -61,6 +61,7 @@ static int cap_ppc_smt;
 static int cap_ppc_rma;
 static int cap_spapr_tce;
 static int cap_hior;
+static int cap_one_reg;
 
 /* XXX We have a race condition where we actually have a level triggered
  *     interrupt, but the infrastructure can't expose that yet, so the guest
@@ -89,6 +90,7 @@ int kvm_arch_init(KVMState *s)
     cap_ppc_smt = kvm_check_extension(s, KVM_CAP_PPC_SMT);
     cap_ppc_rma = kvm_check_extension(s, KVM_CAP_PPC_RMA);
     cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE);
+    cap_one_reg = kvm_check_extension(s, KVM_CAP_ONE_REG);
     cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR);
 
     if (!cap_interrupt_level) {
@@ -449,6 +451,76 @@ static void kvm_sw_tlb_put(PowerPCCPU *cpu)
     g_free(bitmap);
 }
 
+static void kvm_get_one_spr(CPUState *cs, uint64_t id, int spr)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
+    union {
+        uint32_t u32;
+        uint64_t u64;
+    } val;
+    struct kvm_one_reg reg = {
+        .id = id,
+        .addr = (uintptr_t) &val,
+    };
+    int ret;
+
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+    if (ret != 0) {
+        fprintf(stderr, "Warning: Unable to retrieve SPR %d from KVM: %s\n",
+                spr, strerror(errno));
+    } else {
+        switch (id & KVM_REG_SIZE_MASK) {
+        case KVM_REG_SIZE_U32:
+            env->spr[spr] = val.u32;
+            break;
+
+        case KVM_REG_SIZE_U64:
+            env->spr[spr] = val.u64;
+            break;
+
+        default:
+            /* Don't handle this size yet */
+            abort();
+        }
+    }
+}
+
+static void kvm_put_one_spr(CPUState *cs, uint64_t id, int spr)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
+    union {
+        uint32_t u32;
+        uint64_t u64;
+    } val;
+    struct kvm_one_reg reg = {
+        .id = id,
+        .addr = (uintptr_t) &val,
+    };
+    int ret;
+
+    switch (id & KVM_REG_SIZE_MASK) {
+    case KVM_REG_SIZE_U32:
+        val.u32 = env->spr[spr];
+        break;
+
+    case KVM_REG_SIZE_U64:
+        val.u64 = env->spr[spr];
+        break;
+
+    default:
+        /* Don't handle this size yet */
+        abort();
+    }
+
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+    if (ret != 0) {
+        fprintf(stderr, "Warning: Unable to set SPR %d to KVM: %s\n",
+                spr, strerror(errno));
+    }
+}
+
 int kvm_arch_put_registers(CPUState *cs, int level)
 {
     PowerPCCPU *cpu = POWERPC_CPU(cs);
@@ -530,15 +602,22 @@ int kvm_arch_put_registers(CPUState *cs, int level)
     }
 
     if (cap_hior && (level >= KVM_PUT_RESET_STATE)) {
-        uint64_t hior = env->spr[SPR_HIOR];
-        struct kvm_one_reg reg = {
-            .id = KVM_REG_PPC_HIOR,
-            .addr = (uintptr_t) &hior,
-        };
+        kvm_put_one_spr(cs, KVM_REG_PPC_HIOR, SPR_HIOR);
+    }
 
-        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
-        if (ret) {
-            return ret;
+    if (cap_one_reg) {
+        int i;
+
+        /* We deliberately ignore errors here, for kernels which have
+         * the ONE_REG calls, but don't support the specific
+         * registers, there's a reasonable chance things will still
+         * work, at least until we try to migrate. */
+        for (i = 0; i < 1024; i++) {
+            uint64_t id = env->spr_cb[i].one_reg_id;
+
+            if (id != 0) {
+                kvm_put_one_spr(cs, id, i);
+            }
         }
     }
 
@@ -721,6 +800,26 @@ int kvm_arch_get_registers(CPUState *cs)
         }
     }
 
+    if (cap_hior) {
+        kvm_get_one_spr(cs, KVM_REG_PPC_HIOR, SPR_HIOR);
+    }
+
+    if (cap_one_reg) {
+        int i;
+
+        /* We deliberately ignore errors here, for kernels which have
+         * the ONE_REG calls, but don't support the specific
+         * registers, there's a reasonable chance things will still
+         * work, at least until we try to migrate. */
+        for (i = 0; i < 1024; i++) {
+            uint64_t id = env->spr_cb[i].one_reg_id;
+
+            if (id != 0) {
+                kvm_get_one_spr(cs, id, i);
+            }
+        }
+    }
+
     return 0;
 }
 
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 1015077..7fb314c 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -572,26 +572,42 @@ static inline void vscr_init (CPUPPCState *env, uint32_t val)
     set_flush_to_zero(vscr_nj, &env->vec_status);
 }
 
-#if defined(CONFIG_USER_ONLY)
-#define spr_register(env, num, name, uea_read, uea_write,                     \
-                     oea_read, oea_write, initial_value)                      \
-do {                                                                          \
-     _spr_register(env, num, name, uea_read, uea_write, initial_value);       \
-} while (0)
-static inline void _spr_register (CPUPPCState *env, int num,
-                                  const char *name,
-                                  void (*uea_read)(void *opaque, int gprn, int sprn),
-                                  void (*uea_write)(void *opaque, int sprn, int gprn),
-                                  target_ulong initial_value)
+#ifdef CONFIG_USER_ONLY
+#define spr_register_kvm(env, num, name, uea_read, uea_write,                  \
+                         oea_read, oea_write, one_reg_id, initial_value)       \
+    _spr_register(env, num, name, uea_read, uea_write, initial_value)
+#else
+#if !defined(CONFIG_KVM)
+#define spr_register_kvm(env, num, name, uea_read, uea_write,                  \
+                         oea_read, oea_write, one_reg_id, initial_value) \
+    _spr_register(env, num, name, uea_read, uea_write,                         \
+                  oea_read, oea_write, initial_value)
 #else
-static inline void spr_register (CPUPPCState *env, int num,
+#define spr_register_kvm(env, num, name, uea_read, uea_write,                  \
+                         oea_read, oea_write, one_reg_id, initial_value) \
+    _spr_register(env, num, name, uea_read, uea_write,                         \
+                  oea_read, oea_write, one_reg_id, initial_value)
+#endif
+#endif
+
+#define spr_register(env, num, name, uea_read, uea_write,                      \
+                     oea_read, oea_write, initial_value)                       \
+    spr_register_kvm(env, num, name, uea_read, uea_write,                      \
+                     oea_read, oea_write, 0, initial_value)
+
+static inline void _spr_register(CPUPPCState *env, int num,
                                  const char *name,
                                  void (*uea_read)(void *opaque, int gprn, int sprn),
                                  void (*uea_write)(void *opaque, int sprn, int gprn),
+#if !defined(CONFIG_USER_ONLY)
+
                                  void (*oea_read)(void *opaque, int gprn, int sprn),
                                  void (*oea_write)(void *opaque, int sprn, int gprn),
-                                 target_ulong initial_value)
 #endif
+#if defined(CONFIG_KVM)
+                                 uint64_t one_reg_id,
+#endif
+                                 target_ulong initial_value)
 {
     ppc_spr_t *spr;
 
@@ -667,14 +683,14 @@ static void gen_spr_generic (CPUPPCState *env)
 static void gen_spr_ne_601 (CPUPPCState *env)
 {
     /* Exception processing */
-    spr_register(env, SPR_DSISR, "DSISR",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    spr_register(env, SPR_DAR, "DAR",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
+    spr_register_kvm(env, SPR_DSISR, "DSISR",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_DSISR, 0x00000000);
+    spr_register_kvm(env, SPR_DAR, "DAR",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_DAR, 0x00000000);
     /* Timer */
     spr_register(env, SPR_DECR, "DECR",
                  SPR_NOACCESS, SPR_NOACCESS,
@@ -918,10 +934,10 @@ static void gen_spr_7xx (CPUPPCState *env)
 {
     /* Breakpoints */
     /* XXX : not implemented */
-    spr_register(env, SPR_DABR, "DABR",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
+    spr_register_kvm(env, SPR_DABR, "DABR",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_DABR, 0x00000000);
     /* XXX : not implemented */
     spr_register(env, SPR_IABR, "IABR",
                  SPR_NOACCESS, SPR_NOACCESS,
@@ -1047,10 +1063,10 @@ static void gen_spr_604 (CPUPPCState *env)
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
     /* XXX : not implemented */
-    spr_register(env, SPR_DABR, "DABR",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
+    spr_register_kvm(env, SPR_DABR, "DABR",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_DABR, 0x00000000);
     /* Performance counters */
     /* XXX : not implemented */
     spr_register(env, SPR_MMCR0, "MMCR0",
@@ -2305,14 +2321,14 @@ static void gen_spr_620 (CPUPPCState *env)
 static void gen_spr_5xx_8xx (CPUPPCState *env)
 {
     /* Exception processing */
-    spr_register(env, SPR_DSISR, "DSISR",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
-    spr_register(env, SPR_DAR, "DAR",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
+    spr_register_kvm(env, SPR_DSISR, "DSISR",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_DSISR, 0x00000000);
+    spr_register_kvm(env, SPR_DAR, "DAR",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_DAR, 0x00000000);
     /* Timer */
     spr_register(env, SPR_DECR, "DECR",
                  SPR_NOACCESS, SPR_NOACCESS,
@@ -7036,22 +7052,22 @@ static void init_proc_POWER7 (CPUPPCState *env)
                  0x00000000);
 #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);
+    spr_register_kvm(env, SPR_PURR,   "PURR",
+                     &spr_read_purr, SPR_NOACCESS,
+                     &spr_read_purr, SPR_NOACCESS,
+                     KVM_REG_PPC_PURR, 0x00000000);
+    spr_register_kvm(env, SPR_SPURR,   "SPURR",
+                     &spr_read_purr, SPR_NOACCESS,
+                     &spr_read_purr, SPR_NOACCESS,
+                     KVM_REG_PPC_SPURR, 0x00000000);
     spr_register(env, SPR_CFAR, "SPR_CFAR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_cfar, &spr_write_cfar,
                  0x00000000);
-    spr_register(env, SPR_DSCR, "SPR_DSCR",
-                 SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_read_generic, &spr_write_generic,
-                 0x00000000);
+    spr_register_kvm(env, SPR_DSCR, "SPR_DSCR",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     KVM_REG_PPC_DSCR, 0x00000000);
 #endif /* !CONFIG_USER_ONLY */
     /* Memory management */
     /* XXX : not implemented */
commit d60fa42e8bae39440f997ebfe8fe328269a57d16
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Tue Feb 19 04:41:11 2013 +0000

    Save memory allocation in the elf loader
    
    The current elf loader uses too much memory. For example, I have a
    executable with a bss section of 400 MB and I set the ram size to 512
    MB. Qemu uses about 780MB of RAM (which is fine), but there's a peak at
    1.6 GB during initialization (this is not fine).
    
    This patch fixes two things:
     1) do not allocate each elf program twice.
     2) do not allocate memory for areas that are only zeros.
    
    For this we need a new field in Rom: "datasize" which is the size of the
    allocated data. If datasize is less than romsize, it means that the area
    from datasize to romsize is filled with zeros.
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/elf_ops.h b/hw/elf_ops.h
index 531a425..acc701e 100644
--- a/hw/elf_ops.h
+++ b/hw/elf_ops.h
@@ -197,7 +197,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
     struct elfhdr ehdr;
     struct elf_phdr *phdr = NULL, *ph;
     int size, i, total_size;
-    elf_word mem_size;
+    elf_word mem_size, file_size;
     uint64_t addr, low = (uint64_t)-1, high = 0;
     uint8_t *data = NULL;
     char label[128];
@@ -252,14 +252,16 @@ static int glue(load_elf, SZ)(const char *name, int fd,
     for(i = 0; i < ehdr.e_phnum; i++) {
         ph = &phdr[i];
         if (ph->p_type == PT_LOAD) {
-            mem_size = ph->p_memsz;
-            /* XXX: avoid allocating */
-            data = g_malloc0(mem_size);
+            mem_size = ph->p_memsz; /* Size of the ROM */
+            file_size = ph->p_filesz; /* Size of the allocated data */
+            data = g_malloc0(file_size);
             if (ph->p_filesz > 0) {
-                if (lseek(fd, ph->p_offset, SEEK_SET) < 0)
+                if (lseek(fd, ph->p_offset, SEEK_SET) < 0) {
                     goto fail;
-                if (read(fd, data, ph->p_filesz) != ph->p_filesz)
+                }
+                if (read(fd, data, file_size) != file_size) {
                     goto fail;
+                }
             }
             /* address_offset is hack for kernel images that are
                linked at the wrong physical address.  */
@@ -281,7 +283,9 @@ static int glue(load_elf, SZ)(const char *name, int fd,
             }
 
             snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
-            rom_add_blob_fixed(label, data, mem_size, addr);
+
+            /* rom_add_elf_program() seize the ownership of 'data' */
+            rom_add_elf_program(label, data, file_size, mem_size, addr);
 
             total_size += mem_size;
             if (addr < low)
@@ -289,7 +293,6 @@ static int glue(load_elf, SZ)(const char *name, int fd,
             if ((addr + mem_size) > high)
                 high = addr + mem_size;
 
-            g_free(data);
             data = NULL;
         }
     }
diff --git a/hw/loader.c b/hw/loader.c
index 995edc3..bd2b52d 100644
--- a/hw/loader.c
+++ b/hw/loader.c
@@ -533,7 +533,14 @@ typedef struct Rom Rom;
 struct Rom {
     char *name;
     char *path;
+
+    /* datasize is the amount of memory allocated in "data". If datasize is less
+     * than romsize, it means that the area from datasize to romsize is filled
+     * with zeros.
+     */
     size_t romsize;
+    size_t datasize;
+
     uint8_t *data;
     int isrom;
     char *fw_dir;
@@ -589,14 +596,15 @@ int rom_add_file(const char *file, const char *fw_dir,
         rom->fw_dir  = g_strdup(fw_dir);
         rom->fw_file = g_strdup(file);
     }
-    rom->addr    = addr;
-    rom->romsize = lseek(fd, 0, SEEK_END);
-    rom->data    = g_malloc0(rom->romsize);
+    rom->addr     = addr;
+    rom->romsize  = lseek(fd, 0, SEEK_END);
+    rom->datasize = rom->romsize;
+    rom->data     = g_malloc0(rom->datasize);
     lseek(fd, 0, SEEK_SET);
-    rc = read(fd, rom->data, rom->romsize);
-    if (rc != rom->romsize) {
+    rc = read(fd, rom->data, rom->datasize);
+    if (rc != rom->datasize) {
         fprintf(stderr, "rom: file %-20s: read error: rc=%d (expected %zd)\n",
-                rom->name, rc, rom->romsize);
+                rom->name, rc, rom->datasize);
         goto err;
     }
     close(fd);
@@ -637,16 +645,37 @@ int rom_add_blob(const char *name, const void *blob, size_t len,
 {
     Rom *rom;
 
-    rom = g_malloc0(sizeof(*rom));
-    rom->name    = g_strdup(name);
-    rom->addr    = addr;
-    rom->romsize = len;
-    rom->data    = g_malloc0(rom->romsize);
+    rom           = g_malloc0(sizeof(*rom));
+    rom->name     = g_strdup(name);
+    rom->addr     = addr;
+    rom->romsize  = len;
+    rom->datasize = len;
+    rom->data     = g_malloc0(rom->datasize);
     memcpy(rom->data, blob, len);
     rom_insert(rom);
     return 0;
 }
 
+/* This function is specific for elf program because we don't need to allocate
+ * all the rom. We just allocate the first part and the rest is just zeros. This
+ * is why romsize and datasize are different. Also, this function seize the
+ * memory ownership of "data", so we don't have to allocate and copy the buffer.
+ */
+int rom_add_elf_program(const char *name, void *data, size_t datasize,
+                        size_t romsize, hwaddr addr)
+{
+    Rom *rom;
+
+    rom           = g_malloc0(sizeof(*rom));
+    rom->name     = g_strdup(name);
+    rom->addr     = addr;
+    rom->datasize = datasize;
+    rom->romsize  = romsize;
+    rom->data     = data;
+    rom_insert(rom);
+    return 0;
+}
+
 int rom_add_vga(const char *file)
 {
     return rom_add_file(file, "vgaroms", 0, -1);
@@ -668,7 +697,7 @@ static void rom_reset(void *unused)
         if (rom->data == NULL) {
             continue;
         }
-        cpu_physical_memory_write_rom(rom->addr, rom->data, rom->romsize);
+        cpu_physical_memory_write_rom(rom->addr, rom->data, rom->datasize);
         if (rom->isrom) {
             /* rom needs to be written only once */
             g_free(rom->data);
@@ -756,13 +785,33 @@ int rom_copy(uint8_t *dest, hwaddr addr, size_t size)
 
         d = dest + (rom->addr - addr);
         s = rom->data;
-        l = rom->romsize;
+        l = rom->datasize;
 
         if ((d + l) > (dest + size)) {
             l = dest - d;
         }
 
         memcpy(d, s, l);
+
+        if (rom->romsize > rom->datasize) {
+            /* If datasize is less than romsize, it means that we didn't
+             * allocate all the ROM because the trailing data are only zeros.
+             */
+
+            d += l;
+            l = rom->romsize - rom->datasize;
+
+            if ((d + l) > (dest + size)) {
+                /* Rom size doesn't fit in the destination area. Adjust to avoid
+                 * overflow.
+                 */
+                l = dest - d;
+            }
+
+            if (l > 0) {
+                memset(d, 0x0, l);
+            }
+        }
     }
 
     return (d + l) - dest;
diff --git a/hw/loader.h b/hw/loader.h
index 5e61c95..0958f06 100644
--- a/hw/loader.h
+++ b/hw/loader.h
@@ -27,6 +27,8 @@ int rom_add_file(const char *file, const char *fw_dir,
                  hwaddr addr, int32_t bootindex);
 int rom_add_blob(const char *name, const void *blob, size_t len,
                  hwaddr addr);
+int rom_add_elf_program(const char *name, void *data, size_t datasize,
+                        size_t romsize, hwaddr addr);
 int rom_load_all(void);
 void rom_set_fw(void *f);
 int rom_copy(uint8_t *dest, hwaddr addr, size_t size);
commit 6bbd5dde9a10520eb069c4bff9f2e34b96b1cfee
Author: Erlon Cruz <erlon.cruz at br.flextronics.com>
Date:   Mon Feb 18 05:00:32 2013 +0000

    pseries: Implement h_read hcall
    
    This h_call is useful for DLPAR in future amongst other things. Given an index
    it fetches the corresponding PTE stored in the htab.
    
    Signed-off-by: Erlon Cruz <erlon.cruz at br.flextronics.com>
    Acked-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
index 7b89594..77c052f 100644
--- a/hw/spapr_hcall.c
+++ b/hw/spapr_hcall.c
@@ -323,6 +323,36 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
+static target_ulong h_read(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                           target_ulong opcode, target_ulong *args)
+{
+    CPUPPCState *env = &cpu->env;
+    target_ulong flags = args[0];
+    target_ulong pte_index = args[1];
+    uint8_t *hpte;
+    int i, ridx, n_entries = 1;
+
+    if ((pte_index * HASH_PTE_SIZE_64) & ~env->htab_mask) {
+        return H_PARAMETER;
+    }
+
+    if (flags & H_READ_4) {
+        /* Clear the two low order bits */
+        pte_index &= ~(3ULL);
+        n_entries = 4;
+    }
+
+    hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
+
+    for (i = 0, ridx = 0; i < n_entries; i++) {
+        args[ridx++] = ldq_p(hpte);
+        args[ridx++] = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
+        hpte += HASH_PTE_SIZE_64;
+    }
+
+    return H_SUCCESS;
+}
+
 static target_ulong h_set_dabr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
                                target_ulong opcode, target_ulong *args)
 {
@@ -710,6 +740,7 @@ static void hypercall_register_types(void)
     spapr_register_hypercall(H_ENTER, h_enter);
     spapr_register_hypercall(H_REMOVE, h_remove);
     spapr_register_hypercall(H_PROTECT, h_protect);
+    spapr_register_hypercall(H_READ, h_read);
 
     /* hcall-bulk */
     spapr_register_hypercall(H_BULK_REMOVE, h_bulk_remove);
commit befa8af375acd52d7118fa8d4fdf15acee8d378a
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:51 2013 +0000

    target-ppc: Change "POWER7" CPU alias
    
    Let it resolve to v2.3 rather than v2.0.
    
    Suggested-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index b0d4357..1015077 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7332,7 +7332,7 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "Boxer", "POWER3" },
     { "Dino",  "POWER3" },
     { "POWER3+", "631" },
-    { "POWER7", "POWER7_v2.0" },
+    { "POWER7", "POWER7_v2.3" },
     { "970fx", "970fx_v3.1" },
     { "970mp", "970mp_v1.1" },
     { "Apache", "RS64" },
commit cc4a04db05b083748b0ee9e642d68496a3d531ec
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:50 2013 +0000

    target-ppc: Fix remaining microcontroller typos among models
    
    controler -> controller
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/cpu-models.c b/target-ppc/cpu-models.c
index f0be585..66408c0 100644
--- a/target-ppc/cpu-models.c
+++ b/target-ppc/cpu-models.c
@@ -93,7 +93,7 @@
     /* XXX: to be checked */
     POWERPC_DEF("401G2",         CPU_POWERPC_401G2,                  401x2,
                 "PowerPC 401G2")
-    /* PowerPC 401 microcontrolers                                           */
+    /* PowerPC 401 microcontrollers                                          */
 #if defined(TODO)
     POWERPC_DEF("401GF",         CPU_POWERPC_401GF,                  401,
                 "PowerPC 401GF")
@@ -107,7 +107,7 @@
                 NULL)
 #endif
     /* PowerPC 403 family                                                    */
-    /* PowerPC 403 microcontrolers                                           */
+    /* PowerPC 403 microcontrollers                                          */
     POWERPC_DEF("403GA",         CPU_POWERPC_403GA,                  403,
                 "PowerPC 403 GA")
     POWERPC_DEF("403GB",         CPU_POWERPC_403GB,                  403,
@@ -174,7 +174,7 @@
     POWERPC_DEF("405F6",         CPU_POWERPC_405F6,                  405,
                 "PowerPC 405 F6")
 #endif
-    /* PowerPC 405 microcontrolers                                           */
+    /* PowerPC 405 microcontrollers                                          */
     POWERPC_DEF("405CRa",        CPU_POWERPC_405CRa,                 405,
                 "PowerPC 405 CRa")
     POWERPC_DEF("405CRb",        CPU_POWERPC_405CRb,                 405,
@@ -245,7 +245,7 @@
     POWERPC_DEF("LC77700",       CPU_POWERPC_LC77700,                405,
                 "PowerPC LC77700 (Sanyo)")
 #endif
-    /* PowerPC 401/403/405 based set-top-box microcontrolers                 */
+    /* PowerPC 401/403/405 based set-top-box microcontrollers                */
 #if defined(TODO)
     POWERPC_DEF("STB01000",      CPU_POWERPC_STB01000,               401x2,
                 "STB010000")
@@ -337,7 +337,7 @@
     POWERPC_DEF("440H6",         CPU_POWERPC_440H6,                  440Gx5,
                 "PowerPC 440H6")
 #endif
-    /* PowerPC 440 microcontrolers                                           */
+    /* PowerPC 440 microcontrollers                                          */
     POWERPC_DEF("440EPa",        CPU_POWERPC_440EPa,                 440EP,
                 "PowerPC 440 EPa")
     POWERPC_DEF("440EPb",        CPU_POWERPC_440EPb,                 440EP,
@@ -397,7 +397,7 @@
     POWERPC_DEF("464",           CPU_POWERPC_464,                    460,
                 "Generic PowerPC 464")
 #endif
-    /* PowerPC 464 microcontrolers                                           */
+    /* PowerPC 464 microcontrollers                                          */
 #if defined(TODO)
     POWERPC_DEF("464H90",        CPU_POWERPC_464H90,                 460,
                 "PowerPC 464H90")
commit 953af181f5d1c51e8111c345c70f277185f1a6e0
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:49 2013 +0000

    target-ppc: Split model definitions out of translate_init.c
    
    Now that model definitions only reference their parent type, model
    definitions are independent of the family definitions and can be
    compiled independently of TCG translation.
    
    Keep all #if defined(TODO) code local to cpu-models.c.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/Makefile.objs b/target-ppc/Makefile.objs
index a028dcd..00ac4ad 100644
--- a/target-ppc/Makefile.objs
+++ b/target-ppc/Makefile.objs
@@ -1,3 +1,4 @@
+obj-y += cpu-models.o
 obj-y += translate.o
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-$(CONFIG_KVM) += kvm.o kvm_ppc.o
diff --git a/target-ppc/cpu-models.c b/target-ppc/cpu-models.c
new file mode 100644
index 0000000..f0be585
--- /dev/null
+++ b/target-ppc/cpu-models.c
@@ -0,0 +1,1225 @@
+/*
+ *  PowerPC CPU initialization for qemu.
+ *
+ *  Copyright (c) 2003-2007 Jocelyn Mayer
+ *  Copyright 2011 Freescale Semiconductor, Inc.
+ *  Copyright 2013 SUSE LINUX Products GmbH
+ *
+ * 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/>.
+ */
+
+/* A lot of PowerPC definition have been included here.
+ * Most of them are not usable for now but have been kept
+ * inside "#if defined(TODO) ... #endif" statements to make tests easier.
+ */
+
+#include "cpu.h"
+#include "cpu-models.h"
+
+#if defined(CONFIG_USER_ONLY)
+#define TODO_USER_ONLY 1
+#endif
+
+/***************************************************************************/
+/* PowerPC CPU definitions                                                 */
+#define POWERPC_DEF_PREFIX(pvr, svr, type)                                  \
+    glue(glue(glue(glue(pvr, _), svr), _), type)
+#define POWERPC_DEF_SVR(_name, _desc, _pvr, _svr, _type)                    \
+    static void                                                             \
+    glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_class_init)            \
+    (ObjectClass *oc, void *data)                                           \
+    {                                                                       \
+        DeviceClass *dc = DEVICE_CLASS(oc);                                 \
+        PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);                       \
+                                                                            \
+        pcc->pvr          = _pvr;                                           \
+        pcc->svr          = _svr;                                           \
+        dc->desc          = _desc;                                          \
+    }                                                                       \
+                                                                            \
+    static const TypeInfo                                                   \
+    glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_type_info) = {         \
+        .name       = _name "-" TYPE_POWERPC_CPU,                           \
+        .parent     = stringify(_type) "-family-" TYPE_POWERPC_CPU,         \
+        .class_init =                                                       \
+            glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_class_init),   \
+    };                                                                      \
+                                                                            \
+    static void                                                             \
+    glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_register_types)(void)  \
+    {                                                                       \
+        type_register_static(                                               \
+            &glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_type_info));  \
+    }                                                                       \
+                                                                            \
+    type_init(                                                              \
+        glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_register_types))
+
+#define POWERPC_DEF(_name, _pvr, _type, _desc)                              \
+    POWERPC_DEF_SVR(_name, _desc, _pvr, POWERPC_SVR_NONE, _type)
+
+    /* Embedded PowerPC                                                      */
+    /* PowerPC 401 family                                                    */
+    POWERPC_DEF("401",           CPU_POWERPC_401,                    401,
+                "Generic PowerPC 401")
+    /* PowerPC 401 cores                                                     */
+    POWERPC_DEF("401A1",         CPU_POWERPC_401A1,                  401,
+                "PowerPC 401A1")
+    POWERPC_DEF("401B2",         CPU_POWERPC_401B2,                  401x2,
+                "PowerPC 401B2")
+#if defined(TODO)
+    POWERPC_DEF("401B3",         CPU_POWERPC_401B3,                  401x3,
+                "PowerPC 401B3")
+#endif
+    POWERPC_DEF("401C2",         CPU_POWERPC_401C2,                  401x2,
+                "PowerPC 401C2")
+    POWERPC_DEF("401D2",         CPU_POWERPC_401D2,                  401x2,
+                "PowerPC 401D2")
+    POWERPC_DEF("401E2",         CPU_POWERPC_401E2,                  401x2,
+                "PowerPC 401E2")
+    POWERPC_DEF("401F2",         CPU_POWERPC_401F2,                  401x2,
+                "PowerPC 401F2")
+    /* XXX: to be checked */
+    POWERPC_DEF("401G2",         CPU_POWERPC_401G2,                  401x2,
+                "PowerPC 401G2")
+    /* PowerPC 401 microcontrolers                                           */
+#if defined(TODO)
+    POWERPC_DEF("401GF",         CPU_POWERPC_401GF,                  401,
+                "PowerPC 401GF")
+#endif
+    POWERPC_DEF("IOP480",        CPU_POWERPC_IOP480,                 IOP480,
+                "IOP480 (401 microcontroller)")
+    POWERPC_DEF("Cobra",         CPU_POWERPC_COBRA,                  401,
+                "IBM Processor for Network Resources")
+#if defined(TODO)
+    POWERPC_DEF("Xipchip",       CPU_POWERPC_XIPCHIP,                401,
+                NULL)
+#endif
+    /* PowerPC 403 family                                                    */
+    /* PowerPC 403 microcontrolers                                           */
+    POWERPC_DEF("403GA",         CPU_POWERPC_403GA,                  403,
+                "PowerPC 403 GA")
+    POWERPC_DEF("403GB",         CPU_POWERPC_403GB,                  403,
+                "PowerPC 403 GB")
+    POWERPC_DEF("403GC",         CPU_POWERPC_403GC,                  403,
+                "PowerPC 403 GC")
+    POWERPC_DEF("403GCX",        CPU_POWERPC_403GCX,                 403GCX,
+                "PowerPC 403 GCX")
+#if defined(TODO)
+    POWERPC_DEF("403GP",         CPU_POWERPC_403GP,                  403,
+                "PowerPC 403 GP")
+#endif
+    /* PowerPC 405 family                                                    */
+    /* PowerPC 405 cores                                                     */
+#if defined(TODO)
+    POWERPC_DEF("405A3",         CPU_POWERPC_405A3,                  405,
+                "PowerPC 405 A3")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("405A4",         CPU_POWERPC_405A4,                  405,
+                "PowerPC 405 A4")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("405B3",         CPU_POWERPC_405B3,                  405,
+                "PowerPC 405 B3")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("405B4",         CPU_POWERPC_405B4,                  405,
+                "PowerPC 405 B4")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("405C3",         CPU_POWERPC_405C3,                  405,
+                "PowerPC 405 C3")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("405C4",         CPU_POWERPC_405C4,                  405,
+                "PowerPC 405 C4")
+#endif
+    POWERPC_DEF("405D2",         CPU_POWERPC_405D2,                  405,
+                "PowerPC 405 D2")
+#if defined(TODO)
+    POWERPC_DEF("405D3",         CPU_POWERPC_405D3,                  405,
+                "PowerPC 405 D3")
+#endif
+    POWERPC_DEF("405D4",         CPU_POWERPC_405D4,                  405,
+                "PowerPC 405 D4")
+#if defined(TODO)
+    POWERPC_DEF("405D5",         CPU_POWERPC_405D5,                  405,
+                "PowerPC 405 D5")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("405E4",         CPU_POWERPC_405E4,                  405,
+                "PowerPC 405 E4")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("405F4",         CPU_POWERPC_405F4,                  405,
+                "PowerPC 405 F4")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("405F5",         CPU_POWERPC_405F5,                  405,
+                "PowerPC 405 F5")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("405F6",         CPU_POWERPC_405F6,                  405,
+                "PowerPC 405 F6")
+#endif
+    /* PowerPC 405 microcontrolers                                           */
+    POWERPC_DEF("405CRa",        CPU_POWERPC_405CRa,                 405,
+                "PowerPC 405 CRa")
+    POWERPC_DEF("405CRb",        CPU_POWERPC_405CRb,                 405,
+                "PowerPC 405 CRb")
+    POWERPC_DEF("405CRc",        CPU_POWERPC_405CRc,                 405,
+                "PowerPC 405 CRc")
+    POWERPC_DEF("405EP",         CPU_POWERPC_405EP,                  405,
+                "PowerPC 405 EP")
+#if defined(TODO)
+    POWERPC_DEF("405EXr",        CPU_POWERPC_405EXr,                 405,
+                "PowerPC 405 EXr")
+#endif
+    POWERPC_DEF("405EZ",         CPU_POWERPC_405EZ,                  405,
+                "PowerPC 405 EZ")
+#if defined(TODO)
+    POWERPC_DEF("405FX",         CPU_POWERPC_405FX,                  405,
+                "PowerPC 405 FX")
+#endif
+    POWERPC_DEF("405GPa",        CPU_POWERPC_405GPa,                 405,
+                "PowerPC 405 GPa")
+    POWERPC_DEF("405GPb",        CPU_POWERPC_405GPb,                 405,
+                "PowerPC 405 GPb")
+    POWERPC_DEF("405GPc",        CPU_POWERPC_405GPc,                 405,
+                "PowerPC 405 GPc")
+    POWERPC_DEF("405GPd",        CPU_POWERPC_405GPd,                 405,
+                "PowerPC 405 GPd")
+    POWERPC_DEF("405GPR",        CPU_POWERPC_405GPR,                 405,
+                "PowerPC 405 GPR")
+#if defined(TODO)
+    POWERPC_DEF("405H",          CPU_POWERPC_405H,                   405,
+                "PowerPC 405 H")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("405L",          CPU_POWERPC_405L,                   405,
+                "PowerPC 405 L")
+#endif
+    POWERPC_DEF("405LP",         CPU_POWERPC_405LP,                  405,
+                "PowerPC 405 LP")
+#if defined(TODO)
+    POWERPC_DEF("405PM",         CPU_POWERPC_405PM,                  405,
+                "PowerPC 405 PM")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("405PS",         CPU_POWERPC_405PS,                  405,
+                "PowerPC 405 PS")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("405S",          CPU_POWERPC_405S,                   405,
+                "PowerPC 405 S")
+#endif
+    POWERPC_DEF("Npe405H",       CPU_POWERPC_NPE405H,                405,
+                "Npe405 H")
+    POWERPC_DEF("Npe405H2",      CPU_POWERPC_NPE405H2,               405,
+                "Npe405 H2")
+    POWERPC_DEF("Npe405L",       CPU_POWERPC_NPE405L,                405,
+                "Npe405 L")
+    POWERPC_DEF("Npe4GS3",       CPU_POWERPC_NPE4GS3,                405,
+                "Npe4GS3")
+#if defined(TODO)
+    POWERPC_DEF("Npcxx1",        CPU_POWERPC_NPCxx1,                 405,
+                NULL)
+#endif
+#if defined(TODO)
+    POWERPC_DEF("Npr161",        CPU_POWERPC_NPR161,                 405,
+                NULL)
+#endif
+#if defined(TODO)
+    POWERPC_DEF("LC77700",       CPU_POWERPC_LC77700,                405,
+                "PowerPC LC77700 (Sanyo)")
+#endif
+    /* PowerPC 401/403/405 based set-top-box microcontrolers                 */
+#if defined(TODO)
+    POWERPC_DEF("STB01000",      CPU_POWERPC_STB01000,               401x2,
+                "STB010000")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("STB01010",      CPU_POWERPC_STB01010,               401x2,
+                "STB01010")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("STB0210",       CPU_POWERPC_STB0210,                401x3,
+                "STB0210")
+#endif
+    POWERPC_DEF("STB03",         CPU_POWERPC_STB03,                  405,
+                "STB03xx")
+#if defined(TODO)
+    POWERPC_DEF("STB043",        CPU_POWERPC_STB043,                 405,
+                "STB043x")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("STB045",        CPU_POWERPC_STB045,                 405,
+                "STB045x")
+#endif
+    POWERPC_DEF("STB04",         CPU_POWERPC_STB04,                  405,
+                "STB04xx")
+    POWERPC_DEF("STB25",         CPU_POWERPC_STB25,                  405,
+                "STB25xx")
+#if defined(TODO)
+    POWERPC_DEF("STB130",        CPU_POWERPC_STB130,                 405,
+                "STB130")
+#endif
+    /* Xilinx PowerPC 405 cores                                              */
+    POWERPC_DEF("x2vp4",         CPU_POWERPC_X2VP4,                  405,
+                NULL)
+    POWERPC_DEF("x2vp20",        CPU_POWERPC_X2VP20,                 405,
+                NULL)
+#if defined(TODO)
+    POWERPC_DEF("zl10310",       CPU_POWERPC_ZL10310,                405,
+                "Zarlink ZL10310")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("zl10311",       CPU_POWERPC_ZL10311,                405,
+                "Zarlink ZL10311")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("zl10320",       CPU_POWERPC_ZL10320,                405,
+                "Zarlink ZL10320")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("zl10321",       CPU_POWERPC_ZL10321,                405,
+                "Zarlink ZL10321")
+#endif
+    /* PowerPC 440 family                                                    */
+#if defined(TODO_USER_ONLY)
+    POWERPC_DEF("440",           CPU_POWERPC_440,                    440GP,
+                "Generic PowerPC 440")
+#endif
+    /* PowerPC 440 cores                                                     */
+#if defined(TODO)
+    POWERPC_DEF("440A4",         CPU_POWERPC_440A4,                  440x4,
+                "PowerPC 440 A4")
+#endif
+    POWERPC_DEF("440-Xilinx",    CPU_POWERPC_440_XILINX,             440x5,
+                "PowerPC 440 Xilinx 5")
+#if defined(TODO)
+    POWERPC_DEF("440A5",         CPU_POWERPC_440A5,                  440x5,
+                "PowerPC 440 A5")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("440B4",         CPU_POWERPC_440B4,                  440x4,
+                "PowerPC 440 B4")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("440G4",         CPU_POWERPC_440G4,                  440x4,
+                "PowerPC 440 G4")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("440F5",         CPU_POWERPC_440F5,                  440x5,
+                "PowerPC 440 F5")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("440G5",         CPU_POWERPC_440G5,                  440x5,
+                "PowerPC 440 G5")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("440H4",         CPU_POWERPC_440H4,                  440x4,
+                "PowerPC 440H4")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("440H6",         CPU_POWERPC_440H6,                  440Gx5,
+                "PowerPC 440H6")
+#endif
+    /* PowerPC 440 microcontrolers                                           */
+    POWERPC_DEF("440EPa",        CPU_POWERPC_440EPa,                 440EP,
+                "PowerPC 440 EPa")
+    POWERPC_DEF("440EPb",        CPU_POWERPC_440EPb,                 440EP,
+                "PowerPC 440 EPb")
+    POWERPC_DEF("440EPX",        CPU_POWERPC_440EPX,                 440EP,
+                "PowerPC 440 EPX")
+#if defined(TODO_USER_ONLY)
+    POWERPC_DEF("440GPb",        CPU_POWERPC_440GPb,                 440GP,
+                "PowerPC 440 GPb")
+#endif
+#if defined(TODO_USER_ONLY)
+    POWERPC_DEF("440GPc",        CPU_POWERPC_440GPc,                 440GP,
+                "PowerPC 440 GPc")
+#endif
+#if defined(TODO_USER_ONLY)
+    POWERPC_DEF("440GRa",        CPU_POWERPC_440GRa,                 440x5,
+                "PowerPC 440 GRa")
+#endif
+#if defined(TODO_USER_ONLY)
+    POWERPC_DEF("440GRX",        CPU_POWERPC_440GRX,                 440x5,
+                "PowerPC 440 GRX")
+#endif
+#if defined(TODO_USER_ONLY)
+    POWERPC_DEF("440GXa",        CPU_POWERPC_440GXa,                 440EP,
+                "PowerPC 440 GXa")
+#endif
+#if defined(TODO_USER_ONLY)
+    POWERPC_DEF("440GXb",        CPU_POWERPC_440GXb,                 440EP,
+                "PowerPC 440 GXb")
+#endif
+#if defined(TODO_USER_ONLY)
+    POWERPC_DEF("440GXc",        CPU_POWERPC_440GXc,                 440EP,
+                "PowerPC 440 GXc")
+#endif
+#if defined(TODO_USER_ONLY)
+    POWERPC_DEF("440GXf",        CPU_POWERPC_440GXf,                 440EP,
+                "PowerPC 440 GXf")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("440S",          CPU_POWERPC_440S,                   440,
+                "PowerPC 440 S")
+#endif
+#if defined(TODO_USER_ONLY)
+    POWERPC_DEF("440SP",         CPU_POWERPC_440SP,                  440EP,
+                "PowerPC 440 SP")
+#endif
+#if defined(TODO_USER_ONLY)
+    POWERPC_DEF("440SP2",        CPU_POWERPC_440SP2,                 440EP,
+                "PowerPC 440 SP2")
+#endif
+#if defined(TODO_USER_ONLY)
+    POWERPC_DEF("440SPE",        CPU_POWERPC_440SPE,                 440EP,
+                "PowerPC 440 SPE")
+#endif
+    /* PowerPC 460 family                                                    */
+#if defined(TODO)
+    POWERPC_DEF("464",           CPU_POWERPC_464,                    460,
+                "Generic PowerPC 464")
+#endif
+    /* PowerPC 464 microcontrolers                                           */
+#if defined(TODO)
+    POWERPC_DEF("464H90",        CPU_POWERPC_464H90,                 460,
+                "PowerPC 464H90")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("464H90F",       CPU_POWERPC_464H90F,                460F,
+                "PowerPC 464H90F")
+#endif
+    /* Freescale embedded PowerPC cores                                      */
+    /* MPC5xx family (aka RCPU)                                              */
+#if defined(TODO_USER_ONLY)
+    POWERPC_DEF("MPC5xx",        CPU_POWERPC_MPC5xx,                 MPC5xx,
+                "Generic MPC5xx core")
+#endif
+    /* MPC8xx family (aka PowerQUICC)                                        */
+#if defined(TODO_USER_ONLY)
+    POWERPC_DEF("MPC8xx",        CPU_POWERPC_MPC8xx,                 MPC8xx,
+                "Generic MPC8xx core")
+#endif
+    /* MPC82xx family (aka PowerQUICC-II)                                    */
+    POWERPC_DEF("G2",            CPU_POWERPC_G2,                     G2,
+                "PowerPC G2 core")
+    POWERPC_DEF("G2H4",          CPU_POWERPC_G2H4,                   G2,
+                "PowerPC G2 H4 core")
+    POWERPC_DEF("G2GP",          CPU_POWERPC_G2gp,                   G2,
+                "PowerPC G2 GP core")
+    POWERPC_DEF("G2LS",          CPU_POWERPC_G2ls,                   G2,
+                "PowerPC G2 LS core")
+    POWERPC_DEF("G2HiP3",        CPU_POWERPC_G2_HIP3,                G2,
+                "PowerPC G2 HiP3 core")
+    POWERPC_DEF("G2HiP4",        CPU_POWERPC_G2_HIP4,                G2,
+                "PowerPC G2 HiP4 core")
+    POWERPC_DEF("MPC603",        CPU_POWERPC_MPC603,                 603E,
+                "PowerPC MPC603 core")
+    POWERPC_DEF("G2le",          CPU_POWERPC_G2LE,                   G2LE,
+        "PowerPC G2le core (same as G2 plus little-endian mode support)")
+    POWERPC_DEF("G2leGP",        CPU_POWERPC_G2LEgp,                 G2LE,
+                "PowerPC G2LE GP core")
+    POWERPC_DEF("G2leLS",        CPU_POWERPC_G2LEls,                 G2LE,
+                "PowerPC G2LE LS core")
+    POWERPC_DEF("G2leGP1",       CPU_POWERPC_G2LEgp1,                G2LE,
+                "PowerPC G2LE GP1 core")
+    POWERPC_DEF("G2leGP3",       CPU_POWERPC_G2LEgp3,                G2LE,
+                "PowerPC G2LE GP3 core")
+    /* PowerPC G2 microcontrollers                                           */
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5121", "MPC5121",
+                    CPU_POWERPC_MPC5121,      POWERPC_SVR_5121,      G2LE)
+#endif
+    POWERPC_DEF_SVR("MPC5200_v10", "MPC5200 v1.0",
+                    CPU_POWERPC_MPC5200_v10,  POWERPC_SVR_5200_v10,  G2LE)
+    POWERPC_DEF_SVR("MPC5200_v11", "MPC5200 v1.1",
+                    CPU_POWERPC_MPC5200_v11,  POWERPC_SVR_5200_v11,  G2LE)
+    POWERPC_DEF_SVR("MPC5200_v12", "MPC5200 v1.2",
+                    CPU_POWERPC_MPC5200_v12,  POWERPC_SVR_5200_v12,  G2LE)
+    POWERPC_DEF_SVR("MPC5200B_v20", "MPC5200B v2.0",
+                    CPU_POWERPC_MPC5200B_v20, POWERPC_SVR_5200B_v20, G2LE)
+    POWERPC_DEF_SVR("MPC5200B_v21", "MPC5200B v2.1",
+                    CPU_POWERPC_MPC5200B_v21, POWERPC_SVR_5200B_v21, G2LE)
+    /* e200 family                                                           */
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC55xx", "Generic MPC55xx core",
+                    CPU_POWERPC_MPC55xx,      POWERPC_SVR_55xx,      e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF("e200z0",        CPU_POWERPC_e200z0,                 e200,
+                "PowerPC e200z0 core")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("e200z1",        CPU_POWERPC_e200z1,                 e200,
+                "PowerPC e200z1 core")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("e200z3",        CPU_POWERPC_e200z3,                 e200,
+                "PowerPC e200z3 core")
+#endif
+    POWERPC_DEF("e200z5",        CPU_POWERPC_e200z5,                 e200,
+                "PowerPC e200z5 core")
+    POWERPC_DEF("e200z6",        CPU_POWERPC_e200z6,                 e200,
+                "PowerPC e200z6 core")
+    /* PowerPC e200 microcontrollers                                         */
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5514E", "MPC5514E",
+                    CPU_POWERPC_MPC5514E,     POWERPC_SVR_5514E,     e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5514E_v0", "MPC5514E v0",
+                    CPU_POWERPC_MPC5514E_v0,  POWERPC_SVR_5514E_v0,  e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5514E_v1", "MPC5514E v1",
+                    CPU_POWERPC_MPC5514E_v1,  POWERPC_SVR_5514E_v1,  e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5514G", "MPC5514G",
+                    CPU_POWERPC_MPC5514G,     POWERPC_SVR_5514G,     e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5514G_v0", "MPC5514G v0",
+                    CPU_POWERPC_MPC5514G_v0,  POWERPC_SVR_5514G_v0,  e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5514G_v1", "MPC5514G v1",
+                    CPU_POWERPC_MPC5514G_v1,  POWERPC_SVR_5514G_v1,  e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5515S", "MPC5515S",
+                    CPU_POWERPC_MPC5515S,     POWERPC_SVR_5515S,     e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5516E", "MPC5516E",
+                    CPU_POWERPC_MPC5516E,     POWERPC_SVR_5516E,     e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5516E_v0", "MPC5516E v0",
+                    CPU_POWERPC_MPC5516E_v0,  POWERPC_SVR_5516E_v0,  e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5516E_v1", "MPC5516E v1",
+                    CPU_POWERPC_MPC5516E_v1,  POWERPC_SVR_5516E_v1,  e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5516G", "MPC5516G",
+                    CPU_POWERPC_MPC5516G,     POWERPC_SVR_5516G,     e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5516G_v0", "MPC5516G v0",
+                    CPU_POWERPC_MPC5516G_v0,  POWERPC_SVR_5516G_v0,  e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5516G_v1", "MPC5516G v1",
+                    CPU_POWERPC_MPC5516G_v1,  POWERPC_SVR_5516G_v1,  e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5516S", "MPC5516S",
+                    CPU_POWERPC_MPC5516S,     POWERPC_SVR_5516S,     e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5533", "MPC5533",
+                    CPU_POWERPC_MPC5533,      POWERPC_SVR_5533,      e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5534", "MPC5534",
+                    CPU_POWERPC_MPC5534,      POWERPC_SVR_5534,      e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5553", "MPC5553",
+                    CPU_POWERPC_MPC5553,      POWERPC_SVR_5553,      e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5554", "MPC5554",
+                    CPU_POWERPC_MPC5554,      POWERPC_SVR_5554,      e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5561", "MPC5561",
+                    CPU_POWERPC_MPC5561,      POWERPC_SVR_5561,      e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5565", "MPC5565",
+                    CPU_POWERPC_MPC5565,      POWERPC_SVR_5565,      e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5566", "MPC5566",
+                    CPU_POWERPC_MPC5566,      POWERPC_SVR_5566,      e200)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC5567", "MPC5567",
+                    CPU_POWERPC_MPC5567,      POWERPC_SVR_5567,      e200)
+#endif
+    /* e300 family                                                           */
+    POWERPC_DEF("e300c1",        CPU_POWERPC_e300c1,                 e300,
+                "PowerPC e300c1 core")
+    POWERPC_DEF("e300c2",        CPU_POWERPC_e300c2,                 e300,
+                "PowerPC e300c2 core")
+    POWERPC_DEF("e300c3",        CPU_POWERPC_e300c3,                 e300,
+                "PowerPC e300c3 core")
+    POWERPC_DEF("e300c4",        CPU_POWERPC_e300c4,                 e300,
+                "PowerPC e300c4 core")
+    /* PowerPC e300 microcontrollers                                         */
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC8313", "MPC8313",
+                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8313,      e300)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC8313E", "MPC8313E",
+                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8313E,     e300)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC8314", "MPC8314",
+                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8314,      e300)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC8314E", "MPC8314E",
+                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8314E,     e300)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC8315", "MPC8315",
+                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8315,      e300)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC8315E", "MPC8315E",
+                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8315E,     e300)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC8321", "MPC8321",
+                    CPU_POWERPC_MPC832x,      POWERPC_SVR_8321,      e300)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC8321E", "MPC8321E",
+                    CPU_POWERPC_MPC832x,      POWERPC_SVR_8321E,     e300)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC8323", "MPC8323",
+                    CPU_POWERPC_MPC832x,      POWERPC_SVR_8323,      e300)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC8323E", "MPC8323E",
+                    CPU_POWERPC_MPC832x,      POWERPC_SVR_8323E,     e300)
+#endif
+    POWERPC_DEF_SVR("MPC8343", "MPC8343",
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8343,      e300)
+    POWERPC_DEF_SVR("MPC8343A", "MPC8343A",
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8343A,     e300)
+    POWERPC_DEF_SVR("MPC8343E", "MPC8343E",
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8343E,     e300)
+    POWERPC_DEF_SVR("MPC8343EA", "MPC8343EA",
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8343EA,    e300)
+    POWERPC_DEF_SVR("MPC8347T", "MPC8347T",
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347T,     e300)
+    POWERPC_DEF_SVR("MPC8347P", "MPC8347P",
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347P,     e300)
+    POWERPC_DEF_SVR("MPC8347AT", "MPC8347AT",
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347AT,    e300)
+    POWERPC_DEF_SVR("MPC8347AP", "MPC8347AP",
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347AP,    e300)
+    POWERPC_DEF_SVR("MPC8347ET", "MPC8347ET",
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347ET,    e300)
+    POWERPC_DEF_SVR("MPC8347EP", "MPC8343EP",
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EP,    e300)
+    POWERPC_DEF_SVR("MPC8347EAT", "MPC8347EAT",
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EAT,   e300)
+    POWERPC_DEF_SVR("MPC8347EAP", "MPC8343EAP",
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EAP,   e300)
+    POWERPC_DEF_SVR("MPC8349", "MPC8349",
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8349,      e300)
+    POWERPC_DEF_SVR("MPC8349A", "MPC8349A",
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8349A,     e300)
+    POWERPC_DEF_SVR("MPC8349E", "MPC8349E",
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8349E,     e300)
+    POWERPC_DEF_SVR("MPC8349EA", "MPC8349EA",
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8349EA,    e300)
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC8358E", "MPC8358E",
+                    CPU_POWERPC_MPC835x,      POWERPC_SVR_8358E,     e300)
+#endif
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC8360E", "MPC8360E",
+                    CPU_POWERPC_MPC836x,      POWERPC_SVR_8360E,     e300)
+#endif
+    POWERPC_DEF_SVR("MPC8377", "MPC8377",
+                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8377,      e300)
+    POWERPC_DEF_SVR("MPC8377E", "MPC8377E",
+                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8377E,     e300)
+    POWERPC_DEF_SVR("MPC8378", "MPC8378",
+                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8378,      e300)
+    POWERPC_DEF_SVR("MPC8378E", "MPC8378E",
+                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8378E,     e300)
+    POWERPC_DEF_SVR("MPC8379", "MPC8379",
+                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8379,      e300)
+    POWERPC_DEF_SVR("MPC8379E", "MPC8379E",
+                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8379E,     e300)
+    /* e500 family                                                           */
+    POWERPC_DEF("e500_v10",      CPU_POWERPC_e500v1_v10,             e500v1,
+                "PowerPC e500 v1.0 core")
+    POWERPC_DEF("e500_v20",      CPU_POWERPC_e500v1_v20,             e500v1,
+                "PowerPC e500 v2.0 core")
+    POWERPC_DEF("e500v2_v10",    CPU_POWERPC_e500v2_v10,             e500v2,
+                "PowerPC e500v2 v1.0 core")
+    POWERPC_DEF("e500v2_v20",    CPU_POWERPC_e500v2_v20,             e500v2,
+                "PowerPC e500v2 v2.0 core")
+    POWERPC_DEF("e500v2_v21",    CPU_POWERPC_e500v2_v21,             e500v2,
+                "PowerPC e500v2 v2.1 core")
+    POWERPC_DEF("e500v2_v22",    CPU_POWERPC_e500v2_v22,             e500v2,
+                "PowerPC e500v2 v2.2 core")
+    POWERPC_DEF("e500v2_v30",    CPU_POWERPC_e500v2_v30,             e500v2,
+                "PowerPC e500v2 v3.0 core")
+    POWERPC_DEF_SVR("e500mc", "e500mc",
+                    CPU_POWERPC_e500mc,       POWERPC_SVR_E500,      e500mc)
+#ifdef TARGET_PPC64
+    POWERPC_DEF_SVR("e5500", "e5500",
+                    CPU_POWERPC_e5500,        POWERPC_SVR_E500,      e5500)
+#endif
+    /* PowerPC e500 microcontrollers                                         */
+    POWERPC_DEF_SVR("MPC8533_v10", "MPC8533 v1.0",
+                    CPU_POWERPC_MPC8533_v10,  POWERPC_SVR_8533_v10,  e500v2)
+    POWERPC_DEF_SVR("MPC8533_v11", "MPC8533 v1.1",
+                    CPU_POWERPC_MPC8533_v11,  POWERPC_SVR_8533_v11,  e500v2)
+    POWERPC_DEF_SVR("MPC8533E_v10", "MPC8533E v1.0",
+                    CPU_POWERPC_MPC8533E_v10, POWERPC_SVR_8533E_v10, e500v2)
+    POWERPC_DEF_SVR("MPC8533E_v11", "MPC8533E v1.1",
+                    CPU_POWERPC_MPC8533E_v11, POWERPC_SVR_8533E_v11, e500v2)
+    POWERPC_DEF_SVR("MPC8540_v10", "MPC8540 v1.0",
+                    CPU_POWERPC_MPC8540_v10,  POWERPC_SVR_8540_v10,  e500v1)
+    POWERPC_DEF_SVR("MPC8540_v20", "MPC8540 v2.0",
+                    CPU_POWERPC_MPC8540_v20,  POWERPC_SVR_8540_v20,  e500v1)
+    POWERPC_DEF_SVR("MPC8540_v21", "MPC8540 v2.1",
+                    CPU_POWERPC_MPC8540_v21,  POWERPC_SVR_8540_v21,  e500v1)
+    POWERPC_DEF_SVR("MPC8541_v10", "MPC8541 v1.0",
+                    CPU_POWERPC_MPC8541_v10,  POWERPC_SVR_8541_v10,  e500v1)
+    POWERPC_DEF_SVR("MPC8541_v11", "MPC8541 v1.1",
+                    CPU_POWERPC_MPC8541_v11,  POWERPC_SVR_8541_v11,  e500v1)
+    POWERPC_DEF_SVR("MPC8541E_v10", "MPC8541E v1.0",
+                    CPU_POWERPC_MPC8541E_v10, POWERPC_SVR_8541E_v10, e500v1)
+    POWERPC_DEF_SVR("MPC8541E_v11", "MPC8541E v1.1",
+                    CPU_POWERPC_MPC8541E_v11, POWERPC_SVR_8541E_v11, e500v1)
+    POWERPC_DEF_SVR("MPC8543_v10", "MPC8543 v1.0",
+                    CPU_POWERPC_MPC8543_v10,  POWERPC_SVR_8543_v10,  e500v2)
+    POWERPC_DEF_SVR("MPC8543_v11", "MPC8543 v1.1",
+                    CPU_POWERPC_MPC8543_v11,  POWERPC_SVR_8543_v11,  e500v2)
+    POWERPC_DEF_SVR("MPC8543_v20", "MPC8543 v2.0",
+                    CPU_POWERPC_MPC8543_v20,  POWERPC_SVR_8543_v20,  e500v2)
+    POWERPC_DEF_SVR("MPC8543_v21", "MPC8543 v2.1",
+                    CPU_POWERPC_MPC8543_v21,  POWERPC_SVR_8543_v21,  e500v2)
+    POWERPC_DEF_SVR("MPC8543E_v10", "MPC8543E v1.0",
+                    CPU_POWERPC_MPC8543E_v10, POWERPC_SVR_8543E_v10, e500v2)
+    POWERPC_DEF_SVR("MPC8543E_v11", "MPC8543E v1.1",
+                    CPU_POWERPC_MPC8543E_v11, POWERPC_SVR_8543E_v11, e500v2)
+    POWERPC_DEF_SVR("MPC8543E_v20", "MPC8543E v2.0",
+                    CPU_POWERPC_MPC8543E_v20, POWERPC_SVR_8543E_v20, e500v2)
+    POWERPC_DEF_SVR("MPC8543E_v21", "MPC8543E v2.1",
+                    CPU_POWERPC_MPC8543E_v21, POWERPC_SVR_8543E_v21, e500v2)
+    POWERPC_DEF_SVR("MPC8544_v10", "MPC8544 v1.0",
+                    CPU_POWERPC_MPC8544_v10,  POWERPC_SVR_8544_v10,  e500v2)
+    POWERPC_DEF_SVR("MPC8544_v11", "MPC8544 v1.1",
+                    CPU_POWERPC_MPC8544_v11,  POWERPC_SVR_8544_v11,  e500v2)
+    POWERPC_DEF_SVR("MPC8544E_v10", "MPC8544E v1.0",
+                    CPU_POWERPC_MPC8544E_v10, POWERPC_SVR_8544E_v10, e500v2)
+    POWERPC_DEF_SVR("MPC8544E_v11", "MPC8544E v1.1",
+                    CPU_POWERPC_MPC8544E_v11, POWERPC_SVR_8544E_v11, e500v2)
+    POWERPC_DEF_SVR("MPC8545_v20", "MPC8545 v2.0",
+                    CPU_POWERPC_MPC8545_v20,  POWERPC_SVR_8545_v20,  e500v2)
+    POWERPC_DEF_SVR("MPC8545_v21", "MPC8545 v2.1",
+                    CPU_POWERPC_MPC8545_v21,  POWERPC_SVR_8545_v21,  e500v2)
+    POWERPC_DEF_SVR("MPC8545E_v20", "MPC8545E v2.0",
+                    CPU_POWERPC_MPC8545E_v20, POWERPC_SVR_8545E_v20, e500v2)
+    POWERPC_DEF_SVR("MPC8545E_v21", "MPC8545E v2.1",
+                    CPU_POWERPC_MPC8545E_v21, POWERPC_SVR_8545E_v21, e500v2)
+    POWERPC_DEF_SVR("MPC8547E_v20", "MPC8547E v2.0",
+                    CPU_POWERPC_MPC8547E_v20, POWERPC_SVR_8547E_v20, e500v2)
+    POWERPC_DEF_SVR("MPC8547E_v21", "MPC8547E v2.1",
+                    CPU_POWERPC_MPC8547E_v21, POWERPC_SVR_8547E_v21, e500v2)
+    POWERPC_DEF_SVR("MPC8548_v10", "MPC8548 v1.0",
+                    CPU_POWERPC_MPC8548_v10,  POWERPC_SVR_8548_v10,  e500v2)
+    POWERPC_DEF_SVR("MPC8548_v11", "MPC8548 v1.1",
+                    CPU_POWERPC_MPC8548_v11,  POWERPC_SVR_8548_v11,  e500v2)
+    POWERPC_DEF_SVR("MPC8548_v20", "MPC8548 v2.0",
+                    CPU_POWERPC_MPC8548_v20,  POWERPC_SVR_8548_v20,  e500v2)
+    POWERPC_DEF_SVR("MPC8548_v21", "MPC8548 v2.1",
+                    CPU_POWERPC_MPC8548_v21,  POWERPC_SVR_8548_v21,  e500v2)
+    POWERPC_DEF_SVR("MPC8548E_v10", "MPC8548E v1.0",
+                    CPU_POWERPC_MPC8548E_v10, POWERPC_SVR_8548E_v10, e500v2)
+    POWERPC_DEF_SVR("MPC8548E_v11", "MPC8548E v1.1",
+                    CPU_POWERPC_MPC8548E_v11, POWERPC_SVR_8548E_v11, e500v2)
+    POWERPC_DEF_SVR("MPC8548E_v20", "MPC8548E v2.0",
+                    CPU_POWERPC_MPC8548E_v20, POWERPC_SVR_8548E_v20, e500v2)
+    POWERPC_DEF_SVR("MPC8548E_v21", "MPC8548E v2.1",
+                    CPU_POWERPC_MPC8548E_v21, POWERPC_SVR_8548E_v21, e500v2)
+    POWERPC_DEF_SVR("MPC8555_v10", "MPC8555 v1.0",
+                    CPU_POWERPC_MPC8555_v10,  POWERPC_SVR_8555_v10,  e500v2)
+    POWERPC_DEF_SVR("MPC8555_v11", "MPC8555 v1.1",
+                    CPU_POWERPC_MPC8555_v11,  POWERPC_SVR_8555_v11,  e500v2)
+    POWERPC_DEF_SVR("MPC8555E_v10", "MPC8555E v1.0",
+                    CPU_POWERPC_MPC8555E_v10, POWERPC_SVR_8555E_v10, e500v2)
+    POWERPC_DEF_SVR("MPC8555E_v11", "MPC8555E v1.1",
+                    CPU_POWERPC_MPC8555E_v11, POWERPC_SVR_8555E_v11, e500v2)
+    POWERPC_DEF_SVR("MPC8560_v10", "MPC8560 v1.0",
+                    CPU_POWERPC_MPC8560_v10,  POWERPC_SVR_8560_v10,  e500v2)
+    POWERPC_DEF_SVR("MPC8560_v20", "MPC8560 v2.0",
+                    CPU_POWERPC_MPC8560_v20,  POWERPC_SVR_8560_v20,  e500v2)
+    POWERPC_DEF_SVR("MPC8560_v21", "MPC8560 v2.1",
+                    CPU_POWERPC_MPC8560_v21,  POWERPC_SVR_8560_v21,  e500v2)
+    POWERPC_DEF_SVR("MPC8567", "MPC8567",
+                    CPU_POWERPC_MPC8567,      POWERPC_SVR_8567,      e500v2)
+    POWERPC_DEF_SVR("MPC8567E", "MPC8567E",
+                    CPU_POWERPC_MPC8567E,     POWERPC_SVR_8567E,     e500v2)
+    POWERPC_DEF_SVR("MPC8568", "MPC8568",
+                    CPU_POWERPC_MPC8568,      POWERPC_SVR_8568,      e500v2)
+    POWERPC_DEF_SVR("MPC8568E", "MPC8568E",
+                    CPU_POWERPC_MPC8568E,     POWERPC_SVR_8568E,     e500v2)
+    POWERPC_DEF_SVR("MPC8572", "MPC8572",
+                    CPU_POWERPC_MPC8572,      POWERPC_SVR_8572,      e500v2)
+    POWERPC_DEF_SVR("MPC8572E", "MPC8572E",
+                    CPU_POWERPC_MPC8572E,     POWERPC_SVR_8572E,     e500v2)
+    /* e600 family                                                           */
+    POWERPC_DEF("e600",          CPU_POWERPC_e600,                   7400,
+                "PowerPC e600 core")
+    /* PowerPC e600 microcontrollers                                         */
+#if defined(TODO)
+    POWERPC_DEF_SVR("MPC8610", "MPC8610",
+                    CPU_POWERPC_MPC8610,      POWERPC_SVR_8610,      7400)
+#endif
+    POWERPC_DEF_SVR("MPC8641", "MPC8641",
+                    CPU_POWERPC_MPC8641,      POWERPC_SVR_8641,      7400)
+    POWERPC_DEF_SVR("MPC8641D", "MPC8641D",
+                    CPU_POWERPC_MPC8641D,     POWERPC_SVR_8641D,     7400)
+    /* 32 bits "classic" PowerPC                                             */
+    /* PowerPC 6xx family                                                    */
+    POWERPC_DEF("601_v0",        CPU_POWERPC_601_v0,                 601,
+                "PowerPC 601v0")
+    POWERPC_DEF("601_v1",        CPU_POWERPC_601_v1,                 601,
+                "PowerPC 601v1")
+    POWERPC_DEF("601_v2",        CPU_POWERPC_601_v2,                 601v,
+                "PowerPC 601v2")
+    POWERPC_DEF("602",           CPU_POWERPC_602,                    602,
+                "PowerPC 602")
+    POWERPC_DEF("603",           CPU_POWERPC_603,                    603,
+                "PowerPC 603")
+    POWERPC_DEF("603e_v1.1",     CPU_POWERPC_603E_v11,               603E,
+                "PowerPC 603e v1.1")
+    POWERPC_DEF("603e_v1.2",     CPU_POWERPC_603E_v12,               603E,
+                "PowerPC 603e v1.2")
+    POWERPC_DEF("603e_v1.3",     CPU_POWERPC_603E_v13,               603E,
+                "PowerPC 603e v1.3")
+    POWERPC_DEF("603e_v1.4",     CPU_POWERPC_603E_v14,               603E,
+                "PowerPC 603e v1.4")
+    POWERPC_DEF("603e_v2.2",     CPU_POWERPC_603E_v22,               603E,
+                "PowerPC 603e v2.2")
+    POWERPC_DEF("603e_v3",       CPU_POWERPC_603E_v3,                603E,
+                "PowerPC 603e v3")
+    POWERPC_DEF("603e_v4",       CPU_POWERPC_603E_v4,                603E,
+                "PowerPC 603e v4")
+    POWERPC_DEF("603e_v4.1",     CPU_POWERPC_603E_v41,               603E,
+                "PowerPC 603e v4.1")
+    POWERPC_DEF("603e7",         CPU_POWERPC_603E7,                  603E,
+                "PowerPC 603e (aka PID7)")
+    POWERPC_DEF("603e7t",        CPU_POWERPC_603E7t,                 603E,
+                "PowerPC 603e7t")
+    POWERPC_DEF("603e7v",        CPU_POWERPC_603E7v,                 603E,
+                "PowerPC 603e7v")
+    POWERPC_DEF("603e7v1",       CPU_POWERPC_603E7v1,                603E,
+                "PowerPC 603e7v1")
+    POWERPC_DEF("603e7v2",       CPU_POWERPC_603E7v2,                603E,
+                "PowerPC 603e7v2")
+    POWERPC_DEF("603p",          CPU_POWERPC_603P,                   603E,
+                "PowerPC 603p (aka PID7v)")
+    POWERPC_DEF("604",           CPU_POWERPC_604,                    604,
+                "PowerPC 604")
+    POWERPC_DEF("604e_v1.0",     CPU_POWERPC_604E_v10,               604E,
+                "PowerPC 604e v1.0")
+    POWERPC_DEF("604e_v2.2",     CPU_POWERPC_604E_v22,               604E,
+                "PowerPC 604e v2.2")
+    POWERPC_DEF("604e_v2.4",     CPU_POWERPC_604E_v24,               604E,
+                "PowerPC 604e v2.4")
+    POWERPC_DEF("604r",          CPU_POWERPC_604R,                   604E,
+                "PowerPC 604r (aka PIDA)")
+#if defined(TODO)
+    POWERPC_DEF("604ev",         CPU_POWERPC_604EV,                  604E,
+                "PowerPC 604ev")
+#endif
+    /* PowerPC 7xx family                                                    */
+    POWERPC_DEF("740_v1.0",      CPU_POWERPC_7x0_v10,                740,
+                "PowerPC 740 v1.0 (G3)")
+    POWERPC_DEF("750_v1.0",      CPU_POWERPC_7x0_v10,                750,
+                "PowerPC 750 v1.0 (G3)")
+    POWERPC_DEF("740_v2.0",      CPU_POWERPC_7x0_v20,                740,
+                "PowerPC 740 v2.0 (G3)")
+    POWERPC_DEF("750_v2.0",      CPU_POWERPC_7x0_v20,                750,
+                "PowerPC 750 v2.0 (G3)")
+    POWERPC_DEF("740_v2.1",      CPU_POWERPC_7x0_v21,                740,
+                "PowerPC 740 v2.1 (G3)")
+    POWERPC_DEF("750_v2.1",      CPU_POWERPC_7x0_v21,                750,
+                "PowerPC 750 v2.1 (G3)")
+    POWERPC_DEF("740_v2.2",      CPU_POWERPC_7x0_v22,                740,
+                "PowerPC 740 v2.2 (G3)")
+    POWERPC_DEF("750_v2.2",      CPU_POWERPC_7x0_v22,                750,
+                "PowerPC 750 v2.2 (G3)")
+    POWERPC_DEF("740_v3.0",      CPU_POWERPC_7x0_v30,                740,
+                "PowerPC 740 v3.0 (G3)")
+    POWERPC_DEF("750_v3.0",      CPU_POWERPC_7x0_v30,                750,
+                "PowerPC 750 v3.0 (G3)")
+    POWERPC_DEF("740_v3.1",      CPU_POWERPC_7x0_v31,                740,
+                "PowerPC 740 v3.1 (G3)")
+    POWERPC_DEF("750_v3.1",      CPU_POWERPC_7x0_v31,                750,
+                "PowerPC 750 v3.1 (G3)")
+    POWERPC_DEF("740e",          CPU_POWERPC_740E,                   740,
+                "PowerPC 740E (G3)")
+    POWERPC_DEF("750e",          CPU_POWERPC_750E,                   750,
+                "PowerPC 750E (G3)")
+    POWERPC_DEF("740p",          CPU_POWERPC_7x0P,                   740,
+                "PowerPC 740P (G3)")
+    POWERPC_DEF("750p",          CPU_POWERPC_7x0P,                   750,
+                "PowerPC 750P (G3)")
+    POWERPC_DEF("750cl_v1.0",    CPU_POWERPC_750CL_v10,              750cl,
+                "PowerPC 750CL v1.0")
+    POWERPC_DEF("750cl_v2.0",    CPU_POWERPC_750CL_v20,              750cl,
+                "PowerPC 750CL v2.0")
+    POWERPC_DEF("750cx_v1.0",    CPU_POWERPC_750CX_v10,              750cx,
+                "PowerPC 750CX v1.0 (G3 embedded)")
+    POWERPC_DEF("750cx_v2.0",    CPU_POWERPC_750CX_v20,              750cx,
+                "PowerPC 750CX v2.1 (G3 embedded)")
+    POWERPC_DEF("750cx_v2.1",    CPU_POWERPC_750CX_v21,              750cx,
+                "PowerPC 750CX v2.1 (G3 embedded)")
+    POWERPC_DEF("750cx_v2.2",    CPU_POWERPC_750CX_v22,              750cx,
+                "PowerPC 750CX v2.2 (G3 embedded)")
+    POWERPC_DEF("750cxe_v2.1",   CPU_POWERPC_750CXE_v21,             750cx,
+                "PowerPC 750CXe v2.1 (G3 embedded)")
+    POWERPC_DEF("750cxe_v2.2",   CPU_POWERPC_750CXE_v22,             750cx,
+                "PowerPC 750CXe v2.2 (G3 embedded)")
+    POWERPC_DEF("750cxe_v2.3",   CPU_POWERPC_750CXE_v23,             750cx,
+                "PowerPC 750CXe v2.3 (G3 embedded)")
+    POWERPC_DEF("750cxe_v2.4",   CPU_POWERPC_750CXE_v24,             750cx,
+                "PowerPC 750CXe v2.4 (G3 embedded)")
+    POWERPC_DEF("750cxe_v2.4b",  CPU_POWERPC_750CXE_v24b,            750cx,
+                "PowerPC 750CXe v2.4b (G3 embedded)")
+    POWERPC_DEF("750cxe_v3.0",   CPU_POWERPC_750CXE_v30,             750cx,
+                "PowerPC 750CXe v3.0 (G3 embedded)")
+    POWERPC_DEF("750cxe_v3.1",   CPU_POWERPC_750CXE_v31,             750cx,
+                "PowerPC 750CXe v3.1 (G3 embedded)")
+    POWERPC_DEF("750cxe_v3.1b",  CPU_POWERPC_750CXE_v31b,            750cx,
+                "PowerPC 750CXe v3.1b (G3 embedded)")
+    POWERPC_DEF("750cxr",        CPU_POWERPC_750CXR,                 750cx,
+                "PowerPC 750CXr (G3 embedded)")
+    POWERPC_DEF("750fl",         CPU_POWERPC_750FL,                  750fx,
+                "PowerPC 750FL (G3 embedded)")
+    POWERPC_DEF("750fx_v1.0",    CPU_POWERPC_750FX_v10,              750fx,
+                "PowerPC 750FX v1.0 (G3 embedded)")
+    POWERPC_DEF("750fx_v2.0",    CPU_POWERPC_750FX_v20,              750fx,
+                "PowerPC 750FX v2.0 (G3 embedded)")
+    POWERPC_DEF("750fx_v2.1",    CPU_POWERPC_750FX_v21,              750fx,
+                "PowerPC 750FX v2.1 (G3 embedded)")
+    POWERPC_DEF("750fx_v2.2",    CPU_POWERPC_750FX_v22,              750fx,
+                "PowerPC 750FX v2.2 (G3 embedded)")
+    POWERPC_DEF("750fx_v2.3",    CPU_POWERPC_750FX_v23,              750fx,
+                "PowerPC 750FX v2.3 (G3 embedded)")
+    POWERPC_DEF("750gl",         CPU_POWERPC_750GL,                  750gx,
+                "PowerPC 750GL (G3 embedded)")
+    POWERPC_DEF("750gx_v1.0",    CPU_POWERPC_750GX_v10,              750gx,
+                "PowerPC 750GX v1.0 (G3 embedded)")
+    POWERPC_DEF("750gx_v1.1",    CPU_POWERPC_750GX_v11,              750gx,
+                "PowerPC 750GX v1.1 (G3 embedded)")
+    POWERPC_DEF("750gx_v1.2",    CPU_POWERPC_750GX_v12,              750gx,
+                "PowerPC 750GX v1.2 (G3 embedded)")
+    POWERPC_DEF("750l_v2.0",     CPU_POWERPC_750L_v20,               750,
+                "PowerPC 750L v2.0 (G3 embedded)")
+    POWERPC_DEF("750l_v2.1",     CPU_POWERPC_750L_v21,               750,
+                "PowerPC 750L v2.1 (G3 embedded)")
+    POWERPC_DEF("750l_v2.2",     CPU_POWERPC_750L_v22,               750,
+                "PowerPC 750L v2.2 (G3 embedded)")
+    POWERPC_DEF("750l_v3.0",     CPU_POWERPC_750L_v30,               750,
+                "PowerPC 750L v3.0 (G3 embedded)")
+    POWERPC_DEF("750l_v3.2",     CPU_POWERPC_750L_v32,               750,
+                "PowerPC 750L v3.2 (G3 embedded)")
+    POWERPC_DEF("745_v1.0",      CPU_POWERPC_7x5_v10,                745,
+                "PowerPC 745 v1.0")
+    POWERPC_DEF("755_v1.0",      CPU_POWERPC_7x5_v10,                755,
+                "PowerPC 755 v1.0")
+    POWERPC_DEF("745_v1.1",      CPU_POWERPC_7x5_v11,                745,
+                "PowerPC 745 v1.1")
+    POWERPC_DEF("755_v1.1",      CPU_POWERPC_7x5_v11,                755,
+                "PowerPC 755 v1.1")
+    POWERPC_DEF("745_v2.0",      CPU_POWERPC_7x5_v20,                745,
+                "PowerPC 745 v2.0")
+    POWERPC_DEF("755_v2.0",      CPU_POWERPC_7x5_v20,                755,
+                "PowerPC 755 v2.0")
+    POWERPC_DEF("745_v2.1",      CPU_POWERPC_7x5_v21,                745,
+                "PowerPC 745 v2.1")
+    POWERPC_DEF("755_v2.1",      CPU_POWERPC_7x5_v21,                755,
+                "PowerPC 755 v2.1")
+    POWERPC_DEF("745_v2.2",      CPU_POWERPC_7x5_v22,                745,
+                "PowerPC 745 v2.2")
+    POWERPC_DEF("755_v2.2",      CPU_POWERPC_7x5_v22,                755,
+                "PowerPC 755 v2.2")
+    POWERPC_DEF("745_v2.3",      CPU_POWERPC_7x5_v23,                745,
+                "PowerPC 745 v2.3")
+    POWERPC_DEF("755_v2.3",      CPU_POWERPC_7x5_v23,                755,
+                "PowerPC 755 v2.3")
+    POWERPC_DEF("745_v2.4",      CPU_POWERPC_7x5_v24,                745,
+                "PowerPC 745 v2.4")
+    POWERPC_DEF("755_v2.4",      CPU_POWERPC_7x5_v24,                755,
+                "PowerPC 755 v2.4")
+    POWERPC_DEF("745_v2.5",      CPU_POWERPC_7x5_v25,                745,
+                "PowerPC 745 v2.5")
+    POWERPC_DEF("755_v2.5",      CPU_POWERPC_7x5_v25,                755,
+                "PowerPC 755 v2.5")
+    POWERPC_DEF("745_v2.6",      CPU_POWERPC_7x5_v26,                745,
+                "PowerPC 745 v2.6")
+    POWERPC_DEF("755_v2.6",      CPU_POWERPC_7x5_v26,                755,
+                "PowerPC 755 v2.6")
+    POWERPC_DEF("745_v2.7",      CPU_POWERPC_7x5_v27,                745,
+                "PowerPC 745 v2.7")
+    POWERPC_DEF("755_v2.7",      CPU_POWERPC_7x5_v27,                755,
+                "PowerPC 755 v2.7")
+    POWERPC_DEF("745_v2.8",      CPU_POWERPC_7x5_v28,                745,
+                "PowerPC 745 v2.8")
+    POWERPC_DEF("755_v2.8",      CPU_POWERPC_7x5_v28,                755,
+                "PowerPC 755 v2.8")
+#if defined(TODO)
+    POWERPC_DEF("745p",          CPU_POWERPC_7x5P,                   745,
+                "PowerPC 745P (G3)")
+    POWERPC_DEF("755p",          CPU_POWERPC_7x5P,                   755,
+                "PowerPC 755P (G3)")
+#endif
+    /* PowerPC 74xx family                                                   */
+    POWERPC_DEF("7400_v1.0",     CPU_POWERPC_7400_v10,               7400,
+                "PowerPC 7400 v1.0 (G4)")
+    POWERPC_DEF("7400_v1.1",     CPU_POWERPC_7400_v11,               7400,
+                "PowerPC 7400 v1.1 (G4)")
+    POWERPC_DEF("7400_v2.0",     CPU_POWERPC_7400_v20,               7400,
+                "PowerPC 7400 v2.0 (G4)")
+    POWERPC_DEF("7400_v2.1",     CPU_POWERPC_7400_v21,               7400,
+                "PowerPC 7400 v2.1 (G4)")
+    POWERPC_DEF("7400_v2.2",     CPU_POWERPC_7400_v22,               7400,
+                "PowerPC 7400 v2.2 (G4)")
+    POWERPC_DEF("7400_v2.6",     CPU_POWERPC_7400_v26,               7400,
+                "PowerPC 7400 v2.6 (G4)")
+    POWERPC_DEF("7400_v2.7",     CPU_POWERPC_7400_v27,               7400,
+                "PowerPC 7400 v2.7 (G4)")
+    POWERPC_DEF("7400_v2.8",     CPU_POWERPC_7400_v28,               7400,
+                "PowerPC 7400 v2.8 (G4)")
+    POWERPC_DEF("7400_v2.9",     CPU_POWERPC_7400_v29,               7400,
+                "PowerPC 7400 v2.9 (G4)")
+    POWERPC_DEF("7410_v1.0",     CPU_POWERPC_7410_v10,               7410,
+                "PowerPC 7410 v1.0 (G4)")
+    POWERPC_DEF("7410_v1.1",     CPU_POWERPC_7410_v11,               7410,
+                "PowerPC 7410 v1.1 (G4)")
+    POWERPC_DEF("7410_v1.2",     CPU_POWERPC_7410_v12,               7410,
+                "PowerPC 7410 v1.2 (G4)")
+    POWERPC_DEF("7410_v1.3",     CPU_POWERPC_7410_v13,               7410,
+                "PowerPC 7410 v1.3 (G4)")
+    POWERPC_DEF("7410_v1.4",     CPU_POWERPC_7410_v14,               7410,
+                "PowerPC 7410 v1.4 (G4)")
+    POWERPC_DEF("7448_v1.0",     CPU_POWERPC_7448_v10,               7400,
+                "PowerPC 7448 v1.0 (G4)")
+    POWERPC_DEF("7448_v1.1",     CPU_POWERPC_7448_v11,               7400,
+                "PowerPC 7448 v1.1 (G4)")
+    POWERPC_DEF("7448_v2.0",     CPU_POWERPC_7448_v20,               7400,
+                "PowerPC 7448 v2.0 (G4)")
+    POWERPC_DEF("7448_v2.1",     CPU_POWERPC_7448_v21,               7400,
+                "PowerPC 7448 v2.1 (G4)")
+    POWERPC_DEF("7450_v1.0",     CPU_POWERPC_7450_v10,               7450,
+                "PowerPC 7450 v1.0 (G4)")
+    POWERPC_DEF("7450_v1.1",     CPU_POWERPC_7450_v11,               7450,
+                "PowerPC 7450 v1.1 (G4)")
+    POWERPC_DEF("7450_v1.2",     CPU_POWERPC_7450_v12,               7450,
+                "PowerPC 7450 v1.2 (G4)")
+    POWERPC_DEF("7450_v2.0",     CPU_POWERPC_7450_v20,               7450,
+                "PowerPC 7450 v2.0 (G4)")
+    POWERPC_DEF("7450_v2.1",     CPU_POWERPC_7450_v21,               7450,
+                "PowerPC 7450 v2.1 (G4)")
+    POWERPC_DEF("7441_v2.1",     CPU_POWERPC_7450_v21,               7440,
+                "PowerPC 7441 v2.1 (G4)")
+    POWERPC_DEF("7441_v2.3",     CPU_POWERPC_74x1_v23,               7440,
+                "PowerPC 7441 v2.3 (G4)")
+    POWERPC_DEF("7451_v2.3",     CPU_POWERPC_74x1_v23,               7450,
+                "PowerPC 7451 v2.3 (G4)")
+    POWERPC_DEF("7441_v2.10",    CPU_POWERPC_74x1_v210,              7440,
+                "PowerPC 7441 v2.10 (G4)")
+    POWERPC_DEF("7451_v2.10",    CPU_POWERPC_74x1_v210,              7450,
+                "PowerPC 7451 v2.10 (G4)")
+    POWERPC_DEF("7445_v1.0",     CPU_POWERPC_74x5_v10,               7445,
+                "PowerPC 7445 v1.0 (G4)")
+    POWERPC_DEF("7455_v1.0",     CPU_POWERPC_74x5_v10,               7455,
+                "PowerPC 7455 v1.0 (G4)")
+    POWERPC_DEF("7445_v2.1",     CPU_POWERPC_74x5_v21,               7445,
+                "PowerPC 7445 v2.1 (G4)")
+    POWERPC_DEF("7455_v2.1",     CPU_POWERPC_74x5_v21,               7455,
+                "PowerPC 7455 v2.1 (G4)")
+    POWERPC_DEF("7445_v3.2",     CPU_POWERPC_74x5_v32,               7445,
+                "PowerPC 7445 v3.2 (G4)")
+    POWERPC_DEF("7455_v3.2",     CPU_POWERPC_74x5_v32,               7455,
+                "PowerPC 7455 v3.2 (G4)")
+    POWERPC_DEF("7445_v3.3",     CPU_POWERPC_74x5_v33,               7445,
+                "PowerPC 7445 v3.3 (G4)")
+    POWERPC_DEF("7455_v3.3",     CPU_POWERPC_74x5_v33,               7455,
+                "PowerPC 7455 v3.3 (G4)")
+    POWERPC_DEF("7445_v3.4",     CPU_POWERPC_74x5_v34,               7445,
+                "PowerPC 7445 v3.4 (G4)")
+    POWERPC_DEF("7455_v3.4",     CPU_POWERPC_74x5_v34,               7455,
+                "PowerPC 7455 v3.4 (G4)")
+    POWERPC_DEF("7447_v1.0",     CPU_POWERPC_74x7_v10,               7445,
+                "PowerPC 7447 v1.0 (G4)")
+    POWERPC_DEF("7457_v1.0",     CPU_POWERPC_74x7_v10,               7455,
+                "PowerPC 7457 v1.0 (G4)")
+    POWERPC_DEF("7447_v1.1",     CPU_POWERPC_74x7_v11,               7445,
+                "PowerPC 7447 v1.1 (G4)")
+    POWERPC_DEF("7457_v1.1",     CPU_POWERPC_74x7_v11,               7455,
+                "PowerPC 7457 v1.1 (G4)")
+    POWERPC_DEF("7457_v1.2",     CPU_POWERPC_74x7_v12,               7455,
+                "PowerPC 7457 v1.2 (G4)")
+    POWERPC_DEF("7447A_v1.0",    CPU_POWERPC_74x7A_v10,              7445,
+                "PowerPC 7447A v1.0 (G4)")
+    POWERPC_DEF("7457A_v1.0",    CPU_POWERPC_74x7A_v10,              7455,
+                "PowerPC 7457A v1.0 (G4)")
+    POWERPC_DEF("7447A_v1.1",    CPU_POWERPC_74x7A_v11,              7445,
+                "PowerPC 7447A v1.1 (G4)")
+    POWERPC_DEF("7457A_v1.1",    CPU_POWERPC_74x7A_v11,              7455,
+                "PowerPC 7457A v1.1 (G4)")
+    POWERPC_DEF("7447A_v1.2",    CPU_POWERPC_74x7A_v12,              7445,
+                "PowerPC 7447A v1.2 (G4)")
+    POWERPC_DEF("7457A_v1.2",    CPU_POWERPC_74x7A_v12,              7455,
+                "PowerPC 7457A v1.2 (G4)")
+    /* 64 bits PowerPC                                                       */
+#if defined (TARGET_PPC64)
+    POWERPC_DEF("620",           CPU_POWERPC_620,                    620,
+                "PowerPC 620")
+#if defined(TODO)
+    POWERPC_DEF("630",           CPU_POWERPC_630,                    630,
+                "PowerPC 630 (POWER3)")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("631",           CPU_POWERPC_631,                    631,
+                "PowerPC 631 (Power 3+)")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("POWER4",        CPU_POWERPC_POWER4,                 POWER4,
+                "POWER4")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("POWER4+",       CPU_POWERPC_POWER4P,                POWER4P,
+                "POWER4p")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("POWER5",        CPU_POWERPC_POWER5,                 POWER5,
+                "POWER5")
+    POWERPC_DEF("POWER5gr",      CPU_POWERPC_POWER5GR,               POWER5,
+                "POWER5GR")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("POWER5+",       CPU_POWERPC_POWER5P,                POWER5P,
+                "POWER5+")
+    POWERPC_DEF("POWER5gs",      CPU_POWERPC_POWER5GS,               POWER5P,
+                "POWER5GS")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("POWER6",        CPU_POWERPC_POWER6,                 POWER6,
+                "POWER6")
+    POWERPC_DEF("POWER6_5",      CPU_POWERPC_POWER6_5,               POWER5,
+                "POWER6 running in POWER5 mode")
+    POWERPC_DEF("POWER6A",       CPU_POWERPC_POWER6A,                POWER6,
+                "POWER6A")
+#endif
+    POWERPC_DEF("POWER7_v2.0",   CPU_POWERPC_POWER7_v20,             POWER7,
+                "POWER7 v2.0")
+    POWERPC_DEF("POWER7_v2.1",   CPU_POWERPC_POWER7_v21,             POWER7,
+                "POWER7 v2.1")
+    POWERPC_DEF("POWER7_v2.3",   CPU_POWERPC_POWER7_v23,             POWER7,
+                "POWER7 v2.3")
+    POWERPC_DEF("970",           CPU_POWERPC_970,                    970,
+                "PowerPC 970")
+    POWERPC_DEF("970fx_v1.0",    CPU_POWERPC_970FX_v10,              970FX,
+                "PowerPC 970FX v1.0 (G5)")
+    POWERPC_DEF("970fx_v2.0",    CPU_POWERPC_970FX_v20,              970FX,
+                "PowerPC 970FX v2.0 (G5)")
+    POWERPC_DEF("970fx_v2.1",    CPU_POWERPC_970FX_v21,              970FX,
+                "PowerPC 970FX v2.1 (G5)")
+    POWERPC_DEF("970fx_v3.0",    CPU_POWERPC_970FX_v30,              970FX,
+                "PowerPC 970FX v3.0 (G5)")
+    POWERPC_DEF("970fx_v3.1",    CPU_POWERPC_970FX_v31,              970FX,
+                "PowerPC 970FX v3.1 (G5)")
+    POWERPC_DEF("970gx",         CPU_POWERPC_970GX,                  970GX,
+                "PowerPC 970GX (G5)")
+    POWERPC_DEF("970mp_v1.0",    CPU_POWERPC_970MP_v10,              970MP,
+                "PowerPC 970MP v1.0")
+    POWERPC_DEF("970mp_v1.1",    CPU_POWERPC_970MP_v11,              970MP,
+                "PowerPC 970MP v1.1")
+#if defined(TODO)
+    POWERPC_DEF("Cell",          CPU_POWERPC_CELL,                   970,
+                "PowerPC Cell")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("Cell_v1.0",     CPU_POWERPC_CELL_v10,               970,
+                "PowerPC Cell v1.0")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("Cell_v2.0",     CPU_POWERPC_CELL_v20,               970,
+                "PowerPC Cell v2.0")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("Cell_v3.0",     CPU_POWERPC_CELL_v30,               970,
+                "PowerPC Cell v3.0")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("Cell_v3.1",     CPU_POWERPC_CELL_v31,               970,
+                "PowerPC Cell v3.1")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("Cell_v3.2",     CPU_POWERPC_CELL_v32,               970,
+                "PowerPC Cell v3.2")
+#endif
+#if defined(TODO)
+    /* This one seems to support the whole POWER2 instruction set
+     * and the PowerPC 64 one.
+     */
+    /* What about A10 & A30 ? */
+    POWERPC_DEF("RS64",          CPU_POWERPC_RS64,                   RS64,
+                "RS64 (Apache/A35)")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("RS64-II",       CPU_POWERPC_RS64II,                 RS64,
+                "RS64-II (NorthStar/A50)")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("RS64-III",      CPU_POWERPC_RS64III,                RS64,
+                "RS64-III (Pulsar)")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("RS64-IV",       CPU_POWERPC_RS64IV,                 RS64,
+                "RS64-IV (IceStar/IStar/SStar)")
+#endif
+#endif /* defined (TARGET_PPC64) */
+    /* POWER                                                                 */
+#if defined(TODO)
+    POWERPC_DEF("POWER",         CPU_POWERPC_POWER,                  POWER,
+                "Original POWER")
+#endif
+#if defined(TODO)
+    POWERPC_DEF("POWER2",        CPU_POWERPC_POWER2,                 POWER,
+                "POWER2")
+#endif
+    /* PA semi cores                                                         */
+#if defined(TODO)
+    POWERPC_DEF("PA6T",          CPU_POWERPC_PA6T,                   PA6T,
+                "PA PA6T")
+#endif
+
diff --git a/target-ppc/cpu-models.h b/target-ppc/cpu-models.h
new file mode 100644
index 0000000..edff0f4
--- /dev/null
+++ b/target-ppc/cpu-models.h
@@ -0,0 +1,727 @@
+/*
+ *  PowerPC CPU initialization for qemu.
+ *
+ *  Copyright (c) 2003-2007 Jocelyn Mayer
+ *  Copyright 2011 Freescale Semiconductor, Inc.
+ *  Copyright 2013 SUSE LINUX Products GmbH
+ *
+ * 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 TARGET_PPC_CPU_MODELS_H
+#define TARGET_PPC_CPU_MODELS_H
+
+/*****************************************************************************/
+/* PVR definitions for most known PowerPC                                    */
+enum {
+    /* PowerPC 401 family */
+    /* Generic PowerPC 401 */
+#define CPU_POWERPC_401              CPU_POWERPC_401G2
+    /* PowerPC 401 cores */
+    CPU_POWERPC_401A1              = 0x00210000,
+    CPU_POWERPC_401B2              = 0x00220000,
+#if 0
+    CPU_POWERPC_401B3              = xxx,
+#endif
+    CPU_POWERPC_401C2              = 0x00230000,
+    CPU_POWERPC_401D2              = 0x00240000,
+    CPU_POWERPC_401E2              = 0x00250000,
+    CPU_POWERPC_401F2              = 0x00260000,
+    CPU_POWERPC_401G2              = 0x00270000,
+    /* PowerPC 401 microcontrolers */
+#if 0
+    CPU_POWERPC_401GF              = xxx,
+#endif
+#define CPU_POWERPC_IOP480           CPU_POWERPC_401B2
+    /* IBM Processor for Network Resources */
+    CPU_POWERPC_COBRA              = 0x10100000, /* XXX: 405 ? */
+#if 0
+    CPU_POWERPC_XIPCHIP            = xxx,
+#endif
+    /* PowerPC 403 family */
+    /* PowerPC 403 microcontrollers */
+    CPU_POWERPC_403GA              = 0x00200011,
+    CPU_POWERPC_403GB              = 0x00200100,
+    CPU_POWERPC_403GC              = 0x00200200,
+    CPU_POWERPC_403GCX             = 0x00201400,
+#if 0
+    CPU_POWERPC_403GP              = xxx,
+#endif
+    /* PowerPC 405 family */
+    /* PowerPC 405 cores */
+#if 0
+    CPU_POWERPC_405A3              = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405A4              = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405B3              = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405B4              = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405C3              = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405C4              = xxx,
+#endif
+    CPU_POWERPC_405D2              = 0x20010000,
+#if 0
+    CPU_POWERPC_405D3              = xxx,
+#endif
+    CPU_POWERPC_405D4              = 0x41810000,
+#if 0
+    CPU_POWERPC_405D5              = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405E4              = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405F4              = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405F5              = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405F6              = xxx,
+#endif
+    /* PowerPC 405 microcontrolers */
+    /* XXX: missing 0x200108a0 */
+    CPU_POWERPC_405CRa             = 0x40110041,
+    CPU_POWERPC_405CRb             = 0x401100C5,
+    CPU_POWERPC_405CRc             = 0x40110145,
+    CPU_POWERPC_405EP              = 0x51210950,
+#if 0
+    CPU_POWERPC_405EXr             = xxx,
+#endif
+    CPU_POWERPC_405EZ              = 0x41511460, /* 0x51210950 ? */
+#if 0
+    CPU_POWERPC_405FX              = xxx,
+#endif
+    CPU_POWERPC_405GPa             = 0x40110000,
+    CPU_POWERPC_405GPb             = 0x40110040,
+    CPU_POWERPC_405GPc             = 0x40110082,
+    CPU_POWERPC_405GPd             = 0x401100C4,
+    CPU_POWERPC_405GPR             = 0x50910951,
+#if 0
+    CPU_POWERPC_405H               = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405L               = xxx,
+#endif
+    CPU_POWERPC_405LP              = 0x41F10000,
+#if 0
+    CPU_POWERPC_405PM              = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405PS              = xxx,
+#endif
+#if 0
+    CPU_POWERPC_405S               = xxx,
+#endif
+    /* IBM network processors */
+    CPU_POWERPC_NPE405H            = 0x414100C0,
+    CPU_POWERPC_NPE405H2           = 0x41410140,
+    CPU_POWERPC_NPE405L            = 0x416100C0,
+    CPU_POWERPC_NPE4GS3            = 0x40B10000,
+#if 0
+    CPU_POWERPC_NPCxx1             = xxx,
+#endif
+#if 0
+    CPU_POWERPC_NPR161             = xxx,
+#endif
+#if 0
+    CPU_POWERPC_LC77700            = xxx,
+#endif
+    /* IBM STBxxx (PowerPC 401/403/405 core based microcontrollers) */
+#if 0
+    CPU_POWERPC_STB01000           = xxx,
+#endif
+#if 0
+    CPU_POWERPC_STB01010           = xxx,
+#endif
+#if 0
+    CPU_POWERPC_STB0210            = xxx, /* 401B3 */
+#endif
+    CPU_POWERPC_STB03              = 0x40310000, /* 0x40130000 ? */
+#if 0
+    CPU_POWERPC_STB043             = xxx,
+#endif
+#if 0
+    CPU_POWERPC_STB045             = xxx,
+#endif
+    CPU_POWERPC_STB04              = 0x41810000,
+    CPU_POWERPC_STB25              = 0x51510950,
+#if 0
+    CPU_POWERPC_STB130             = xxx,
+#endif
+    /* Xilinx cores */
+    CPU_POWERPC_X2VP4              = 0x20010820,
+    CPU_POWERPC_X2VP20             = 0x20010860,
+#if 0
+    CPU_POWERPC_ZL10310            = xxx,
+#endif
+#if 0
+    CPU_POWERPC_ZL10311            = xxx,
+#endif
+#if 0
+    CPU_POWERPC_ZL10320            = xxx,
+#endif
+#if 0
+    CPU_POWERPC_ZL10321            = xxx,
+#endif
+    /* PowerPC 440 family */
+    /* Generic PowerPC 440 */
+#define CPU_POWERPC_440              CPU_POWERPC_440GXf
+    /* PowerPC 440 cores */
+#if 0
+    CPU_POWERPC_440A4              = xxx,
+#endif
+    CPU_POWERPC_440_XILINX         = 0x7ff21910,
+#if 0
+    CPU_POWERPC_440A5              = xxx,
+#endif
+#if 0
+    CPU_POWERPC_440B4              = xxx,
+#endif
+#if 0
+    CPU_POWERPC_440F5              = xxx,
+#endif
+#if 0
+    CPU_POWERPC_440G5              = xxx,
+#endif
+#if 0
+    CPU_POWERPC_440H4              = xxx,
+#endif
+#if 0
+    CPU_POWERPC_440H6              = xxx,
+#endif
+    /* PowerPC 440 microcontrolers */
+    CPU_POWERPC_440EPa             = 0x42221850,
+    CPU_POWERPC_440EPb             = 0x422218D3,
+    CPU_POWERPC_440GPb             = 0x40120440,
+    CPU_POWERPC_440GPc             = 0x40120481,
+#define CPU_POWERPC_440GRa           CPU_POWERPC_440EPb
+    CPU_POWERPC_440GRX             = 0x200008D0,
+#define CPU_POWERPC_440EPX           CPU_POWERPC_440GRX
+    CPU_POWERPC_440GXa             = 0x51B21850,
+    CPU_POWERPC_440GXb             = 0x51B21851,
+    CPU_POWERPC_440GXc             = 0x51B21892,
+    CPU_POWERPC_440GXf             = 0x51B21894,
+#if 0
+    CPU_POWERPC_440S               = xxx,
+#endif
+    CPU_POWERPC_440SP              = 0x53221850,
+    CPU_POWERPC_440SP2             = 0x53221891,
+    CPU_POWERPC_440SPE             = 0x53421890,
+    /* PowerPC 460 family */
+#if 0
+    /* Generic PowerPC 464 */
+#define CPU_POWERPC_464              CPU_POWERPC_464H90
+#endif
+    /* PowerPC 464 microcontrolers */
+#if 0
+    CPU_POWERPC_464H90             = xxx,
+#endif
+#if 0
+    CPU_POWERPC_464H90FP           = xxx,
+#endif
+    /* Freescale embedded PowerPC cores */
+    /* PowerPC MPC 5xx cores (aka RCPU) */
+    CPU_POWERPC_MPC5xx             = 0x00020020,
+    /* PowerPC MPC 8xx cores (aka PowerQUICC) */
+    CPU_POWERPC_MPC8xx             = 0x00500000,
+    /* G2 cores (aka PowerQUICC-II) */
+    CPU_POWERPC_G2                 = 0x00810011,
+    CPU_POWERPC_G2H4               = 0x80811010,
+    CPU_POWERPC_G2gp               = 0x80821010,
+    CPU_POWERPC_G2ls               = 0x90810010,
+    CPU_POWERPC_MPC603             = 0x00810100,
+    CPU_POWERPC_G2_HIP3            = 0x00810101,
+    CPU_POWERPC_G2_HIP4            = 0x80811014,
+    /*   G2_LE core (aka PowerQUICC-II) */
+    CPU_POWERPC_G2LE               = 0x80820010,
+    CPU_POWERPC_G2LEgp             = 0x80822010,
+    CPU_POWERPC_G2LEls             = 0xA0822010,
+    CPU_POWERPC_G2LEgp1            = 0x80822011,
+    CPU_POWERPC_G2LEgp3            = 0x80822013,
+    /* MPC52xx microcontrollers  */
+    /* XXX: MPC 5121 ? */
+#define CPU_POWERPC_MPC5200_v10      CPU_POWERPC_G2LEgp1
+#define CPU_POWERPC_MPC5200_v11      CPU_POWERPC_G2LEgp1
+#define CPU_POWERPC_MPC5200_v12      CPU_POWERPC_G2LEgp1
+#define CPU_POWERPC_MPC5200B_v20     CPU_POWERPC_G2LEgp1
+#define CPU_POWERPC_MPC5200B_v21     CPU_POWERPC_G2LEgp1
+    /* e200 family */
+    /* e200 cores */
+#if 0
+    CPU_POWERPC_e200z0             = xxx,
+#endif
+#if 0
+    CPU_POWERPC_e200z1             = xxx,
+#endif
+#if 0 /* ? */
+    CPU_POWERPC_e200z3             = 0x81120000,
+#endif
+    CPU_POWERPC_e200z5             = 0x81000000,
+    CPU_POWERPC_e200z6             = 0x81120000,
+    /* MPC55xx microcontrollers */
+#define CPU_POWERPC_MPC55xx          CPU_POWERPC_MPC5567
+#if 0
+#define CPU_POWERPC_MPC5514E         CPU_POWERPC_MPC5514E_v1
+#define CPU_POWERPC_MPC5514E_v0      CPU_POWERPC_e200z0
+#define CPU_POWERPC_MPC5514E_v1      CPU_POWERPC_e200z1
+#define CPU_POWERPC_MPC5514G         CPU_POWERPC_MPC5514G_v1
+#define CPU_POWERPC_MPC5514G_v0      CPU_POWERPC_e200z0
+#define CPU_POWERPC_MPC5514G_v1      CPU_POWERPC_e200z1
+#define CPU_POWERPC_MPC5515S         CPU_POWERPC_e200z1
+#define CPU_POWERPC_MPC5516E         CPU_POWERPC_MPC5516E_v1
+#define CPU_POWERPC_MPC5516E_v0      CPU_POWERPC_e200z0
+#define CPU_POWERPC_MPC5516E_v1      CPU_POWERPC_e200z1
+#define CPU_POWERPC_MPC5516G         CPU_POWERPC_MPC5516G_v1
+#define CPU_POWERPC_MPC5516G_v0      CPU_POWERPC_e200z0
+#define CPU_POWERPC_MPC5516G_v1      CPU_POWERPC_e200z1
+#define CPU_POWERPC_MPC5516S         CPU_POWERPC_e200z1
+#endif
+#if 0
+#define CPU_POWERPC_MPC5533          CPU_POWERPC_e200z3
+#define CPU_POWERPC_MPC5534          CPU_POWERPC_e200z3
+#endif
+#define CPU_POWERPC_MPC5553          CPU_POWERPC_e200z6
+#define CPU_POWERPC_MPC5554          CPU_POWERPC_e200z6
+#define CPU_POWERPC_MPC5561          CPU_POWERPC_e200z6
+#define CPU_POWERPC_MPC5565          CPU_POWERPC_e200z6
+#define CPU_POWERPC_MPC5566          CPU_POWERPC_e200z6
+#define CPU_POWERPC_MPC5567          CPU_POWERPC_e200z6
+    /* e300 family */
+    /* e300 cores */
+    CPU_POWERPC_e300c1             = 0x00830010,
+    CPU_POWERPC_e300c2             = 0x00840010,
+    CPU_POWERPC_e300c3             = 0x00850010,
+    CPU_POWERPC_e300c4             = 0x00860010,
+    /* MPC83xx microcontrollers */
+#define CPU_POWERPC_MPC831x          CPU_POWERPC_e300c3
+#define CPU_POWERPC_MPC832x          CPU_POWERPC_e300c2
+#define CPU_POWERPC_MPC834x          CPU_POWERPC_e300c1
+#define CPU_POWERPC_MPC835x          CPU_POWERPC_e300c1
+#define CPU_POWERPC_MPC836x          CPU_POWERPC_e300c1
+#define CPU_POWERPC_MPC837x          CPU_POWERPC_e300c4
+    /* e500 family */
+    /* e500 cores  */
+#define CPU_POWERPC_e500             CPU_POWERPC_e500v2_v22
+    CPU_POWERPC_e500v1_v10         = 0x80200010,
+    CPU_POWERPC_e500v1_v20         = 0x80200020,
+    CPU_POWERPC_e500v2_v10         = 0x80210010,
+    CPU_POWERPC_e500v2_v11         = 0x80210011,
+    CPU_POWERPC_e500v2_v20         = 0x80210020,
+    CPU_POWERPC_e500v2_v21         = 0x80210021,
+    CPU_POWERPC_e500v2_v22         = 0x80210022,
+    CPU_POWERPC_e500v2_v30         = 0x80210030,
+    CPU_POWERPC_e500mc             = 0x80230020,
+    CPU_POWERPC_e5500              = 0x80240020,
+    /* MPC85xx microcontrollers */
+#define CPU_POWERPC_MPC8533_v10      CPU_POWERPC_e500v2_v21
+#define CPU_POWERPC_MPC8533_v11      CPU_POWERPC_e500v2_v22
+#define CPU_POWERPC_MPC8533E_v10     CPU_POWERPC_e500v2_v21
+#define CPU_POWERPC_MPC8533E_v11     CPU_POWERPC_e500v2_v22
+#define CPU_POWERPC_MPC8540_v10      CPU_POWERPC_e500v1_v10
+#define CPU_POWERPC_MPC8540_v20      CPU_POWERPC_e500v1_v20
+#define CPU_POWERPC_MPC8540_v21      CPU_POWERPC_e500v1_v20
+#define CPU_POWERPC_MPC8541_v10      CPU_POWERPC_e500v1_v20
+#define CPU_POWERPC_MPC8541_v11      CPU_POWERPC_e500v1_v20
+#define CPU_POWERPC_MPC8541E_v10     CPU_POWERPC_e500v1_v20
+#define CPU_POWERPC_MPC8541E_v11     CPU_POWERPC_e500v1_v20
+#define CPU_POWERPC_MPC8543_v10      CPU_POWERPC_e500v2_v10
+#define CPU_POWERPC_MPC8543_v11      CPU_POWERPC_e500v2_v11
+#define CPU_POWERPC_MPC8543_v20      CPU_POWERPC_e500v2_v20
+#define CPU_POWERPC_MPC8543_v21      CPU_POWERPC_e500v2_v21
+#define CPU_POWERPC_MPC8543E_v10     CPU_POWERPC_e500v2_v10
+#define CPU_POWERPC_MPC8543E_v11     CPU_POWERPC_e500v2_v11
+#define CPU_POWERPC_MPC8543E_v20     CPU_POWERPC_e500v2_v20
+#define CPU_POWERPC_MPC8543E_v21     CPU_POWERPC_e500v2_v21
+#define CPU_POWERPC_MPC8544_v10      CPU_POWERPC_e500v2_v21
+#define CPU_POWERPC_MPC8544_v11      CPU_POWERPC_e500v2_v22
+#define CPU_POWERPC_MPC8544E_v11     CPU_POWERPC_e500v2_v22
+#define CPU_POWERPC_MPC8544E_v10     CPU_POWERPC_e500v2_v21
+#define CPU_POWERPC_MPC8545_v10      CPU_POWERPC_e500v2_v10
+#define CPU_POWERPC_MPC8545_v20      CPU_POWERPC_e500v2_v20
+#define CPU_POWERPC_MPC8545_v21      CPU_POWERPC_e500v2_v21
+#define CPU_POWERPC_MPC8545E_v10     CPU_POWERPC_e500v2_v10
+#define CPU_POWERPC_MPC8545E_v20     CPU_POWERPC_e500v2_v20
+#define CPU_POWERPC_MPC8545E_v21     CPU_POWERPC_e500v2_v21
+#define CPU_POWERPC_MPC8547E_v10     CPU_POWERPC_e500v2_v10
+#define CPU_POWERPC_MPC8547E_v20     CPU_POWERPC_e500v2_v20
+#define CPU_POWERPC_MPC8547E_v21     CPU_POWERPC_e500v2_v21
+#define CPU_POWERPC_MPC8548_v10      CPU_POWERPC_e500v2_v10
+#define CPU_POWERPC_MPC8548_v11      CPU_POWERPC_e500v2_v11
+#define CPU_POWERPC_MPC8548_v20      CPU_POWERPC_e500v2_v20
+#define CPU_POWERPC_MPC8548_v21      CPU_POWERPC_e500v2_v21
+#define CPU_POWERPC_MPC8548E_v10     CPU_POWERPC_e500v2_v10
+#define CPU_POWERPC_MPC8548E_v11     CPU_POWERPC_e500v2_v11
+#define CPU_POWERPC_MPC8548E_v20     CPU_POWERPC_e500v2_v20
+#define CPU_POWERPC_MPC8548E_v21     CPU_POWERPC_e500v2_v21
+#define CPU_POWERPC_MPC8555_v10      CPU_POWERPC_e500v2_v10
+#define CPU_POWERPC_MPC8555_v11      CPU_POWERPC_e500v2_v11
+#define CPU_POWERPC_MPC8555E_v10     CPU_POWERPC_e500v2_v10
+#define CPU_POWERPC_MPC8555E_v11     CPU_POWERPC_e500v2_v11
+#define CPU_POWERPC_MPC8560_v10      CPU_POWERPC_e500v2_v10
+#define CPU_POWERPC_MPC8560_v20      CPU_POWERPC_e500v2_v20
+#define CPU_POWERPC_MPC8560_v21      CPU_POWERPC_e500v2_v21
+#define CPU_POWERPC_MPC8567          CPU_POWERPC_e500v2_v22
+#define CPU_POWERPC_MPC8567E         CPU_POWERPC_e500v2_v22
+#define CPU_POWERPC_MPC8568          CPU_POWERPC_e500v2_v22
+#define CPU_POWERPC_MPC8568E         CPU_POWERPC_e500v2_v22
+#define CPU_POWERPC_MPC8572          CPU_POWERPC_e500v2_v30
+#define CPU_POWERPC_MPC8572E         CPU_POWERPC_e500v2_v30
+    /* e600 family */
+    /* e600 cores */
+    CPU_POWERPC_e600               = 0x80040010,
+    /* MPC86xx microcontrollers */
+#define CPU_POWERPC_MPC8610          CPU_POWERPC_e600
+#define CPU_POWERPC_MPC8641          CPU_POWERPC_e600
+#define CPU_POWERPC_MPC8641D         CPU_POWERPC_e600
+    /* PowerPC 6xx cores */
+    CPU_POWERPC_601_v0             = 0x00010001,
+    CPU_POWERPC_601_v1             = 0x00010001,
+    CPU_POWERPC_601_v2             = 0x00010002,
+    CPU_POWERPC_602                = 0x00050100,
+    CPU_POWERPC_603                = 0x00030100,
+    CPU_POWERPC_603E_v11           = 0x00060101,
+    CPU_POWERPC_603E_v12           = 0x00060102,
+    CPU_POWERPC_603E_v13           = 0x00060103,
+    CPU_POWERPC_603E_v14           = 0x00060104,
+    CPU_POWERPC_603E_v22           = 0x00060202,
+    CPU_POWERPC_603E_v3            = 0x00060300,
+    CPU_POWERPC_603E_v4            = 0x00060400,
+    CPU_POWERPC_603E_v41           = 0x00060401,
+    CPU_POWERPC_603E7t             = 0x00071201,
+    CPU_POWERPC_603E7v             = 0x00070100,
+    CPU_POWERPC_603E7v1            = 0x00070101,
+    CPU_POWERPC_603E7v2            = 0x00070201,
+    CPU_POWERPC_603E7              = 0x00070200,
+    CPU_POWERPC_603P               = 0x00070000,
+    /* XXX: missing 0x00040303 (604) */
+    CPU_POWERPC_604                = 0x00040103,
+    /* XXX: missing 0x00091203 */
+    /* XXX: missing 0x00092110 */
+    /* XXX: missing 0x00092120 */
+    CPU_POWERPC_604E_v10           = 0x00090100,
+    CPU_POWERPC_604E_v22           = 0x00090202,
+    CPU_POWERPC_604E_v24           = 0x00090204,
+    /* XXX: missing 0x000a0100 */
+    /* XXX: missing 0x00093102 */
+    CPU_POWERPC_604R               = 0x000a0101,
+#if 0
+    CPU_POWERPC_604EV              = xxx, /* XXX: same as 604R ? */
+#endif
+    /* PowerPC 740/750 cores (aka G3) */
+    /* XXX: missing 0x00084202 */
+    CPU_POWERPC_7x0_v10            = 0x00080100,
+    CPU_POWERPC_7x0_v20            = 0x00080200,
+    CPU_POWERPC_7x0_v21            = 0x00080201,
+    CPU_POWERPC_7x0_v22            = 0x00080202,
+    CPU_POWERPC_7x0_v30            = 0x00080300,
+    CPU_POWERPC_7x0_v31            = 0x00080301,
+    CPU_POWERPC_740E               = 0x00080100,
+    CPU_POWERPC_750E               = 0x00080200,
+    CPU_POWERPC_7x0P               = 0x10080000,
+    /* XXX: missing 0x00087010 (CL ?) */
+    CPU_POWERPC_750CL_v10          = 0x00087200,
+    CPU_POWERPC_750CL_v20          = 0x00087210, /* aka rev E */
+    CPU_POWERPC_750CX_v10          = 0x00082100,
+    CPU_POWERPC_750CX_v20          = 0x00082200,
+    CPU_POWERPC_750CX_v21          = 0x00082201,
+    CPU_POWERPC_750CX_v22          = 0x00082202,
+    CPU_POWERPC_750CXE_v21         = 0x00082211,
+    CPU_POWERPC_750CXE_v22         = 0x00082212,
+    CPU_POWERPC_750CXE_v23         = 0x00082213,
+    CPU_POWERPC_750CXE_v24         = 0x00082214,
+    CPU_POWERPC_750CXE_v24b        = 0x00083214,
+    CPU_POWERPC_750CXE_v30         = 0x00082310,
+    CPU_POWERPC_750CXE_v31         = 0x00082311,
+    CPU_POWERPC_750CXE_v31b        = 0x00083311,
+    CPU_POWERPC_750CXR             = 0x00083410,
+    CPU_POWERPC_750FL              = 0x70000203,
+    CPU_POWERPC_750FX_v10          = 0x70000100,
+    CPU_POWERPC_750FX_v20          = 0x70000200,
+    CPU_POWERPC_750FX_v21          = 0x70000201,
+    CPU_POWERPC_750FX_v22          = 0x70000202,
+    CPU_POWERPC_750FX_v23          = 0x70000203,
+    CPU_POWERPC_750GL              = 0x70020102,
+    CPU_POWERPC_750GX_v10          = 0x70020100,
+    CPU_POWERPC_750GX_v11          = 0x70020101,
+    CPU_POWERPC_750GX_v12          = 0x70020102,
+    CPU_POWERPC_750L_v20           = 0x00088200,
+    CPU_POWERPC_750L_v21           = 0x00088201,
+    CPU_POWERPC_750L_v22           = 0x00088202,
+    CPU_POWERPC_750L_v30           = 0x00088300,
+    CPU_POWERPC_750L_v32           = 0x00088302,
+    /* PowerPC 745/755 cores */
+    CPU_POWERPC_7x5_v10            = 0x00083100,
+    CPU_POWERPC_7x5_v11            = 0x00083101,
+    CPU_POWERPC_7x5_v20            = 0x00083200,
+    CPU_POWERPC_7x5_v21            = 0x00083201,
+    CPU_POWERPC_7x5_v22            = 0x00083202, /* aka D */
+    CPU_POWERPC_7x5_v23            = 0x00083203, /* aka E */
+    CPU_POWERPC_7x5_v24            = 0x00083204,
+    CPU_POWERPC_7x5_v25            = 0x00083205,
+    CPU_POWERPC_7x5_v26            = 0x00083206,
+    CPU_POWERPC_7x5_v27            = 0x00083207,
+    CPU_POWERPC_7x5_v28            = 0x00083208,
+#if 0
+    CPU_POWERPC_7x5P               = xxx,
+#endif
+    /* PowerPC 74xx cores (aka G4) */
+    /* XXX: missing 0x000C1101 */
+    CPU_POWERPC_7400_v10           = 0x000C0100,
+    CPU_POWERPC_7400_v11           = 0x000C0101,
+    CPU_POWERPC_7400_v20           = 0x000C0200,
+    CPU_POWERPC_7400_v21           = 0x000C0201,
+    CPU_POWERPC_7400_v22           = 0x000C0202,
+    CPU_POWERPC_7400_v26           = 0x000C0206,
+    CPU_POWERPC_7400_v27           = 0x000C0207,
+    CPU_POWERPC_7400_v28           = 0x000C0208,
+    CPU_POWERPC_7400_v29           = 0x000C0209,
+    CPU_POWERPC_7410_v10           = 0x800C1100,
+    CPU_POWERPC_7410_v11           = 0x800C1101,
+    CPU_POWERPC_7410_v12           = 0x800C1102, /* aka C */
+    CPU_POWERPC_7410_v13           = 0x800C1103, /* aka D */
+    CPU_POWERPC_7410_v14           = 0x800C1104, /* aka E */
+    CPU_POWERPC_7448_v10           = 0x80040100,
+    CPU_POWERPC_7448_v11           = 0x80040101,
+    CPU_POWERPC_7448_v20           = 0x80040200,
+    CPU_POWERPC_7448_v21           = 0x80040201,
+    CPU_POWERPC_7450_v10           = 0x80000100,
+    CPU_POWERPC_7450_v11           = 0x80000101,
+    CPU_POWERPC_7450_v12           = 0x80000102,
+    CPU_POWERPC_7450_v20           = 0x80000200, /* aka A, B, C, D: 2.04 */
+    CPU_POWERPC_7450_v21           = 0x80000201, /* aka E */
+    CPU_POWERPC_74x1_v23           = 0x80000203, /* aka G: 2.3 */
+    /* XXX: this entry might be a bug in some documentation */
+    CPU_POWERPC_74x1_v210          = 0x80000210, /* aka G: 2.3 ? */
+    CPU_POWERPC_74x5_v10           = 0x80010100,
+    /* XXX: missing 0x80010200 */
+    CPU_POWERPC_74x5_v21           = 0x80010201, /* aka C: 2.1 */
+    CPU_POWERPC_74x5_v32           = 0x80010302,
+    CPU_POWERPC_74x5_v33           = 0x80010303, /* aka F: 3.3 */
+    CPU_POWERPC_74x5_v34           = 0x80010304, /* aka G: 3.4 */
+    CPU_POWERPC_74x7_v10           = 0x80020100, /* aka A: 1.0 */
+    CPU_POWERPC_74x7_v11           = 0x80020101, /* aka B: 1.1 */
+    CPU_POWERPC_74x7_v12           = 0x80020102, /* aka C: 1.2 */
+    CPU_POWERPC_74x7A_v10          = 0x80030100, /* aka A: 1.0 */
+    CPU_POWERPC_74x7A_v11          = 0x80030101, /* aka B: 1.1 */
+    CPU_POWERPC_74x7A_v12          = 0x80030102, /* aka C: 1.2 */
+    /* 64 bits PowerPC */
+#if defined(TARGET_PPC64)
+    CPU_POWERPC_620                = 0x00140000,
+    CPU_POWERPC_630                = 0x00400000,
+    CPU_POWERPC_631                = 0x00410104,
+    CPU_POWERPC_POWER4             = 0x00350000,
+    CPU_POWERPC_POWER4P            = 0x00380000,
+     /* XXX: missing 0x003A0201 */
+    CPU_POWERPC_POWER5             = 0x003A0203,
+#define CPU_POWERPC_POWER5GR         CPU_POWERPC_POWER5
+    CPU_POWERPC_POWER5P            = 0x003B0000,
+#define CPU_POWERPC_POWER5GS         CPU_POWERPC_POWER5P
+    CPU_POWERPC_POWER6             = 0x003E0000,
+    CPU_POWERPC_POWER6_5           = 0x0F000001, /* POWER6 in POWER5 mode */
+    CPU_POWERPC_POWER6A            = 0x0F000002,
+    CPU_POWERPC_POWER7_v20         = 0x003F0200,
+    CPU_POWERPC_POWER7_v21         = 0x003F0201,
+    CPU_POWERPC_POWER7_v23         = 0x003F0203,
+    CPU_POWERPC_970                = 0x00390202,
+    CPU_POWERPC_970FX_v10          = 0x00391100,
+    CPU_POWERPC_970FX_v20          = 0x003C0200,
+    CPU_POWERPC_970FX_v21          = 0x003C0201,
+    CPU_POWERPC_970FX_v30          = 0x003C0300,
+    CPU_POWERPC_970FX_v31          = 0x003C0301,
+    CPU_POWERPC_970GX              = 0x00450000,
+    CPU_POWERPC_970MP_v10          = 0x00440100,
+    CPU_POWERPC_970MP_v11          = 0x00440101,
+#define CPU_POWERPC_CELL             CPU_POWERPC_CELL_v32
+    CPU_POWERPC_CELL_v10           = 0x00700100,
+    CPU_POWERPC_CELL_v20           = 0x00700400,
+    CPU_POWERPC_CELL_v30           = 0x00700500,
+    CPU_POWERPC_CELL_v31           = 0x00700501,
+#define CPU_POWERPC_CELL_v32         CPU_POWERPC_CELL_v31
+    CPU_POWERPC_RS64               = 0x00330000,
+    CPU_POWERPC_RS64II             = 0x00340000,
+    CPU_POWERPC_RS64III            = 0x00360000,
+    CPU_POWERPC_RS64IV             = 0x00370000,
+#endif /* defined(TARGET_PPC64) */
+    /* Original POWER */
+    /* XXX: should be POWER (RIOS), RSC3308, RSC4608,
+     * POWER2 (RIOS2) & RSC2 (P2SC) here
+     */
+#if 0
+    CPU_POWER                      = xxx, /* 0x20000 ? 0x30000 for RSC ? */
+#endif
+#if 0
+    CPU_POWER2                     = xxx, /* 0x40000 ? */
+#endif
+    /* PA Semi core */
+    CPU_POWERPC_PA6T               = 0x00900000,
+};
+
+/* System version register (used on MPC 8xxx)                                */
+enum {
+    POWERPC_SVR_NONE               = 0x00000000,
+    POWERPC_SVR_5200_v10           = 0x80110010,
+    POWERPC_SVR_5200_v11           = 0x80110011,
+    POWERPC_SVR_5200_v12           = 0x80110012,
+    POWERPC_SVR_5200B_v20          = 0x80110020,
+    POWERPC_SVR_5200B_v21          = 0x80110021,
+#define POWERPC_SVR_55xx             POWERPC_SVR_5567
+#if 0
+    POWERPC_SVR_5533               = xxx,
+#endif
+#if 0
+    POWERPC_SVR_5534               = xxx,
+#endif
+#if 0
+    POWERPC_SVR_5553               = xxx,
+#endif
+#if 0
+    POWERPC_SVR_5554               = xxx,
+#endif
+#if 0
+    POWERPC_SVR_5561               = xxx,
+#endif
+#if 0
+    POWERPC_SVR_5565               = xxx,
+#endif
+#if 0
+    POWERPC_SVR_5566               = xxx,
+#endif
+#if 0
+    POWERPC_SVR_5567               = xxx,
+#endif
+#if 0
+    POWERPC_SVR_8313               = xxx,
+#endif
+#if 0
+    POWERPC_SVR_8313E              = xxx,
+#endif
+#if 0
+    POWERPC_SVR_8314               = xxx,
+#endif
+#if 0
+    POWERPC_SVR_8314E              = xxx,
+#endif
+#if 0
+    POWERPC_SVR_8315               = xxx,
+#endif
+#if 0
+    POWERPC_SVR_8315E              = xxx,
+#endif
+#if 0
+    POWERPC_SVR_8321               = xxx,
+#endif
+#if 0
+    POWERPC_SVR_8321E              = xxx,
+#endif
+#if 0
+    POWERPC_SVR_8323               = xxx,
+#endif
+#if 0
+    POWERPC_SVR_8323E              = xxx,
+#endif
+    POWERPC_SVR_8343               = 0x80570010,
+    POWERPC_SVR_8343A              = 0x80570030,
+    POWERPC_SVR_8343E              = 0x80560010,
+    POWERPC_SVR_8343EA             = 0x80560030,
+    POWERPC_SVR_8347P              = 0x80550010, /* PBGA package */
+    POWERPC_SVR_8347T              = 0x80530010, /* TBGA package */
+    POWERPC_SVR_8347AP             = 0x80550030, /* PBGA package */
+    POWERPC_SVR_8347AT             = 0x80530030, /* TBGA package */
+    POWERPC_SVR_8347EP             = 0x80540010, /* PBGA package */
+    POWERPC_SVR_8347ET             = 0x80520010, /* TBGA package */
+    POWERPC_SVR_8347EAP            = 0x80540030, /* PBGA package */
+    POWERPC_SVR_8347EAT            = 0x80520030, /* TBGA package */
+    POWERPC_SVR_8349               = 0x80510010,
+    POWERPC_SVR_8349A              = 0x80510030,
+    POWERPC_SVR_8349E              = 0x80500010,
+    POWERPC_SVR_8349EA             = 0x80500030,
+#if 0
+    POWERPC_SVR_8358E              = xxx,
+#endif
+#if 0
+    POWERPC_SVR_8360E              = xxx,
+#endif
+#define POWERPC_SVR_E500             0x40000000
+    POWERPC_SVR_8377               = 0x80C70010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8377E              = 0x80C60010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8378               = 0x80C50010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8378E              = 0x80C40010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8379               = 0x80C30010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8379E              = 0x80C00010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8533_v10           = 0x80340010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8533_v11           = 0x80340011 | POWERPC_SVR_E500,
+    POWERPC_SVR_8533E_v10          = 0x803C0010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8533E_v11          = 0x803C0011 | POWERPC_SVR_E500,
+    POWERPC_SVR_8540_v10           = 0x80300010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8540_v20           = 0x80300020 | POWERPC_SVR_E500,
+    POWERPC_SVR_8540_v21           = 0x80300021 | POWERPC_SVR_E500,
+    POWERPC_SVR_8541_v10           = 0x80720010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8541_v11           = 0x80720011 | POWERPC_SVR_E500,
+    POWERPC_SVR_8541E_v10          = 0x807A0010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8541E_v11          = 0x807A0011 | POWERPC_SVR_E500,
+    POWERPC_SVR_8543_v10           = 0x80320010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8543_v11           = 0x80320011 | POWERPC_SVR_E500,
+    POWERPC_SVR_8543_v20           = 0x80320020 | POWERPC_SVR_E500,
+    POWERPC_SVR_8543_v21           = 0x80320021 | POWERPC_SVR_E500,
+    POWERPC_SVR_8543E_v10          = 0x803A0010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8543E_v11          = 0x803A0011 | POWERPC_SVR_E500,
+    POWERPC_SVR_8543E_v20          = 0x803A0020 | POWERPC_SVR_E500,
+    POWERPC_SVR_8543E_v21          = 0x803A0021 | POWERPC_SVR_E500,
+    POWERPC_SVR_8544_v10           = 0x80340110 | POWERPC_SVR_E500,
+    POWERPC_SVR_8544_v11           = 0x80340111 | POWERPC_SVR_E500,
+    POWERPC_SVR_8544E_v10          = 0x803C0110 | POWERPC_SVR_E500,
+    POWERPC_SVR_8544E_v11          = 0x803C0111 | POWERPC_SVR_E500,
+    POWERPC_SVR_8545_v20           = 0x80310220 | POWERPC_SVR_E500,
+    POWERPC_SVR_8545_v21           = 0x80310221 | POWERPC_SVR_E500,
+    POWERPC_SVR_8545E_v20          = 0x80390220 | POWERPC_SVR_E500,
+    POWERPC_SVR_8545E_v21          = 0x80390221 | POWERPC_SVR_E500,
+    POWERPC_SVR_8547E_v20          = 0x80390120 | POWERPC_SVR_E500,
+    POWERPC_SVR_8547E_v21          = 0x80390121 | POWERPC_SVR_E500,
+    POWERPC_SVR_8548_v10           = 0x80310010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8548_v11           = 0x80310011 | POWERPC_SVR_E500,
+    POWERPC_SVR_8548_v20           = 0x80310020 | POWERPC_SVR_E500,
+    POWERPC_SVR_8548_v21           = 0x80310021 | POWERPC_SVR_E500,
+    POWERPC_SVR_8548E_v10          = 0x80390010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8548E_v11          = 0x80390011 | POWERPC_SVR_E500,
+    POWERPC_SVR_8548E_v20          = 0x80390020 | POWERPC_SVR_E500,
+    POWERPC_SVR_8548E_v21          = 0x80390021 | POWERPC_SVR_E500,
+    POWERPC_SVR_8555_v10           = 0x80710010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8555_v11           = 0x80710011 | POWERPC_SVR_E500,
+    POWERPC_SVR_8555E_v10          = 0x80790010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8555E_v11          = 0x80790011 | POWERPC_SVR_E500,
+    POWERPC_SVR_8560_v10           = 0x80700010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8560_v20           = 0x80700020 | POWERPC_SVR_E500,
+    POWERPC_SVR_8560_v21           = 0x80700021 | POWERPC_SVR_E500,
+    POWERPC_SVR_8567               = 0x80750111 | POWERPC_SVR_E500,
+    POWERPC_SVR_8567E              = 0x807D0111 | POWERPC_SVR_E500,
+    POWERPC_SVR_8568               = 0x80750011 | POWERPC_SVR_E500,
+    POWERPC_SVR_8568E              = 0x807D0011 | POWERPC_SVR_E500,
+    POWERPC_SVR_8572               = 0x80E00010 | POWERPC_SVR_E500,
+    POWERPC_SVR_8572E              = 0x80E80010 | POWERPC_SVR_E500,
+#if 0
+    POWERPC_SVR_8610               = xxx,
+#endif
+    POWERPC_SVR_8641               = 0x80900021,
+    POWERPC_SVR_8641D              = 0x80900121,
+};
+
+#endif
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 31566e0..b0d4357 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -18,24 +18,17 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-/* A lot of PowerPC definition have been included here.
- * Most of them are not usable for now but have been kept
- * inside "#if defined(TODO) ... #endif" statements to make tests easier.
- */
-
 #include "disas/bfd.h"
 #include "exec/gdbstub.h"
 #include <sysemu/kvm.h>
 #include "kvm_ppc.h"
 #include "sysemu/arch_init.h"
 #include "sysemu/cpus.h"
+#include "cpu-models.h"
 
 //#define PPC_DUMP_CPU
 //#define PPC_DEBUG_SPR
 //#define PPC_DUMP_SPR_ACCESSES
-#if defined(CONFIG_USER_ONLY)
-#define TODO_USER_ONLY 1
-#endif
 
 /* For user-mode emulation, we don't emulate any IRQ controller */
 #if defined(CONFIG_USER_ONLY)
@@ -4876,18 +4869,16 @@ POWERPC_FAMILY(e5500)(ObjectClass *oc, void *data)
 /* Non-embedded PowerPC                                                      */
 
 /* POWER : same as 601, without mfmsr, mfsr                                  */
-#if defined(TODO)
 POWERPC_FAMILY(POWER)(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
     dc->desc = "POWER";
-    pcc->insns_flags = XXX_TODO;
+    /* pcc->insns_flags = XXX_TODO; */
     /* POWER RSC (from RAD6000) */
     pcc->msr_mask = 0x00000000FEF0ULL;
 }
-#endif /* TODO */
 
 #define POWERPC_MSRR_601     (0x0000000000001040ULL)
 
@@ -7173,1900 +7164,6 @@ POWERPC_FAMILY(620)(ObjectClass *oc, void *data)
 
 #endif /* defined (TARGET_PPC64) */
 
-/*****************************************************************************/
-/* PVR definitions for most known PowerPC                                    */
-enum {
-    /* PowerPC 401 family */
-    /* Generic PowerPC 401 */
-#define CPU_POWERPC_401              CPU_POWERPC_401G2
-    /* PowerPC 401 cores */
-    CPU_POWERPC_401A1              = 0x00210000,
-    CPU_POWERPC_401B2              = 0x00220000,
-#if 0
-    CPU_POWERPC_401B3              = xxx,
-#endif
-    CPU_POWERPC_401C2              = 0x00230000,
-    CPU_POWERPC_401D2              = 0x00240000,
-    CPU_POWERPC_401E2              = 0x00250000,
-    CPU_POWERPC_401F2              = 0x00260000,
-    CPU_POWERPC_401G2              = 0x00270000,
-    /* PowerPC 401 microcontrolers */
-#if 0
-    CPU_POWERPC_401GF              = xxx,
-#endif
-#define CPU_POWERPC_IOP480           CPU_POWERPC_401B2
-    /* IBM Processor for Network Resources */
-    CPU_POWERPC_COBRA              = 0x10100000, /* XXX: 405 ? */
-#if 0
-    CPU_POWERPC_XIPCHIP            = xxx,
-#endif
-    /* PowerPC 403 family */
-    /* PowerPC 403 microcontrollers */
-    CPU_POWERPC_403GA              = 0x00200011,
-    CPU_POWERPC_403GB              = 0x00200100,
-    CPU_POWERPC_403GC              = 0x00200200,
-    CPU_POWERPC_403GCX             = 0x00201400,
-#if 0
-    CPU_POWERPC_403GP              = xxx,
-#endif
-    /* PowerPC 405 family */
-    /* PowerPC 405 cores */
-#if 0
-    CPU_POWERPC_405A3              = xxx,
-#endif
-#if 0
-    CPU_POWERPC_405A4              = xxx,
-#endif
-#if 0
-    CPU_POWERPC_405B3              = xxx,
-#endif
-#if 0
-    CPU_POWERPC_405B4              = xxx,
-#endif
-#if 0
-    CPU_POWERPC_405C3              = xxx,
-#endif
-#if 0
-    CPU_POWERPC_405C4              = xxx,
-#endif
-    CPU_POWERPC_405D2              = 0x20010000,
-#if 0
-    CPU_POWERPC_405D3              = xxx,
-#endif
-    CPU_POWERPC_405D4              = 0x41810000,
-#if 0
-    CPU_POWERPC_405D5              = xxx,
-#endif
-#if 0
-    CPU_POWERPC_405E4              = xxx,
-#endif
-#if 0
-    CPU_POWERPC_405F4              = xxx,
-#endif
-#if 0
-    CPU_POWERPC_405F5              = xxx,
-#endif
-#if 0
-    CPU_POWERPC_405F6              = xxx,
-#endif
-    /* PowerPC 405 microcontrolers */
-    /* XXX: missing 0x200108a0 */
-    CPU_POWERPC_405CRa             = 0x40110041,
-    CPU_POWERPC_405CRb             = 0x401100C5,
-    CPU_POWERPC_405CRc             = 0x40110145,
-    CPU_POWERPC_405EP              = 0x51210950,
-#if 0
-    CPU_POWERPC_405EXr             = xxx,
-#endif
-    CPU_POWERPC_405EZ              = 0x41511460, /* 0x51210950 ? */
-#if 0
-    CPU_POWERPC_405FX              = xxx,
-#endif
-    CPU_POWERPC_405GPa             = 0x40110000,
-    CPU_POWERPC_405GPb             = 0x40110040,
-    CPU_POWERPC_405GPc             = 0x40110082,
-    CPU_POWERPC_405GPd             = 0x401100C4,
-    CPU_POWERPC_405GPR             = 0x50910951,
-#if 0
-    CPU_POWERPC_405H               = xxx,
-#endif
-#if 0
-    CPU_POWERPC_405L               = xxx,
-#endif
-    CPU_POWERPC_405LP              = 0x41F10000,
-#if 0
-    CPU_POWERPC_405PM              = xxx,
-#endif
-#if 0
-    CPU_POWERPC_405PS              = xxx,
-#endif
-#if 0
-    CPU_POWERPC_405S               = xxx,
-#endif
-    /* IBM network processors */
-    CPU_POWERPC_NPE405H            = 0x414100C0,
-    CPU_POWERPC_NPE405H2           = 0x41410140,
-    CPU_POWERPC_NPE405L            = 0x416100C0,
-    CPU_POWERPC_NPE4GS3            = 0x40B10000,
-#if 0
-    CPU_POWERPC_NPCxx1             = xxx,
-#endif
-#if 0
-    CPU_POWERPC_NPR161             = xxx,
-#endif
-#if 0
-    CPU_POWERPC_LC77700            = xxx,
-#endif
-    /* IBM STBxxx (PowerPC 401/403/405 core based microcontrollers) */
-#if 0
-    CPU_POWERPC_STB01000           = xxx,
-#endif
-#if 0
-    CPU_POWERPC_STB01010           = xxx,
-#endif
-#if 0
-    CPU_POWERPC_STB0210            = xxx, /* 401B3 */
-#endif
-    CPU_POWERPC_STB03              = 0x40310000, /* 0x40130000 ? */
-#if 0
-    CPU_POWERPC_STB043             = xxx,
-#endif
-#if 0
-    CPU_POWERPC_STB045             = xxx,
-#endif
-    CPU_POWERPC_STB04              = 0x41810000,
-    CPU_POWERPC_STB25              = 0x51510950,
-#if 0
-    CPU_POWERPC_STB130             = xxx,
-#endif
-    /* Xilinx cores */
-    CPU_POWERPC_X2VP4              = 0x20010820,
-    CPU_POWERPC_X2VP20             = 0x20010860,
-#if 0
-    CPU_POWERPC_ZL10310            = xxx,
-#endif
-#if 0
-    CPU_POWERPC_ZL10311            = xxx,
-#endif
-#if 0
-    CPU_POWERPC_ZL10320            = xxx,
-#endif
-#if 0
-    CPU_POWERPC_ZL10321            = xxx,
-#endif
-    /* PowerPC 440 family */
-    /* Generic PowerPC 440 */
-#define CPU_POWERPC_440              CPU_POWERPC_440GXf
-    /* PowerPC 440 cores */
-#if 0
-    CPU_POWERPC_440A4              = xxx,
-#endif
-    CPU_POWERPC_440_XILINX         = 0x7ff21910,
-#if 0
-    CPU_POWERPC_440A5              = xxx,
-#endif
-#if 0
-    CPU_POWERPC_440B4              = xxx,
-#endif
-#if 0
-    CPU_POWERPC_440F5              = xxx,
-#endif
-#if 0
-    CPU_POWERPC_440G5              = xxx,
-#endif
-#if 0
-    CPU_POWERPC_440H4              = xxx,
-#endif
-#if 0
-    CPU_POWERPC_440H6              = xxx,
-#endif
-    /* PowerPC 440 microcontrolers */
-    CPU_POWERPC_440EPa             = 0x42221850,
-    CPU_POWERPC_440EPb             = 0x422218D3,
-    CPU_POWERPC_440GPb             = 0x40120440,
-    CPU_POWERPC_440GPc             = 0x40120481,
-#define CPU_POWERPC_440GRa           CPU_POWERPC_440EPb
-    CPU_POWERPC_440GRX             = 0x200008D0,
-#define CPU_POWERPC_440EPX           CPU_POWERPC_440GRX
-    CPU_POWERPC_440GXa             = 0x51B21850,
-    CPU_POWERPC_440GXb             = 0x51B21851,
-    CPU_POWERPC_440GXc             = 0x51B21892,
-    CPU_POWERPC_440GXf             = 0x51B21894,
-#if 0
-    CPU_POWERPC_440S               = xxx,
-#endif
-    CPU_POWERPC_440SP              = 0x53221850,
-    CPU_POWERPC_440SP2             = 0x53221891,
-    CPU_POWERPC_440SPE             = 0x53421890,
-    /* PowerPC 460 family */
-#if 0
-    /* Generic PowerPC 464 */
-#define CPU_POWERPC_464              CPU_POWERPC_464H90
-#endif
-    /* PowerPC 464 microcontrolers */
-#if 0
-    CPU_POWERPC_464H90             = xxx,
-#endif
-#if 0
-    CPU_POWERPC_464H90FP           = xxx,
-#endif
-    /* Freescale embedded PowerPC cores */
-    /* PowerPC MPC 5xx cores (aka RCPU) */
-    CPU_POWERPC_MPC5xx             = 0x00020020,
-    /* PowerPC MPC 8xx cores (aka PowerQUICC) */
-    CPU_POWERPC_MPC8xx             = 0x00500000,
-    /* G2 cores (aka PowerQUICC-II) */
-    CPU_POWERPC_G2                 = 0x00810011,
-    CPU_POWERPC_G2H4               = 0x80811010,
-    CPU_POWERPC_G2gp               = 0x80821010,
-    CPU_POWERPC_G2ls               = 0x90810010,
-    CPU_POWERPC_MPC603             = 0x00810100,
-    CPU_POWERPC_G2_HIP3            = 0x00810101,
-    CPU_POWERPC_G2_HIP4            = 0x80811014,
-    /*   G2_LE core (aka PowerQUICC-II) */
-    CPU_POWERPC_G2LE               = 0x80820010,
-    CPU_POWERPC_G2LEgp             = 0x80822010,
-    CPU_POWERPC_G2LEls             = 0xA0822010,
-    CPU_POWERPC_G2LEgp1            = 0x80822011,
-    CPU_POWERPC_G2LEgp3            = 0x80822013,
-    /* MPC52xx microcontrollers  */
-    /* XXX: MPC 5121 ? */
-#define CPU_POWERPC_MPC5200_v10      CPU_POWERPC_G2LEgp1
-#define CPU_POWERPC_MPC5200_v11      CPU_POWERPC_G2LEgp1
-#define CPU_POWERPC_MPC5200_v12      CPU_POWERPC_G2LEgp1
-#define CPU_POWERPC_MPC5200B_v20     CPU_POWERPC_G2LEgp1
-#define CPU_POWERPC_MPC5200B_v21     CPU_POWERPC_G2LEgp1
-    /* e200 family */
-    /* e200 cores */
-#if 0
-    CPU_POWERPC_e200z0             = xxx,
-#endif
-#if 0
-    CPU_POWERPC_e200z1             = xxx,
-#endif
-#if 0 /* ? */
-    CPU_POWERPC_e200z3             = 0x81120000,
-#endif
-    CPU_POWERPC_e200z5             = 0x81000000,
-    CPU_POWERPC_e200z6             = 0x81120000,
-    /* MPC55xx microcontrollers */
-#define CPU_POWERPC_MPC55xx          CPU_POWERPC_MPC5567
-#if 0
-#define CPU_POWERPC_MPC5514E         CPU_POWERPC_MPC5514E_v1
-#define CPU_POWERPC_MPC5514E_v0      CPU_POWERPC_e200z0
-#define CPU_POWERPC_MPC5514E_v1      CPU_POWERPC_e200z1
-#define CPU_POWERPC_MPC5514G         CPU_POWERPC_MPC5514G_v1
-#define CPU_POWERPC_MPC5514G_v0      CPU_POWERPC_e200z0
-#define CPU_POWERPC_MPC5514G_v1      CPU_POWERPC_e200z1
-#define CPU_POWERPC_MPC5515S         CPU_POWERPC_e200z1
-#define CPU_POWERPC_MPC5516E         CPU_POWERPC_MPC5516E_v1
-#define CPU_POWERPC_MPC5516E_v0      CPU_POWERPC_e200z0
-#define CPU_POWERPC_MPC5516E_v1      CPU_POWERPC_e200z1
-#define CPU_POWERPC_MPC5516G         CPU_POWERPC_MPC5516G_v1
-#define CPU_POWERPC_MPC5516G_v0      CPU_POWERPC_e200z0
-#define CPU_POWERPC_MPC5516G_v1      CPU_POWERPC_e200z1
-#define CPU_POWERPC_MPC5516S         CPU_POWERPC_e200z1
-#endif
-#if 0
-#define CPU_POWERPC_MPC5533          CPU_POWERPC_e200z3
-#define CPU_POWERPC_MPC5534          CPU_POWERPC_e200z3
-#endif
-#define CPU_POWERPC_MPC5553          CPU_POWERPC_e200z6
-#define CPU_POWERPC_MPC5554          CPU_POWERPC_e200z6
-#define CPU_POWERPC_MPC5561          CPU_POWERPC_e200z6
-#define CPU_POWERPC_MPC5565          CPU_POWERPC_e200z6
-#define CPU_POWERPC_MPC5566          CPU_POWERPC_e200z6
-#define CPU_POWERPC_MPC5567          CPU_POWERPC_e200z6
-    /* e300 family */
-    /* e300 cores */
-    CPU_POWERPC_e300c1             = 0x00830010,
-    CPU_POWERPC_e300c2             = 0x00840010,
-    CPU_POWERPC_e300c3             = 0x00850010,
-    CPU_POWERPC_e300c4             = 0x00860010,
-    /* MPC83xx microcontrollers */
-#define CPU_POWERPC_MPC831x          CPU_POWERPC_e300c3
-#define CPU_POWERPC_MPC832x          CPU_POWERPC_e300c2
-#define CPU_POWERPC_MPC834x          CPU_POWERPC_e300c1
-#define CPU_POWERPC_MPC835x          CPU_POWERPC_e300c1
-#define CPU_POWERPC_MPC836x          CPU_POWERPC_e300c1
-#define CPU_POWERPC_MPC837x          CPU_POWERPC_e300c4
-    /* e500 family */
-    /* e500 cores  */
-#define CPU_POWERPC_e500             CPU_POWERPC_e500v2_v22
-    CPU_POWERPC_e500v1_v10         = 0x80200010,
-    CPU_POWERPC_e500v1_v20         = 0x80200020,
-    CPU_POWERPC_e500v2_v10         = 0x80210010,
-    CPU_POWERPC_e500v2_v11         = 0x80210011,
-    CPU_POWERPC_e500v2_v20         = 0x80210020,
-    CPU_POWERPC_e500v2_v21         = 0x80210021,
-    CPU_POWERPC_e500v2_v22         = 0x80210022,
-    CPU_POWERPC_e500v2_v30         = 0x80210030,
-    CPU_POWERPC_e500mc             = 0x80230020,
-    CPU_POWERPC_e5500              = 0x80240020,
-    /* MPC85xx microcontrollers */
-#define CPU_POWERPC_MPC8533_v10      CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8533_v11      CPU_POWERPC_e500v2_v22
-#define CPU_POWERPC_MPC8533E_v10     CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8533E_v11     CPU_POWERPC_e500v2_v22
-#define CPU_POWERPC_MPC8540_v10      CPU_POWERPC_e500v1_v10
-#define CPU_POWERPC_MPC8540_v20      CPU_POWERPC_e500v1_v20
-#define CPU_POWERPC_MPC8540_v21      CPU_POWERPC_e500v1_v20
-#define CPU_POWERPC_MPC8541_v10      CPU_POWERPC_e500v1_v20
-#define CPU_POWERPC_MPC8541_v11      CPU_POWERPC_e500v1_v20
-#define CPU_POWERPC_MPC8541E_v10     CPU_POWERPC_e500v1_v20
-#define CPU_POWERPC_MPC8541E_v11     CPU_POWERPC_e500v1_v20
-#define CPU_POWERPC_MPC8543_v10      CPU_POWERPC_e500v2_v10
-#define CPU_POWERPC_MPC8543_v11      CPU_POWERPC_e500v2_v11
-#define CPU_POWERPC_MPC8543_v20      CPU_POWERPC_e500v2_v20
-#define CPU_POWERPC_MPC8543_v21      CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8543E_v10     CPU_POWERPC_e500v2_v10
-#define CPU_POWERPC_MPC8543E_v11     CPU_POWERPC_e500v2_v11
-#define CPU_POWERPC_MPC8543E_v20     CPU_POWERPC_e500v2_v20
-#define CPU_POWERPC_MPC8543E_v21     CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8544_v10      CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8544_v11      CPU_POWERPC_e500v2_v22
-#define CPU_POWERPC_MPC8544E_v11     CPU_POWERPC_e500v2_v22
-#define CPU_POWERPC_MPC8544E_v10     CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8545_v10      CPU_POWERPC_e500v2_v10
-#define CPU_POWERPC_MPC8545_v20      CPU_POWERPC_e500v2_v20
-#define CPU_POWERPC_MPC8545_v21      CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8545E_v10     CPU_POWERPC_e500v2_v10
-#define CPU_POWERPC_MPC8545E_v20     CPU_POWERPC_e500v2_v20
-#define CPU_POWERPC_MPC8545E_v21     CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8547E_v10     CPU_POWERPC_e500v2_v10
-#define CPU_POWERPC_MPC8547E_v20     CPU_POWERPC_e500v2_v20
-#define CPU_POWERPC_MPC8547E_v21     CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8548_v10      CPU_POWERPC_e500v2_v10
-#define CPU_POWERPC_MPC8548_v11      CPU_POWERPC_e500v2_v11
-#define CPU_POWERPC_MPC8548_v20      CPU_POWERPC_e500v2_v20
-#define CPU_POWERPC_MPC8548_v21      CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8548E_v10     CPU_POWERPC_e500v2_v10
-#define CPU_POWERPC_MPC8548E_v11     CPU_POWERPC_e500v2_v11
-#define CPU_POWERPC_MPC8548E_v20     CPU_POWERPC_e500v2_v20
-#define CPU_POWERPC_MPC8548E_v21     CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8555_v10      CPU_POWERPC_e500v2_v10
-#define CPU_POWERPC_MPC8555_v11      CPU_POWERPC_e500v2_v11
-#define CPU_POWERPC_MPC8555E_v10     CPU_POWERPC_e500v2_v10
-#define CPU_POWERPC_MPC8555E_v11     CPU_POWERPC_e500v2_v11
-#define CPU_POWERPC_MPC8560_v10      CPU_POWERPC_e500v2_v10
-#define CPU_POWERPC_MPC8560_v20      CPU_POWERPC_e500v2_v20
-#define CPU_POWERPC_MPC8560_v21      CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8567          CPU_POWERPC_e500v2_v22
-#define CPU_POWERPC_MPC8567E         CPU_POWERPC_e500v2_v22
-#define CPU_POWERPC_MPC8568          CPU_POWERPC_e500v2_v22
-#define CPU_POWERPC_MPC8568E         CPU_POWERPC_e500v2_v22
-#define CPU_POWERPC_MPC8572          CPU_POWERPC_e500v2_v30
-#define CPU_POWERPC_MPC8572E         CPU_POWERPC_e500v2_v30
-    /* e600 family */
-    /* e600 cores */
-    CPU_POWERPC_e600               = 0x80040010,
-    /* MPC86xx microcontrollers */
-#define CPU_POWERPC_MPC8610          CPU_POWERPC_e600
-#define CPU_POWERPC_MPC8641          CPU_POWERPC_e600
-#define CPU_POWERPC_MPC8641D         CPU_POWERPC_e600
-    /* PowerPC 6xx cores */
-    CPU_POWERPC_601_v0             = 0x00010001,
-    CPU_POWERPC_601_v1             = 0x00010001,
-    CPU_POWERPC_601_v2             = 0x00010002,
-    CPU_POWERPC_602                = 0x00050100,
-    CPU_POWERPC_603                = 0x00030100,
-    CPU_POWERPC_603E_v11           = 0x00060101,
-    CPU_POWERPC_603E_v12           = 0x00060102,
-    CPU_POWERPC_603E_v13           = 0x00060103,
-    CPU_POWERPC_603E_v14           = 0x00060104,
-    CPU_POWERPC_603E_v22           = 0x00060202,
-    CPU_POWERPC_603E_v3            = 0x00060300,
-    CPU_POWERPC_603E_v4            = 0x00060400,
-    CPU_POWERPC_603E_v41           = 0x00060401,
-    CPU_POWERPC_603E7t             = 0x00071201,
-    CPU_POWERPC_603E7v             = 0x00070100,
-    CPU_POWERPC_603E7v1            = 0x00070101,
-    CPU_POWERPC_603E7v2            = 0x00070201,
-    CPU_POWERPC_603E7              = 0x00070200,
-    CPU_POWERPC_603P               = 0x00070000,
-    /* XXX: missing 0x00040303 (604) */
-    CPU_POWERPC_604                = 0x00040103,
-    /* XXX: missing 0x00091203 */
-    /* XXX: missing 0x00092110 */
-    /* XXX: missing 0x00092120 */
-    CPU_POWERPC_604E_v10           = 0x00090100,
-    CPU_POWERPC_604E_v22           = 0x00090202,
-    CPU_POWERPC_604E_v24           = 0x00090204,
-    /* XXX: missing 0x000a0100 */
-    /* XXX: missing 0x00093102 */
-    CPU_POWERPC_604R               = 0x000a0101,
-#if 0
-    CPU_POWERPC_604EV              = xxx, /* XXX: same as 604R ? */
-#endif
-    /* PowerPC 740/750 cores (aka G3) */
-    /* XXX: missing 0x00084202 */
-    CPU_POWERPC_7x0_v10            = 0x00080100,
-    CPU_POWERPC_7x0_v20            = 0x00080200,
-    CPU_POWERPC_7x0_v21            = 0x00080201,
-    CPU_POWERPC_7x0_v22            = 0x00080202,
-    CPU_POWERPC_7x0_v30            = 0x00080300,
-    CPU_POWERPC_7x0_v31            = 0x00080301,
-    CPU_POWERPC_740E               = 0x00080100,
-    CPU_POWERPC_750E               = 0x00080200,
-    CPU_POWERPC_7x0P               = 0x10080000,
-    /* XXX: missing 0x00087010 (CL ?) */
-    CPU_POWERPC_750CL_v10          = 0x00087200,
-    CPU_POWERPC_750CL_v20          = 0x00087210, /* aka rev E */
-    CPU_POWERPC_750CX_v10          = 0x00082100,
-    CPU_POWERPC_750CX_v20          = 0x00082200,
-    CPU_POWERPC_750CX_v21          = 0x00082201,
-    CPU_POWERPC_750CX_v22          = 0x00082202,
-    CPU_POWERPC_750CXE_v21         = 0x00082211,
-    CPU_POWERPC_750CXE_v22         = 0x00082212,
-    CPU_POWERPC_750CXE_v23         = 0x00082213,
-    CPU_POWERPC_750CXE_v24         = 0x00082214,
-    CPU_POWERPC_750CXE_v24b        = 0x00083214,
-    CPU_POWERPC_750CXE_v30         = 0x00082310,
-    CPU_POWERPC_750CXE_v31         = 0x00082311,
-    CPU_POWERPC_750CXE_v31b        = 0x00083311,
-    CPU_POWERPC_750CXR             = 0x00083410,
-    CPU_POWERPC_750FL              = 0x70000203,
-    CPU_POWERPC_750FX_v10          = 0x70000100,
-    CPU_POWERPC_750FX_v20          = 0x70000200,
-    CPU_POWERPC_750FX_v21          = 0x70000201,
-    CPU_POWERPC_750FX_v22          = 0x70000202,
-    CPU_POWERPC_750FX_v23          = 0x70000203,
-    CPU_POWERPC_750GL              = 0x70020102,
-    CPU_POWERPC_750GX_v10          = 0x70020100,
-    CPU_POWERPC_750GX_v11          = 0x70020101,
-    CPU_POWERPC_750GX_v12          = 0x70020102,
-    CPU_POWERPC_750L_v20           = 0x00088200,
-    CPU_POWERPC_750L_v21           = 0x00088201,
-    CPU_POWERPC_750L_v22           = 0x00088202,
-    CPU_POWERPC_750L_v30           = 0x00088300,
-    CPU_POWERPC_750L_v32           = 0x00088302,
-    /* PowerPC 745/755 cores */
-    CPU_POWERPC_7x5_v10            = 0x00083100,
-    CPU_POWERPC_7x5_v11            = 0x00083101,
-    CPU_POWERPC_7x5_v20            = 0x00083200,
-    CPU_POWERPC_7x5_v21            = 0x00083201,
-    CPU_POWERPC_7x5_v22            = 0x00083202, /* aka D */
-    CPU_POWERPC_7x5_v23            = 0x00083203, /* aka E */
-    CPU_POWERPC_7x5_v24            = 0x00083204,
-    CPU_POWERPC_7x5_v25            = 0x00083205,
-    CPU_POWERPC_7x5_v26            = 0x00083206,
-    CPU_POWERPC_7x5_v27            = 0x00083207,
-    CPU_POWERPC_7x5_v28            = 0x00083208,
-#if 0
-    CPU_POWERPC_7x5P               = xxx,
-#endif
-    /* PowerPC 74xx cores (aka G4) */
-    /* XXX: missing 0x000C1101 */
-    CPU_POWERPC_7400_v10           = 0x000C0100,
-    CPU_POWERPC_7400_v11           = 0x000C0101,
-    CPU_POWERPC_7400_v20           = 0x000C0200,
-    CPU_POWERPC_7400_v21           = 0x000C0201,
-    CPU_POWERPC_7400_v22           = 0x000C0202,
-    CPU_POWERPC_7400_v26           = 0x000C0206,
-    CPU_POWERPC_7400_v27           = 0x000C0207,
-    CPU_POWERPC_7400_v28           = 0x000C0208,
-    CPU_POWERPC_7400_v29           = 0x000C0209,
-    CPU_POWERPC_7410_v10           = 0x800C1100,
-    CPU_POWERPC_7410_v11           = 0x800C1101,
-    CPU_POWERPC_7410_v12           = 0x800C1102, /* aka C */
-    CPU_POWERPC_7410_v13           = 0x800C1103, /* aka D */
-    CPU_POWERPC_7410_v14           = 0x800C1104, /* aka E */
-    CPU_POWERPC_7448_v10           = 0x80040100,
-    CPU_POWERPC_7448_v11           = 0x80040101,
-    CPU_POWERPC_7448_v20           = 0x80040200,
-    CPU_POWERPC_7448_v21           = 0x80040201,
-    CPU_POWERPC_7450_v10           = 0x80000100,
-    CPU_POWERPC_7450_v11           = 0x80000101,
-    CPU_POWERPC_7450_v12           = 0x80000102,
-    CPU_POWERPC_7450_v20           = 0x80000200, /* aka A, B, C, D: 2.04 */
-    CPU_POWERPC_7450_v21           = 0x80000201, /* aka E */
-    CPU_POWERPC_74x1_v23           = 0x80000203, /* aka G: 2.3 */
-    /* XXX: this entry might be a bug in some documentation */
-    CPU_POWERPC_74x1_v210          = 0x80000210, /* aka G: 2.3 ? */
-    CPU_POWERPC_74x5_v10           = 0x80010100,
-    /* XXX: missing 0x80010200 */
-    CPU_POWERPC_74x5_v21           = 0x80010201, /* aka C: 2.1 */
-    CPU_POWERPC_74x5_v32           = 0x80010302,
-    CPU_POWERPC_74x5_v33           = 0x80010303, /* aka F: 3.3 */
-    CPU_POWERPC_74x5_v34           = 0x80010304, /* aka G: 3.4 */
-    CPU_POWERPC_74x7_v10           = 0x80020100, /* aka A: 1.0 */
-    CPU_POWERPC_74x7_v11           = 0x80020101, /* aka B: 1.1 */
-    CPU_POWERPC_74x7_v12           = 0x80020102, /* aka C: 1.2 */
-    CPU_POWERPC_74x7A_v10          = 0x80030100, /* aka A: 1.0 */
-    CPU_POWERPC_74x7A_v11          = 0x80030101, /* aka B: 1.1 */
-    CPU_POWERPC_74x7A_v12          = 0x80030102, /* aka C: 1.2 */
-    /* 64 bits PowerPC */
-#if defined(TARGET_PPC64)
-    CPU_POWERPC_620                = 0x00140000,
-    CPU_POWERPC_630                = 0x00400000,
-    CPU_POWERPC_631                = 0x00410104,
-    CPU_POWERPC_POWER4             = 0x00350000,
-    CPU_POWERPC_POWER4P            = 0x00380000,
-     /* XXX: missing 0x003A0201 */
-    CPU_POWERPC_POWER5             = 0x003A0203,
-#define CPU_POWERPC_POWER5GR         CPU_POWERPC_POWER5
-    CPU_POWERPC_POWER5P            = 0x003B0000,
-#define CPU_POWERPC_POWER5GS         CPU_POWERPC_POWER5P
-    CPU_POWERPC_POWER6             = 0x003E0000,
-    CPU_POWERPC_POWER6_5           = 0x0F000001, /* POWER6 in POWER5 mode */
-    CPU_POWERPC_POWER6A            = 0x0F000002,
-    CPU_POWERPC_POWER7_v20         = 0x003F0200,
-    CPU_POWERPC_POWER7_v21         = 0x003F0201,
-    CPU_POWERPC_POWER7_v23         = 0x003F0203,
-    CPU_POWERPC_970                = 0x00390202,
-    CPU_POWERPC_970FX_v10          = 0x00391100,
-    CPU_POWERPC_970FX_v20          = 0x003C0200,
-    CPU_POWERPC_970FX_v21          = 0x003C0201,
-    CPU_POWERPC_970FX_v30          = 0x003C0300,
-    CPU_POWERPC_970FX_v31          = 0x003C0301,
-    CPU_POWERPC_970GX              = 0x00450000,
-    CPU_POWERPC_970MP_v10          = 0x00440100,
-    CPU_POWERPC_970MP_v11          = 0x00440101,
-#define CPU_POWERPC_CELL             CPU_POWERPC_CELL_v32
-    CPU_POWERPC_CELL_v10           = 0x00700100,
-    CPU_POWERPC_CELL_v20           = 0x00700400,
-    CPU_POWERPC_CELL_v30           = 0x00700500,
-    CPU_POWERPC_CELL_v31           = 0x00700501,
-#define CPU_POWERPC_CELL_v32         CPU_POWERPC_CELL_v31
-    CPU_POWERPC_RS64               = 0x00330000,
-    CPU_POWERPC_RS64II             = 0x00340000,
-    CPU_POWERPC_RS64III            = 0x00360000,
-    CPU_POWERPC_RS64IV             = 0x00370000,
-#endif /* defined(TARGET_PPC64) */
-    /* Original POWER */
-    /* XXX: should be POWER (RIOS), RSC3308, RSC4608,
-     * POWER2 (RIOS2) & RSC2 (P2SC) here
-     */
-#if 0
-    CPU_POWER                      = xxx, /* 0x20000 ? 0x30000 for RSC ? */
-#endif
-#if 0
-    CPU_POWER2                     = xxx, /* 0x40000 ? */
-#endif
-    /* PA Semi core */
-    CPU_POWERPC_PA6T               = 0x00900000,
-};
-
-/* System version register (used on MPC 8xxx)                                */
-enum {
-    POWERPC_SVR_NONE               = 0x00000000,
-    POWERPC_SVR_5200_v10           = 0x80110010,
-    POWERPC_SVR_5200_v11           = 0x80110011,
-    POWERPC_SVR_5200_v12           = 0x80110012,
-    POWERPC_SVR_5200B_v20          = 0x80110020,
-    POWERPC_SVR_5200B_v21          = 0x80110021,
-#define POWERPC_SVR_55xx             POWERPC_SVR_5567
-#if 0
-    POWERPC_SVR_5533               = xxx,
-#endif
-#if 0
-    POWERPC_SVR_5534               = xxx,
-#endif
-#if 0
-    POWERPC_SVR_5553               = xxx,
-#endif
-#if 0
-    POWERPC_SVR_5554               = xxx,
-#endif
-#if 0
-    POWERPC_SVR_5561               = xxx,
-#endif
-#if 0
-    POWERPC_SVR_5565               = xxx,
-#endif
-#if 0
-    POWERPC_SVR_5566               = xxx,
-#endif
-#if 0
-    POWERPC_SVR_5567               = xxx,
-#endif
-#if 0
-    POWERPC_SVR_8313               = xxx,
-#endif
-#if 0
-    POWERPC_SVR_8313E              = xxx,
-#endif
-#if 0
-    POWERPC_SVR_8314               = xxx,
-#endif
-#if 0
-    POWERPC_SVR_8314E              = xxx,
-#endif
-#if 0
-    POWERPC_SVR_8315               = xxx,
-#endif
-#if 0
-    POWERPC_SVR_8315E              = xxx,
-#endif
-#if 0
-    POWERPC_SVR_8321               = xxx,
-#endif
-#if 0
-    POWERPC_SVR_8321E              = xxx,
-#endif
-#if 0
-    POWERPC_SVR_8323               = xxx,
-#endif
-#if 0
-    POWERPC_SVR_8323E              = xxx,
-#endif
-    POWERPC_SVR_8343               = 0x80570010,
-    POWERPC_SVR_8343A              = 0x80570030,
-    POWERPC_SVR_8343E              = 0x80560010,
-    POWERPC_SVR_8343EA             = 0x80560030,
-    POWERPC_SVR_8347P              = 0x80550010, /* PBGA package */
-    POWERPC_SVR_8347T              = 0x80530010, /* TBGA package */
-    POWERPC_SVR_8347AP             = 0x80550030, /* PBGA package */
-    POWERPC_SVR_8347AT             = 0x80530030, /* TBGA package */
-    POWERPC_SVR_8347EP             = 0x80540010, /* PBGA package */
-    POWERPC_SVR_8347ET             = 0x80520010, /* TBGA package */
-    POWERPC_SVR_8347EAP            = 0x80540030, /* PBGA package */
-    POWERPC_SVR_8347EAT            = 0x80520030, /* TBGA package */
-    POWERPC_SVR_8349               = 0x80510010,
-    POWERPC_SVR_8349A              = 0x80510030,
-    POWERPC_SVR_8349E              = 0x80500010,
-    POWERPC_SVR_8349EA             = 0x80500030,
-#if 0
-    POWERPC_SVR_8358E              = xxx,
-#endif
-#if 0
-    POWERPC_SVR_8360E              = xxx,
-#endif
-#define POWERPC_SVR_E500             0x40000000
-    POWERPC_SVR_8377               = 0x80C70010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8377E              = 0x80C60010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8378               = 0x80C50010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8378E              = 0x80C40010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8379               = 0x80C30010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8379E              = 0x80C00010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8533_v10           = 0x80340010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8533_v11           = 0x80340011 | POWERPC_SVR_E500,
-    POWERPC_SVR_8533E_v10          = 0x803C0010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8533E_v11          = 0x803C0011 | POWERPC_SVR_E500,
-    POWERPC_SVR_8540_v10           = 0x80300010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8540_v20           = 0x80300020 | POWERPC_SVR_E500,
-    POWERPC_SVR_8540_v21           = 0x80300021 | POWERPC_SVR_E500,
-    POWERPC_SVR_8541_v10           = 0x80720010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8541_v11           = 0x80720011 | POWERPC_SVR_E500,
-    POWERPC_SVR_8541E_v10          = 0x807A0010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8541E_v11          = 0x807A0011 | POWERPC_SVR_E500,
-    POWERPC_SVR_8543_v10           = 0x80320010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8543_v11           = 0x80320011 | POWERPC_SVR_E500,
-    POWERPC_SVR_8543_v20           = 0x80320020 | POWERPC_SVR_E500,
-    POWERPC_SVR_8543_v21           = 0x80320021 | POWERPC_SVR_E500,
-    POWERPC_SVR_8543E_v10          = 0x803A0010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8543E_v11          = 0x803A0011 | POWERPC_SVR_E500,
-    POWERPC_SVR_8543E_v20          = 0x803A0020 | POWERPC_SVR_E500,
-    POWERPC_SVR_8543E_v21          = 0x803A0021 | POWERPC_SVR_E500,
-    POWERPC_SVR_8544_v10           = 0x80340110 | POWERPC_SVR_E500,
-    POWERPC_SVR_8544_v11           = 0x80340111 | POWERPC_SVR_E500,
-    POWERPC_SVR_8544E_v10          = 0x803C0110 | POWERPC_SVR_E500,
-    POWERPC_SVR_8544E_v11          = 0x803C0111 | POWERPC_SVR_E500,
-    POWERPC_SVR_8545_v20           = 0x80310220 | POWERPC_SVR_E500,
-    POWERPC_SVR_8545_v21           = 0x80310221 | POWERPC_SVR_E500,
-    POWERPC_SVR_8545E_v20          = 0x80390220 | POWERPC_SVR_E500,
-    POWERPC_SVR_8545E_v21          = 0x80390221 | POWERPC_SVR_E500,
-    POWERPC_SVR_8547E_v20          = 0x80390120 | POWERPC_SVR_E500,
-    POWERPC_SVR_8547E_v21          = 0x80390121 | POWERPC_SVR_E500,
-    POWERPC_SVR_8548_v10           = 0x80310010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8548_v11           = 0x80310011 | POWERPC_SVR_E500,
-    POWERPC_SVR_8548_v20           = 0x80310020 | POWERPC_SVR_E500,
-    POWERPC_SVR_8548_v21           = 0x80310021 | POWERPC_SVR_E500,
-    POWERPC_SVR_8548E_v10          = 0x80390010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8548E_v11          = 0x80390011 | POWERPC_SVR_E500,
-    POWERPC_SVR_8548E_v20          = 0x80390020 | POWERPC_SVR_E500,
-    POWERPC_SVR_8548E_v21          = 0x80390021 | POWERPC_SVR_E500,
-    POWERPC_SVR_8555_v10           = 0x80710010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8555_v11           = 0x80710011 | POWERPC_SVR_E500,
-    POWERPC_SVR_8555E_v10          = 0x80790010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8555E_v11          = 0x80790011 | POWERPC_SVR_E500,
-    POWERPC_SVR_8560_v10           = 0x80700010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8560_v20           = 0x80700020 | POWERPC_SVR_E500,
-    POWERPC_SVR_8560_v21           = 0x80700021 | POWERPC_SVR_E500,
-    POWERPC_SVR_8567               = 0x80750111 | POWERPC_SVR_E500,
-    POWERPC_SVR_8567E              = 0x807D0111 | POWERPC_SVR_E500,
-    POWERPC_SVR_8568               = 0x80750011 | POWERPC_SVR_E500,
-    POWERPC_SVR_8568E              = 0x807D0011 | POWERPC_SVR_E500,
-    POWERPC_SVR_8572               = 0x80E00010 | POWERPC_SVR_E500,
-    POWERPC_SVR_8572E              = 0x80E80010 | POWERPC_SVR_E500,
-#if 0
-    POWERPC_SVR_8610               = xxx,
-#endif
-    POWERPC_SVR_8641               = 0x80900021,
-    POWERPC_SVR_8641D              = 0x80900121,
-};
-
-/***************************************************************************/
-/* PowerPC CPU definitions                                                 */
-#define POWERPC_DEF_PREFIX(pvr, svr, type)                                  \
-    glue(glue(glue(glue(pvr, _), svr), _), type)
-#define POWERPC_DEF_SVR(_name, _desc, _pvr, _svr, _type)                    \
-    static void                                                             \
-    glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_class_init)            \
-    (ObjectClass *oc, void *data)                                           \
-    {                                                                       \
-        DeviceClass *dc = DEVICE_CLASS(oc);                                 \
-        PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);                       \
-                                                                            \
-        pcc->pvr          = _pvr;                                           \
-        pcc->svr          = _svr;                                           \
-        dc->desc          = _desc;                                          \
-    }                                                                       \
-                                                                            \
-    static const TypeInfo                                                   \
-    glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_type_info) = {         \
-        .name       = _name "-" TYPE_POWERPC_CPU,                           \
-        .parent     = stringify(_type) "-family-" TYPE_POWERPC_CPU,         \
-        .class_init =                                                       \
-            glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_class_init),   \
-    };                                                                      \
-                                                                            \
-    static void                                                             \
-    glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_register_types)(void)  \
-    {                                                                       \
-        type_register_static(                                               \
-            &glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_type_info));  \
-    }                                                                       \
-                                                                            \
-    type_init(                                                              \
-        glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_register_types))
-
-#define POWERPC_DEF(_name, _pvr, _type, _desc)                              \
-    POWERPC_DEF_SVR(_name, _desc, _pvr, POWERPC_SVR_NONE, _type)
-
-    /* Embedded PowerPC                                                      */
-    /* PowerPC 401 family                                                    */
-    POWERPC_DEF("401",           CPU_POWERPC_401,                    401,
-                "Generic PowerPC 401")
-    /* PowerPC 401 cores                                                     */
-    POWERPC_DEF("401A1",         CPU_POWERPC_401A1,                  401,
-                "PowerPC 401A1")
-    POWERPC_DEF("401B2",         CPU_POWERPC_401B2,                  401x2,
-                "PowerPC 401B2")
-#if defined(TODO)
-    POWERPC_DEF("401B3",         CPU_POWERPC_401B3,                  401x3,
-                "PowerPC 401B3")
-#endif
-    POWERPC_DEF("401C2",         CPU_POWERPC_401C2,                  401x2,
-                "PowerPC 401C2")
-    POWERPC_DEF("401D2",         CPU_POWERPC_401D2,                  401x2,
-                "PowerPC 401D2")
-    POWERPC_DEF("401E2",         CPU_POWERPC_401E2,                  401x2,
-                "PowerPC 401E2")
-    POWERPC_DEF("401F2",         CPU_POWERPC_401F2,                  401x2,
-                "PowerPC 401F2")
-    /* XXX: to be checked */
-    POWERPC_DEF("401G2",         CPU_POWERPC_401G2,                  401x2,
-                "PowerPC 401G2")
-    /* PowerPC 401 microcontrolers                                           */
-#if defined(TODO)
-    POWERPC_DEF("401GF",         CPU_POWERPC_401GF,                  401,
-                "PowerPC 401GF")
-#endif
-    POWERPC_DEF("IOP480",        CPU_POWERPC_IOP480,                 IOP480,
-                "IOP480 (401 microcontroller)")
-    POWERPC_DEF("Cobra",         CPU_POWERPC_COBRA,                  401,
-                "IBM Processor for Network Resources")
-#if defined(TODO)
-    POWERPC_DEF("Xipchip",       CPU_POWERPC_XIPCHIP,                401,
-                NULL)
-#endif
-    /* PowerPC 403 family                                                    */
-    /* PowerPC 403 microcontrolers                                           */
-    POWERPC_DEF("403GA",         CPU_POWERPC_403GA,                  403,
-                "PowerPC 403 GA")
-    POWERPC_DEF("403GB",         CPU_POWERPC_403GB,                  403,
-                "PowerPC 403 GB")
-    POWERPC_DEF("403GC",         CPU_POWERPC_403GC,                  403,
-                "PowerPC 403 GC")
-    POWERPC_DEF("403GCX",        CPU_POWERPC_403GCX,                 403GCX,
-                "PowerPC 403 GCX")
-#if defined(TODO)
-    POWERPC_DEF("403GP",         CPU_POWERPC_403GP,                  403,
-                "PowerPC 403 GP")
-#endif
-    /* PowerPC 405 family                                                    */
-    /* PowerPC 405 cores                                                     */
-#if defined(TODO)
-    POWERPC_DEF("405A3",         CPU_POWERPC_405A3,                  405,
-                "PowerPC 405 A3")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("405A4",         CPU_POWERPC_405A4,                  405,
-                "PowerPC 405 A4")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("405B3",         CPU_POWERPC_405B3,                  405,
-                "PowerPC 405 B3")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("405B4",         CPU_POWERPC_405B4,                  405,
-                "PowerPC 405 B4")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("405C3",         CPU_POWERPC_405C3,                  405,
-                "PowerPC 405 C3")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("405C4",         CPU_POWERPC_405C4,                  405,
-                "PowerPC 405 C4")
-#endif
-    POWERPC_DEF("405D2",         CPU_POWERPC_405D2,                  405,
-                "PowerPC 405 D2")
-#if defined(TODO)
-    POWERPC_DEF("405D3",         CPU_POWERPC_405D3,                  405,
-                "PowerPC 405 D3")
-#endif
-    POWERPC_DEF("405D4",         CPU_POWERPC_405D4,                  405,
-                "PowerPC 405 D4")
-#if defined(TODO)
-    POWERPC_DEF("405D5",         CPU_POWERPC_405D5,                  405,
-                "PowerPC 405 D5")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("405E4",         CPU_POWERPC_405E4,                  405,
-                "PowerPC 405 E4")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("405F4",         CPU_POWERPC_405F4,                  405,
-                "PowerPC 405 F4")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("405F5",         CPU_POWERPC_405F5,                  405,
-                "PowerPC 405 F5")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("405F6",         CPU_POWERPC_405F6,                  405,
-                "PowerPC 405 F6")
-#endif
-    /* PowerPC 405 microcontrolers                                           */
-    POWERPC_DEF("405CRa",        CPU_POWERPC_405CRa,                 405,
-                "PowerPC 405 CRa")
-    POWERPC_DEF("405CRb",        CPU_POWERPC_405CRb,                 405,
-                "PowerPC 405 CRb")
-    POWERPC_DEF("405CRc",        CPU_POWERPC_405CRc,                 405,
-                "PowerPC 405 CRc")
-    POWERPC_DEF("405EP",         CPU_POWERPC_405EP,                  405,
-                "PowerPC 405 EP")
-#if defined(TODO)
-    POWERPC_DEF("405EXr",        CPU_POWERPC_405EXr,                 405,
-                "PowerPC 405 EXr")
-#endif
-    POWERPC_DEF("405EZ",         CPU_POWERPC_405EZ,                  405,
-                "PowerPC 405 EZ")
-#if defined(TODO)
-    POWERPC_DEF("405FX",         CPU_POWERPC_405FX,                  405,
-                "PowerPC 405 FX")
-#endif
-    POWERPC_DEF("405GPa",        CPU_POWERPC_405GPa,                 405,
-                "PowerPC 405 GPa")
-    POWERPC_DEF("405GPb",        CPU_POWERPC_405GPb,                 405,
-                "PowerPC 405 GPb")
-    POWERPC_DEF("405GPc",        CPU_POWERPC_405GPc,                 405,
-                "PowerPC 405 GPc")
-    POWERPC_DEF("405GPd",        CPU_POWERPC_405GPd,                 405,
-                "PowerPC 405 GPd")
-    POWERPC_DEF("405GPR",        CPU_POWERPC_405GPR,                 405,
-                "PowerPC 405 GPR")
-#if defined(TODO)
-    POWERPC_DEF("405H",          CPU_POWERPC_405H,                   405,
-                "PowerPC 405 H")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("405L",          CPU_POWERPC_405L,                   405,
-                "PowerPC 405 L")
-#endif
-    POWERPC_DEF("405LP",         CPU_POWERPC_405LP,                  405,
-                "PowerPC 405 LP")
-#if defined(TODO)
-    POWERPC_DEF("405PM",         CPU_POWERPC_405PM,                  405,
-                "PowerPC 405 PM")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("405PS",         CPU_POWERPC_405PS,                  405,
-                "PowerPC 405 PS")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("405S",          CPU_POWERPC_405S,                   405,
-                "PowerPC 405 S")
-#endif
-    POWERPC_DEF("Npe405H",       CPU_POWERPC_NPE405H,                405,
-                "Npe405 H")
-    POWERPC_DEF("Npe405H2",      CPU_POWERPC_NPE405H2,               405,
-                "Npe405 H2")
-    POWERPC_DEF("Npe405L",       CPU_POWERPC_NPE405L,                405,
-                "Npe405 L")
-    POWERPC_DEF("Npe4GS3",       CPU_POWERPC_NPE4GS3,                405,
-                "Npe4GS3")
-#if defined(TODO)
-    POWERPC_DEF("Npcxx1",        CPU_POWERPC_NPCxx1,                 405,
-                NULL)
-#endif
-#if defined(TODO)
-    POWERPC_DEF("Npr161",        CPU_POWERPC_NPR161,                 405,
-                NULL)
-#endif
-#if defined(TODO)
-    POWERPC_DEF("LC77700",       CPU_POWERPC_LC77700,                405,
-                "PowerPC LC77700 (Sanyo)")
-#endif
-    /* PowerPC 401/403/405 based set-top-box microcontrolers                 */
-#if defined(TODO)
-    POWERPC_DEF("STB01000",      CPU_POWERPC_STB01000,               401x2,
-                "STB010000")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("STB01010",      CPU_POWERPC_STB01010,               401x2,
-                "STB01010")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("STB0210",       CPU_POWERPC_STB0210,                401x3,
-                "STB0210")
-#endif
-    POWERPC_DEF("STB03",         CPU_POWERPC_STB03,                  405,
-                "STB03xx")
-#if defined(TODO)
-    POWERPC_DEF("STB043",        CPU_POWERPC_STB043,                 405,
-                "STB043x")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("STB045",        CPU_POWERPC_STB045,                 405,
-                "STB045x")
-#endif
-    POWERPC_DEF("STB04",         CPU_POWERPC_STB04,                  405,
-                "STB04xx")
-    POWERPC_DEF("STB25",         CPU_POWERPC_STB25,                  405,
-                "STB25xx")
-#if defined(TODO)
-    POWERPC_DEF("STB130",        CPU_POWERPC_STB130,                 405,
-                "STB130")
-#endif
-    /* Xilinx PowerPC 405 cores                                              */
-    POWERPC_DEF("x2vp4",         CPU_POWERPC_X2VP4,                  405,
-                NULL)
-    POWERPC_DEF("x2vp20",        CPU_POWERPC_X2VP20,                 405,
-                NULL)
-#if defined(TODO)
-    POWERPC_DEF("zl10310",       CPU_POWERPC_ZL10310,                405,
-                "Zarlink ZL10310")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("zl10311",       CPU_POWERPC_ZL10311,                405,
-                "Zarlink ZL10311")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("zl10320",       CPU_POWERPC_ZL10320,                405,
-                "Zarlink ZL10320")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("zl10321",       CPU_POWERPC_ZL10321,                405,
-                "Zarlink ZL10321")
-#endif
-    /* PowerPC 440 family                                                    */
-#if defined(TODO_USER_ONLY)
-    POWERPC_DEF("440",           CPU_POWERPC_440,                    440GP,
-                "Generic PowerPC 440")
-#endif
-    /* PowerPC 440 cores                                                     */
-#if defined(TODO)
-    POWERPC_DEF("440A4",         CPU_POWERPC_440A4,                  440x4,
-                "PowerPC 440 A4")
-#endif
-    POWERPC_DEF("440-Xilinx",    CPU_POWERPC_440_XILINX,             440x5,
-                "PowerPC 440 Xilinx 5")
-#if defined(TODO)
-    POWERPC_DEF("440A5",         CPU_POWERPC_440A5,                  440x5,
-                "PowerPC 440 A5")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("440B4",         CPU_POWERPC_440B4,                  440x4,
-                "PowerPC 440 B4")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("440G4",         CPU_POWERPC_440G4,                  440x4,
-                "PowerPC 440 G4")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("440F5",         CPU_POWERPC_440F5,                  440x5,
-                "PowerPC 440 F5")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("440G5",         CPU_POWERPC_440G5,                  440x5,
-                "PowerPC 440 G5")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("440H4",         CPU_POWERPC_440H4,                  440x4,
-                "PowerPC 440H4")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("440H6",         CPU_POWERPC_440H6,                  440Gx5,
-                "PowerPC 440H6")
-#endif
-    /* PowerPC 440 microcontrolers                                           */
-    POWERPC_DEF("440EPa",        CPU_POWERPC_440EPa,                 440EP,
-                "PowerPC 440 EPa")
-    POWERPC_DEF("440EPb",        CPU_POWERPC_440EPb,                 440EP,
-                "PowerPC 440 EPb")
-    POWERPC_DEF("440EPX",        CPU_POWERPC_440EPX,                 440EP,
-                "PowerPC 440 EPX")
-#if defined(TODO_USER_ONLY)
-    POWERPC_DEF("440GPb",        CPU_POWERPC_440GPb,                 440GP,
-                "PowerPC 440 GPb")
-#endif
-#if defined(TODO_USER_ONLY)
-    POWERPC_DEF("440GPc",        CPU_POWERPC_440GPc,                 440GP,
-                "PowerPC 440 GPc")
-#endif
-#if defined(TODO_USER_ONLY)
-    POWERPC_DEF("440GRa",        CPU_POWERPC_440GRa,                 440x5,
-                "PowerPC 440 GRa")
-#endif
-#if defined(TODO_USER_ONLY)
-    POWERPC_DEF("440GRX",        CPU_POWERPC_440GRX,                 440x5,
-                "PowerPC 440 GRX")
-#endif
-#if defined(TODO_USER_ONLY)
-    POWERPC_DEF("440GXa",        CPU_POWERPC_440GXa,                 440EP,
-                "PowerPC 440 GXa")
-#endif
-#if defined(TODO_USER_ONLY)
-    POWERPC_DEF("440GXb",        CPU_POWERPC_440GXb,                 440EP,
-                "PowerPC 440 GXb")
-#endif
-#if defined(TODO_USER_ONLY)
-    POWERPC_DEF("440GXc",        CPU_POWERPC_440GXc,                 440EP,
-                "PowerPC 440 GXc")
-#endif
-#if defined(TODO_USER_ONLY)
-    POWERPC_DEF("440GXf",        CPU_POWERPC_440GXf,                 440EP,
-                "PowerPC 440 GXf")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("440S",          CPU_POWERPC_440S,                   440,
-                "PowerPC 440 S")
-#endif
-#if defined(TODO_USER_ONLY)
-    POWERPC_DEF("440SP",         CPU_POWERPC_440SP,                  440EP,
-                "PowerPC 440 SP")
-#endif
-#if defined(TODO_USER_ONLY)
-    POWERPC_DEF("440SP2",        CPU_POWERPC_440SP2,                 440EP,
-                "PowerPC 440 SP2")
-#endif
-#if defined(TODO_USER_ONLY)
-    POWERPC_DEF("440SPE",        CPU_POWERPC_440SPE,                 440EP,
-                "PowerPC 440 SPE")
-#endif
-    /* PowerPC 460 family                                                    */
-#if defined(TODO)
-    POWERPC_DEF("464",           CPU_POWERPC_464,                    460,
-                "Generic PowerPC 464")
-#endif
-    /* PowerPC 464 microcontrolers                                           */
-#if defined(TODO)
-    POWERPC_DEF("464H90",        CPU_POWERPC_464H90,                 460,
-                "PowerPC 464H90")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("464H90F",       CPU_POWERPC_464H90F,                460F,
-                "PowerPC 464H90F")
-#endif
-    /* Freescale embedded PowerPC cores                                      */
-    /* MPC5xx family (aka RCPU)                                              */
-#if defined(TODO_USER_ONLY)
-    POWERPC_DEF("MPC5xx",        CPU_POWERPC_MPC5xx,                 MPC5xx,
-                "Generic MPC5xx core")
-#endif
-    /* MPC8xx family (aka PowerQUICC)                                        */
-#if defined(TODO_USER_ONLY)
-    POWERPC_DEF("MPC8xx",        CPU_POWERPC_MPC8xx,                 MPC8xx,
-                "Generic MPC8xx core")
-#endif
-    /* MPC82xx family (aka PowerQUICC-II)                                    */
-    POWERPC_DEF("G2",            CPU_POWERPC_G2,                     G2,
-                "PowerPC G2 core")
-    POWERPC_DEF("G2H4",          CPU_POWERPC_G2H4,                   G2,
-                "PowerPC G2 H4 core")
-    POWERPC_DEF("G2GP",          CPU_POWERPC_G2gp,                   G2,
-                "PowerPC G2 GP core")
-    POWERPC_DEF("G2LS",          CPU_POWERPC_G2ls,                   G2,
-                "PowerPC G2 LS core")
-    POWERPC_DEF("G2HiP3",        CPU_POWERPC_G2_HIP3,                G2,
-                "PowerPC G2 HiP3 core")
-    POWERPC_DEF("G2HiP4",        CPU_POWERPC_G2_HIP4,                G2,
-                "PowerPC G2 HiP4 core")
-    POWERPC_DEF("MPC603",        CPU_POWERPC_MPC603,                 603E,
-                "PowerPC MPC603 core")
-    POWERPC_DEF("G2le",          CPU_POWERPC_G2LE,                   G2LE,
-        "PowerPC G2le core (same as G2 plus little-endian mode support)")
-    POWERPC_DEF("G2leGP",        CPU_POWERPC_G2LEgp,                 G2LE,
-                "PowerPC G2LE GP core")
-    POWERPC_DEF("G2leLS",        CPU_POWERPC_G2LEls,                 G2LE,
-                "PowerPC G2LE LS core")
-    POWERPC_DEF("G2leGP1",       CPU_POWERPC_G2LEgp1,                G2LE,
-                "PowerPC G2LE GP1 core")
-    POWERPC_DEF("G2leGP3",       CPU_POWERPC_G2LEgp3,                G2LE,
-                "PowerPC G2LE GP3 core")
-    /* PowerPC G2 microcontrollers                                           */
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5121", "MPC5121",
-                    CPU_POWERPC_MPC5121,      POWERPC_SVR_5121,      G2LE)
-#endif
-    POWERPC_DEF_SVR("MPC5200_v10", "MPC5200 v1.0",
-                    CPU_POWERPC_MPC5200_v10,  POWERPC_SVR_5200_v10,  G2LE)
-    POWERPC_DEF_SVR("MPC5200_v11", "MPC5200 v1.1",
-                    CPU_POWERPC_MPC5200_v11,  POWERPC_SVR_5200_v11,  G2LE)
-    POWERPC_DEF_SVR("MPC5200_v12", "MPC5200 v1.2",
-                    CPU_POWERPC_MPC5200_v12,  POWERPC_SVR_5200_v12,  G2LE)
-    POWERPC_DEF_SVR("MPC5200B_v20", "MPC5200B v2.0",
-                    CPU_POWERPC_MPC5200B_v20, POWERPC_SVR_5200B_v20, G2LE)
-    POWERPC_DEF_SVR("MPC5200B_v21", "MPC5200B v2.1",
-                    CPU_POWERPC_MPC5200B_v21, POWERPC_SVR_5200B_v21, G2LE)
-    /* e200 family                                                           */
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC55xx", "Generic MPC55xx core",
-                    CPU_POWERPC_MPC55xx,      POWERPC_SVR_55xx,      e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF("e200z0",        CPU_POWERPC_e200z0,                 e200,
-                "PowerPC e200z0 core")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("e200z1",        CPU_POWERPC_e200z1,                 e200,
-                "PowerPC e200z1 core")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("e200z3",        CPU_POWERPC_e200z3,                 e200,
-                "PowerPC e200z3 core")
-#endif
-    POWERPC_DEF("e200z5",        CPU_POWERPC_e200z5,                 e200,
-                "PowerPC e200z5 core")
-    POWERPC_DEF("e200z6",        CPU_POWERPC_e200z6,                 e200,
-                "PowerPC e200z6 core")
-    /* PowerPC e200 microcontrollers                                         */
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5514E", "MPC5514E",
-                    CPU_POWERPC_MPC5514E,     POWERPC_SVR_5514E,     e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5514E_v0", "MPC5514E v0",
-                    CPU_POWERPC_MPC5514E_v0,  POWERPC_SVR_5514E_v0,  e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5514E_v1", "MPC5514E v1",
-                    CPU_POWERPC_MPC5514E_v1,  POWERPC_SVR_5514E_v1,  e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5514G", "MPC5514G",
-                    CPU_POWERPC_MPC5514G,     POWERPC_SVR_5514G,     e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5514G_v0", "MPC5514G v0",
-                    CPU_POWERPC_MPC5514G_v0,  POWERPC_SVR_5514G_v0,  e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5514G_v1", "MPC5514G v1",
-                    CPU_POWERPC_MPC5514G_v1,  POWERPC_SVR_5514G_v1,  e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5515S", "MPC5515S",
-                    CPU_POWERPC_MPC5515S,     POWERPC_SVR_5515S,     e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5516E", "MPC5516E",
-                    CPU_POWERPC_MPC5516E,     POWERPC_SVR_5516E,     e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5516E_v0", "MPC5516E v0",
-                    CPU_POWERPC_MPC5516E_v0,  POWERPC_SVR_5516E_v0,  e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5516E_v1", "MPC5516E v1",
-                    CPU_POWERPC_MPC5516E_v1,  POWERPC_SVR_5516E_v1,  e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5516G", "MPC5516G",
-                    CPU_POWERPC_MPC5516G,     POWERPC_SVR_5516G,     e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5516G_v0", "MPC5516G v0",
-                    CPU_POWERPC_MPC5516G_v0,  POWERPC_SVR_5516G_v0,  e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5516G_v1", "MPC5516G v1",
-                    CPU_POWERPC_MPC5516G_v1,  POWERPC_SVR_5516G_v1,  e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5516S", "MPC5516S",
-                    CPU_POWERPC_MPC5516S,     POWERPC_SVR_5516S,     e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5533", "MPC5533",
-                    CPU_POWERPC_MPC5533,      POWERPC_SVR_5533,      e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5534", "MPC5534",
-                    CPU_POWERPC_MPC5534,      POWERPC_SVR_5534,      e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5553", "MPC5553",
-                    CPU_POWERPC_MPC5553,      POWERPC_SVR_5553,      e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5554", "MPC5554",
-                    CPU_POWERPC_MPC5554,      POWERPC_SVR_5554,      e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5561", "MPC5561",
-                    CPU_POWERPC_MPC5561,      POWERPC_SVR_5561,      e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5565", "MPC5565",
-                    CPU_POWERPC_MPC5565,      POWERPC_SVR_5565,      e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5566", "MPC5566",
-                    CPU_POWERPC_MPC5566,      POWERPC_SVR_5566,      e200)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC5567", "MPC5567",
-                    CPU_POWERPC_MPC5567,      POWERPC_SVR_5567,      e200)
-#endif
-    /* e300 family                                                           */
-    POWERPC_DEF("e300c1",        CPU_POWERPC_e300c1,                 e300,
-                "PowerPC e300c1 core")
-    POWERPC_DEF("e300c2",        CPU_POWERPC_e300c2,                 e300,
-                "PowerPC e300c2 core")
-    POWERPC_DEF("e300c3",        CPU_POWERPC_e300c3,                 e300,
-                "PowerPC e300c3 core")
-    POWERPC_DEF("e300c4",        CPU_POWERPC_e300c4,                 e300,
-                "PowerPC e300c4 core")
-    /* PowerPC e300 microcontrollers                                         */
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC8313", "MPC8313",
-                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8313,      e300)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC8313E", "MPC8313E",
-                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8313E,     e300)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC8314", "MPC8314",
-                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8314,      e300)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC8314E", "MPC8314E",
-                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8314E,     e300)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC8315", "MPC8315",
-                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8315,      e300)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC8315E", "MPC8315E",
-                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8315E,     e300)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC8321", "MPC8321",
-                    CPU_POWERPC_MPC832x,      POWERPC_SVR_8321,      e300)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC8321E", "MPC8321E",
-                    CPU_POWERPC_MPC832x,      POWERPC_SVR_8321E,     e300)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC8323", "MPC8323",
-                    CPU_POWERPC_MPC832x,      POWERPC_SVR_8323,      e300)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC8323E", "MPC8323E",
-                    CPU_POWERPC_MPC832x,      POWERPC_SVR_8323E,     e300)
-#endif
-    POWERPC_DEF_SVR("MPC8343", "MPC8343",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8343,      e300)
-    POWERPC_DEF_SVR("MPC8343A", "MPC8343A",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8343A,     e300)
-    POWERPC_DEF_SVR("MPC8343E", "MPC8343E",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8343E,     e300)
-    POWERPC_DEF_SVR("MPC8343EA", "MPC8343EA",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8343EA,    e300)
-    POWERPC_DEF_SVR("MPC8347T", "MPC8347T",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347T,     e300)
-    POWERPC_DEF_SVR("MPC8347P", "MPC8347P",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347P,     e300)
-    POWERPC_DEF_SVR("MPC8347AT", "MPC8347AT",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347AT,    e300)
-    POWERPC_DEF_SVR("MPC8347AP", "MPC8347AP",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347AP,    e300)
-    POWERPC_DEF_SVR("MPC8347ET", "MPC8347ET",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347ET,    e300)
-    POWERPC_DEF_SVR("MPC8347EP", "MPC8343EP",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EP,    e300)
-    POWERPC_DEF_SVR("MPC8347EAT", "MPC8347EAT",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EAT,   e300)
-    POWERPC_DEF_SVR("MPC8347EAP", "MPC8343EAP",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EAP,   e300)
-    POWERPC_DEF_SVR("MPC8349", "MPC8349",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8349,      e300)
-    POWERPC_DEF_SVR("MPC8349A", "MPC8349A",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8349A,     e300)
-    POWERPC_DEF_SVR("MPC8349E", "MPC8349E",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8349E,     e300)
-    POWERPC_DEF_SVR("MPC8349EA", "MPC8349EA",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8349EA,    e300)
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC8358E", "MPC8358E",
-                    CPU_POWERPC_MPC835x,      POWERPC_SVR_8358E,     e300)
-#endif
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC8360E", "MPC8360E",
-                    CPU_POWERPC_MPC836x,      POWERPC_SVR_8360E,     e300)
-#endif
-    POWERPC_DEF_SVR("MPC8377", "MPC8377",
-                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8377,      e300)
-    POWERPC_DEF_SVR("MPC8377E", "MPC8377E",
-                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8377E,     e300)
-    POWERPC_DEF_SVR("MPC8378", "MPC8378",
-                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8378,      e300)
-    POWERPC_DEF_SVR("MPC8378E", "MPC8378E",
-                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8378E,     e300)
-    POWERPC_DEF_SVR("MPC8379", "MPC8379",
-                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8379,      e300)
-    POWERPC_DEF_SVR("MPC8379E", "MPC8379E",
-                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8379E,     e300)
-    /* e500 family                                                           */
-    POWERPC_DEF("e500_v10",      CPU_POWERPC_e500v1_v10,             e500v1,
-                "PowerPC e500 v1.0 core")
-    POWERPC_DEF("e500_v20",      CPU_POWERPC_e500v1_v20,             e500v1,
-                "PowerPC e500 v2.0 core")
-    POWERPC_DEF("e500v2_v10",    CPU_POWERPC_e500v2_v10,             e500v2,
-                "PowerPC e500v2 v1.0 core")
-    POWERPC_DEF("e500v2_v20",    CPU_POWERPC_e500v2_v20,             e500v2,
-                "PowerPC e500v2 v2.0 core")
-    POWERPC_DEF("e500v2_v21",    CPU_POWERPC_e500v2_v21,             e500v2,
-                "PowerPC e500v2 v2.1 core")
-    POWERPC_DEF("e500v2_v22",    CPU_POWERPC_e500v2_v22,             e500v2,
-                "PowerPC e500v2 v2.2 core")
-    POWERPC_DEF("e500v2_v30",    CPU_POWERPC_e500v2_v30,             e500v2,
-                "PowerPC e500v2 v3.0 core")
-    POWERPC_DEF_SVR("e500mc", "e500mc",
-                    CPU_POWERPC_e500mc,       POWERPC_SVR_E500,      e500mc)
-#ifdef TARGET_PPC64
-    POWERPC_DEF_SVR("e5500", "e5500",
-                    CPU_POWERPC_e5500,        POWERPC_SVR_E500,      e5500)
-#endif
-    /* PowerPC e500 microcontrollers                                         */
-    POWERPC_DEF_SVR("MPC8533_v10", "MPC8533 v1.0",
-                    CPU_POWERPC_MPC8533_v10,  POWERPC_SVR_8533_v10,  e500v2)
-    POWERPC_DEF_SVR("MPC8533_v11", "MPC8533 v1.1",
-                    CPU_POWERPC_MPC8533_v11,  POWERPC_SVR_8533_v11,  e500v2)
-    POWERPC_DEF_SVR("MPC8533E_v10", "MPC8533E v1.0",
-                    CPU_POWERPC_MPC8533E_v10, POWERPC_SVR_8533E_v10, e500v2)
-    POWERPC_DEF_SVR("MPC8533E_v11", "MPC8533E v1.1",
-                    CPU_POWERPC_MPC8533E_v11, POWERPC_SVR_8533E_v11, e500v2)
-    POWERPC_DEF_SVR("MPC8540_v10", "MPC8540 v1.0",
-                    CPU_POWERPC_MPC8540_v10,  POWERPC_SVR_8540_v10,  e500v1)
-    POWERPC_DEF_SVR("MPC8540_v20", "MPC8540 v2.0",
-                    CPU_POWERPC_MPC8540_v20,  POWERPC_SVR_8540_v20,  e500v1)
-    POWERPC_DEF_SVR("MPC8540_v21", "MPC8540 v2.1",
-                    CPU_POWERPC_MPC8540_v21,  POWERPC_SVR_8540_v21,  e500v1)
-    POWERPC_DEF_SVR("MPC8541_v10", "MPC8541 v1.0",
-                    CPU_POWERPC_MPC8541_v10,  POWERPC_SVR_8541_v10,  e500v1)
-    POWERPC_DEF_SVR("MPC8541_v11", "MPC8541 v1.1",
-                    CPU_POWERPC_MPC8541_v11,  POWERPC_SVR_8541_v11,  e500v1)
-    POWERPC_DEF_SVR("MPC8541E_v10", "MPC8541E v1.0",
-                    CPU_POWERPC_MPC8541E_v10, POWERPC_SVR_8541E_v10, e500v1)
-    POWERPC_DEF_SVR("MPC8541E_v11", "MPC8541E v1.1",
-                    CPU_POWERPC_MPC8541E_v11, POWERPC_SVR_8541E_v11, e500v1)
-    POWERPC_DEF_SVR("MPC8543_v10", "MPC8543 v1.0",
-                    CPU_POWERPC_MPC8543_v10,  POWERPC_SVR_8543_v10,  e500v2)
-    POWERPC_DEF_SVR("MPC8543_v11", "MPC8543 v1.1",
-                    CPU_POWERPC_MPC8543_v11,  POWERPC_SVR_8543_v11,  e500v2)
-    POWERPC_DEF_SVR("MPC8543_v20", "MPC8543 v2.0",
-                    CPU_POWERPC_MPC8543_v20,  POWERPC_SVR_8543_v20,  e500v2)
-    POWERPC_DEF_SVR("MPC8543_v21", "MPC8543 v2.1",
-                    CPU_POWERPC_MPC8543_v21,  POWERPC_SVR_8543_v21,  e500v2)
-    POWERPC_DEF_SVR("MPC8543E_v10", "MPC8543E v1.0",
-                    CPU_POWERPC_MPC8543E_v10, POWERPC_SVR_8543E_v10, e500v2)
-    POWERPC_DEF_SVR("MPC8543E_v11", "MPC8543E v1.1",
-                    CPU_POWERPC_MPC8543E_v11, POWERPC_SVR_8543E_v11, e500v2)
-    POWERPC_DEF_SVR("MPC8543E_v20", "MPC8543E v2.0",
-                    CPU_POWERPC_MPC8543E_v20, POWERPC_SVR_8543E_v20, e500v2)
-    POWERPC_DEF_SVR("MPC8543E_v21", "MPC8543E v2.1",
-                    CPU_POWERPC_MPC8543E_v21, POWERPC_SVR_8543E_v21, e500v2)
-    POWERPC_DEF_SVR("MPC8544_v10", "MPC8544 v1.0",
-                    CPU_POWERPC_MPC8544_v10,  POWERPC_SVR_8544_v10,  e500v2)
-    POWERPC_DEF_SVR("MPC8544_v11", "MPC8544 v1.1",
-                    CPU_POWERPC_MPC8544_v11,  POWERPC_SVR_8544_v11,  e500v2)
-    POWERPC_DEF_SVR("MPC8544E_v10", "MPC8544E v1.0",
-                    CPU_POWERPC_MPC8544E_v10, POWERPC_SVR_8544E_v10, e500v2)
-    POWERPC_DEF_SVR("MPC8544E_v11", "MPC8544E v1.1",
-                    CPU_POWERPC_MPC8544E_v11, POWERPC_SVR_8544E_v11, e500v2)
-    POWERPC_DEF_SVR("MPC8545_v20", "MPC8545 v2.0",
-                    CPU_POWERPC_MPC8545_v20,  POWERPC_SVR_8545_v20,  e500v2)
-    POWERPC_DEF_SVR("MPC8545_v21", "MPC8545 v2.1",
-                    CPU_POWERPC_MPC8545_v21,  POWERPC_SVR_8545_v21,  e500v2)
-    POWERPC_DEF_SVR("MPC8545E_v20", "MPC8545E v2.0",
-                    CPU_POWERPC_MPC8545E_v20, POWERPC_SVR_8545E_v20, e500v2)
-    POWERPC_DEF_SVR("MPC8545E_v21", "MPC8545E v2.1",
-                    CPU_POWERPC_MPC8545E_v21, POWERPC_SVR_8545E_v21, e500v2)
-    POWERPC_DEF_SVR("MPC8547E_v20", "MPC8547E v2.0",
-                    CPU_POWERPC_MPC8547E_v20, POWERPC_SVR_8547E_v20, e500v2)
-    POWERPC_DEF_SVR("MPC8547E_v21", "MPC8547E v2.1",
-                    CPU_POWERPC_MPC8547E_v21, POWERPC_SVR_8547E_v21, e500v2)
-    POWERPC_DEF_SVR("MPC8548_v10", "MPC8548 v1.0",
-                    CPU_POWERPC_MPC8548_v10,  POWERPC_SVR_8548_v10,  e500v2)
-    POWERPC_DEF_SVR("MPC8548_v11", "MPC8548 v1.1",
-                    CPU_POWERPC_MPC8548_v11,  POWERPC_SVR_8548_v11,  e500v2)
-    POWERPC_DEF_SVR("MPC8548_v20", "MPC8548 v2.0",
-                    CPU_POWERPC_MPC8548_v20,  POWERPC_SVR_8548_v20,  e500v2)
-    POWERPC_DEF_SVR("MPC8548_v21", "MPC8548 v2.1",
-                    CPU_POWERPC_MPC8548_v21,  POWERPC_SVR_8548_v21,  e500v2)
-    POWERPC_DEF_SVR("MPC8548E_v10", "MPC8548E v1.0",
-                    CPU_POWERPC_MPC8548E_v10, POWERPC_SVR_8548E_v10, e500v2)
-    POWERPC_DEF_SVR("MPC8548E_v11", "MPC8548E v1.1",
-                    CPU_POWERPC_MPC8548E_v11, POWERPC_SVR_8548E_v11, e500v2)
-    POWERPC_DEF_SVR("MPC8548E_v20", "MPC8548E v2.0",
-                    CPU_POWERPC_MPC8548E_v20, POWERPC_SVR_8548E_v20, e500v2)
-    POWERPC_DEF_SVR("MPC8548E_v21", "MPC8548E v2.1",
-                    CPU_POWERPC_MPC8548E_v21, POWERPC_SVR_8548E_v21, e500v2)
-    POWERPC_DEF_SVR("MPC8555_v10", "MPC8555 v1.0",
-                    CPU_POWERPC_MPC8555_v10,  POWERPC_SVR_8555_v10,  e500v2)
-    POWERPC_DEF_SVR("MPC8555_v11", "MPC8555 v1.1",
-                    CPU_POWERPC_MPC8555_v11,  POWERPC_SVR_8555_v11,  e500v2)
-    POWERPC_DEF_SVR("MPC8555E_v10", "MPC8555E v1.0",
-                    CPU_POWERPC_MPC8555E_v10, POWERPC_SVR_8555E_v10, e500v2)
-    POWERPC_DEF_SVR("MPC8555E_v11", "MPC8555E v1.1",
-                    CPU_POWERPC_MPC8555E_v11, POWERPC_SVR_8555E_v11, e500v2)
-    POWERPC_DEF_SVR("MPC8560_v10", "MPC8560 v1.0",
-                    CPU_POWERPC_MPC8560_v10,  POWERPC_SVR_8560_v10,  e500v2)
-    POWERPC_DEF_SVR("MPC8560_v20", "MPC8560 v2.0",
-                    CPU_POWERPC_MPC8560_v20,  POWERPC_SVR_8560_v20,  e500v2)
-    POWERPC_DEF_SVR("MPC8560_v21", "MPC8560 v2.1",
-                    CPU_POWERPC_MPC8560_v21,  POWERPC_SVR_8560_v21,  e500v2)
-    POWERPC_DEF_SVR("MPC8567", "MPC8567",
-                    CPU_POWERPC_MPC8567,      POWERPC_SVR_8567,      e500v2)
-    POWERPC_DEF_SVR("MPC8567E", "MPC8567E",
-                    CPU_POWERPC_MPC8567E,     POWERPC_SVR_8567E,     e500v2)
-    POWERPC_DEF_SVR("MPC8568", "MPC8568",
-                    CPU_POWERPC_MPC8568,      POWERPC_SVR_8568,      e500v2)
-    POWERPC_DEF_SVR("MPC8568E", "MPC8568E",
-                    CPU_POWERPC_MPC8568E,     POWERPC_SVR_8568E,     e500v2)
-    POWERPC_DEF_SVR("MPC8572", "MPC8572",
-                    CPU_POWERPC_MPC8572,      POWERPC_SVR_8572,      e500v2)
-    POWERPC_DEF_SVR("MPC8572E", "MPC8572E",
-                    CPU_POWERPC_MPC8572E,     POWERPC_SVR_8572E,     e500v2)
-    /* e600 family                                                           */
-    POWERPC_DEF("e600",          CPU_POWERPC_e600,                   7400,
-                "PowerPC e600 core")
-    /* PowerPC e600 microcontrollers                                         */
-#if defined(TODO)
-    POWERPC_DEF_SVR("MPC8610", "MPC8610",
-                    CPU_POWERPC_MPC8610,      POWERPC_SVR_8610,      7400)
-#endif
-    POWERPC_DEF_SVR("MPC8641", "MPC8641",
-                    CPU_POWERPC_MPC8641,      POWERPC_SVR_8641,      7400)
-    POWERPC_DEF_SVR("MPC8641D", "MPC8641D",
-                    CPU_POWERPC_MPC8641D,     POWERPC_SVR_8641D,     7400)
-    /* 32 bits "classic" PowerPC                                             */
-    /* PowerPC 6xx family                                                    */
-    POWERPC_DEF("601_v0",        CPU_POWERPC_601_v0,                 601,
-                "PowerPC 601v0")
-    POWERPC_DEF("601_v1",        CPU_POWERPC_601_v1,                 601,
-                "PowerPC 601v1")
-    POWERPC_DEF("601_v2",        CPU_POWERPC_601_v2,                 601v,
-                "PowerPC 601v2")
-    POWERPC_DEF("602",           CPU_POWERPC_602,                    602,
-                "PowerPC 602")
-    POWERPC_DEF("603",           CPU_POWERPC_603,                    603,
-                "PowerPC 603")
-    POWERPC_DEF("603e_v1.1",     CPU_POWERPC_603E_v11,               603E,
-                "PowerPC 603e v1.1")
-    POWERPC_DEF("603e_v1.2",     CPU_POWERPC_603E_v12,               603E,
-                "PowerPC 603e v1.2")
-    POWERPC_DEF("603e_v1.3",     CPU_POWERPC_603E_v13,               603E,
-                "PowerPC 603e v1.3")
-    POWERPC_DEF("603e_v1.4",     CPU_POWERPC_603E_v14,               603E,
-                "PowerPC 603e v1.4")
-    POWERPC_DEF("603e_v2.2",     CPU_POWERPC_603E_v22,               603E,
-                "PowerPC 603e v2.2")
-    POWERPC_DEF("603e_v3",       CPU_POWERPC_603E_v3,                603E,
-                "PowerPC 603e v3")
-    POWERPC_DEF("603e_v4",       CPU_POWERPC_603E_v4,                603E,
-                "PowerPC 603e v4")
-    POWERPC_DEF("603e_v4.1",     CPU_POWERPC_603E_v41,               603E,
-                "PowerPC 603e v4.1")
-    POWERPC_DEF("603e7",         CPU_POWERPC_603E7,                  603E,
-                "PowerPC 603e (aka PID7)")
-    POWERPC_DEF("603e7t",        CPU_POWERPC_603E7t,                 603E,
-                "PowerPC 603e7t")
-    POWERPC_DEF("603e7v",        CPU_POWERPC_603E7v,                 603E,
-                "PowerPC 603e7v")
-    POWERPC_DEF("603e7v1",       CPU_POWERPC_603E7v1,                603E,
-                "PowerPC 603e7v1")
-    POWERPC_DEF("603e7v2",       CPU_POWERPC_603E7v2,                603E,
-                "PowerPC 603e7v2")
-    POWERPC_DEF("603p",          CPU_POWERPC_603P,                   603E,
-                "PowerPC 603p (aka PID7v)")
-    POWERPC_DEF("604",           CPU_POWERPC_604,                    604,
-                "PowerPC 604")
-    POWERPC_DEF("604e_v1.0",     CPU_POWERPC_604E_v10,               604E,
-                "PowerPC 604e v1.0")
-    POWERPC_DEF("604e_v2.2",     CPU_POWERPC_604E_v22,               604E,
-                "PowerPC 604e v2.2")
-    POWERPC_DEF("604e_v2.4",     CPU_POWERPC_604E_v24,               604E,
-                "PowerPC 604e v2.4")
-    POWERPC_DEF("604r",          CPU_POWERPC_604R,                   604E,
-                "PowerPC 604r (aka PIDA)")
-#if defined(TODO)
-    POWERPC_DEF("604ev",         CPU_POWERPC_604EV,                  604E,
-                "PowerPC 604ev")
-#endif
-    /* PowerPC 7xx family                                                    */
-    POWERPC_DEF("740_v1.0",      CPU_POWERPC_7x0_v10,                740,
-                "PowerPC 740 v1.0 (G3)")
-    POWERPC_DEF("750_v1.0",      CPU_POWERPC_7x0_v10,                750,
-                "PowerPC 750 v1.0 (G3)")
-    POWERPC_DEF("740_v2.0",      CPU_POWERPC_7x0_v20,                740,
-                "PowerPC 740 v2.0 (G3)")
-    POWERPC_DEF("750_v2.0",      CPU_POWERPC_7x0_v20,                750,
-                "PowerPC 750 v2.0 (G3)")
-    POWERPC_DEF("740_v2.1",      CPU_POWERPC_7x0_v21,                740,
-                "PowerPC 740 v2.1 (G3)")
-    POWERPC_DEF("750_v2.1",      CPU_POWERPC_7x0_v21,                750,
-                "PowerPC 750 v2.1 (G3)")
-    POWERPC_DEF("740_v2.2",      CPU_POWERPC_7x0_v22,                740,
-                "PowerPC 740 v2.2 (G3)")
-    POWERPC_DEF("750_v2.2",      CPU_POWERPC_7x0_v22,                750,
-                "PowerPC 750 v2.2 (G3)")
-    POWERPC_DEF("740_v3.0",      CPU_POWERPC_7x0_v30,                740,
-                "PowerPC 740 v3.0 (G3)")
-    POWERPC_DEF("750_v3.0",      CPU_POWERPC_7x0_v30,                750,
-                "PowerPC 750 v3.0 (G3)")
-    POWERPC_DEF("740_v3.1",      CPU_POWERPC_7x0_v31,                740,
-                "PowerPC 740 v3.1 (G3)")
-    POWERPC_DEF("750_v3.1",      CPU_POWERPC_7x0_v31,                750,
-                "PowerPC 750 v3.1 (G3)")
-    POWERPC_DEF("740e",          CPU_POWERPC_740E,                   740,
-                "PowerPC 740E (G3)")
-    POWERPC_DEF("750e",          CPU_POWERPC_750E,                   750,
-                "PowerPC 750E (G3)")
-    POWERPC_DEF("740p",          CPU_POWERPC_7x0P,                   740,
-                "PowerPC 740P (G3)")
-    POWERPC_DEF("750p",          CPU_POWERPC_7x0P,                   750,
-                "PowerPC 750P (G3)")
-    POWERPC_DEF("750cl_v1.0",    CPU_POWERPC_750CL_v10,              750cl,
-                "PowerPC 750CL v1.0")
-    POWERPC_DEF("750cl_v2.0",    CPU_POWERPC_750CL_v20,              750cl,
-                "PowerPC 750CL v2.0")
-    POWERPC_DEF("750cx_v1.0",    CPU_POWERPC_750CX_v10,              750cx,
-                "PowerPC 750CX v1.0 (G3 embedded)")
-    POWERPC_DEF("750cx_v2.0",    CPU_POWERPC_750CX_v20,              750cx,
-                "PowerPC 750CX v2.1 (G3 embedded)")
-    POWERPC_DEF("750cx_v2.1",    CPU_POWERPC_750CX_v21,              750cx,
-                "PowerPC 750CX v2.1 (G3 embedded)")
-    POWERPC_DEF("750cx_v2.2",    CPU_POWERPC_750CX_v22,              750cx,
-                "PowerPC 750CX v2.2 (G3 embedded)")
-    POWERPC_DEF("750cxe_v2.1",   CPU_POWERPC_750CXE_v21,             750cx,
-                "PowerPC 750CXe v2.1 (G3 embedded)")
-    POWERPC_DEF("750cxe_v2.2",   CPU_POWERPC_750CXE_v22,             750cx,
-                "PowerPC 750CXe v2.2 (G3 embedded)")
-    POWERPC_DEF("750cxe_v2.3",   CPU_POWERPC_750CXE_v23,             750cx,
-                "PowerPC 750CXe v2.3 (G3 embedded)")
-    POWERPC_DEF("750cxe_v2.4",   CPU_POWERPC_750CXE_v24,             750cx,
-                "PowerPC 750CXe v2.4 (G3 embedded)")
-    POWERPC_DEF("750cxe_v2.4b",  CPU_POWERPC_750CXE_v24b,            750cx,
-                "PowerPC 750CXe v2.4b (G3 embedded)")
-    POWERPC_DEF("750cxe_v3.0",   CPU_POWERPC_750CXE_v30,             750cx,
-                "PowerPC 750CXe v3.0 (G3 embedded)")
-    POWERPC_DEF("750cxe_v3.1",   CPU_POWERPC_750CXE_v31,             750cx,
-                "PowerPC 750CXe v3.1 (G3 embedded)")
-    POWERPC_DEF("750cxe_v3.1b",  CPU_POWERPC_750CXE_v31b,            750cx,
-                "PowerPC 750CXe v3.1b (G3 embedded)")
-    POWERPC_DEF("750cxr",        CPU_POWERPC_750CXR,                 750cx,
-                "PowerPC 750CXr (G3 embedded)")
-    POWERPC_DEF("750fl",         CPU_POWERPC_750FL,                  750fx,
-                "PowerPC 750FL (G3 embedded)")
-    POWERPC_DEF("750fx_v1.0",    CPU_POWERPC_750FX_v10,              750fx,
-                "PowerPC 750FX v1.0 (G3 embedded)")
-    POWERPC_DEF("750fx_v2.0",    CPU_POWERPC_750FX_v20,              750fx,
-                "PowerPC 750FX v2.0 (G3 embedded)")
-    POWERPC_DEF("750fx_v2.1",    CPU_POWERPC_750FX_v21,              750fx,
-                "PowerPC 750FX v2.1 (G3 embedded)")
-    POWERPC_DEF("750fx_v2.2",    CPU_POWERPC_750FX_v22,              750fx,
-                "PowerPC 750FX v2.2 (G3 embedded)")
-    POWERPC_DEF("750fx_v2.3",    CPU_POWERPC_750FX_v23,              750fx,
-                "PowerPC 750FX v2.3 (G3 embedded)")
-    POWERPC_DEF("750gl",         CPU_POWERPC_750GL,                  750gx,
-                "PowerPC 750GL (G3 embedded)")
-    POWERPC_DEF("750gx_v1.0",    CPU_POWERPC_750GX_v10,              750gx,
-                "PowerPC 750GX v1.0 (G3 embedded)")
-    POWERPC_DEF("750gx_v1.1",    CPU_POWERPC_750GX_v11,              750gx,
-                "PowerPC 750GX v1.1 (G3 embedded)")
-    POWERPC_DEF("750gx_v1.2",    CPU_POWERPC_750GX_v12,              750gx,
-                "PowerPC 750GX v1.2 (G3 embedded)")
-    POWERPC_DEF("750l_v2.0",     CPU_POWERPC_750L_v20,               750,
-                "PowerPC 750L v2.0 (G3 embedded)")
-    POWERPC_DEF("750l_v2.1",     CPU_POWERPC_750L_v21,               750,
-                "PowerPC 750L v2.1 (G3 embedded)")
-    POWERPC_DEF("750l_v2.2",     CPU_POWERPC_750L_v22,               750,
-                "PowerPC 750L v2.2 (G3 embedded)")
-    POWERPC_DEF("750l_v3.0",     CPU_POWERPC_750L_v30,               750,
-                "PowerPC 750L v3.0 (G3 embedded)")
-    POWERPC_DEF("750l_v3.2",     CPU_POWERPC_750L_v32,               750,
-                "PowerPC 750L v3.2 (G3 embedded)")
-    POWERPC_DEF("745_v1.0",      CPU_POWERPC_7x5_v10,                745,
-                "PowerPC 745 v1.0")
-    POWERPC_DEF("755_v1.0",      CPU_POWERPC_7x5_v10,                755,
-                "PowerPC 755 v1.0")
-    POWERPC_DEF("745_v1.1",      CPU_POWERPC_7x5_v11,                745,
-                "PowerPC 745 v1.1")
-    POWERPC_DEF("755_v1.1",      CPU_POWERPC_7x5_v11,                755,
-                "PowerPC 755 v1.1")
-    POWERPC_DEF("745_v2.0",      CPU_POWERPC_7x5_v20,                745,
-                "PowerPC 745 v2.0")
-    POWERPC_DEF("755_v2.0",      CPU_POWERPC_7x5_v20,                755,
-                "PowerPC 755 v2.0")
-    POWERPC_DEF("745_v2.1",      CPU_POWERPC_7x5_v21,                745,
-                "PowerPC 745 v2.1")
-    POWERPC_DEF("755_v2.1",      CPU_POWERPC_7x5_v21,                755,
-                "PowerPC 755 v2.1")
-    POWERPC_DEF("745_v2.2",      CPU_POWERPC_7x5_v22,                745,
-                "PowerPC 745 v2.2")
-    POWERPC_DEF("755_v2.2",      CPU_POWERPC_7x5_v22,                755,
-                "PowerPC 755 v2.2")
-    POWERPC_DEF("745_v2.3",      CPU_POWERPC_7x5_v23,                745,
-                "PowerPC 745 v2.3")
-    POWERPC_DEF("755_v2.3",      CPU_POWERPC_7x5_v23,                755,
-                "PowerPC 755 v2.3")
-    POWERPC_DEF("745_v2.4",      CPU_POWERPC_7x5_v24,                745,
-                "PowerPC 745 v2.4")
-    POWERPC_DEF("755_v2.4",      CPU_POWERPC_7x5_v24,                755,
-                "PowerPC 755 v2.4")
-    POWERPC_DEF("745_v2.5",      CPU_POWERPC_7x5_v25,                745,
-                "PowerPC 745 v2.5")
-    POWERPC_DEF("755_v2.5",      CPU_POWERPC_7x5_v25,                755,
-                "PowerPC 755 v2.5")
-    POWERPC_DEF("745_v2.6",      CPU_POWERPC_7x5_v26,                745,
-                "PowerPC 745 v2.6")
-    POWERPC_DEF("755_v2.6",      CPU_POWERPC_7x5_v26,                755,
-                "PowerPC 755 v2.6")
-    POWERPC_DEF("745_v2.7",      CPU_POWERPC_7x5_v27,                745,
-                "PowerPC 745 v2.7")
-    POWERPC_DEF("755_v2.7",      CPU_POWERPC_7x5_v27,                755,
-                "PowerPC 755 v2.7")
-    POWERPC_DEF("745_v2.8",      CPU_POWERPC_7x5_v28,                745,
-                "PowerPC 745 v2.8")
-    POWERPC_DEF("755_v2.8",      CPU_POWERPC_7x5_v28,                755,
-                "PowerPC 755 v2.8")
-#if defined(TODO)
-    POWERPC_DEF("745p",          CPU_POWERPC_7x5P,                   745,
-                "PowerPC 745P (G3)")
-    POWERPC_DEF("755p",          CPU_POWERPC_7x5P,                   755,
-                "PowerPC 755P (G3)")
-#endif
-    /* PowerPC 74xx family                                                   */
-    POWERPC_DEF("7400_v1.0",     CPU_POWERPC_7400_v10,               7400,
-                "PowerPC 7400 v1.0 (G4)")
-    POWERPC_DEF("7400_v1.1",     CPU_POWERPC_7400_v11,               7400,
-                "PowerPC 7400 v1.1 (G4)")
-    POWERPC_DEF("7400_v2.0",     CPU_POWERPC_7400_v20,               7400,
-                "PowerPC 7400 v2.0 (G4)")
-    POWERPC_DEF("7400_v2.1",     CPU_POWERPC_7400_v21,               7400,
-                "PowerPC 7400 v2.1 (G4)")
-    POWERPC_DEF("7400_v2.2",     CPU_POWERPC_7400_v22,               7400,
-                "PowerPC 7400 v2.2 (G4)")
-    POWERPC_DEF("7400_v2.6",     CPU_POWERPC_7400_v26,               7400,
-                "PowerPC 7400 v2.6 (G4)")
-    POWERPC_DEF("7400_v2.7",     CPU_POWERPC_7400_v27,               7400,
-                "PowerPC 7400 v2.7 (G4)")
-    POWERPC_DEF("7400_v2.8",     CPU_POWERPC_7400_v28,               7400,
-                "PowerPC 7400 v2.8 (G4)")
-    POWERPC_DEF("7400_v2.9",     CPU_POWERPC_7400_v29,               7400,
-                "PowerPC 7400 v2.9 (G4)")
-    POWERPC_DEF("7410_v1.0",     CPU_POWERPC_7410_v10,               7410,
-                "PowerPC 7410 v1.0 (G4)")
-    POWERPC_DEF("7410_v1.1",     CPU_POWERPC_7410_v11,               7410,
-                "PowerPC 7410 v1.1 (G4)")
-    POWERPC_DEF("7410_v1.2",     CPU_POWERPC_7410_v12,               7410,
-                "PowerPC 7410 v1.2 (G4)")
-    POWERPC_DEF("7410_v1.3",     CPU_POWERPC_7410_v13,               7410,
-                "PowerPC 7410 v1.3 (G4)")
-    POWERPC_DEF("7410_v1.4",     CPU_POWERPC_7410_v14,               7410,
-                "PowerPC 7410 v1.4 (G4)")
-    POWERPC_DEF("7448_v1.0",     CPU_POWERPC_7448_v10,               7400,
-                "PowerPC 7448 v1.0 (G4)")
-    POWERPC_DEF("7448_v1.1",     CPU_POWERPC_7448_v11,               7400,
-                "PowerPC 7448 v1.1 (G4)")
-    POWERPC_DEF("7448_v2.0",     CPU_POWERPC_7448_v20,               7400,
-                "PowerPC 7448 v2.0 (G4)")
-    POWERPC_DEF("7448_v2.1",     CPU_POWERPC_7448_v21,               7400,
-                "PowerPC 7448 v2.1 (G4)")
-    POWERPC_DEF("7450_v1.0",     CPU_POWERPC_7450_v10,               7450,
-                "PowerPC 7450 v1.0 (G4)")
-    POWERPC_DEF("7450_v1.1",     CPU_POWERPC_7450_v11,               7450,
-                "PowerPC 7450 v1.1 (G4)")
-    POWERPC_DEF("7450_v1.2",     CPU_POWERPC_7450_v12,               7450,
-                "PowerPC 7450 v1.2 (G4)")
-    POWERPC_DEF("7450_v2.0",     CPU_POWERPC_7450_v20,               7450,
-                "PowerPC 7450 v2.0 (G4)")
-    POWERPC_DEF("7450_v2.1",     CPU_POWERPC_7450_v21,               7450,
-                "PowerPC 7450 v2.1 (G4)")
-    POWERPC_DEF("7441_v2.1",     CPU_POWERPC_7450_v21,               7440,
-                "PowerPC 7441 v2.1 (G4)")
-    POWERPC_DEF("7441_v2.3",     CPU_POWERPC_74x1_v23,               7440,
-                "PowerPC 7441 v2.3 (G4)")
-    POWERPC_DEF("7451_v2.3",     CPU_POWERPC_74x1_v23,               7450,
-                "PowerPC 7451 v2.3 (G4)")
-    POWERPC_DEF("7441_v2.10",    CPU_POWERPC_74x1_v210,              7440,
-                "PowerPC 7441 v2.10 (G4)")
-    POWERPC_DEF("7451_v2.10",    CPU_POWERPC_74x1_v210,              7450,
-                "PowerPC 7451 v2.10 (G4)")
-    POWERPC_DEF("7445_v1.0",     CPU_POWERPC_74x5_v10,               7445,
-                "PowerPC 7445 v1.0 (G4)")
-    POWERPC_DEF("7455_v1.0",     CPU_POWERPC_74x5_v10,               7455,
-                "PowerPC 7455 v1.0 (G4)")
-    POWERPC_DEF("7445_v2.1",     CPU_POWERPC_74x5_v21,               7445,
-                "PowerPC 7445 v2.1 (G4)")
-    POWERPC_DEF("7455_v2.1",     CPU_POWERPC_74x5_v21,               7455,
-                "PowerPC 7455 v2.1 (G4)")
-    POWERPC_DEF("7445_v3.2",     CPU_POWERPC_74x5_v32,               7445,
-                "PowerPC 7445 v3.2 (G4)")
-    POWERPC_DEF("7455_v3.2",     CPU_POWERPC_74x5_v32,               7455,
-                "PowerPC 7455 v3.2 (G4)")
-    POWERPC_DEF("7445_v3.3",     CPU_POWERPC_74x5_v33,               7445,
-                "PowerPC 7445 v3.3 (G4)")
-    POWERPC_DEF("7455_v3.3",     CPU_POWERPC_74x5_v33,               7455,
-                "PowerPC 7455 v3.3 (G4)")
-    POWERPC_DEF("7445_v3.4",     CPU_POWERPC_74x5_v34,               7445,
-                "PowerPC 7445 v3.4 (G4)")
-    POWERPC_DEF("7455_v3.4",     CPU_POWERPC_74x5_v34,               7455,
-                "PowerPC 7455 v3.4 (G4)")
-    POWERPC_DEF("7447_v1.0",     CPU_POWERPC_74x7_v10,               7445,
-                "PowerPC 7447 v1.0 (G4)")
-    POWERPC_DEF("7457_v1.0",     CPU_POWERPC_74x7_v10,               7455,
-                "PowerPC 7457 v1.0 (G4)")
-    POWERPC_DEF("7447_v1.1",     CPU_POWERPC_74x7_v11,               7445,
-                "PowerPC 7447 v1.1 (G4)")
-    POWERPC_DEF("7457_v1.1",     CPU_POWERPC_74x7_v11,               7455,
-                "PowerPC 7457 v1.1 (G4)")
-    POWERPC_DEF("7457_v1.2",     CPU_POWERPC_74x7_v12,               7455,
-                "PowerPC 7457 v1.2 (G4)")
-    POWERPC_DEF("7447A_v1.0",    CPU_POWERPC_74x7A_v10,              7445,
-                "PowerPC 7447A v1.0 (G4)")
-    POWERPC_DEF("7457A_v1.0",    CPU_POWERPC_74x7A_v10,              7455,
-                "PowerPC 7457A v1.0 (G4)")
-    POWERPC_DEF("7447A_v1.1",    CPU_POWERPC_74x7A_v11,              7445,
-                "PowerPC 7447A v1.1 (G4)")
-    POWERPC_DEF("7457A_v1.1",    CPU_POWERPC_74x7A_v11,              7455,
-                "PowerPC 7457A v1.1 (G4)")
-    POWERPC_DEF("7447A_v1.2",    CPU_POWERPC_74x7A_v12,              7445,
-                "PowerPC 7447A v1.2 (G4)")
-    POWERPC_DEF("7457A_v1.2",    CPU_POWERPC_74x7A_v12,              7455,
-                "PowerPC 7457A v1.2 (G4)")
-    /* 64 bits PowerPC                                                       */
-#if defined (TARGET_PPC64)
-    POWERPC_DEF("620",           CPU_POWERPC_620,                    620,
-                "PowerPC 620")
-#if defined(TODO)
-    POWERPC_DEF("630",           CPU_POWERPC_630,                    630,
-                "PowerPC 630 (POWER3)")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("631",           CPU_POWERPC_631,                    631,
-                "PowerPC 631 (Power 3+)")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("POWER4",        CPU_POWERPC_POWER4,                 POWER4,
-                "POWER4")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("POWER4+",       CPU_POWERPC_POWER4P,                POWER4P,
-                "POWER4p")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("POWER5",        CPU_POWERPC_POWER5,                 POWER5,
-                "POWER5")
-    POWERPC_DEF("POWER5gr",      CPU_POWERPC_POWER5GR,               POWER5,
-                "POWER5GR")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("POWER5+",       CPU_POWERPC_POWER5P,                POWER5P,
-                "POWER5+")
-    POWERPC_DEF("POWER5gs",      CPU_POWERPC_POWER5GS,               POWER5P,
-                "POWER5GS")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("POWER6",        CPU_POWERPC_POWER6,                 POWER6,
-                "POWER6")
-    POWERPC_DEF("POWER6_5",      CPU_POWERPC_POWER6_5,               POWER5,
-                "POWER6 running in POWER5 mode")
-    POWERPC_DEF("POWER6A",       CPU_POWERPC_POWER6A,                POWER6,
-                "POWER6A")
-#endif
-    POWERPC_DEF("POWER7_v2.0",   CPU_POWERPC_POWER7_v20,             POWER7,
-                "POWER7 v2.0")
-    POWERPC_DEF("POWER7_v2.1",   CPU_POWERPC_POWER7_v21,             POWER7,
-                "POWER7 v2.1")
-    POWERPC_DEF("POWER7_v2.3",   CPU_POWERPC_POWER7_v23,             POWER7,
-                "POWER7 v2.3")
-    POWERPC_DEF("970",           CPU_POWERPC_970,                    970,
-                "PowerPC 970")
-    POWERPC_DEF("970fx_v1.0",    CPU_POWERPC_970FX_v10,              970FX,
-                "PowerPC 970FX v1.0 (G5)")
-    POWERPC_DEF("970fx_v2.0",    CPU_POWERPC_970FX_v20,              970FX,
-                "PowerPC 970FX v2.0 (G5)")
-    POWERPC_DEF("970fx_v2.1",    CPU_POWERPC_970FX_v21,              970FX,
-                "PowerPC 970FX v2.1 (G5)")
-    POWERPC_DEF("970fx_v3.0",    CPU_POWERPC_970FX_v30,              970FX,
-                "PowerPC 970FX v3.0 (G5)")
-    POWERPC_DEF("970fx_v3.1",    CPU_POWERPC_970FX_v31,              970FX,
-                "PowerPC 970FX v3.1 (G5)")
-    POWERPC_DEF("970gx",         CPU_POWERPC_970GX,                  970GX,
-                "PowerPC 970GX (G5)")
-    POWERPC_DEF("970mp_v1.0",    CPU_POWERPC_970MP_v10,              970MP,
-                "PowerPC 970MP v1.0")
-    POWERPC_DEF("970mp_v1.1",    CPU_POWERPC_970MP_v11,              970MP,
-                "PowerPC 970MP v1.1")
-#if defined(TODO)
-    POWERPC_DEF("Cell",          CPU_POWERPC_CELL,                   970,
-                "PowerPC Cell")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("Cell_v1.0",     CPU_POWERPC_CELL_v10,               970,
-                "PowerPC Cell v1.0")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("Cell_v2.0",     CPU_POWERPC_CELL_v20,               970,
-                "PowerPC Cell v2.0")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("Cell_v3.0",     CPU_POWERPC_CELL_v30,               970,
-                "PowerPC Cell v3.0")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("Cell_v3.1",     CPU_POWERPC_CELL_v31,               970,
-                "PowerPC Cell v3.1")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("Cell_v3.2",     CPU_POWERPC_CELL_v32,               970,
-                "PowerPC Cell v3.2")
-#endif
-#if defined(TODO)
-    /* This one seems to support the whole POWER2 instruction set
-     * and the PowerPC 64 one.
-     */
-    /* What about A10 & A30 ? */
-    POWERPC_DEF("RS64",          CPU_POWERPC_RS64,                   RS64,
-                "RS64 (Apache/A35)")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("RS64-II",       CPU_POWERPC_RS64II,                 RS64,
-                "RS64-II (NorthStar/A50)")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("RS64-III",      CPU_POWERPC_RS64III,                RS64,
-                "RS64-III (Pulsar)")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("RS64-IV",       CPU_POWERPC_RS64IV,                 RS64,
-                "RS64-IV (IceStar/IStar/SStar)")
-#endif
-#endif /* defined (TARGET_PPC64) */
-    /* POWER                                                                 */
-#if defined(TODO)
-    POWERPC_DEF("POWER",         CPU_POWERPC_POWER,                  POWER,
-                "Original POWER")
-#endif
-#if defined(TODO)
-    POWERPC_DEF("POWER2",        CPU_POWERPC_POWER2,                 POWER,
-                "POWER2")
-#endif
-    /* PA semi cores                                                         */
-#if defined(TODO)
-    POWERPC_DEF("PA6T",          CPU_POWERPC_PA6T,                   PA6T,
-                "PA PA6T")
-#endif
 
 typedef struct PowerPCCPUAlias {
     const char *alias;
commit 09cc86f2b16ae242c031a01c6adca0ac5c5791ce
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:48 2013 +0000

    target-ppc: Update Coding Style for CPU models
    
    Drop the space in #if defined (TODO).
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index bd5230c..31566e0 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7923,7 +7923,7 @@ enum {
                 "PowerPC 401A1")
     POWERPC_DEF("401B2",         CPU_POWERPC_401B2,                  401x2,
                 "PowerPC 401B2")
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("401B3",         CPU_POWERPC_401B3,                  401x3,
                 "PowerPC 401B3")
 #endif
@@ -7939,7 +7939,7 @@ enum {
     POWERPC_DEF("401G2",         CPU_POWERPC_401G2,                  401x2,
                 "PowerPC 401G2")
     /* PowerPC 401 microcontrolers                                           */
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("401GF",         CPU_POWERPC_401GF,                  401,
                 "PowerPC 401GF")
 #endif
@@ -7947,7 +7947,7 @@ enum {
                 "IOP480 (401 microcontroller)")
     POWERPC_DEF("Cobra",         CPU_POWERPC_COBRA,                  401,
                 "IBM Processor for Network Resources")
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("Xipchip",       CPU_POWERPC_XIPCHIP,                401,
                 NULL)
 #endif
@@ -7961,61 +7961,61 @@ enum {
                 "PowerPC 403 GC")
     POWERPC_DEF("403GCX",        CPU_POWERPC_403GCX,                 403GCX,
                 "PowerPC 403 GCX")
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("403GP",         CPU_POWERPC_403GP,                  403,
                 "PowerPC 403 GP")
 #endif
     /* PowerPC 405 family                                                    */
     /* PowerPC 405 cores                                                     */
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("405A3",         CPU_POWERPC_405A3,                  405,
                 "PowerPC 405 A3")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("405A4",         CPU_POWERPC_405A4,                  405,
                 "PowerPC 405 A4")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("405B3",         CPU_POWERPC_405B3,                  405,
                 "PowerPC 405 B3")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("405B4",         CPU_POWERPC_405B4,                  405,
                 "PowerPC 405 B4")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("405C3",         CPU_POWERPC_405C3,                  405,
                 "PowerPC 405 C3")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("405C4",         CPU_POWERPC_405C4,                  405,
                 "PowerPC 405 C4")
 #endif
     POWERPC_DEF("405D2",         CPU_POWERPC_405D2,                  405,
                 "PowerPC 405 D2")
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("405D3",         CPU_POWERPC_405D3,                  405,
                 "PowerPC 405 D3")
 #endif
     POWERPC_DEF("405D4",         CPU_POWERPC_405D4,                  405,
                 "PowerPC 405 D4")
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("405D5",         CPU_POWERPC_405D5,                  405,
                 "PowerPC 405 D5")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("405E4",         CPU_POWERPC_405E4,                  405,
                 "PowerPC 405 E4")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("405F4",         CPU_POWERPC_405F4,                  405,
                 "PowerPC 405 F4")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("405F5",         CPU_POWERPC_405F5,                  405,
                 "PowerPC 405 F5")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("405F6",         CPU_POWERPC_405F6,                  405,
                 "PowerPC 405 F6")
 #endif
@@ -8078,38 +8078,38 @@ enum {
                 "Npe405 L")
     POWERPC_DEF("Npe4GS3",       CPU_POWERPC_NPE4GS3,                405,
                 "Npe4GS3")
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("Npcxx1",        CPU_POWERPC_NPCxx1,                 405,
                 NULL)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("Npr161",        CPU_POWERPC_NPR161,                 405,
                 NULL)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("LC77700",       CPU_POWERPC_LC77700,                405,
                 "PowerPC LC77700 (Sanyo)")
 #endif
     /* PowerPC 401/403/405 based set-top-box microcontrolers                 */
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("STB01000",      CPU_POWERPC_STB01000,               401x2,
                 "STB010000")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("STB01010",      CPU_POWERPC_STB01010,               401x2,
                 "STB01010")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("STB0210",       CPU_POWERPC_STB0210,                401x3,
                 "STB0210")
 #endif
     POWERPC_DEF("STB03",         CPU_POWERPC_STB03,                  405,
                 "STB03xx")
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("STB043",        CPU_POWERPC_STB043,                 405,
                 "STB043x")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("STB045",        CPU_POWERPC_STB045,                 405,
                 "STB045x")
 #endif
@@ -8117,7 +8117,7 @@ enum {
                 "STB04xx")
     POWERPC_DEF("STB25",         CPU_POWERPC_STB25,                  405,
                 "STB25xx")
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("STB130",        CPU_POWERPC_STB130,                 405,
                 "STB130")
 #endif
@@ -8126,19 +8126,19 @@ enum {
                 NULL)
     POWERPC_DEF("x2vp20",        CPU_POWERPC_X2VP20,                 405,
                 NULL)
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("zl10310",       CPU_POWERPC_ZL10310,                405,
                 "Zarlink ZL10310")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("zl10311",       CPU_POWERPC_ZL10311,                405,
                 "Zarlink ZL10311")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("zl10320",       CPU_POWERPC_ZL10320,                405,
                 "Zarlink ZL10320")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("zl10321",       CPU_POWERPC_ZL10321,                405,
                 "Zarlink ZL10321")
 #endif
@@ -8148,37 +8148,37 @@ enum {
                 "Generic PowerPC 440")
 #endif
     /* PowerPC 440 cores                                                     */
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("440A4",         CPU_POWERPC_440A4,                  440x4,
                 "PowerPC 440 A4")
 #endif
     POWERPC_DEF("440-Xilinx",    CPU_POWERPC_440_XILINX,             440x5,
                 "PowerPC 440 Xilinx 5")
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("440A5",         CPU_POWERPC_440A5,                  440x5,
                 "PowerPC 440 A5")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("440B4",         CPU_POWERPC_440B4,                  440x4,
                 "PowerPC 440 B4")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("440G4",         CPU_POWERPC_440G4,                  440x4,
                 "PowerPC 440 G4")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("440F5",         CPU_POWERPC_440F5,                  440x5,
                 "PowerPC 440 F5")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("440G5",         CPU_POWERPC_440G5,                  440x5,
                 "PowerPC 440 G5")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("440H4",         CPU_POWERPC_440H4,                  440x4,
                 "PowerPC 440H4")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("440H6",         CPU_POWERPC_440H6,                  440Gx5,
                 "PowerPC 440H6")
 #endif
@@ -8238,16 +8238,16 @@ enum {
                 "PowerPC 440 SPE")
 #endif
     /* PowerPC 460 family                                                    */
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("464",           CPU_POWERPC_464,                    460,
                 "Generic PowerPC 464")
 #endif
     /* PowerPC 464 microcontrolers                                           */
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("464H90",        CPU_POWERPC_464H90,                 460,
                 "PowerPC 464H90")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("464H90F",       CPU_POWERPC_464H90F,                460F,
                 "PowerPC 464H90F")
 #endif
@@ -8303,19 +8303,19 @@ enum {
     POWERPC_DEF_SVR("MPC5200B_v21", "MPC5200B v2.1",
                     CPU_POWERPC_MPC5200B_v21, POWERPC_SVR_5200B_v21, G2LE)
     /* e200 family                                                           */
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC55xx", "Generic MPC55xx core",
                     CPU_POWERPC_MPC55xx,      POWERPC_SVR_55xx,      e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("e200z0",        CPU_POWERPC_e200z0,                 e200,
                 "PowerPC e200z0 core")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("e200z1",        CPU_POWERPC_e200z1,                 e200,
                 "PowerPC e200z1 core")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("e200z3",        CPU_POWERPC_e200z3,                 e200,
                 "PowerPC e200z3 core")
 #endif
@@ -8324,91 +8324,91 @@ enum {
     POWERPC_DEF("e200z6",        CPU_POWERPC_e200z6,                 e200,
                 "PowerPC e200z6 core")
     /* PowerPC e200 microcontrollers                                         */
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5514E", "MPC5514E",
                     CPU_POWERPC_MPC5514E,     POWERPC_SVR_5514E,     e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5514E_v0", "MPC5514E v0",
                     CPU_POWERPC_MPC5514E_v0,  POWERPC_SVR_5514E_v0,  e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5514E_v1", "MPC5514E v1",
                     CPU_POWERPC_MPC5514E_v1,  POWERPC_SVR_5514E_v1,  e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5514G", "MPC5514G",
                     CPU_POWERPC_MPC5514G,     POWERPC_SVR_5514G,     e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5514G_v0", "MPC5514G v0",
                     CPU_POWERPC_MPC5514G_v0,  POWERPC_SVR_5514G_v0,  e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5514G_v1", "MPC5514G v1",
                     CPU_POWERPC_MPC5514G_v1,  POWERPC_SVR_5514G_v1,  e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5515S", "MPC5515S",
                     CPU_POWERPC_MPC5515S,     POWERPC_SVR_5515S,     e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5516E", "MPC5516E",
                     CPU_POWERPC_MPC5516E,     POWERPC_SVR_5516E,     e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5516E_v0", "MPC5516E v0",
                     CPU_POWERPC_MPC5516E_v0,  POWERPC_SVR_5516E_v0,  e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5516E_v1", "MPC5516E v1",
                     CPU_POWERPC_MPC5516E_v1,  POWERPC_SVR_5516E_v1,  e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5516G", "MPC5516G",
                     CPU_POWERPC_MPC5516G,     POWERPC_SVR_5516G,     e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5516G_v0", "MPC5516G v0",
                     CPU_POWERPC_MPC5516G_v0,  POWERPC_SVR_5516G_v0,  e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5516G_v1", "MPC5516G v1",
                     CPU_POWERPC_MPC5516G_v1,  POWERPC_SVR_5516G_v1,  e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5516S", "MPC5516S",
                     CPU_POWERPC_MPC5516S,     POWERPC_SVR_5516S,     e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5533", "MPC5533",
                     CPU_POWERPC_MPC5533,      POWERPC_SVR_5533,      e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5534", "MPC5534",
                     CPU_POWERPC_MPC5534,      POWERPC_SVR_5534,      e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5553", "MPC5553",
                     CPU_POWERPC_MPC5553,      POWERPC_SVR_5553,      e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5554", "MPC5554",
                     CPU_POWERPC_MPC5554,      POWERPC_SVR_5554,      e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5561", "MPC5561",
                     CPU_POWERPC_MPC5561,      POWERPC_SVR_5561,      e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5565", "MPC5565",
                     CPU_POWERPC_MPC5565,      POWERPC_SVR_5565,      e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5566", "MPC5566",
                     CPU_POWERPC_MPC5566,      POWERPC_SVR_5566,      e200)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC5567", "MPC5567",
                     CPU_POWERPC_MPC5567,      POWERPC_SVR_5567,      e200)
 #endif
@@ -8422,43 +8422,43 @@ enum {
     POWERPC_DEF("e300c4",        CPU_POWERPC_e300c4,                 e300,
                 "PowerPC e300c4 core")
     /* PowerPC e300 microcontrollers                                         */
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC8313", "MPC8313",
                     CPU_POWERPC_MPC831x,      POWERPC_SVR_8313,      e300)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC8313E", "MPC8313E",
                     CPU_POWERPC_MPC831x,      POWERPC_SVR_8313E,     e300)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC8314", "MPC8314",
                     CPU_POWERPC_MPC831x,      POWERPC_SVR_8314,      e300)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC8314E", "MPC8314E",
                     CPU_POWERPC_MPC831x,      POWERPC_SVR_8314E,     e300)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC8315", "MPC8315",
                     CPU_POWERPC_MPC831x,      POWERPC_SVR_8315,      e300)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC8315E", "MPC8315E",
                     CPU_POWERPC_MPC831x,      POWERPC_SVR_8315E,     e300)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC8321", "MPC8321",
                     CPU_POWERPC_MPC832x,      POWERPC_SVR_8321,      e300)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC8321E", "MPC8321E",
                     CPU_POWERPC_MPC832x,      POWERPC_SVR_8321E,     e300)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC8323", "MPC8323",
                     CPU_POWERPC_MPC832x,      POWERPC_SVR_8323,      e300)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC8323E", "MPC8323E",
                     CPU_POWERPC_MPC832x,      POWERPC_SVR_8323E,     e300)
 #endif
@@ -8494,11 +8494,11 @@ enum {
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8349E,     e300)
     POWERPC_DEF_SVR("MPC8349EA", "MPC8349EA",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8349EA,    e300)
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC8358E", "MPC8358E",
                     CPU_POWERPC_MPC835x,      POWERPC_SVR_8358E,     e300)
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC8360E", "MPC8360E",
                     CPU_POWERPC_MPC836x,      POWERPC_SVR_8360E,     e300)
 #endif
@@ -8640,7 +8640,7 @@ enum {
     POWERPC_DEF("e600",          CPU_POWERPC_e600,                   7400,
                 "PowerPC e600 core")
     /* PowerPC e600 microcontrollers                                         */
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF_SVR("MPC8610", "MPC8610",
                     CPU_POWERPC_MPC8610,      POWERPC_SVR_8610,      7400)
 #endif
@@ -8839,7 +8839,7 @@ enum {
                 "PowerPC 745 v2.8")
     POWERPC_DEF("755_v2.8",      CPU_POWERPC_7x5_v28,                755,
                 "PowerPC 755 v2.8")
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("745p",          CPU_POWERPC_7x5P,                   745,
                 "PowerPC 745P (G3)")
     POWERPC_DEF("755p",          CPU_POWERPC_7x5P,                   755,
@@ -8948,35 +8948,35 @@ enum {
 #if defined (TARGET_PPC64)
     POWERPC_DEF("620",           CPU_POWERPC_620,                    620,
                 "PowerPC 620")
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("630",           CPU_POWERPC_630,                    630,
                 "PowerPC 630 (POWER3)")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("631",           CPU_POWERPC_631,                    631,
                 "PowerPC 631 (Power 3+)")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("POWER4",        CPU_POWERPC_POWER4,                 POWER4,
                 "POWER4")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("POWER4+",       CPU_POWERPC_POWER4P,                POWER4P,
                 "POWER4p")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("POWER5",        CPU_POWERPC_POWER5,                 POWER5,
                 "POWER5")
     POWERPC_DEF("POWER5gr",      CPU_POWERPC_POWER5GR,               POWER5,
                 "POWER5GR")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("POWER5+",       CPU_POWERPC_POWER5P,                POWER5P,
                 "POWER5+")
     POWERPC_DEF("POWER5gs",      CPU_POWERPC_POWER5GS,               POWER5P,
                 "POWER5GS")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("POWER6",        CPU_POWERPC_POWER6,                 POWER6,
                 "POWER6")
     POWERPC_DEF("POWER6_5",      CPU_POWERPC_POWER6_5,               POWER5,
@@ -9008,31 +9008,31 @@ enum {
                 "PowerPC 970MP v1.0")
     POWERPC_DEF("970mp_v1.1",    CPU_POWERPC_970MP_v11,              970MP,
                 "PowerPC 970MP v1.1")
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("Cell",          CPU_POWERPC_CELL,                   970,
                 "PowerPC Cell")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("Cell_v1.0",     CPU_POWERPC_CELL_v10,               970,
                 "PowerPC Cell v1.0")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("Cell_v2.0",     CPU_POWERPC_CELL_v20,               970,
                 "PowerPC Cell v2.0")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("Cell_v3.0",     CPU_POWERPC_CELL_v30,               970,
                 "PowerPC Cell v3.0")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("Cell_v3.1",     CPU_POWERPC_CELL_v31,               970,
                 "PowerPC Cell v3.1")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("Cell_v3.2",     CPU_POWERPC_CELL_v32,               970,
                 "PowerPC Cell v3.2")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     /* This one seems to support the whole POWER2 instruction set
      * and the PowerPC 64 one.
      */
@@ -9040,30 +9040,30 @@ enum {
     POWERPC_DEF("RS64",          CPU_POWERPC_RS64,                   RS64,
                 "RS64 (Apache/A35)")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("RS64-II",       CPU_POWERPC_RS64II,                 RS64,
                 "RS64-II (NorthStar/A50)")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("RS64-III",      CPU_POWERPC_RS64III,                RS64,
                 "RS64-III (Pulsar)")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("RS64-IV",       CPU_POWERPC_RS64IV,                 RS64,
                 "RS64-IV (IceStar/IStar/SStar)")
 #endif
 #endif /* defined (TARGET_PPC64) */
     /* POWER                                                                 */
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("POWER",         CPU_POWERPC_POWER,                  POWER,
                 "Original POWER")
 #endif
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("POWER2",        CPU_POWERPC_POWER2,                 POWER,
                 "POWER2")
 #endif
     /* PA semi cores                                                         */
-#if defined (TODO)
+#if defined(TODO)
     POWERPC_DEF("PA6T",          CPU_POWERPC_PA6T,                   PA6T,
                 "PA PA6T")
 #endif
commit e0233c9abe16d8f7cdeb76ea54e84c68fe2b0037
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:47 2013 +0000

    target-ppc: Turn descriptive CPU model comments into device descriptions
    
    Fix microcontroller typo while at it.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 3ec7c1e..bd5230c 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7876,11 +7876,11 @@ enum {
     POWERPC_SVR_8641D              = 0x80900121,
 };
 
-/*****************************************************************************/
-/* PowerPC CPU definitions                                                   */
+/***************************************************************************/
+/* PowerPC CPU definitions                                                 */
 #define POWERPC_DEF_PREFIX(pvr, svr, type)                                  \
     glue(glue(glue(glue(pvr, _), svr), _), type)
-#define POWERPC_DEF_SVR(_name, _pvr, _svr, _type)                             \
+#define POWERPC_DEF_SVR(_name, _desc, _pvr, _svr, _type)                    \
     static void                                                             \
     glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_class_init)            \
     (ObjectClass *oc, void *data)                                           \
@@ -7890,7 +7890,7 @@ enum {
                                                                             \
         pcc->pvr          = _pvr;                                           \
         pcc->svr          = _svr;                                           \
-        dc->desc          = NULL;                                           \
+        dc->desc          = _desc;                                          \
     }                                                                       \
                                                                             \
     static const TypeInfo                                                   \
@@ -7911,1267 +7911,1161 @@ enum {
     type_init(                                                              \
         glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_register_types))
 
-#define POWERPC_DEF(_name, _pvr, _type)                                       \
-POWERPC_DEF_SVR(_name, _pvr, POWERPC_SVR_NONE, _type)
+#define POWERPC_DEF(_name, _pvr, _type, _desc)                              \
+    POWERPC_DEF_SVR(_name, _desc, _pvr, POWERPC_SVR_NONE, _type)
 
     /* Embedded PowerPC                                                      */
     /* PowerPC 401 family                                                    */
-    /* Generic PowerPC 401 */
-    POWERPC_DEF("401",           CPU_POWERPC_401,                    401)
+    POWERPC_DEF("401",           CPU_POWERPC_401,                    401,
+                "Generic PowerPC 401")
     /* PowerPC 401 cores                                                     */
-    /* PowerPC 401A1 */
-    POWERPC_DEF("401A1",         CPU_POWERPC_401A1,                  401)
-    /* PowerPC 401B2                                                         */
-    POWERPC_DEF("401B2",         CPU_POWERPC_401B2,                  401x2)
+    POWERPC_DEF("401A1",         CPU_POWERPC_401A1,                  401,
+                "PowerPC 401A1")
+    POWERPC_DEF("401B2",         CPU_POWERPC_401B2,                  401x2,
+                "PowerPC 401B2")
 #if defined (TODO)
-    /* PowerPC 401B3                                                         */
-    POWERPC_DEF("401B3",         CPU_POWERPC_401B3,                  401x3)
-#endif
-    /* PowerPC 401C2                                                         */
-    POWERPC_DEF("401C2",         CPU_POWERPC_401C2,                  401x2)
-    /* PowerPC 401D2                                                         */
-    POWERPC_DEF("401D2",         CPU_POWERPC_401D2,                  401x2)
-    /* PowerPC 401E2                                                         */
-    POWERPC_DEF("401E2",         CPU_POWERPC_401E2,                  401x2)
-    /* PowerPC 401F2                                                         */
-    POWERPC_DEF("401F2",         CPU_POWERPC_401F2,                  401x2)
-    /* PowerPC 401G2                                                         */
+    POWERPC_DEF("401B3",         CPU_POWERPC_401B3,                  401x3,
+                "PowerPC 401B3")
+#endif
+    POWERPC_DEF("401C2",         CPU_POWERPC_401C2,                  401x2,
+                "PowerPC 401C2")
+    POWERPC_DEF("401D2",         CPU_POWERPC_401D2,                  401x2,
+                "PowerPC 401D2")
+    POWERPC_DEF("401E2",         CPU_POWERPC_401E2,                  401x2,
+                "PowerPC 401E2")
+    POWERPC_DEF("401F2",         CPU_POWERPC_401F2,                  401x2,
+                "PowerPC 401F2")
     /* XXX: to be checked */
-    POWERPC_DEF("401G2",         CPU_POWERPC_401G2,                  401x2)
+    POWERPC_DEF("401G2",         CPU_POWERPC_401G2,                  401x2,
+                "PowerPC 401G2")
     /* PowerPC 401 microcontrolers                                           */
 #if defined (TODO)
-    /* PowerPC 401GF                                                         */
-    POWERPC_DEF("401GF",         CPU_POWERPC_401GF,                  401)
+    POWERPC_DEF("401GF",         CPU_POWERPC_401GF,                  401,
+                "PowerPC 401GF")
 #endif
-    /* IOP480 (401 microcontroler)                                           */
-    POWERPC_DEF("IOP480",        CPU_POWERPC_IOP480,                 IOP480)
-    /* IBM Processor for Network Resources                                   */
-    POWERPC_DEF("Cobra",         CPU_POWERPC_COBRA,                  401)
+    POWERPC_DEF("IOP480",        CPU_POWERPC_IOP480,                 IOP480,
+                "IOP480 (401 microcontroller)")
+    POWERPC_DEF("Cobra",         CPU_POWERPC_COBRA,                  401,
+                "IBM Processor for Network Resources")
 #if defined (TODO)
-    POWERPC_DEF("Xipchip",       CPU_POWERPC_XIPCHIP,                401)
+    POWERPC_DEF("Xipchip",       CPU_POWERPC_XIPCHIP,                401,
+                NULL)
 #endif
     /* PowerPC 403 family                                                    */
     /* PowerPC 403 microcontrolers                                           */
-    /* PowerPC 403 GA                                                        */
-    POWERPC_DEF("403GA",         CPU_POWERPC_403GA,                  403)
-    /* PowerPC 403 GB                                                        */
-    POWERPC_DEF("403GB",         CPU_POWERPC_403GB,                  403)
-    /* PowerPC 403 GC                                                        */
-    POWERPC_DEF("403GC",         CPU_POWERPC_403GC,                  403)
-    /* PowerPC 403 GCX                                                       */
-    POWERPC_DEF("403GCX",        CPU_POWERPC_403GCX,                 403GCX)
+    POWERPC_DEF("403GA",         CPU_POWERPC_403GA,                  403,
+                "PowerPC 403 GA")
+    POWERPC_DEF("403GB",         CPU_POWERPC_403GB,                  403,
+                "PowerPC 403 GB")
+    POWERPC_DEF("403GC",         CPU_POWERPC_403GC,                  403,
+                "PowerPC 403 GC")
+    POWERPC_DEF("403GCX",        CPU_POWERPC_403GCX,                 403GCX,
+                "PowerPC 403 GCX")
 #if defined (TODO)
-    /* PowerPC 403 GP                                                        */
-    POWERPC_DEF("403GP",         CPU_POWERPC_403GP,                  403)
+    POWERPC_DEF("403GP",         CPU_POWERPC_403GP,                  403,
+                "PowerPC 403 GP")
 #endif
     /* PowerPC 405 family                                                    */
     /* PowerPC 405 cores                                                     */
 #if defined (TODO)
-    /* PowerPC 405 A3                                                        */
-    POWERPC_DEF("405A3",         CPU_POWERPC_405A3,                  405)
+    POWERPC_DEF("405A3",         CPU_POWERPC_405A3,                  405,
+                "PowerPC 405 A3")
 #endif
 #if defined (TODO)
-    /* PowerPC 405 A4                                                        */
-    POWERPC_DEF("405A4",         CPU_POWERPC_405A4,                  405)
+    POWERPC_DEF("405A4",         CPU_POWERPC_405A4,                  405,
+                "PowerPC 405 A4")
 #endif
 #if defined (TODO)
-    /* PowerPC 405 B3                                                        */
-    POWERPC_DEF("405B3",         CPU_POWERPC_405B3,                  405)
+    POWERPC_DEF("405B3",         CPU_POWERPC_405B3,                  405,
+                "PowerPC 405 B3")
 #endif
 #if defined (TODO)
-    /* PowerPC 405 B4                                                        */
-    POWERPC_DEF("405B4",         CPU_POWERPC_405B4,                  405)
+    POWERPC_DEF("405B4",         CPU_POWERPC_405B4,                  405,
+                "PowerPC 405 B4")
 #endif
 #if defined (TODO)
-    /* PowerPC 405 C3                                                        */
-    POWERPC_DEF("405C3",         CPU_POWERPC_405C3,                  405)
+    POWERPC_DEF("405C3",         CPU_POWERPC_405C3,                  405,
+                "PowerPC 405 C3")
 #endif
 #if defined (TODO)
-    /* PowerPC 405 C4                                                        */
-    POWERPC_DEF("405C4",         CPU_POWERPC_405C4,                  405)
+    POWERPC_DEF("405C4",         CPU_POWERPC_405C4,                  405,
+                "PowerPC 405 C4")
 #endif
-    /* PowerPC 405 D2                                                        */
-    POWERPC_DEF("405D2",         CPU_POWERPC_405D2,                  405)
+    POWERPC_DEF("405D2",         CPU_POWERPC_405D2,                  405,
+                "PowerPC 405 D2")
 #if defined (TODO)
-    /* PowerPC 405 D3                                                        */
-    POWERPC_DEF("405D3",         CPU_POWERPC_405D3,                  405)
+    POWERPC_DEF("405D3",         CPU_POWERPC_405D3,                  405,
+                "PowerPC 405 D3")
 #endif
-    /* PowerPC 405 D4                                                        */
-    POWERPC_DEF("405D4",         CPU_POWERPC_405D4,                  405)
+    POWERPC_DEF("405D4",         CPU_POWERPC_405D4,                  405,
+                "PowerPC 405 D4")
 #if defined (TODO)
-    /* PowerPC 405 D5                                                        */
-    POWERPC_DEF("405D5",         CPU_POWERPC_405D5,                  405)
+    POWERPC_DEF("405D5",         CPU_POWERPC_405D5,                  405,
+                "PowerPC 405 D5")
 #endif
 #if defined (TODO)
-    /* PowerPC 405 E4                                                        */
-    POWERPC_DEF("405E4",         CPU_POWERPC_405E4,                  405)
+    POWERPC_DEF("405E4",         CPU_POWERPC_405E4,                  405,
+                "PowerPC 405 E4")
 #endif
 #if defined (TODO)
-    /* PowerPC 405 F4                                                        */
-    POWERPC_DEF("405F4",         CPU_POWERPC_405F4,                  405)
+    POWERPC_DEF("405F4",         CPU_POWERPC_405F4,                  405,
+                "PowerPC 405 F4")
 #endif
 #if defined (TODO)
-    /* PowerPC 405 F5                                                        */
-    POWERPC_DEF("405F5",         CPU_POWERPC_405F5,                  405)
+    POWERPC_DEF("405F5",         CPU_POWERPC_405F5,                  405,
+                "PowerPC 405 F5")
 #endif
 #if defined (TODO)
-    /* PowerPC 405 F6                                                        */
-    POWERPC_DEF("405F6",         CPU_POWERPC_405F6,                  405)
+    POWERPC_DEF("405F6",         CPU_POWERPC_405F6,                  405,
+                "PowerPC 405 F6")
 #endif
     /* PowerPC 405 microcontrolers                                           */
-    /* PowerPC 405 CRa                                                       */
-    POWERPC_DEF("405CRa",        CPU_POWERPC_405CRa,                 405)
-    /* PowerPC 405 CRb                                                       */
-    POWERPC_DEF("405CRb",        CPU_POWERPC_405CRb,                 405)
-    /* PowerPC 405 CRc                                                       */
-    POWERPC_DEF("405CRc",        CPU_POWERPC_405CRc,                 405)
-    /* PowerPC 405 EP                                                        */
-    POWERPC_DEF("405EP",         CPU_POWERPC_405EP,                  405)
+    POWERPC_DEF("405CRa",        CPU_POWERPC_405CRa,                 405,
+                "PowerPC 405 CRa")
+    POWERPC_DEF("405CRb",        CPU_POWERPC_405CRb,                 405,
+                "PowerPC 405 CRb")
+    POWERPC_DEF("405CRc",        CPU_POWERPC_405CRc,                 405,
+                "PowerPC 405 CRc")
+    POWERPC_DEF("405EP",         CPU_POWERPC_405EP,                  405,
+                "PowerPC 405 EP")
 #if defined(TODO)
-    /* PowerPC 405 EXr                                                       */
-    POWERPC_DEF("405EXr",        CPU_POWERPC_405EXr,                 405)
+    POWERPC_DEF("405EXr",        CPU_POWERPC_405EXr,                 405,
+                "PowerPC 405 EXr")
 #endif
-    /* PowerPC 405 EZ                                                        */
-    POWERPC_DEF("405EZ",         CPU_POWERPC_405EZ,                  405)
+    POWERPC_DEF("405EZ",         CPU_POWERPC_405EZ,                  405,
+                "PowerPC 405 EZ")
 #if defined(TODO)
-    /* PowerPC 405 FX                                                        */
-    POWERPC_DEF("405FX",         CPU_POWERPC_405FX,                  405)
-#endif
-    /* PowerPC 405 GPa                                                       */
-    POWERPC_DEF("405GPa",        CPU_POWERPC_405GPa,                 405)
-    /* PowerPC 405 GPb                                                       */
-    POWERPC_DEF("405GPb",        CPU_POWERPC_405GPb,                 405)
-    /* PowerPC 405 GPc                                                       */
-    POWERPC_DEF("405GPc",        CPU_POWERPC_405GPc,                 405)
-    /* PowerPC 405 GPd                                                       */
-    POWERPC_DEF("405GPd",        CPU_POWERPC_405GPd,                 405)
-    /* PowerPC 405 GPR                                                       */
-    POWERPC_DEF("405GPR",        CPU_POWERPC_405GPR,                 405)
+    POWERPC_DEF("405FX",         CPU_POWERPC_405FX,                  405,
+                "PowerPC 405 FX")
+#endif
+    POWERPC_DEF("405GPa",        CPU_POWERPC_405GPa,                 405,
+                "PowerPC 405 GPa")
+    POWERPC_DEF("405GPb",        CPU_POWERPC_405GPb,                 405,
+                "PowerPC 405 GPb")
+    POWERPC_DEF("405GPc",        CPU_POWERPC_405GPc,                 405,
+                "PowerPC 405 GPc")
+    POWERPC_DEF("405GPd",        CPU_POWERPC_405GPd,                 405,
+                "PowerPC 405 GPd")
+    POWERPC_DEF("405GPR",        CPU_POWERPC_405GPR,                 405,
+                "PowerPC 405 GPR")
 #if defined(TODO)
-    /* PowerPC 405 H                                                         */
-    POWERPC_DEF("405H",          CPU_POWERPC_405H,                   405)
+    POWERPC_DEF("405H",          CPU_POWERPC_405H,                   405,
+                "PowerPC 405 H")
 #endif
 #if defined(TODO)
-    /* PowerPC 405 L                                                         */
-    POWERPC_DEF("405L",          CPU_POWERPC_405L,                   405)
+    POWERPC_DEF("405L",          CPU_POWERPC_405L,                   405,
+                "PowerPC 405 L")
 #endif
-    /* PowerPC 405 LP                                                        */
-    POWERPC_DEF("405LP",         CPU_POWERPC_405LP,                  405)
+    POWERPC_DEF("405LP",         CPU_POWERPC_405LP,                  405,
+                "PowerPC 405 LP")
 #if defined(TODO)
-    /* PowerPC 405 PM                                                        */
-    POWERPC_DEF("405PM",         CPU_POWERPC_405PM,                  405)
+    POWERPC_DEF("405PM",         CPU_POWERPC_405PM,                  405,
+                "PowerPC 405 PM")
 #endif
 #if defined(TODO)
-    /* PowerPC 405 PS                                                        */
-    POWERPC_DEF("405PS",         CPU_POWERPC_405PS,                  405)
+    POWERPC_DEF("405PS",         CPU_POWERPC_405PS,                  405,
+                "PowerPC 405 PS")
 #endif
 #if defined(TODO)
-    /* PowerPC 405 S                                                         */
-    POWERPC_DEF("405S",          CPU_POWERPC_405S,                   405)
-#endif
-    /* Npe405 H                                                              */
-    POWERPC_DEF("Npe405H",       CPU_POWERPC_NPE405H,                405)
-    /* Npe405 H2                                                             */
-    POWERPC_DEF("Npe405H2",      CPU_POWERPC_NPE405H2,               405)
-    /* Npe405 L                                                              */
-    POWERPC_DEF("Npe405L",       CPU_POWERPC_NPE405L,                405)
-    /* Npe4GS3                                                               */
-    POWERPC_DEF("Npe4GS3",       CPU_POWERPC_NPE4GS3,                405)
+    POWERPC_DEF("405S",          CPU_POWERPC_405S,                   405,
+                "PowerPC 405 S")
+#endif
+    POWERPC_DEF("Npe405H",       CPU_POWERPC_NPE405H,                405,
+                "Npe405 H")
+    POWERPC_DEF("Npe405H2",      CPU_POWERPC_NPE405H2,               405,
+                "Npe405 H2")
+    POWERPC_DEF("Npe405L",       CPU_POWERPC_NPE405L,                405,
+                "Npe405 L")
+    POWERPC_DEF("Npe4GS3",       CPU_POWERPC_NPE4GS3,                405,
+                "Npe4GS3")
 #if defined (TODO)
-    POWERPC_DEF("Npcxx1",        CPU_POWERPC_NPCxx1,                 405)
+    POWERPC_DEF("Npcxx1",        CPU_POWERPC_NPCxx1,                 405,
+                NULL)
 #endif
 #if defined (TODO)
-    POWERPC_DEF("Npr161",        CPU_POWERPC_NPR161,                 405)
+    POWERPC_DEF("Npr161",        CPU_POWERPC_NPR161,                 405,
+                NULL)
 #endif
 #if defined (TODO)
-    /* PowerPC LC77700 (Sanyo)                                               */
-    POWERPC_DEF("LC77700",       CPU_POWERPC_LC77700,                405)
+    POWERPC_DEF("LC77700",       CPU_POWERPC_LC77700,                405,
+                "PowerPC LC77700 (Sanyo)")
 #endif
     /* PowerPC 401/403/405 based set-top-box microcontrolers                 */
 #if defined (TODO)
-    /* STB010000                                                             */
-    POWERPC_DEF("STB01000",      CPU_POWERPC_STB01000,               401x2)
+    POWERPC_DEF("STB01000",      CPU_POWERPC_STB01000,               401x2,
+                "STB010000")
 #endif
 #if defined (TODO)
-    /* STB01010                                                              */
-    POWERPC_DEF("STB01010",      CPU_POWERPC_STB01010,               401x2)
+    POWERPC_DEF("STB01010",      CPU_POWERPC_STB01010,               401x2,
+                "STB01010")
 #endif
 #if defined (TODO)
-    /* STB0210                                                               */
-    POWERPC_DEF("STB0210",       CPU_POWERPC_STB0210,                401x3)
+    POWERPC_DEF("STB0210",       CPU_POWERPC_STB0210,                401x3,
+                "STB0210")
 #endif
-    /* STB03xx                                                               */
-    POWERPC_DEF("STB03",         CPU_POWERPC_STB03,                  405)
+    POWERPC_DEF("STB03",         CPU_POWERPC_STB03,                  405,
+                "STB03xx")
 #if defined (TODO)
-    /* STB043x                                                               */
-    POWERPC_DEF("STB043",        CPU_POWERPC_STB043,                 405)
+    POWERPC_DEF("STB043",        CPU_POWERPC_STB043,                 405,
+                "STB043x")
 #endif
 #if defined (TODO)
-    /* STB045x                                                               */
-    POWERPC_DEF("STB045",        CPU_POWERPC_STB045,                 405)
+    POWERPC_DEF("STB045",        CPU_POWERPC_STB045,                 405,
+                "STB045x")
 #endif
-    /* STB04xx                                                               */
-    POWERPC_DEF("STB04",         CPU_POWERPC_STB04,                  405)
-    /* STB25xx                                                               */
-    POWERPC_DEF("STB25",         CPU_POWERPC_STB25,                  405)
+    POWERPC_DEF("STB04",         CPU_POWERPC_STB04,                  405,
+                "STB04xx")
+    POWERPC_DEF("STB25",         CPU_POWERPC_STB25,                  405,
+                "STB25xx")
 #if defined (TODO)
-    /* STB130                                                                */
-    POWERPC_DEF("STB130",        CPU_POWERPC_STB130,                 405)
+    POWERPC_DEF("STB130",        CPU_POWERPC_STB130,                 405,
+                "STB130")
 #endif
     /* Xilinx PowerPC 405 cores                                              */
-    POWERPC_DEF("x2vp4",         CPU_POWERPC_X2VP4,                  405)
-    POWERPC_DEF("x2vp20",        CPU_POWERPC_X2VP20,                 405)
+    POWERPC_DEF("x2vp4",         CPU_POWERPC_X2VP4,                  405,
+                NULL)
+    POWERPC_DEF("x2vp20",        CPU_POWERPC_X2VP20,                 405,
+                NULL)
 #if defined (TODO)
-    /* Zarlink ZL10310                                                       */
-    POWERPC_DEF("zl10310",       CPU_POWERPC_ZL10310,                405)
+    POWERPC_DEF("zl10310",       CPU_POWERPC_ZL10310,                405,
+                "Zarlink ZL10310")
 #endif
 #if defined (TODO)
-    /* Zarlink ZL10311                                                       */
-    POWERPC_DEF("zl10311",       CPU_POWERPC_ZL10311,                405)
+    POWERPC_DEF("zl10311",       CPU_POWERPC_ZL10311,                405,
+                "Zarlink ZL10311")
 #endif
 #if defined (TODO)
-    /* Zarlink ZL10320                                                       */
-    POWERPC_DEF("zl10320",       CPU_POWERPC_ZL10320,                405)
+    POWERPC_DEF("zl10320",       CPU_POWERPC_ZL10320,                405,
+                "Zarlink ZL10320")
 #endif
 #if defined (TODO)
-    /* Zarlink ZL10321                                                       */
-    POWERPC_DEF("zl10321",       CPU_POWERPC_ZL10321,                405)
+    POWERPC_DEF("zl10321",       CPU_POWERPC_ZL10321,                405,
+                "Zarlink ZL10321")
 #endif
     /* PowerPC 440 family                                                    */
 #if defined(TODO_USER_ONLY)
-    /* Generic PowerPC 440                                                   */
-    POWERPC_DEF("440",           CPU_POWERPC_440,                    440GP)
+    POWERPC_DEF("440",           CPU_POWERPC_440,                    440GP,
+                "Generic PowerPC 440")
 #endif
     /* PowerPC 440 cores                                                     */
 #if defined (TODO)
-    /* PowerPC 440 A4                                                        */
-    POWERPC_DEF("440A4",         CPU_POWERPC_440A4,                  440x4)
+    POWERPC_DEF("440A4",         CPU_POWERPC_440A4,                  440x4,
+                "PowerPC 440 A4")
 #endif
-    /* PowerPC 440 Xilinx 5                                                  */
-    POWERPC_DEF("440-Xilinx",    CPU_POWERPC_440_XILINX,             440x5)
+    POWERPC_DEF("440-Xilinx",    CPU_POWERPC_440_XILINX,             440x5,
+                "PowerPC 440 Xilinx 5")
 #if defined (TODO)
-    /* PowerPC 440 A5                                                        */
-    POWERPC_DEF("440A5",         CPU_POWERPC_440A5,                  440x5)
+    POWERPC_DEF("440A5",         CPU_POWERPC_440A5,                  440x5,
+                "PowerPC 440 A5")
 #endif
 #if defined (TODO)
-    /* PowerPC 440 B4                                                        */
-    POWERPC_DEF("440B4",         CPU_POWERPC_440B4,                  440x4)
+    POWERPC_DEF("440B4",         CPU_POWERPC_440B4,                  440x4,
+                "PowerPC 440 B4")
 #endif
 #if defined (TODO)
-    /* PowerPC 440 G4                                                        */
-    POWERPC_DEF("440G4",         CPU_POWERPC_440G4,                  440x4)
+    POWERPC_DEF("440G4",         CPU_POWERPC_440G4,                  440x4,
+                "PowerPC 440 G4")
 #endif
 #if defined (TODO)
-    /* PowerPC 440 F5                                                        */
-    POWERPC_DEF("440F5",         CPU_POWERPC_440F5,                  440x5)
+    POWERPC_DEF("440F5",         CPU_POWERPC_440F5,                  440x5,
+                "PowerPC 440 F5")
 #endif
 #if defined (TODO)
-    /* PowerPC 440 G5                                                        */
-    POWERPC_DEF("440G5",         CPU_POWERPC_440G5,                  440x5)
+    POWERPC_DEF("440G5",         CPU_POWERPC_440G5,                  440x5,
+                "PowerPC 440 G5")
 #endif
 #if defined (TODO)
-    /* PowerPC 440H4                                                         */
-    POWERPC_DEF("440H4",         CPU_POWERPC_440H4,                  440x4)
+    POWERPC_DEF("440H4",         CPU_POWERPC_440H4,                  440x4,
+                "PowerPC 440H4")
 #endif
 #if defined (TODO)
-    /* PowerPC 440H6                                                         */
-    POWERPC_DEF("440H6",         CPU_POWERPC_440H6,                  440Gx5)
+    POWERPC_DEF("440H6",         CPU_POWERPC_440H6,                  440Gx5,
+                "PowerPC 440H6")
 #endif
     /* PowerPC 440 microcontrolers                                           */
-    /* PowerPC 440 EPa                                                       */
-    POWERPC_DEF("440EPa",        CPU_POWERPC_440EPa,                 440EP)
-    /* PowerPC 440 EPb                                                       */
-    POWERPC_DEF("440EPb",        CPU_POWERPC_440EPb,                 440EP)
-    /* PowerPC 440 EPX                                                       */
-    POWERPC_DEF("440EPX",        CPU_POWERPC_440EPX,                 440EP)
+    POWERPC_DEF("440EPa",        CPU_POWERPC_440EPa,                 440EP,
+                "PowerPC 440 EPa")
+    POWERPC_DEF("440EPb",        CPU_POWERPC_440EPb,                 440EP,
+                "PowerPC 440 EPb")
+    POWERPC_DEF("440EPX",        CPU_POWERPC_440EPX,                 440EP,
+                "PowerPC 440 EPX")
 #if defined(TODO_USER_ONLY)
-    /* PowerPC 440 GPb                                                       */
-    POWERPC_DEF("440GPb",        CPU_POWERPC_440GPb,                 440GP)
+    POWERPC_DEF("440GPb",        CPU_POWERPC_440GPb,                 440GP,
+                "PowerPC 440 GPb")
 #endif
 #if defined(TODO_USER_ONLY)
-    /* PowerPC 440 GPc                                                       */
-    POWERPC_DEF("440GPc",        CPU_POWERPC_440GPc,                 440GP)
+    POWERPC_DEF("440GPc",        CPU_POWERPC_440GPc,                 440GP,
+                "PowerPC 440 GPc")
 #endif
 #if defined(TODO_USER_ONLY)
-    /* PowerPC 440 GRa                                                       */
-    POWERPC_DEF("440GRa",        CPU_POWERPC_440GRa,                 440x5)
+    POWERPC_DEF("440GRa",        CPU_POWERPC_440GRa,                 440x5,
+                "PowerPC 440 GRa")
 #endif
 #if defined(TODO_USER_ONLY)
-    /* PowerPC 440 GRX                                                       */
-    POWERPC_DEF("440GRX",        CPU_POWERPC_440GRX,                 440x5)
+    POWERPC_DEF("440GRX",        CPU_POWERPC_440GRX,                 440x5,
+                "PowerPC 440 GRX")
 #endif
 #if defined(TODO_USER_ONLY)
-    /* PowerPC 440 GXa                                                       */
-    POWERPC_DEF("440GXa",        CPU_POWERPC_440GXa,                 440EP)
+    POWERPC_DEF("440GXa",        CPU_POWERPC_440GXa,                 440EP,
+                "PowerPC 440 GXa")
 #endif
 #if defined(TODO_USER_ONLY)
-    /* PowerPC 440 GXb                                                       */
-    POWERPC_DEF("440GXb",        CPU_POWERPC_440GXb,                 440EP)
+    POWERPC_DEF("440GXb",        CPU_POWERPC_440GXb,                 440EP,
+                "PowerPC 440 GXb")
 #endif
 #if defined(TODO_USER_ONLY)
-    /* PowerPC 440 GXc                                                       */
-    POWERPC_DEF("440GXc",        CPU_POWERPC_440GXc,                 440EP)
+    POWERPC_DEF("440GXc",        CPU_POWERPC_440GXc,                 440EP,
+                "PowerPC 440 GXc")
 #endif
 #if defined(TODO_USER_ONLY)
-    /* PowerPC 440 GXf                                                       */
-    POWERPC_DEF("440GXf",        CPU_POWERPC_440GXf,                 440EP)
+    POWERPC_DEF("440GXf",        CPU_POWERPC_440GXf,                 440EP,
+                "PowerPC 440 GXf")
 #endif
 #if defined(TODO)
-    /* PowerPC 440 S                                                         */
-    POWERPC_DEF("440S",          CPU_POWERPC_440S,                   440)
+    POWERPC_DEF("440S",          CPU_POWERPC_440S,                   440,
+                "PowerPC 440 S")
 #endif
 #if defined(TODO_USER_ONLY)
-    /* PowerPC 440 SP                                                        */
-    POWERPC_DEF("440SP",         CPU_POWERPC_440SP,                  440EP)
+    POWERPC_DEF("440SP",         CPU_POWERPC_440SP,                  440EP,
+                "PowerPC 440 SP")
 #endif
 #if defined(TODO_USER_ONLY)
-    /* PowerPC 440 SP2                                                       */
-    POWERPC_DEF("440SP2",        CPU_POWERPC_440SP2,                 440EP)
+    POWERPC_DEF("440SP2",        CPU_POWERPC_440SP2,                 440EP,
+                "PowerPC 440 SP2")
 #endif
 #if defined(TODO_USER_ONLY)
-    /* PowerPC 440 SPE                                                       */
-    POWERPC_DEF("440SPE",        CPU_POWERPC_440SPE,                 440EP)
+    POWERPC_DEF("440SPE",        CPU_POWERPC_440SPE,                 440EP,
+                "PowerPC 440 SPE")
 #endif
     /* PowerPC 460 family                                                    */
 #if defined (TODO)
-    /* Generic PowerPC 464                                                   */
-    POWERPC_DEF("464",           CPU_POWERPC_464,                    460)
+    POWERPC_DEF("464",           CPU_POWERPC_464,                    460,
+                "Generic PowerPC 464")
 #endif
     /* PowerPC 464 microcontrolers                                           */
 #if defined (TODO)
-    /* PowerPC 464H90                                                        */
-    POWERPC_DEF("464H90",        CPU_POWERPC_464H90,                 460)
+    POWERPC_DEF("464H90",        CPU_POWERPC_464H90,                 460,
+                "PowerPC 464H90")
 #endif
 #if defined (TODO)
-    /* PowerPC 464H90F                                                       */
-    POWERPC_DEF("464H90F",       CPU_POWERPC_464H90F,                460F)
+    POWERPC_DEF("464H90F",       CPU_POWERPC_464H90F,                460F,
+                "PowerPC 464H90F")
 #endif
     /* Freescale embedded PowerPC cores                                      */
     /* MPC5xx family (aka RCPU)                                              */
 #if defined(TODO_USER_ONLY)
-    /* Generic MPC5xx core                                                   */
-    POWERPC_DEF("MPC5xx",        CPU_POWERPC_MPC5xx,                 MPC5xx)
+    POWERPC_DEF("MPC5xx",        CPU_POWERPC_MPC5xx,                 MPC5xx,
+                "Generic MPC5xx core")
 #endif
     /* MPC8xx family (aka PowerQUICC)                                        */
 #if defined(TODO_USER_ONLY)
-    /* Generic MPC8xx core                                                   */
-    POWERPC_DEF("MPC8xx",        CPU_POWERPC_MPC8xx,                 MPC8xx)
+    POWERPC_DEF("MPC8xx",        CPU_POWERPC_MPC8xx,                 MPC8xx,
+                "Generic MPC8xx core")
 #endif
     /* MPC82xx family (aka PowerQUICC-II)                                    */
-    /* PowerPC G2 core                                                       */
-    POWERPC_DEF("G2",            CPU_POWERPC_G2,                     G2)
-    /* PowerPC G2 H4 core                                                    */
-    POWERPC_DEF("G2H4",          CPU_POWERPC_G2H4,                   G2)
-    /* PowerPC G2 GP core                                                    */
-    POWERPC_DEF("G2GP",          CPU_POWERPC_G2gp,                   G2)
-    /* PowerPC G2 LS core                                                    */
-    POWERPC_DEF("G2LS",          CPU_POWERPC_G2ls,                   G2)
-    /* PowerPC G2 HiP3 core                                                  */
-    POWERPC_DEF("G2HiP3",        CPU_POWERPC_G2_HIP3,                G2)
-    /* PowerPC G2 HiP4 core                                                  */
-    POWERPC_DEF("G2HiP4",        CPU_POWERPC_G2_HIP4,                G2)
-    /* PowerPC MPC603 core                                                   */
-    POWERPC_DEF("MPC603",        CPU_POWERPC_MPC603,                 603E)
-    /* PowerPC G2le core (same as G2 plus little-endian mode support)        */
-    POWERPC_DEF("G2le",          CPU_POWERPC_G2LE,                   G2LE)
-    /* PowerPC G2LE GP core                                                  */
-    POWERPC_DEF("G2leGP",        CPU_POWERPC_G2LEgp,                 G2LE)
-    /* PowerPC G2LE LS core                                                  */
-    POWERPC_DEF("G2leLS",        CPU_POWERPC_G2LEls,                 G2LE)
-    /* PowerPC G2LE GP1 core                                                 */
-    POWERPC_DEF("G2leGP1",       CPU_POWERPC_G2LEgp1,                G2LE)
-    /* PowerPC G2LE GP3 core                                                 */
-    POWERPC_DEF("G2leGP3",       CPU_POWERPC_G2LEgp3,                G2LE)
+    POWERPC_DEF("G2",            CPU_POWERPC_G2,                     G2,
+                "PowerPC G2 core")
+    POWERPC_DEF("G2H4",          CPU_POWERPC_G2H4,                   G2,
+                "PowerPC G2 H4 core")
+    POWERPC_DEF("G2GP",          CPU_POWERPC_G2gp,                   G2,
+                "PowerPC G2 GP core")
+    POWERPC_DEF("G2LS",          CPU_POWERPC_G2ls,                   G2,
+                "PowerPC G2 LS core")
+    POWERPC_DEF("G2HiP3",        CPU_POWERPC_G2_HIP3,                G2,
+                "PowerPC G2 HiP3 core")
+    POWERPC_DEF("G2HiP4",        CPU_POWERPC_G2_HIP4,                G2,
+                "PowerPC G2 HiP4 core")
+    POWERPC_DEF("MPC603",        CPU_POWERPC_MPC603,                 603E,
+                "PowerPC MPC603 core")
+    POWERPC_DEF("G2le",          CPU_POWERPC_G2LE,                   G2LE,
+        "PowerPC G2le core (same as G2 plus little-endian mode support)")
+    POWERPC_DEF("G2leGP",        CPU_POWERPC_G2LEgp,                 G2LE,
+                "PowerPC G2LE GP core")
+    POWERPC_DEF("G2leLS",        CPU_POWERPC_G2LEls,                 G2LE,
+                "PowerPC G2LE LS core")
+    POWERPC_DEF("G2leGP1",       CPU_POWERPC_G2LEgp1,                G2LE,
+                "PowerPC G2LE GP1 core")
+    POWERPC_DEF("G2leGP3",       CPU_POWERPC_G2LEgp3,                G2LE,
+                "PowerPC G2LE GP3 core")
     /* PowerPC G2 microcontrollers                                           */
 #if defined(TODO)
-    /* MPC5121                                                               */
-    POWERPC_DEF_SVR("MPC5121",
+    POWERPC_DEF_SVR("MPC5121", "MPC5121",
                     CPU_POWERPC_MPC5121,      POWERPC_SVR_5121,      G2LE)
 #endif
-    /* MPC5200 v1.0                                                          */
-    POWERPC_DEF_SVR("MPC5200_v10",
+    POWERPC_DEF_SVR("MPC5200_v10", "MPC5200 v1.0",
                     CPU_POWERPC_MPC5200_v10,  POWERPC_SVR_5200_v10,  G2LE)
-    /* MPC5200 v1.1                                                          */
-    POWERPC_DEF_SVR("MPC5200_v11",
+    POWERPC_DEF_SVR("MPC5200_v11", "MPC5200 v1.1",
                     CPU_POWERPC_MPC5200_v11,  POWERPC_SVR_5200_v11,  G2LE)
-    /* MPC5200 v1.2                                                          */
-    POWERPC_DEF_SVR("MPC5200_v12",
+    POWERPC_DEF_SVR("MPC5200_v12", "MPC5200 v1.2",
                     CPU_POWERPC_MPC5200_v12,  POWERPC_SVR_5200_v12,  G2LE)
-    /* MPC5200B v2.0                                                         */
-    POWERPC_DEF_SVR("MPC5200B_v20",
+    POWERPC_DEF_SVR("MPC5200B_v20", "MPC5200B v2.0",
                     CPU_POWERPC_MPC5200B_v20, POWERPC_SVR_5200B_v20, G2LE)
-    /* MPC5200B v2.1                                                         */
-    POWERPC_DEF_SVR("MPC5200B_v21",
+    POWERPC_DEF_SVR("MPC5200B_v21", "MPC5200B v2.1",
                     CPU_POWERPC_MPC5200B_v21, POWERPC_SVR_5200B_v21, G2LE)
     /* e200 family                                                           */
-    /* Generic MPC55xx core                                                  */
 #if defined (TODO)
-    POWERPC_DEF_SVR("MPC55xx",
+    POWERPC_DEF_SVR("MPC55xx", "Generic MPC55xx core",
                     CPU_POWERPC_MPC55xx,      POWERPC_SVR_55xx,      e200)
 #endif
 #if defined (TODO)
-    /* PowerPC e200z0 core                                                   */
-    POWERPC_DEF("e200z0",        CPU_POWERPC_e200z0,                 e200)
+    POWERPC_DEF("e200z0",        CPU_POWERPC_e200z0,                 e200,
+                "PowerPC e200z0 core")
 #endif
 #if defined (TODO)
-    /* PowerPC e200z1 core                                                   */
-    POWERPC_DEF("e200z1",        CPU_POWERPC_e200z1,                 e200)
+    POWERPC_DEF("e200z1",        CPU_POWERPC_e200z1,                 e200,
+                "PowerPC e200z1 core")
 #endif
 #if defined (TODO)
-    /* PowerPC e200z3 core                                                   */
-    POWERPC_DEF("e200z3",        CPU_POWERPC_e200z3,                 e200)
+    POWERPC_DEF("e200z3",        CPU_POWERPC_e200z3,                 e200,
+                "PowerPC e200z3 core")
 #endif
-    /* PowerPC e200z5 core                                                   */
-    POWERPC_DEF("e200z5",        CPU_POWERPC_e200z5,                 e200)
-    /* PowerPC e200z6 core                                                   */
-    POWERPC_DEF("e200z6",        CPU_POWERPC_e200z6,                 e200)
+    POWERPC_DEF("e200z5",        CPU_POWERPC_e200z5,                 e200,
+                "PowerPC e200z5 core")
+    POWERPC_DEF("e200z6",        CPU_POWERPC_e200z6,                 e200,
+                "PowerPC e200z6 core")
     /* PowerPC e200 microcontrollers                                         */
 #if defined (TODO)
-    /* MPC5514E                                                              */
-    POWERPC_DEF_SVR("MPC5514E",
+    POWERPC_DEF_SVR("MPC5514E", "MPC5514E",
                     CPU_POWERPC_MPC5514E,     POWERPC_SVR_5514E,     e200)
 #endif
 #if defined (TODO)
-    /* MPC5514E v0                                                           */
-    POWERPC_DEF_SVR("MPC5514E_v0",
+    POWERPC_DEF_SVR("MPC5514E_v0", "MPC5514E v0",
                     CPU_POWERPC_MPC5514E_v0,  POWERPC_SVR_5514E_v0,  e200)
 #endif
 #if defined (TODO)
-    /* MPC5514E v1                                                           */
-    POWERPC_DEF_SVR("MPC5514E_v1",
+    POWERPC_DEF_SVR("MPC5514E_v1", "MPC5514E v1",
                     CPU_POWERPC_MPC5514E_v1,  POWERPC_SVR_5514E_v1,  e200)
 #endif
 #if defined (TODO)
-    /* MPC5514G                                                              */
-    POWERPC_DEF_SVR("MPC5514G",
+    POWERPC_DEF_SVR("MPC5514G", "MPC5514G",
                     CPU_POWERPC_MPC5514G,     POWERPC_SVR_5514G,     e200)
 #endif
 #if defined (TODO)
-    /* MPC5514G v0                                                           */
-    POWERPC_DEF_SVR("MPC5514G_v0",
+    POWERPC_DEF_SVR("MPC5514G_v0", "MPC5514G v0",
                     CPU_POWERPC_MPC5514G_v0,  POWERPC_SVR_5514G_v0,  e200)
 #endif
 #if defined (TODO)
-    /* MPC5514G v1                                                           */
-    POWERPC_DEF_SVR("MPC5514G_v1",
+    POWERPC_DEF_SVR("MPC5514G_v1", "MPC5514G v1",
                     CPU_POWERPC_MPC5514G_v1,  POWERPC_SVR_5514G_v1,  e200)
 #endif
 #if defined (TODO)
-    /* MPC5515S                                                              */
-    POWERPC_DEF_SVR("MPC5515S",
+    POWERPC_DEF_SVR("MPC5515S", "MPC5515S",
                     CPU_POWERPC_MPC5515S,     POWERPC_SVR_5515S,     e200)
 #endif
 #if defined (TODO)
-    /* MPC5516E                                                              */
-    POWERPC_DEF_SVR("MPC5516E",
+    POWERPC_DEF_SVR("MPC5516E", "MPC5516E",
                     CPU_POWERPC_MPC5516E,     POWERPC_SVR_5516E,     e200)
 #endif
 #if defined (TODO)
-    /* MPC5516E v0                                                           */
-    POWERPC_DEF_SVR("MPC5516E_v0",
+    POWERPC_DEF_SVR("MPC5516E_v0", "MPC5516E v0",
                     CPU_POWERPC_MPC5516E_v0,  POWERPC_SVR_5516E_v0,  e200)
 #endif
 #if defined (TODO)
-    /* MPC5516E v1                                                           */
-    POWERPC_DEF_SVR("MPC5516E_v1",
+    POWERPC_DEF_SVR("MPC5516E_v1", "MPC5516E v1",
                     CPU_POWERPC_MPC5516E_v1,  POWERPC_SVR_5516E_v1,  e200)
 #endif
 #if defined (TODO)
-    /* MPC5516G                                                              */
-    POWERPC_DEF_SVR("MPC5516G",
+    POWERPC_DEF_SVR("MPC5516G", "MPC5516G",
                     CPU_POWERPC_MPC5516G,     POWERPC_SVR_5516G,     e200)
 #endif
 #if defined (TODO)
-    /* MPC5516G v0                                                           */
-    POWERPC_DEF_SVR("MPC5516G_v0",
+    POWERPC_DEF_SVR("MPC5516G_v0", "MPC5516G v0",
                     CPU_POWERPC_MPC5516G_v0,  POWERPC_SVR_5516G_v0,  e200)
 #endif
 #if defined (TODO)
-    /* MPC5516G v1                                                           */
-    POWERPC_DEF_SVR("MPC5516G_v1",
+    POWERPC_DEF_SVR("MPC5516G_v1", "MPC5516G v1",
                     CPU_POWERPC_MPC5516G_v1,  POWERPC_SVR_5516G_v1,  e200)
 #endif
 #if defined (TODO)
-    /* MPC5516S                                                              */
-    POWERPC_DEF_SVR("MPC5516S",
+    POWERPC_DEF_SVR("MPC5516S", "MPC5516S",
                     CPU_POWERPC_MPC5516S,     POWERPC_SVR_5516S,     e200)
 #endif
 #if defined (TODO)
-    /* MPC5533                                                               */
-    POWERPC_DEF_SVR("MPC5533",
+    POWERPC_DEF_SVR("MPC5533", "MPC5533",
                     CPU_POWERPC_MPC5533,      POWERPC_SVR_5533,      e200)
 #endif
 #if defined (TODO)
-    /* MPC5534                                                               */
-    POWERPC_DEF_SVR("MPC5534",
+    POWERPC_DEF_SVR("MPC5534", "MPC5534",
                     CPU_POWERPC_MPC5534,      POWERPC_SVR_5534,      e200)
 #endif
 #if defined (TODO)
-    /* MPC5553                                                               */
-    POWERPC_DEF_SVR("MPC5553",
+    POWERPC_DEF_SVR("MPC5553", "MPC5553",
                     CPU_POWERPC_MPC5553,      POWERPC_SVR_5553,      e200)
 #endif
 #if defined (TODO)
-    /* MPC5554                                                               */
-    POWERPC_DEF_SVR("MPC5554",
+    POWERPC_DEF_SVR("MPC5554", "MPC5554",
                     CPU_POWERPC_MPC5554,      POWERPC_SVR_5554,      e200)
 #endif
 #if defined (TODO)
-    /* MPC5561                                                               */
-    POWERPC_DEF_SVR("MPC5561",
+    POWERPC_DEF_SVR("MPC5561", "MPC5561",
                     CPU_POWERPC_MPC5561,      POWERPC_SVR_5561,      e200)
 #endif
 #if defined (TODO)
-    /* MPC5565                                                               */
-    POWERPC_DEF_SVR("MPC5565",
+    POWERPC_DEF_SVR("MPC5565", "MPC5565",
                     CPU_POWERPC_MPC5565,      POWERPC_SVR_5565,      e200)
 #endif
 #if defined (TODO)
-    /* MPC5566                                                               */
-    POWERPC_DEF_SVR("MPC5566",
+    POWERPC_DEF_SVR("MPC5566", "MPC5566",
                     CPU_POWERPC_MPC5566,      POWERPC_SVR_5566,      e200)
 #endif
 #if defined (TODO)
-    /* MPC5567                                                               */
-    POWERPC_DEF_SVR("MPC5567",
+    POWERPC_DEF_SVR("MPC5567", "MPC5567",
                     CPU_POWERPC_MPC5567,      POWERPC_SVR_5567,      e200)
 #endif
     /* e300 family                                                           */
-    /* PowerPC e300c1 core                                                   */
-    POWERPC_DEF("e300c1",        CPU_POWERPC_e300c1,                 e300)
-    /* PowerPC e300c2 core                                                   */
-    POWERPC_DEF("e300c2",        CPU_POWERPC_e300c2,                 e300)
-    /* PowerPC e300c3 core                                                   */
-    POWERPC_DEF("e300c3",        CPU_POWERPC_e300c3,                 e300)
-    /* PowerPC e300c4 core                                                   */
-    POWERPC_DEF("e300c4",        CPU_POWERPC_e300c4,                 e300)
+    POWERPC_DEF("e300c1",        CPU_POWERPC_e300c1,                 e300,
+                "PowerPC e300c1 core")
+    POWERPC_DEF("e300c2",        CPU_POWERPC_e300c2,                 e300,
+                "PowerPC e300c2 core")
+    POWERPC_DEF("e300c3",        CPU_POWERPC_e300c3,                 e300,
+                "PowerPC e300c3 core")
+    POWERPC_DEF("e300c4",        CPU_POWERPC_e300c4,                 e300,
+                "PowerPC e300c4 core")
     /* PowerPC e300 microcontrollers                                         */
 #if defined (TODO)
-    /* MPC8313                                                               */
-    POWERPC_DEF_SVR("MPC8313",
+    POWERPC_DEF_SVR("MPC8313", "MPC8313",
                     CPU_POWERPC_MPC831x,      POWERPC_SVR_8313,      e300)
 #endif
 #if defined (TODO)
-    /* MPC8313E                                                              */
-    POWERPC_DEF_SVR("MPC8313E",
+    POWERPC_DEF_SVR("MPC8313E", "MPC8313E",
                     CPU_POWERPC_MPC831x,      POWERPC_SVR_8313E,     e300)
 #endif
 #if defined (TODO)
-    /* MPC8314                                                               */
-    POWERPC_DEF_SVR("MPC8314",
+    POWERPC_DEF_SVR("MPC8314", "MPC8314",
                     CPU_POWERPC_MPC831x,      POWERPC_SVR_8314,      e300)
 #endif
 #if defined (TODO)
-    /* MPC8314E                                                              */
-    POWERPC_DEF_SVR("MPC8314E",
+    POWERPC_DEF_SVR("MPC8314E", "MPC8314E",
                     CPU_POWERPC_MPC831x,      POWERPC_SVR_8314E,     e300)
 #endif
 #if defined (TODO)
-    /* MPC8315                                                               */
-    POWERPC_DEF_SVR("MPC8315",
+    POWERPC_DEF_SVR("MPC8315", "MPC8315",
                     CPU_POWERPC_MPC831x,      POWERPC_SVR_8315,      e300)
 #endif
 #if defined (TODO)
-    /* MPC8315E                                                              */
-    POWERPC_DEF_SVR("MPC8315E",
+    POWERPC_DEF_SVR("MPC8315E", "MPC8315E",
                     CPU_POWERPC_MPC831x,      POWERPC_SVR_8315E,     e300)
 #endif
 #if defined (TODO)
-    /* MPC8321                                                               */
-    POWERPC_DEF_SVR("MPC8321",
+    POWERPC_DEF_SVR("MPC8321", "MPC8321",
                     CPU_POWERPC_MPC832x,      POWERPC_SVR_8321,      e300)
 #endif
 #if defined (TODO)
-    /* MPC8321E                                                              */
-    POWERPC_DEF_SVR("MPC8321E",
+    POWERPC_DEF_SVR("MPC8321E", "MPC8321E",
                     CPU_POWERPC_MPC832x,      POWERPC_SVR_8321E,     e300)
 #endif
 #if defined (TODO)
-    /* MPC8323                                                               */
-    POWERPC_DEF_SVR("MPC8323",
+    POWERPC_DEF_SVR("MPC8323", "MPC8323",
                     CPU_POWERPC_MPC832x,      POWERPC_SVR_8323,      e300)
 #endif
 #if defined (TODO)
-    /* MPC8323E                                                              */
-    POWERPC_DEF_SVR("MPC8323E",
+    POWERPC_DEF_SVR("MPC8323E", "MPC8323E",
                     CPU_POWERPC_MPC832x,      POWERPC_SVR_8323E,     e300)
 #endif
-    /* MPC8343                                                               */
-    POWERPC_DEF_SVR("MPC8343",
+    POWERPC_DEF_SVR("MPC8343", "MPC8343",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8343,      e300)
-    /* MPC8343A                                                              */
-    POWERPC_DEF_SVR("MPC8343A",
+    POWERPC_DEF_SVR("MPC8343A", "MPC8343A",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8343A,     e300)
-    /* MPC8343E                                                              */
-    POWERPC_DEF_SVR("MPC8343E",
+    POWERPC_DEF_SVR("MPC8343E", "MPC8343E",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8343E,     e300)
-    /* MPC8343EA                                                             */
-    POWERPC_DEF_SVR("MPC8343EA",
+    POWERPC_DEF_SVR("MPC8343EA", "MPC8343EA",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8343EA,    e300)
-    /* MPC8347T                                                              */
-    POWERPC_DEF_SVR("MPC8347T",
+    POWERPC_DEF_SVR("MPC8347T", "MPC8347T",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8347T,     e300)
-    /* MPC8347P                                                              */
-    POWERPC_DEF_SVR("MPC8347P",
+    POWERPC_DEF_SVR("MPC8347P", "MPC8347P",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8347P,     e300)
-    /* MPC8347AT                                                             */
-    POWERPC_DEF_SVR("MPC8347AT",
+    POWERPC_DEF_SVR("MPC8347AT", "MPC8347AT",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8347AT,    e300)
-    /* MPC8347AP                                                             */
-    POWERPC_DEF_SVR("MPC8347AP",
+    POWERPC_DEF_SVR("MPC8347AP", "MPC8347AP",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8347AP,    e300)
-    /* MPC8347ET                                                             */
-    POWERPC_DEF_SVR("MPC8347ET",
+    POWERPC_DEF_SVR("MPC8347ET", "MPC8347ET",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8347ET,    e300)
-    /* MPC8343EP                                                             */
-    POWERPC_DEF_SVR("MPC8347EP",
+    POWERPC_DEF_SVR("MPC8347EP", "MPC8343EP",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EP,    e300)
-    /* MPC8347EAT                                                            */
-    POWERPC_DEF_SVR("MPC8347EAT",
+    POWERPC_DEF_SVR("MPC8347EAT", "MPC8347EAT",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EAT,   e300)
-    /* MPC8343EAP                                                            */
-    POWERPC_DEF_SVR("MPC8347EAP",
+    POWERPC_DEF_SVR("MPC8347EAP", "MPC8343EAP",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EAP,   e300)
-    /* MPC8349                                                               */
-    POWERPC_DEF_SVR("MPC8349",
+    POWERPC_DEF_SVR("MPC8349", "MPC8349",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8349,      e300)
-    /* MPC8349A                                                              */
-    POWERPC_DEF_SVR("MPC8349A",
+    POWERPC_DEF_SVR("MPC8349A", "MPC8349A",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8349A,     e300)
-    /* MPC8349E                                                              */
-    POWERPC_DEF_SVR("MPC8349E",
+    POWERPC_DEF_SVR("MPC8349E", "MPC8349E",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8349E,     e300)
-    /* MPC8349EA                                                             */
-    POWERPC_DEF_SVR("MPC8349EA",
+    POWERPC_DEF_SVR("MPC8349EA", "MPC8349EA",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8349EA,    e300)
 #if defined (TODO)
-    /* MPC8358E                                                              */
-    POWERPC_DEF_SVR("MPC8358E",
+    POWERPC_DEF_SVR("MPC8358E", "MPC8358E",
                     CPU_POWERPC_MPC835x,      POWERPC_SVR_8358E,     e300)
 #endif
 #if defined (TODO)
-    /* MPC8360E                                                              */
-    POWERPC_DEF_SVR("MPC8360E",
+    POWERPC_DEF_SVR("MPC8360E", "MPC8360E",
                     CPU_POWERPC_MPC836x,      POWERPC_SVR_8360E,     e300)
 #endif
-    /* MPC8377                                                               */
-    POWERPC_DEF_SVR("MPC8377",
+    POWERPC_DEF_SVR("MPC8377", "MPC8377",
                     CPU_POWERPC_MPC837x,      POWERPC_SVR_8377,      e300)
-    /* MPC8377E                                                              */
-    POWERPC_DEF_SVR("MPC8377E",
+    POWERPC_DEF_SVR("MPC8377E", "MPC8377E",
                     CPU_POWERPC_MPC837x,      POWERPC_SVR_8377E,     e300)
-    /* MPC8378                                                               */
-    POWERPC_DEF_SVR("MPC8378",
+    POWERPC_DEF_SVR("MPC8378", "MPC8378",
                     CPU_POWERPC_MPC837x,      POWERPC_SVR_8378,      e300)
-    /* MPC8378E                                                              */
-    POWERPC_DEF_SVR("MPC8378E",
+    POWERPC_DEF_SVR("MPC8378E", "MPC8378E",
                     CPU_POWERPC_MPC837x,      POWERPC_SVR_8378E,     e300)
-    /* MPC8379                                                               */
-    POWERPC_DEF_SVR("MPC8379",
+    POWERPC_DEF_SVR("MPC8379", "MPC8379",
                     CPU_POWERPC_MPC837x,      POWERPC_SVR_8379,      e300)
-    /* MPC8379E                                                              */
-    POWERPC_DEF_SVR("MPC8379E",
+    POWERPC_DEF_SVR("MPC8379E", "MPC8379E",
                     CPU_POWERPC_MPC837x,      POWERPC_SVR_8379E,     e300)
     /* e500 family                                                           */
-    /* PowerPC e500 v1.0 core                                                */
-    POWERPC_DEF("e500_v10",      CPU_POWERPC_e500v1_v10,             e500v1)
-    /* PowerPC e500 v2.0 core                                                */
-    POWERPC_DEF("e500_v20",      CPU_POWERPC_e500v1_v20,             e500v1)
-    /* PowerPC e500v2 v1.0 core                                              */
-    POWERPC_DEF("e500v2_v10",    CPU_POWERPC_e500v2_v10,             e500v2)
-    /* PowerPC e500v2 v2.0 core                                              */
-    POWERPC_DEF("e500v2_v20",    CPU_POWERPC_e500v2_v20,             e500v2)
-    /* PowerPC e500v2 v2.1 core                                              */
-    POWERPC_DEF("e500v2_v21",    CPU_POWERPC_e500v2_v21,             e500v2)
-    /* PowerPC e500v2 v2.2 core                                              */
-    POWERPC_DEF("e500v2_v22",    CPU_POWERPC_e500v2_v22,             e500v2)
-    /* PowerPC e500v2 v3.0 core                                              */
-    POWERPC_DEF("e500v2_v30",    CPU_POWERPC_e500v2_v30,             e500v2)
-    POWERPC_DEF_SVR("e500mc", CPU_POWERPC_e500mc, POWERPC_SVR_E500,  e500mc)
+    POWERPC_DEF("e500_v10",      CPU_POWERPC_e500v1_v10,             e500v1,
+                "PowerPC e500 v1.0 core")
+    POWERPC_DEF("e500_v20",      CPU_POWERPC_e500v1_v20,             e500v1,
+                "PowerPC e500 v2.0 core")
+    POWERPC_DEF("e500v2_v10",    CPU_POWERPC_e500v2_v10,             e500v2,
+                "PowerPC e500v2 v1.0 core")
+    POWERPC_DEF("e500v2_v20",    CPU_POWERPC_e500v2_v20,             e500v2,
+                "PowerPC e500v2 v2.0 core")
+    POWERPC_DEF("e500v2_v21",    CPU_POWERPC_e500v2_v21,             e500v2,
+                "PowerPC e500v2 v2.1 core")
+    POWERPC_DEF("e500v2_v22",    CPU_POWERPC_e500v2_v22,             e500v2,
+                "PowerPC e500v2 v2.2 core")
+    POWERPC_DEF("e500v2_v30",    CPU_POWERPC_e500v2_v30,             e500v2,
+                "PowerPC e500v2 v3.0 core")
+    POWERPC_DEF_SVR("e500mc", "e500mc",
+                    CPU_POWERPC_e500mc,       POWERPC_SVR_E500,      e500mc)
 #ifdef TARGET_PPC64
-    POWERPC_DEF_SVR("e5500",    CPU_POWERPC_e5500, POWERPC_SVR_E500, e5500)
+    POWERPC_DEF_SVR("e5500", "e5500",
+                    CPU_POWERPC_e5500,        POWERPC_SVR_E500,      e5500)
 #endif
     /* PowerPC e500 microcontrollers                                         */
-    /* MPC8533 v1.0                                                          */
-    POWERPC_DEF_SVR("MPC8533_v10",
+    POWERPC_DEF_SVR("MPC8533_v10", "MPC8533 v1.0",
                     CPU_POWERPC_MPC8533_v10,  POWERPC_SVR_8533_v10,  e500v2)
-    /* MPC8533 v1.1                                                          */
-    POWERPC_DEF_SVR("MPC8533_v11",
+    POWERPC_DEF_SVR("MPC8533_v11", "MPC8533 v1.1",
                     CPU_POWERPC_MPC8533_v11,  POWERPC_SVR_8533_v11,  e500v2)
-    /* MPC8533E v1.0                                                         */
-    POWERPC_DEF_SVR("MPC8533E_v10",
+    POWERPC_DEF_SVR("MPC8533E_v10", "MPC8533E v1.0",
                     CPU_POWERPC_MPC8533E_v10, POWERPC_SVR_8533E_v10, e500v2)
-    POWERPC_DEF_SVR("MPC8533E_v11",
+    POWERPC_DEF_SVR("MPC8533E_v11", "MPC8533E v1.1",
                     CPU_POWERPC_MPC8533E_v11, POWERPC_SVR_8533E_v11, e500v2)
-    /* MPC8540 v1.0                                                          */
-    POWERPC_DEF_SVR("MPC8540_v10",
+    POWERPC_DEF_SVR("MPC8540_v10", "MPC8540 v1.0",
                     CPU_POWERPC_MPC8540_v10,  POWERPC_SVR_8540_v10,  e500v1)
-    /* MPC8540 v2.0                                                          */
-    POWERPC_DEF_SVR("MPC8540_v20",
+    POWERPC_DEF_SVR("MPC8540_v20", "MPC8540 v2.0",
                     CPU_POWERPC_MPC8540_v20,  POWERPC_SVR_8540_v20,  e500v1)
-    /* MPC8540 v2.1                                                          */
-    POWERPC_DEF_SVR("MPC8540_v21",
+    POWERPC_DEF_SVR("MPC8540_v21", "MPC8540 v2.1",
                     CPU_POWERPC_MPC8540_v21,  POWERPC_SVR_8540_v21,  e500v1)
-    /* MPC8541 v1.0                                                          */
-    POWERPC_DEF_SVR("MPC8541_v10",
+    POWERPC_DEF_SVR("MPC8541_v10", "MPC8541 v1.0",
                     CPU_POWERPC_MPC8541_v10,  POWERPC_SVR_8541_v10,  e500v1)
-    /* MPC8541 v1.1                                                          */
-    POWERPC_DEF_SVR("MPC8541_v11",
+    POWERPC_DEF_SVR("MPC8541_v11", "MPC8541 v1.1",
                     CPU_POWERPC_MPC8541_v11,  POWERPC_SVR_8541_v11,  e500v1)
-    /* MPC8541E v1.0                                                         */
-    POWERPC_DEF_SVR("MPC8541E_v10",
+    POWERPC_DEF_SVR("MPC8541E_v10", "MPC8541E v1.0",
                     CPU_POWERPC_MPC8541E_v10, POWERPC_SVR_8541E_v10, e500v1)
-    /* MPC8541E v1.1                                                         */
-    POWERPC_DEF_SVR("MPC8541E_v11",
+    POWERPC_DEF_SVR("MPC8541E_v11", "MPC8541E v1.1",
                     CPU_POWERPC_MPC8541E_v11, POWERPC_SVR_8541E_v11, e500v1)
-    /* MPC8543 v1.0                                                          */
-    POWERPC_DEF_SVR("MPC8543_v10",
+    POWERPC_DEF_SVR("MPC8543_v10", "MPC8543 v1.0",
                     CPU_POWERPC_MPC8543_v10,  POWERPC_SVR_8543_v10,  e500v2)
-    /* MPC8543 v1.1                                                          */
-    POWERPC_DEF_SVR("MPC8543_v11",
+    POWERPC_DEF_SVR("MPC8543_v11", "MPC8543 v1.1",
                     CPU_POWERPC_MPC8543_v11,  POWERPC_SVR_8543_v11,  e500v2)
-    /* MPC8543 v2.0                                                          */
-    POWERPC_DEF_SVR("MPC8543_v20",
+    POWERPC_DEF_SVR("MPC8543_v20", "MPC8543 v2.0",
                     CPU_POWERPC_MPC8543_v20,  POWERPC_SVR_8543_v20,  e500v2)
-    /* MPC8543 v2.1                                                          */
-    POWERPC_DEF_SVR("MPC8543_v21",
+    POWERPC_DEF_SVR("MPC8543_v21", "MPC8543 v2.1",
                     CPU_POWERPC_MPC8543_v21,  POWERPC_SVR_8543_v21,  e500v2)
-    /* MPC8543E v1.0                                                         */
-    POWERPC_DEF_SVR("MPC8543E_v10",
+    POWERPC_DEF_SVR("MPC8543E_v10", "MPC8543E v1.0",
                     CPU_POWERPC_MPC8543E_v10, POWERPC_SVR_8543E_v10, e500v2)
-    /* MPC8543E v1.1                                                         */
-    POWERPC_DEF_SVR("MPC8543E_v11",
+    POWERPC_DEF_SVR("MPC8543E_v11", "MPC8543E v1.1",
                     CPU_POWERPC_MPC8543E_v11, POWERPC_SVR_8543E_v11, e500v2)
-    /* MPC8543E v2.0                                                         */
-    POWERPC_DEF_SVR("MPC8543E_v20",
+    POWERPC_DEF_SVR("MPC8543E_v20", "MPC8543E v2.0",
                     CPU_POWERPC_MPC8543E_v20, POWERPC_SVR_8543E_v20, e500v2)
-    /* MPC8543E v2.1                                                         */
-    POWERPC_DEF_SVR("MPC8543E_v21",
+    POWERPC_DEF_SVR("MPC8543E_v21", "MPC8543E v2.1",
                     CPU_POWERPC_MPC8543E_v21, POWERPC_SVR_8543E_v21, e500v2)
-    /* MPC8544 v1.0                                                          */
-    POWERPC_DEF_SVR("MPC8544_v10",
+    POWERPC_DEF_SVR("MPC8544_v10", "MPC8544 v1.0",
                     CPU_POWERPC_MPC8544_v10,  POWERPC_SVR_8544_v10,  e500v2)
-    /* MPC8544 v1.1                                                          */
-    POWERPC_DEF_SVR("MPC8544_v11",
+    POWERPC_DEF_SVR("MPC8544_v11", "MPC8544 v1.1",
                     CPU_POWERPC_MPC8544_v11,  POWERPC_SVR_8544_v11,  e500v2)
-    /* MPC8544E v1.0                                                         */
-    POWERPC_DEF_SVR("MPC8544E_v10",
+    POWERPC_DEF_SVR("MPC8544E_v10", "MPC8544E v1.0",
                     CPU_POWERPC_MPC8544E_v10, POWERPC_SVR_8544E_v10, e500v2)
-    /* MPC8544E v1.1                                                         */
-    POWERPC_DEF_SVR("MPC8544E_v11",
+    POWERPC_DEF_SVR("MPC8544E_v11", "MPC8544E v1.1",
                     CPU_POWERPC_MPC8544E_v11, POWERPC_SVR_8544E_v11, e500v2)
-    /* MPC8545 v2.0                                                          */
-    POWERPC_DEF_SVR("MPC8545_v20",
+    POWERPC_DEF_SVR("MPC8545_v20", "MPC8545 v2.0",
                     CPU_POWERPC_MPC8545_v20,  POWERPC_SVR_8545_v20,  e500v2)
-    /* MPC8545 v2.1                                                          */
-    POWERPC_DEF_SVR("MPC8545_v21",
+    POWERPC_DEF_SVR("MPC8545_v21", "MPC8545 v2.1",
                     CPU_POWERPC_MPC8545_v21,  POWERPC_SVR_8545_v21,  e500v2)
-    /* MPC8545E v2.0                                                         */
-    POWERPC_DEF_SVR("MPC8545E_v20",
+    POWERPC_DEF_SVR("MPC8545E_v20", "MPC8545E v2.0",
                     CPU_POWERPC_MPC8545E_v20, POWERPC_SVR_8545E_v20, e500v2)
-    /* MPC8545E v2.1                                                         */
-    POWERPC_DEF_SVR("MPC8545E_v21",
+    POWERPC_DEF_SVR("MPC8545E_v21", "MPC8545E v2.1",
                     CPU_POWERPC_MPC8545E_v21, POWERPC_SVR_8545E_v21, e500v2)
-    /* MPC8547E v2.0                                                         */
-    POWERPC_DEF_SVR("MPC8547E_v20",
+    POWERPC_DEF_SVR("MPC8547E_v20", "MPC8547E v2.0",
                     CPU_POWERPC_MPC8547E_v20, POWERPC_SVR_8547E_v20, e500v2)
-    /* MPC8547E v2.1                                                         */
-    POWERPC_DEF_SVR("MPC8547E_v21",
+    POWERPC_DEF_SVR("MPC8547E_v21", "MPC8547E v2.1",
                     CPU_POWERPC_MPC8547E_v21, POWERPC_SVR_8547E_v21, e500v2)
-    /* MPC8548 v1.0                                                          */
-    POWERPC_DEF_SVR("MPC8548_v10",
+    POWERPC_DEF_SVR("MPC8548_v10", "MPC8548 v1.0",
                     CPU_POWERPC_MPC8548_v10,  POWERPC_SVR_8548_v10,  e500v2)
-    /* MPC8548 v1.1                                                          */
-    POWERPC_DEF_SVR("MPC8548_v11",
+    POWERPC_DEF_SVR("MPC8548_v11", "MPC8548 v1.1",
                     CPU_POWERPC_MPC8548_v11,  POWERPC_SVR_8548_v11,  e500v2)
-    /* MPC8548 v2.0                                                          */
-    POWERPC_DEF_SVR("MPC8548_v20",
+    POWERPC_DEF_SVR("MPC8548_v20", "MPC8548 v2.0",
                     CPU_POWERPC_MPC8548_v20,  POWERPC_SVR_8548_v20,  e500v2)
-    /* MPC8548 v2.1                                                          */
-    POWERPC_DEF_SVR("MPC8548_v21",
+    POWERPC_DEF_SVR("MPC8548_v21", "MPC8548 v2.1",
                     CPU_POWERPC_MPC8548_v21,  POWERPC_SVR_8548_v21,  e500v2)
-    /* MPC8548E v1.0                                                         */
-    POWERPC_DEF_SVR("MPC8548E_v10",
+    POWERPC_DEF_SVR("MPC8548E_v10", "MPC8548E v1.0",
                     CPU_POWERPC_MPC8548E_v10, POWERPC_SVR_8548E_v10, e500v2)
-    /* MPC8548E v1.1                                                         */
-    POWERPC_DEF_SVR("MPC8548E_v11",
+    POWERPC_DEF_SVR("MPC8548E_v11", "MPC8548E v1.1",
                     CPU_POWERPC_MPC8548E_v11, POWERPC_SVR_8548E_v11, e500v2)
-    /* MPC8548E v2.0                                                         */
-    POWERPC_DEF_SVR("MPC8548E_v20",
+    POWERPC_DEF_SVR("MPC8548E_v20", "MPC8548E v2.0",
                     CPU_POWERPC_MPC8548E_v20, POWERPC_SVR_8548E_v20, e500v2)
-    /* MPC8548E v2.1                                                         */
-    POWERPC_DEF_SVR("MPC8548E_v21",
+    POWERPC_DEF_SVR("MPC8548E_v21", "MPC8548E v2.1",
                     CPU_POWERPC_MPC8548E_v21, POWERPC_SVR_8548E_v21, e500v2)
-    /* MPC8555 v1.0                                                          */
-    POWERPC_DEF_SVR("MPC8555_v10",
+    POWERPC_DEF_SVR("MPC8555_v10", "MPC8555 v1.0",
                     CPU_POWERPC_MPC8555_v10,  POWERPC_SVR_8555_v10,  e500v2)
-    /* MPC8555 v1.1                                                          */
-    POWERPC_DEF_SVR("MPC8555_v11",
+    POWERPC_DEF_SVR("MPC8555_v11", "MPC8555 v1.1",
                     CPU_POWERPC_MPC8555_v11,  POWERPC_SVR_8555_v11,  e500v2)
-    /* MPC8555E v1.0                                                         */
-    POWERPC_DEF_SVR("MPC8555E_v10",
+    POWERPC_DEF_SVR("MPC8555E_v10", "MPC8555E v1.0",
                     CPU_POWERPC_MPC8555E_v10, POWERPC_SVR_8555E_v10, e500v2)
-    /* MPC8555E v1.1                                                         */
-    POWERPC_DEF_SVR("MPC8555E_v11",
+    POWERPC_DEF_SVR("MPC8555E_v11", "MPC8555E v1.1",
                     CPU_POWERPC_MPC8555E_v11, POWERPC_SVR_8555E_v11, e500v2)
-    /* MPC8560 v1.0                                                          */
-    POWERPC_DEF_SVR("MPC8560_v10",
+    POWERPC_DEF_SVR("MPC8560_v10", "MPC8560 v1.0",
                     CPU_POWERPC_MPC8560_v10,  POWERPC_SVR_8560_v10,  e500v2)
-    /* MPC8560 v2.0                                                          */
-    POWERPC_DEF_SVR("MPC8560_v20",
+    POWERPC_DEF_SVR("MPC8560_v20", "MPC8560 v2.0",
                     CPU_POWERPC_MPC8560_v20,  POWERPC_SVR_8560_v20,  e500v2)
-    /* MPC8560 v2.1                                                          */
-    POWERPC_DEF_SVR("MPC8560_v21",
+    POWERPC_DEF_SVR("MPC8560_v21", "MPC8560 v2.1",
                     CPU_POWERPC_MPC8560_v21,  POWERPC_SVR_8560_v21,  e500v2)
-    /* MPC8567                                                               */
-    POWERPC_DEF_SVR("MPC8567",
+    POWERPC_DEF_SVR("MPC8567", "MPC8567",
                     CPU_POWERPC_MPC8567,      POWERPC_SVR_8567,      e500v2)
-    /* MPC8567E                                                              */
-    POWERPC_DEF_SVR("MPC8567E",
+    POWERPC_DEF_SVR("MPC8567E", "MPC8567E",
                     CPU_POWERPC_MPC8567E,     POWERPC_SVR_8567E,     e500v2)
-    /* MPC8568                                                               */
-    POWERPC_DEF_SVR("MPC8568",
+    POWERPC_DEF_SVR("MPC8568", "MPC8568",
                     CPU_POWERPC_MPC8568,      POWERPC_SVR_8568,      e500v2)
-    /* MPC8568E                                                              */
-    POWERPC_DEF_SVR("MPC8568E",
+    POWERPC_DEF_SVR("MPC8568E", "MPC8568E",
                     CPU_POWERPC_MPC8568E,     POWERPC_SVR_8568E,     e500v2)
-    /* MPC8572                                                               */
-    POWERPC_DEF_SVR("MPC8572",
+    POWERPC_DEF_SVR("MPC8572", "MPC8572",
                     CPU_POWERPC_MPC8572,      POWERPC_SVR_8572,      e500v2)
-    /* MPC8572E                                                              */
-    POWERPC_DEF_SVR("MPC8572E",
+    POWERPC_DEF_SVR("MPC8572E", "MPC8572E",
                     CPU_POWERPC_MPC8572E,     POWERPC_SVR_8572E,     e500v2)
     /* e600 family                                                           */
-    /* PowerPC e600 core                                                     */
-    POWERPC_DEF("e600",          CPU_POWERPC_e600,                   7400)
+    POWERPC_DEF("e600",          CPU_POWERPC_e600,                   7400,
+                "PowerPC e600 core")
     /* PowerPC e600 microcontrollers                                         */
 #if defined (TODO)
-    /* MPC8610                                                               */
-    POWERPC_DEF_SVR("MPC8610",
+    POWERPC_DEF_SVR("MPC8610", "MPC8610",
                     CPU_POWERPC_MPC8610,      POWERPC_SVR_8610,      7400)
 #endif
-    /* MPC8641                                                               */
-    POWERPC_DEF_SVR("MPC8641",
+    POWERPC_DEF_SVR("MPC8641", "MPC8641",
                     CPU_POWERPC_MPC8641,      POWERPC_SVR_8641,      7400)
-    /* MPC8641D                                                              */
-    POWERPC_DEF_SVR("MPC8641D",
+    POWERPC_DEF_SVR("MPC8641D", "MPC8641D",
                     CPU_POWERPC_MPC8641D,     POWERPC_SVR_8641D,     7400)
     /* 32 bits "classic" PowerPC                                             */
     /* PowerPC 6xx family                                                    */
-    /* PowerPC 601v0                                                         */
-    POWERPC_DEF("601_v0",        CPU_POWERPC_601_v0,                 601)
-    /* PowerPC 601v1                                                         */
-    POWERPC_DEF("601_v1",        CPU_POWERPC_601_v1,                 601)
-    /* PowerPC 601v2                                                         */
-    POWERPC_DEF("601_v2",        CPU_POWERPC_601_v2,                 601v)
-    /* PowerPC 602                                                           */
-    POWERPC_DEF("602",           CPU_POWERPC_602,                    602)
-    /* PowerPC 603                                                           */
-    POWERPC_DEF("603",           CPU_POWERPC_603,                    603)
-    /* PowerPC 603e v1.1                                                     */
-    POWERPC_DEF("603e_v1.1",     CPU_POWERPC_603E_v11,               603E)
-    /* PowerPC 603e v1.2                                                     */
-    POWERPC_DEF("603e_v1.2",     CPU_POWERPC_603E_v12,               603E)
-    /* PowerPC 603e v1.3                                                     */
-    POWERPC_DEF("603e_v1.3",     CPU_POWERPC_603E_v13,               603E)
-    /* PowerPC 603e v1.4                                                     */
-    POWERPC_DEF("603e_v1.4",     CPU_POWERPC_603E_v14,               603E)
-    /* PowerPC 603e v2.2                                                     */
-    POWERPC_DEF("603e_v2.2",     CPU_POWERPC_603E_v22,               603E)
-    /* PowerPC 603e v3                                                       */
-    POWERPC_DEF("603e_v3",       CPU_POWERPC_603E_v3,                603E)
-    /* PowerPC 603e v4                                                       */
-    POWERPC_DEF("603e_v4",       CPU_POWERPC_603E_v4,                603E)
-    /* PowerPC 603e v4.1                                                     */
-    POWERPC_DEF("603e_v4.1",     CPU_POWERPC_603E_v41,               603E)
-    /* PowerPC 603e (aka PID7)                                               */
-    POWERPC_DEF("603e7",         CPU_POWERPC_603E7,                  603E)
-    /* PowerPC 603e7t                                                        */
-    POWERPC_DEF("603e7t",        CPU_POWERPC_603E7t,                 603E)
-    /* PowerPC 603e7v                                                        */
-    POWERPC_DEF("603e7v",        CPU_POWERPC_603E7v,                 603E)
-    /* PowerPC 603e7v1                                                       */
-    POWERPC_DEF("603e7v1",       CPU_POWERPC_603E7v1,                603E)
-    /* PowerPC 603e7v2                                                       */
-    POWERPC_DEF("603e7v2",       CPU_POWERPC_603E7v2,                603E)
-    /* PowerPC 603p (aka PID7v)                                              */
-    POWERPC_DEF("603p",          CPU_POWERPC_603P,                   603E)
-    /* PowerPC 604                                                           */
-    POWERPC_DEF("604",           CPU_POWERPC_604,                    604)
-    /* PowerPC 604e v1.0                                                     */
-    POWERPC_DEF("604e_v1.0",     CPU_POWERPC_604E_v10,               604E)
-    /* PowerPC 604e v2.2                                                     */
-    POWERPC_DEF("604e_v2.2",     CPU_POWERPC_604E_v22,               604E)
-    /* PowerPC 604e v2.4                                                     */
-    POWERPC_DEF("604e_v2.4",     CPU_POWERPC_604E_v24,               604E)
-    /* PowerPC 604r (aka PIDA)                                               */
-    POWERPC_DEF("604r",          CPU_POWERPC_604R,                   604E)
+    POWERPC_DEF("601_v0",        CPU_POWERPC_601_v0,                 601,
+                "PowerPC 601v0")
+    POWERPC_DEF("601_v1",        CPU_POWERPC_601_v1,                 601,
+                "PowerPC 601v1")
+    POWERPC_DEF("601_v2",        CPU_POWERPC_601_v2,                 601v,
+                "PowerPC 601v2")
+    POWERPC_DEF("602",           CPU_POWERPC_602,                    602,
+                "PowerPC 602")
+    POWERPC_DEF("603",           CPU_POWERPC_603,                    603,
+                "PowerPC 603")
+    POWERPC_DEF("603e_v1.1",     CPU_POWERPC_603E_v11,               603E,
+                "PowerPC 603e v1.1")
+    POWERPC_DEF("603e_v1.2",     CPU_POWERPC_603E_v12,               603E,
+                "PowerPC 603e v1.2")
+    POWERPC_DEF("603e_v1.3",     CPU_POWERPC_603E_v13,               603E,
+                "PowerPC 603e v1.3")
+    POWERPC_DEF("603e_v1.4",     CPU_POWERPC_603E_v14,               603E,
+                "PowerPC 603e v1.4")
+    POWERPC_DEF("603e_v2.2",     CPU_POWERPC_603E_v22,               603E,
+                "PowerPC 603e v2.2")
+    POWERPC_DEF("603e_v3",       CPU_POWERPC_603E_v3,                603E,
+                "PowerPC 603e v3")
+    POWERPC_DEF("603e_v4",       CPU_POWERPC_603E_v4,                603E,
+                "PowerPC 603e v4")
+    POWERPC_DEF("603e_v4.1",     CPU_POWERPC_603E_v41,               603E,
+                "PowerPC 603e v4.1")
+    POWERPC_DEF("603e7",         CPU_POWERPC_603E7,                  603E,
+                "PowerPC 603e (aka PID7)")
+    POWERPC_DEF("603e7t",        CPU_POWERPC_603E7t,                 603E,
+                "PowerPC 603e7t")
+    POWERPC_DEF("603e7v",        CPU_POWERPC_603E7v,                 603E,
+                "PowerPC 603e7v")
+    POWERPC_DEF("603e7v1",       CPU_POWERPC_603E7v1,                603E,
+                "PowerPC 603e7v1")
+    POWERPC_DEF("603e7v2",       CPU_POWERPC_603E7v2,                603E,
+                "PowerPC 603e7v2")
+    POWERPC_DEF("603p",          CPU_POWERPC_603P,                   603E,
+                "PowerPC 603p (aka PID7v)")
+    POWERPC_DEF("604",           CPU_POWERPC_604,                    604,
+                "PowerPC 604")
+    POWERPC_DEF("604e_v1.0",     CPU_POWERPC_604E_v10,               604E,
+                "PowerPC 604e v1.0")
+    POWERPC_DEF("604e_v2.2",     CPU_POWERPC_604E_v22,               604E,
+                "PowerPC 604e v2.2")
+    POWERPC_DEF("604e_v2.4",     CPU_POWERPC_604E_v24,               604E,
+                "PowerPC 604e v2.4")
+    POWERPC_DEF("604r",          CPU_POWERPC_604R,                   604E,
+                "PowerPC 604r (aka PIDA)")
 #if defined(TODO)
-    /* PowerPC 604ev                                                         */
-    POWERPC_DEF("604ev",         CPU_POWERPC_604EV,                  604E)
+    POWERPC_DEF("604ev",         CPU_POWERPC_604EV,                  604E,
+                "PowerPC 604ev")
 #endif
     /* PowerPC 7xx family                                                    */
-    /* PowerPC 740 v1.0 (G3)                                                 */
-    POWERPC_DEF("740_v1.0",      CPU_POWERPC_7x0_v10,                740)
-    /* PowerPC 750 v1.0 (G3)                                                 */
-    POWERPC_DEF("750_v1.0",      CPU_POWERPC_7x0_v10,                750)
-    /* PowerPC 740 v2.0 (G3)                                                 */
-    POWERPC_DEF("740_v2.0",      CPU_POWERPC_7x0_v20,                740)
-    /* PowerPC 750 v2.0 (G3)                                                 */
-    POWERPC_DEF("750_v2.0",      CPU_POWERPC_7x0_v20,                750)
-    /* PowerPC 740 v2.1 (G3)                                                 */
-    POWERPC_DEF("740_v2.1",      CPU_POWERPC_7x0_v21,                740)
-    /* PowerPC 750 v2.1 (G3)                                                 */
-    POWERPC_DEF("750_v2.1",      CPU_POWERPC_7x0_v21,                750)
-    /* PowerPC 740 v2.2 (G3)                                                 */
-    POWERPC_DEF("740_v2.2",      CPU_POWERPC_7x0_v22,                740)
-    /* PowerPC 750 v2.2 (G3)                                                 */
-    POWERPC_DEF("750_v2.2",      CPU_POWERPC_7x0_v22,                750)
-    /* PowerPC 740 v3.0 (G3)                                                 */
-    POWERPC_DEF("740_v3.0",      CPU_POWERPC_7x0_v30,                740)
-    /* PowerPC 750 v3.0 (G3)                                                 */
-    POWERPC_DEF("750_v3.0",      CPU_POWERPC_7x0_v30,                750)
-    /* PowerPC 740 v3.1 (G3)                                                 */
-    POWERPC_DEF("740_v3.1",      CPU_POWERPC_7x0_v31,                740)
-    /* PowerPC 750 v3.1 (G3)                                                 */
-    POWERPC_DEF("750_v3.1",      CPU_POWERPC_7x0_v31,                750)
-    /* PowerPC 740E (G3)                                                     */
-    POWERPC_DEF("740e",          CPU_POWERPC_740E,                   740)
-    /* PowerPC 750E (G3)                                                     */
-    POWERPC_DEF("750e",          CPU_POWERPC_750E,                   750)
-    /* PowerPC 740P (G3)                                                     */
-    POWERPC_DEF("740p",          CPU_POWERPC_7x0P,                   740)
-    /* PowerPC 750P (G3)                                                     */
-    POWERPC_DEF("750p",          CPU_POWERPC_7x0P,                   750)
-    /* PowerPC 750CL v1.0                                                    */
-    POWERPC_DEF("750cl_v1.0",    CPU_POWERPC_750CL_v10,              750cl)
-    /* PowerPC 750CL v2.0                                                    */
-    POWERPC_DEF("750cl_v2.0",    CPU_POWERPC_750CL_v20,              750cl)
-    /* PowerPC 750CX v1.0 (G3 embedded)                                      */
-    POWERPC_DEF("750cx_v1.0",    CPU_POWERPC_750CX_v10,              750cx)
-    /* PowerPC 750CX v2.1 (G3 embedded)                                      */
-    POWERPC_DEF("750cx_v2.0",    CPU_POWERPC_750CX_v20,              750cx)
-    /* PowerPC 750CX v2.1 (G3 embedded)                                      */
-    POWERPC_DEF("750cx_v2.1",    CPU_POWERPC_750CX_v21,              750cx)
-    /* PowerPC 750CX v2.2 (G3 embedded)                                      */
-    POWERPC_DEF("750cx_v2.2",    CPU_POWERPC_750CX_v22,              750cx)
-    /* PowerPC 750CXe v2.1 (G3 embedded)                                     */
-    POWERPC_DEF("750cxe_v2.1",   CPU_POWERPC_750CXE_v21,             750cx)
-    /* PowerPC 750CXe v2.2 (G3 embedded)                                     */
-    POWERPC_DEF("750cxe_v2.2",   CPU_POWERPC_750CXE_v22,             750cx)
-    /* PowerPC 750CXe v2.3 (G3 embedded)                                     */
-    POWERPC_DEF("750cxe_v2.3",   CPU_POWERPC_750CXE_v23,             750cx)
-    /* PowerPC 750CXe v2.4 (G3 embedded)                                     */
-    POWERPC_DEF("750cxe_v2.4",   CPU_POWERPC_750CXE_v24,             750cx)
-    /* PowerPC 750CXe v2.4b (G3 embedded)                                    */
-    POWERPC_DEF("750cxe_v2.4b",  CPU_POWERPC_750CXE_v24b,            750cx)
-    /* PowerPC 750CXe v3.0 (G3 embedded)                                     */
-    POWERPC_DEF("750cxe_v3.0",   CPU_POWERPC_750CXE_v30,             750cx)
-    /* PowerPC 750CXe v3.1 (G3 embedded)                                     */
-    POWERPC_DEF("750cxe_v3.1",   CPU_POWERPC_750CXE_v31,             750cx)
-    /* PowerPC 750CXe v3.1b (G3 embedded)                                    */
-    POWERPC_DEF("750cxe_v3.1b",  CPU_POWERPC_750CXE_v31b,            750cx)
-    /* PowerPC 750CXr (G3 embedded)                                          */
-    POWERPC_DEF("750cxr",        CPU_POWERPC_750CXR,                 750cx)
-    /* PowerPC 750FL (G3 embedded)                                           */
-    POWERPC_DEF("750fl",         CPU_POWERPC_750FL,                  750fx)
-    /* PowerPC 750FX v1.0 (G3 embedded)                                      */
-    POWERPC_DEF("750fx_v1.0",    CPU_POWERPC_750FX_v10,              750fx)
-    /* PowerPC 750FX v2.0 (G3 embedded)                                      */
-    POWERPC_DEF("750fx_v2.0",    CPU_POWERPC_750FX_v20,              750fx)
-    /* PowerPC 750FX v2.1 (G3 embedded)                                      */
-    POWERPC_DEF("750fx_v2.1",    CPU_POWERPC_750FX_v21,              750fx)
-    /* PowerPC 750FX v2.2 (G3 embedded)                                      */
-    POWERPC_DEF("750fx_v2.2",    CPU_POWERPC_750FX_v22,              750fx)
-    /* PowerPC 750FX v2.3 (G3 embedded)                                      */
-    POWERPC_DEF("750fx_v2.3",    CPU_POWERPC_750FX_v23,              750fx)
-    /* PowerPC 750GL (G3 embedded)                                           */
-    POWERPC_DEF("750gl",         CPU_POWERPC_750GL,                  750gx)
-    /* PowerPC 750GX v1.0 (G3 embedded)                                      */
-    POWERPC_DEF("750gx_v1.0",    CPU_POWERPC_750GX_v10,              750gx)
-    /* PowerPC 750GX v1.1 (G3 embedded)                                      */
-    POWERPC_DEF("750gx_v1.1",    CPU_POWERPC_750GX_v11,              750gx)
-    /* PowerPC 750GX v1.2 (G3 embedded)                                      */
-    POWERPC_DEF("750gx_v1.2",    CPU_POWERPC_750GX_v12,              750gx)
-    /* PowerPC 750L v2.0 (G3 embedded)                                       */
-    POWERPC_DEF("750l_v2.0",     CPU_POWERPC_750L_v20,               750)
-    /* PowerPC 750L v2.1 (G3 embedded)                                       */
-    POWERPC_DEF("750l_v2.1",     CPU_POWERPC_750L_v21,               750)
-    /* PowerPC 750L v2.2 (G3 embedded)                                       */
-    POWERPC_DEF("750l_v2.2",     CPU_POWERPC_750L_v22,               750)
-    /* PowerPC 750L v3.0 (G3 embedded)                                       */
-    POWERPC_DEF("750l_v3.0",     CPU_POWERPC_750L_v30,               750)
-    /* PowerPC 750L v3.2 (G3 embedded)                                       */
-    POWERPC_DEF("750l_v3.2",     CPU_POWERPC_750L_v32,               750)
-    /* PowerPC 745 v1.0                                                      */
-    POWERPC_DEF("745_v1.0",      CPU_POWERPC_7x5_v10,                745)
-    /* PowerPC 755 v1.0                                                      */
-    POWERPC_DEF("755_v1.0",      CPU_POWERPC_7x5_v10,                755)
-    /* PowerPC 745 v1.1                                                      */
-    POWERPC_DEF("745_v1.1",      CPU_POWERPC_7x5_v11,                745)
-    /* PowerPC 755 v1.1                                                      */
-    POWERPC_DEF("755_v1.1",      CPU_POWERPC_7x5_v11,                755)
-    /* PowerPC 745 v2.0                                                      */
-    POWERPC_DEF("745_v2.0",      CPU_POWERPC_7x5_v20,                745)
-    /* PowerPC 755 v2.0                                                      */
-    POWERPC_DEF("755_v2.0",      CPU_POWERPC_7x5_v20,                755)
-    /* PowerPC 745 v2.1                                                      */
-    POWERPC_DEF("745_v2.1",      CPU_POWERPC_7x5_v21,                745)
-    /* PowerPC 755 v2.1                                                      */
-    POWERPC_DEF("755_v2.1",      CPU_POWERPC_7x5_v21,                755)
-    /* PowerPC 745 v2.2                                                      */
-    POWERPC_DEF("745_v2.2",      CPU_POWERPC_7x5_v22,                745)
-    /* PowerPC 755 v2.2                                                      */
-    POWERPC_DEF("755_v2.2",      CPU_POWERPC_7x5_v22,                755)
-    /* PowerPC 745 v2.3                                                      */
-    POWERPC_DEF("745_v2.3",      CPU_POWERPC_7x5_v23,                745)
-    /* PowerPC 755 v2.3                                                      */
-    POWERPC_DEF("755_v2.3",      CPU_POWERPC_7x5_v23,                755)
-    /* PowerPC 745 v2.4                                                      */
-    POWERPC_DEF("745_v2.4",      CPU_POWERPC_7x5_v24,                745)
-    /* PowerPC 755 v2.4                                                      */
-    POWERPC_DEF("755_v2.4",      CPU_POWERPC_7x5_v24,                755)
-    /* PowerPC 745 v2.5                                                      */
-    POWERPC_DEF("745_v2.5",      CPU_POWERPC_7x5_v25,                745)
-    /* PowerPC 755 v2.5                                                      */
-    POWERPC_DEF("755_v2.5",      CPU_POWERPC_7x5_v25,                755)
-    /* PowerPC 745 v2.6                                                      */
-    POWERPC_DEF("745_v2.6",      CPU_POWERPC_7x5_v26,                745)
-    /* PowerPC 755 v2.6                                                      */
-    POWERPC_DEF("755_v2.6",      CPU_POWERPC_7x5_v26,                755)
-    /* PowerPC 745 v2.7                                                      */
-    POWERPC_DEF("745_v2.7",      CPU_POWERPC_7x5_v27,                745)
-    /* PowerPC 755 v2.7                                                      */
-    POWERPC_DEF("755_v2.7",      CPU_POWERPC_7x5_v27,                755)
-    /* PowerPC 745 v2.8                                                      */
-    POWERPC_DEF("745_v2.8",      CPU_POWERPC_7x5_v28,                745)
-    /* PowerPC 755 v2.8                                                      */
-    POWERPC_DEF("755_v2.8",      CPU_POWERPC_7x5_v28,                755)
+    POWERPC_DEF("740_v1.0",      CPU_POWERPC_7x0_v10,                740,
+                "PowerPC 740 v1.0 (G3)")
+    POWERPC_DEF("750_v1.0",      CPU_POWERPC_7x0_v10,                750,
+                "PowerPC 750 v1.0 (G3)")
+    POWERPC_DEF("740_v2.0",      CPU_POWERPC_7x0_v20,                740,
+                "PowerPC 740 v2.0 (G3)")
+    POWERPC_DEF("750_v2.0",      CPU_POWERPC_7x0_v20,                750,
+                "PowerPC 750 v2.0 (G3)")
+    POWERPC_DEF("740_v2.1",      CPU_POWERPC_7x0_v21,                740,
+                "PowerPC 740 v2.1 (G3)")
+    POWERPC_DEF("750_v2.1",      CPU_POWERPC_7x0_v21,                750,
+                "PowerPC 750 v2.1 (G3)")
+    POWERPC_DEF("740_v2.2",      CPU_POWERPC_7x0_v22,                740,
+                "PowerPC 740 v2.2 (G3)")
+    POWERPC_DEF("750_v2.2",      CPU_POWERPC_7x0_v22,                750,
+                "PowerPC 750 v2.2 (G3)")
+    POWERPC_DEF("740_v3.0",      CPU_POWERPC_7x0_v30,                740,
+                "PowerPC 740 v3.0 (G3)")
+    POWERPC_DEF("750_v3.0",      CPU_POWERPC_7x0_v30,                750,
+                "PowerPC 750 v3.0 (G3)")
+    POWERPC_DEF("740_v3.1",      CPU_POWERPC_7x0_v31,                740,
+                "PowerPC 740 v3.1 (G3)")
+    POWERPC_DEF("750_v3.1",      CPU_POWERPC_7x0_v31,                750,
+                "PowerPC 750 v3.1 (G3)")
+    POWERPC_DEF("740e",          CPU_POWERPC_740E,                   740,
+                "PowerPC 740E (G3)")
+    POWERPC_DEF("750e",          CPU_POWERPC_750E,                   750,
+                "PowerPC 750E (G3)")
+    POWERPC_DEF("740p",          CPU_POWERPC_7x0P,                   740,
+                "PowerPC 740P (G3)")
+    POWERPC_DEF("750p",          CPU_POWERPC_7x0P,                   750,
+                "PowerPC 750P (G3)")
+    POWERPC_DEF("750cl_v1.0",    CPU_POWERPC_750CL_v10,              750cl,
+                "PowerPC 750CL v1.0")
+    POWERPC_DEF("750cl_v2.0",    CPU_POWERPC_750CL_v20,              750cl,
+                "PowerPC 750CL v2.0")
+    POWERPC_DEF("750cx_v1.0",    CPU_POWERPC_750CX_v10,              750cx,
+                "PowerPC 750CX v1.0 (G3 embedded)")
+    POWERPC_DEF("750cx_v2.0",    CPU_POWERPC_750CX_v20,              750cx,
+                "PowerPC 750CX v2.1 (G3 embedded)")
+    POWERPC_DEF("750cx_v2.1",    CPU_POWERPC_750CX_v21,              750cx,
+                "PowerPC 750CX v2.1 (G3 embedded)")
+    POWERPC_DEF("750cx_v2.2",    CPU_POWERPC_750CX_v22,              750cx,
+                "PowerPC 750CX v2.2 (G3 embedded)")
+    POWERPC_DEF("750cxe_v2.1",   CPU_POWERPC_750CXE_v21,             750cx,
+                "PowerPC 750CXe v2.1 (G3 embedded)")
+    POWERPC_DEF("750cxe_v2.2",   CPU_POWERPC_750CXE_v22,             750cx,
+                "PowerPC 750CXe v2.2 (G3 embedded)")
+    POWERPC_DEF("750cxe_v2.3",   CPU_POWERPC_750CXE_v23,             750cx,
+                "PowerPC 750CXe v2.3 (G3 embedded)")
+    POWERPC_DEF("750cxe_v2.4",   CPU_POWERPC_750CXE_v24,             750cx,
+                "PowerPC 750CXe v2.4 (G3 embedded)")
+    POWERPC_DEF("750cxe_v2.4b",  CPU_POWERPC_750CXE_v24b,            750cx,
+                "PowerPC 750CXe v2.4b (G3 embedded)")
+    POWERPC_DEF("750cxe_v3.0",   CPU_POWERPC_750CXE_v30,             750cx,
+                "PowerPC 750CXe v3.0 (G3 embedded)")
+    POWERPC_DEF("750cxe_v3.1",   CPU_POWERPC_750CXE_v31,             750cx,
+                "PowerPC 750CXe v3.1 (G3 embedded)")
+    POWERPC_DEF("750cxe_v3.1b",  CPU_POWERPC_750CXE_v31b,            750cx,
+                "PowerPC 750CXe v3.1b (G3 embedded)")
+    POWERPC_DEF("750cxr",        CPU_POWERPC_750CXR,                 750cx,
+                "PowerPC 750CXr (G3 embedded)")
+    POWERPC_DEF("750fl",         CPU_POWERPC_750FL,                  750fx,
+                "PowerPC 750FL (G3 embedded)")
+    POWERPC_DEF("750fx_v1.0",    CPU_POWERPC_750FX_v10,              750fx,
+                "PowerPC 750FX v1.0 (G3 embedded)")
+    POWERPC_DEF("750fx_v2.0",    CPU_POWERPC_750FX_v20,              750fx,
+                "PowerPC 750FX v2.0 (G3 embedded)")
+    POWERPC_DEF("750fx_v2.1",    CPU_POWERPC_750FX_v21,              750fx,
+                "PowerPC 750FX v2.1 (G3 embedded)")
+    POWERPC_DEF("750fx_v2.2",    CPU_POWERPC_750FX_v22,              750fx,
+                "PowerPC 750FX v2.2 (G3 embedded)")
+    POWERPC_DEF("750fx_v2.3",    CPU_POWERPC_750FX_v23,              750fx,
+                "PowerPC 750FX v2.3 (G3 embedded)")
+    POWERPC_DEF("750gl",         CPU_POWERPC_750GL,                  750gx,
+                "PowerPC 750GL (G3 embedded)")
+    POWERPC_DEF("750gx_v1.0",    CPU_POWERPC_750GX_v10,              750gx,
+                "PowerPC 750GX v1.0 (G3 embedded)")
+    POWERPC_DEF("750gx_v1.1",    CPU_POWERPC_750GX_v11,              750gx,
+                "PowerPC 750GX v1.1 (G3 embedded)")
+    POWERPC_DEF("750gx_v1.2",    CPU_POWERPC_750GX_v12,              750gx,
+                "PowerPC 750GX v1.2 (G3 embedded)")
+    POWERPC_DEF("750l_v2.0",     CPU_POWERPC_750L_v20,               750,
+                "PowerPC 750L v2.0 (G3 embedded)")
+    POWERPC_DEF("750l_v2.1",     CPU_POWERPC_750L_v21,               750,
+                "PowerPC 750L v2.1 (G3 embedded)")
+    POWERPC_DEF("750l_v2.2",     CPU_POWERPC_750L_v22,               750,
+                "PowerPC 750L v2.2 (G3 embedded)")
+    POWERPC_DEF("750l_v3.0",     CPU_POWERPC_750L_v30,               750,
+                "PowerPC 750L v3.0 (G3 embedded)")
+    POWERPC_DEF("750l_v3.2",     CPU_POWERPC_750L_v32,               750,
+                "PowerPC 750L v3.2 (G3 embedded)")
+    POWERPC_DEF("745_v1.0",      CPU_POWERPC_7x5_v10,                745,
+                "PowerPC 745 v1.0")
+    POWERPC_DEF("755_v1.0",      CPU_POWERPC_7x5_v10,                755,
+                "PowerPC 755 v1.0")
+    POWERPC_DEF("745_v1.1",      CPU_POWERPC_7x5_v11,                745,
+                "PowerPC 745 v1.1")
+    POWERPC_DEF("755_v1.1",      CPU_POWERPC_7x5_v11,                755,
+                "PowerPC 755 v1.1")
+    POWERPC_DEF("745_v2.0",      CPU_POWERPC_7x5_v20,                745,
+                "PowerPC 745 v2.0")
+    POWERPC_DEF("755_v2.0",      CPU_POWERPC_7x5_v20,                755,
+                "PowerPC 755 v2.0")
+    POWERPC_DEF("745_v2.1",      CPU_POWERPC_7x5_v21,                745,
+                "PowerPC 745 v2.1")
+    POWERPC_DEF("755_v2.1",      CPU_POWERPC_7x5_v21,                755,
+                "PowerPC 755 v2.1")
+    POWERPC_DEF("745_v2.2",      CPU_POWERPC_7x5_v22,                745,
+                "PowerPC 745 v2.2")
+    POWERPC_DEF("755_v2.2",      CPU_POWERPC_7x5_v22,                755,
+                "PowerPC 755 v2.2")
+    POWERPC_DEF("745_v2.3",      CPU_POWERPC_7x5_v23,                745,
+                "PowerPC 745 v2.3")
+    POWERPC_DEF("755_v2.3",      CPU_POWERPC_7x5_v23,                755,
+                "PowerPC 755 v2.3")
+    POWERPC_DEF("745_v2.4",      CPU_POWERPC_7x5_v24,                745,
+                "PowerPC 745 v2.4")
+    POWERPC_DEF("755_v2.4",      CPU_POWERPC_7x5_v24,                755,
+                "PowerPC 755 v2.4")
+    POWERPC_DEF("745_v2.5",      CPU_POWERPC_7x5_v25,                745,
+                "PowerPC 745 v2.5")
+    POWERPC_DEF("755_v2.5",      CPU_POWERPC_7x5_v25,                755,
+                "PowerPC 755 v2.5")
+    POWERPC_DEF("745_v2.6",      CPU_POWERPC_7x5_v26,                745,
+                "PowerPC 745 v2.6")
+    POWERPC_DEF("755_v2.6",      CPU_POWERPC_7x5_v26,                755,
+                "PowerPC 755 v2.6")
+    POWERPC_DEF("745_v2.7",      CPU_POWERPC_7x5_v27,                745,
+                "PowerPC 745 v2.7")
+    POWERPC_DEF("755_v2.7",      CPU_POWERPC_7x5_v27,                755,
+                "PowerPC 755 v2.7")
+    POWERPC_DEF("745_v2.8",      CPU_POWERPC_7x5_v28,                745,
+                "PowerPC 745 v2.8")
+    POWERPC_DEF("755_v2.8",      CPU_POWERPC_7x5_v28,                755,
+                "PowerPC 755 v2.8")
 #if defined (TODO)
-    /* PowerPC 745P (G3)                                                     */
-    POWERPC_DEF("745p",          CPU_POWERPC_7x5P,                   745)
-    /* PowerPC 755P (G3)                                                     */
-    POWERPC_DEF("755p",          CPU_POWERPC_7x5P,                   755)
+    POWERPC_DEF("745p",          CPU_POWERPC_7x5P,                   745,
+                "PowerPC 745P (G3)")
+    POWERPC_DEF("755p",          CPU_POWERPC_7x5P,                   755,
+                "PowerPC 755P (G3)")
 #endif
     /* PowerPC 74xx family                                                   */
-    /* PowerPC 7400 v1.0 (G4)                                                */
-    POWERPC_DEF("7400_v1.0",     CPU_POWERPC_7400_v10,               7400)
-    /* PowerPC 7400 v1.1 (G4)                                                */
-    POWERPC_DEF("7400_v1.1",     CPU_POWERPC_7400_v11,               7400)
-    /* PowerPC 7400 v2.0 (G4)                                                */
-    POWERPC_DEF("7400_v2.0",     CPU_POWERPC_7400_v20,               7400)
-    /* PowerPC 7400 v2.1 (G4)                                                */
-    POWERPC_DEF("7400_v2.1",     CPU_POWERPC_7400_v21,               7400)
-    /* PowerPC 7400 v2.2 (G4)                                                */
-    POWERPC_DEF("7400_v2.2",     CPU_POWERPC_7400_v22,               7400)
-    /* PowerPC 7400 v2.6 (G4)                                                */
-    POWERPC_DEF("7400_v2.6",     CPU_POWERPC_7400_v26,               7400)
-    /* PowerPC 7400 v2.7 (G4)                                                */
-    POWERPC_DEF("7400_v2.7",     CPU_POWERPC_7400_v27,               7400)
-    /* PowerPC 7400 v2.8 (G4)                                                */
-    POWERPC_DEF("7400_v2.8",     CPU_POWERPC_7400_v28,               7400)
-    /* PowerPC 7400 v2.9 (G4)                                                */
-    POWERPC_DEF("7400_v2.9",     CPU_POWERPC_7400_v29,               7400)
-    /* PowerPC 7410 v1.0 (G4)                                                */
-    POWERPC_DEF("7410_v1.0",     CPU_POWERPC_7410_v10,               7410)
-    /* PowerPC 7410 v1.1 (G4)                                                */
-    POWERPC_DEF("7410_v1.1",     CPU_POWERPC_7410_v11,               7410)
-    /* PowerPC 7410 v1.2 (G4)                                                */
-    POWERPC_DEF("7410_v1.2",     CPU_POWERPC_7410_v12,               7410)
-    /* PowerPC 7410 v1.3 (G4)                                                */
-    POWERPC_DEF("7410_v1.3",     CPU_POWERPC_7410_v13,               7410)
-    /* PowerPC 7410 v1.4 (G4)                                                */
-    POWERPC_DEF("7410_v1.4",     CPU_POWERPC_7410_v14,               7410)
-    /* PowerPC 7448 v1.0 (G4)                                                */
-    POWERPC_DEF("7448_v1.0",     CPU_POWERPC_7448_v10,               7400)
-    /* PowerPC 7448 v1.1 (G4)                                                */
-    POWERPC_DEF("7448_v1.1",     CPU_POWERPC_7448_v11,               7400)
-    /* PowerPC 7448 v2.0 (G4)                                                */
-    POWERPC_DEF("7448_v2.0",     CPU_POWERPC_7448_v20,               7400)
-    /* PowerPC 7448 v2.1 (G4)                                                */
-    POWERPC_DEF("7448_v2.1",     CPU_POWERPC_7448_v21,               7400)
-    /* PowerPC 7450 v1.0 (G4)                                                */
-    POWERPC_DEF("7450_v1.0",     CPU_POWERPC_7450_v10,               7450)
-    /* PowerPC 7450 v1.1 (G4)                                                */
-    POWERPC_DEF("7450_v1.1",     CPU_POWERPC_7450_v11,               7450)
-    /* PowerPC 7450 v1.2 (G4)                                                */
-    POWERPC_DEF("7450_v1.2",     CPU_POWERPC_7450_v12,               7450)
-    /* PowerPC 7450 v2.0 (G4)                                                */
-    POWERPC_DEF("7450_v2.0",     CPU_POWERPC_7450_v20,               7450)
-    /* PowerPC 7450 v2.1 (G4)                                                */
-    POWERPC_DEF("7450_v2.1",     CPU_POWERPC_7450_v21,               7450)
-    /* PowerPC 7441 v2.1 (G4)                                                */
-    POWERPC_DEF("7441_v2.1",     CPU_POWERPC_7450_v21,               7440)
-    /* PowerPC 7441 v2.3 (G4)                                                */
-    POWERPC_DEF("7441_v2.3",     CPU_POWERPC_74x1_v23,               7440)
-    /* PowerPC 7451 v2.3 (G4)                                                */
-    POWERPC_DEF("7451_v2.3",     CPU_POWERPC_74x1_v23,               7450)
-    /* PowerPC 7441 v2.10 (G4)                                                */
-    POWERPC_DEF("7441_v2.10",    CPU_POWERPC_74x1_v210,              7440)
-    /* PowerPC 7451 v2.10 (G4)                                               */
-    POWERPC_DEF("7451_v2.10",    CPU_POWERPC_74x1_v210,              7450)
-    /* PowerPC 7445 v1.0 (G4)                                                */
-    POWERPC_DEF("7445_v1.0",     CPU_POWERPC_74x5_v10,               7445)
-    /* PowerPC 7455 v1.0 (G4)                                                */
-    POWERPC_DEF("7455_v1.0",     CPU_POWERPC_74x5_v10,               7455)
-    /* PowerPC 7445 v2.1 (G4)                                                */
-    POWERPC_DEF("7445_v2.1",     CPU_POWERPC_74x5_v21,               7445)
-    /* PowerPC 7455 v2.1 (G4)                                                */
-    POWERPC_DEF("7455_v2.1",     CPU_POWERPC_74x5_v21,               7455)
-    /* PowerPC 7445 v3.2 (G4)                                                */
-    POWERPC_DEF("7445_v3.2",     CPU_POWERPC_74x5_v32,               7445)
-    /* PowerPC 7455 v3.2 (G4)                                                */
-    POWERPC_DEF("7455_v3.2",     CPU_POWERPC_74x5_v32,               7455)
-    /* PowerPC 7445 v3.3 (G4)                                                */
-    POWERPC_DEF("7445_v3.3",     CPU_POWERPC_74x5_v33,               7445)
-    /* PowerPC 7455 v3.3 (G4)                                                */
-    POWERPC_DEF("7455_v3.3",     CPU_POWERPC_74x5_v33,               7455)
-    /* PowerPC 7445 v3.4 (G4)                                                */
-    POWERPC_DEF("7445_v3.4",     CPU_POWERPC_74x5_v34,               7445)
-    /* PowerPC 7455 v3.4 (G4)                                                */
-    POWERPC_DEF("7455_v3.4",     CPU_POWERPC_74x5_v34,               7455)
-    /* PowerPC 7447 v1.0 (G4)                                                */
-    POWERPC_DEF("7447_v1.0",     CPU_POWERPC_74x7_v10,               7445)
-    /* PowerPC 7457 v1.0 (G4)                                                */
-    POWERPC_DEF("7457_v1.0",     CPU_POWERPC_74x7_v10,               7455)
-    /* PowerPC 7447 v1.1 (G4)                                                */
-    POWERPC_DEF("7447_v1.1",     CPU_POWERPC_74x7_v11,               7445)
-    /* PowerPC 7457 v1.1 (G4)                                                */
-    POWERPC_DEF("7457_v1.1",     CPU_POWERPC_74x7_v11,               7455)
-    /* PowerPC 7457 v1.2 (G4)                                                */
-    POWERPC_DEF("7457_v1.2",     CPU_POWERPC_74x7_v12,               7455)
-    /* PowerPC 7447A v1.0 (G4)                                               */
-    POWERPC_DEF("7447A_v1.0",    CPU_POWERPC_74x7A_v10,              7445)
-    /* PowerPC 7457A v1.0 (G4)                                               */
-    POWERPC_DEF("7457A_v1.0",    CPU_POWERPC_74x7A_v10,              7455)
-    /* PowerPC 7447A v1.1 (G4)                                               */
-    POWERPC_DEF("7447A_v1.1",    CPU_POWERPC_74x7A_v11,              7445)
-    /* PowerPC 7457A v1.1 (G4)                                               */
-    POWERPC_DEF("7457A_v1.1",    CPU_POWERPC_74x7A_v11,              7455)
-    /* PowerPC 7447A v1.2 (G4)                                               */
-    POWERPC_DEF("7447A_v1.2",    CPU_POWERPC_74x7A_v12,              7445)
-    /* PowerPC 7457A v1.2 (G4)                                               */
-    POWERPC_DEF("7457A_v1.2",    CPU_POWERPC_74x7A_v12,              7455)
+    POWERPC_DEF("7400_v1.0",     CPU_POWERPC_7400_v10,               7400,
+                "PowerPC 7400 v1.0 (G4)")
+    POWERPC_DEF("7400_v1.1",     CPU_POWERPC_7400_v11,               7400,
+                "PowerPC 7400 v1.1 (G4)")
+    POWERPC_DEF("7400_v2.0",     CPU_POWERPC_7400_v20,               7400,
+                "PowerPC 7400 v2.0 (G4)")
+    POWERPC_DEF("7400_v2.1",     CPU_POWERPC_7400_v21,               7400,
+                "PowerPC 7400 v2.1 (G4)")
+    POWERPC_DEF("7400_v2.2",     CPU_POWERPC_7400_v22,               7400,
+                "PowerPC 7400 v2.2 (G4)")
+    POWERPC_DEF("7400_v2.6",     CPU_POWERPC_7400_v26,               7400,
+                "PowerPC 7400 v2.6 (G4)")
+    POWERPC_DEF("7400_v2.7",     CPU_POWERPC_7400_v27,               7400,
+                "PowerPC 7400 v2.7 (G4)")
+    POWERPC_DEF("7400_v2.8",     CPU_POWERPC_7400_v28,               7400,
+                "PowerPC 7400 v2.8 (G4)")
+    POWERPC_DEF("7400_v2.9",     CPU_POWERPC_7400_v29,               7400,
+                "PowerPC 7400 v2.9 (G4)")
+    POWERPC_DEF("7410_v1.0",     CPU_POWERPC_7410_v10,               7410,
+                "PowerPC 7410 v1.0 (G4)")
+    POWERPC_DEF("7410_v1.1",     CPU_POWERPC_7410_v11,               7410,
+                "PowerPC 7410 v1.1 (G4)")
+    POWERPC_DEF("7410_v1.2",     CPU_POWERPC_7410_v12,               7410,
+                "PowerPC 7410 v1.2 (G4)")
+    POWERPC_DEF("7410_v1.3",     CPU_POWERPC_7410_v13,               7410,
+                "PowerPC 7410 v1.3 (G4)")
+    POWERPC_DEF("7410_v1.4",     CPU_POWERPC_7410_v14,               7410,
+                "PowerPC 7410 v1.4 (G4)")
+    POWERPC_DEF("7448_v1.0",     CPU_POWERPC_7448_v10,               7400,
+                "PowerPC 7448 v1.0 (G4)")
+    POWERPC_DEF("7448_v1.1",     CPU_POWERPC_7448_v11,               7400,
+                "PowerPC 7448 v1.1 (G4)")
+    POWERPC_DEF("7448_v2.0",     CPU_POWERPC_7448_v20,               7400,
+                "PowerPC 7448 v2.0 (G4)")
+    POWERPC_DEF("7448_v2.1",     CPU_POWERPC_7448_v21,               7400,
+                "PowerPC 7448 v2.1 (G4)")
+    POWERPC_DEF("7450_v1.0",     CPU_POWERPC_7450_v10,               7450,
+                "PowerPC 7450 v1.0 (G4)")
+    POWERPC_DEF("7450_v1.1",     CPU_POWERPC_7450_v11,               7450,
+                "PowerPC 7450 v1.1 (G4)")
+    POWERPC_DEF("7450_v1.2",     CPU_POWERPC_7450_v12,               7450,
+                "PowerPC 7450 v1.2 (G4)")
+    POWERPC_DEF("7450_v2.0",     CPU_POWERPC_7450_v20,               7450,
+                "PowerPC 7450 v2.0 (G4)")
+    POWERPC_DEF("7450_v2.1",     CPU_POWERPC_7450_v21,               7450,
+                "PowerPC 7450 v2.1 (G4)")
+    POWERPC_DEF("7441_v2.1",     CPU_POWERPC_7450_v21,               7440,
+                "PowerPC 7441 v2.1 (G4)")
+    POWERPC_DEF("7441_v2.3",     CPU_POWERPC_74x1_v23,               7440,
+                "PowerPC 7441 v2.3 (G4)")
+    POWERPC_DEF("7451_v2.3",     CPU_POWERPC_74x1_v23,               7450,
+                "PowerPC 7451 v2.3 (G4)")
+    POWERPC_DEF("7441_v2.10",    CPU_POWERPC_74x1_v210,              7440,
+                "PowerPC 7441 v2.10 (G4)")
+    POWERPC_DEF("7451_v2.10",    CPU_POWERPC_74x1_v210,              7450,
+                "PowerPC 7451 v2.10 (G4)")
+    POWERPC_DEF("7445_v1.0",     CPU_POWERPC_74x5_v10,               7445,
+                "PowerPC 7445 v1.0 (G4)")
+    POWERPC_DEF("7455_v1.0",     CPU_POWERPC_74x5_v10,               7455,
+                "PowerPC 7455 v1.0 (G4)")
+    POWERPC_DEF("7445_v2.1",     CPU_POWERPC_74x5_v21,               7445,
+                "PowerPC 7445 v2.1 (G4)")
+    POWERPC_DEF("7455_v2.1",     CPU_POWERPC_74x5_v21,               7455,
+                "PowerPC 7455 v2.1 (G4)")
+    POWERPC_DEF("7445_v3.2",     CPU_POWERPC_74x5_v32,               7445,
+                "PowerPC 7445 v3.2 (G4)")
+    POWERPC_DEF("7455_v3.2",     CPU_POWERPC_74x5_v32,               7455,
+                "PowerPC 7455 v3.2 (G4)")
+    POWERPC_DEF("7445_v3.3",     CPU_POWERPC_74x5_v33,               7445,
+                "PowerPC 7445 v3.3 (G4)")
+    POWERPC_DEF("7455_v3.3",     CPU_POWERPC_74x5_v33,               7455,
+                "PowerPC 7455 v3.3 (G4)")
+    POWERPC_DEF("7445_v3.4",     CPU_POWERPC_74x5_v34,               7445,
+                "PowerPC 7445 v3.4 (G4)")
+    POWERPC_DEF("7455_v3.4",     CPU_POWERPC_74x5_v34,               7455,
+                "PowerPC 7455 v3.4 (G4)")
+    POWERPC_DEF("7447_v1.0",     CPU_POWERPC_74x7_v10,               7445,
+                "PowerPC 7447 v1.0 (G4)")
+    POWERPC_DEF("7457_v1.0",     CPU_POWERPC_74x7_v10,               7455,
+                "PowerPC 7457 v1.0 (G4)")
+    POWERPC_DEF("7447_v1.1",     CPU_POWERPC_74x7_v11,               7445,
+                "PowerPC 7447 v1.1 (G4)")
+    POWERPC_DEF("7457_v1.1",     CPU_POWERPC_74x7_v11,               7455,
+                "PowerPC 7457 v1.1 (G4)")
+    POWERPC_DEF("7457_v1.2",     CPU_POWERPC_74x7_v12,               7455,
+                "PowerPC 7457 v1.2 (G4)")
+    POWERPC_DEF("7447A_v1.0",    CPU_POWERPC_74x7A_v10,              7445,
+                "PowerPC 7447A v1.0 (G4)")
+    POWERPC_DEF("7457A_v1.0",    CPU_POWERPC_74x7A_v10,              7455,
+                "PowerPC 7457A v1.0 (G4)")
+    POWERPC_DEF("7447A_v1.1",    CPU_POWERPC_74x7A_v11,              7445,
+                "PowerPC 7447A v1.1 (G4)")
+    POWERPC_DEF("7457A_v1.1",    CPU_POWERPC_74x7A_v11,              7455,
+                "PowerPC 7457A v1.1 (G4)")
+    POWERPC_DEF("7447A_v1.2",    CPU_POWERPC_74x7A_v12,              7445,
+                "PowerPC 7447A v1.2 (G4)")
+    POWERPC_DEF("7457A_v1.2",    CPU_POWERPC_74x7A_v12,              7455,
+                "PowerPC 7457A v1.2 (G4)")
     /* 64 bits PowerPC                                                       */
 #if defined (TARGET_PPC64)
-    /* PowerPC 620                                                           */
-    POWERPC_DEF("620",           CPU_POWERPC_620,                    620)
+    POWERPC_DEF("620",           CPU_POWERPC_620,                    620,
+                "PowerPC 620")
 #if defined (TODO)
-    /* PowerPC 630 (POWER3)                                                  */
-    POWERPC_DEF("630",           CPU_POWERPC_630,                    630)
+    POWERPC_DEF("630",           CPU_POWERPC_630,                    630,
+                "PowerPC 630 (POWER3)")
 #endif
 #if defined (TODO)
-    /* PowerPC 631 (Power 3+)                                                */
-    POWERPC_DEF("631",           CPU_POWERPC_631,                    631)
+    POWERPC_DEF("631",           CPU_POWERPC_631,                    631,
+                "PowerPC 631 (Power 3+)")
 #endif
 #if defined (TODO)
-    /* POWER4                                                                */
-    POWERPC_DEF("POWER4",        CPU_POWERPC_POWER4,                 POWER4)
+    POWERPC_DEF("POWER4",        CPU_POWERPC_POWER4,                 POWER4,
+                "POWER4")
 #endif
 #if defined (TODO)
-    /* POWER4p                                                               */
-    POWERPC_DEF("POWER4+",       CPU_POWERPC_POWER4P,                POWER4P)
+    POWERPC_DEF("POWER4+",       CPU_POWERPC_POWER4P,                POWER4P,
+                "POWER4p")
 #endif
 #if defined (TODO)
-    /* POWER5                                                                */
-    POWERPC_DEF("POWER5",        CPU_POWERPC_POWER5,                 POWER5)
-    /* POWER5GR                                                              */
-    POWERPC_DEF("POWER5gr",      CPU_POWERPC_POWER5GR,               POWER5)
+    POWERPC_DEF("POWER5",        CPU_POWERPC_POWER5,                 POWER5,
+                "POWER5")
+    POWERPC_DEF("POWER5gr",      CPU_POWERPC_POWER5GR,               POWER5,
+                "POWER5GR")
 #endif
 #if defined (TODO)
-    /* POWER5+                                                               */
-    POWERPC_DEF("POWER5+",       CPU_POWERPC_POWER5P,                POWER5P)
-    /* POWER5GS                                                              */
-    POWERPC_DEF("POWER5gs",      CPU_POWERPC_POWER5GS,               POWER5P)
+    POWERPC_DEF("POWER5+",       CPU_POWERPC_POWER5P,                POWER5P,
+                "POWER5+")
+    POWERPC_DEF("POWER5gs",      CPU_POWERPC_POWER5GS,               POWER5P,
+                "POWER5GS")
 #endif
 #if defined (TODO)
-    /* POWER6                                                                */
-    POWERPC_DEF("POWER6",        CPU_POWERPC_POWER6,                 POWER6)
-    /* POWER6 running in POWER5 mode                                         */
-    POWERPC_DEF("POWER6_5",      CPU_POWERPC_POWER6_5,               POWER5)
-    /* POWER6A                                                               */
-    POWERPC_DEF("POWER6A",       CPU_POWERPC_POWER6A,                POWER6)
-#endif
-    /* POWER7                                                                */
-    POWERPC_DEF("POWER7_v2.0",   CPU_POWERPC_POWER7_v20,             POWER7)
-    POWERPC_DEF("POWER7_v2.1",   CPU_POWERPC_POWER7_v21,             POWER7)
-    POWERPC_DEF("POWER7_v2.3",   CPU_POWERPC_POWER7_v23,             POWER7)
-    /* PowerPC 970                                                           */
-    POWERPC_DEF("970",           CPU_POWERPC_970,                    970)
-    /* PowerPC 970FX v1.0 (G5)                                               */
-    POWERPC_DEF("970fx_v1.0",    CPU_POWERPC_970FX_v10,              970FX)
-    /* PowerPC 970FX v2.0 (G5)                                               */
-    POWERPC_DEF("970fx_v2.0",    CPU_POWERPC_970FX_v20,              970FX)
-    /* PowerPC 970FX v2.1 (G5)                                               */
-    POWERPC_DEF("970fx_v2.1",    CPU_POWERPC_970FX_v21,              970FX)
-    /* PowerPC 970FX v3.0 (G5)                                               */
-    POWERPC_DEF("970fx_v3.0",    CPU_POWERPC_970FX_v30,              970FX)
-    /* PowerPC 970FX v3.1 (G5)                                               */
-    POWERPC_DEF("970fx_v3.1",    CPU_POWERPC_970FX_v31,              970FX)
-    /* PowerPC 970GX (G5)                                                    */
-    POWERPC_DEF("970gx",         CPU_POWERPC_970GX,                  970GX)
-    /* PowerPC 970MP v1.0                                                    */
-    POWERPC_DEF("970mp_v1.0",    CPU_POWERPC_970MP_v10,              970MP)
-    /* PowerPC 970MP v1.1                                                    */
-    POWERPC_DEF("970mp_v1.1",    CPU_POWERPC_970MP_v11,              970MP)
+    POWERPC_DEF("POWER6",        CPU_POWERPC_POWER6,                 POWER6,
+                "POWER6")
+    POWERPC_DEF("POWER6_5",      CPU_POWERPC_POWER6_5,               POWER5,
+                "POWER6 running in POWER5 mode")
+    POWERPC_DEF("POWER6A",       CPU_POWERPC_POWER6A,                POWER6,
+                "POWER6A")
+#endif
+    POWERPC_DEF("POWER7_v2.0",   CPU_POWERPC_POWER7_v20,             POWER7,
+                "POWER7 v2.0")
+    POWERPC_DEF("POWER7_v2.1",   CPU_POWERPC_POWER7_v21,             POWER7,
+                "POWER7 v2.1")
+    POWERPC_DEF("POWER7_v2.3",   CPU_POWERPC_POWER7_v23,             POWER7,
+                "POWER7 v2.3")
+    POWERPC_DEF("970",           CPU_POWERPC_970,                    970,
+                "PowerPC 970")
+    POWERPC_DEF("970fx_v1.0",    CPU_POWERPC_970FX_v10,              970FX,
+                "PowerPC 970FX v1.0 (G5)")
+    POWERPC_DEF("970fx_v2.0",    CPU_POWERPC_970FX_v20,              970FX,
+                "PowerPC 970FX v2.0 (G5)")
+    POWERPC_DEF("970fx_v2.1",    CPU_POWERPC_970FX_v21,              970FX,
+                "PowerPC 970FX v2.1 (G5)")
+    POWERPC_DEF("970fx_v3.0",    CPU_POWERPC_970FX_v30,              970FX,
+                "PowerPC 970FX v3.0 (G5)")
+    POWERPC_DEF("970fx_v3.1",    CPU_POWERPC_970FX_v31,              970FX,
+                "PowerPC 970FX v3.1 (G5)")
+    POWERPC_DEF("970gx",         CPU_POWERPC_970GX,                  970GX,
+                "PowerPC 970GX (G5)")
+    POWERPC_DEF("970mp_v1.0",    CPU_POWERPC_970MP_v10,              970MP,
+                "PowerPC 970MP v1.0")
+    POWERPC_DEF("970mp_v1.1",    CPU_POWERPC_970MP_v11,              970MP,
+                "PowerPC 970MP v1.1")
 #if defined (TODO)
-    /* PowerPC Cell                                                          */
-    POWERPC_DEF("Cell",          CPU_POWERPC_CELL,                   970)
+    POWERPC_DEF("Cell",          CPU_POWERPC_CELL,                   970,
+                "PowerPC Cell")
 #endif
 #if defined (TODO)
-    /* PowerPC Cell v1.0                                                     */
-    POWERPC_DEF("Cell_v1.0",     CPU_POWERPC_CELL_v10,               970)
+    POWERPC_DEF("Cell_v1.0",     CPU_POWERPC_CELL_v10,               970,
+                "PowerPC Cell v1.0")
 #endif
 #if defined (TODO)
-    /* PowerPC Cell v2.0                                                     */
-    POWERPC_DEF("Cell_v2.0",     CPU_POWERPC_CELL_v20,               970)
+    POWERPC_DEF("Cell_v2.0",     CPU_POWERPC_CELL_v20,               970,
+                "PowerPC Cell v2.0")
 #endif
 #if defined (TODO)
-    /* PowerPC Cell v3.0                                                     */
-    POWERPC_DEF("Cell_v3.0",     CPU_POWERPC_CELL_v30,               970)
+    POWERPC_DEF("Cell_v3.0",     CPU_POWERPC_CELL_v30,               970,
+                "PowerPC Cell v3.0")
 #endif
 #if defined (TODO)
-    /* PowerPC Cell v3.1                                                     */
-    POWERPC_DEF("Cell_v3.1",     CPU_POWERPC_CELL_v31,               970)
+    POWERPC_DEF("Cell_v3.1",     CPU_POWERPC_CELL_v31,               970,
+                "PowerPC Cell v3.1")
 #endif
 #if defined (TODO)
-    /* PowerPC Cell v3.2                                                     */
-    POWERPC_DEF("Cell_v3.2",     CPU_POWERPC_CELL_v32,               970)
+    POWERPC_DEF("Cell_v3.2",     CPU_POWERPC_CELL_v32,               970,
+                "PowerPC Cell v3.2")
 #endif
 #if defined (TODO)
-    /* RS64 (Apache/A35)                                                     */
     /* This one seems to support the whole POWER2 instruction set
      * and the PowerPC 64 one.
      */
     /* What about A10 & A30 ? */
-    POWERPC_DEF("RS64",          CPU_POWERPC_RS64,                   RS64)
+    POWERPC_DEF("RS64",          CPU_POWERPC_RS64,                   RS64,
+                "RS64 (Apache/A35)")
 #endif
 #if defined (TODO)
-    /* RS64-II (NorthStar/A50)                                               */
-    POWERPC_DEF("RS64-II",       CPU_POWERPC_RS64II,                 RS64)
+    POWERPC_DEF("RS64-II",       CPU_POWERPC_RS64II,                 RS64,
+                "RS64-II (NorthStar/A50)")
 #endif
 #if defined (TODO)
-    /* RS64-III (Pulsar)                                                     */
-    POWERPC_DEF("RS64-III",      CPU_POWERPC_RS64III,                RS64)
+    POWERPC_DEF("RS64-III",      CPU_POWERPC_RS64III,                RS64,
+                "RS64-III (Pulsar)")
 #endif
 #if defined (TODO)
-    /* RS64-IV (IceStar/IStar/SStar)                                         */
-    POWERPC_DEF("RS64-IV",       CPU_POWERPC_RS64IV,                 RS64)
+    POWERPC_DEF("RS64-IV",       CPU_POWERPC_RS64IV,                 RS64,
+                "RS64-IV (IceStar/IStar/SStar)")
 #endif
 #endif /* defined (TARGET_PPC64) */
     /* POWER                                                                 */
 #if defined (TODO)
-    /* Original POWER                                                        */
-    POWERPC_DEF("POWER",         CPU_POWERPC_POWER,                  POWER)
+    POWERPC_DEF("POWER",         CPU_POWERPC_POWER,                  POWER,
+                "Original POWER")
 #endif
 #if defined (TODO)
-    /* POWER2                                                                */
-    POWERPC_DEF("POWER2",        CPU_POWERPC_POWER2,                 POWER)
+    POWERPC_DEF("POWER2",        CPU_POWERPC_POWER2,                 POWER,
+                "POWER2")
 #endif
     /* PA semi cores                                                         */
 #if defined (TODO)
-    /* PA PA6T */
-    POWERPC_DEF("PA6T",          CPU_POWERPC_PA6T,                   PA6T)
+    POWERPC_DEF("PA6T",          CPU_POWERPC_PA6T,                   PA6T,
+                "PA PA6T")
 #endif
 
 typedef struct PowerPCCPUAlias {
commit ca5dff0a3e532ea9168934fc361e96d969007284
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:46 2013 +0000

    target-ppc: Turn descriptive CPU family comments into device descriptions
    
    This gets rid of some more overly long comments that have lost most of
    their purpose now that in most cases there's only two functions left per
    CPU family.
    
    The class field is inherited by the actual CPU models, so override it.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index eea9adf..3ec7c1e 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -3274,7 +3274,6 @@ static int check_pow_hid0_74xx (CPUPPCState *env)
                                                                             \
     static void glue(glue(ppc_, _name), _cpu_family_class_init)
 
-/* PowerPC 401                                                               */
 static void init_proc_401 (CPUPPCState *env)
 {
     gen_spr_40x(env);
@@ -3292,8 +3291,10 @@ static void init_proc_401 (CPUPPCState *env)
 
 POWERPC_FAMILY(401)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 401";
     pcc->init_proc = init_proc_401;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
@@ -3312,7 +3313,6 @@ POWERPC_FAMILY(401)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 401x2                                                             */
 static void init_proc_401x2 (CPUPPCState *env)
 {
     gen_spr_40x(env);
@@ -3338,8 +3338,10 @@ static void init_proc_401x2 (CPUPPCState *env)
 
 POWERPC_FAMILY(401x2)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 401x2";
     pcc->init_proc = init_proc_401x2;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -3359,7 +3361,6 @@ POWERPC_FAMILY(401x2)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 401x3                                                             */
 static void init_proc_401x3 (CPUPPCState *env)
 {
     gen_spr_40x(env);
@@ -3379,8 +3380,10 @@ static void init_proc_401x3 (CPUPPCState *env)
 
 POWERPC_FAMILY(401x3)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 401x3";
     pcc->init_proc = init_proc_401x3;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -3400,7 +3403,6 @@ POWERPC_FAMILY(401x3)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* IOP480                                                                    */
 static void init_proc_IOP480 (CPUPPCState *env)
 {
     gen_spr_40x(env);
@@ -3426,8 +3428,10 @@ static void init_proc_IOP480 (CPUPPCState *env)
 
 POWERPC_FAMILY(IOP480)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "IOP480";
     pcc->init_proc = init_proc_IOP480;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
@@ -3447,7 +3451,6 @@ POWERPC_FAMILY(IOP480)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 403                                                               */
 static void init_proc_403 (CPUPPCState *env)
 {
     gen_spr_40x(env);
@@ -3466,8 +3469,10 @@ static void init_proc_403 (CPUPPCState *env)
 
 POWERPC_FAMILY(403)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 403";
     pcc->init_proc = init_proc_403;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
@@ -3486,7 +3491,6 @@ POWERPC_FAMILY(403)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 403 GCX                                                           */
 static void init_proc_403GCX (CPUPPCState *env)
 {
     gen_spr_40x(env);
@@ -3524,8 +3528,10 @@ static void init_proc_403GCX (CPUPPCState *env)
 
 POWERPC_FAMILY(403GCX)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 403 GCX";
     pcc->init_proc = init_proc_403GCX;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
@@ -3545,7 +3551,6 @@ POWERPC_FAMILY(403GCX)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 405                                                               */
 static void init_proc_405 (CPUPPCState *env)
 {
     /* Time base */
@@ -3582,8 +3587,10 @@ static void init_proc_405 (CPUPPCState *env)
 
 POWERPC_FAMILY(405)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 405";
     pcc->init_proc = init_proc_405;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -3603,7 +3610,6 @@ POWERPC_FAMILY(405)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 440 EP                                                            */
 static void init_proc_440EP (CPUPPCState *env)
 {
     /* Time base */
@@ -3672,8 +3678,10 @@ static void init_proc_440EP (CPUPPCState *env)
 
 POWERPC_FAMILY(440EP)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 440 EP";
     pcc->init_proc = init_proc_440EP;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
@@ -3696,7 +3704,6 @@ POWERPC_FAMILY(440EP)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 440 GP                                                            */
 static void init_proc_440GP (CPUPPCState *env)
 {
     /* Time base */
@@ -3747,8 +3754,10 @@ static void init_proc_440GP (CPUPPCState *env)
 
 POWERPC_FAMILY(440GP)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 440 GP";
     pcc->init_proc = init_proc_440GP;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
@@ -3768,7 +3777,6 @@ POWERPC_FAMILY(440GP)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 440x4                                                             */
 static void init_proc_440x4 (CPUPPCState *env)
 {
     /* Time base */
@@ -3819,8 +3827,10 @@ static void init_proc_440x4 (CPUPPCState *env)
 
 POWERPC_FAMILY(440x4)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 440x4";
     pcc->init_proc = init_proc_440x4;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
@@ -3840,7 +3850,6 @@ POWERPC_FAMILY(440x4)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 440x5                                                             */
 static void init_proc_440x5 (CPUPPCState *env)
 {
     /* Time base */
@@ -3909,8 +3918,10 @@ static void init_proc_440x5 (CPUPPCState *env)
 
 POWERPC_FAMILY(440x5)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 440x5";
     pcc->init_proc = init_proc_440x5;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
@@ -3930,7 +3941,6 @@ POWERPC_FAMILY(440x5)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 460 (guessed)                                                     */
 static void init_proc_460 (CPUPPCState *env)
 {
     /* Time base */
@@ -4004,8 +4014,10 @@ static void init_proc_460 (CPUPPCState *env)
 
 POWERPC_FAMILY(460)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 460 (guessed)";
     pcc->init_proc = init_proc_460;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
@@ -4026,7 +4038,6 @@ POWERPC_FAMILY(460)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 460F (guessed)                                                    */
 static void init_proc_460F (CPUPPCState *env)
 {
     /* Time base */
@@ -4100,8 +4111,10 @@ static void init_proc_460F (CPUPPCState *env)
 
 POWERPC_FAMILY(460F)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 460F (guessed)";
     pcc->init_proc = init_proc_460F;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
@@ -4125,7 +4138,6 @@ POWERPC_FAMILY(460F)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
 }
 
-/* Freescale 5xx cores (aka RCPU) */
 static void init_proc_MPC5xx (CPUPPCState *env)
 {
     /* Time base */
@@ -4140,8 +4152,10 @@ static void init_proc_MPC5xx (CPUPPCState *env)
 
 POWERPC_FAMILY(MPC5xx)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "Freescale 5xx cores (aka RCPU)";
     pcc->init_proc = init_proc_MPC5xx;
     pcc->check_pow = check_pow_none;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
@@ -4158,7 +4172,6 @@ POWERPC_FAMILY(MPC5xx)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* Freescale 8xx cores (aka PowerQUICC) */
 static void init_proc_MPC8xx (CPUPPCState *env)
 {
     /* Time base */
@@ -4173,8 +4186,10 @@ static void init_proc_MPC8xx (CPUPPCState *env)
 
 POWERPC_FAMILY(MPC8xx)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "Freescale 8xx cores (aka PowerQUICC)";
     pcc->init_proc = init_proc_MPC8xx;
     pcc->check_pow = check_pow_none;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING  |
@@ -4191,7 +4206,7 @@ POWERPC_FAMILY(MPC8xx)(ObjectClass *oc, void *data)
 }
 
 /* Freescale 82xx cores (aka PowerQUICC-II)                                  */
-/* PowerPC G2                                                                */
+
 static void init_proc_G2 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -4234,8 +4249,10 @@ static void init_proc_G2 (CPUPPCState *env)
 
 POWERPC_FAMILY(G2)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC G2";
     pcc->init_proc = init_proc_G2;
     pcc->check_pow = check_pow_hid0;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -4255,7 +4272,6 @@ POWERPC_FAMILY(G2)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC G2LE                                                              */
 static void init_proc_G2LE (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -4298,8 +4314,10 @@ static void init_proc_G2LE (CPUPPCState *env)
 
 POWERPC_FAMILY(G2LE)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC G2LE";
     pcc->init_proc = init_proc_G2LE;
     pcc->check_pow = check_pow_hid0;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -4319,7 +4337,6 @@ POWERPC_FAMILY(G2LE)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK;
 }
 
-/* e200 core                                                                 */
 static void init_proc_e200 (CPUPPCState *env)
 {
     /* Time base */
@@ -4429,8 +4446,10 @@ static void init_proc_e200 (CPUPPCState *env)
 
 POWERPC_FAMILY(e200)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "e200 core";
     pcc->init_proc = init_proc_e200;
     pcc->check_pow = check_pow_hid0;
     /* XXX: unimplemented instructions:
@@ -4460,7 +4479,6 @@ POWERPC_FAMILY(e200)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* e300 core                                                                 */
 static void init_proc_e300 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -4496,8 +4514,10 @@ static void init_proc_e300 (CPUPPCState *env)
 
 POWERPC_FAMILY(e300)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "e300 core";
     pcc->init_proc = init_proc_e300;
     pcc->check_pow = check_pow_hid0;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -4517,11 +4537,6 @@ POWERPC_FAMILY(e300)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK;
 }
 
-/* e500v1 core                                                               */
-/* e500v2 core                                                               */
-/* e500mc core                                                               */
-/* e5500 core                                                                 */
-
 #if !defined(CONFIG_USER_ONLY)
 static void spr_write_mas73(void *opaque, int sprn, int gprn)
 {
@@ -4738,8 +4753,10 @@ static void init_proc_e500v1(CPUPPCState *env)
 
 POWERPC_FAMILY(e500v1)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "e500v1 core";
     pcc->init_proc = init_proc_e500v1;
     pcc->check_pow = check_pow_hid0;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL |
@@ -4766,8 +4783,10 @@ static void init_proc_e500v2(CPUPPCState *env)
 
 POWERPC_FAMILY(e500v2)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "e500v2 core";
     pcc->init_proc = init_proc_e500v2;
     pcc->check_pow = check_pow_hid0;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL |
@@ -4794,8 +4813,10 @@ static void init_proc_e500mc(CPUPPCState *env)
 
 POWERPC_FAMILY(e500mc)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "e500mc core";
     pcc->init_proc = init_proc_e500mc;
     pcc->check_pow = check_pow_none;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL |
@@ -4825,8 +4846,10 @@ static void init_proc_e5500(CPUPPCState *env)
 
 POWERPC_FAMILY(e5500)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "e5500 core";
     pcc->init_proc = init_proc_e5500;
     pcc->check_pow = check_pow_none;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL |
@@ -4856,15 +4879,16 @@ POWERPC_FAMILY(e5500)(ObjectClass *oc, void *data)
 #if defined(TODO)
 POWERPC_FAMILY(POWER)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "POWER";
     pcc->insns_flags = XXX_TODO;
     /* POWER RSC (from RAD6000) */
     pcc->msr_mask = 0x00000000FEF0ULL;
 }
 #endif /* TODO */
 
-/* PowerPC 601                                                               */
 #define POWERPC_MSRR_601     (0x0000000000001040ULL)
 
 static void init_proc_601 (CPUPPCState *env)
@@ -4906,8 +4930,10 @@ static void init_proc_601 (CPUPPCState *env)
 
 POWERPC_FAMILY(601)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 601";
     pcc->init_proc = init_proc_601;
     pcc->check_pow = check_pow_none;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_POWER_BR |
@@ -4924,7 +4950,6 @@ POWERPC_FAMILY(601)(ObjectClass *oc, void *data)
     pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_RTC_CLK;
 }
 
-/* PowerPC 601v                                                              */
 #define POWERPC_MSRR_601v    (0x0000000000001040ULL)
 
 static void init_proc_601v (CPUPPCState *env)
@@ -4939,8 +4964,10 @@ static void init_proc_601v (CPUPPCState *env)
 
 POWERPC_FAMILY(601v)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 601v";
     pcc->init_proc = init_proc_601v;
     pcc->check_pow = check_pow_none;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_POWER_BR |
@@ -4957,7 +4984,6 @@ POWERPC_FAMILY(601v)(ObjectClass *oc, void *data)
     pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_RTC_CLK;
 }
 
-/* PowerPC 602                                                               */
 static void init_proc_602 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -4987,8 +5013,10 @@ static void init_proc_602 (CPUPPCState *env)
 
 POWERPC_FAMILY(602)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 602";
     pcc->init_proc = init_proc_602;
     pcc->check_pow = check_pow_hid0;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -5009,7 +5037,6 @@ POWERPC_FAMILY(602)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 603                                                               */
 static void init_proc_603 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5039,8 +5066,10 @@ static void init_proc_603 (CPUPPCState *env)
 
 POWERPC_FAMILY(603)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 603";
     pcc->init_proc = init_proc_603;
     pcc->check_pow = check_pow_hid0;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -5060,7 +5089,6 @@ POWERPC_FAMILY(603)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 603e                                                              */
 static void init_proc_603E (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5095,8 +5123,10 @@ static void init_proc_603E (CPUPPCState *env)
 
 POWERPC_FAMILY(603E)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 603e";
     pcc->init_proc = init_proc_603E;
     pcc->check_pow = check_pow_hid0;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -5116,7 +5146,6 @@ POWERPC_FAMILY(603E)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 604                                                               */
 static void init_proc_604 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5140,8 +5169,10 @@ static void init_proc_604 (CPUPPCState *env)
 
 POWERPC_FAMILY(604)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 604";
     pcc->init_proc = init_proc_604;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -5161,7 +5192,6 @@ POWERPC_FAMILY(604)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 604E                                                              */
 static void init_proc_604E (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5205,8 +5235,10 @@ static void init_proc_604E (CPUPPCState *env)
 
 POWERPC_FAMILY(604E)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 604E";
     pcc->init_proc = init_proc_604E;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -5226,7 +5258,6 @@ POWERPC_FAMILY(604E)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 740                                                               */
 static void init_proc_740 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5257,8 +5288,10 @@ static void init_proc_740 (CPUPPCState *env)
 
 POWERPC_FAMILY(740)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 740";
     pcc->init_proc = init_proc_740;
     pcc->check_pow = check_pow_hid0;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -5278,7 +5311,6 @@ POWERPC_FAMILY(740)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 750                                                               */
 static void init_proc_750 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5317,8 +5349,10 @@ static void init_proc_750 (CPUPPCState *env)
 
 POWERPC_FAMILY(750)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 750";
     pcc->init_proc = init_proc_750;
     pcc->check_pow = check_pow_hid0;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -5338,7 +5372,6 @@ POWERPC_FAMILY(750)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 750 CL                                                            */
 static void init_proc_750cl (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5462,8 +5495,10 @@ static void init_proc_750cl (CPUPPCState *env)
 
 POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 750 CL";
     pcc->init_proc = init_proc_750cl;
     pcc->check_pow = check_pow_hid0;
     /* XXX: not implemented:
@@ -5521,7 +5556,6 @@ POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 750CX                                                             */
 static void init_proc_750cx (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5564,8 +5598,10 @@ static void init_proc_750cx (CPUPPCState *env)
 
 POWERPC_FAMILY(750cx)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 750CX";
     pcc->init_proc = init_proc_750cx;
     pcc->check_pow = check_pow_hid0;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -5585,7 +5621,6 @@ POWERPC_FAMILY(750cx)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 750FX                                                             */
 static void init_proc_750fx (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5633,8 +5668,10 @@ static void init_proc_750fx (CPUPPCState *env)
 
 POWERPC_FAMILY(750fx)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 750FX";
     pcc->init_proc = init_proc_750fx;
     pcc->check_pow = check_pow_hid0;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -5654,7 +5691,6 @@ POWERPC_FAMILY(750fx)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 750GX                                                             */
 static void init_proc_750gx (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5702,8 +5738,10 @@ static void init_proc_750gx (CPUPPCState *env)
 
 POWERPC_FAMILY(750gx)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 750GX";
     pcc->init_proc = init_proc_750gx;
     pcc->check_pow = check_pow_hid0;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -5723,7 +5761,6 @@ POWERPC_FAMILY(750gx)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 745                                                               */
 static void init_proc_745 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5762,8 +5799,10 @@ static void init_proc_745 (CPUPPCState *env)
 
 POWERPC_FAMILY(745)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 745";
     pcc->init_proc = init_proc_745;
     pcc->check_pow = check_pow_hid0;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -5783,7 +5822,6 @@ POWERPC_FAMILY(745)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 755                                                               */
 static void init_proc_755 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5833,8 +5871,10 @@ static void init_proc_755 (CPUPPCState *env)
 
 POWERPC_FAMILY(755)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 755";
     pcc->init_proc = init_proc_755;
     pcc->check_pow = check_pow_hid0;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -5854,7 +5894,6 @@ POWERPC_FAMILY(755)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 7400 (aka G4)                                                     */
 static void init_proc_7400 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5887,8 +5926,10 @@ static void init_proc_7400 (CPUPPCState *env)
 
 POWERPC_FAMILY(7400)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 7400 (aka G4)";
     pcc->init_proc = init_proc_7400;
     pcc->check_pow = check_pow_hid0;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -5913,7 +5954,6 @@ POWERPC_FAMILY(7400)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 7410 (aka G4)                                                     */
 static void init_proc_7410 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5952,8 +5992,10 @@ static void init_proc_7410 (CPUPPCState *env)
 
 POWERPC_FAMILY(7410)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 7410 (aka G4)";
     pcc->init_proc = init_proc_7410;
     pcc->check_pow = check_pow_hid0;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -5978,7 +6020,6 @@ POWERPC_FAMILY(7410)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 7440 (aka G4)                                                     */
 static void init_proc_7440 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -6043,8 +6084,10 @@ static void init_proc_7440 (CPUPPCState *env)
 
 POWERPC_FAMILY(7440)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 7440 (aka G4)";
     pcc->init_proc = init_proc_7440;
     pcc->check_pow = check_pow_hid0_74xx;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -6069,7 +6112,6 @@ POWERPC_FAMILY(7440)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 7450 (aka G4)                                                     */
 static void init_proc_7450 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -6160,8 +6202,10 @@ static void init_proc_7450 (CPUPPCState *env)
 
 POWERPC_FAMILY(7450)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 7450 (aka G4)";
     pcc->init_proc = init_proc_7450;
     pcc->check_pow = check_pow_hid0_74xx;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -6186,7 +6230,6 @@ POWERPC_FAMILY(7450)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 7445 (aka G4)                                                     */
 static void init_proc_7445 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -6280,8 +6323,10 @@ static void init_proc_7445 (CPUPPCState *env)
 
 POWERPC_FAMILY(7445)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 7445 (aka G4)";
     pcc->init_proc = init_proc_7445;
     pcc->check_pow = check_pow_hid0_74xx;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -6306,7 +6351,6 @@ POWERPC_FAMILY(7445)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 7455 (aka G4)                                                     */
 static void init_proc_7455 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -6402,8 +6446,10 @@ static void init_proc_7455 (CPUPPCState *env)
 
 POWERPC_FAMILY(7455)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 7455 (aka G4)";
     pcc->init_proc = init_proc_7455;
     pcc->check_pow = check_pow_hid0_74xx;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -6428,7 +6474,6 @@ POWERPC_FAMILY(7455)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 7457 (aka G4)                                                     */
 static void init_proc_7457 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -6548,8 +6593,10 @@ static void init_proc_7457 (CPUPPCState *env)
 
 POWERPC_FAMILY(7457)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 7457 (aka G4)";
     pcc->init_proc = init_proc_7457;
     pcc->check_pow = check_pow_hid0_74xx;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -6575,7 +6622,6 @@ POWERPC_FAMILY(7457)(ObjectClass *oc, void *data)
 }
 
 #if defined (TARGET_PPC64)
-/* PowerPC 970                                                               */
 #if defined(CONFIG_USER_ONLY)
 #define POWERPC970_HID5_INIT 0x00000080
 #else
@@ -6654,8 +6700,10 @@ static void init_proc_970 (CPUPPCState *env)
 
 POWERPC_FAMILY(970)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 970";
     pcc->init_proc = init_proc_970;
     pcc->check_pow = check_pow_970;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -6678,7 +6726,6 @@ POWERPC_FAMILY(970)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 970FX (aka G5)                                                    */
 static int check_pow_970FX (CPUPPCState *env)
 {
     if (env->spr[SPR_HID0] & 0x00600000)
@@ -6763,8 +6810,10 @@ static void init_proc_970FX (CPUPPCState *env)
 
 POWERPC_FAMILY(970FX)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 970FX (aka G5)";
     pcc->init_proc = init_proc_970FX;
     pcc->check_pow = check_pow_970FX;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -6787,7 +6836,6 @@ POWERPC_FAMILY(970FX)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 970 GX                                                            */
 static int check_pow_970GX (CPUPPCState *env)
 {
     if (env->spr[SPR_HID0] & 0x00600000)
@@ -6860,8 +6908,10 @@ static void init_proc_970GX (CPUPPCState *env)
 
 POWERPC_FAMILY(970GX)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 970 GX";
     pcc->init_proc = init_proc_970GX;
     pcc->check_pow = check_pow_970GX;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -6884,7 +6934,6 @@ POWERPC_FAMILY(970GX)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* PowerPC 970 MP                                                            */
 static int check_pow_970MP (CPUPPCState *env)
 {
     if (env->spr[SPR_HID0] & 0x01C00000)
@@ -6957,8 +7006,10 @@ static void init_proc_970MP (CPUPPCState *env)
 
 POWERPC_FAMILY(970MP)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 970 MP";
     pcc->init_proc = init_proc_970MP;
     pcc->check_pow = check_pow_970MP;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -6981,7 +7032,6 @@ POWERPC_FAMILY(970MP)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK;
 }
 
-/* POWER7 */
 static void init_proc_POWER7 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -7046,8 +7096,10 @@ static void init_proc_POWER7 (CPUPPCState *env)
 
 POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "POWER7";
     pcc->init_proc = init_proc_POWER7;
     pcc->check_pow = check_pow_nocheck;
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -7071,7 +7123,6 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR;
 }
 
-/* PowerPC 620                                                               */
 static void init_proc_620 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -7095,8 +7146,10 @@ static void init_proc_620 (CPUPPCState *env)
 
 POWERPC_FAMILY(620)(ObjectClass *oc, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
+    dc->desc = "PowerPC 620";
     pcc->init_proc = init_proc_620;
     pcc->check_pow = check_pow_nocheck; /* Check this */
     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
@@ -7832,10 +7885,12 @@ enum {
     glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_class_init)            \
     (ObjectClass *oc, void *data)                                           \
     {                                                                       \
+        DeviceClass *dc = DEVICE_CLASS(oc);                                 \
         PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);                       \
                                                                             \
         pcc->pvr          = _pvr;                                           \
         pcc->svr          = _svr;                                           \
+        dc->desc          = NULL;                                           \
     }                                                                       \
                                                                             \
     static const TypeInfo                                                   \
commit ba9fd9f1509c9729286a1071e217db9df05e6896
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:45 2013 +0000

    target-ppc: Set remaining fields on CPU family classes
    
    Now POWERPC_DEF_SVR() no longer sets family-specific fields itself.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index ca56028..eea9adf 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -3275,14 +3275,6 @@ static int check_pow_hid0_74xx (CPUPPCState *env)
     static void glue(glue(ppc_, _name), _cpu_family_class_init)
 
 /* PowerPC 401                                                               */
-#define POWERPC_MSRM_401     (0x00000000000FD201ULL)
-#define POWERPC_MMU_401      (POWERPC_MMU_REAL)
-#define POWERPC_EXCP_401     (POWERPC_EXCP_40x)
-#define POWERPC_INPUT_401    (PPC_FLAGS_INPUT_401)
-#define POWERPC_BFDM_401     (bfd_mach_ppc_403)
-#define POWERPC_FLAG_401     (POWERPC_FLAG_CE | POWERPC_FLAG_DE |             \
-                              POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_401 (CPUPPCState *env)
 {
     gen_spr_40x(env);
@@ -3311,17 +3303,16 @@ POWERPC_FAMILY(401)(ObjectClass *oc, void *data)
                        PPC_MEM_SYNC | PPC_MEM_EIEIO |
                        PPC_4xx_COMMON | PPC_40x_EXCP;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x00000000000FD201ULL;
+    pcc->mmu_model = POWERPC_MMU_REAL;
+    pcc->excp_model = POWERPC_EXCP_40x;
+    pcc->bus_model = PPC_FLAGS_INPUT_401;
+    pcc->bfd_mach = bfd_mach_ppc_403;
+    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DE |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 401x2                                                             */
-#define POWERPC_MSRM_401x2   (0x00000000001FD231ULL)
-#define POWERPC_MMU_401x2    (POWERPC_MMU_SOFT_4xx_Z)
-#define POWERPC_EXCP_401x2   (POWERPC_EXCP_40x)
-#define POWERPC_INPUT_401x2  (PPC_FLAGS_INPUT_401)
-#define POWERPC_BFDM_401x2   (bfd_mach_ppc_403)
-#define POWERPC_FLAG_401x2   (POWERPC_FLAG_CE | POWERPC_FLAG_DE |             \
-                              POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_401x2 (CPUPPCState *env)
 {
     gen_spr_40x(env);
@@ -3359,17 +3350,16 @@ POWERPC_FAMILY(401x2)(ObjectClass *oc, void *data)
                        PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC |
                        PPC_4xx_COMMON | PPC_40x_EXCP;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x00000000001FD231ULL;
+    pcc->mmu_model = POWERPC_MMU_SOFT_4xx_Z;
+    pcc->excp_model = POWERPC_EXCP_40x;
+    pcc->bus_model = PPC_FLAGS_INPUT_401;
+    pcc->bfd_mach = bfd_mach_ppc_403;
+    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DE |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 401x3                                                             */
-#define POWERPC_MSRM_401x3   (0x00000000001FD631ULL)
-#define POWERPC_MMU_401x3    (POWERPC_MMU_SOFT_4xx_Z)
-#define POWERPC_EXCP_401x3   (POWERPC_EXCP_40x)
-#define POWERPC_INPUT_401x3  (PPC_FLAGS_INPUT_401)
-#define POWERPC_BFDM_401x3   (bfd_mach_ppc_403)
-#define POWERPC_FLAG_401x3   (POWERPC_FLAG_CE | POWERPC_FLAG_DE |             \
-                              POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_401x3 (CPUPPCState *env)
 {
     gen_spr_40x(env);
@@ -3401,17 +3391,16 @@ POWERPC_FAMILY(401x3)(ObjectClass *oc, void *data)
                        PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC |
                        PPC_4xx_COMMON | PPC_40x_EXCP;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x00000000001FD631ULL;
+    pcc->mmu_model = POWERPC_MMU_SOFT_4xx_Z;
+    pcc->excp_model = POWERPC_EXCP_40x;
+    pcc->bus_model = PPC_FLAGS_INPUT_401;
+    pcc->bfd_mach = bfd_mach_ppc_403;
+    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DE |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* IOP480                                                                    */
-#define POWERPC_MSRM_IOP480  (0x00000000001FD231ULL)
-#define POWERPC_MMU_IOP480   (POWERPC_MMU_SOFT_4xx_Z)
-#define POWERPC_EXCP_IOP480  (POWERPC_EXCP_40x)
-#define POWERPC_INPUT_IOP480 (PPC_FLAGS_INPUT_401)
-#define POWERPC_BFDM_IOP480  (bfd_mach_ppc_403)
-#define POWERPC_FLAG_IOP480  (POWERPC_FLAG_CE | POWERPC_FLAG_DE |             \
-                              POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_IOP480 (CPUPPCState *env)
 {
     gen_spr_40x(env);
@@ -3449,17 +3438,16 @@ POWERPC_FAMILY(IOP480)(ObjectClass *oc, void *data)
                        PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC |
                        PPC_4xx_COMMON | PPC_40x_EXCP;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x00000000001FD231ULL;
+    pcc->mmu_model = POWERPC_MMU_SOFT_4xx_Z;
+    pcc->excp_model = POWERPC_EXCP_40x;
+    pcc->bus_model = PPC_FLAGS_INPUT_401;
+    pcc->bfd_mach = bfd_mach_ppc_403;
+    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DE |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 403                                                               */
-#define POWERPC_MSRM_403     (0x000000000007D00DULL)
-#define POWERPC_MMU_403      (POWERPC_MMU_REAL)
-#define POWERPC_EXCP_403     (POWERPC_EXCP_40x)
-#define POWERPC_INPUT_403    (PPC_FLAGS_INPUT_401)
-#define POWERPC_BFDM_403     (bfd_mach_ppc_403)
-#define POWERPC_FLAG_403     (POWERPC_FLAG_CE | POWERPC_FLAG_PX |             \
-                              POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_403 (CPUPPCState *env)
 {
     gen_spr_40x(env);
@@ -3489,17 +3477,16 @@ POWERPC_FAMILY(403)(ObjectClass *oc, void *data)
                        PPC_MEM_SYNC | PPC_MEM_EIEIO |
                        PPC_4xx_COMMON | PPC_40x_EXCP;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000007D00DULL;
+    pcc->mmu_model = POWERPC_MMU_REAL;
+    pcc->excp_model = POWERPC_EXCP_40x;
+    pcc->bus_model = PPC_FLAGS_INPUT_401;
+    pcc->bfd_mach = bfd_mach_ppc_403;
+    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_PX |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 403 GCX                                                           */
-#define POWERPC_MSRM_403GCX  (0x000000000007D00DULL)
-#define POWERPC_MMU_403GCX   (POWERPC_MMU_SOFT_4xx_Z)
-#define POWERPC_EXCP_403GCX  (POWERPC_EXCP_40x)
-#define POWERPC_INPUT_403GCX (PPC_FLAGS_INPUT_401)
-#define POWERPC_BFDM_403GCX  (bfd_mach_ppc_403)
-#define POWERPC_FLAG_403GCX  (POWERPC_FLAG_CE | POWERPC_FLAG_PX |             \
-                              POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_403GCX (CPUPPCState *env)
 {
     gen_spr_40x(env);
@@ -3549,17 +3536,16 @@ POWERPC_FAMILY(403GCX)(ObjectClass *oc, void *data)
                        PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC |
                        PPC_4xx_COMMON | PPC_40x_EXCP;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000007D00DULL;
+    pcc->mmu_model = POWERPC_MMU_SOFT_4xx_Z;
+    pcc->excp_model = POWERPC_EXCP_40x;
+    pcc->bus_model = PPC_FLAGS_INPUT_401;
+    pcc->bfd_mach = bfd_mach_ppc_403;
+    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_PX |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 405                                                               */
-#define POWERPC_MSRM_405     (0x000000000006E630ULL)
-#define POWERPC_MMU_405      (POWERPC_MMU_SOFT_4xx)
-#define POWERPC_EXCP_405     (POWERPC_EXCP_40x)
-#define POWERPC_INPUT_405    (PPC_FLAGS_INPUT_405)
-#define POWERPC_BFDM_405     (bfd_mach_ppc_403)
-#define POWERPC_FLAG_405     (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
-                              POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_405 (CPUPPCState *env)
 {
     /* Time base */
@@ -3608,17 +3594,16 @@ POWERPC_FAMILY(405)(ObjectClass *oc, void *data)
                        PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC |
                        PPC_4xx_COMMON | PPC_405_MAC | PPC_40x_EXCP;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000006E630ULL;
+    pcc->mmu_model = POWERPC_MMU_SOFT_4xx;
+    pcc->excp_model = POWERPC_EXCP_40x;
+    pcc->bus_model = PPC_FLAGS_INPUT_405;
+    pcc->bfd_mach = bfd_mach_ppc_403;
+    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DWE |
+                 POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 440 EP                                                            */
-#define POWERPC_MSRM_440EP   (0x000000000006FF30ULL)
-#define POWERPC_MMU_440EP    (POWERPC_MMU_BOOKE)
-#define POWERPC_EXCP_440EP   (POWERPC_EXCP_BOOKE)
-#define POWERPC_INPUT_440EP  (PPC_FLAGS_INPUT_BookE)
-#define POWERPC_BFDM_440EP   (bfd_mach_ppc_403)
-#define POWERPC_FLAG_440EP   (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
-                              POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_440EP (CPUPPCState *env)
 {
     /* Time base */
@@ -3702,17 +3687,16 @@ POWERPC_FAMILY(440EP)(ObjectClass *oc, void *data)
                        PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
                        PPC_440_SPEC;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000006FF30ULL;
+    pcc->mmu_model = POWERPC_MMU_BOOKE;
+    pcc->excp_model = POWERPC_EXCP_BOOKE;
+    pcc->bus_model = PPC_FLAGS_INPUT_BookE;
+    pcc->bfd_mach = bfd_mach_ppc_403;
+    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DWE |
+                 POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 440 GP                                                            */
-#define POWERPC_MSRM_440GP   (0x000000000006FF30ULL)
-#define POWERPC_MMU_440GP    (POWERPC_MMU_BOOKE)
-#define POWERPC_EXCP_440GP   (POWERPC_EXCP_BOOKE)
-#define POWERPC_INPUT_440GP  (PPC_FLAGS_INPUT_BookE)
-#define POWERPC_BFDM_440GP   (bfd_mach_ppc_403)
-#define POWERPC_FLAG_440GP   (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
-                              POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_440GP (CPUPPCState *env)
 {
     /* Time base */
@@ -3775,17 +3759,16 @@ POWERPC_FAMILY(440GP)(ObjectClass *oc, void *data)
                        PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
                        PPC_440_SPEC;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000006FF30ULL;
+    pcc->mmu_model = POWERPC_MMU_BOOKE;
+    pcc->excp_model = POWERPC_EXCP_BOOKE;
+    pcc->bus_model = PPC_FLAGS_INPUT_BookE;
+    pcc->bfd_mach = bfd_mach_ppc_403;
+    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DWE |
+                 POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 440x4                                                             */
-#define POWERPC_MSRM_440x4   (0x000000000006FF30ULL)
-#define POWERPC_MMU_440x4    (POWERPC_MMU_BOOKE)
-#define POWERPC_EXCP_440x4   (POWERPC_EXCP_BOOKE)
-#define POWERPC_INPUT_440x4  (PPC_FLAGS_INPUT_BookE)
-#define POWERPC_BFDM_440x4   (bfd_mach_ppc_403)
-#define POWERPC_FLAG_440x4   (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
-                              POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_440x4 (CPUPPCState *env)
 {
     /* Time base */
@@ -3848,17 +3831,16 @@ POWERPC_FAMILY(440x4)(ObjectClass *oc, void *data)
                        PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
                        PPC_440_SPEC;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000006FF30ULL;
+    pcc->mmu_model = POWERPC_MMU_BOOKE;
+    pcc->excp_model = POWERPC_EXCP_BOOKE;
+    pcc->bus_model = PPC_FLAGS_INPUT_BookE;
+    pcc->bfd_mach = bfd_mach_ppc_403;
+    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DWE |
+                 POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 440x5                                                             */
-#define POWERPC_MSRM_440x5   (0x000000000006FF30ULL)
-#define POWERPC_MMU_440x5    (POWERPC_MMU_BOOKE)
-#define POWERPC_EXCP_440x5   (POWERPC_EXCP_BOOKE)
-#define POWERPC_INPUT_440x5  (PPC_FLAGS_INPUT_BookE)
-#define POWERPC_BFDM_440x5   (bfd_mach_ppc_403)
-#define POWERPC_FLAG_440x5   (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |           \
-                              POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_440x5 (CPUPPCState *env)
 {
     /* Time base */
@@ -3939,17 +3921,16 @@ POWERPC_FAMILY(440x5)(ObjectClass *oc, void *data)
                        PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
                        PPC_440_SPEC;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000006FF30ULL;
+    pcc->mmu_model = POWERPC_MMU_BOOKE;
+    pcc->excp_model = POWERPC_EXCP_BOOKE;
+    pcc->bus_model = PPC_FLAGS_INPUT_BookE;
+    pcc->bfd_mach = bfd_mach_ppc_403;
+    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DWE |
+                 POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 460 (guessed)                                                     */
-#define POWERPC_MSRM_460     (0x000000000006FF30ULL)
-#define POWERPC_MMU_460      (POWERPC_MMU_BOOKE)
-#define POWERPC_EXCP_460     (POWERPC_EXCP_BOOKE)
-#define POWERPC_INPUT_460    (PPC_FLAGS_INPUT_BookE)
-#define POWERPC_BFDM_460     (bfd_mach_ppc_403)
-#define POWERPC_FLAG_460     (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
-                              POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_460 (CPUPPCState *env)
 {
     /* Time base */
@@ -4036,17 +4017,16 @@ POWERPC_FAMILY(460)(ObjectClass *oc, void *data)
                        PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
                        PPC_440_SPEC;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000006FF30ULL;
+    pcc->mmu_model = POWERPC_MMU_BOOKE;
+    pcc->excp_model = POWERPC_EXCP_BOOKE;
+    pcc->bus_model = PPC_FLAGS_INPUT_BookE;
+    pcc->bfd_mach = bfd_mach_ppc_403;
+    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DWE |
+                 POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 460F (guessed)                                                    */
-#define POWERPC_MSRM_460     (0x000000000006FF30ULL)
-#define POWERPC_MMU_460F     (POWERPC_MMU_BOOKE)
-#define POWERPC_EXCP_460F    (POWERPC_EXCP_BOOKE)
-#define POWERPC_INPUT_460F   (PPC_FLAGS_INPUT_BookE)
-#define POWERPC_BFDM_460F    (bfd_mach_ppc_403)
-#define POWERPC_FLAG_460F    (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
-                              POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_460F (CPUPPCState *env)
 {
     /* Time base */
@@ -4136,17 +4116,16 @@ POWERPC_FAMILY(460F)(ObjectClass *oc, void *data)
                        PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
                        PPC_440_SPEC;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000006FF30ULL;
+    pcc->mmu_model = POWERPC_MMU_BOOKE;
+    pcc->excp_model = POWERPC_EXCP_BOOKE;
+    pcc->bus_model = PPC_FLAGS_INPUT_BookE;
+    pcc->bfd_mach = bfd_mach_ppc_403;
+    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DWE |
+                 POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK;
 }
 
 /* Freescale 5xx cores (aka RCPU) */
-#define POWERPC_MSRM_MPC5xx  (0x000000000001FF43ULL)
-#define POWERPC_MMU_MPC5xx   (POWERPC_MMU_REAL)
-#define POWERPC_EXCP_MPC5xx  (POWERPC_EXCP_603)
-#define POWERPC_INPUT_MPC5xx (PPC_FLAGS_INPUT_RCPU)
-#define POWERPC_BFDM_MPC5xx  (bfd_mach_ppc_505)
-#define POWERPC_FLAG_MPC5xx  (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
-                              POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_MPC5xx (CPUPPCState *env)
 {
     /* Time base */
@@ -4170,17 +4149,16 @@ POWERPC_FAMILY(MPC5xx)(ObjectClass *oc, void *data)
                        PPC_CACHE_ICBI | PPC_FLOAT | PPC_FLOAT_STFIWX |
                        PPC_MFTB;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000001FF43ULL;
+    pcc->mmu_model = POWERPC_MMU_REAL;
+    pcc->excp_model = POWERPC_EXCP_603;
+    pcc->bus_model = PPC_FLAGS_INPUT_RCPU;
+    pcc->bfd_mach = bfd_mach_ppc_505;
+    pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* Freescale 8xx cores (aka PowerQUICC) */
-#define POWERPC_MSRM_MPC8xx  (0x000000000001F673ULL)
-#define POWERPC_MMU_MPC8xx   (POWERPC_MMU_MPC8xx)
-#define POWERPC_EXCP_MPC8xx  (POWERPC_EXCP_603)
-#define POWERPC_INPUT_MPC8xx (PPC_FLAGS_INPUT_RCPU)
-#define POWERPC_BFDM_MPC8xx  (bfd_mach_ppc_860)
-#define POWERPC_FLAG_MPC8xx  (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
-                              POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_MPC8xx (CPUPPCState *env)
 {
     /* Time base */
@@ -4203,18 +4181,17 @@ POWERPC_FAMILY(MPC8xx)(ObjectClass *oc, void *data)
                        PPC_MEM_EIEIO | PPC_MEM_SYNC |
                        PPC_CACHE_ICBI | PPC_MFTB;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000001F673ULL;
+    pcc->mmu_model = POWERPC_MMU_MPC8xx;
+    pcc->excp_model = POWERPC_EXCP_603;
+    pcc->bus_model = PPC_FLAGS_INPUT_RCPU;
+    pcc->bfd_mach = bfd_mach_ppc_860;
+    pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* Freescale 82xx cores (aka PowerQUICC-II)                                  */
 /* PowerPC G2                                                                */
-#define POWERPC_MSRM_G2      (0x000000000006FFF2ULL)
-#define POWERPC_MMU_G2       (POWERPC_MMU_SOFT_6xx)
-//#define POWERPC_EXCP_G2      (POWERPC_EXCP_G2)
-#define POWERPC_INPUT_G2     (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_G2      (bfd_mach_ppc_ec603e)
-#define POWERPC_FLAG_G2      (POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |           \
-                              POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_G2 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -4269,17 +4246,16 @@ POWERPC_FAMILY(G2)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
                        PPC_SEGMENT | PPC_EXTERN;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000006FFF2ULL;
+    pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
+    pcc->excp_model = POWERPC_EXCP_G2;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_ec603e;
+    pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC G2LE                                                              */
-#define POWERPC_MSRM_G2LE    (0x000000000007FFF3ULL)
-#define POWERPC_MMU_G2LE     (POWERPC_MMU_SOFT_6xx)
-#define POWERPC_EXCP_G2LE    (POWERPC_EXCP_G2)
-#define POWERPC_INPUT_G2LE   (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_G2LE    (bfd_mach_ppc_ec603e)
-#define POWERPC_FLAG_G2LE    (POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |           \
-                              POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_G2LE (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -4334,18 +4310,16 @@ POWERPC_FAMILY(G2LE)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
                        PPC_SEGMENT | PPC_EXTERN;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000007FFF3ULL;
+    pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
+    pcc->excp_model = POWERPC_EXCP_G2;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_ec603e;
+    pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK;
 }
 
 /* e200 core                                                                 */
-#define POWERPC_MSRM_e200    (0x000000000606FF30ULL)
-#define POWERPC_MMU_e200     (POWERPC_MMU_BOOKE206)
-#define POWERPC_EXCP_e200    (POWERPC_EXCP_BOOKE)
-#define POWERPC_INPUT_e200   (PPC_FLAGS_INPUT_BookE)
-#define POWERPC_BFDM_e200    (bfd_mach_ppc_860)
-#define POWERPC_FLAG_e200    (POWERPC_FLAG_SPE | POWERPC_FLAG_CE |            \
-                              POWERPC_FLAG_UBLE | POWERPC_FLAG_DE |           \
-                              POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_e200 (CPUPPCState *env)
 {
     /* Time base */
@@ -4476,17 +4450,17 @@ POWERPC_FAMILY(e200)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBSYNC | PPC_TLBIVAX |
                        PPC_BOOKE;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000606FF30ULL;
+    pcc->mmu_model = POWERPC_MMU_BOOKE206;
+    pcc->excp_model = POWERPC_EXCP_BOOKE;
+    pcc->bus_model = PPC_FLAGS_INPUT_BookE;
+    pcc->bfd_mach = bfd_mach_ppc_860;
+    pcc->flags = POWERPC_FLAG_SPE | POWERPC_FLAG_CE |
+                 POWERPC_FLAG_UBLE | POWERPC_FLAG_DE |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* e300 core                                                                 */
-#define POWERPC_MSRM_e300    (0x000000000007FFF3ULL)
-#define POWERPC_MMU_e300     (POWERPC_MMU_SOFT_6xx)
-#define POWERPC_EXCP_e300    (POWERPC_EXCP_603)
-#define POWERPC_INPUT_e300   (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_e300    (bfd_mach_ppc_603)
-#define POWERPC_FLAG_e300    (POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |           \
-                              POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_e300 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -4534,47 +4508,19 @@ POWERPC_FAMILY(e300)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
                        PPC_SEGMENT | PPC_EXTERN;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000007FFF3ULL;
+    pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
+    pcc->excp_model = POWERPC_EXCP_603;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_603;
+    pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK;
 }
 
 /* e500v1 core                                                               */
-#define POWERPC_MSRM_e500v1    (0x000000000606FF30ULL)
-#define POWERPC_MMU_e500v1     (POWERPC_MMU_BOOKE206)
-#define POWERPC_EXCP_e500v1    (POWERPC_EXCP_BOOKE)
-#define POWERPC_INPUT_e500v1   (PPC_FLAGS_INPUT_BookE)
-#define POWERPC_BFDM_e500v1    (bfd_mach_ppc_860)
-#define POWERPC_FLAG_e500v1    (POWERPC_FLAG_SPE | POWERPC_FLAG_CE |    \
-                                POWERPC_FLAG_UBLE | POWERPC_FLAG_DE |   \
-                                POWERPC_FLAG_BUS_CLK)
-
 /* e500v2 core                                                               */
-#define POWERPC_MSRM_e500v2    (0x000000000606FF30ULL)
-#define POWERPC_MMU_e500v2     (POWERPC_MMU_BOOKE206)
-#define POWERPC_EXCP_e500v2    (POWERPC_EXCP_BOOKE)
-#define POWERPC_INPUT_e500v2   (PPC_FLAGS_INPUT_BookE)
-#define POWERPC_BFDM_e500v2    (bfd_mach_ppc_860)
-#define POWERPC_FLAG_e500v2    (POWERPC_FLAG_SPE | POWERPC_FLAG_CE |    \
-                                POWERPC_FLAG_UBLE | POWERPC_FLAG_DE |   \
-                                POWERPC_FLAG_BUS_CLK)
-
 /* e500mc core                                                               */
-#define POWERPC_MSRM_e500mc    (0x000000001402FB36ULL)
-#define POWERPC_MMU_e500mc     (POWERPC_MMU_BOOKE206)
-#define POWERPC_EXCP_e500mc    (POWERPC_EXCP_BOOKE)
-#define POWERPC_INPUT_e500mc   (PPC_FLAGS_INPUT_BookE)
-/* Fixme: figure out the correct flag for e500mc */
-#define POWERPC_BFDM_e500mc    (bfd_mach_ppc_e500)
-#define POWERPC_FLAG_e500mc    (POWERPC_FLAG_CE | POWERPC_FLAG_DE | \
-                                POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-
 /* e5500 core                                                                 */
-#define POWERPC_MSRM_e5500     (0x000000009402FB36ULL)
-#define POWERPC_MMU_e5500      (POWERPC_MMU_BOOKE206)
-#define POWERPC_EXCP_e5500     (POWERPC_EXCP_BOOKE)
-#define POWERPC_INPUT_e5500    (PPC_FLAGS_INPUT_BookE)
-/* Fixme: figure out the correct flag for e5500 */
-#define POWERPC_BFDM_e5500     (bfd_mach_ppc_e500)
-#define POWERPC_FLAG_e5500     (POWERPC_FLAG_CE | POWERPC_FLAG_DE | \
-                                POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
 
 #if !defined(CONFIG_USER_ONLY)
 static void spr_write_mas73(void *opaque, int sprn, int gprn)
@@ -4803,6 +4749,14 @@ POWERPC_FAMILY(e500v1)(ObjectClass *oc, void *data)
                        PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
                        PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC;
     pcc->insns_flags2 = PPC2_BOOKE206;
+    pcc->msr_mask = 0x000000000606FF30ULL;
+    pcc->mmu_model = POWERPC_MMU_BOOKE206;
+    pcc->excp_model = POWERPC_EXCP_BOOKE;
+    pcc->bus_model = PPC_FLAGS_INPUT_BookE;
+    pcc->bfd_mach = bfd_mach_ppc_860;
+    pcc->flags = POWERPC_FLAG_SPE | POWERPC_FLAG_CE |
+                 POWERPC_FLAG_UBLE | POWERPC_FLAG_DE |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 static void init_proc_e500v2(CPUPPCState *env)
@@ -4823,6 +4777,14 @@ POWERPC_FAMILY(e500v2)(ObjectClass *oc, void *data)
                        PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
                        PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC;
     pcc->insns_flags2 = PPC2_BOOKE206;
+    pcc->msr_mask = 0x000000000606FF30ULL;
+    pcc->mmu_model = POWERPC_MMU_BOOKE206;
+    pcc->excp_model = POWERPC_EXCP_BOOKE;
+    pcc->bus_model = PPC_FLAGS_INPUT_BookE;
+    pcc->bfd_mach = bfd_mach_ppc_860;
+    pcc->flags = POWERPC_FLAG_SPE | POWERPC_FLAG_CE |
+                 POWERPC_FLAG_UBLE | POWERPC_FLAG_DE |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 static void init_proc_e500mc(CPUPPCState *env)
@@ -4845,6 +4807,14 @@ POWERPC_FAMILY(e500mc)(ObjectClass *oc, void *data)
                        PPC_FLOAT_STFIWX | PPC_WAIT |
                        PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC;
     pcc->insns_flags2 = PPC2_BOOKE206 | PPC2_PRCNTL;
+    pcc->msr_mask = 0x000000001402FB36ULL;
+    pcc->mmu_model = POWERPC_MMU_BOOKE206;
+    pcc->excp_model = POWERPC_EXCP_BOOKE;
+    pcc->bus_model = PPC_FLAGS_INPUT_BookE;
+    /* FIXME: figure out the correct flag for e500mc */
+    pcc->bfd_mach = bfd_mach_ppc_e500;
+    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DE |
+                 POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
 #ifdef TARGET_PPC64
@@ -4869,6 +4839,14 @@ POWERPC_FAMILY(e5500)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC |
                        PPC_64B | PPC_POPCNTB | PPC_POPCNTWD;
     pcc->insns_flags2 = PPC2_BOOKE206 | PPC2_PRCNTL;
+    pcc->msr_mask = 0x000000009402FB36ULL;
+    pcc->mmu_model = POWERPC_MMU_BOOKE206;
+    pcc->excp_model = POWERPC_EXCP_BOOKE;
+    pcc->bus_model = PPC_FLAGS_INPUT_BookE;
+    /* FIXME: figure out the correct flag for e5500 */
+    pcc->bfd_mach = bfd_mach_ppc_e500;
+    pcc->flags = POWERPC_FLAG_CE | POWERPC_FLAG_DE |
+                 POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 #endif
 
@@ -4876,25 +4854,18 @@ POWERPC_FAMILY(e5500)(ObjectClass *oc, void *data)
 
 /* POWER : same as 601, without mfmsr, mfsr                                  */
 #if defined(TODO)
-/* POWER RSC (from RAD6000) */
-#define POWERPC_MSRM_POWER   (0x00000000FEF0ULL)
-
 POWERPC_FAMILY(POWER)(ObjectClass *oc, void *data)
 {
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
     pcc->insns_flags = XXX_TODO;
+    /* POWER RSC (from RAD6000) */
+    pcc->msr_mask = 0x00000000FEF0ULL;
 }
 #endif /* TODO */
 
 /* PowerPC 601                                                               */
-#define POWERPC_MSRM_601     (0x000000000000FD70ULL)
 #define POWERPC_MSRR_601     (0x0000000000001040ULL)
-//#define POWERPC_MMU_601      (POWERPC_MMU_601)
-//#define POWERPC_EXCP_601     (POWERPC_EXCP_601)
-#define POWERPC_INPUT_601    (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_601     (bfd_mach_ppc_601)
-#define POWERPC_FLAG_601     (POWERPC_FLAG_SE | POWERPC_FLAG_RTC_CLK)
 
 static void init_proc_601 (CPUPPCState *env)
 {
@@ -4945,16 +4916,16 @@ POWERPC_FAMILY(601)(ObjectClass *oc, void *data)
                        PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE |
                        PPC_SEGMENT | PPC_EXTERN;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000000FD70ULL;
+    pcc->mmu_model = POWERPC_MMU_601;
+    pcc->excp_model = POWERPC_EXCP_601;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_601;
+    pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_RTC_CLK;
 }
 
 /* PowerPC 601v                                                              */
-#define POWERPC_MSRM_601v    (0x000000000000FD70ULL)
 #define POWERPC_MSRR_601v    (0x0000000000001040ULL)
-#define POWERPC_MMU_601v     (POWERPC_MMU_601)
-#define POWERPC_EXCP_601v    (POWERPC_EXCP_601)
-#define POWERPC_INPUT_601v   (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_601v    (bfd_mach_ppc_601)
-#define POWERPC_FLAG_601v    (POWERPC_FLAG_SE | POWERPC_FLAG_RTC_CLK)
 
 static void init_proc_601v (CPUPPCState *env)
 {
@@ -4978,18 +4949,15 @@ POWERPC_FAMILY(601v)(ObjectClass *oc, void *data)
                        PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE |
                        PPC_SEGMENT | PPC_EXTERN;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000000FD70ULL;
+    pcc->mmu_model = POWERPC_MMU_601;
+    pcc->excp_model = POWERPC_EXCP_601;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_601;
+    pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_RTC_CLK;
 }
 
 /* PowerPC 602                                                               */
-#define POWERPC_MSRM_602     (0x0000000000C7FF73ULL)
-/* XXX: 602 MMU is quite specific. Should add a special case */
-#define POWERPC_MMU_602      (POWERPC_MMU_SOFT_6xx)
-//#define POWERPC_EXCP_602     (POWERPC_EXCP_602)
-#define POWERPC_INPUT_602    (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_602     (bfd_mach_ppc_602)
-#define POWERPC_FLAG_602     (POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |           \
-                              POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_602 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5031,17 +4999,17 @@ POWERPC_FAMILY(602)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBIE | PPC_6xx_TLB | PPC_MEM_TLBSYNC |
                        PPC_SEGMENT | PPC_602_SPEC;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x0000000000C7FF73ULL;
+    /* XXX: 602 MMU is quite specific. Should add a special case */
+    pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
+    pcc->excp_model = POWERPC_EXCP_602;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_602;
+    pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 603                                                               */
-#define POWERPC_MSRM_603     (0x000000000007FF73ULL)
-#define POWERPC_MMU_603      (POWERPC_MMU_SOFT_6xx)
-//#define POWERPC_EXCP_603     (POWERPC_EXCP_603)
-#define POWERPC_INPUT_603    (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_603     (bfd_mach_ppc_603)
-#define POWERPC_FLAG_603     (POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |           \
-                              POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_603 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5083,17 +5051,16 @@ POWERPC_FAMILY(603)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
                        PPC_SEGMENT | PPC_EXTERN;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000007FF73ULL;
+    pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
+    pcc->excp_model = POWERPC_EXCP_603;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_603;
+    pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 603e                                                              */
-#define POWERPC_MSRM_603E    (0x000000000007FF73ULL)
-#define POWERPC_MMU_603E     (POWERPC_MMU_SOFT_6xx)
-//#define POWERPC_EXCP_603E    (POWERPC_EXCP_603E)
-#define POWERPC_INPUT_603E   (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_603E    (bfd_mach_ppc_ec603e)
-#define POWERPC_FLAG_603E    (POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |           \
-                              POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_603E (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5140,17 +5107,16 @@ POWERPC_FAMILY(603E)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
                        PPC_SEGMENT | PPC_EXTERN;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000007FF73ULL;
+    pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
+    pcc->excp_model = POWERPC_EXCP_603E;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_ec603e;
+    pcc->flags = POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 604                                                               */
-#define POWERPC_MSRM_604     (0x000000000005FF77ULL)
-#define POWERPC_MMU_604      (POWERPC_MMU_32B)
-//#define POWERPC_EXCP_604     (POWERPC_EXCP_604)
-#define POWERPC_INPUT_604    (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_604     (bfd_mach_ppc_604)
-#define POWERPC_FLAG_604     (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
-                              POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_604 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5186,17 +5152,16 @@ POWERPC_FAMILY(604)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
                        PPC_SEGMENT | PPC_EXTERN;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000005FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_32B;
+    pcc->excp_model = POWERPC_EXCP_604;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_604;
+    pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
+                 POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 604E                                                              */
-#define POWERPC_MSRM_604E    (0x000000000005FF77ULL)
-#define POWERPC_MMU_604E     (POWERPC_MMU_32B)
-#define POWERPC_EXCP_604E    (POWERPC_EXCP_604)
-#define POWERPC_INPUT_604E   (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_604E    (bfd_mach_ppc_604)
-#define POWERPC_FLAG_604E    (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
-                              POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_604E (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5252,17 +5217,16 @@ POWERPC_FAMILY(604E)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
                        PPC_SEGMENT | PPC_EXTERN;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000005FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_32B;
+    pcc->excp_model = POWERPC_EXCP_604;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_604;
+    pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
+                 POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 740                                                               */
-#define POWERPC_MSRM_740     (0x000000000005FF77ULL)
-#define POWERPC_MMU_740      (POWERPC_MMU_32B)
-#define POWERPC_EXCP_740     (POWERPC_EXCP_7x0)
-#define POWERPC_INPUT_740    (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_740     (bfd_mach_ppc_750)
-#define POWERPC_FLAG_740     (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
-                              POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_740 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5305,17 +5269,16 @@ POWERPC_FAMILY(740)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
                        PPC_SEGMENT | PPC_EXTERN;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000005FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_32B;
+    pcc->excp_model = POWERPC_EXCP_7x0;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_750;
+    pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
+                 POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 750                                                               */
-#define POWERPC_MSRM_750     (0x000000000005FF77ULL)
-#define POWERPC_MMU_750      (POWERPC_MMU_32B)
-#define POWERPC_EXCP_750     (POWERPC_EXCP_7x0)
-#define POWERPC_INPUT_750    (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_750     (bfd_mach_ppc_750)
-#define POWERPC_FLAG_750     (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
-                              POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_750 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5366,17 +5329,16 @@ POWERPC_FAMILY(750)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
                        PPC_SEGMENT | PPC_EXTERN;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000005FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_32B;
+    pcc->excp_model = POWERPC_EXCP_7x0;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_750;
+    pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
+                 POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 750 CL                                                            */
-#define POWERPC_MSRM_750cl   (0x000000000005FF77ULL)
-#define POWERPC_MMU_750cl    (POWERPC_MMU_32B)
-#define POWERPC_EXCP_750cl   (POWERPC_EXCP_7x0)
-#define POWERPC_INPUT_750cl  (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_750cl   (bfd_mach_ppc_750)
-#define POWERPC_FLAG_750cl   (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
-                              POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_750cl (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5550,17 +5512,16 @@ POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
                        PPC_SEGMENT | PPC_EXTERN;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000005FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_32B;
+    pcc->excp_model = POWERPC_EXCP_7x0;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_750;
+    pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
+                 POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 750CX                                                             */
-#define POWERPC_MSRM_750cx   (0x000000000005FF77ULL)
-#define POWERPC_MMU_750cx    (POWERPC_MMU_32B)
-#define POWERPC_EXCP_750cx   (POWERPC_EXCP_7x0)
-#define POWERPC_INPUT_750cx  (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_750cx   (bfd_mach_ppc_750)
-#define POWERPC_FLAG_750cx   (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
-                              POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_750cx (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5615,17 +5576,16 @@ POWERPC_FAMILY(750cx)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
                        PPC_SEGMENT | PPC_EXTERN;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000005FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_32B;
+    pcc->excp_model = POWERPC_EXCP_7x0;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_750;
+    pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
+                 POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 750FX                                                             */
-#define POWERPC_MSRM_750fx   (0x000000000005FF77ULL)
-#define POWERPC_MMU_750fx    (POWERPC_MMU_32B)
-#define POWERPC_EXCP_750fx   (POWERPC_EXCP_7x0)
-#define POWERPC_INPUT_750fx  (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_750fx   (bfd_mach_ppc_750)
-#define POWERPC_FLAG_750fx   (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
-                              POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_750fx (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5685,17 +5645,16 @@ POWERPC_FAMILY(750fx)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
                        PPC_SEGMENT | PPC_EXTERN;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000005FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_32B;
+    pcc->excp_model = POWERPC_EXCP_7x0;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_750;
+    pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
+                 POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 750GX                                                             */
-#define POWERPC_MSRM_750gx   (0x000000000005FF77ULL)
-#define POWERPC_MMU_750gx    (POWERPC_MMU_32B)
-#define POWERPC_EXCP_750gx   (POWERPC_EXCP_7x0)
-#define POWERPC_INPUT_750gx  (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_750gx   (bfd_mach_ppc_750)
-#define POWERPC_FLAG_750gx   (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
-                              POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_750gx (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5755,17 +5714,16 @@ POWERPC_FAMILY(750gx)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
                        PPC_SEGMENT | PPC_EXTERN;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000005FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_32B;
+    pcc->excp_model = POWERPC_EXCP_7x0;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_750;
+    pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
+                 POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 745                                                               */
-#define POWERPC_MSRM_745     (0x000000000005FF77ULL)
-#define POWERPC_MMU_745      (POWERPC_MMU_SOFT_6xx)
-#define POWERPC_EXCP_745     (POWERPC_EXCP_7x5)
-#define POWERPC_INPUT_745    (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_745     (bfd_mach_ppc_750)
-#define POWERPC_FLAG_745     (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
-                              POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_745 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5816,17 +5774,16 @@ POWERPC_FAMILY(745)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
                        PPC_SEGMENT | PPC_EXTERN;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000005FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
+    pcc->excp_model = POWERPC_EXCP_7x5;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_750;
+    pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
+                 POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 755                                                               */
-#define POWERPC_MSRM_755     (0x000000000005FF77ULL)
-#define POWERPC_MMU_755      (POWERPC_MMU_SOFT_6xx)
-#define POWERPC_EXCP_755     (POWERPC_EXCP_7x5)
-#define POWERPC_INPUT_755    (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_755     (bfd_mach_ppc_750)
-#define POWERPC_FLAG_755     (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
-                              POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_755 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5888,18 +5845,16 @@ POWERPC_FAMILY(755)(ObjectClass *oc, void *data)
                        PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
                        PPC_SEGMENT | PPC_EXTERN;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000005FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_SOFT_6xx;
+    pcc->excp_model = POWERPC_EXCP_7x5;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_750;
+    pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
+                 POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 7400 (aka G4)                                                     */
-#define POWERPC_MSRM_7400    (0x000000000205FF77ULL)
-#define POWERPC_MMU_7400     (POWERPC_MMU_32B)
-#define POWERPC_EXCP_7400    (POWERPC_EXCP_74xx)
-#define POWERPC_INPUT_7400   (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_7400    (bfd_mach_ppc_7400)
-#define POWERPC_FLAG_7400    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
-                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
-                              POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_7400 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5948,18 +5903,17 @@ POWERPC_FAMILY(7400)(ObjectClass *oc, void *data)
                        PPC_SEGMENT | PPC_EXTERN |
                        PPC_ALTIVEC;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000205FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_32B;
+    pcc->excp_model = POWERPC_EXCP_74xx;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_7400;
+    pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 7410 (aka G4)                                                     */
-#define POWERPC_MSRM_7410    (0x000000000205FF77ULL)
-#define POWERPC_MMU_7410     (POWERPC_MMU_32B)
-#define POWERPC_EXCP_7410    (POWERPC_EXCP_74xx)
-#define POWERPC_INPUT_7410   (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_7410    (bfd_mach_ppc_7400)
-#define POWERPC_FLAG_7410    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
-                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
-                              POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_7410 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -6014,18 +5968,17 @@ POWERPC_FAMILY(7410)(ObjectClass *oc, void *data)
                        PPC_SEGMENT | PPC_EXTERN |
                        PPC_ALTIVEC;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000205FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_32B;
+    pcc->excp_model = POWERPC_EXCP_74xx;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_7400;
+    pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 7440 (aka G4)                                                     */
-#define POWERPC_MSRM_7440    (0x000000000205FF77ULL)
-#define POWERPC_MMU_7440     (POWERPC_MMU_SOFT_74xx)
-#define POWERPC_EXCP_7440    (POWERPC_EXCP_74xx)
-#define POWERPC_INPUT_7440   (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_7440    (bfd_mach_ppc_7400)
-#define POWERPC_FLAG_7440    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
-                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
-                              POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_7440 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -6106,18 +6059,17 @@ POWERPC_FAMILY(7440)(ObjectClass *oc, void *data)
                        PPC_SEGMENT | PPC_EXTERN |
                        PPC_ALTIVEC;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000205FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_SOFT_74xx;
+    pcc->excp_model = POWERPC_EXCP_74xx;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_7400;
+    pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 7450 (aka G4)                                                     */
-#define POWERPC_MSRM_7450    (0x000000000205FF77ULL)
-#define POWERPC_MMU_7450     (POWERPC_MMU_SOFT_74xx)
-#define POWERPC_EXCP_7450    (POWERPC_EXCP_74xx)
-#define POWERPC_INPUT_7450   (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_7450    (bfd_mach_ppc_7400)
-#define POWERPC_FLAG_7450    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
-                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
-                              POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_7450 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -6224,18 +6176,17 @@ POWERPC_FAMILY(7450)(ObjectClass *oc, void *data)
                        PPC_SEGMENT | PPC_EXTERN |
                        PPC_ALTIVEC;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000205FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_SOFT_74xx;
+    pcc->excp_model = POWERPC_EXCP_74xx;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_7400;
+    pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 7445 (aka G4)                                                     */
-#define POWERPC_MSRM_7445    (0x000000000205FF77ULL)
-#define POWERPC_MMU_7445     (POWERPC_MMU_SOFT_74xx)
-#define POWERPC_EXCP_7445    (POWERPC_EXCP_74xx)
-#define POWERPC_INPUT_7445   (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_7445    (bfd_mach_ppc_7400)
-#define POWERPC_FLAG_7445    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
-                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
-                              POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_7445 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -6345,18 +6296,17 @@ POWERPC_FAMILY(7445)(ObjectClass *oc, void *data)
                        PPC_SEGMENT | PPC_EXTERN |
                        PPC_ALTIVEC;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000205FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_SOFT_74xx;
+    pcc->excp_model = POWERPC_EXCP_74xx;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_7400;
+    pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 7455 (aka G4)                                                     */
-#define POWERPC_MSRM_7455    (0x000000000205FF77ULL)
-#define POWERPC_MMU_7455     (POWERPC_MMU_SOFT_74xx)
-#define POWERPC_EXCP_7455    (POWERPC_EXCP_74xx)
-#define POWERPC_INPUT_7455   (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_7455    (bfd_mach_ppc_7400)
-#define POWERPC_FLAG_7455    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
-                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
-                              POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_7455 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -6468,18 +6418,17 @@ POWERPC_FAMILY(7455)(ObjectClass *oc, void *data)
                        PPC_SEGMENT | PPC_EXTERN |
                        PPC_ALTIVEC;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000205FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_SOFT_74xx;
+    pcc->excp_model = POWERPC_EXCP_74xx;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_7400;
+    pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 7457 (aka G4)                                                     */
-#define POWERPC_MSRM_7457    (0x000000000205FF77ULL)
-#define POWERPC_MMU_7457     (POWERPC_MMU_SOFT_74xx)
-#define POWERPC_EXCP_7457    (POWERPC_EXCP_74xx)
-#define POWERPC_INPUT_7457   (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_7457    (bfd_mach_ppc_7400)
-#define POWERPC_FLAG_7457    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
-                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
-                              POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_7457 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -6615,19 +6564,18 @@ POWERPC_FAMILY(7457)(ObjectClass *oc, void *data)
                        PPC_SEGMENT | PPC_EXTERN |
                        PPC_ALTIVEC;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x000000000205FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_SOFT_74xx;
+    pcc->excp_model = POWERPC_EXCP_74xx;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc_7400;
+    pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 #if defined (TARGET_PPC64)
 /* PowerPC 970                                                               */
-#define POWERPC_MSRM_970     (0x900000000204FF36ULL)
-#define POWERPC_MMU_970      (POWERPC_MMU_64B)
-//#define POWERPC_EXCP_970     (POWERPC_EXCP_970)
-#define POWERPC_INPUT_970    (PPC_FLAGS_INPUT_970)
-#define POWERPC_BFDM_970     (bfd_mach_ppc64)
-#define POWERPC_FLAG_970     (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
-                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
-                              POWERPC_FLAG_BUS_CLK)
-
 #if defined(CONFIG_USER_ONLY)
 #define POWERPC970_HID5_INIT 0x00000080
 #else
@@ -6720,18 +6668,17 @@ POWERPC_FAMILY(970)(ObjectClass *oc, void *data)
                        PPC_64B | PPC_ALTIVEC |
                        PPC_SEGMENT_64B | PPC_SLBI;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x900000000204FF36ULL;
+    pcc->mmu_model = POWERPC_MMU_64B;
+    pcc->excp_model = POWERPC_EXCP_970;
+    pcc->bus_model = PPC_FLAGS_INPUT_970;
+    pcc->bfd_mach = bfd_mach_ppc64;
+    pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 970FX (aka G5)                                                    */
-#define POWERPC_MSRM_970FX   (0x800000000204FF36ULL)
-#define POWERPC_MMU_970FX    (POWERPC_MMU_64B)
-#define POWERPC_EXCP_970FX   (POWERPC_EXCP_970)
-#define POWERPC_INPUT_970FX  (PPC_FLAGS_INPUT_970)
-#define POWERPC_BFDM_970FX   (bfd_mach_ppc64)
-#define POWERPC_FLAG_970FX   (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
-                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
-                              POWERPC_FLAG_BUS_CLK)
-
 static int check_pow_970FX (CPUPPCState *env)
 {
     if (env->spr[SPR_HID0] & 0x00600000)
@@ -6830,18 +6777,17 @@ POWERPC_FAMILY(970FX)(ObjectClass *oc, void *data)
                        PPC_64B | PPC_ALTIVEC |
                        PPC_SEGMENT_64B | PPC_SLBI;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x800000000204FF36ULL;
+    pcc->mmu_model = POWERPC_MMU_64B;
+    pcc->excp_model = POWERPC_EXCP_970;
+    pcc->bus_model = PPC_FLAGS_INPUT_970;
+    pcc->bfd_mach = bfd_mach_ppc64;
+    pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 970 GX                                                            */
-#define POWERPC_MSRM_970GX   (0x800000000204FF36ULL)
-#define POWERPC_MMU_970GX    (POWERPC_MMU_64B)
-#define POWERPC_EXCP_970GX   (POWERPC_EXCP_970)
-#define POWERPC_INPUT_970GX  (PPC_FLAGS_INPUT_970)
-#define POWERPC_BFDM_970GX   (bfd_mach_ppc64)
-#define POWERPC_FLAG_970GX   (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
-                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
-                              POWERPC_FLAG_BUS_CLK)
-
 static int check_pow_970GX (CPUPPCState *env)
 {
     if (env->spr[SPR_HID0] & 0x00600000)
@@ -6928,18 +6874,17 @@ POWERPC_FAMILY(970GX)(ObjectClass *oc, void *data)
                        PPC_64B | PPC_ALTIVEC |
                        PPC_SEGMENT_64B | PPC_SLBI;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x800000000204FF36ULL;
+    pcc->mmu_model = POWERPC_MMU_64B;
+    pcc->excp_model = POWERPC_EXCP_970;
+    pcc->bus_model = PPC_FLAGS_INPUT_970;
+    pcc->bfd_mach = bfd_mach_ppc64;
+    pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* PowerPC 970 MP                                                            */
-#define POWERPC_MSRM_970MP   (0x900000000204FF36ULL)
-#define POWERPC_MMU_970MP    (POWERPC_MMU_64B)
-#define POWERPC_EXCP_970MP   (POWERPC_EXCP_970)
-#define POWERPC_INPUT_970MP  (PPC_FLAGS_INPUT_970)
-#define POWERPC_BFDM_970MP   (bfd_mach_ppc64)
-#define POWERPC_FLAG_970MP   (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
-                              POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
-                              POWERPC_FLAG_BUS_CLK)
-
 static int check_pow_970MP (CPUPPCState *env)
 {
     if (env->spr[SPR_HID0] & 0x01C00000)
@@ -7026,18 +6971,17 @@ POWERPC_FAMILY(970MP)(ObjectClass *oc, void *data)
                        PPC_64B | PPC_ALTIVEC |
                        PPC_SEGMENT_64B | PPC_SLBI;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x900000000204FF36ULL;
+    pcc->mmu_model = POWERPC_MMU_64B;
+    pcc->excp_model = POWERPC_EXCP_970;
+    pcc->bus_model = PPC_FLAGS_INPUT_970;
+    pcc->bfd_mach = bfd_mach_ppc64;
+    pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
+                 POWERPC_FLAG_BUS_CLK;
 }
 
 /* POWER7 */
-#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 | POWERPC_FLAG_CFAR)
-
 static void init_proc_POWER7 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -7117,17 +7061,17 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
                        PPC_SEGMENT_64B | PPC_SLBI |
                        PPC_POPCNTB | PPC_POPCNTWD;
     pcc->insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX;
+    pcc->msr_mask = 0x800000000204FF36ULL;
+    pcc->mmu_model = POWERPC_MMU_2_06;
+    pcc->excp_model = POWERPC_EXCP_POWER7;
+    pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
+    pcc->bfd_mach = bfd_mach_ppc64;
+    pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
+                 POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
+                 POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR;
 }
 
 /* PowerPC 620                                                               */
-#define POWERPC_MSRM_620     (0x800000000005FF77ULL)
-//#define POWERPC_MMU_620      (POWERPC_MMU_620)
-#define POWERPC_EXCP_620     (POWERPC_EXCP_970)
-#define POWERPC_INPUT_620    (PPC_FLAGS_INPUT_6xx)
-#define POWERPC_BFDM_620     (bfd_mach_ppc64)
-#define POWERPC_FLAG_620     (POWERPC_FLAG_SE | POWERPC_FLAG_BE |            \
-                              POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-
 static void init_proc_620 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -7165,6 +7109,13 @@ POWERPC_FAMILY(620)(ObjectClass *oc, void *data)
                        PPC_SEGMENT | PPC_EXTERN |
                        PPC_64B | PPC_SLBI;
     pcc->insns_flags2 = PPC_NONE;
+    pcc->msr_mask = 0x800000000005FF77ULL;
+    pcc->mmu_model = POWERPC_MMU_620;
+    pcc->excp_model = POWERPC_EXCP_970;
+    pcc->bus_model = PPC_FLAGS_INPUT_6xx;
+    pcc->bfd_mach = bfd_mach_ppc64;
+    pcc->flags = POWERPC_FLAG_SE | POWERPC_FLAG_BE |
+                 POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK;
 }
 
 #endif /* defined (TARGET_PPC64) */
@@ -7885,12 +7836,6 @@ enum {
                                                                             \
         pcc->pvr          = _pvr;                                           \
         pcc->svr          = _svr;                                           \
-        pcc->msr_mask     = glue(POWERPC_MSRM_, _type);                     \
-        pcc->mmu_model    = glue(POWERPC_MMU_, _type);                      \
-        pcc->excp_model   = glue(POWERPC_EXCP_, _type);                     \
-        pcc->bus_model    = glue(POWERPC_INPUT_, _type);                    \
-        pcc->bfd_mach     = glue(POWERPC_BFDM_, _type);                     \
-        pcc->flags        = glue(POWERPC_FLAG_, _type);                     \
     }                                                                       \
                                                                             \
     static const TypeInfo                                                   \
commit 4d7fb187e07b35dcbe51e906927a94ed691e0c7a
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:44 2013 +0000

    target-ppc: Register all types for TARGET_PPCEMB
    
    Don't attempt to suppress registration of CPU types, since the criteria
    is actually a property of the class and should thus become a field.
    Since we can't check a field set in a class_init function before
    registering the type that leads to execution of that function, guard the
    -cpu class lookup instead and suppress exposing these classes in -cpu ?
    and in QMP.
    
    In case someone tries to hot-add an incompatible CPU via device_add,
    error out in realize.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 06df161..ca56028 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7876,14 +7876,6 @@ enum {
 /* PowerPC CPU definitions                                                   */
 #define POWERPC_DEF_PREFIX(pvr, svr, type)                                  \
     glue(glue(glue(glue(pvr, _), svr), _), type)
-#if defined(TARGET_PPCEMB)
-#define POWERPC_DEF_CONDITION(type)                                         \
-    if (glue(POWERPC_MMU_, type) != POWERPC_MMU_BOOKE) {                    \
-        return;                                                             \
-    }
-#else
-#define POWERPC_DEF_CONDITION(type)
-#endif
 #define POWERPC_DEF_SVR(_name, _pvr, _svr, _type)                             \
     static void                                                             \
     glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_class_init)            \
@@ -7912,7 +7904,6 @@ enum {
     static void                                                             \
     glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_register_types)(void)  \
     {                                                                       \
-        POWERPC_DEF_CONDITION(_type)                                        \
         type_register_static(                                               \
             &glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_type_info));  \
     }                                                                       \
@@ -10040,6 +10031,15 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp)
         }
     }
 
+#if defined(TARGET_PPCEMB)
+    if (pcc->mmu_model != POWERPC_MMU_BOOKE) {
+        error_setg(errp, "CPU does not possess a BookE MMU. "
+                   "Please use qemu-system-ppc or qemu-system-ppc64 instead "
+                   "or choose another CPU model.");
+        return;
+    }
+#endif
+
     create_ppc_opcodes(cpu, &local_err);
     if (local_err != NULL) {
         error_propagate(errp, local_err);
@@ -10239,6 +10239,12 @@ static gint ppc_cpu_compare_class_pvr(gconstpointer a, gconstpointer b)
         return -1;
     }
 
+#if defined(TARGET_PPCEMB)
+    if (pcc->mmu_model != POWERPC_MMU_BOOKE) {
+        return -1;
+    }
+#endif
+
     return pcc->pvr == pvr ? 0 : -1;
 }
 
@@ -10261,8 +10267,14 @@ static gint ppc_cpu_compare_class_name(gconstpointer a, gconstpointer b)
 {
     ObjectClass *oc = (ObjectClass *)a;
     const char *name = b;
+#if defined(TARGET_PPCEMB)
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+#endif
 
     if (strncasecmp(name, object_class_get_name(oc), strlen(name)) == 0 &&
+#if defined(TARGET_PPCEMB)
+        pcc->mmu_model == POWERPC_MMU_BOOKE &&
+#endif
         strcmp(object_class_get_name(oc) + strlen(name),
                "-" TYPE_POWERPC_CPU) == 0) {
         return 0;
@@ -10381,6 +10393,12 @@ static void ppc_cpu_list_entry(gpointer data, gpointer user_data)
     const char *typename = object_class_get_name(oc);
     char *name;
 
+#if defined(TARGET_PPCEMB)
+    if (pcc->mmu_model != POWERPC_MMU_BOOKE) {
+        return;
+    }
+#endif
+
     name = g_strndup(typename,
                      strlen(typename) - strlen("-" TYPE_POWERPC_CPU));
     (*s->cpu_fprintf)(s->file, "PowerPC %-16s PVR %08x\n",
@@ -10421,6 +10439,13 @@ static void ppc_cpu_defs_entry(gpointer data, gpointer user_data)
     const char *typename;
     CpuDefinitionInfoList *entry;
     CpuDefinitionInfo *info;
+#if defined(TARGET_PPCEMB)
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    if (pcc->mmu_model != POWERPC_MMU_BOOKE) {
+        return;
+    }
+#endif
 
     typename = object_class_get_name(oc);
     info = g_malloc0(sizeof(*info));
commit 53116ebfc98b72a00297255e216fac87c65e23a5
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:43 2013 +0000

    target-ppc: Set instruction flags on CPU family classes
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index c300aa8..06df161 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -3275,13 +3275,6 @@ static int check_pow_hid0_74xx (CPUPPCState *env)
     static void glue(glue(ppc_, _name), _cpu_family_class_init)
 
 /* PowerPC 401                                                               */
-#define POWERPC_INSNS_401    (PPC_INSNS_BASE | PPC_STRING |                   \
-                              PPC_WRTEE | PPC_DCR |                           \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_40x_ICBT |     \
-                              PPC_CACHE_DCBZ |                                \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_4xx_COMMON | PPC_40x_EXCP)
-#define POWERPC_INSNS2_401   (PPC_NONE)
 #define POWERPC_MSRM_401     (0x00000000000FD201ULL)
 #define POWERPC_MMU_401      (POWERPC_MMU_REAL)
 #define POWERPC_EXCP_401     (POWERPC_EXCP_40x)
@@ -3311,17 +3304,16 @@ POWERPC_FAMILY(401)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_401;
     pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
+                       PPC_WRTEE | PPC_DCR |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_40x_ICBT |
+                       PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_4xx_COMMON | PPC_40x_EXCP;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 401x2                                                             */
-#define POWERPC_INSNS_401x2  (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_DCR | PPC_WRTEE |                           \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_40x_ICBT |     \
-                              PPC_CACHE_DCBZ | PPC_CACHE_DCBA |               \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
-                              PPC_4xx_COMMON | PPC_40x_EXCP)
-#define POWERPC_INSNS2_401x2 (PPC_NONE)
 #define POWERPC_MSRM_401x2   (0x00000000001FD231ULL)
 #define POWERPC_MMU_401x2    (POWERPC_MMU_SOFT_4xx_Z)
 #define POWERPC_EXCP_401x2   (POWERPC_EXCP_40x)
@@ -3359,17 +3351,17 @@ POWERPC_FAMILY(401x2)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_401x2;
     pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_DCR | PPC_WRTEE |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_40x_ICBT |
+                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC |
+                       PPC_4xx_COMMON | PPC_40x_EXCP;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 401x3                                                             */
-#define POWERPC_INSNS_401x3  (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_DCR | PPC_WRTEE |                           \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_40x_ICBT |     \
-                              PPC_CACHE_DCBZ | PPC_CACHE_DCBA |               \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
-                              PPC_4xx_COMMON | PPC_40x_EXCP)
-#define POWERPC_INSNS2_401x3 (PPC_NONE)
 #define POWERPC_MSRM_401x3   (0x00000000001FD631ULL)
 #define POWERPC_MMU_401x3    (POWERPC_MMU_SOFT_4xx_Z)
 #define POWERPC_EXCP_401x3   (POWERPC_EXCP_40x)
@@ -3401,17 +3393,17 @@ POWERPC_FAMILY(401x3)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_401x3;
     pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_DCR | PPC_WRTEE |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_40x_ICBT |
+                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC |
+                       PPC_4xx_COMMON | PPC_40x_EXCP;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* IOP480                                                                    */
-#define POWERPC_INSNS_IOP480 (PPC_INSNS_BASE | PPC_STRING |                   \
-                              PPC_DCR | PPC_WRTEE |                           \
-                              PPC_CACHE | PPC_CACHE_ICBI |  PPC_40x_ICBT |    \
-                              PPC_CACHE_DCBZ | PPC_CACHE_DCBA |               \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
-                              PPC_4xx_COMMON | PPC_40x_EXCP)
-#define POWERPC_INSNS2_IOP480 (PPC_NONE)
 #define POWERPC_MSRM_IOP480  (0x00000000001FD231ULL)
 #define POWERPC_MMU_IOP480   (POWERPC_MMU_SOFT_4xx_Z)
 #define POWERPC_EXCP_IOP480  (POWERPC_EXCP_40x)
@@ -3449,16 +3441,17 @@ POWERPC_FAMILY(IOP480)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_IOP480;
     pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
+                       PPC_DCR | PPC_WRTEE |
+                       PPC_CACHE | PPC_CACHE_ICBI |  PPC_40x_ICBT |
+                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC |
+                       PPC_4xx_COMMON | PPC_40x_EXCP;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 403                                                               */
-#define POWERPC_INSNS_403    (PPC_INSNS_BASE | PPC_STRING |                   \
-                              PPC_DCR | PPC_WRTEE |                           \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_40x_ICBT |     \
-                              PPC_CACHE_DCBZ |                                \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_4xx_COMMON | PPC_40x_EXCP)
-#define POWERPC_INSNS2_403   (PPC_NONE)
 #define POWERPC_MSRM_403     (0x000000000007D00DULL)
 #define POWERPC_MMU_403      (POWERPC_MMU_REAL)
 #define POWERPC_EXCP_403     (POWERPC_EXCP_40x)
@@ -3489,17 +3482,16 @@ POWERPC_FAMILY(403)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_403;
     pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
+                       PPC_DCR | PPC_WRTEE |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_40x_ICBT |
+                       PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_4xx_COMMON | PPC_40x_EXCP;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 403 GCX                                                           */
-#define POWERPC_INSNS_403GCX (PPC_INSNS_BASE | PPC_STRING |                   \
-                              PPC_DCR | PPC_WRTEE |                           \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_40x_ICBT |     \
-                              PPC_CACHE_DCBZ |                                \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
-                              PPC_4xx_COMMON | PPC_40x_EXCP)
-#define POWERPC_INSNS2_403GCX (PPC_NONE)
 #define POWERPC_MSRM_403GCX  (0x000000000007D00DULL)
 #define POWERPC_MMU_403GCX   (POWERPC_MMU_SOFT_4xx_Z)
 #define POWERPC_EXCP_403GCX  (POWERPC_EXCP_40x)
@@ -3549,17 +3541,17 @@ POWERPC_FAMILY(403GCX)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_403GCX;
     pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
+                       PPC_DCR | PPC_WRTEE |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_40x_ICBT |
+                       PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC |
+                       PPC_4xx_COMMON | PPC_40x_EXCP;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 405                                                               */
-#define POWERPC_INSNS_405    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_DCR | PPC_WRTEE |                           \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_40x_ICBT |     \
-                              PPC_CACHE_DCBZ | PPC_CACHE_DCBA |               \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC | \
-                              PPC_4xx_COMMON | PPC_405_MAC | PPC_40x_EXCP)
-#define POWERPC_INSNS2_405   (PPC_NONE)
 #define POWERPC_MSRM_405     (0x000000000006E630ULL)
 #define POWERPC_MMU_405      (POWERPC_MMU_SOFT_4xx)
 #define POWERPC_EXCP_405     (POWERPC_EXCP_40x)
@@ -3608,20 +3600,17 @@ POWERPC_FAMILY(405)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_405;
     pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_DCR | PPC_WRTEE |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_40x_ICBT |
+                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_40x_TLB | PPC_MEM_TLBIA | PPC_MEM_TLBSYNC |
+                       PPC_4xx_COMMON | PPC_405_MAC | PPC_40x_EXCP;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 440 EP                                                            */
-#define POWERPC_INSNS_440EP  (PPC_INSNS_BASE | PPC_STRING |                   \
-                              PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |   \
-                              PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |           \
-                              PPC_FLOAT_STFIWX |                              \
-                              PPC_DCR | PPC_WRTEE | PPC_RFMCI |               \
-                              PPC_CACHE | PPC_CACHE_ICBI |                    \
-                              PPC_CACHE_DCBZ | PPC_CACHE_DCBA |               \
-                              PPC_MEM_TLBSYNC | PPC_MFTB |                    \
-                              PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |      \
-                              PPC_440_SPEC)
-#define POWERPC_INSNS2_440EP (PPC_NONE)
 #define POWERPC_MSRM_440EP   (0x000000000006FF30ULL)
 #define POWERPC_MMU_440EP    (POWERPC_MMU_BOOKE)
 #define POWERPC_EXCP_440EP   (POWERPC_EXCP_BOOKE)
@@ -3702,17 +3691,20 @@ POWERPC_FAMILY(440EP)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_440EP;
     pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
+                       PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |
+                       PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
+                       PPC_FLOAT_STFIWX |
+                       PPC_DCR | PPC_WRTEE | PPC_RFMCI |
+                       PPC_CACHE | PPC_CACHE_ICBI |
+                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
+                       PPC_MEM_TLBSYNC | PPC_MFTB |
+                       PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
+                       PPC_440_SPEC;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 440 GP                                                            */
-#define POWERPC_INSNS_440GP  (PPC_INSNS_BASE | PPC_STRING |                   \
-                              PPC_DCR | PPC_DCRX | PPC_WRTEE | PPC_MFAPIDI |  \
-                              PPC_CACHE | PPC_CACHE_ICBI |                    \
-                              PPC_CACHE_DCBZ | PPC_CACHE_DCBA |               \
-                              PPC_MEM_TLBSYNC | PPC_TLBIVA | PPC_MFTB |       \
-                              PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |      \
-                              PPC_440_SPEC)
-#define POWERPC_INSNS2_440GP (PPC_NONE)
 #define POWERPC_MSRM_440GP   (0x000000000006FF30ULL)
 #define POWERPC_MMU_440GP    (POWERPC_MMU_BOOKE)
 #define POWERPC_EXCP_440GP   (POWERPC_EXCP_BOOKE)
@@ -3775,17 +3767,17 @@ POWERPC_FAMILY(440GP)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_440GP;
     pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
+                       PPC_DCR | PPC_DCRX | PPC_WRTEE | PPC_MFAPIDI |
+                       PPC_CACHE | PPC_CACHE_ICBI |
+                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
+                       PPC_MEM_TLBSYNC | PPC_TLBIVA | PPC_MFTB |
+                       PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
+                       PPC_440_SPEC;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 440x4                                                             */
-#define POWERPC_INSNS_440x4  (PPC_INSNS_BASE | PPC_STRING |                   \
-                              PPC_DCR | PPC_WRTEE |                           \
-                              PPC_CACHE | PPC_CACHE_ICBI |                    \
-                              PPC_CACHE_DCBZ | PPC_CACHE_DCBA |               \
-                              PPC_MEM_TLBSYNC | PPC_MFTB |                    \
-                              PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |      \
-                              PPC_440_SPEC)
-#define POWERPC_INSNS2_440x4 (PPC_NONE)
 #define POWERPC_MSRM_440x4   (0x000000000006FF30ULL)
 #define POWERPC_MMU_440x4    (POWERPC_MMU_BOOKE)
 #define POWERPC_EXCP_440x4   (POWERPC_EXCP_BOOKE)
@@ -3848,17 +3840,17 @@ POWERPC_FAMILY(440x4)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_440x4;
     pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
+                       PPC_DCR | PPC_WRTEE |
+                       PPC_CACHE | PPC_CACHE_ICBI |
+                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
+                       PPC_MEM_TLBSYNC | PPC_MFTB |
+                       PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
+                       PPC_440_SPEC;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 440x5                                                             */
-#define POWERPC_INSNS_440x5  (PPC_INSNS_BASE | PPC_STRING |                   \
-                              PPC_DCR | PPC_WRTEE | PPC_RFMCI |               \
-                              PPC_CACHE | PPC_CACHE_ICBI |                    \
-                              PPC_CACHE_DCBZ | PPC_CACHE_DCBA |               \
-                              PPC_MEM_TLBSYNC | PPC_MFTB |                    \
-                              PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |      \
-                              PPC_440_SPEC)
-#define POWERPC_INSNS2_440x5 (PPC_NONE)
 #define POWERPC_MSRM_440x5   (0x000000000006FF30ULL)
 #define POWERPC_MMU_440x5    (POWERPC_MMU_BOOKE)
 #define POWERPC_EXCP_440x5   (POWERPC_EXCP_BOOKE)
@@ -3939,18 +3931,17 @@ POWERPC_FAMILY(440x5)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_440x5;
     pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
+                       PPC_DCR | PPC_WRTEE | PPC_RFMCI |
+                       PPC_CACHE | PPC_CACHE_ICBI |
+                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
+                       PPC_MEM_TLBSYNC | PPC_MFTB |
+                       PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
+                       PPC_440_SPEC;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 460 (guessed)                                                     */
-#define POWERPC_INSNS_460    (PPC_INSNS_BASE | PPC_STRING |                   \
-                              PPC_DCR | PPC_DCRX  | PPC_DCRUX |               \
-                              PPC_WRTEE | PPC_MFAPIDI | PPC_MFTB |            \
-                              PPC_CACHE | PPC_CACHE_ICBI |                    \
-                              PPC_CACHE_DCBZ | PPC_CACHE_DCBA |               \
-                              PPC_MEM_TLBSYNC | PPC_TLBIVA |                  \
-                              PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |      \
-                              PPC_440_SPEC)
-#define POWERPC_INSNS2_460   (PPC_NONE)
 #define POWERPC_MSRM_460     (0x000000000006FF30ULL)
 #define POWERPC_MMU_460      (POWERPC_MMU_BOOKE)
 #define POWERPC_EXCP_460     (POWERPC_EXCP_BOOKE)
@@ -4036,21 +4027,18 @@ POWERPC_FAMILY(460)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_460;
     pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
+                       PPC_DCR | PPC_DCRX  | PPC_DCRUX |
+                       PPC_WRTEE | PPC_MFAPIDI | PPC_MFTB |
+                       PPC_CACHE | PPC_CACHE_ICBI |
+                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
+                       PPC_MEM_TLBSYNC | PPC_TLBIVA |
+                       PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
+                       PPC_440_SPEC;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 460F (guessed)                                                    */
-#define POWERPC_INSNS_460F   (PPC_INSNS_BASE | PPC_STRING |                   \
-                              PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |   \
-                              PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |           \
-                              PPC_FLOAT_STFIWX | PPC_MFTB |                   \
-                              PPC_DCR | PPC_DCRX | PPC_DCRUX |                \
-                              PPC_WRTEE | PPC_MFAPIDI |                       \
-                              PPC_CACHE | PPC_CACHE_ICBI |                    \
-                              PPC_CACHE_DCBZ | PPC_CACHE_DCBA |               \
-                              PPC_MEM_TLBSYNC | PPC_TLBIVA |                  \
-                              PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |      \
-                              PPC_440_SPEC)
-#define POWERPC_INSNS2_460F  (PPC_NONE)
 #define POWERPC_MSRM_460     (0x000000000006FF30ULL)
 #define POWERPC_MMU_460F     (POWERPC_MMU_BOOKE)
 #define POWERPC_EXCP_460F    (POWERPC_EXCP_BOOKE)
@@ -4136,14 +4124,21 @@ POWERPC_FAMILY(460F)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_460F;
     pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
+                       PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |
+                       PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
+                       PPC_FLOAT_STFIWX | PPC_MFTB |
+                       PPC_DCR | PPC_DCRX | PPC_DCRUX |
+                       PPC_WRTEE | PPC_MFAPIDI |
+                       PPC_CACHE | PPC_CACHE_ICBI |
+                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
+                       PPC_MEM_TLBSYNC | PPC_TLBIVA |
+                       PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC |
+                       PPC_440_SPEC;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* Freescale 5xx cores (aka RCPU) */
-#define POWERPC_INSNS_MPC5xx (PPC_INSNS_BASE | PPC_STRING |                   \
-                              PPC_MEM_EIEIO | PPC_MEM_SYNC |                  \
-                              PPC_CACHE_ICBI | PPC_FLOAT | PPC_FLOAT_STFIWX | \
-                              PPC_MFTB)
-#define POWERPC_INSNS2_MPC5xx (PPC_NONE)
 #define POWERPC_MSRM_MPC5xx  (0x000000000001FF43ULL)
 #define POWERPC_MMU_MPC5xx   (POWERPC_MMU_REAL)
 #define POWERPC_EXCP_MPC5xx  (POWERPC_EXCP_603)
@@ -4170,13 +4165,14 @@ POWERPC_FAMILY(MPC5xx)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_MPC5xx;
     pcc->check_pow = check_pow_none;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING |
+                       PPC_MEM_EIEIO | PPC_MEM_SYNC |
+                       PPC_CACHE_ICBI | PPC_FLOAT | PPC_FLOAT_STFIWX |
+                       PPC_MFTB;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* Freescale 8xx cores (aka PowerQUICC) */
-#define POWERPC_INSNS_MPC8xx (PPC_INSNS_BASE | PPC_STRING  |                  \
-                              PPC_MEM_EIEIO | PPC_MEM_SYNC |                  \
-                              PPC_CACHE_ICBI | PPC_MFTB)
-#define POWERPC_INSNS2_MPC8xx (PPC_NONE)
 #define POWERPC_MSRM_MPC8xx  (0x000000000001F673ULL)
 #define POWERPC_MMU_MPC8xx   (POWERPC_MMU_MPC8xx)
 #define POWERPC_EXCP_MPC8xx  (POWERPC_EXCP_603)
@@ -4203,18 +4199,14 @@ POWERPC_FAMILY(MPC8xx)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_MPC8xx;
     pcc->check_pow = check_pow_none;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING  |
+                       PPC_MEM_EIEIO | PPC_MEM_SYNC |
+                       PPC_CACHE_ICBI | PPC_MFTB;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* Freescale 82xx cores (aka PowerQUICC-II)                                  */
 /* PowerPC G2                                                                */
-#define POWERPC_INSNS_G2     (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
-                              PPC_FLOAT_STFIWX |                              \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
-                              PPC_SEGMENT | PPC_EXTERN)
-#define POWERPC_INSNS2_G2    (PPC_NONE)
 #define POWERPC_MSRM_G2      (0x000000000006FFF2ULL)
 #define POWERPC_MMU_G2       (POWERPC_MMU_SOFT_6xx)
 //#define POWERPC_EXCP_G2      (POWERPC_EXCP_G2)
@@ -4269,17 +4261,17 @@ POWERPC_FAMILY(G2)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_G2;
     pcc->check_pow = check_pow_hid0;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
+                       PPC_FLOAT_STFIWX |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
+                       PPC_SEGMENT | PPC_EXTERN;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC G2LE                                                              */
-#define POWERPC_INSNS_G2LE   (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
-                              PPC_FLOAT_STFIWX |                              \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
-                              PPC_SEGMENT | PPC_EXTERN)
-#define POWERPC_INSNS2_G2LE  (PPC_NONE)
 #define POWERPC_MSRM_G2LE    (0x000000000007FFF3ULL)
 #define POWERPC_MMU_G2LE     (POWERPC_MMU_SOFT_6xx)
 #define POWERPC_EXCP_G2LE    (POWERPC_EXCP_G2)
@@ -4334,26 +4326,17 @@ POWERPC_FAMILY(G2LE)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_G2LE;
     pcc->check_pow = check_pow_hid0;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
+                       PPC_FLOAT_STFIWX |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
+                       PPC_SEGMENT | PPC_EXTERN;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* e200 core                                                                 */
-/* XXX: unimplemented instructions:
- * dcblc
- * dcbtlst
- * dcbtstls
- * icblc
- * icbtls
- * tlbivax
- * all SPE multiply-accumulate instructions
- */
-#define POWERPC_INSNS_e200   (PPC_INSNS_BASE | PPC_ISEL |                     \
-                              PPC_SPE | PPC_SPE_SINGLE |                      \
-                              PPC_WRTEE | PPC_RFDI |                          \
-                              PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |   \
-                              PPC_CACHE_DCBZ | PPC_CACHE_DCBA |               \
-                              PPC_MEM_TLBSYNC | PPC_TLBIVAX |                 \
-                              PPC_BOOKE)
-#define POWERPC_INSNS2_e200  (PPC_NONE)
 #define POWERPC_MSRM_e200    (0x000000000606FF30ULL)
 #define POWERPC_MMU_e200     (POWERPC_MMU_BOOKE206)
 #define POWERPC_EXCP_e200    (POWERPC_EXCP_BOOKE)
@@ -4476,17 +4459,26 @@ POWERPC_FAMILY(e200)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_e200;
     pcc->check_pow = check_pow_hid0;
+    /* XXX: unimplemented instructions:
+     * dcblc
+     * dcbtlst
+     * dcbtstls
+     * icblc
+     * icbtls
+     * tlbivax
+     * all SPE multiply-accumulate instructions
+     */
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL |
+                       PPC_SPE | PPC_SPE_SINGLE |
+                       PPC_WRTEE | PPC_RFDI |
+                       PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |
+                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
+                       PPC_MEM_TLBSYNC | PPC_TLBIVAX |
+                       PPC_BOOKE;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* e300 core                                                                 */
-#define POWERPC_INSNS_e300   (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
-                              PPC_FLOAT_STFIWX |                              \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
-                              PPC_SEGMENT | PPC_EXTERN)
-#define POWERPC_INSNS2_e300  (PPC_NONE)
 #define POWERPC_MSRM_e300    (0x000000000007FFF3ULL)
 #define POWERPC_MMU_e300     (POWERPC_MMU_SOFT_6xx)
 #define POWERPC_EXCP_e300    (POWERPC_EXCP_603)
@@ -4534,16 +4526,17 @@ POWERPC_FAMILY(e300)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_e300;
     pcc->check_pow = check_pow_hid0;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
+                       PPC_FLOAT_STFIWX |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
+                       PPC_SEGMENT | PPC_EXTERN;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* e500v1 core                                                               */
-#define POWERPC_INSNS_e500v1   (PPC_INSNS_BASE | PPC_ISEL |             \
-                                PPC_SPE | PPC_SPE_SINGLE |              \
-                                PPC_WRTEE | PPC_RFDI |                  \
-                                PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI | \
-                                PPC_CACHE_DCBZ | PPC_CACHE_DCBA |       \
-                                PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC)
-#define POWERPC_INSNS2_e500v1  (PPC2_BOOKE206)
 #define POWERPC_MSRM_e500v1    (0x000000000606FF30ULL)
 #define POWERPC_MMU_e500v1     (POWERPC_MMU_BOOKE206)
 #define POWERPC_EXCP_e500v1    (POWERPC_EXCP_BOOKE)
@@ -4554,13 +4547,6 @@ POWERPC_FAMILY(e300)(ObjectClass *oc, void *data)
                                 POWERPC_FLAG_BUS_CLK)
 
 /* e500v2 core                                                               */
-#define POWERPC_INSNS_e500v2   (PPC_INSNS_BASE | PPC_ISEL |             \
-                                PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE |   \
-                                PPC_WRTEE | PPC_RFDI |                  \
-                                PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI | \
-                                PPC_CACHE_DCBZ | PPC_CACHE_DCBA |       \
-                                PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC)
-#define POWERPC_INSNS2_e500v2  (PPC2_BOOKE206)
 #define POWERPC_MSRM_e500v2    (0x000000000606FF30ULL)
 #define POWERPC_MMU_e500v2     (POWERPC_MMU_BOOKE206)
 #define POWERPC_EXCP_e500v2    (POWERPC_EXCP_BOOKE)
@@ -4571,15 +4557,6 @@ POWERPC_FAMILY(e300)(ObjectClass *oc, void *data)
                                 POWERPC_FLAG_BUS_CLK)
 
 /* e500mc core                                                               */
-#define POWERPC_INSNS_e500mc   (PPC_INSNS_BASE | PPC_ISEL |                 \
-                                PPC_WRTEE | PPC_RFDI | PPC_RFMCI |          \
-                                PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI | \
-                                PPC_CACHE_DCBZ | PPC_CACHE_DCBA |           \
-                                PPC_FLOAT | PPC_FLOAT_FRES |                \
-                                PPC_FLOAT_FRSQRTE | PPC_FLOAT_FSEL |        \
-                                PPC_FLOAT_STFIWX | PPC_WAIT |               \
-                                PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC)
-#define POWERPC_INSNS2_e500mc  (PPC2_BOOKE206 | PPC2_PRCNTL)
 #define POWERPC_MSRM_e500mc    (0x000000001402FB36ULL)
 #define POWERPC_MMU_e500mc     (POWERPC_MMU_BOOKE206)
 #define POWERPC_EXCP_e500mc    (POWERPC_EXCP_BOOKE)
@@ -4590,16 +4567,6 @@ POWERPC_FAMILY(e300)(ObjectClass *oc, void *data)
                                 POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
 
 /* e5500 core                                                                 */
-#define POWERPC_INSNS_e5500    (PPC_INSNS_BASE | PPC_ISEL |                    \
-                                PPC_WRTEE | PPC_RFDI | PPC_RFMCI |             \
-                                PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |  \
-                                PPC_CACHE_DCBZ | PPC_CACHE_DCBA |              \
-                                PPC_FLOAT | PPC_FLOAT_FRES |                   \
-                                PPC_FLOAT_FRSQRTE | PPC_FLOAT_FSEL |           \
-                                PPC_FLOAT_STFIWX | PPC_WAIT |                  \
-                                PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC | \
-                                PPC_64B | PPC_POPCNTB | PPC_POPCNTWD)
-#define POWERPC_INSNS2_e5500   (PPC2_BOOKE206 | PPC2_PRCNTL)
 #define POWERPC_MSRM_e5500     (0x000000009402FB36ULL)
 #define POWERPC_MMU_e5500      (POWERPC_MMU_BOOKE206)
 #define POWERPC_EXCP_e5500     (POWERPC_EXCP_BOOKE)
@@ -4829,6 +4796,13 @@ POWERPC_FAMILY(e500v1)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_e500v1;
     pcc->check_pow = check_pow_hid0;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL |
+                       PPC_SPE | PPC_SPE_SINGLE |
+                       PPC_WRTEE | PPC_RFDI |
+                       PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |
+                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
+                       PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC;
+    pcc->insns_flags2 = PPC2_BOOKE206;
 }
 
 static void init_proc_e500v2(CPUPPCState *env)
@@ -4842,6 +4816,13 @@ POWERPC_FAMILY(e500v2)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_e500v2;
     pcc->check_pow = check_pow_hid0;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL |
+                       PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE |
+                       PPC_WRTEE | PPC_RFDI |
+                       PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |
+                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
+                       PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC;
+    pcc->insns_flags2 = PPC2_BOOKE206;
 }
 
 static void init_proc_e500mc(CPUPPCState *env)
@@ -4855,6 +4836,15 @@ POWERPC_FAMILY(e500mc)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_e500mc;
     pcc->check_pow = check_pow_none;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL |
+                       PPC_WRTEE | PPC_RFDI | PPC_RFMCI |
+                       PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |
+                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
+                       PPC_FLOAT | PPC_FLOAT_FRES |
+                       PPC_FLOAT_FRSQRTE | PPC_FLOAT_FSEL |
+                       PPC_FLOAT_STFIWX | PPC_WAIT |
+                       PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC;
+    pcc->insns_flags2 = PPC2_BOOKE206 | PPC2_PRCNTL;
 }
 
 #ifdef TARGET_PPC64
@@ -4869,6 +4859,16 @@ POWERPC_FAMILY(e5500)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_e5500;
     pcc->check_pow = check_pow_none;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL |
+                       PPC_WRTEE | PPC_RFDI | PPC_RFMCI |
+                       PPC_CACHE | PPC_CACHE_LOCK | PPC_CACHE_ICBI |
+                       PPC_CACHE_DCBZ | PPC_CACHE_DCBA |
+                       PPC_FLOAT | PPC_FLOAT_FRES |
+                       PPC_FLOAT_FRSQRTE | PPC_FLOAT_FSEL |
+                       PPC_FLOAT_STFIWX | PPC_WAIT |
+                       PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC |
+                       PPC_64B | PPC_POPCNTB | PPC_POPCNTWD;
+    pcc->insns_flags2 = PPC2_BOOKE206 | PPC2_PRCNTL;
 }
 #endif
 
@@ -4876,18 +4876,18 @@ POWERPC_FAMILY(e5500)(ObjectClass *oc, void *data)
 
 /* POWER : same as 601, without mfmsr, mfsr                                  */
 #if defined(TODO)
-#define POWERPC_INSNS_POWER  (XXX_TODO)
 /* POWER RSC (from RAD6000) */
 #define POWERPC_MSRM_POWER   (0x00000000FEF0ULL)
+
+POWERPC_FAMILY(POWER)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->insns_flags = XXX_TODO;
+}
 #endif /* TODO */
 
 /* PowerPC 601                                                               */
-#define POWERPC_INSNS_601    (PPC_INSNS_BASE | PPC_STRING | PPC_POWER_BR |    \
-                              PPC_FLOAT |                                     \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE |  \
-                              PPC_SEGMENT | PPC_EXTERN)
-#define POWERPC_INSNS2_601   (PPC_NONE)
 #define POWERPC_MSRM_601     (0x000000000000FD70ULL)
 #define POWERPC_MSRR_601     (0x0000000000001040ULL)
 //#define POWERPC_MMU_601      (POWERPC_MMU_601)
@@ -4939,15 +4939,15 @@ POWERPC_FAMILY(601)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_601;
     pcc->check_pow = check_pow_none;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_POWER_BR |
+                       PPC_FLOAT |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE |
+                       PPC_SEGMENT | PPC_EXTERN;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 601v                                                              */
-#define POWERPC_INSNS_601v   (PPC_INSNS_BASE | PPC_STRING | PPC_POWER_BR |    \
-                              PPC_FLOAT |                                     \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE |  \
-                              PPC_SEGMENT | PPC_EXTERN)
-#define POWERPC_INSNS2_601v  (PPC_NONE)
 #define POWERPC_MSRM_601v    (0x000000000000FD70ULL)
 #define POWERPC_MSRR_601v    (0x0000000000001040ULL)
 #define POWERPC_MMU_601v     (POWERPC_MMU_601)
@@ -4972,17 +4972,15 @@ POWERPC_FAMILY(601v)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_601v;
     pcc->check_pow = check_pow_none;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_POWER_BR |
+                       PPC_FLOAT |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE |
+                       PPC_SEGMENT | PPC_EXTERN;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 602                                                               */
-#define POWERPC_INSNS_602    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
-                              PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |          \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_6xx_TLB | PPC_MEM_TLBSYNC | \
-                              PPC_SEGMENT | PPC_602_SPEC)
-#define POWERPC_INSNS2_602   (PPC_NONE)
 #define POWERPC_MSRM_602     (0x0000000000C7FF73ULL)
 /* XXX: 602 MMU is quite specific. Should add a special case */
 #define POWERPC_MMU_602      (POWERPC_MMU_SOFT_6xx)
@@ -5025,17 +5023,17 @@ POWERPC_FAMILY(602)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_602;
     pcc->check_pow = check_pow_hid0;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
+                       PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_6xx_TLB | PPC_MEM_TLBSYNC |
+                       PPC_SEGMENT | PPC_602_SPEC;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 603                                                               */
-#define POWERPC_INSNS_603    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
-                              PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |          \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
-                              PPC_SEGMENT | PPC_EXTERN)
-#define POWERPC_INSNS2_603   (PPC_NONE)
 #define POWERPC_MSRM_603     (0x000000000007FF73ULL)
 #define POWERPC_MMU_603      (POWERPC_MMU_SOFT_6xx)
 //#define POWERPC_EXCP_603     (POWERPC_EXCP_603)
@@ -5077,17 +5075,17 @@ POWERPC_FAMILY(603)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_603;
     pcc->check_pow = check_pow_hid0;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
+                       PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
+                       PPC_SEGMENT | PPC_EXTERN;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 603e                                                              */
-#define POWERPC_INSNS_603E   (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
-                              PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |          \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
-                              PPC_SEGMENT | PPC_EXTERN)
-#define POWERPC_INSNS2_603E  (PPC_NONE)
 #define POWERPC_MSRM_603E    (0x000000000007FF73ULL)
 #define POWERPC_MMU_603E     (POWERPC_MMU_SOFT_6xx)
 //#define POWERPC_EXCP_603E    (POWERPC_EXCP_603E)
@@ -5134,17 +5132,17 @@ POWERPC_FAMILY(603E)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_603E;
     pcc->check_pow = check_pow_hid0;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
+                       PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
+                       PPC_SEGMENT | PPC_EXTERN;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 604                                                               */
-#define POWERPC_INSNS_604    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
-                              PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |          \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_SEGMENT | PPC_EXTERN)
-#define POWERPC_INSNS2_604   (PPC_NONE)
 #define POWERPC_MSRM_604     (0x000000000005FF77ULL)
 #define POWERPC_MMU_604      (POWERPC_MMU_32B)
 //#define POWERPC_EXCP_604     (POWERPC_EXCP_604)
@@ -5180,17 +5178,17 @@ POWERPC_FAMILY(604)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_604;
     pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
+                       PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_SEGMENT | PPC_EXTERN;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 604E                                                              */
-#define POWERPC_INSNS_604E   (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
-                              PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |          \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_SEGMENT | PPC_EXTERN)
-#define POWERPC_INSNS2_604E  (PPC_NONE)
 #define POWERPC_MSRM_604E    (0x000000000005FF77ULL)
 #define POWERPC_MMU_604E     (POWERPC_MMU_32B)
 #define POWERPC_EXCP_604E    (POWERPC_EXCP_604)
@@ -5246,17 +5244,17 @@ POWERPC_FAMILY(604E)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_604E;
     pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
+                       PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_SEGMENT | PPC_EXTERN;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 740                                                               */
-#define POWERPC_INSNS_740    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
-                              PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |          \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_SEGMENT | PPC_EXTERN)
-#define POWERPC_INSNS2_740   (PPC_NONE)
 #define POWERPC_MSRM_740     (0x000000000005FF77ULL)
 #define POWERPC_MMU_740      (POWERPC_MMU_32B)
 #define POWERPC_EXCP_740     (POWERPC_EXCP_7x0)
@@ -5299,17 +5297,17 @@ POWERPC_FAMILY(740)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_740;
     pcc->check_pow = check_pow_hid0;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
+                       PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_SEGMENT | PPC_EXTERN;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 750                                                               */
-#define POWERPC_INSNS_750    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
-                              PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |          \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_SEGMENT | PPC_EXTERN)
-#define POWERPC_INSNS2_750   (PPC_NONE)
 #define POWERPC_MSRM_750     (0x000000000005FF77ULL)
 #define POWERPC_MMU_750      (POWERPC_MMU_32B)
 #define POWERPC_EXCP_750     (POWERPC_EXCP_7x0)
@@ -5360,55 +5358,17 @@ POWERPC_FAMILY(750)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_750;
     pcc->check_pow = check_pow_hid0;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
+                       PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_SEGMENT | PPC_EXTERN;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 750 CL                                                            */
-/* XXX: not implemented:
- * cache lock instructions:
- * dcbz_l
- * floating point paired instructions
- * psq_lux
- * psq_lx
- * psq_stux
- * psq_stx
- * ps_abs
- * ps_add
- * ps_cmpo0
- * ps_cmpo1
- * ps_cmpu0
- * ps_cmpu1
- * ps_div
- * ps_madd
- * ps_madds0
- * ps_madds1
- * ps_merge00
- * ps_merge01
- * ps_merge10
- * ps_merge11
- * ps_mr
- * ps_msub
- * ps_mul
- * ps_muls0
- * ps_muls1
- * ps_nabs
- * ps_neg
- * ps_nmadd
- * ps_nmsub
- * ps_res
- * ps_rsqrte
- * ps_sel
- * ps_sub
- * ps_sum0
- * ps_sum1
- */
-#define POWERPC_INSNS_750cl  (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
-                              PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |          \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_SEGMENT | PPC_EXTERN)
-#define POWERPC_INSNS2_750cl (PPC_NONE)
 #define POWERPC_MSRM_750cl   (0x000000000005FF77ULL)
 #define POWERPC_MMU_750cl    (POWERPC_MMU_32B)
 #define POWERPC_EXCP_750cl   (POWERPC_EXCP_7x0)
@@ -5544,17 +5504,55 @@ POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_750cl;
     pcc->check_pow = check_pow_hid0;
+    /* XXX: not implemented:
+     * cache lock instructions:
+     * dcbz_l
+     * floating point paired instructions
+     * psq_lux
+     * psq_lx
+     * psq_stux
+     * psq_stx
+     * ps_abs
+     * ps_add
+     * ps_cmpo0
+     * ps_cmpo1
+     * ps_cmpu0
+     * ps_cmpu1
+     * ps_div
+     * ps_madd
+     * ps_madds0
+     * ps_madds1
+     * ps_merge00
+     * ps_merge01
+     * ps_merge10
+     * ps_merge11
+     * ps_mr
+     * ps_msub
+     * ps_mul
+     * ps_muls0
+     * ps_muls1
+     * ps_nabs
+     * ps_neg
+     * ps_nmadd
+     * ps_nmsub
+     * ps_res
+     * ps_rsqrte
+     * ps_sel
+     * ps_sub
+     * ps_sum0
+     * ps_sum1
+     */
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
+                       PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_SEGMENT | PPC_EXTERN;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 750CX                                                             */
-#define POWERPC_INSNS_750cx  (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
-                              PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |          \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_SEGMENT | PPC_EXTERN)
-#define POWERPC_INSNS2_750cx (PPC_NONE)
 #define POWERPC_MSRM_750cx   (0x000000000005FF77ULL)
 #define POWERPC_MMU_750cx    (POWERPC_MMU_32B)
 #define POWERPC_EXCP_750cx   (POWERPC_EXCP_7x0)
@@ -5609,17 +5607,17 @@ POWERPC_FAMILY(750cx)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_750cx;
     pcc->check_pow = check_pow_hid0;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
+                       PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_SEGMENT | PPC_EXTERN;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 750FX                                                             */
-#define POWERPC_INSNS_750fx  (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
-                              PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |          \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_SEGMENT  | PPC_EXTERN)
-#define POWERPC_INSNS2_750fx (PPC_NONE)
 #define POWERPC_MSRM_750fx   (0x000000000005FF77ULL)
 #define POWERPC_MMU_750fx    (POWERPC_MMU_32B)
 #define POWERPC_EXCP_750fx   (POWERPC_EXCP_7x0)
@@ -5679,17 +5677,17 @@ POWERPC_FAMILY(750fx)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_750fx;
     pcc->check_pow = check_pow_hid0;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
+                       PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_SEGMENT | PPC_EXTERN;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 750GX                                                             */
-#define POWERPC_INSNS_750gx  (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
-                              PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |          \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_SEGMENT  | PPC_EXTERN)
-#define POWERPC_INSNS2_750gx (PPC_NONE)
 #define POWERPC_MSRM_750gx   (0x000000000005FF77ULL)
 #define POWERPC_MMU_750gx    (POWERPC_MMU_32B)
 #define POWERPC_EXCP_750gx   (POWERPC_EXCP_7x0)
@@ -5749,17 +5747,17 @@ POWERPC_FAMILY(750gx)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_750gx;
     pcc->check_pow = check_pow_hid0;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
+                       PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_SEGMENT | PPC_EXTERN;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 745                                                               */
-#define POWERPC_INSNS_745    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
-                              PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |          \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
-                              PPC_SEGMENT | PPC_EXTERN)
-#define POWERPC_INSNS2_745   (PPC_NONE)
 #define POWERPC_MSRM_745     (0x000000000005FF77ULL)
 #define POWERPC_MMU_745      (POWERPC_MMU_SOFT_6xx)
 #define POWERPC_EXCP_745     (POWERPC_EXCP_7x5)
@@ -5810,17 +5808,17 @@ POWERPC_FAMILY(745)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_745;
     pcc->check_pow = check_pow_hid0;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
+                       PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
+                       PPC_SEGMENT | PPC_EXTERN;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 755                                                               */
-#define POWERPC_INSNS_755    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
-                              PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
-                              PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |          \
-                              PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB | \
-                              PPC_SEGMENT | PPC_EXTERN)
-#define POWERPC_INSNS2_755   (PPC_NONE)
 #define POWERPC_MSRM_755     (0x000000000005FF77ULL)
 #define POWERPC_MMU_755      (POWERPC_MMU_SOFT_6xx)
 #define POWERPC_EXCP_755     (POWERPC_EXCP_7x5)
@@ -5882,21 +5880,17 @@ POWERPC_FAMILY(755)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_755;
     pcc->check_pow = check_pow_hid0;
+    pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+                       PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
+                       PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX |
+                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_6xx_TLB |
+                       PPC_SEGMENT | PPC_EXTERN;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 7400 (aka G4)                                                     */
-#define POWERPC_INSNS_7400   (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_DCBA | PPC_CACHE_DCBZ |               \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_MEM_TLBIA |                                 \
-                              PPC_SEGMENT | PPC_EXTERN |                      \
-                              PPC_ALTIVEC)
-#define POWERPC_INSNS2_7400  (PPC_NONE)
 #define POWERPC_MSRM_7400    (0x000000000205FF77ULL)
 #define POWERPC_MMU_7400     (POWERPC_MMU_32B)
 #define POWERPC_EXCP_7400    (POWERPC_EXCP_74xx)
@@ -5942,21 +5936,21 @@ POWERPC_FAMILY(7400)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_7400;
     pcc->check_pow = check_pow_hid0;
+    pcc->insns_flags = 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_DCBA | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_MEM_TLBIA |
+                       PPC_SEGMENT | PPC_EXTERN |
+                       PPC_ALTIVEC;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 7410 (aka G4)                                                     */
-#define POWERPC_INSNS_7410   (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_DCBA | PPC_CACHE_DCBZ |               \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_MEM_TLBIA |                                 \
-                              PPC_SEGMENT | PPC_EXTERN |                      \
-                              PPC_ALTIVEC)
-#define POWERPC_INSNS2_7410  (PPC_NONE)
 #define POWERPC_MSRM_7410    (0x000000000205FF77ULL)
 #define POWERPC_MMU_7410     (POWERPC_MMU_32B)
 #define POWERPC_EXCP_7410    (POWERPC_EXCP_74xx)
@@ -6008,21 +6002,21 @@ POWERPC_FAMILY(7410)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_7410;
     pcc->check_pow = check_pow_hid0;
+    pcc->insns_flags = 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_DCBA | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_MEM_TLBIA |
+                       PPC_SEGMENT | PPC_EXTERN |
+                       PPC_ALTIVEC;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 7440 (aka G4)                                                     */
-#define POWERPC_INSNS_7440   (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_DCBA | PPC_CACHE_DCBZ |               \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_MEM_TLBIA | PPC_74xx_TLB |                  \
-                              PPC_SEGMENT | PPC_EXTERN |                      \
-                              PPC_ALTIVEC)
-#define POWERPC_INSNS2_7440  (PPC_NONE)
 #define POWERPC_MSRM_7440    (0x000000000205FF77ULL)
 #define POWERPC_MMU_7440     (POWERPC_MMU_SOFT_74xx)
 #define POWERPC_EXCP_7440    (POWERPC_EXCP_74xx)
@@ -6100,21 +6094,21 @@ POWERPC_FAMILY(7440)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_7440;
     pcc->check_pow = check_pow_hid0_74xx;
+    pcc->insns_flags = 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_DCBA | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_MEM_TLBIA | PPC_74xx_TLB |
+                       PPC_SEGMENT | PPC_EXTERN |
+                       PPC_ALTIVEC;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 7450 (aka G4)                                                     */
-#define POWERPC_INSNS_7450   (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_DCBA | PPC_CACHE_DCBZ |               \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_MEM_TLBIA | PPC_74xx_TLB |                  \
-                              PPC_SEGMENT | PPC_EXTERN |                      \
-                              PPC_ALTIVEC)
-#define POWERPC_INSNS2_7450  (PPC_NONE)
 #define POWERPC_MSRM_7450    (0x000000000205FF77ULL)
 #define POWERPC_MMU_7450     (POWERPC_MMU_SOFT_74xx)
 #define POWERPC_EXCP_7450    (POWERPC_EXCP_74xx)
@@ -6218,21 +6212,21 @@ POWERPC_FAMILY(7450)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_7450;
     pcc->check_pow = check_pow_hid0_74xx;
+    pcc->insns_flags = 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_DCBA | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_MEM_TLBIA | PPC_74xx_TLB |
+                       PPC_SEGMENT | PPC_EXTERN |
+                       PPC_ALTIVEC;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 7445 (aka G4)                                                     */
-#define POWERPC_INSNS_7445   (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_DCBA | PPC_CACHE_DCBZ |               \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_MEM_TLBIA | PPC_74xx_TLB |                  \
-                              PPC_SEGMENT | PPC_EXTERN |                      \
-                              PPC_ALTIVEC)
-#define POWERPC_INSNS2_7445  (PPC_NONE)
 #define POWERPC_MSRM_7445    (0x000000000205FF77ULL)
 #define POWERPC_MMU_7445     (POWERPC_MMU_SOFT_74xx)
 #define POWERPC_EXCP_7445    (POWERPC_EXCP_74xx)
@@ -6339,21 +6333,21 @@ POWERPC_FAMILY(7445)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_7445;
     pcc->check_pow = check_pow_hid0_74xx;
+    pcc->insns_flags = 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_DCBA | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_MEM_TLBIA | PPC_74xx_TLB |
+                       PPC_SEGMENT | PPC_EXTERN |
+                       PPC_ALTIVEC;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 7455 (aka G4)                                                     */
-#define POWERPC_INSNS_7455   (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_DCBA | PPC_CACHE_DCBZ |               \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_MEM_TLBIA | PPC_74xx_TLB |                  \
-                              PPC_SEGMENT | PPC_EXTERN |                      \
-                              PPC_ALTIVEC)
-#define POWERPC_INSNS2_7455  (PPC_NONE)
 #define POWERPC_MSRM_7455    (0x000000000205FF77ULL)
 #define POWERPC_MMU_7455     (POWERPC_MMU_SOFT_74xx)
 #define POWERPC_EXCP_7455    (POWERPC_EXCP_74xx)
@@ -6462,21 +6456,21 @@ POWERPC_FAMILY(7455)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_7455;
     pcc->check_pow = check_pow_hid0_74xx;
+    pcc->insns_flags = 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_DCBA | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_MEM_TLBIA | PPC_74xx_TLB |
+                       PPC_SEGMENT | PPC_EXTERN |
+                       PPC_ALTIVEC;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 7457 (aka G4)                                                     */
-#define POWERPC_INSNS_7457   (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_DCBA | PPC_CACHE_DCBZ |               \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_MEM_TLBIA | PPC_74xx_TLB |                  \
-                              PPC_SEGMENT | PPC_EXTERN |                      \
-                              PPC_ALTIVEC)
-#define POWERPC_INSNS2_7457  (PPC_NONE)
 #define POWERPC_MSRM_7457    (0x000000000205FF77ULL)
 #define POWERPC_MMU_7457     (POWERPC_MMU_SOFT_74xx)
 #define POWERPC_EXCP_7457    (POWERPC_EXCP_74xx)
@@ -6609,20 +6603,22 @@ POWERPC_FAMILY(7457)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_7457;
     pcc->check_pow = check_pow_hid0_74xx;
+    pcc->insns_flags = 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_DCBA | PPC_CACHE_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_MEM_TLBIA | PPC_74xx_TLB |
+                       PPC_SEGMENT | PPC_EXTERN |
+                       PPC_ALTIVEC;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 #if defined (TARGET_PPC64)
 /* PowerPC 970                                                               */
-#define POWERPC_INSNS_970    (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_DCBZ |  \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_64B | PPC_ALTIVEC |                         \
-                              PPC_SEGMENT_64B | PPC_SLBI)
-#define POWERPC_INSNS2_970   (PPC_NONE)
 #define POWERPC_MSRM_970     (0x900000000204FF36ULL)
 #define POWERPC_MMU_970      (POWERPC_MMU_64B)
 //#define POWERPC_EXCP_970     (POWERPC_EXCP_970)
@@ -6714,19 +6710,19 @@ POWERPC_FAMILY(970)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_970;
     pcc->check_pow = check_pow_970;
+    pcc->insns_flags = 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_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_64B | PPC_ALTIVEC |
+                       PPC_SEGMENT_64B | PPC_SLBI;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 970FX (aka G5)                                                    */
-#define POWERPC_INSNS_970FX  (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_DCBZ |  \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_64B | PPC_ALTIVEC |                         \
-                              PPC_SEGMENT_64B | PPC_SLBI)
-#define POWERPC_INSNS2_970FX (PPC_NONE)
 #define POWERPC_MSRM_970FX   (0x800000000204FF36ULL)
 #define POWERPC_MMU_970FX    (POWERPC_MMU_64B)
 #define POWERPC_EXCP_970FX   (POWERPC_EXCP_970)
@@ -6824,19 +6820,19 @@ POWERPC_FAMILY(970FX)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_970FX;
     pcc->check_pow = check_pow_970FX;
+    pcc->insns_flags = 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_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_64B | PPC_ALTIVEC |
+                       PPC_SEGMENT_64B | PPC_SLBI;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 970 GX                                                            */
-#define POWERPC_INSNS_970GX  (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_DCBZ |  \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_64B | PPC_ALTIVEC |                         \
-                              PPC_SEGMENT_64B | PPC_SLBI)
-#define POWERPC_INSNS2_970GX (PPC_NONE)
 #define POWERPC_MSRM_970GX   (0x800000000204FF36ULL)
 #define POWERPC_MMU_970GX    (POWERPC_MMU_64B)
 #define POWERPC_EXCP_970GX   (POWERPC_EXCP_970)
@@ -6922,19 +6918,19 @@ POWERPC_FAMILY(970GX)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_970GX;
     pcc->check_pow = check_pow_970GX;
+    pcc->insns_flags = 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_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_64B | PPC_ALTIVEC |
+                       PPC_SEGMENT_64B | PPC_SLBI;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* PowerPC 970 MP                                                            */
-#define POWERPC_INSNS_970MP  (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_DCBZ |  \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_64B | PPC_ALTIVEC |                         \
-                              PPC_SEGMENT_64B | PPC_SLBI)
-#define POWERPC_INSNS2_970MP (PPC_NONE)
 #define POWERPC_MSRM_970MP   (0x900000000204FF36ULL)
 #define POWERPC_MMU_970MP    (POWERPC_MMU_64B)
 #define POWERPC_EXCP_970MP   (POWERPC_EXCP_970)
@@ -7020,20 +7016,19 @@ POWERPC_FAMILY(970MP)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_970MP;
     pcc->check_pow = check_pow_970MP;
+    pcc->insns_flags = 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_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_64B | PPC_ALTIVEC |
+                       PPC_SEGMENT_64B | PPC_SLBI;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 /* 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_DCBZ |  \
-                              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_INSNS2_POWER7 (PPC2_VSX | PPC2_DFP | PPC2_DBRX)
 #define POWERPC_MSRM_POWER7   (0x800000000204FF36ULL)
 #define POWERPC_MMU_POWER7    (POWERPC_MMU_2_06)
 #define POWERPC_EXCP_POWER7   (POWERPC_EXCP_POWER7)
@@ -7111,19 +7106,20 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_POWER7;
     pcc->check_pow = check_pow_nocheck;
+    pcc->insns_flags = 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_DCBZ |
+                       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;
+    pcc->insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX;
 }
 
 /* PowerPC 620                                                               */
-#define POWERPC_INSNS_620    (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_DCBZ |   \
-                              PPC_MEM_SYNC | PPC_MEM_EIEIO |                  \
-                              PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |               \
-                              PPC_SEGMENT | PPC_EXTERN |                      \
-                              PPC_64B | PPC_SLBI)
-#define POWERPC_INSNS2_620   (PPC_NONE)
 #define POWERPC_MSRM_620     (0x800000000005FF77ULL)
 //#define POWERPC_MMU_620      (POWERPC_MMU_620)
 #define POWERPC_EXCP_620     (POWERPC_EXCP_970)
@@ -7159,6 +7155,16 @@ POWERPC_FAMILY(620)(ObjectClass *oc, void *data)
 
     pcc->init_proc = init_proc_620;
     pcc->check_pow = check_pow_nocheck; /* Check this */
+    pcc->insns_flags = 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_DCBZ |
+                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
+                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+                       PPC_SEGMENT | PPC_EXTERN |
+                       PPC_64B | PPC_SLBI;
+    pcc->insns_flags2 = PPC_NONE;
 }
 
 #endif /* defined (TARGET_PPC64) */
@@ -7887,8 +7893,6 @@ enum {
                                                                             \
         pcc->pvr          = _pvr;                                           \
         pcc->svr          = _svr;                                           \
-        pcc->insns_flags  = glue(POWERPC_INSNS_, _type);                    \
-        pcc->insns_flags2 = glue(POWERPC_INSNS2_, _type);                   \
         pcc->msr_mask     = glue(POWERPC_MSRM_, _type);                     \
         pcc->mmu_model    = glue(POWERPC_MMU_, _type);                      \
         pcc->excp_model   = glue(POWERPC_EXCP_, _type);                     \
commit 7856e3a41ba8ec5da3dc0b449dc6feaf999d3ffe
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:42 2013 +0000

    target-ppc: Introduce abstract CPU family types
    
    Instead of assigning *_<family> constants, set .parent to a family type.
    
    Introduce a POWERPC_FAMILY() macro to keep type registration close to
    its implementation. This macro will need tweaking later.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index f707197..c300aa8 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -3252,6 +3252,28 @@ static int check_pow_hid0_74xx (CPUPPCState *env)
 /*****************************************************************************/
 /* PowerPC implementations definitions                                       */
 
+#define POWERPC_FAMILY(_name)                                               \
+    static void                                                             \
+    glue(glue(ppc_, _name), _cpu_family_class_init)(ObjectClass *, void *); \
+                                                                            \
+    static const TypeInfo                                                   \
+    glue(glue(ppc_, _name), _cpu_family_type_info) = {                      \
+        .name = stringify(_name) "-family-" TYPE_POWERPC_CPU,               \
+        .parent = TYPE_POWERPC_CPU,                                         \
+        .abstract = true,                                                   \
+        .class_init = glue(glue(ppc_, _name), _cpu_family_class_init),      \
+    };                                                                      \
+                                                                            \
+    static void glue(glue(ppc_, _name), _cpu_family_register_types)(void)   \
+    {                                                                       \
+        type_register_static(                                               \
+            &glue(glue(ppc_, _name), _cpu_family_type_info));               \
+    }                                                                       \
+                                                                            \
+    type_init(glue(glue(ppc_, _name), _cpu_family_register_types))          \
+                                                                            \
+    static void glue(glue(ppc_, _name), _cpu_family_class_init)
+
 /* PowerPC 401                                                               */
 #define POWERPC_INSNS_401    (PPC_INSNS_BASE | PPC_STRING |                   \
                               PPC_WRTEE | PPC_DCR |                           \
@@ -3267,7 +3289,6 @@ static int check_pow_hid0_74xx (CPUPPCState *env)
 #define POWERPC_BFDM_401     (bfd_mach_ppc_403)
 #define POWERPC_FLAG_401     (POWERPC_FLAG_CE | POWERPC_FLAG_DE |             \
                               POWERPC_FLAG_BUS_CLK)
-#define check_pow_401        check_pow_nocheck
 
 static void init_proc_401 (CPUPPCState *env)
 {
@@ -3284,6 +3305,14 @@ static void init_proc_401 (CPUPPCState *env)
     SET_WDT_PERIOD(16, 20, 24, 28);
 }
 
+POWERPC_FAMILY(401)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_401;
+    pcc->check_pow = check_pow_nocheck;
+}
+
 /* PowerPC 401x2                                                             */
 #define POWERPC_INSNS_401x2  (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_DCR | PPC_WRTEE |                           \
@@ -3300,7 +3329,6 @@ static void init_proc_401 (CPUPPCState *env)
 #define POWERPC_BFDM_401x2   (bfd_mach_ppc_403)
 #define POWERPC_FLAG_401x2   (POWERPC_FLAG_CE | POWERPC_FLAG_DE |             \
                               POWERPC_FLAG_BUS_CLK)
-#define check_pow_401x2      check_pow_nocheck
 
 static void init_proc_401x2 (CPUPPCState *env)
 {
@@ -3325,6 +3353,14 @@ static void init_proc_401x2 (CPUPPCState *env)
     SET_WDT_PERIOD(16, 20, 24, 28);
 }
 
+POWERPC_FAMILY(401x2)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_401x2;
+    pcc->check_pow = check_pow_nocheck;
+}
+
 /* PowerPC 401x3                                                             */
 #define POWERPC_INSNS_401x3  (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_DCR | PPC_WRTEE |                           \
@@ -3341,9 +3377,7 @@ static void init_proc_401x2 (CPUPPCState *env)
 #define POWERPC_BFDM_401x3   (bfd_mach_ppc_403)
 #define POWERPC_FLAG_401x3   (POWERPC_FLAG_CE | POWERPC_FLAG_DE |             \
                               POWERPC_FLAG_BUS_CLK)
-#define check_pow_401x3      check_pow_nocheck
 
-__attribute__ (( unused ))
 static void init_proc_401x3 (CPUPPCState *env)
 {
     gen_spr_40x(env);
@@ -3361,6 +3395,14 @@ static void init_proc_401x3 (CPUPPCState *env)
     SET_WDT_PERIOD(16, 20, 24, 28);
 }
 
+POWERPC_FAMILY(401x3)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_401x3;
+    pcc->check_pow = check_pow_nocheck;
+}
+
 /* IOP480                                                                    */
 #define POWERPC_INSNS_IOP480 (PPC_INSNS_BASE | PPC_STRING |                   \
                               PPC_DCR | PPC_WRTEE |                           \
@@ -3377,7 +3419,6 @@ static void init_proc_401x3 (CPUPPCState *env)
 #define POWERPC_BFDM_IOP480  (bfd_mach_ppc_403)
 #define POWERPC_FLAG_IOP480  (POWERPC_FLAG_CE | POWERPC_FLAG_DE |             \
                               POWERPC_FLAG_BUS_CLK)
-#define check_pow_IOP480     check_pow_nocheck
 
 static void init_proc_IOP480 (CPUPPCState *env)
 {
@@ -3402,6 +3443,14 @@ static void init_proc_IOP480 (CPUPPCState *env)
     SET_WDT_PERIOD(16, 20, 24, 28);
 }
 
+POWERPC_FAMILY(IOP480)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_IOP480;
+    pcc->check_pow = check_pow_nocheck;
+}
+
 /* PowerPC 403                                                               */
 #define POWERPC_INSNS_403    (PPC_INSNS_BASE | PPC_STRING |                   \
                               PPC_DCR | PPC_WRTEE |                           \
@@ -3417,7 +3466,6 @@ static void init_proc_IOP480 (CPUPPCState *env)
 #define POWERPC_BFDM_403     (bfd_mach_ppc_403)
 #define POWERPC_FLAG_403     (POWERPC_FLAG_CE | POWERPC_FLAG_PX |             \
                               POWERPC_FLAG_BUS_CLK)
-#define check_pow_403        check_pow_nocheck
 
 static void init_proc_403 (CPUPPCState *env)
 {
@@ -3435,6 +3483,14 @@ static void init_proc_403 (CPUPPCState *env)
     SET_WDT_PERIOD(16, 20, 24, 28);
 }
 
+POWERPC_FAMILY(403)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_403;
+    pcc->check_pow = check_pow_nocheck;
+}
+
 /* PowerPC 403 GCX                                                           */
 #define POWERPC_INSNS_403GCX (PPC_INSNS_BASE | PPC_STRING |                   \
                               PPC_DCR | PPC_WRTEE |                           \
@@ -3451,7 +3507,6 @@ static void init_proc_403 (CPUPPCState *env)
 #define POWERPC_BFDM_403GCX  (bfd_mach_ppc_403)
 #define POWERPC_FLAG_403GCX  (POWERPC_FLAG_CE | POWERPC_FLAG_PX |             \
                               POWERPC_FLAG_BUS_CLK)
-#define check_pow_403GCX     check_pow_nocheck
 
 static void init_proc_403GCX (CPUPPCState *env)
 {
@@ -3488,6 +3543,14 @@ static void init_proc_403GCX (CPUPPCState *env)
     SET_WDT_PERIOD(16, 20, 24, 28);
 }
 
+POWERPC_FAMILY(403GCX)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_403GCX;
+    pcc->check_pow = check_pow_nocheck;
+}
+
 /* PowerPC 405                                                               */
 #define POWERPC_INSNS_405    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_DCR | PPC_WRTEE |                           \
@@ -3504,7 +3567,6 @@ static void init_proc_403GCX (CPUPPCState *env)
 #define POWERPC_BFDM_405     (bfd_mach_ppc_403)
 #define POWERPC_FLAG_405     (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
                               POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK)
-#define check_pow_405        check_pow_nocheck
 
 static void init_proc_405 (CPUPPCState *env)
 {
@@ -3540,6 +3602,14 @@ static void init_proc_405 (CPUPPCState *env)
     SET_WDT_PERIOD(16, 20, 24, 28);
 }
 
+POWERPC_FAMILY(405)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_405;
+    pcc->check_pow = check_pow_nocheck;
+}
+
 /* PowerPC 440 EP                                                            */
 #define POWERPC_INSNS_440EP  (PPC_INSNS_BASE | PPC_STRING |                   \
                               PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |   \
@@ -3559,7 +3629,6 @@ static void init_proc_405 (CPUPPCState *env)
 #define POWERPC_BFDM_440EP   (bfd_mach_ppc_403)
 #define POWERPC_FLAG_440EP   (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
                               POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK)
-#define check_pow_440EP      check_pow_nocheck
 
 static void init_proc_440EP (CPUPPCState *env)
 {
@@ -3627,6 +3696,14 @@ static void init_proc_440EP (CPUPPCState *env)
     SET_WDT_PERIOD(20, 24, 28, 32);
 }
 
+POWERPC_FAMILY(440EP)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_440EP;
+    pcc->check_pow = check_pow_nocheck;
+}
+
 /* PowerPC 440 GP                                                            */
 #define POWERPC_INSNS_440GP  (PPC_INSNS_BASE | PPC_STRING |                   \
                               PPC_DCR | PPC_DCRX | PPC_WRTEE | PPC_MFAPIDI |  \
@@ -3643,9 +3720,7 @@ static void init_proc_440EP (CPUPPCState *env)
 #define POWERPC_BFDM_440GP   (bfd_mach_ppc_403)
 #define POWERPC_FLAG_440GP   (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
                               POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK)
-#define check_pow_440GP      check_pow_nocheck
 
-__attribute__ (( unused ))
 static void init_proc_440GP (CPUPPCState *env)
 {
     /* Time base */
@@ -3694,6 +3769,14 @@ static void init_proc_440GP (CPUPPCState *env)
     SET_WDT_PERIOD(20, 24, 28, 32);
 }
 
+POWERPC_FAMILY(440GP)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_440GP;
+    pcc->check_pow = check_pow_nocheck;
+}
+
 /* PowerPC 440x4                                                             */
 #define POWERPC_INSNS_440x4  (PPC_INSNS_BASE | PPC_STRING |                   \
                               PPC_DCR | PPC_WRTEE |                           \
@@ -3710,9 +3793,7 @@ static void init_proc_440GP (CPUPPCState *env)
 #define POWERPC_BFDM_440x4   (bfd_mach_ppc_403)
 #define POWERPC_FLAG_440x4   (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
                               POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK)
-#define check_pow_440x4      check_pow_nocheck
 
-__attribute__ (( unused ))
 static void init_proc_440x4 (CPUPPCState *env)
 {
     /* Time base */
@@ -3761,6 +3842,14 @@ static void init_proc_440x4 (CPUPPCState *env)
     SET_WDT_PERIOD(20, 24, 28, 32);
 }
 
+POWERPC_FAMILY(440x4)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_440x4;
+    pcc->check_pow = check_pow_nocheck;
+}
+
 /* PowerPC 440x5                                                             */
 #define POWERPC_INSNS_440x5  (PPC_INSNS_BASE | PPC_STRING |                   \
                               PPC_DCR | PPC_WRTEE | PPC_RFMCI |               \
@@ -3777,7 +3866,6 @@ static void init_proc_440x4 (CPUPPCState *env)
 #define POWERPC_BFDM_440x5   (bfd_mach_ppc_403)
 #define POWERPC_FLAG_440x5   (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |           \
                               POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK)
-#define check_pow_440x5      check_pow_nocheck
 
 static void init_proc_440x5 (CPUPPCState *env)
 {
@@ -3845,6 +3933,14 @@ static void init_proc_440x5 (CPUPPCState *env)
     SET_WDT_PERIOD(20, 24, 28, 32);
 }
 
+POWERPC_FAMILY(440x5)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_440x5;
+    pcc->check_pow = check_pow_nocheck;
+}
+
 /* PowerPC 460 (guessed)                                                     */
 #define POWERPC_INSNS_460    (PPC_INSNS_BASE | PPC_STRING |                   \
                               PPC_DCR | PPC_DCRX  | PPC_DCRUX |               \
@@ -3862,9 +3958,7 @@ static void init_proc_440x5 (CPUPPCState *env)
 #define POWERPC_BFDM_460     (bfd_mach_ppc_403)
 #define POWERPC_FLAG_460     (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
                               POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK)
-#define check_pow_460        check_pow_nocheck
 
-__attribute__ (( unused ))
 static void init_proc_460 (CPUPPCState *env)
 {
     /* Time base */
@@ -3936,6 +4030,14 @@ static void init_proc_460 (CPUPPCState *env)
     SET_WDT_PERIOD(20, 24, 28, 32);
 }
 
+POWERPC_FAMILY(460)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_460;
+    pcc->check_pow = check_pow_nocheck;
+}
+
 /* PowerPC 460F (guessed)                                                    */
 #define POWERPC_INSNS_460F   (PPC_INSNS_BASE | PPC_STRING |                   \
                               PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL |   \
@@ -3956,9 +4058,7 @@ static void init_proc_460 (CPUPPCState *env)
 #define POWERPC_BFDM_460F    (bfd_mach_ppc_403)
 #define POWERPC_FLAG_460F    (POWERPC_FLAG_CE | POWERPC_FLAG_DWE |            \
                               POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK)
-#define check_pow_460F       check_pow_nocheck
 
-__attribute__ (( unused ))
 static void init_proc_460F (CPUPPCState *env)
 {
     /* Time base */
@@ -4030,6 +4130,14 @@ static void init_proc_460F (CPUPPCState *env)
     SET_WDT_PERIOD(20, 24, 28, 32);
 }
 
+POWERPC_FAMILY(460F)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_460F;
+    pcc->check_pow = check_pow_nocheck;
+}
+
 /* Freescale 5xx cores (aka RCPU) */
 #define POWERPC_INSNS_MPC5xx (PPC_INSNS_BASE | PPC_STRING |                   \
                               PPC_MEM_EIEIO | PPC_MEM_SYNC |                  \
@@ -4043,9 +4151,7 @@ static void init_proc_460F (CPUPPCState *env)
 #define POWERPC_BFDM_MPC5xx  (bfd_mach_ppc_505)
 #define POWERPC_FLAG_MPC5xx  (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
                               POWERPC_FLAG_BUS_CLK)
-#define check_pow_MPC5xx     check_pow_none
 
-__attribute__ (( unused ))
 static void init_proc_MPC5xx (CPUPPCState *env)
 {
     /* Time base */
@@ -4058,6 +4164,14 @@ static void init_proc_MPC5xx (CPUPPCState *env)
     /* XXX: TODO: allocate internal IRQ controller */
 }
 
+POWERPC_FAMILY(MPC5xx)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_MPC5xx;
+    pcc->check_pow = check_pow_none;
+}
+
 /* Freescale 8xx cores (aka PowerQUICC) */
 #define POWERPC_INSNS_MPC8xx (PPC_INSNS_BASE | PPC_STRING  |                  \
                               PPC_MEM_EIEIO | PPC_MEM_SYNC |                  \
@@ -4070,9 +4184,7 @@ static void init_proc_MPC5xx (CPUPPCState *env)
 #define POWERPC_BFDM_MPC8xx  (bfd_mach_ppc_860)
 #define POWERPC_FLAG_MPC8xx  (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
                               POWERPC_FLAG_BUS_CLK)
-#define check_pow_MPC8xx     check_pow_none
 
-__attribute__ (( unused ))
 static void init_proc_MPC8xx (CPUPPCState *env)
 {
     /* Time base */
@@ -4085,6 +4197,14 @@ static void init_proc_MPC8xx (CPUPPCState *env)
     /* XXX: TODO: allocate internal IRQ controller */
 }
 
+POWERPC_FAMILY(MPC8xx)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_MPC8xx;
+    pcc->check_pow = check_pow_none;
+}
+
 /* Freescale 82xx cores (aka PowerQUICC-II)                                  */
 /* PowerPC G2                                                                */
 #define POWERPC_INSNS_G2     (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
@@ -4102,7 +4222,6 @@ static void init_proc_MPC8xx (CPUPPCState *env)
 #define POWERPC_BFDM_G2      (bfd_mach_ppc_ec603e)
 #define POWERPC_FLAG_G2      (POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |           \
                               POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK)
-#define check_pow_G2         check_pow_hid0
 
 static void init_proc_G2 (CPUPPCState *env)
 {
@@ -4144,6 +4263,14 @@ static void init_proc_G2 (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(G2)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_G2;
+    pcc->check_pow = check_pow_hid0;
+}
+
 /* PowerPC G2LE                                                              */
 #define POWERPC_INSNS_G2LE   (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -4160,7 +4287,6 @@ static void init_proc_G2 (CPUPPCState *env)
 #define POWERPC_BFDM_G2LE    (bfd_mach_ppc_ec603e)
 #define POWERPC_FLAG_G2LE    (POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |           \
                               POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK)
-#define check_pow_G2LE       check_pow_hid0
 
 static void init_proc_G2LE (CPUPPCState *env)
 {
@@ -4202,6 +4328,14 @@ static void init_proc_G2LE (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(G2LE)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_G2LE;
+    pcc->check_pow = check_pow_hid0;
+}
+
 /* e200 core                                                                 */
 /* XXX: unimplemented instructions:
  * dcblc
@@ -4228,9 +4362,7 @@ static void init_proc_G2LE (CPUPPCState *env)
 #define POWERPC_FLAG_e200    (POWERPC_FLAG_SPE | POWERPC_FLAG_CE |            \
                               POWERPC_FLAG_UBLE | POWERPC_FLAG_DE |           \
                               POWERPC_FLAG_BUS_CLK)
-#define check_pow_e200       check_pow_hid0
 
-__attribute__ (( unused ))
 static void init_proc_e200 (CPUPPCState *env)
 {
     /* Time base */
@@ -4338,6 +4470,14 @@ static void init_proc_e200 (CPUPPCState *env)
     /* XXX: TODO: allocate internal IRQ controller */
 }
 
+POWERPC_FAMILY(e200)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_e200;
+    pcc->check_pow = check_pow_hid0;
+}
+
 /* e300 core                                                                 */
 #define POWERPC_INSNS_e300   (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -4354,9 +4494,7 @@ static void init_proc_e200 (CPUPPCState *env)
 #define POWERPC_BFDM_e300    (bfd_mach_ppc_603)
 #define POWERPC_FLAG_e300    (POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |           \
                               POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK)
-#define check_pow_e300       check_pow_hid0
 
-__attribute__ (( unused ))
 static void init_proc_e300 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -4390,6 +4528,14 @@ static void init_proc_e300 (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(e300)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_e300;
+    pcc->check_pow = check_pow_hid0;
+}
+
 /* e500v1 core                                                               */
 #define POWERPC_INSNS_e500v1   (PPC_INSNS_BASE | PPC_ISEL |             \
                                 PPC_SPE | PPC_SPE_SINGLE |              \
@@ -4406,8 +4552,6 @@ static void init_proc_e300 (CPUPPCState *env)
 #define POWERPC_FLAG_e500v1    (POWERPC_FLAG_SPE | POWERPC_FLAG_CE |    \
                                 POWERPC_FLAG_UBLE | POWERPC_FLAG_DE |   \
                                 POWERPC_FLAG_BUS_CLK)
-#define check_pow_e500v1       check_pow_hid0
-#define init_proc_e500v1       init_proc_e500v1
 
 /* e500v2 core                                                               */
 #define POWERPC_INSNS_e500v2   (PPC_INSNS_BASE | PPC_ISEL |             \
@@ -4425,8 +4569,6 @@ static void init_proc_e300 (CPUPPCState *env)
 #define POWERPC_FLAG_e500v2    (POWERPC_FLAG_SPE | POWERPC_FLAG_CE |    \
                                 POWERPC_FLAG_UBLE | POWERPC_FLAG_DE |   \
                                 POWERPC_FLAG_BUS_CLK)
-#define check_pow_e500v2       check_pow_hid0
-#define init_proc_e500v2       init_proc_e500v2
 
 /* e500mc core                                                               */
 #define POWERPC_INSNS_e500mc   (PPC_INSNS_BASE | PPC_ISEL |                 \
@@ -4446,8 +4588,6 @@ static void init_proc_e300 (CPUPPCState *env)
 #define POWERPC_BFDM_e500mc    (bfd_mach_ppc_e500)
 #define POWERPC_FLAG_e500mc    (POWERPC_FLAG_CE | POWERPC_FLAG_DE | \
                                 POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-#define check_pow_e500mc       check_pow_none
-#define init_proc_e500mc       init_proc_e500mc
 
 /* e5500 core                                                                 */
 #define POWERPC_INSNS_e5500    (PPC_INSNS_BASE | PPC_ISEL |                    \
@@ -4468,8 +4608,6 @@ static void init_proc_e300 (CPUPPCState *env)
 #define POWERPC_BFDM_e5500     (bfd_mach_ppc_e500)
 #define POWERPC_FLAG_e5500     (POWERPC_FLAG_CE | POWERPC_FLAG_DE | \
                                 POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-#define check_pow_e5500        check_pow_none
-#define init_proc_e5500        init_proc_e5500
 
 #if !defined(CONFIG_USER_ONLY)
 static void spr_write_mas73(void *opaque, int sprn, int gprn)
@@ -4685,21 +4823,53 @@ static void init_proc_e500v1(CPUPPCState *env)
     init_proc_e500(env, fsl_e500v1);
 }
 
+POWERPC_FAMILY(e500v1)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_e500v1;
+    pcc->check_pow = check_pow_hid0;
+}
+
 static void init_proc_e500v2(CPUPPCState *env)
 {
     init_proc_e500(env, fsl_e500v2);
 }
 
+POWERPC_FAMILY(e500v2)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_e500v2;
+    pcc->check_pow = check_pow_hid0;
+}
+
 static void init_proc_e500mc(CPUPPCState *env)
 {
     init_proc_e500(env, fsl_e500mc);
 }
 
+POWERPC_FAMILY(e500mc)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_e500mc;
+    pcc->check_pow = check_pow_none;
+}
+
 #ifdef TARGET_PPC64
 static void init_proc_e5500(CPUPPCState *env)
 {
     init_proc_e500(env, fsl_e5500);
 }
+
+POWERPC_FAMILY(e5500)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_e5500;
+    pcc->check_pow = check_pow_none;
+}
 #endif
 
 /* Non-embedded PowerPC                                                      */
@@ -4725,7 +4895,6 @@ static void init_proc_e5500(CPUPPCState *env)
 #define POWERPC_INPUT_601    (PPC_FLAGS_INPUT_6xx)
 #define POWERPC_BFDM_601     (bfd_mach_ppc_601)
 #define POWERPC_FLAG_601     (POWERPC_FLAG_SE | POWERPC_FLAG_RTC_CLK)
-#define check_pow_601        check_pow_none
 
 static void init_proc_601 (CPUPPCState *env)
 {
@@ -4764,6 +4933,14 @@ static void init_proc_601 (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(601)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_601;
+    pcc->check_pow = check_pow_none;
+}
+
 /* PowerPC 601v                                                              */
 #define POWERPC_INSNS_601v   (PPC_INSNS_BASE | PPC_STRING | PPC_POWER_BR |    \
                               PPC_FLOAT |                                     \
@@ -4778,7 +4955,6 @@ static void init_proc_601 (CPUPPCState *env)
 #define POWERPC_INPUT_601v   (PPC_FLAGS_INPUT_6xx)
 #define POWERPC_BFDM_601v    (bfd_mach_ppc_601)
 #define POWERPC_FLAG_601v    (POWERPC_FLAG_SE | POWERPC_FLAG_RTC_CLK)
-#define check_pow_601v       check_pow_none
 
 static void init_proc_601v (CPUPPCState *env)
 {
@@ -4790,6 +4966,14 @@ static void init_proc_601v (CPUPPCState *env)
                  0x00000000);
 }
 
+POWERPC_FAMILY(601v)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_601v;
+    pcc->check_pow = check_pow_none;
+}
+
 /* PowerPC 602                                                               */
 #define POWERPC_INSNS_602    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -4807,7 +4991,6 @@ static void init_proc_601v (CPUPPCState *env)
 #define POWERPC_BFDM_602     (bfd_mach_ppc_602)
 #define POWERPC_FLAG_602     (POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |           \
                               POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK)
-#define check_pow_602        check_pow_hid0
 
 static void init_proc_602 (CPUPPCState *env)
 {
@@ -4836,6 +5019,14 @@ static void init_proc_602 (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(602)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_602;
+    pcc->check_pow = check_pow_hid0;
+}
+
 /* PowerPC 603                                                               */
 #define POWERPC_INSNS_603    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -4852,7 +5043,6 @@ static void init_proc_602 (CPUPPCState *env)
 #define POWERPC_BFDM_603     (bfd_mach_ppc_603)
 #define POWERPC_FLAG_603     (POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |           \
                               POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK)
-#define check_pow_603        check_pow_hid0
 
 static void init_proc_603 (CPUPPCState *env)
 {
@@ -4881,6 +5071,14 @@ static void init_proc_603 (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(603)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_603;
+    pcc->check_pow = check_pow_hid0;
+}
+
 /* PowerPC 603e                                                              */
 #define POWERPC_INSNS_603E   (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -4897,7 +5095,6 @@ static void init_proc_603 (CPUPPCState *env)
 #define POWERPC_BFDM_603E    (bfd_mach_ppc_ec603e)
 #define POWERPC_FLAG_603E    (POWERPC_FLAG_TGPR | POWERPC_FLAG_SE |           \
                               POWERPC_FLAG_BE | POWERPC_FLAG_BUS_CLK)
-#define check_pow_603E       check_pow_hid0
 
 static void init_proc_603E (CPUPPCState *env)
 {
@@ -4931,6 +5128,14 @@ static void init_proc_603E (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(603E)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_603E;
+    pcc->check_pow = check_pow_hid0;
+}
+
 /* PowerPC 604                                                               */
 #define POWERPC_INSNS_604    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -4947,7 +5152,6 @@ static void init_proc_603E (CPUPPCState *env)
 #define POWERPC_BFDM_604     (bfd_mach_ppc_604)
 #define POWERPC_FLAG_604     (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
                               POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-#define check_pow_604        check_pow_nocheck
 
 static void init_proc_604 (CPUPPCState *env)
 {
@@ -4970,6 +5174,14 @@ static void init_proc_604 (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(604)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_604;
+    pcc->check_pow = check_pow_nocheck;
+}
+
 /* PowerPC 604E                                                              */
 #define POWERPC_INSNS_604E   (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -4986,7 +5198,6 @@ static void init_proc_604 (CPUPPCState *env)
 #define POWERPC_BFDM_604E    (bfd_mach_ppc_604)
 #define POWERPC_FLAG_604E    (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
                               POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-#define check_pow_604E       check_pow_nocheck
 
 static void init_proc_604E (CPUPPCState *env)
 {
@@ -5029,6 +5240,14 @@ static void init_proc_604E (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(604E)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_604E;
+    pcc->check_pow = check_pow_nocheck;
+}
+
 /* PowerPC 740                                                               */
 #define POWERPC_INSNS_740    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -5045,7 +5264,6 @@ static void init_proc_604E (CPUPPCState *env)
 #define POWERPC_BFDM_740     (bfd_mach_ppc_750)
 #define POWERPC_FLAG_740     (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
                               POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-#define check_pow_740        check_pow_hid0
 
 static void init_proc_740 (CPUPPCState *env)
 {
@@ -5075,6 +5293,14 @@ static void init_proc_740 (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(740)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_740;
+    pcc->check_pow = check_pow_hid0;
+}
+
 /* PowerPC 750                                                               */
 #define POWERPC_INSNS_750    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -5091,7 +5317,6 @@ static void init_proc_740 (CPUPPCState *env)
 #define POWERPC_BFDM_750     (bfd_mach_ppc_750)
 #define POWERPC_FLAG_750     (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
                               POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-#define check_pow_750        check_pow_hid0
 
 static void init_proc_750 (CPUPPCState *env)
 {
@@ -5129,6 +5354,14 @@ static void init_proc_750 (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(750)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_750;
+    pcc->check_pow = check_pow_hid0;
+}
+
 /* PowerPC 750 CL                                                            */
 /* XXX: not implemented:
  * cache lock instructions:
@@ -5183,7 +5416,6 @@ static void init_proc_750 (CPUPPCState *env)
 #define POWERPC_BFDM_750cl   (bfd_mach_ppc_750)
 #define POWERPC_FLAG_750cl   (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
                               POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-#define check_pow_750cl      check_pow_hid0
 
 static void init_proc_750cl (CPUPPCState *env)
 {
@@ -5306,6 +5538,14 @@ static void init_proc_750cl (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_750cl;
+    pcc->check_pow = check_pow_hid0;
+}
+
 /* PowerPC 750CX                                                             */
 #define POWERPC_INSNS_750cx  (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -5322,7 +5562,6 @@ static void init_proc_750cl (CPUPPCState *env)
 #define POWERPC_BFDM_750cx   (bfd_mach_ppc_750)
 #define POWERPC_FLAG_750cx   (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
                               POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-#define check_pow_750cx      check_pow_hid0
 
 static void init_proc_750cx (CPUPPCState *env)
 {
@@ -5364,6 +5603,14 @@ static void init_proc_750cx (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(750cx)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_750cx;
+    pcc->check_pow = check_pow_hid0;
+}
+
 /* PowerPC 750FX                                                             */
 #define POWERPC_INSNS_750fx  (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -5380,7 +5627,6 @@ static void init_proc_750cx (CPUPPCState *env)
 #define POWERPC_BFDM_750fx   (bfd_mach_ppc_750)
 #define POWERPC_FLAG_750fx   (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
                               POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-#define check_pow_750fx      check_pow_hid0
 
 static void init_proc_750fx (CPUPPCState *env)
 {
@@ -5427,6 +5673,14 @@ static void init_proc_750fx (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(750fx)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_750fx;
+    pcc->check_pow = check_pow_hid0;
+}
+
 /* PowerPC 750GX                                                             */
 #define POWERPC_INSNS_750gx  (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -5443,7 +5697,6 @@ static void init_proc_750fx (CPUPPCState *env)
 #define POWERPC_BFDM_750gx   (bfd_mach_ppc_750)
 #define POWERPC_FLAG_750gx   (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
                               POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-#define check_pow_750gx      check_pow_hid0
 
 static void init_proc_750gx (CPUPPCState *env)
 {
@@ -5490,6 +5743,14 @@ static void init_proc_750gx (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(750gx)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_750gx;
+    pcc->check_pow = check_pow_hid0;
+}
+
 /* PowerPC 745                                                               */
 #define POWERPC_INSNS_745    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -5506,7 +5767,6 @@ static void init_proc_750gx (CPUPPCState *env)
 #define POWERPC_BFDM_745     (bfd_mach_ppc_750)
 #define POWERPC_FLAG_745     (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
                               POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-#define check_pow_745        check_pow_hid0
 
 static void init_proc_745 (CPUPPCState *env)
 {
@@ -5544,6 +5804,14 @@ static void init_proc_745 (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(745)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_745;
+    pcc->check_pow = check_pow_hid0;
+}
+
 /* PowerPC 755                                                               */
 #define POWERPC_INSNS_755    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -5560,7 +5828,6 @@ static void init_proc_745 (CPUPPCState *env)
 #define POWERPC_BFDM_755     (bfd_mach_ppc_750)
 #define POWERPC_FLAG_755     (POWERPC_FLAG_SE | POWERPC_FLAG_BE |             \
                               POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-#define check_pow_755        check_pow_hid0
 
 static void init_proc_755 (CPUPPCState *env)
 {
@@ -5609,6 +5876,14 @@ static void init_proc_755 (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(755)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_755;
+    pcc->check_pow = check_pow_hid0;
+}
+
 /* PowerPC 7400 (aka G4)                                                     */
 #define POWERPC_INSNS_7400   (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -5630,7 +5905,6 @@ static void init_proc_755 (CPUPPCState *env)
 #define POWERPC_FLAG_7400    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
                               POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
                               POWERPC_FLAG_BUS_CLK)
-#define check_pow_7400       check_pow_hid0
 
 static void init_proc_7400 (CPUPPCState *env)
 {
@@ -5662,6 +5936,14 @@ static void init_proc_7400 (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(7400)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_7400;
+    pcc->check_pow = check_pow_hid0;
+}
+
 /* PowerPC 7410 (aka G4)                                                     */
 #define POWERPC_INSNS_7410   (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -5683,7 +5965,6 @@ static void init_proc_7400 (CPUPPCState *env)
 #define POWERPC_FLAG_7410    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
                               POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
                               POWERPC_FLAG_BUS_CLK)
-#define check_pow_7410       check_pow_hid0
 
 static void init_proc_7410 (CPUPPCState *env)
 {
@@ -5721,6 +6002,14 @@ static void init_proc_7410 (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(7410)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_7410;
+    pcc->check_pow = check_pow_hid0;
+}
+
 /* PowerPC 7440 (aka G4)                                                     */
 #define POWERPC_INSNS_7440   (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -5742,9 +6031,7 @@ static void init_proc_7410 (CPUPPCState *env)
 #define POWERPC_FLAG_7440    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
                               POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
                               POWERPC_FLAG_BUS_CLK)
-#define check_pow_7440       check_pow_hid0_74xx
 
-__attribute__ (( unused ))
 static void init_proc_7440 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5807,6 +6094,14 @@ static void init_proc_7440 (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(7440)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_7440;
+    pcc->check_pow = check_pow_hid0_74xx;
+}
+
 /* PowerPC 7450 (aka G4)                                                     */
 #define POWERPC_INSNS_7450   (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -5828,9 +6123,7 @@ static void init_proc_7440 (CPUPPCState *env)
 #define POWERPC_FLAG_7450    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
                               POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
                               POWERPC_FLAG_BUS_CLK)
-#define check_pow_7450       check_pow_hid0_74xx
 
-__attribute__ (( unused ))
 static void init_proc_7450 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -5919,6 +6212,14 @@ static void init_proc_7450 (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(7450)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_7450;
+    pcc->check_pow = check_pow_hid0_74xx;
+}
+
 /* PowerPC 7445 (aka G4)                                                     */
 #define POWERPC_INSNS_7445   (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -5940,9 +6241,7 @@ static void init_proc_7450 (CPUPPCState *env)
 #define POWERPC_FLAG_7445    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
                               POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
                               POWERPC_FLAG_BUS_CLK)
-#define check_pow_7445       check_pow_hid0_74xx
 
-__attribute__ (( unused ))
 static void init_proc_7445 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -6034,6 +6333,14 @@ static void init_proc_7445 (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(7445)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_7445;
+    pcc->check_pow = check_pow_hid0_74xx;
+}
+
 /* PowerPC 7455 (aka G4)                                                     */
 #define POWERPC_INSNS_7455   (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -6055,9 +6362,7 @@ static void init_proc_7445 (CPUPPCState *env)
 #define POWERPC_FLAG_7455    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
                               POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
                               POWERPC_FLAG_BUS_CLK)
-#define check_pow_7455       check_pow_hid0_74xx
 
-__attribute__ (( unused ))
 static void init_proc_7455 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -6151,6 +6456,14 @@ static void init_proc_7455 (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(7455)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_7455;
+    pcc->check_pow = check_pow_hid0_74xx;
+}
+
 /* PowerPC 7457 (aka G4)                                                     */
 #define POWERPC_INSNS_7457   (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -6172,9 +6485,7 @@ static void init_proc_7455 (CPUPPCState *env)
 #define POWERPC_FLAG_7457    (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
                               POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
                               POWERPC_FLAG_BUS_CLK)
-#define check_pow_7457       check_pow_hid0_74xx
 
-__attribute__ (( unused ))
 static void init_proc_7457 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -6292,6 +6603,14 @@ static void init_proc_7457 (CPUPPCState *env)
     ppc6xx_irq_init(env);
 }
 
+POWERPC_FAMILY(7457)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_7457;
+    pcc->check_pow = check_pow_hid0_74xx;
+}
+
 #if defined (TARGET_PPC64)
 /* PowerPC 970                                                               */
 #define POWERPC_INSNS_970    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
@@ -6389,6 +6708,14 @@ static void init_proc_970 (CPUPPCState *env)
     vscr_init(env, 0x00010000);
 }
 
+POWERPC_FAMILY(970)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_970;
+    pcc->check_pow = check_pow_970;
+}
+
 /* PowerPC 970FX (aka G5)                                                    */
 #define POWERPC_INSNS_970FX  (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -6491,6 +6818,14 @@ static void init_proc_970FX (CPUPPCState *env)
     vscr_init(env, 0x00010000);
 }
 
+POWERPC_FAMILY(970FX)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_970FX;
+    pcc->check_pow = check_pow_970FX;
+}
+
 /* PowerPC 970 GX                                                            */
 #define POWERPC_INSNS_970GX  (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -6581,6 +6916,14 @@ static void init_proc_970GX (CPUPPCState *env)
     vscr_init(env, 0x00010000);
 }
 
+POWERPC_FAMILY(970GX)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_970GX;
+    pcc->check_pow = check_pow_970GX;
+}
+
 /* PowerPC 970 MP                                                            */
 #define POWERPC_INSNS_970MP  (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -6671,6 +7014,14 @@ static void init_proc_970MP (CPUPPCState *env)
     vscr_init(env, 0x00010000);
 }
 
+POWERPC_FAMILY(970MP)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_970MP;
+    pcc->check_pow = check_pow_970MP;
+}
+
 /* POWER7 */
 #define POWERPC_INSNS_POWER7  (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -6691,7 +7042,6 @@ static void init_proc_970MP (CPUPPCState *env)
 #define POWERPC_FLAG_POWER7   (POWERPC_FLAG_VRE | POWERPC_FLAG_SE |            \
                               POWERPC_FLAG_BE | POWERPC_FLAG_PMM |            \
                               POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR)
-#define check_pow_POWER7    check_pow_nocheck
 
 static void init_proc_POWER7 (CPUPPCState *env)
 {
@@ -6755,6 +7105,14 @@ static void init_proc_POWER7 (CPUPPCState *env)
     vscr_init(env, 0x00010000);
 }
 
+POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_POWER7;
+    pcc->check_pow = check_pow_nocheck;
+}
+
 /* PowerPC 620                                                               */
 #define POWERPC_INSNS_620    (PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |        \
                               PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |   \
@@ -6773,9 +7131,7 @@ static void init_proc_POWER7 (CPUPPCState *env)
 #define POWERPC_BFDM_620     (bfd_mach_ppc64)
 #define POWERPC_FLAG_620     (POWERPC_FLAG_SE | POWERPC_FLAG_BE |            \
                               POWERPC_FLAG_PMM | POWERPC_FLAG_BUS_CLK)
-#define check_pow_620        check_pow_nocheck /* Check this */
 
-__attribute__ (( unused ))
 static void init_proc_620 (CPUPPCState *env)
 {
     gen_spr_ne_601(env);
@@ -6796,6 +7152,15 @@ static void init_proc_620 (CPUPPCState *env)
     /* Allocate hardware IRQ controller */
     ppc6xx_irq_init(env);
 }
+
+POWERPC_FAMILY(620)(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    pcc->init_proc = init_proc_620;
+    pcc->check_pow = check_pow_nocheck; /* Check this */
+}
+
 #endif /* defined (TARGET_PPC64) */
 
 /*****************************************************************************/
@@ -7530,14 +7895,12 @@ enum {
         pcc->bus_model    = glue(POWERPC_INPUT_, _type);                    \
         pcc->bfd_mach     = glue(POWERPC_BFDM_, _type);                     \
         pcc->flags        = glue(POWERPC_FLAG_, _type);                     \
-        pcc->init_proc    = &glue(init_proc_, _type);                       \
-        pcc->check_pow    = &glue(check_pow_, _type);                       \
     }                                                                       \
                                                                             \
     static const TypeInfo                                                   \
     glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_type_info) = {         \
         .name       = _name "-" TYPE_POWERPC_CPU,                           \
-        .parent     = TYPE_POWERPC_CPU,                                     \
+        .parent     = stringify(_type) "-family-" TYPE_POWERPC_CPU,         \
         .class_init =                                                       \
             glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_class_init),   \
     };                                                                      \
commit cfe34f44b3a13ed32891e0b3c84be91d3d91a4b8
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:41 2013 +0000

    target-ppc: Convert CPU definitions
    
    Turn the array of model definitions into a set of self-registering QOM
    types with their own class_init. Unique identifiers are obtained from
    the combination of PVR, SVR and family identifiers; this requires all
    alias #defines to be removed from the list. Possibly there are some more
    left after this commit that are not currently being compiled.
    
    Prepares for introducing abstract intermediate CPU types for families.
    
    Keep the right-aligned macro line breaks within 78 chars to aid
    three-way merges.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index 4e8ceca..2bf0ab6 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -53,8 +53,21 @@ typedef struct PowerPCCPUClass {
     DeviceRealize parent_realize;
     void (*parent_reset)(CPUState *cpu);
 
-    /* TODO inline fields here */
-    ppc_def_t *info;
+    uint32_t pvr;
+    uint32_t svr;
+    uint64_t insns_flags;
+    uint64_t insns_flags2;
+    uint64_t msr_mask;
+    powerpc_mmu_t   mmu_model;
+    powerpc_excp_t  excp_model;
+    powerpc_input_t bus_model;
+    uint32_t flags;
+    int bfd_mach;
+#if defined(TARGET_PPC64)
+    const struct ppc_segment_page_sizes *sps;
+#endif
+    void (*init_proc)(CPUPPCState *env);
+    int  (*check_pow)(CPUPPCState *env);
 } PowerPCCPUClass;
 
 /**
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 20f4565..e4cf96c 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -307,7 +307,6 @@ enum powerpc_input_t {
 #define PPC_INPUT(env) (env->bus_model)
 
 /*****************************************************************************/
-typedef struct ppc_def_t ppc_def_t;
 typedef struct opc_handler_t opc_handler_t;
 
 /*****************************************************************************/
@@ -902,25 +901,6 @@ struct ppc_segment_page_sizes {
 /* The whole PowerPC CPU context */
 #define NB_MMU_MODES 3
 
-struct ppc_def_t {
-    const char *name;
-    uint32_t pvr;
-    uint32_t svr;
-    uint64_t insns_flags;
-    uint64_t insns_flags2;
-    uint64_t msr_mask;
-    powerpc_mmu_t   mmu_model;
-    powerpc_excp_t  excp_model;
-    powerpc_input_t bus_model;
-    uint32_t flags;
-    int bfd_mach;
-#if defined(TARGET_PPC64)
-    const struct ppc_segment_page_sizes *sps;
-#endif
-    void (*init_proc)(CPUPPCState *env);
-    int  (*check_pow)(CPUPPCState *env);
-};
-
 struct CPUPPCState {
     /* First are the most commonly used resources
      * during translated code execution
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 8e64416..a89c3cf 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1263,7 +1263,7 @@ static void kvmppc_host_cpu_initfn(Object *obj)
 
     assert(kvm_enabled());
 
-    if (pcc->info->pvr != mfpvr()) {
+    if (pcc->pvr != mfpvr()) {
         fprintf(stderr, "Your host CPU is unsupported.\n"
                 "Please choose a supported model instead, see -cpu ?.\n");
         exit(1);
@@ -1275,30 +1275,38 @@ static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
     uint32_t host_pvr = mfpvr();
     PowerPCCPUClass *pvr_pcc;
-    ppc_def_t *spec;
     uint32_t vmx = kvmppc_get_vmx();
     uint32_t dfp = kvmppc_get_dfp();
 
-    spec = g_malloc0(sizeof(*spec));
-
     pvr_pcc = ppc_cpu_class_by_pvr(host_pvr);
     if (pvr_pcc != NULL) {
-        memcpy(spec, pvr_pcc->info, sizeof(*spec));
+        pcc->pvr          = pvr_pcc->pvr;
+        pcc->svr          = pvr_pcc->svr;
+        pcc->insns_flags  = pvr_pcc->insns_flags;
+        pcc->insns_flags2 = pvr_pcc->insns_flags2;
+        pcc->msr_mask     = pvr_pcc->msr_mask;
+        pcc->mmu_model    = pvr_pcc->mmu_model;
+        pcc->excp_model   = pvr_pcc->excp_model;
+        pcc->bus_model    = pvr_pcc->bus_model;
+        pcc->flags        = pvr_pcc->flags;
+        pcc->bfd_mach     = pvr_pcc->bfd_mach;
+#ifdef TARGET_PPC64
+        pcc->sps          = pvr_pcc->sps;
+#endif
+        pcc->init_proc    = pvr_pcc->init_proc;
+        pcc->check_pow    = pvr_pcc->check_pow;
     }
-    pcc->info = spec;
-    /* Override the display name for -cpu ? and QMP */
-    pcc->info->name = "host";
 
-    /* Now fix up the spec with information we can query from the host */
+    /* Now fix up the class with information we can query from the host */
 
     if (vmx != -1) {
         /* Only override when we know what the host supports */
-        alter_insns(&spec->insns_flags, PPC_ALTIVEC, vmx > 0);
-        alter_insns(&spec->insns_flags2, PPC2_VSX, vmx > 1);
+        alter_insns(&pcc->insns_flags, PPC_ALTIVEC, vmx > 0);
+        alter_insns(&pcc->insns_flags2, PPC2_VSX, vmx > 1);
     }
     if (dfp != -1) {
         /* Only override when we know what the host supports */
-        alter_insns(&spec->insns_flags2, PPC2_DFP, dfp);
+        alter_insns(&pcc->insns_flags2, PPC2_DFP, dfp);
     }
 }
 
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 7eb565d..f707197 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7503,26 +7503,59 @@ enum {
 
 /*****************************************************************************/
 /* PowerPC CPU definitions                                                   */
+#define POWERPC_DEF_PREFIX(pvr, svr, type)                                  \
+    glue(glue(glue(glue(pvr, _), svr), _), type)
+#if defined(TARGET_PPCEMB)
+#define POWERPC_DEF_CONDITION(type)                                         \
+    if (glue(POWERPC_MMU_, type) != POWERPC_MMU_BOOKE) {                    \
+        return;                                                             \
+    }
+#else
+#define POWERPC_DEF_CONDITION(type)
+#endif
 #define POWERPC_DEF_SVR(_name, _pvr, _svr, _type)                             \
-    {                                                                         \
-        .name         = _name,                                                \
-        .pvr          = _pvr,                                                 \
-        .svr          = _svr,                                                 \
-        .insns_flags  = glue(POWERPC_INSNS_,_type),                           \
-        .insns_flags2 = glue(POWERPC_INSNS2_,_type),                          \
-        .msr_mask     = glue(POWERPC_MSRM_,_type),                            \
-        .mmu_model    = glue(POWERPC_MMU_,_type),                             \
-        .excp_model   = glue(POWERPC_EXCP_,_type),                            \
-        .bus_model    = glue(POWERPC_INPUT_,_type),                           \
-        .bfd_mach     = glue(POWERPC_BFDM_,_type),                            \
-        .flags        = glue(POWERPC_FLAG_,_type),                            \
-        .init_proc    = &glue(init_proc_,_type),                              \
-        .check_pow    = &glue(check_pow_,_type),                              \
-    },
+    static void                                                             \
+    glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_class_init)            \
+    (ObjectClass *oc, void *data)                                           \
+    {                                                                       \
+        PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);                       \
+                                                                            \
+        pcc->pvr          = _pvr;                                           \
+        pcc->svr          = _svr;                                           \
+        pcc->insns_flags  = glue(POWERPC_INSNS_, _type);                    \
+        pcc->insns_flags2 = glue(POWERPC_INSNS2_, _type);                   \
+        pcc->msr_mask     = glue(POWERPC_MSRM_, _type);                     \
+        pcc->mmu_model    = glue(POWERPC_MMU_, _type);                      \
+        pcc->excp_model   = glue(POWERPC_EXCP_, _type);                     \
+        pcc->bus_model    = glue(POWERPC_INPUT_, _type);                    \
+        pcc->bfd_mach     = glue(POWERPC_BFDM_, _type);                     \
+        pcc->flags        = glue(POWERPC_FLAG_, _type);                     \
+        pcc->init_proc    = &glue(init_proc_, _type);                       \
+        pcc->check_pow    = &glue(check_pow_, _type);                       \
+    }                                                                       \
+                                                                            \
+    static const TypeInfo                                                   \
+    glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_type_info) = {         \
+        .name       = _name "-" TYPE_POWERPC_CPU,                           \
+        .parent     = TYPE_POWERPC_CPU,                                     \
+        .class_init =                                                       \
+            glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_class_init),   \
+    };                                                                      \
+                                                                            \
+    static void                                                             \
+    glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_register_types)(void)  \
+    {                                                                       \
+        POWERPC_DEF_CONDITION(_type)                                        \
+        type_register_static(                                               \
+            &glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_type_info));  \
+    }                                                                       \
+                                                                            \
+    type_init(                                                              \
+        glue(POWERPC_DEF_PREFIX(_pvr, _svr, _type), _cpu_register_types))
+
 #define POWERPC_DEF(_name, _pvr, _type)                                       \
 POWERPC_DEF_SVR(_name, _pvr, POWERPC_SVR_NONE, _type)
 
-static const ppc_def_t ppc_defs[] = {
     /* Embedded PowerPC                                                      */
     /* PowerPC 401 family                                                    */
     /* Generic PowerPC 401 */
@@ -8782,7 +8815,6 @@ static const ppc_def_t ppc_defs[] = {
     /* PA PA6T */
     POWERPC_DEF("PA6T",          CPU_POWERPC_PA6T,                   PA6T)
 #endif
-};
 
 typedef struct PowerPCCPUAlias {
     const char *alias;
@@ -8981,8 +9013,10 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
 
 /*****************************************************************************/
 /* Generic CPU instantiation routine                                         */
-static void init_ppc_proc (CPUPPCState *env, const ppc_def_t *def)
+static void init_ppc_proc(PowerPCCPU *cpu)
 {
+    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+    CPUPPCState *env = &cpu->env;
 #if !defined(CONFIG_USER_ONLY)
     int i;
 
@@ -9010,23 +9044,23 @@ static void init_ppc_proc (CPUPPCState *env, const ppc_def_t *def)
 #endif
                  SPR_NOACCESS,
                  &spr_read_generic, SPR_NOACCESS,
-                 def->pvr);
+                 pcc->pvr);
     /* Register SVR if it's defined to anything else than POWERPC_SVR_NONE */
-    if (def->svr != POWERPC_SVR_NONE) {
-        if (def->svr & POWERPC_SVR_E500) {
+    if (pcc->svr != POWERPC_SVR_NONE) {
+        if (pcc->svr & POWERPC_SVR_E500) {
             spr_register(env, SPR_E500_SVR, "SVR",
                          SPR_NOACCESS, SPR_NOACCESS,
                          &spr_read_generic, SPR_NOACCESS,
-                         def->svr & ~POWERPC_SVR_E500);
+                         pcc->svr & ~POWERPC_SVR_E500);
         } else {
             spr_register(env, SPR_SVR, "SVR",
                          SPR_NOACCESS, SPR_NOACCESS,
                          &spr_read_generic, SPR_NOACCESS,
-                         def->svr);
+                         pcc->svr);
         }
     }
     /* PowerPC implementation specific initialisations (SPRs, timers, ...) */
-    (*def->init_proc)(env);
+    (*pcc->init_proc)(env);
 #if !defined(CONFIG_USER_ONLY)
     env->excp_prefix = env->hreset_excp_prefix;
 #endif
@@ -9377,13 +9411,12 @@ static void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp)
 {
     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
     CPUPPCState *env = &cpu->env;
-    const ppc_def_t *def = pcc->info;
     opcode_t *opc;
 
     fill_new_table(env->opcodes, 0x40);
     for (opc = opcodes; opc < &opcodes[ARRAY_SIZE(opcodes)]; opc++) {
-        if (((opc->handler.type & def->insns_flags) != 0) ||
-            ((opc->handler.type2 & def->insns_flags2) != 0)) {
+        if (((opc->handler.type & pcc->insns_flags) != 0) ||
+            ((opc->handler.type2 & pcc->insns_flags2) != 0)) {
             if (register_insn(env->opcodes, opc) < 0) {
                 error_setg(errp, "ERROR initializing PowerPC instruction "
                            "0x%02x 0x%02x 0x%02x", opc->opc1, opc->opc2,
@@ -9615,7 +9648,6 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp)
     PowerPCCPU *cpu = POWERPC_CPU(dev);
     CPUPPCState *env = &cpu->env;
     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
-    ppc_def_t *def = pcc->info;
     Error *local_err = NULL;
 #if !defined(CONFIG_USER_ONLY)
     int max_smt = kvm_enabled() ? kvmppc_smt_threads() : 1;
@@ -9646,17 +9678,17 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp)
         error_propagate(errp, local_err);
         return;
     }
-    init_ppc_proc(env, def);
+    init_ppc_proc(cpu);
 
-    if (def->insns_flags & PPC_FLOAT) {
+    if (pcc->insns_flags & PPC_FLOAT) {
         gdb_register_coprocessor(env, gdb_get_float_reg, gdb_set_float_reg,
                                  33, "power-fpu.xml", 0);
     }
-    if (def->insns_flags & PPC_ALTIVEC) {
+    if (pcc->insns_flags & PPC_ALTIVEC) {
         gdb_register_coprocessor(env, gdb_get_avr_reg, gdb_set_avr_reg,
                                  34, "power-altivec.xml", 0);
     }
-    if (def->insns_flags & PPC_SPE) {
+    if (pcc->insns_flags & PPC_SPE) {
         gdb_register_coprocessor(env, gdb_get_spe_reg, gdb_set_spe_reg,
                                  34, "power-spe.xml", 0);
     }
@@ -9782,7 +9814,7 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp)
         }
         printf("PowerPC %-12s : PVR %08x MSR %016" PRIx64 "\n"
                "    MMU model        : %s\n",
-               def->name, def->pvr, def->msr_mask, mmu_model);
+               pcc->name, pcc->pvr, pcc->msr_mask, mmu_model);
 #if !defined(CONFIG_USER_ONLY)
         if (env->tlb != NULL) {
             printf("                       %d %s TLB in %d ways\n",
@@ -9840,7 +9872,7 @@ static gint ppc_cpu_compare_class_pvr(gconstpointer a, gconstpointer b)
         return -1;
     }
 
-    return pcc->info->pvr == pvr ? 0 : -1;
+    return pcc->pvr == pvr ? 0 : -1;
 }
 
 PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr)
@@ -9964,9 +9996,9 @@ static gint ppc_cpu_list_compare(gconstpointer a, gconstpointer b)
         return -1;
     } else {
         /* Avoid an integer overflow during subtraction */
-        if (pcc_a->info->pvr < pcc_b->info->pvr) {
+        if (pcc_a->pvr < pcc_b->pvr) {
             return -1;
-        } else if (pcc_a->info->pvr > pcc_b->info->pvr) {
+        } else if (pcc_a->pvr > pcc_b->pvr) {
             return 1;
         } else {
             return 0;
@@ -9985,7 +10017,7 @@ static void ppc_cpu_list_entry(gpointer data, gpointer user_data)
     name = g_strndup(typename,
                      strlen(typename) - strlen("-" TYPE_POWERPC_CPU));
     (*s->cpu_fprintf)(s->file, "PowerPC %-16s PVR %08x\n",
-                      name, pcc->info->pvr);
+                      name, pcc->pvr);
     g_free(name);
 }
 
@@ -10046,27 +10078,6 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
     return cpu_list;
 }
 
-static void ppc_cpu_def_class_init(ObjectClass *oc, void *data)
-{
-    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
-    ppc_def_t *info = data;
-
-    pcc->info = info;
-}
-
-static void ppc_cpu_register_model(const ppc_def_t *def)
-{
-    TypeInfo type_info = {
-        .parent = TYPE_POWERPC_CPU,
-        .class_init = ppc_cpu_def_class_init,
-        .class_data = (void *)def,
-    };
-
-    type_info.name = g_strdup_printf("%s-" TYPE_POWERPC_CPU, def->name),
-    type_register(&type_info);
-    g_free((gpointer)type_info.name);
-}
-
 /* CPUClass::reset() */
 static void ppc_cpu_reset(CPUState *s)
 {
@@ -10138,24 +10149,23 @@ static void ppc_cpu_initfn(Object *obj)
     PowerPCCPU *cpu = POWERPC_CPU(obj);
     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
     CPUPPCState *env = &cpu->env;
-    ppc_def_t *def = pcc->info;
 
     cs->env_ptr = env;
     cpu_exec_init(env);
 
-    env->msr_mask = def->msr_mask;
-    env->mmu_model = def->mmu_model;
-    env->excp_model = def->excp_model;
-    env->bus_model = def->bus_model;
-    env->insns_flags = def->insns_flags;
-    env->insns_flags2 = def->insns_flags2;
-    env->flags = def->flags;
-    env->bfd_mach = def->bfd_mach;
-    env->check_pow = def->check_pow;
+    env->msr_mask = pcc->msr_mask;
+    env->mmu_model = pcc->mmu_model;
+    env->excp_model = pcc->excp_model;
+    env->bus_model = pcc->bus_model;
+    env->insns_flags = pcc->insns_flags;
+    env->insns_flags2 = pcc->insns_flags2;
+    env->flags = pcc->flags;
+    env->bfd_mach = pcc->bfd_mach;
+    env->check_pow = pcc->check_pow;
 
 #if defined(TARGET_PPC64)
-    if (def->sps) {
-        env->sps = *def->sps;
+    if (pcc->sps) {
+        env->sps = *pcc->sps;
     } else if (env->mmu_model & POWERPC_MMU_64) {
         /* Use default sets of page sizes */
         static const struct ppc_segment_page_sizes defsps = {
@@ -10206,20 +10216,7 @@ static const TypeInfo ppc_cpu_type_info = {
 
 static void ppc_cpu_register_types(void)
 {
-    int i;
-
     type_register_static(&ppc_cpu_type_info);
-
-    for (i = 0; i < ARRAY_SIZE(ppc_defs); i++) {
-        const ppc_def_t *def = &ppc_defs[i];
-#if defined(TARGET_PPCEMB)
-        /* When using the ppcemb target, we only support 440 style cores */
-        if (def->mmu_model != POWERPC_MMU_BOOKE) {
-            continue;
-        }
-#endif
-        ppc_cpu_register_model(def);
-    }
 }
 
 type_init(ppc_cpu_register_types)
commit de400129daf3ff0f7468363f6d886fcdcc626ea6
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:40 2013 +0000

    target-ppc: Get model name from type name
    
    We are about to drop the redundant name field along with ppc_def_t.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 9d4831f..7eb565d 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -9979,9 +9979,14 @@ static void ppc_cpu_list_entry(gpointer data, gpointer user_data)
     ObjectClass *oc = data;
     CPUListState *s = user_data;
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+    const char *typename = object_class_get_name(oc);
+    char *name;
 
+    name = g_strndup(typename,
+                     strlen(typename) - strlen("-" TYPE_POWERPC_CPU));
     (*s->cpu_fprintf)(s->file, "PowerPC %-16s PVR %08x\n",
-                      pcc->info->name, pcc->info->pvr);
+                      name, pcc->info->pvr);
+    g_free(name);
 }
 
 void ppc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
@@ -10014,12 +10019,14 @@ static void ppc_cpu_defs_entry(gpointer data, gpointer user_data)
 {
     ObjectClass *oc = data;
     CpuDefinitionInfoList **first = user_data;
-    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+    const char *typename;
     CpuDefinitionInfoList *entry;
     CpuDefinitionInfo *info;
 
+    typename = object_class_get_name(oc);
     info = g_malloc0(sizeof(*info));
-    info->name = g_strdup(pcc->info->name);
+    info->name = g_strndup(typename,
+                           strlen(typename) - strlen("-" TYPE_POWERPC_CPU));
 
     entry = g_malloc0(sizeof(*entry));
     entry->value = info;
commit f591784b639c72138f0cfd30b46dcf328f9adc8b
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:39 2013 +0000

    target-ppc: Extract POWER7 alias
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index bcb22cc..9d4831f 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7315,7 +7315,6 @@ 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_POWER7_v21         = 0x003F0201,
     CPU_POWERPC_POWER7_v23         = 0x003F0203,
@@ -8703,7 +8702,6 @@ static const ppc_def_t ppc_defs[] = {
     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_DEF("POWER7_v2.1",   CPU_POWERPC_POWER7_v21,             POWER7)
     POWERPC_DEF("POWER7_v2.3",   CPU_POWERPC_POWER7_v23,             POWER7)
@@ -8953,6 +8951,7 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "Boxer", "POWER3" },
     { "Dino",  "POWER3" },
     { "POWER3+", "631" },
+    { "POWER7", "POWER7_v2.0" },
     { "970fx", "970fx_v3.1" },
     { "970mp", "970mp_v1.1" },
     { "Apache", "RS64" },
commit df43f4b863ba4f7f89afedddc86ad9e11157b51e
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:38 2013 +0000

    target-ppc: Extract 970 aliases
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 3fa131f..bcb22cc 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7320,14 +7320,12 @@ enum {
     CPU_POWERPC_POWER7_v21         = 0x003F0201,
     CPU_POWERPC_POWER7_v23         = 0x003F0203,
     CPU_POWERPC_970                = 0x00390202,
-#define CPU_POWERPC_970FX            CPU_POWERPC_970FX_v31
     CPU_POWERPC_970FX_v10          = 0x00391100,
     CPU_POWERPC_970FX_v20          = 0x003C0200,
     CPU_POWERPC_970FX_v21          = 0x003C0201,
     CPU_POWERPC_970FX_v30          = 0x003C0300,
     CPU_POWERPC_970FX_v31          = 0x003C0301,
     CPU_POWERPC_970GX              = 0x00450000,
-#define CPU_POWERPC_970MP            CPU_POWERPC_970MP_v11
     CPU_POWERPC_970MP_v10          = 0x00440100,
     CPU_POWERPC_970MP_v11          = 0x00440101,
 #define CPU_POWERPC_CELL             CPU_POWERPC_CELL_v32
@@ -8711,8 +8709,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("POWER7_v2.3",   CPU_POWERPC_POWER7_v23,             POWER7)
     /* PowerPC 970                                                           */
     POWERPC_DEF("970",           CPU_POWERPC_970,                    970)
-    /* PowerPC 970FX (G5)                                                    */
-    POWERPC_DEF("970fx",         CPU_POWERPC_970FX,                  970FX)
     /* PowerPC 970FX v1.0 (G5)                                               */
     POWERPC_DEF("970fx_v1.0",    CPU_POWERPC_970FX_v10,              970FX)
     /* PowerPC 970FX v2.0 (G5)                                               */
@@ -8725,8 +8721,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("970fx_v3.1",    CPU_POWERPC_970FX_v31,              970FX)
     /* PowerPC 970GX (G5)                                                    */
     POWERPC_DEF("970gx",         CPU_POWERPC_970GX,                  970GX)
-    /* PowerPC 970MP                                                         */
-    POWERPC_DEF("970mp",         CPU_POWERPC_970MP,                  970MP)
     /* PowerPC 970MP v1.0                                                    */
     POWERPC_DEF("970mp_v1.0",    CPU_POWERPC_970MP_v10,              970MP)
     /* PowerPC 970MP v1.1                                                    */
@@ -8959,6 +8953,8 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "Boxer", "POWER3" },
     { "Dino",  "POWER3" },
     { "POWER3+", "631" },
+    { "970fx", "970fx_v3.1" },
+    { "970mp", "970mp_v1.1" },
     { "Apache", "RS64" },
     { "A35",    "RS64" },
     { "NorthStar", "RS64-II" },
commit 4bdba7fd2efbd57b9dc12bfb930f085a54f3df47
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:37 2013 +0000

    target-ppc: Extract 405GPe alias
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 4e5278d..3fa131f 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -6891,7 +6891,6 @@ enum {
     CPU_POWERPC_405GPb             = 0x40110040,
     CPU_POWERPC_405GPc             = 0x40110082,
     CPU_POWERPC_405GPd             = 0x401100C4,
-#define CPU_POWERPC_405GPe           CPU_POWERPC_405CRc
     CPU_POWERPC_405GPR             = 0x50910951,
 #if 0
     CPU_POWERPC_405H               = xxx,
@@ -7658,8 +7657,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("405GPc",        CPU_POWERPC_405GPc,                 405)
     /* PowerPC 405 GPd                                                       */
     POWERPC_DEF("405GPd",        CPU_POWERPC_405GPd,                 405)
-    /* PowerPC 405 GPe                                                       */
-    POWERPC_DEF("405GPe",        CPU_POWERPC_405GPe,                 405)
     /* PowerPC 405 GPR                                                       */
     POWERPC_DEF("405GPR",        CPU_POWERPC_405GPR,                 405)
 #if defined(TODO)
@@ -8805,6 +8802,7 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "405", "405D4" },
     { "405CR", "405CRc" },
     { "405GP", "405GPd" },
+    { "405GPe", "405CRc" },
     { "x2vp7", "x2vp4" },
     { "x2vp50", "x2vp20" },
 
commit 7b48a1ad3242fc7f6a19620f8a23f92a4f9ffb67
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:36 2013 +0000

    target-ppc: Extract MPC8240 alias
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 2e41f0b..4e5278d 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7042,8 +7042,6 @@ enum {
 #define CPU_POWERPC_MPC5200_v12      CPU_POWERPC_G2LEgp1
 #define CPU_POWERPC_MPC5200B_v20     CPU_POWERPC_G2LEgp1
 #define CPU_POWERPC_MPC5200B_v21     CPU_POWERPC_G2LEgp1
-    /* MPC82xx microcontrollers */
-#define CPU_POWERPC_MPC8240          CPU_POWERPC_MPC603
     /* e200 family */
     /* e200 cores */
 #if 0
@@ -7899,9 +7897,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("G2leGP1",       CPU_POWERPC_G2LEgp1,                G2LE)
     /* PowerPC G2LE GP3 core                                                 */
     POWERPC_DEF("G2leGP3",       CPU_POWERPC_G2LEgp3,                G2LE)
-    /* PowerPC MPC603 microcontrollers                                       */
-    /* MPC8240                                                               */
-    POWERPC_DEF("MPC8240",       CPU_POWERPC_MPC8240,                603E)
     /* PowerPC G2 microcontrollers                                           */
 #if defined(TODO)
     /* MPC5121                                                               */
@@ -8852,6 +8847,9 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "MPC880", "MPC8xx" },
     { "MPC885", "MPC8xx" },
 
+    /* PowerPC MPC603 microcontrollers */
+    { "MPC8240", "603" },
+
     { "MPC52xx", "MPC5200" },
     { "MPC5200", "MPC5200_v12" },
     { "MPC5200B", "MPC5200B_v21" },
commit 236824f276fafbfbb5399ca2c9c72298a401e223
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:35 2013 +0000

    target-ppc: Extract MPC5200/MPC5200B aliases
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 625811e..2e41f0b 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7037,11 +7037,9 @@ enum {
     CPU_POWERPC_G2LEgp3            = 0x80822013,
     /* MPC52xx microcontrollers  */
     /* XXX: MPC 5121 ? */
-#define CPU_POWERPC_MPC5200          CPU_POWERPC_MPC5200_v12
 #define CPU_POWERPC_MPC5200_v10      CPU_POWERPC_G2LEgp1
 #define CPU_POWERPC_MPC5200_v11      CPU_POWERPC_G2LEgp1
 #define CPU_POWERPC_MPC5200_v12      CPU_POWERPC_G2LEgp1
-#define CPU_POWERPC_MPC5200B         CPU_POWERPC_MPC5200B_v21
 #define CPU_POWERPC_MPC5200B_v20     CPU_POWERPC_G2LEgp1
 #define CPU_POWERPC_MPC5200B_v21     CPU_POWERPC_G2LEgp1
     /* MPC82xx microcontrollers */
@@ -7363,11 +7361,9 @@ enum {
 /* System version register (used on MPC 8xxx)                                */
 enum {
     POWERPC_SVR_NONE               = 0x00000000,
-#define POWERPC_SVR_5200             POWERPC_SVR_5200_v12
     POWERPC_SVR_5200_v10           = 0x80110010,
     POWERPC_SVR_5200_v11           = 0x80110011,
     POWERPC_SVR_5200_v12           = 0x80110012,
-#define POWERPC_SVR_5200B            POWERPC_SVR_5200B_v21
     POWERPC_SVR_5200B_v20          = 0x80110020,
     POWERPC_SVR_5200B_v21          = 0x80110021,
 #define POWERPC_SVR_55xx             POWERPC_SVR_5567
@@ -7912,9 +7908,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF_SVR("MPC5121",
                     CPU_POWERPC_MPC5121,      POWERPC_SVR_5121,      G2LE)
 #endif
-    /* MPC5200                                                               */
-    POWERPC_DEF_SVR("MPC5200",
-                    CPU_POWERPC_MPC5200,      POWERPC_SVR_5200,      G2LE)
     /* MPC5200 v1.0                                                          */
     POWERPC_DEF_SVR("MPC5200_v10",
                     CPU_POWERPC_MPC5200_v10,  POWERPC_SVR_5200_v10,  G2LE)
@@ -7924,9 +7917,6 @@ static const ppc_def_t ppc_defs[] = {
     /* MPC5200 v1.2                                                          */
     POWERPC_DEF_SVR("MPC5200_v12",
                     CPU_POWERPC_MPC5200_v12,  POWERPC_SVR_5200_v12,  G2LE)
-    /* MPC5200B                                                              */
-    POWERPC_DEF_SVR("MPC5200B",
-                    CPU_POWERPC_MPC5200B,     POWERPC_SVR_5200B,     G2LE)
     /* MPC5200B v2.0                                                         */
     POWERPC_DEF_SVR("MPC5200B_v20",
                     CPU_POWERPC_MPC5200B_v20, POWERPC_SVR_5200B_v20, G2LE)
@@ -8863,6 +8853,8 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "MPC885", "MPC8xx" },
 
     { "MPC52xx", "MPC5200" },
+    { "MPC5200", "MPC5200_v12" },
+    { "MPC5200B", "MPC5200B_v21" },
 
     { "MPC82xx", "MPC8280" },
     { "PowerQUICC-II", "MPC82xx" },
commit cf9314cd77f07398303423dd17c520fa92d0b30f
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:34 2013 +0000

    target-ppc: Extract MPC52xx alias
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 89c9e24..625811e 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7037,7 +7037,6 @@ enum {
     CPU_POWERPC_G2LEgp3            = 0x80822013,
     /* MPC52xx microcontrollers  */
     /* XXX: MPC 5121 ? */
-#define CPU_POWERPC_MPC52xx          CPU_POWERPC_MPC5200
 #define CPU_POWERPC_MPC5200          CPU_POWERPC_MPC5200_v12
 #define CPU_POWERPC_MPC5200_v10      CPU_POWERPC_G2LEgp1
 #define CPU_POWERPC_MPC5200_v11      CPU_POWERPC_G2LEgp1
@@ -7364,7 +7363,6 @@ enum {
 /* System version register (used on MPC 8xxx)                                */
 enum {
     POWERPC_SVR_NONE               = 0x00000000,
-#define POWERPC_SVR_52xx             POWERPC_SVR_5200
 #define POWERPC_SVR_5200             POWERPC_SVR_5200_v12
     POWERPC_SVR_5200_v10           = 0x80110010,
     POWERPC_SVR_5200_v11           = 0x80110011,
@@ -7881,9 +7879,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("MPC8xx",        CPU_POWERPC_MPC8xx,                 MPC8xx)
 #endif
     /* MPC82xx family (aka PowerQUICC-II)                                    */
-    /* Generic MPC52xx core                                                  */
-    POWERPC_DEF_SVR("MPC52xx",
-                    CPU_POWERPC_MPC52xx,      POWERPC_SVR_52xx,      G2LE)
     /* PowerPC G2 core                                                       */
     POWERPC_DEF("G2",            CPU_POWERPC_G2,                     G2)
     /* PowerPC G2 H4 core                                                    */
@@ -8867,6 +8862,8 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "MPC880", "MPC8xx" },
     { "MPC885", "MPC8xx" },
 
+    { "MPC52xx", "MPC5200" },
+
     { "MPC82xx", "MPC8280" },
     { "PowerQUICC-II", "MPC82xx" },
     { "MPC8241", "G2HiP4" },
commit d329ceb2baa441629e83006a7e86933d871edadd
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:33 2013 +0000

    target-ppc: Extract MPC82xx_HiP{3, 4} aliases
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 6ba6d26..89c9e24 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7047,20 +7047,6 @@ enum {
 #define CPU_POWERPC_MPC5200B_v21     CPU_POWERPC_G2LEgp1
     /* MPC82xx microcontrollers */
 #define CPU_POWERPC_MPC8240          CPU_POWERPC_MPC603
-#define CPU_POWERPC_MPC8241          CPU_POWERPC_G2_HIP4
-#define CPU_POWERPC_MPC8245          CPU_POWERPC_G2_HIP4
-#define CPU_POWERPC_MPC8250_HiP3     CPU_POWERPC_G2_HIP3
-#define CPU_POWERPC_MPC8250_HiP4     CPU_POWERPC_G2_HIP4
-#define CPU_POWERPC_MPC8255_HiP3     CPU_POWERPC_G2_HIP3
-#define CPU_POWERPC_MPC8255_HiP4     CPU_POWERPC_G2_HIP4
-#define CPU_POWERPC_MPC8260_HiP3     CPU_POWERPC_G2_HIP3
-#define CPU_POWERPC_MPC8260_HiP4     CPU_POWERPC_G2_HIP4
-#define CPU_POWERPC_MPC8264_HiP3     CPU_POWERPC_G2_HIP3
-#define CPU_POWERPC_MPC8264_HiP4     CPU_POWERPC_G2_HIP4
-#define CPU_POWERPC_MPC8265_HiP3     CPU_POWERPC_G2_HIP3
-#define CPU_POWERPC_MPC8265_HiP4     CPU_POWERPC_G2_HIP4
-#define CPU_POWERPC_MPC8266_HiP3     CPU_POWERPC_G2_HIP3
-#define CPU_POWERPC_MPC8266_HiP4     CPU_POWERPC_G2_HIP4
     /* e200 family */
     /* e200 cores */
 #if 0
@@ -7952,34 +7938,6 @@ static const ppc_def_t ppc_defs[] = {
     /* MPC5200B v2.1                                                         */
     POWERPC_DEF_SVR("MPC5200B_v21",
                     CPU_POWERPC_MPC5200B_v21, POWERPC_SVR_5200B_v21, G2LE)
-    /* MPC8241                                                               */
-    POWERPC_DEF("MPC8241",       CPU_POWERPC_MPC8241,                G2)
-    /* MPC8245                                                               */
-    POWERPC_DEF("MPC8245",       CPU_POWERPC_MPC8245,                G2)
-    /* MPC8250 HiP3                                                          */
-    POWERPC_DEF("MPC8250_HiP3",  CPU_POWERPC_MPC8250_HiP3,           G2)
-    /* MPC8250 HiP4                                                          */
-    POWERPC_DEF("MPC8250_HiP4",  CPU_POWERPC_MPC8250_HiP4,           G2)
-    /* MPC8255 HiP3                                                          */
-    POWERPC_DEF("MPC8255_HiP3",  CPU_POWERPC_MPC8255_HiP3,           G2)
-    /* MPC8255 HiP4                                                          */
-    POWERPC_DEF("MPC8255_HiP4",  CPU_POWERPC_MPC8255_HiP4,           G2)
-    /* MPC8260 HiP3                                                          */
-    POWERPC_DEF("MPC8260_HiP3",  CPU_POWERPC_MPC8260_HiP3,           G2)
-    /* MPC8260 HiP4                                                          */
-    POWERPC_DEF("MPC8260_HiP4",  CPU_POWERPC_MPC8260_HiP4,           G2)
-    /* MPC8264 HiP3                                                          */
-    POWERPC_DEF("MPC8264_HiP3",  CPU_POWERPC_MPC8264_HiP3,           G2)
-    /* MPC8264 HiP4                                                          */
-    POWERPC_DEF("MPC8264_HiP4",  CPU_POWERPC_MPC8264_HiP4,           G2)
-    /* MPC8265 HiP3                                                          */
-    POWERPC_DEF("MPC8265_HiP3",  CPU_POWERPC_MPC8265_HiP3,           G2)
-    /* MPC8265 HiP4                                                          */
-    POWERPC_DEF("MPC8265_HiP4",  CPU_POWERPC_MPC8265_HiP4,           G2)
-    /* MPC8266 HiP3                                                          */
-    POWERPC_DEF("MPC8266_HiP3",  CPU_POWERPC_MPC8266_HiP3,           G2)
-    /* MPC8266 HiP4                                                          */
-    POWERPC_DEF("MPC8266_HiP4",  CPU_POWERPC_MPC8266_HiP4,           G2)
     /* e200 family                                                           */
     /* Generic MPC55xx core                                                  */
 #if defined (TODO)
@@ -8911,14 +8869,28 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
 
     { "MPC82xx", "MPC8280" },
     { "PowerQUICC-II", "MPC82xx" },
+    { "MPC8241", "G2HiP4" },
+    { "MPC8245", "G2HiP4" },
     { "MPC8247", "G2leGP3" },
     { "MPC8248", "G2leGP3" },
     { "MPC8250", "MPC8250_HiP4" },
+    { "MPC8250_HiP3", "G2HiP3" },
+    { "MPC8250_HiP4", "G2HiP4" },
     { "MPC8255", "MPC8255_HiP4" },
+    { "MPC8255_HiP3", "G2HiP3" },
+    { "MPC8255_HiP4", "G2HiP4" },
     { "MPC8260", "MPC8260_HiP4" },
+    { "MPC8260_HiP3", "G2HiP3" },
+    { "MPC8260_HiP4", "G2HiP4" },
     { "MPC8264", "MPC8264_HiP4" },
+    { "MPC8264_HiP3", "G2HiP3" },
+    { "MPC8264_HiP4", "G2HiP4" },
     { "MPC8265", "MPC8265_HiP4" },
+    { "MPC8265_HiP3", "G2HiP3" },
+    { "MPC8265_HiP4", "G2HiP4" },
     { "MPC8266", "MPC8266_HiP4" },
+    { "MPC8266_HiP3", "G2HiP3" },
+    { "MPC8266_HiP4", "G2HiP4" },
     { "MPC8270", "G2leGP3" },
     { "MPC8271", "G2leGP3" },
     { "MPC8272", "G2leGP3" },
commit f172e4b99f73115705842bcd676253644e8c356c
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:32 2013 +0000

    target-ppc: Extract MPC82xx aliases to *_HiP4
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 8fd68ed..6ba6d26 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7049,22 +7049,16 @@ enum {
 #define CPU_POWERPC_MPC8240          CPU_POWERPC_MPC603
 #define CPU_POWERPC_MPC8241          CPU_POWERPC_G2_HIP4
 #define CPU_POWERPC_MPC8245          CPU_POWERPC_G2_HIP4
-#define CPU_POWERPC_MPC8250          CPU_POWERPC_MPC8250_HiP4
 #define CPU_POWERPC_MPC8250_HiP3     CPU_POWERPC_G2_HIP3
 #define CPU_POWERPC_MPC8250_HiP4     CPU_POWERPC_G2_HIP4
-#define CPU_POWERPC_MPC8255          CPU_POWERPC_MPC8255_HiP4
 #define CPU_POWERPC_MPC8255_HiP3     CPU_POWERPC_G2_HIP3
 #define CPU_POWERPC_MPC8255_HiP4     CPU_POWERPC_G2_HIP4
-#define CPU_POWERPC_MPC8260          CPU_POWERPC_MPC8260_HiP4
 #define CPU_POWERPC_MPC8260_HiP3     CPU_POWERPC_G2_HIP3
 #define CPU_POWERPC_MPC8260_HiP4     CPU_POWERPC_G2_HIP4
-#define CPU_POWERPC_MPC8264          CPU_POWERPC_MPC8264_HiP4
 #define CPU_POWERPC_MPC8264_HiP3     CPU_POWERPC_G2_HIP3
 #define CPU_POWERPC_MPC8264_HiP4     CPU_POWERPC_G2_HIP4
-#define CPU_POWERPC_MPC8265          CPU_POWERPC_MPC8265_HiP4
 #define CPU_POWERPC_MPC8265_HiP3     CPU_POWERPC_G2_HIP3
 #define CPU_POWERPC_MPC8265_HiP4     CPU_POWERPC_G2_HIP4
-#define CPU_POWERPC_MPC8266          CPU_POWERPC_MPC8266_HiP4
 #define CPU_POWERPC_MPC8266_HiP3     CPU_POWERPC_G2_HIP3
 #define CPU_POWERPC_MPC8266_HiP4     CPU_POWERPC_G2_HIP4
     /* e200 family */
@@ -7962,38 +7956,26 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("MPC8241",       CPU_POWERPC_MPC8241,                G2)
     /* MPC8245                                                               */
     POWERPC_DEF("MPC8245",       CPU_POWERPC_MPC8245,                G2)
-    /* MPC8250                                                               */
-    POWERPC_DEF("MPC8250",       CPU_POWERPC_MPC8250,                G2)
     /* MPC8250 HiP3                                                          */
     POWERPC_DEF("MPC8250_HiP3",  CPU_POWERPC_MPC8250_HiP3,           G2)
     /* MPC8250 HiP4                                                          */
     POWERPC_DEF("MPC8250_HiP4",  CPU_POWERPC_MPC8250_HiP4,           G2)
-    /* MPC8255                                                               */
-    POWERPC_DEF("MPC8255",       CPU_POWERPC_MPC8255,                G2)
     /* MPC8255 HiP3                                                          */
     POWERPC_DEF("MPC8255_HiP3",  CPU_POWERPC_MPC8255_HiP3,           G2)
     /* MPC8255 HiP4                                                          */
     POWERPC_DEF("MPC8255_HiP4",  CPU_POWERPC_MPC8255_HiP4,           G2)
-    /* MPC8260                                                               */
-    POWERPC_DEF("MPC8260",       CPU_POWERPC_MPC8260,                G2)
     /* MPC8260 HiP3                                                          */
     POWERPC_DEF("MPC8260_HiP3",  CPU_POWERPC_MPC8260_HiP3,           G2)
     /* MPC8260 HiP4                                                          */
     POWERPC_DEF("MPC8260_HiP4",  CPU_POWERPC_MPC8260_HiP4,           G2)
-    /* MPC8264                                                               */
-    POWERPC_DEF("MPC8264",       CPU_POWERPC_MPC8264,                G2)
     /* MPC8264 HiP3                                                          */
     POWERPC_DEF("MPC8264_HiP3",  CPU_POWERPC_MPC8264_HiP3,           G2)
     /* MPC8264 HiP4                                                          */
     POWERPC_DEF("MPC8264_HiP4",  CPU_POWERPC_MPC8264_HiP4,           G2)
-    /* MPC8265                                                               */
-    POWERPC_DEF("MPC8265",       CPU_POWERPC_MPC8265,                G2)
     /* MPC8265 HiP3                                                          */
     POWERPC_DEF("MPC8265_HiP3",  CPU_POWERPC_MPC8265_HiP3,           G2)
     /* MPC8265 HiP4                                                          */
     POWERPC_DEF("MPC8265_HiP4",  CPU_POWERPC_MPC8265_HiP4,           G2)
-    /* MPC8266                                                               */
-    POWERPC_DEF("MPC8266",       CPU_POWERPC_MPC8266,                G2)
     /* MPC8266 HiP3                                                          */
     POWERPC_DEF("MPC8266_HiP3",  CPU_POWERPC_MPC8266_HiP3,           G2)
     /* MPC8266 HiP4                                                          */
@@ -8931,6 +8913,12 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "PowerQUICC-II", "MPC82xx" },
     { "MPC8247", "G2leGP3" },
     { "MPC8248", "G2leGP3" },
+    { "MPC8250", "MPC8250_HiP4" },
+    { "MPC8255", "MPC8255_HiP4" },
+    { "MPC8260", "MPC8260_HiP4" },
+    { "MPC8264", "MPC8264_HiP4" },
+    { "MPC8265", "MPC8265_HiP4" },
+    { "MPC8266", "MPC8266_HiP4" },
     { "MPC8270", "G2leGP3" },
     { "MPC8271", "G2leGP3" },
     { "MPC8272", "G2leGP3" },
commit 4d55320fdb64b9110fa379520434f70d60d90bdd
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:31 2013 +0000

    target-ppc: Extract MPC8247/MPC8248/MPC8270-80 aliases
    
    This depends on the fix for "G2leGP3" PVR.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 2ab7d16..8fd68ed 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7049,8 +7049,6 @@ enum {
 #define CPU_POWERPC_MPC8240          CPU_POWERPC_MPC603
 #define CPU_POWERPC_MPC8241          CPU_POWERPC_G2_HIP4
 #define CPU_POWERPC_MPC8245          CPU_POWERPC_G2_HIP4
-#define CPU_POWERPC_MPC8247          CPU_POWERPC_G2LEgp3
-#define CPU_POWERPC_MPC8248          CPU_POWERPC_G2LEgp3
 #define CPU_POWERPC_MPC8250          CPU_POWERPC_MPC8250_HiP4
 #define CPU_POWERPC_MPC8250_HiP3     CPU_POWERPC_G2_HIP3
 #define CPU_POWERPC_MPC8250_HiP4     CPU_POWERPC_G2_HIP4
@@ -7069,11 +7067,6 @@ enum {
 #define CPU_POWERPC_MPC8266          CPU_POWERPC_MPC8266_HiP4
 #define CPU_POWERPC_MPC8266_HiP3     CPU_POWERPC_G2_HIP3
 #define CPU_POWERPC_MPC8266_HiP4     CPU_POWERPC_G2_HIP4
-#define CPU_POWERPC_MPC8270          CPU_POWERPC_G2LEgp3
-#define CPU_POWERPC_MPC8271          CPU_POWERPC_G2LEgp3
-#define CPU_POWERPC_MPC8272          CPU_POWERPC_G2LEgp3
-#define CPU_POWERPC_MPC8275          CPU_POWERPC_G2LEgp3
-#define CPU_POWERPC_MPC8280          CPU_POWERPC_G2LEgp3
     /* e200 family */
     /* e200 cores */
 #if 0
@@ -7969,10 +7962,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("MPC8241",       CPU_POWERPC_MPC8241,                G2)
     /* MPC8245                                                               */
     POWERPC_DEF("MPC8245",       CPU_POWERPC_MPC8245,                G2)
-    /* MPC8247                                                               */
-    POWERPC_DEF("MPC8247",       CPU_POWERPC_MPC8247,                G2LE)
-    /* MPC8248                                                               */
-    POWERPC_DEF("MPC8248",       CPU_POWERPC_MPC8248,                G2LE)
     /* MPC8250                                                               */
     POWERPC_DEF("MPC8250",       CPU_POWERPC_MPC8250,                G2)
     /* MPC8250 HiP3                                                          */
@@ -8009,16 +7998,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("MPC8266_HiP3",  CPU_POWERPC_MPC8266_HiP3,           G2)
     /* MPC8266 HiP4                                                          */
     POWERPC_DEF("MPC8266_HiP4",  CPU_POWERPC_MPC8266_HiP4,           G2)
-    /* MPC8270                                                               */
-    POWERPC_DEF("MPC8270",       CPU_POWERPC_MPC8270,                G2LE)
-    /* MPC8271                                                               */
-    POWERPC_DEF("MPC8271",       CPU_POWERPC_MPC8271,                G2LE)
-    /* MPC8272                                                               */
-    POWERPC_DEF("MPC8272",       CPU_POWERPC_MPC8272,                G2LE)
-    /* MPC8275                                                               */
-    POWERPC_DEF("MPC8275",       CPU_POWERPC_MPC8275,                G2LE)
-    /* MPC8280                                                               */
-    POWERPC_DEF("MPC8280",       CPU_POWERPC_MPC8280,                G2LE)
     /* e200 family                                                           */
     /* Generic MPC55xx core                                                  */
 #if defined (TODO)
@@ -8950,6 +8929,13 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
 
     { "MPC82xx", "MPC8280" },
     { "PowerQUICC-II", "MPC82xx" },
+    { "MPC8247", "G2leGP3" },
+    { "MPC8248", "G2leGP3" },
+    { "MPC8270", "G2leGP3" },
+    { "MPC8271", "G2leGP3" },
+    { "MPC8272", "G2leGP3" },
+    { "MPC8275", "G2leGP3" },
+    { "MPC8280", "G2leGP3" },
     { "e200", "e200z6" },
     { "e300", "e300c3" },
     { "MPC8347", "MPC8347T" },
commit 63499f2109f7849420cc8858204bff267a0edcd6
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:30 2013 +0000

    target-ppc: Extract MPC82xx alias
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index a4eae26..2ab7d16 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7046,7 +7046,6 @@ enum {
 #define CPU_POWERPC_MPC5200B_v20     CPU_POWERPC_G2LEgp1
 #define CPU_POWERPC_MPC5200B_v21     CPU_POWERPC_G2LEgp1
     /* MPC82xx microcontrollers */
-#define CPU_POWERPC_MPC82xx          CPU_POWERPC_MPC8280
 #define CPU_POWERPC_MPC8240          CPU_POWERPC_MPC603
 #define CPU_POWERPC_MPC8241          CPU_POWERPC_G2_HIP4
 #define CPU_POWERPC_MPC8245          CPU_POWERPC_G2_HIP4
@@ -7912,8 +7911,6 @@ static const ppc_def_t ppc_defs[] = {
     /* Generic MPC52xx core                                                  */
     POWERPC_DEF_SVR("MPC52xx",
                     CPU_POWERPC_MPC52xx,      POWERPC_SVR_52xx,      G2LE)
-    /* Generic MPC82xx core                                                  */
-    POWERPC_DEF("MPC82xx",       CPU_POWERPC_MPC82xx,                G2)
     /* PowerPC G2 core                                                       */
     POWERPC_DEF("G2",            CPU_POWERPC_G2,                     G2)
     /* PowerPC G2 H4 core                                                    */
@@ -8951,6 +8948,7 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "MPC880", "MPC8xx" },
     { "MPC885", "MPC8xx" },
 
+    { "MPC82xx", "MPC8280" },
     { "PowerQUICC-II", "MPC82xx" },
     { "e200", "e200z6" },
     { "e300", "e300c3" },
commit 4475e98f995ab726ce8bbf70225b2d90b20b9cd3
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:29 2013 +0000

    target-ppc: Extract e200 alias
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index d2cee80..a4eae26 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7077,7 +7077,6 @@ enum {
 #define CPU_POWERPC_MPC8280          CPU_POWERPC_G2LEgp3
     /* e200 family */
     /* e200 cores */
-#define CPU_POWERPC_e200             CPU_POWERPC_e200z6
 #if 0
     CPU_POWERPC_e200z0             = xxx,
 #endif
@@ -8024,8 +8023,6 @@ static const ppc_def_t ppc_defs[] = {
     /* MPC8280                                                               */
     POWERPC_DEF("MPC8280",       CPU_POWERPC_MPC8280,                G2LE)
     /* e200 family                                                           */
-    /* Generic PowerPC e200 core                                             */
-    POWERPC_DEF("e200",          CPU_POWERPC_e200,                   e200)
     /* Generic MPC55xx core                                                  */
 #if defined (TODO)
     POWERPC_DEF_SVR("MPC55xx",
@@ -8955,6 +8952,7 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "MPC885", "MPC8xx" },
 
     { "PowerQUICC-II", "MPC82xx" },
+    { "e200", "e200z6" },
     { "e300", "e300c3" },
     { "MPC8347", "MPC8347T" },
     { "MPC8347A", "MPC8347AT" },
commit 0683641cc754e3d786acdeab8d00723dbd87727b
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:28 2013 +0000

    target-ppc: Extract e300 alias
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 8f765ad..d2cee80 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7119,7 +7119,6 @@ enum {
 #define CPU_POWERPC_MPC5567          CPU_POWERPC_e200z6
     /* e300 family */
     /* e300 cores */
-#define CPU_POWERPC_e300             CPU_POWERPC_e300c3
     CPU_POWERPC_e300c1             = 0x00830010,
     CPU_POWERPC_e300c2             = 0x00840010,
     CPU_POWERPC_e300c3             = 0x00850010,
@@ -8160,8 +8159,6 @@ static const ppc_def_t ppc_defs[] = {
                     CPU_POWERPC_MPC5567,      POWERPC_SVR_5567,      e200)
 #endif
     /* e300 family                                                           */
-    /* Generic PowerPC e300 core                                             */
-    POWERPC_DEF("e300",          CPU_POWERPC_e300,                   e300)
     /* PowerPC e300c1 core                                                   */
     POWERPC_DEF("e300c1",        CPU_POWERPC_e300c1,                 e300)
     /* PowerPC e300c2 core                                                   */
@@ -8958,6 +8955,7 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "MPC885", "MPC8xx" },
 
     { "PowerQUICC-II", "MPC82xx" },
+    { "e300", "e300c3" },
     { "MPC8347", "MPC8347T" },
     { "MPC8347A", "MPC8347AT" },
     { "MPC8347E", "MPC8347ET" },
commit 9538de4fe708ca09af3a786fb9b26e2269ebc8f0
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:27 2013 +0000

    target-ppc: Extract MPC83xx aliases
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 91473dc..8f765ad 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7461,16 +7461,12 @@ enum {
     POWERPC_SVR_8343A              = 0x80570030,
     POWERPC_SVR_8343E              = 0x80560010,
     POWERPC_SVR_8343EA             = 0x80560030,
-#define POWERPC_SVR_8347             POWERPC_SVR_8347T
     POWERPC_SVR_8347P              = 0x80550010, /* PBGA package */
     POWERPC_SVR_8347T              = 0x80530010, /* TBGA package */
-#define POWERPC_SVR_8347A            POWERPC_SVR_8347AT
     POWERPC_SVR_8347AP             = 0x80550030, /* PBGA package */
     POWERPC_SVR_8347AT             = 0x80530030, /* TBGA package */
-#define POWERPC_SVR_8347E            POWERPC_SVR_8347ET
     POWERPC_SVR_8347EP             = 0x80540010, /* PBGA package */
     POWERPC_SVR_8347ET             = 0x80520010, /* TBGA package */
-#define POWERPC_SVR_8347EA            POWERPC_SVR_8347EAT
     POWERPC_SVR_8347EAP            = 0x80540030, /* PBGA package */
     POWERPC_SVR_8347EAT            = 0x80520030, /* TBGA package */
     POWERPC_SVR_8349               = 0x80510010,
@@ -8237,36 +8233,24 @@ static const ppc_def_t ppc_defs[] = {
     /* MPC8343EA                                                             */
     POWERPC_DEF_SVR("MPC8343EA",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8343EA,    e300)
-    /* MPC8347                                                               */
-    POWERPC_DEF_SVR("MPC8347",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347,      e300)
     /* MPC8347T                                                              */
     POWERPC_DEF_SVR("MPC8347T",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8347T,     e300)
     /* MPC8347P                                                              */
     POWERPC_DEF_SVR("MPC8347P",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8347P,     e300)
-    /* MPC8347A                                                              */
-    POWERPC_DEF_SVR("MPC8347A",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347A,     e300)
     /* MPC8347AT                                                             */
     POWERPC_DEF_SVR("MPC8347AT",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8347AT,    e300)
     /* MPC8347AP                                                             */
     POWERPC_DEF_SVR("MPC8347AP",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8347AP,    e300)
-    /* MPC8347E                                                              */
-    POWERPC_DEF_SVR("MPC8347E",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347E,     e300)
     /* MPC8347ET                                                             */
     POWERPC_DEF_SVR("MPC8347ET",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8347ET,    e300)
     /* MPC8343EP                                                             */
     POWERPC_DEF_SVR("MPC8347EP",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EP,    e300)
-    /* MPC8347EA                                                             */
-    POWERPC_DEF_SVR("MPC8347EA",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EA,    e300)
     /* MPC8347EAT                                                            */
     POWERPC_DEF_SVR("MPC8347EAT",
                     CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EAT,   e300)
@@ -8974,6 +8958,10 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "MPC885", "MPC8xx" },
 
     { "PowerQUICC-II", "MPC82xx" },
+    { "MPC8347", "MPC8347T" },
+    { "MPC8347A", "MPC8347AT" },
+    { "MPC8347E", "MPC8347ET" },
+    { "MPC8347EA", "MPC8347EAT" },
     { "e500", "e500v2_v22" },
     { "e500v1", "e500_v20" },
     { "e500v2", "e500v2_v22" },
commit 6d4decb484b5cc31a9a4a069eff21c89f8d288b5
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:26 2013 +0000

    target-ppc: Extract e500v1/e500v2 aliases
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 9939af5..91473dc 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7134,8 +7134,6 @@ enum {
     /* e500 family */
     /* e500 cores  */
 #define CPU_POWERPC_e500             CPU_POWERPC_e500v2_v22
-#define CPU_POWERPC_e500v1           CPU_POWERPC_e500v1_v20
-#define CPU_POWERPC_e500v2           CPU_POWERPC_e500v2_v22
     CPU_POWERPC_e500v1_v10         = 0x80200010,
     CPU_POWERPC_e500v1_v20         = 0x80200020,
     CPU_POWERPC_e500v2_v10         = 0x80210010,
@@ -8316,14 +8314,10 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF_SVR("MPC8379E",
                     CPU_POWERPC_MPC837x,      POWERPC_SVR_8379E,     e300)
     /* e500 family                                                           */
-    /* PowerPC e500v1 core                                                   */
-    POWERPC_DEF("e500v1",        CPU_POWERPC_e500v1,                 e500v1)
     /* PowerPC e500 v1.0 core                                                */
     POWERPC_DEF("e500_v10",      CPU_POWERPC_e500v1_v10,             e500v1)
     /* PowerPC e500 v2.0 core                                                */
     POWERPC_DEF("e500_v20",      CPU_POWERPC_e500v1_v20,             e500v1)
-    /* PowerPC e500v2 core                                                   */
-    POWERPC_DEF("e500v2",        CPU_POWERPC_e500v2,                 e500v2)
     /* PowerPC e500v2 v1.0 core                                              */
     POWERPC_DEF("e500v2_v10",    CPU_POWERPC_e500v2_v10,             e500v2)
     /* PowerPC e500v2 v2.0 core                                              */
@@ -8981,6 +8975,8 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
 
     { "PowerQUICC-II", "MPC82xx" },
     { "e500", "e500v2_v22" },
+    { "e500v1", "e500_v20" },
+    { "e500v2", "e500v2_v22" },
     { "MPC8533", "MPC8533_v11" },
     { "MPC8533E", "MPC8533E_v11" },
     { "MPC8540", "MPC8540_v21" },
commit 52d80768dba6876919bb4e7f4fc00641431ef2cf
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:25 2013 +0000

    target-ppc: Extract MPC85xx aliases
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index c909410..9939af5 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7147,67 +7147,50 @@ enum {
     CPU_POWERPC_e500mc             = 0x80230020,
     CPU_POWERPC_e5500              = 0x80240020,
     /* MPC85xx microcontrollers */
-#define CPU_POWERPC_MPC8533          CPU_POWERPC_MPC8533_v11
 #define CPU_POWERPC_MPC8533_v10      CPU_POWERPC_e500v2_v21
 #define CPU_POWERPC_MPC8533_v11      CPU_POWERPC_e500v2_v22
-#define CPU_POWERPC_MPC8533E         CPU_POWERPC_MPC8533E_v11
 #define CPU_POWERPC_MPC8533E_v10     CPU_POWERPC_e500v2_v21
 #define CPU_POWERPC_MPC8533E_v11     CPU_POWERPC_e500v2_v22
-#define CPU_POWERPC_MPC8540          CPU_POWERPC_MPC8540_v21
 #define CPU_POWERPC_MPC8540_v10      CPU_POWERPC_e500v1_v10
 #define CPU_POWERPC_MPC8540_v20      CPU_POWERPC_e500v1_v20
 #define CPU_POWERPC_MPC8540_v21      CPU_POWERPC_e500v1_v20
-#define CPU_POWERPC_MPC8541          CPU_POWERPC_MPC8541_v11
 #define CPU_POWERPC_MPC8541_v10      CPU_POWERPC_e500v1_v20
 #define CPU_POWERPC_MPC8541_v11      CPU_POWERPC_e500v1_v20
-#define CPU_POWERPC_MPC8541E         CPU_POWERPC_MPC8541E_v11
 #define CPU_POWERPC_MPC8541E_v10     CPU_POWERPC_e500v1_v20
 #define CPU_POWERPC_MPC8541E_v11     CPU_POWERPC_e500v1_v20
-#define CPU_POWERPC_MPC8543          CPU_POWERPC_MPC8543_v21
 #define CPU_POWERPC_MPC8543_v10      CPU_POWERPC_e500v2_v10
 #define CPU_POWERPC_MPC8543_v11      CPU_POWERPC_e500v2_v11
 #define CPU_POWERPC_MPC8543_v20      CPU_POWERPC_e500v2_v20
 #define CPU_POWERPC_MPC8543_v21      CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8543E         CPU_POWERPC_MPC8543E_v21
 #define CPU_POWERPC_MPC8543E_v10     CPU_POWERPC_e500v2_v10
 #define CPU_POWERPC_MPC8543E_v11     CPU_POWERPC_e500v2_v11
 #define CPU_POWERPC_MPC8543E_v20     CPU_POWERPC_e500v2_v20
 #define CPU_POWERPC_MPC8543E_v21     CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8544          CPU_POWERPC_MPC8544_v11
 #define CPU_POWERPC_MPC8544_v10      CPU_POWERPC_e500v2_v21
 #define CPU_POWERPC_MPC8544_v11      CPU_POWERPC_e500v2_v22
 #define CPU_POWERPC_MPC8544E_v11     CPU_POWERPC_e500v2_v22
-#define CPU_POWERPC_MPC8544E         CPU_POWERPC_MPC8544E_v11
 #define CPU_POWERPC_MPC8544E_v10     CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8545          CPU_POWERPC_MPC8545_v21
 #define CPU_POWERPC_MPC8545_v10      CPU_POWERPC_e500v2_v10
 #define CPU_POWERPC_MPC8545_v20      CPU_POWERPC_e500v2_v20
 #define CPU_POWERPC_MPC8545_v21      CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8545E         CPU_POWERPC_MPC8545E_v21
 #define CPU_POWERPC_MPC8545E_v10     CPU_POWERPC_e500v2_v10
 #define CPU_POWERPC_MPC8545E_v20     CPU_POWERPC_e500v2_v20
 #define CPU_POWERPC_MPC8545E_v21     CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8547E         CPU_POWERPC_MPC8547E_v21
 #define CPU_POWERPC_MPC8547E_v10     CPU_POWERPC_e500v2_v10
 #define CPU_POWERPC_MPC8547E_v20     CPU_POWERPC_e500v2_v20
 #define CPU_POWERPC_MPC8547E_v21     CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8548          CPU_POWERPC_MPC8548_v21
 #define CPU_POWERPC_MPC8548_v10      CPU_POWERPC_e500v2_v10
 #define CPU_POWERPC_MPC8548_v11      CPU_POWERPC_e500v2_v11
 #define CPU_POWERPC_MPC8548_v20      CPU_POWERPC_e500v2_v20
 #define CPU_POWERPC_MPC8548_v21      CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8548E         CPU_POWERPC_MPC8548E_v21
 #define CPU_POWERPC_MPC8548E_v10     CPU_POWERPC_e500v2_v10
 #define CPU_POWERPC_MPC8548E_v11     CPU_POWERPC_e500v2_v11
 #define CPU_POWERPC_MPC8548E_v20     CPU_POWERPC_e500v2_v20
 #define CPU_POWERPC_MPC8548E_v21     CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8555          CPU_POWERPC_MPC8555_v11
 #define CPU_POWERPC_MPC8555_v10      CPU_POWERPC_e500v2_v10
 #define CPU_POWERPC_MPC8555_v11      CPU_POWERPC_e500v2_v11
-#define CPU_POWERPC_MPC8555E         CPU_POWERPC_MPC8555E_v11
 #define CPU_POWERPC_MPC8555E_v10     CPU_POWERPC_e500v2_v10
 #define CPU_POWERPC_MPC8555E_v11     CPU_POWERPC_e500v2_v11
-#define CPU_POWERPC_MPC8560          CPU_POWERPC_MPC8560_v21
 #define CPU_POWERPC_MPC8560_v10      CPU_POWERPC_e500v2_v10
 #define CPU_POWERPC_MPC8560_v20      CPU_POWERPC_e500v2_v20
 #define CPU_POWERPC_MPC8560_v21      CPU_POWERPC_e500v2_v21
@@ -7509,64 +7492,47 @@ enum {
     POWERPC_SVR_8378E              = 0x80C40010 | POWERPC_SVR_E500,
     POWERPC_SVR_8379               = 0x80C30010 | POWERPC_SVR_E500,
     POWERPC_SVR_8379E              = 0x80C00010 | POWERPC_SVR_E500,
-#define POWERPC_SVR_8533             POWERPC_SVR_8533_v11
     POWERPC_SVR_8533_v10           = 0x80340010 | POWERPC_SVR_E500,
     POWERPC_SVR_8533_v11           = 0x80340011 | POWERPC_SVR_E500,
-#define POWERPC_SVR_8533E            POWERPC_SVR_8533E_v11
     POWERPC_SVR_8533E_v10          = 0x803C0010 | POWERPC_SVR_E500,
     POWERPC_SVR_8533E_v11          = 0x803C0011 | POWERPC_SVR_E500,
-#define POWERPC_SVR_8540             POWERPC_SVR_8540_v21
     POWERPC_SVR_8540_v10           = 0x80300010 | POWERPC_SVR_E500,
     POWERPC_SVR_8540_v20           = 0x80300020 | POWERPC_SVR_E500,
     POWERPC_SVR_8540_v21           = 0x80300021 | POWERPC_SVR_E500,
-#define POWERPC_SVR_8541             POWERPC_SVR_8541_v11
     POWERPC_SVR_8541_v10           = 0x80720010 | POWERPC_SVR_E500,
     POWERPC_SVR_8541_v11           = 0x80720011 | POWERPC_SVR_E500,
-#define POWERPC_SVR_8541E            POWERPC_SVR_8541E_v11
     POWERPC_SVR_8541E_v10          = 0x807A0010 | POWERPC_SVR_E500,
     POWERPC_SVR_8541E_v11          = 0x807A0011 | POWERPC_SVR_E500,
-#define POWERPC_SVR_8543             POWERPC_SVR_8543_v21
     POWERPC_SVR_8543_v10           = 0x80320010 | POWERPC_SVR_E500,
     POWERPC_SVR_8543_v11           = 0x80320011 | POWERPC_SVR_E500,
     POWERPC_SVR_8543_v20           = 0x80320020 | POWERPC_SVR_E500,
     POWERPC_SVR_8543_v21           = 0x80320021 | POWERPC_SVR_E500,
-#define POWERPC_SVR_8543E            POWERPC_SVR_8543E_v21
     POWERPC_SVR_8543E_v10          = 0x803A0010 | POWERPC_SVR_E500,
     POWERPC_SVR_8543E_v11          = 0x803A0011 | POWERPC_SVR_E500,
     POWERPC_SVR_8543E_v20          = 0x803A0020 | POWERPC_SVR_E500,
     POWERPC_SVR_8543E_v21          = 0x803A0021 | POWERPC_SVR_E500,
-#define POWERPC_SVR_8544             POWERPC_SVR_8544_v11
     POWERPC_SVR_8544_v10           = 0x80340110 | POWERPC_SVR_E500,
     POWERPC_SVR_8544_v11           = 0x80340111 | POWERPC_SVR_E500,
-#define POWERPC_SVR_8544E            POWERPC_SVR_8544E_v11
     POWERPC_SVR_8544E_v10          = 0x803C0110 | POWERPC_SVR_E500,
     POWERPC_SVR_8544E_v11          = 0x803C0111 | POWERPC_SVR_E500,
-#define POWERPC_SVR_8545             POWERPC_SVR_8545_v21
     POWERPC_SVR_8545_v20           = 0x80310220 | POWERPC_SVR_E500,
     POWERPC_SVR_8545_v21           = 0x80310221 | POWERPC_SVR_E500,
-#define POWERPC_SVR_8545E            POWERPC_SVR_8545E_v21
     POWERPC_SVR_8545E_v20          = 0x80390220 | POWERPC_SVR_E500,
     POWERPC_SVR_8545E_v21          = 0x80390221 | POWERPC_SVR_E500,
-#define POWERPC_SVR_8547E            POWERPC_SVR_8547E_v21
     POWERPC_SVR_8547E_v20          = 0x80390120 | POWERPC_SVR_E500,
     POWERPC_SVR_8547E_v21          = 0x80390121 | POWERPC_SVR_E500,
-#define POWERPC_SVR_8548             POWERPC_SVR_8548_v21
     POWERPC_SVR_8548_v10           = 0x80310010 | POWERPC_SVR_E500,
     POWERPC_SVR_8548_v11           = 0x80310011 | POWERPC_SVR_E500,
     POWERPC_SVR_8548_v20           = 0x80310020 | POWERPC_SVR_E500,
     POWERPC_SVR_8548_v21           = 0x80310021 | POWERPC_SVR_E500,
-#define POWERPC_SVR_8548E            POWERPC_SVR_8548E_v21
     POWERPC_SVR_8548E_v10          = 0x80390010 | POWERPC_SVR_E500,
     POWERPC_SVR_8548E_v11          = 0x80390011 | POWERPC_SVR_E500,
     POWERPC_SVR_8548E_v20          = 0x80390020 | POWERPC_SVR_E500,
     POWERPC_SVR_8548E_v21          = 0x80390021 | POWERPC_SVR_E500,
-#define POWERPC_SVR_8555             POWERPC_SVR_8555_v11
     POWERPC_SVR_8555_v10           = 0x80710010 | POWERPC_SVR_E500,
     POWERPC_SVR_8555_v11           = 0x80710011 | POWERPC_SVR_E500,
-#define POWERPC_SVR_8555E            POWERPC_SVR_8555_v11
     POWERPC_SVR_8555E_v10          = 0x80790010 | POWERPC_SVR_E500,
     POWERPC_SVR_8555E_v11          = 0x80790011 | POWERPC_SVR_E500,
-#define POWERPC_SVR_8560             POWERPC_SVR_8560_v21
     POWERPC_SVR_8560_v10           = 0x80700010 | POWERPC_SVR_E500,
     POWERPC_SVR_8560_v20           = 0x80700020 | POWERPC_SVR_E500,
     POWERPC_SVR_8560_v21           = 0x80700021 | POWERPC_SVR_E500,
@@ -8373,26 +8339,17 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF_SVR("e5500",    CPU_POWERPC_e5500, POWERPC_SVR_E500, e5500)
 #endif
     /* PowerPC e500 microcontrollers                                         */
-    /* MPC8533                                                               */
-    POWERPC_DEF_SVR("MPC8533",
-                    CPU_POWERPC_MPC8533,      POWERPC_SVR_8533,      e500v2)
     /* MPC8533 v1.0                                                          */
     POWERPC_DEF_SVR("MPC8533_v10",
                     CPU_POWERPC_MPC8533_v10,  POWERPC_SVR_8533_v10,  e500v2)
     /* MPC8533 v1.1                                                          */
     POWERPC_DEF_SVR("MPC8533_v11",
                     CPU_POWERPC_MPC8533_v11,  POWERPC_SVR_8533_v11,  e500v2)
-    /* MPC8533E                                                              */
-    POWERPC_DEF_SVR("MPC8533E",
-                    CPU_POWERPC_MPC8533E,     POWERPC_SVR_8533E,     e500v2)
     /* MPC8533E v1.0                                                         */
     POWERPC_DEF_SVR("MPC8533E_v10",
                     CPU_POWERPC_MPC8533E_v10, POWERPC_SVR_8533E_v10, e500v2)
     POWERPC_DEF_SVR("MPC8533E_v11",
                     CPU_POWERPC_MPC8533E_v11, POWERPC_SVR_8533E_v11, e500v2)
-    /* MPC8540                                                               */
-    POWERPC_DEF_SVR("MPC8540",
-                    CPU_POWERPC_MPC8540,      POWERPC_SVR_8540,      e500v1)
     /* MPC8540 v1.0                                                          */
     POWERPC_DEF_SVR("MPC8540_v10",
                     CPU_POWERPC_MPC8540_v10,  POWERPC_SVR_8540_v10,  e500v1)
@@ -8402,27 +8359,18 @@ static const ppc_def_t ppc_defs[] = {
     /* MPC8540 v2.1                                                          */
     POWERPC_DEF_SVR("MPC8540_v21",
                     CPU_POWERPC_MPC8540_v21,  POWERPC_SVR_8540_v21,  e500v1)
-    /* MPC8541                                                               */
-    POWERPC_DEF_SVR("MPC8541",
-                    CPU_POWERPC_MPC8541,      POWERPC_SVR_8541,      e500v1)
     /* MPC8541 v1.0                                                          */
     POWERPC_DEF_SVR("MPC8541_v10",
                     CPU_POWERPC_MPC8541_v10,  POWERPC_SVR_8541_v10,  e500v1)
     /* MPC8541 v1.1                                                          */
     POWERPC_DEF_SVR("MPC8541_v11",
                     CPU_POWERPC_MPC8541_v11,  POWERPC_SVR_8541_v11,  e500v1)
-    /* MPC8541E                                                              */
-    POWERPC_DEF_SVR("MPC8541E",
-                    CPU_POWERPC_MPC8541E,     POWERPC_SVR_8541E,     e500v1)
     /* MPC8541E v1.0                                                         */
     POWERPC_DEF_SVR("MPC8541E_v10",
                     CPU_POWERPC_MPC8541E_v10, POWERPC_SVR_8541E_v10, e500v1)
     /* MPC8541E v1.1                                                         */
     POWERPC_DEF_SVR("MPC8541E_v11",
                     CPU_POWERPC_MPC8541E_v11, POWERPC_SVR_8541E_v11, e500v1)
-    /* MPC8543                                                               */
-    POWERPC_DEF_SVR("MPC8543",
-                    CPU_POWERPC_MPC8543,      POWERPC_SVR_8543,      e500v2)
     /* MPC8543 v1.0                                                          */
     POWERPC_DEF_SVR("MPC8543_v10",
                     CPU_POWERPC_MPC8543_v10,  POWERPC_SVR_8543_v10,  e500v2)
@@ -8435,9 +8383,6 @@ static const ppc_def_t ppc_defs[] = {
     /* MPC8543 v2.1                                                          */
     POWERPC_DEF_SVR("MPC8543_v21",
                     CPU_POWERPC_MPC8543_v21,  POWERPC_SVR_8543_v21,  e500v2)
-    /* MPC8543E                                                              */
-    POWERPC_DEF_SVR("MPC8543E",
-                    CPU_POWERPC_MPC8543E,     POWERPC_SVR_8543E,     e500v2)
     /* MPC8543E v1.0                                                         */
     POWERPC_DEF_SVR("MPC8543E_v10",
                     CPU_POWERPC_MPC8543E_v10, POWERPC_SVR_8543E_v10, e500v2)
@@ -8450,54 +8395,36 @@ static const ppc_def_t ppc_defs[] = {
     /* MPC8543E v2.1                                                         */
     POWERPC_DEF_SVR("MPC8543E_v21",
                     CPU_POWERPC_MPC8543E_v21, POWERPC_SVR_8543E_v21, e500v2)
-    /* MPC8544                                                               */
-    POWERPC_DEF_SVR("MPC8544",
-                    CPU_POWERPC_MPC8544,      POWERPC_SVR_8544,      e500v2)
     /* MPC8544 v1.0                                                          */
     POWERPC_DEF_SVR("MPC8544_v10",
                     CPU_POWERPC_MPC8544_v10,  POWERPC_SVR_8544_v10,  e500v2)
     /* MPC8544 v1.1                                                          */
     POWERPC_DEF_SVR("MPC8544_v11",
                     CPU_POWERPC_MPC8544_v11,  POWERPC_SVR_8544_v11,  e500v2)
-    /* MPC8544E                                                              */
-    POWERPC_DEF_SVR("MPC8544E",
-                    CPU_POWERPC_MPC8544E,     POWERPC_SVR_8544E,     e500v2)
     /* MPC8544E v1.0                                                         */
     POWERPC_DEF_SVR("MPC8544E_v10",
                     CPU_POWERPC_MPC8544E_v10, POWERPC_SVR_8544E_v10, e500v2)
     /* MPC8544E v1.1                                                         */
     POWERPC_DEF_SVR("MPC8544E_v11",
                     CPU_POWERPC_MPC8544E_v11, POWERPC_SVR_8544E_v11, e500v2)
-    /* MPC8545                                                               */
-    POWERPC_DEF_SVR("MPC8545",
-                    CPU_POWERPC_MPC8545,      POWERPC_SVR_8545,      e500v2)
     /* MPC8545 v2.0                                                          */
     POWERPC_DEF_SVR("MPC8545_v20",
                     CPU_POWERPC_MPC8545_v20,  POWERPC_SVR_8545_v20,  e500v2)
     /* MPC8545 v2.1                                                          */
     POWERPC_DEF_SVR("MPC8545_v21",
                     CPU_POWERPC_MPC8545_v21,  POWERPC_SVR_8545_v21,  e500v2)
-    /* MPC8545E                                                              */
-    POWERPC_DEF_SVR("MPC8545E",
-                    CPU_POWERPC_MPC8545E,     POWERPC_SVR_8545E,     e500v2)
     /* MPC8545E v2.0                                                         */
     POWERPC_DEF_SVR("MPC8545E_v20",
                     CPU_POWERPC_MPC8545E_v20, POWERPC_SVR_8545E_v20, e500v2)
     /* MPC8545E v2.1                                                         */
     POWERPC_DEF_SVR("MPC8545E_v21",
                     CPU_POWERPC_MPC8545E_v21, POWERPC_SVR_8545E_v21, e500v2)
-    /* MPC8547E                                                              */
-    POWERPC_DEF_SVR("MPC8547E",
-                    CPU_POWERPC_MPC8547E,     POWERPC_SVR_8547E,     e500v2)
     /* MPC8547E v2.0                                                         */
     POWERPC_DEF_SVR("MPC8547E_v20",
                     CPU_POWERPC_MPC8547E_v20, POWERPC_SVR_8547E_v20, e500v2)
     /* MPC8547E v2.1                                                         */
     POWERPC_DEF_SVR("MPC8547E_v21",
                     CPU_POWERPC_MPC8547E_v21, POWERPC_SVR_8547E_v21, e500v2)
-    /* MPC8548                                                               */
-    POWERPC_DEF_SVR("MPC8548",
-                    CPU_POWERPC_MPC8548,      POWERPC_SVR_8548,      e500v2)
     /* MPC8548 v1.0                                                          */
     POWERPC_DEF_SVR("MPC8548_v10",
                     CPU_POWERPC_MPC8548_v10,  POWERPC_SVR_8548_v10,  e500v2)
@@ -8510,9 +8437,6 @@ static const ppc_def_t ppc_defs[] = {
     /* MPC8548 v2.1                                                          */
     POWERPC_DEF_SVR("MPC8548_v21",
                     CPU_POWERPC_MPC8548_v21,  POWERPC_SVR_8548_v21,  e500v2)
-    /* MPC8548E                                                              */
-    POWERPC_DEF_SVR("MPC8548E",
-                    CPU_POWERPC_MPC8548E,     POWERPC_SVR_8548E,     e500v2)
     /* MPC8548E v1.0                                                         */
     POWERPC_DEF_SVR("MPC8548E_v10",
                     CPU_POWERPC_MPC8548E_v10, POWERPC_SVR_8548E_v10, e500v2)
@@ -8525,27 +8449,18 @@ static const ppc_def_t ppc_defs[] = {
     /* MPC8548E v2.1                                                         */
     POWERPC_DEF_SVR("MPC8548E_v21",
                     CPU_POWERPC_MPC8548E_v21, POWERPC_SVR_8548E_v21, e500v2)
-    /* MPC8555                                                               */
-    POWERPC_DEF_SVR("MPC8555",
-                    CPU_POWERPC_MPC8555,      POWERPC_SVR_8555,      e500v2)
     /* MPC8555 v1.0                                                          */
     POWERPC_DEF_SVR("MPC8555_v10",
                     CPU_POWERPC_MPC8555_v10,  POWERPC_SVR_8555_v10,  e500v2)
     /* MPC8555 v1.1                                                          */
     POWERPC_DEF_SVR("MPC8555_v11",
                     CPU_POWERPC_MPC8555_v11,  POWERPC_SVR_8555_v11,  e500v2)
-    /* MPC8555E                                                              */
-    POWERPC_DEF_SVR("MPC8555E",
-                    CPU_POWERPC_MPC8555E,     POWERPC_SVR_8555E,     e500v2)
     /* MPC8555E v1.0                                                         */
     POWERPC_DEF_SVR("MPC8555E_v10",
                     CPU_POWERPC_MPC8555E_v10, POWERPC_SVR_8555E_v10, e500v2)
     /* MPC8555E v1.1                                                         */
     POWERPC_DEF_SVR("MPC8555E_v11",
                     CPU_POWERPC_MPC8555E_v11, POWERPC_SVR_8555E_v11, e500v2)
-    /* MPC8560                                                               */
-    POWERPC_DEF_SVR("MPC8560",
-                    CPU_POWERPC_MPC8560,      POWERPC_SVR_8560,      e500v2)
     /* MPC8560 v1.0                                                          */
     POWERPC_DEF_SVR("MPC8560_v10",
                     CPU_POWERPC_MPC8560_v10,  POWERPC_SVR_8560_v10,  e500v2)
@@ -9066,6 +8981,23 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
 
     { "PowerQUICC-II", "MPC82xx" },
     { "e500", "e500v2_v22" },
+    { "MPC8533", "MPC8533_v11" },
+    { "MPC8533E", "MPC8533E_v11" },
+    { "MPC8540", "MPC8540_v21" },
+    { "MPC8541", "MPC8541_v11" },
+    { "MPC8541E", "MPC8541E_v11" },
+    { "MPC8543", "MPC8543_v21" },
+    { "MPC8543E", "MPC8543E_v21" },
+    { "MPC8544", "MPC8544_v11" },
+    { "MPC8544E", "MPC8544E_v11" },
+    { "MPC8545", "MPC8545_v21" },
+    { "MPC8545E", "MPC8545E_v21" },
+    { "MPC8547E", "MPC8547E_v21" },
+    { "MPC8548", "MPC8548_v21" },
+    { "MPC8548E", "MPC8548E_v21" },
+    { "MPC8555", "MPC8555_v11" },
+    { "MPC8555E", "MPC8555E_v11" },
+    { "MPC8560", "MPC8560_v21" },
     { "601",  "601_v2" },
     { "601v", "601_v2" },
     { "Vanilla", "603" },
commit 91b5d028786b22bc4fe89b439ea55276ad09ec8a
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:21 2013 +0000

    target-ppc: Extract 604e alias
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 03284c7..c909410 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7246,7 +7246,6 @@ enum {
     CPU_POWERPC_603P               = 0x00070000,
     /* XXX: missing 0x00040303 (604) */
     CPU_POWERPC_604                = 0x00040103,
-#define CPU_POWERPC_604E             CPU_POWERPC_604E_v24
     /* XXX: missing 0x00091203 */
     /* XXX: missing 0x00092110 */
     /* XXX: missing 0x00092120 */
@@ -8631,8 +8630,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("603p",          CPU_POWERPC_603P,                   603E)
     /* PowerPC 604                                                           */
     POWERPC_DEF("604",           CPU_POWERPC_604,                    604)
-    /* PowerPC 604e (aka PID9)                                               */
-    POWERPC_DEF("604e",          CPU_POWERPC_604E,                   604E)
     /* PowerPC 604e v1.0                                                     */
     POWERPC_DEF("604e_v1.0",     CPU_POWERPC_604E_v10,               604E)
     /* PowerPC 604e v2.2                                                     */
@@ -9077,6 +9074,7 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "Vaillant", "603e7v" },
     { "603r", "603e7t" },
     { "Goldeneye", "603r" },
+    { "604e", "604e_v2.4" },
     { "Sirocco", "604e" },
     { "Mach5", "604r" },
     { "740", "740_v3.1" },
commit 336c86322d67dd3eb2e6d571b9d94c761b6988ea
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:24 2013 +0000

    target-ppc: Extract 601/601v aliases
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 69455c4..03284c7 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7225,10 +7225,8 @@ enum {
 #define CPU_POWERPC_MPC8641          CPU_POWERPC_e600
 #define CPU_POWERPC_MPC8641D         CPU_POWERPC_e600
     /* PowerPC 6xx cores */
-#define CPU_POWERPC_601              CPU_POWERPC_601_v2
     CPU_POWERPC_601_v0             = 0x00010001,
     CPU_POWERPC_601_v1             = 0x00010001,
-#define CPU_POWERPC_601v             CPU_POWERPC_601_v2
     CPU_POWERPC_601_v2             = 0x00010002,
     CPU_POWERPC_602                = 0x00050100,
     CPU_POWERPC_603                = 0x00030100,
@@ -8593,14 +8591,10 @@ static const ppc_def_t ppc_defs[] = {
                     CPU_POWERPC_MPC8641D,     POWERPC_SVR_8641D,     7400)
     /* 32 bits "classic" PowerPC                                             */
     /* PowerPC 6xx family                                                    */
-    /* PowerPC 601                                                           */
-    POWERPC_DEF("601",           CPU_POWERPC_601,                    601v)
     /* PowerPC 601v0                                                         */
     POWERPC_DEF("601_v0",        CPU_POWERPC_601_v0,                 601)
     /* PowerPC 601v1                                                         */
     POWERPC_DEF("601_v1",        CPU_POWERPC_601_v1,                 601)
-    /* PowerPC 601v                                                          */
-    POWERPC_DEF("601v",          CPU_POWERPC_601v,                   601v)
     /* PowerPC 601v2                                                         */
     POWERPC_DEF("601_v2",        CPU_POWERPC_601_v2,                 601v)
     /* PowerPC 602                                                           */
@@ -9075,6 +9069,8 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
 
     { "PowerQUICC-II", "MPC82xx" },
     { "e500", "e500v2_v22" },
+    { "601",  "601_v2" },
+    { "601v", "601_v2" },
     { "Vanilla", "603" },
     { "603e", "603e_v4.1" },
     { "Stretch", "603e" },
commit 4ae0e9d870f0e588a459529d9cc660e20f2ac5b3
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:23 2013 +0000

    target-ppc: Extract 603r alias
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 59a1644..69455c4 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7246,7 +7246,6 @@ enum {
     CPU_POWERPC_603E7v2            = 0x00070201,
     CPU_POWERPC_603E7              = 0x00070200,
     CPU_POWERPC_603P               = 0x00070000,
-#define CPU_POWERPC_603R             CPU_POWERPC_603E7t
     /* XXX: missing 0x00040303 (604) */
     CPU_POWERPC_604                = 0x00040103,
 #define CPU_POWERPC_604E             CPU_POWERPC_604E_v24
@@ -8636,8 +8635,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("603e7v2",       CPU_POWERPC_603E7v2,                603E)
     /* PowerPC 603p (aka PID7v)                                              */
     POWERPC_DEF("603p",          CPU_POWERPC_603P,                   603E)
-    /* PowerPC 603r (aka PID7t)                                              */
-    POWERPC_DEF("603r",          CPU_POWERPC_603R,                   603E)
     /* PowerPC 604                                                           */
     POWERPC_DEF("604",           CPU_POWERPC_604,                    604)
     /* PowerPC 604e (aka PID9)                                               */
@@ -9082,6 +9079,7 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "603e", "603e_v4.1" },
     { "Stretch", "603e" },
     { "Vaillant", "603e7v" },
+    { "603r", "603e7t" },
     { "Goldeneye", "603r" },
     { "Sirocco", "604e" },
     { "Mach5", "604r" },
commit 16a177333eaa041104f8eeb37d7bbc33d6753695
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:22 2013 +0000

    target-ppc: Extract 603e alias
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index e6be35c..59a1644 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7232,7 +7232,6 @@ enum {
     CPU_POWERPC_601_v2             = 0x00010002,
     CPU_POWERPC_602                = 0x00050100,
     CPU_POWERPC_603                = 0x00030100,
-#define CPU_POWERPC_603E             CPU_POWERPC_603E_v41
     CPU_POWERPC_603E_v11           = 0x00060101,
     CPU_POWERPC_603E_v12           = 0x00060102,
     CPU_POWERPC_603E_v13           = 0x00060103,
@@ -8609,8 +8608,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("602",           CPU_POWERPC_602,                    602)
     /* PowerPC 603                                                           */
     POWERPC_DEF("603",           CPU_POWERPC_603,                    603)
-    /* PowerPC 603e (aka PID6)                                               */
-    POWERPC_DEF("603e",          CPU_POWERPC_603E,                   603E)
     /* PowerPC 603e v1.1                                                     */
     POWERPC_DEF("603e_v1.1",     CPU_POWERPC_603E_v11,               603E)
     /* PowerPC 603e v1.2                                                     */
@@ -9082,6 +9079,7 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "PowerQUICC-II", "MPC82xx" },
     { "e500", "e500v2_v22" },
     { "Vanilla", "603" },
+    { "603e", "603e_v4.1" },
     { "Stretch", "603e" },
     { "Vaillant", "603e7v" },
     { "Goldeneye", "603r" },
commit 0446aecd56739760a2fa4b1dec342e3a4d5ebe9e
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:20 2013 +0000

    target-ppc: Extract 740/750 aliases
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 86db9a5..e6be35c 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7265,7 +7265,6 @@ enum {
 #endif
     /* PowerPC 740/750 cores (aka G3) */
     /* XXX: missing 0x00084202 */
-#define CPU_POWERPC_7x0              CPU_POWERPC_7x0_v31
     CPU_POWERPC_7x0_v10            = 0x00080100,
     CPU_POWERPC_7x0_v20            = 0x00080200,
     CPU_POWERPC_7x0_v21            = 0x00080201,
@@ -8659,10 +8658,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("604ev",         CPU_POWERPC_604EV,                  604E)
 #endif
     /* PowerPC 7xx family                                                    */
-    /* Generic PowerPC 740 (G3)                                              */
-    POWERPC_DEF("740",           CPU_POWERPC_7x0,                    740)
-    /* Generic PowerPC 750 (G3)                                              */
-    POWERPC_DEF("750",           CPU_POWERPC_7x0,                    750)
     /* PowerPC 740 v1.0 (G3)                                                 */
     POWERPC_DEF("740_v1.0",      CPU_POWERPC_7x0_v10,                740)
     /* PowerPC 750 v1.0 (G3)                                                 */
@@ -9092,7 +9087,9 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "Goldeneye", "603r" },
     { "Sirocco", "604e" },
     { "Mach5", "604r" },
+    { "740", "740_v3.1" },
     { "Arthur", "740" },
+    { "750", "750_v3.1" },
     { "Typhoon", "750" },
     { "G3",      "750" },
     { "Conan/Doyle", "750p" },
commit 8fc82f9e0d93b6d827a874a25dce6f6a226cef5d
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:19 2013 +0000

    target-ppc: Extract 750 aliases
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 5981d98..86db9a5 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7276,15 +7276,12 @@ enum {
     CPU_POWERPC_750E               = 0x00080200,
     CPU_POWERPC_7x0P               = 0x10080000,
     /* XXX: missing 0x00087010 (CL ?) */
-#define CPU_POWERPC_750CL            CPU_POWERPC_750CL_v20
     CPU_POWERPC_750CL_v10          = 0x00087200,
     CPU_POWERPC_750CL_v20          = 0x00087210, /* aka rev E */
-#define CPU_POWERPC_750CX            CPU_POWERPC_750CX_v22
     CPU_POWERPC_750CX_v10          = 0x00082100,
     CPU_POWERPC_750CX_v20          = 0x00082200,
     CPU_POWERPC_750CX_v21          = 0x00082201,
     CPU_POWERPC_750CX_v22          = 0x00082202,
-#define CPU_POWERPC_750CXE           CPU_POWERPC_750CXE_v31b
     CPU_POWERPC_750CXE_v21         = 0x00082211,
     CPU_POWERPC_750CXE_v22         = 0x00082212,
     CPU_POWERPC_750CXE_v23         = 0x00082213,
@@ -7295,18 +7292,15 @@ enum {
     CPU_POWERPC_750CXE_v31b        = 0x00083311,
     CPU_POWERPC_750CXR             = 0x00083410,
     CPU_POWERPC_750FL              = 0x70000203,
-#define CPU_POWERPC_750FX            CPU_POWERPC_750FX_v23
     CPU_POWERPC_750FX_v10          = 0x70000100,
     CPU_POWERPC_750FX_v20          = 0x70000200,
     CPU_POWERPC_750FX_v21          = 0x70000201,
     CPU_POWERPC_750FX_v22          = 0x70000202,
     CPU_POWERPC_750FX_v23          = 0x70000203,
     CPU_POWERPC_750GL              = 0x70020102,
-#define CPU_POWERPC_750GX            CPU_POWERPC_750GX_v12
     CPU_POWERPC_750GX_v10          = 0x70020100,
     CPU_POWERPC_750GX_v11          = 0x70020101,
     CPU_POWERPC_750GX_v12          = 0x70020102,
-#define CPU_POWERPC_750L             CPU_POWERPC_750L_v32 /* Aka LoneStar */
     CPU_POWERPC_750L_v20           = 0x00088200,
     CPU_POWERPC_750L_v21           = 0x00088201,
     CPU_POWERPC_750L_v22           = 0x00088202,
@@ -8701,14 +8695,10 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("740p",          CPU_POWERPC_7x0P,                   740)
     /* PowerPC 750P (G3)                                                     */
     POWERPC_DEF("750p",          CPU_POWERPC_7x0P,                   750)
-    /* PowerPC 750CL (G3 embedded)                                           */
-    POWERPC_DEF("750cl",         CPU_POWERPC_750CL,                  750cl)
     /* PowerPC 750CL v1.0                                                    */
     POWERPC_DEF("750cl_v1.0",    CPU_POWERPC_750CL_v10,              750cl)
     /* PowerPC 750CL v2.0                                                    */
     POWERPC_DEF("750cl_v2.0",    CPU_POWERPC_750CL_v20,              750cl)
-    /* PowerPC 750CX (G3 embedded)                                           */
-    POWERPC_DEF("750cx",         CPU_POWERPC_750CX,                  750cx)
     /* PowerPC 750CX v1.0 (G3 embedded)                                      */
     POWERPC_DEF("750cx_v1.0",    CPU_POWERPC_750CX_v10,              750cx)
     /* PowerPC 750CX v2.1 (G3 embedded)                                      */
@@ -8717,8 +8707,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("750cx_v2.1",    CPU_POWERPC_750CX_v21,              750cx)
     /* PowerPC 750CX v2.2 (G3 embedded)                                      */
     POWERPC_DEF("750cx_v2.2",    CPU_POWERPC_750CX_v22,              750cx)
-    /* PowerPC 750CXe (G3 embedded)                                          */
-    POWERPC_DEF("750cxe",        CPU_POWERPC_750CXE,                 750cx)
     /* PowerPC 750CXe v2.1 (G3 embedded)                                     */
     POWERPC_DEF("750cxe_v2.1",   CPU_POWERPC_750CXE_v21,             750cx)
     /* PowerPC 750CXe v2.2 (G3 embedded)                                     */
@@ -8739,8 +8727,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("750cxr",        CPU_POWERPC_750CXR,                 750cx)
     /* PowerPC 750FL (G3 embedded)                                           */
     POWERPC_DEF("750fl",         CPU_POWERPC_750FL,                  750fx)
-    /* PowerPC 750FX (G3 embedded)                                           */
-    POWERPC_DEF("750fx",         CPU_POWERPC_750FX,                  750fx)
     /* PowerPC 750FX v1.0 (G3 embedded)                                      */
     POWERPC_DEF("750fx_v1.0",    CPU_POWERPC_750FX_v10,              750fx)
     /* PowerPC 750FX v2.0 (G3 embedded)                                      */
@@ -8753,16 +8739,12 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("750fx_v2.3",    CPU_POWERPC_750FX_v23,              750fx)
     /* PowerPC 750GL (G3 embedded)                                           */
     POWERPC_DEF("750gl",         CPU_POWERPC_750GL,                  750gx)
-    /* PowerPC 750GX (G3 embedded)                                           */
-    POWERPC_DEF("750gx",         CPU_POWERPC_750GX,                  750gx)
     /* PowerPC 750GX v1.0 (G3 embedded)                                      */
     POWERPC_DEF("750gx_v1.0",    CPU_POWERPC_750GX_v10,              750gx)
     /* PowerPC 750GX v1.1 (G3 embedded)                                      */
     POWERPC_DEF("750gx_v1.1",    CPU_POWERPC_750GX_v11,              750gx)
     /* PowerPC 750GX v1.2 (G3 embedded)                                      */
     POWERPC_DEF("750gx_v1.2",    CPU_POWERPC_750GX_v12,              750gx)
-    /* PowerPC 750L (G3 embedded)                                            */
-    POWERPC_DEF("750l",          CPU_POWERPC_750L,                   750)
     /* PowerPC 750L v2.0 (G3 embedded)                                       */
     POWERPC_DEF("750l_v2.0",     CPU_POWERPC_750L_v20,               750)
     /* PowerPC 750L v2.1 (G3 embedded)                                       */
@@ -9114,6 +9096,12 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "Typhoon", "750" },
     { "G3",      "750" },
     { "Conan/Doyle", "750p" },
+    { "750cl", "750cl_v2.0" },
+    { "750cx", "750cx_v2.2" },
+    { "750cxe", "750cxe_v3.1b" },
+    { "750fx", "750fx_v2.3" },
+    { "750gx", "750gx_v1.2" },
+    { "750l", "750l_v3.2" },
     { "LoneStar", "750l" },
     { "745", "745_v2.8" },
     { "755", "755_v2.8" },
commit 80c7abd3171c2939020f01d5310c3bd066ccad19
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:18 2013 +0000

    target-ppc: Extract 7x5 aliases
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index a97dfb7..5981d98 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7313,7 +7313,6 @@ enum {
     CPU_POWERPC_750L_v30           = 0x00088300,
     CPU_POWERPC_750L_v32           = 0x00088302,
     /* PowerPC 745/755 cores */
-#define CPU_POWERPC_7x5              CPU_POWERPC_7x5_v28
     CPU_POWERPC_7x5_v10            = 0x00083100,
     CPU_POWERPC_7x5_v11            = 0x00083101,
     CPU_POWERPC_7x5_v20            = 0x00083200,
@@ -8774,10 +8773,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("750l_v3.0",     CPU_POWERPC_750L_v30,               750)
     /* PowerPC 750L v3.2 (G3 embedded)                                       */
     POWERPC_DEF("750l_v3.2",     CPU_POWERPC_750L_v32,               750)
-    /* Generic PowerPC 745                                                   */
-    POWERPC_DEF("745",           CPU_POWERPC_7x5,                    745)
-    /* Generic PowerPC 755                                                   */
-    POWERPC_DEF("755",           CPU_POWERPC_7x5,                    755)
     /* PowerPC 745 v1.0                                                      */
     POWERPC_DEF("745_v1.0",      CPU_POWERPC_7x5_v10,                745)
     /* PowerPC 755 v1.0                                                      */
@@ -9120,6 +9115,8 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "G3",      "750" },
     { "Conan/Doyle", "750p" },
     { "LoneStar", "750l" },
+    { "745", "745_v2.8" },
+    { "755", "755_v2.8" },
     { "Goldfinger", "755" },
     { "7400", "7400_v2.9" },
     { "Max", "7400" },
commit 06704e9ceb85916537c8398735aa18e24ebdad86
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:17 2013 +0000

    target-ppc: Extract 7400 alias
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 3fd8fd7..a97dfb7 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7330,7 +7330,6 @@ enum {
 #endif
     /* PowerPC 74xx cores (aka G4) */
     /* XXX: missing 0x000C1101 */
-#define CPU_POWERPC_7400             CPU_POWERPC_7400_v29
     CPU_POWERPC_7400_v10           = 0x000C0100,
     CPU_POWERPC_7400_v11           = 0x000C0101,
     CPU_POWERPC_7400_v20           = 0x000C0200,
@@ -8830,8 +8829,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("755p",          CPU_POWERPC_7x5P,                   755)
 #endif
     /* PowerPC 74xx family                                                   */
-    /* PowerPC 7400 (G4)                                                     */
-    POWERPC_DEF("7400",          CPU_POWERPC_7400,                   7400)
     /* PowerPC 7400 v1.0 (G4)                                                */
     POWERPC_DEF("7400_v1.0",     CPU_POWERPC_7400_v10,               7400)
     /* PowerPC 7400 v1.1 (G4)                                                */
@@ -9124,6 +9121,7 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "Conan/Doyle", "750p" },
     { "LoneStar", "750l" },
     { "Goldfinger", "755" },
+    { "7400", "7400_v2.9" },
     { "Max", "7400" },
     { "G4",  "7400" },
     { "7410", "7410_v1.4" },
commit 08546b912cc5f2940ef9e6d2d83abb43d295bbee
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:16 2013 +0000

    target-ppc: Extract 7410 alias
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 4a4444f..3fd8fd7 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7340,7 +7340,6 @@ enum {
     CPU_POWERPC_7400_v27           = 0x000C0207,
     CPU_POWERPC_7400_v28           = 0x000C0208,
     CPU_POWERPC_7400_v29           = 0x000C0209,
-#define CPU_POWERPC_7410             CPU_POWERPC_7410_v14
     CPU_POWERPC_7410_v10           = 0x800C1100,
     CPU_POWERPC_7410_v11           = 0x800C1101,
     CPU_POWERPC_7410_v12           = 0x800C1102, /* aka C */
@@ -8851,8 +8850,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("7400_v2.8",     CPU_POWERPC_7400_v28,               7400)
     /* PowerPC 7400 v2.9 (G4)                                                */
     POWERPC_DEF("7400_v2.9",     CPU_POWERPC_7400_v29,               7400)
-    /* PowerPC 7410 (G4)                                                     */
-    POWERPC_DEF("7410",          CPU_POWERPC_7410,                   7410)
     /* PowerPC 7410 v1.0 (G4)                                                */
     POWERPC_DEF("7410_v1.0",     CPU_POWERPC_7410_v10,               7410)
     /* PowerPC 7410 v1.1 (G4)                                                */
@@ -9129,6 +9126,7 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "Goldfinger", "755" },
     { "Max", "7400" },
     { "G4",  "7400" },
+    { "7410", "7410_v1.4" },
     { "Nitro", "7410" },
     { "7448", "7448_v2.1" },
     { "7450", "7450_v2.1" },
commit df502ce84527fc55544c66c2bd9a920480036cb6
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:15 2013 +0000

    target-ppc: Extract 7448 alias
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 7bc401b..4a4444f 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7346,7 +7346,6 @@ enum {
     CPU_POWERPC_7410_v12           = 0x800C1102, /* aka C */
     CPU_POWERPC_7410_v13           = 0x800C1103, /* aka D */
     CPU_POWERPC_7410_v14           = 0x800C1104, /* aka E */
-#define CPU_POWERPC_7448             CPU_POWERPC_7448_v21
     CPU_POWERPC_7448_v10           = 0x80040100,
     CPU_POWERPC_7448_v11           = 0x80040101,
     CPU_POWERPC_7448_v20           = 0x80040200,
@@ -8864,8 +8863,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("7410_v1.3",     CPU_POWERPC_7410_v13,               7410)
     /* PowerPC 7410 v1.4 (G4)                                                */
     POWERPC_DEF("7410_v1.4",     CPU_POWERPC_7410_v14,               7410)
-    /* PowerPC 7448 (G4)                                                     */
-    POWERPC_DEF("7448",          CPU_POWERPC_7448,                   7400)
     /* PowerPC 7448 v1.0 (G4)                                                */
     POWERPC_DEF("7448_v1.0",     CPU_POWERPC_7448_v10,               7400)
     /* PowerPC 7448 v1.1 (G4)                                                */
@@ -9133,6 +9130,7 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "Max", "7400" },
     { "G4",  "7400" },
     { "Nitro", "7410" },
+    { "7448", "7448_v2.1" },
     { "7450", "7450_v2.1" },
     { "Vger", "7450" },
     { "7441", "7441_v2.3" },
commit e9a7cf3bb386ce4b425e4dd154fa660e59939ab5
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:14 2013 +0000

    target-ppc: Extract 7450 alias
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index bd3076c..7bc401b 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7351,7 +7351,6 @@ enum {
     CPU_POWERPC_7448_v11           = 0x80040101,
     CPU_POWERPC_7448_v20           = 0x80040200,
     CPU_POWERPC_7448_v21           = 0x80040201,
-#define CPU_POWERPC_7450             CPU_POWERPC_7450_v21
     CPU_POWERPC_7450_v10           = 0x80000100,
     CPU_POWERPC_7450_v11           = 0x80000101,
     CPU_POWERPC_7450_v12           = 0x80000102,
@@ -8875,8 +8874,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("7448_v2.0",     CPU_POWERPC_7448_v20,               7400)
     /* PowerPC 7448 v2.1 (G4)                                                */
     POWERPC_DEF("7448_v2.1",     CPU_POWERPC_7448_v21,               7400)
-    /* PowerPC 7450 (G4)                                                     */
-    POWERPC_DEF("7450",          CPU_POWERPC_7450,                   7450)
     /* PowerPC 7450 v1.0 (G4)                                                */
     POWERPC_DEF("7450_v1.0",     CPU_POWERPC_7450_v10,               7450)
     /* PowerPC 7450 v1.1 (G4)                                                */
@@ -9136,6 +9133,7 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "Max", "7400" },
     { "G4",  "7400" },
     { "Nitro", "7410" },
+    { "7450", "7450_v2.1" },
     { "Vger", "7450" },
     { "7441", "7441_v2.3" },
     { "7451", "7451_v2.3" },
commit 078840e1bc1e21964fbf91548a9430a1a61195de
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:13 2013 +0000

    target-ppc: Extract 74x1 aliases
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index b7c9781..bd3076c 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7357,7 +7357,6 @@ enum {
     CPU_POWERPC_7450_v12           = 0x80000102,
     CPU_POWERPC_7450_v20           = 0x80000200, /* aka A, B, C, D: 2.04 */
     CPU_POWERPC_7450_v21           = 0x80000201, /* aka E */
-#define CPU_POWERPC_74x1             CPU_POWERPC_74x1_v23
     CPU_POWERPC_74x1_v23           = 0x80000203, /* aka G: 2.3 */
     /* XXX: this entry might be a bug in some documentation */
     CPU_POWERPC_74x1_v210          = 0x80000210, /* aka G: 2.3 ? */
@@ -8888,10 +8887,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("7450_v2.0",     CPU_POWERPC_7450_v20,               7450)
     /* PowerPC 7450 v2.1 (G4)                                                */
     POWERPC_DEF("7450_v2.1",     CPU_POWERPC_7450_v21,               7450)
-    /* PowerPC 7441 (G4)                                                     */
-    POWERPC_DEF("7441",          CPU_POWERPC_74x1,                   7440)
-    /* PowerPC 7451 (G4)                                                     */
-    POWERPC_DEF("7451",          CPU_POWERPC_74x1,                   7450)
     /* PowerPC 7441 v2.1 (G4)                                                */
     POWERPC_DEF("7441_v2.1",     CPU_POWERPC_7450_v21,               7440)
     /* PowerPC 7441 v2.3 (G4)                                                */
@@ -9142,6 +9137,8 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "G4",  "7400" },
     { "Nitro", "7410" },
     { "Vger", "7450" },
+    { "7441", "7441_v2.3" },
+    { "7451", "7451_v2.3" },
     { "7445", "7445_v3.2" },
     { "7455", "7455_v3.2" },
     { "Apollo6", "7455" },
commit d96c8a2344eea5d15556d86f986c4911fb875831
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:12 2013 +0000

    target-ppc: Extract 74x5 as aliases
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 27e625e..b7c9781 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7361,7 +7361,6 @@ enum {
     CPU_POWERPC_74x1_v23           = 0x80000203, /* aka G: 2.3 */
     /* XXX: this entry might be a bug in some documentation */
     CPU_POWERPC_74x1_v210          = 0x80000210, /* aka G: 2.3 ? */
-#define CPU_POWERPC_74x5             CPU_POWERPC_74x5_v32
     CPU_POWERPC_74x5_v10           = 0x80010100,
     /* XXX: missing 0x80010200 */
     CPU_POWERPC_74x5_v21           = 0x80010201, /* aka C: 2.1 */
@@ -8903,10 +8902,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("7441_v2.10",    CPU_POWERPC_74x1_v210,              7440)
     /* PowerPC 7451 v2.10 (G4)                                               */
     POWERPC_DEF("7451_v2.10",    CPU_POWERPC_74x1_v210,              7450)
-    /* PowerPC 7445 (G4)                                                     */
-    POWERPC_DEF("7445",          CPU_POWERPC_74x5,                   7445)
-    /* PowerPC 7455 (G4)                                                     */
-    POWERPC_DEF("7455",          CPU_POWERPC_74x5,                   7455)
     /* PowerPC 7445 v1.0 (G4)                                                */
     POWERPC_DEF("7445_v1.0",     CPU_POWERPC_74x5_v10,               7445)
     /* PowerPC 7455 v1.0 (G4)                                                */
@@ -9147,6 +9142,8 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "G4",  "7400" },
     { "Nitro", "7410" },
     { "Vger", "7450" },
+    { "7445", "7445_v3.2" },
+    { "7455", "7455_v3.2" },
     { "Apollo6", "7455" },
     { "7447", "7447_v1.2" },
     { "7457", "7457_v1.2" },
commit 4c739207ddaa2d4da96f887b802536117a49e6e8
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:11 2013 +0000

    target-ppc: Extract 74x7[A] aliases
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 86b5c91..27e625e 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7368,11 +7368,9 @@ enum {
     CPU_POWERPC_74x5_v32           = 0x80010302,
     CPU_POWERPC_74x5_v33           = 0x80010303, /* aka F: 3.3 */
     CPU_POWERPC_74x5_v34           = 0x80010304, /* aka G: 3.4 */
-#define CPU_POWERPC_74x7             CPU_POWERPC_74x7_v12
     CPU_POWERPC_74x7_v10           = 0x80020100, /* aka A: 1.0 */
     CPU_POWERPC_74x7_v11           = 0x80020101, /* aka B: 1.1 */
     CPU_POWERPC_74x7_v12           = 0x80020102, /* aka C: 1.2 */
-#define CPU_POWERPC_74x7A            CPU_POWERPC_74x7A_v12
     CPU_POWERPC_74x7A_v10          = 0x80030100, /* aka A: 1.0 */
     CPU_POWERPC_74x7A_v11          = 0x80030101, /* aka B: 1.1 */
     CPU_POWERPC_74x7A_v12          = 0x80030102, /* aka C: 1.2 */
@@ -8929,10 +8927,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("7445_v3.4",     CPU_POWERPC_74x5_v34,               7445)
     /* PowerPC 7455 v3.4 (G4)                                                */
     POWERPC_DEF("7455_v3.4",     CPU_POWERPC_74x5_v34,               7455)
-    /* PowerPC 7447 (G4)                                                     */
-    POWERPC_DEF("7447",          CPU_POWERPC_74x7,                   7445)
-    /* PowerPC 7457 (G4)                                                     */
-    POWERPC_DEF("7457",          CPU_POWERPC_74x7,                   7455)
     /* PowerPC 7447 v1.0 (G4)                                                */
     POWERPC_DEF("7447_v1.0",     CPU_POWERPC_74x7_v10,               7445)
     /* PowerPC 7457 v1.0 (G4)                                                */
@@ -8943,10 +8937,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("7457_v1.1",     CPU_POWERPC_74x7_v11,               7455)
     /* PowerPC 7457 v1.2 (G4)                                                */
     POWERPC_DEF("7457_v1.2",     CPU_POWERPC_74x7_v12,               7455)
-    /* PowerPC 7447A (G4)                                                    */
-    POWERPC_DEF("7447A",         CPU_POWERPC_74x7A,                  7445)
-    /* PowerPC 7457A (G4)                                                    */
-    POWERPC_DEF("7457A",         CPU_POWERPC_74x7A,                  7455)
     /* PowerPC 7447A v1.0 (G4)                                               */
     POWERPC_DEF("7447A_v1.0",    CPU_POWERPC_74x7A_v10,              7445)
     /* PowerPC 7457A v1.0 (G4)                                               */
@@ -9158,7 +9148,11 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "Nitro", "7410" },
     { "Vger", "7450" },
     { "Apollo6", "7455" },
+    { "7447", "7447_v1.2" },
+    { "7457", "7457_v1.2" },
     { "Apollo7", "7457" },
+    { "7447A", "7447A_v1.2" },
+    { "7457A", "7457A_v1.2" },
     { "Apollo7PM", "7457A_v1.0" },
 #if defined(TARGET_PPC64)
     { "Trident", "620" },
commit a7de06e17ecdd3b2cd57c2b6f01913e663365f49
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:10 2013 +0000

    target-ppc: Turn "ppc32" and "ppc64" CPUs into aliases
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index fb0a366..86b5c91 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -6798,32 +6798,6 @@ static void init_proc_620 (CPUPPCState *env)
 }
 #endif /* defined (TARGET_PPC64) */
 
-/* Default 32 bits PowerPC target will be 604 */
-#define CPU_POWERPC_PPC32     CPU_POWERPC_604
-#define POWERPC_INSNS_PPC32   POWERPC_INSNS_604
-#define POWERPC_INSNS2_PPC32  POWERPC_INSNS2_604
-#define POWERPC_MSRM_PPC32    POWERPC_MSRM_604
-#define POWERPC_MMU_PPC32     POWERPC_MMU_604
-#define POWERPC_EXCP_PPC32    POWERPC_EXCP_604
-#define POWERPC_INPUT_PPC32   POWERPC_INPUT_604
-#define POWERPC_BFDM_PPC32    POWERPC_BFDM_604
-#define POWERPC_FLAG_PPC32    POWERPC_FLAG_604
-#define check_pow_PPC32       check_pow_604
-#define init_proc_PPC32       init_proc_604
-
-/* Default 64 bits PowerPC target will be 970 FX */
-#define CPU_POWERPC_PPC64     CPU_POWERPC_970FX
-#define POWERPC_INSNS_PPC64   POWERPC_INSNS_970FX
-#define POWERPC_INSNS2_PPC64  POWERPC_INSNS2_970FX
-#define POWERPC_MSRM_PPC64    POWERPC_MSRM_970FX
-#define POWERPC_MMU_PPC64     POWERPC_MMU_970FX
-#define POWERPC_EXCP_PPC64    POWERPC_EXCP_970FX
-#define POWERPC_INPUT_PPC64   POWERPC_INPUT_970FX
-#define POWERPC_BFDM_PPC64    POWERPC_BFDM_970FX
-#define POWERPC_FLAG_PPC64    POWERPC_FLAG_970FX
-#define check_pow_PPC64       check_pow_970FX
-#define init_proc_PPC64       init_proc_970FX
-
 /*****************************************************************************/
 /* PVR definitions for most known PowerPC                                    */
 enum {
@@ -9111,11 +9085,6 @@ static const ppc_def_t ppc_defs[] = {
     /* PA PA6T */
     POWERPC_DEF("PA6T",          CPU_POWERPC_PA6T,                   PA6T)
 #endif
-    /* Generic PowerPCs                                                      */
-#if defined (TARGET_PPC64)
-    POWERPC_DEF("ppc64",         CPU_POWERPC_PPC64,                  PPC64)
-#endif
-    POWERPC_DEF("ppc32",         CPU_POWERPC_PPC32,                  PPC32)
 };
 
 typedef struct PowerPCCPUAlias {
@@ -9213,6 +9182,11 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "RSC2", "POWER2" },
     { "P2SC", "POWER2" },
 
+    /* Generic PowerPCs */
+#if defined(TARGET_PPC64)
+    { "ppc64", "970fx" },
+#endif
+    { "ppc32", "604" },
     { "ppc", "ppc32" },
     { "default", "ppc" },
 };
commit 8c00a9991ae759048c444a6836ce2206e4b0d372
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:09 2013 +0000

    target-ppc: Extract 440 aliases
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 8a3cf9f..fb0a366 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7013,17 +7013,13 @@ enum {
     CPU_POWERPC_440H6              = xxx,
 #endif
     /* PowerPC 440 microcontrolers */
-#define CPU_POWERPC_440EP            CPU_POWERPC_440EPb
     CPU_POWERPC_440EPa             = 0x42221850,
     CPU_POWERPC_440EPb             = 0x422218D3,
-#define CPU_POWERPC_440GP            CPU_POWERPC_440GPc
     CPU_POWERPC_440GPb             = 0x40120440,
     CPU_POWERPC_440GPc             = 0x40120481,
-#define CPU_POWERPC_440GR            CPU_POWERPC_440GRa
 #define CPU_POWERPC_440GRa           CPU_POWERPC_440EPb
     CPU_POWERPC_440GRX             = 0x200008D0,
 #define CPU_POWERPC_440EPX           CPU_POWERPC_440GRX
-#define CPU_POWERPC_440GX            CPU_POWERPC_440GXf
     CPU_POWERPC_440GXa             = 0x51B21850,
     CPU_POWERPC_440GXb             = 0x51B21851,
     CPU_POWERPC_440GXc             = 0x51B21892,
@@ -7922,8 +7918,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("440H6",         CPU_POWERPC_440H6,                  440Gx5)
 #endif
     /* PowerPC 440 microcontrolers                                           */
-    /* PowerPC 440 EP                                                        */
-    POWERPC_DEF("440EP",         CPU_POWERPC_440EP,                  440EP)
     /* PowerPC 440 EPa                                                       */
     POWERPC_DEF("440EPa",        CPU_POWERPC_440EPa,                 440EP)
     /* PowerPC 440 EPb                                                       */
@@ -7931,10 +7925,6 @@ static const ppc_def_t ppc_defs[] = {
     /* PowerPC 440 EPX                                                       */
     POWERPC_DEF("440EPX",        CPU_POWERPC_440EPX,                 440EP)
 #if defined(TODO_USER_ONLY)
-    /* PowerPC 440 GP                                                        */
-    POWERPC_DEF("440GP",         CPU_POWERPC_440GP,                  440GP)
-#endif
-#if defined(TODO_USER_ONLY)
     /* PowerPC 440 GPb                                                       */
     POWERPC_DEF("440GPb",        CPU_POWERPC_440GPb,                 440GP)
 #endif
@@ -7943,10 +7933,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("440GPc",        CPU_POWERPC_440GPc,                 440GP)
 #endif
 #if defined(TODO_USER_ONLY)
-    /* PowerPC 440 GR                                                        */
-    POWERPC_DEF("440GR",         CPU_POWERPC_440GR,                  440x5)
-#endif
-#if defined(TODO_USER_ONLY)
     /* PowerPC 440 GRa                                                       */
     POWERPC_DEF("440GRa",        CPU_POWERPC_440GRa,                 440x5)
 #endif
@@ -7955,10 +7941,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("440GRX",        CPU_POWERPC_440GRX,                 440x5)
 #endif
 #if defined(TODO_USER_ONLY)
-    /* PowerPC 440 GX                                                        */
-    POWERPC_DEF("440GX",         CPU_POWERPC_440GX,                  440EP)
-#endif
-#if defined(TODO_USER_ONLY)
     /* PowerPC 440 GXa                                                       */
     POWERPC_DEF("440GXa",        CPU_POWERPC_440GXa,                 440EP)
 #endif
@@ -9149,6 +9131,11 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "x2vp7", "x2vp4" },
     { "x2vp50", "x2vp20" },
 
+    { "440EP", "440EPb" },
+    { "440GP", "440GPc" },
+    { "440GR", "440GRa" },
+    { "440GX", "440GXf" },
+
     { "RCPU", "MPC5xx" },
     /* MPC5xx microcontrollers */
     { "MGT560", "MPC5xx" },
commit 8f43bc789c7ddd1a0f5b3cbc55cf67a1c6ae44e5
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:08 2013 +0000

    target-ppc: Extract 40x aliases
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 6a86e10..8a3cf9f 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -6852,8 +6852,6 @@ enum {
     CPU_POWERPC_XIPCHIP            = xxx,
 #endif
     /* PowerPC 403 family */
-    /* Generic PowerPC 403 */
-#define CPU_POWERPC_403              CPU_POWERPC_403GC
     /* PowerPC 403 microcontrollers */
     CPU_POWERPC_403GA              = 0x00200011,
     CPU_POWERPC_403GB              = 0x00200100,
@@ -6863,8 +6861,6 @@ enum {
     CPU_POWERPC_403GP              = xxx,
 #endif
     /* PowerPC 405 family */
-    /* Generic PowerPC 405 */
-#define CPU_POWERPC_405              CPU_POWERPC_405D4
     /* PowerPC 405 cores */
 #if 0
     CPU_POWERPC_405A3              = xxx,
@@ -6906,7 +6902,6 @@ enum {
 #endif
     /* PowerPC 405 microcontrolers */
     /* XXX: missing 0x200108a0 */
-#define CPU_POWERPC_405CR            CPU_POWERPC_405CRc
     CPU_POWERPC_405CRa             = 0x40110041,
     CPU_POWERPC_405CRb             = 0x401100C5,
     CPU_POWERPC_405CRc             = 0x40110145,
@@ -6918,7 +6913,6 @@ enum {
 #if 0
     CPU_POWERPC_405FX              = xxx,
 #endif
-#define CPU_POWERPC_405GP            CPU_POWERPC_405GPd
     CPU_POWERPC_405GPa             = 0x40110000,
     CPU_POWERPC_405GPb             = 0x40110040,
     CPU_POWERPC_405GPc             = 0x40110082,
@@ -6979,9 +6973,7 @@ enum {
 #endif
     /* Xilinx cores */
     CPU_POWERPC_X2VP4              = 0x20010820,
-#define CPU_POWERPC_X2VP7            CPU_POWERPC_X2VP4
     CPU_POWERPC_X2VP20             = 0x20010860,
-#define CPU_POWERPC_X2VP50           CPU_POWERPC_X2VP20
 #if 0
     CPU_POWERPC_ZL10310            = xxx,
 #endif
@@ -7701,8 +7693,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("Xipchip",       CPU_POWERPC_XIPCHIP,                401)
 #endif
     /* PowerPC 403 family                                                    */
-    /* Generic PowerPC 403                                                   */
-    POWERPC_DEF("403",           CPU_POWERPC_403,                    403)
     /* PowerPC 403 microcontrolers                                           */
     /* PowerPC 403 GA                                                        */
     POWERPC_DEF("403GA",         CPU_POWERPC_403GA,                  403)
@@ -7717,8 +7707,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("403GP",         CPU_POWERPC_403GP,                  403)
 #endif
     /* PowerPC 405 family                                                    */
-    /* Generic PowerPC 405                                                   */
-    POWERPC_DEF("405",           CPU_POWERPC_405,                    405)
     /* PowerPC 405 cores                                                     */
 #if defined (TODO)
     /* PowerPC 405 A3                                                        */
@@ -7773,8 +7761,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("405F6",         CPU_POWERPC_405F6,                  405)
 #endif
     /* PowerPC 405 microcontrolers                                           */
-    /* PowerPC 405 CR                                                        */
-    POWERPC_DEF("405CR",         CPU_POWERPC_405CR,                  405)
     /* PowerPC 405 CRa                                                       */
     POWERPC_DEF("405CRa",        CPU_POWERPC_405CRa,                 405)
     /* PowerPC 405 CRb                                                       */
@@ -7793,8 +7779,6 @@ static const ppc_def_t ppc_defs[] = {
     /* PowerPC 405 FX                                                        */
     POWERPC_DEF("405FX",         CPU_POWERPC_405FX,                  405)
 #endif
-    /* PowerPC 405 GP                                                        */
-    POWERPC_DEF("405GP",         CPU_POWERPC_405GP,                  405)
     /* PowerPC 405 GPa                                                       */
     POWERPC_DEF("405GPa",        CPU_POWERPC_405GPa,                 405)
     /* PowerPC 405 GPb                                                       */
@@ -7880,9 +7864,7 @@ static const ppc_def_t ppc_defs[] = {
 #endif
     /* Xilinx PowerPC 405 cores                                              */
     POWERPC_DEF("x2vp4",         CPU_POWERPC_X2VP4,                  405)
-    POWERPC_DEF("x2vp7",         CPU_POWERPC_X2VP7,                  405)
     POWERPC_DEF("x2vp20",        CPU_POWERPC_X2VP20,                 405)
-    POWERPC_DEF("x2vp50",        CPU_POWERPC_X2VP50,                 405)
 #if defined (TODO)
     /* Zarlink ZL10310                                                       */
     POWERPC_DEF("zl10310",       CPU_POWERPC_ZL10310,                405)
@@ -9160,6 +9142,13 @@ typedef struct PowerPCCPUAlias {
 } PowerPCCPUAlias;
 
 static const PowerPCCPUAlias ppc_cpu_aliases[] = {
+    { "403", "403GC" },
+    { "405", "405D4" },
+    { "405CR", "405CRc" },
+    { "405GP", "405GPd" },
+    { "x2vp7", "x2vp4" },
+    { "x2vp50", "x2vp20" },
+
     { "RCPU", "MPC5xx" },
     /* MPC5xx microcontrollers */
     { "MGT560", "MPC5xx" },
commit 20267b6f327ed2d7c54451034d234d67b1b410e9
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:07 2013 +0000

    target-ppc: Extract MGT823/MPC8xx as aliases
    
    They used different PVRs but were defined to MPC8xx.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 6a5f7e8..6a86e10 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7059,21 +7059,6 @@ enum {
     CPU_POWERPC_MPC5xx             = 0x00020020,
     /* PowerPC MPC 8xx cores (aka PowerQUICC) */
     CPU_POWERPC_MPC8xx             = 0x00500000,
-#define CPU_POWERPC_MGT823           CPU_POWERPC_MPC8xx
-#define CPU_POWERPC_MPC821           CPU_POWERPC_MPC8xx
-#define CPU_POWERPC_MPC823           CPU_POWERPC_MPC8xx
-#define CPU_POWERPC_MPC850           CPU_POWERPC_MPC8xx
-#define CPU_POWERPC_MPC852T          CPU_POWERPC_MPC8xx
-#define CPU_POWERPC_MPC855T          CPU_POWERPC_MPC8xx
-#define CPU_POWERPC_MPC857           CPU_POWERPC_MPC8xx
-#define CPU_POWERPC_MPC859           CPU_POWERPC_MPC8xx
-#define CPU_POWERPC_MPC860           CPU_POWERPC_MPC8xx
-#define CPU_POWERPC_MPC862           CPU_POWERPC_MPC8xx
-#define CPU_POWERPC_MPC866           CPU_POWERPC_MPC8xx
-#define CPU_POWERPC_MPC870           CPU_POWERPC_MPC8xx
-#define CPU_POWERPC_MPC875           CPU_POWERPC_MPC8xx
-#define CPU_POWERPC_MPC880           CPU_POWERPC_MPC8xx
-#define CPU_POWERPC_MPC885           CPU_POWERPC_MPC8xx
     /* G2 cores (aka PowerQUICC-II) */
     CPU_POWERPC_G2                 = 0x00810011,
     CPU_POWERPC_G2H4               = 0x80811010,
@@ -8048,67 +8033,6 @@ static const ppc_def_t ppc_defs[] = {
     /* Generic MPC8xx core                                                   */
     POWERPC_DEF("MPC8xx",        CPU_POWERPC_MPC8xx,                 MPC8xx)
 #endif
-    /* MPC8xx microcontrollers                                               */
-#if defined(TODO_USER_ONLY)
-    /* MGT823                                                                */
-    POWERPC_DEF("MGT823",        CPU_POWERPC_MGT823,                 MPC8xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC821                                                                */
-    POWERPC_DEF("MPC821",        CPU_POWERPC_MPC821,                 MPC8xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC823                                                                */
-    POWERPC_DEF("MPC823",        CPU_POWERPC_MPC823,                 MPC8xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC850                                                                */
-    POWERPC_DEF("MPC850",        CPU_POWERPC_MPC850,                 MPC8xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC852T                                                               */
-    POWERPC_DEF("MPC852T",       CPU_POWERPC_MPC852T,                MPC8xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC855T                                                               */
-    POWERPC_DEF("MPC855T",       CPU_POWERPC_MPC855T,                MPC8xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC857                                                                */
-    POWERPC_DEF("MPC857",        CPU_POWERPC_MPC857,                 MPC8xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC859                                                                */
-    POWERPC_DEF("MPC859",        CPU_POWERPC_MPC859,                 MPC8xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC860                                                                */
-    POWERPC_DEF("MPC860",        CPU_POWERPC_MPC860,                 MPC8xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC862                                                                */
-    POWERPC_DEF("MPC862",        CPU_POWERPC_MPC862,                 MPC8xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC866                                                                */
-    POWERPC_DEF("MPC866",        CPU_POWERPC_MPC866,                 MPC8xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC870                                                                */
-    POWERPC_DEF("MPC870",        CPU_POWERPC_MPC870,                 MPC8xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC875                                                                */
-    POWERPC_DEF("MPC875",        CPU_POWERPC_MPC875,                 MPC8xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC880                                                                */
-    POWERPC_DEF("MPC880",        CPU_POWERPC_MPC880,                 MPC8xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC885                                                                */
-    POWERPC_DEF("MPC885",        CPU_POWERPC_MPC885,                 MPC8xx)
-#endif
     /* MPC82xx family (aka PowerQUICC-II)                                    */
     /* Generic MPC52xx core                                                  */
     POWERPC_DEF_SVR("MPC52xx",
@@ -9253,6 +9177,23 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "MPC566", "MPC5xx" },
 
     { "PowerQUICC", "MPC8xx" },
+    /* MPC8xx microcontrollers */
+    { "MGT823", "MPC8xx" },
+    { "MPC821", "MPC8xx" },
+    { "MPC823", "MPC8xx" },
+    { "MPC850", "MPC8xx" },
+    { "MPC852T", "MPC8xx" },
+    { "MPC855T", "MPC8xx" },
+    { "MPC857", "MPC8xx" },
+    { "MPC859", "MPC8xx" },
+    { "MPC860", "MPC8xx" },
+    { "MPC862", "MPC8xx" },
+    { "MPC866", "MPC8xx" },
+    { "MPC870", "MPC8xx" },
+    { "MPC875", "MPC8xx" },
+    { "MPC880", "MPC8xx" },
+    { "MPC885", "MPC8xx" },
+
     { "PowerQUICC-II", "MPC82xx" },
     { "e500", "e500v2_v22" },
     { "Vanilla", "603" },
commit e0b9a74e53c012953c54f4bd5a09e20cf1cc48a7
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:06 2013 +0000

    target-ppc: Extract MPC5xx aliases
    
    Their PVR differed but was defined to MPC5xx.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 8923105..6a5f7e8 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7057,19 +7057,6 @@ enum {
     /* Freescale embedded PowerPC cores */
     /* PowerPC MPC 5xx cores (aka RCPU) */
     CPU_POWERPC_MPC5xx             = 0x00020020,
-#define CPU_POWERPC_MGT560           CPU_POWERPC_MPC5xx
-#define CPU_POWERPC_MPC509           CPU_POWERPC_MPC5xx
-#define CPU_POWERPC_MPC533           CPU_POWERPC_MPC5xx
-#define CPU_POWERPC_MPC534           CPU_POWERPC_MPC5xx
-#define CPU_POWERPC_MPC555           CPU_POWERPC_MPC5xx
-#define CPU_POWERPC_MPC556           CPU_POWERPC_MPC5xx
-#define CPU_POWERPC_MPC560           CPU_POWERPC_MPC5xx
-#define CPU_POWERPC_MPC561           CPU_POWERPC_MPC5xx
-#define CPU_POWERPC_MPC562           CPU_POWERPC_MPC5xx
-#define CPU_POWERPC_MPC563           CPU_POWERPC_MPC5xx
-#define CPU_POWERPC_MPC564           CPU_POWERPC_MPC5xx
-#define CPU_POWERPC_MPC565           CPU_POWERPC_MPC5xx
-#define CPU_POWERPC_MPC566           CPU_POWERPC_MPC5xx
     /* PowerPC MPC 8xx cores (aka PowerQUICC) */
     CPU_POWERPC_MPC8xx             = 0x00500000,
 #define CPU_POWERPC_MGT823           CPU_POWERPC_MPC8xx
@@ -8056,59 +8043,6 @@ static const ppc_def_t ppc_defs[] = {
     /* Generic MPC5xx core                                                   */
     POWERPC_DEF("MPC5xx",        CPU_POWERPC_MPC5xx,                 MPC5xx)
 #endif
-    /* MPC5xx microcontrollers                                               */
-#if defined(TODO_USER_ONLY)
-    /* MGT560                                                                */
-    POWERPC_DEF("MGT560",        CPU_POWERPC_MGT560,                 MPC5xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC509                                                                */
-    POWERPC_DEF("MPC509",        CPU_POWERPC_MPC509,                 MPC5xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC533                                                                */
-    POWERPC_DEF("MPC533",        CPU_POWERPC_MPC533,                 MPC5xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC534                                                                */
-    POWERPC_DEF("MPC534",        CPU_POWERPC_MPC534,                 MPC5xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC555                                                                */
-    POWERPC_DEF("MPC555",        CPU_POWERPC_MPC555,                 MPC5xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC556                                                                */
-    POWERPC_DEF("MPC556",        CPU_POWERPC_MPC556,                 MPC5xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC560                                                                */
-    POWERPC_DEF("MPC560",        CPU_POWERPC_MPC560,                 MPC5xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC561                                                                */
-    POWERPC_DEF("MPC561",        CPU_POWERPC_MPC561,                 MPC5xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC562                                                                */
-    POWERPC_DEF("MPC562",        CPU_POWERPC_MPC562,                 MPC5xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC563                                                                */
-    POWERPC_DEF("MPC563",        CPU_POWERPC_MPC563,                 MPC5xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC564                                                                */
-    POWERPC_DEF("MPC564",        CPU_POWERPC_MPC564,                 MPC5xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC565                                                                */
-    POWERPC_DEF("MPC565",        CPU_POWERPC_MPC565,                 MPC5xx)
-#endif
-#if defined(TODO_USER_ONLY)
-    /* MPC566                                                                */
-    POWERPC_DEF("MPC566",        CPU_POWERPC_MPC566,                 MPC5xx)
-#endif
     /* MPC8xx family (aka PowerQUICC)                                        */
 #if defined(TODO_USER_ONLY)
     /* Generic MPC8xx core                                                   */
@@ -9303,6 +9237,21 @@ typedef struct PowerPCCPUAlias {
 
 static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "RCPU", "MPC5xx" },
+    /* MPC5xx microcontrollers */
+    { "MGT560", "MPC5xx" },
+    { "MPC509", "MPC5xx" },
+    { "MPC533", "MPC5xx" },
+    { "MPC534", "MPC5xx" },
+    { "MPC555", "MPC5xx" },
+    { "MPC556", "MPC5xx" },
+    { "MPC560", "MPC5xx" },
+    { "MPC561", "MPC5xx" },
+    { "MPC562", "MPC5xx" },
+    { "MPC563", "MPC5xx" },
+    { "MPC564", "MPC5xx" },
+    { "MPC565", "MPC5xx" },
+    { "MPC566", "MPC5xx" },
+
     { "PowerQUICC", "MPC8xx" },
     { "PowerQUICC-II", "MPC82xx" },
     { "e500", "e500v2_v22" },
commit f7851859d2af38bbdf953269a7e2a9b4681b4253
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:05 2013 +0000

    target-ppc: Make -cpu "ppc" an alias to "ppc32"
    
    Drop the #if 0'ed alternative to make it "ppc64" for TARGET_PPC64.
    If we ever want to change it, we can more easily do so now.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 862f40a..8923105 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -6824,33 +6824,6 @@ static void init_proc_620 (CPUPPCState *env)
 #define check_pow_PPC64       check_pow_970FX
 #define init_proc_PPC64       init_proc_970FX
 
-/* Default PowerPC target will be PowerPC 32 */
-#if defined (TARGET_PPC64) && 0 // XXX: TODO
-#define CPU_POWERPC_DEFAULT    CPU_POWERPC_PPC64
-#define POWERPC_INSNS_DEFAULT  POWERPC_INSNS_PPC64
-#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS2_PPC64
-#define POWERPC_MSRM_DEFAULT   POWERPC_MSRM_PPC64
-#define POWERPC_MMU_DEFAULT    POWERPC_MMU_PPC64
-#define POWERPC_EXCP_DEFAULT   POWERPC_EXCP_PPC64
-#define POWERPC_INPUT_DEFAULT  POWERPC_INPUT_PPC64
-#define POWERPC_BFDM_DEFAULT   POWERPC_BFDM_PPC64
-#define POWERPC_FLAG_DEFAULT   POWERPC_FLAG_PPC64
-#define check_pow_DEFAULT      check_pow_PPC64
-#define init_proc_DEFAULT      init_proc_PPC64
-#else
-#define CPU_POWERPC_DEFAULT    CPU_POWERPC_PPC32
-#define POWERPC_INSNS_DEFAULT  POWERPC_INSNS_PPC32
-#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS2_PPC32
-#define POWERPC_MSRM_DEFAULT   POWERPC_MSRM_PPC32
-#define POWERPC_MMU_DEFAULT    POWERPC_MMU_PPC32
-#define POWERPC_EXCP_DEFAULT   POWERPC_EXCP_PPC32
-#define POWERPC_INPUT_DEFAULT  POWERPC_INPUT_PPC32
-#define POWERPC_BFDM_DEFAULT   POWERPC_BFDM_PPC32
-#define POWERPC_FLAG_DEFAULT   POWERPC_FLAG_PPC32
-#define check_pow_DEFAULT      check_pow_PPC32
-#define init_proc_DEFAULT      init_proc_PPC32
-#endif
-
 /*****************************************************************************/
 /* PVR definitions for most known PowerPC                                    */
 enum {
@@ -9321,7 +9294,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("ppc64",         CPU_POWERPC_PPC64,                  PPC64)
 #endif
     POWERPC_DEF("ppc32",         CPU_POWERPC_PPC32,                  PPC32)
-    POWERPC_DEF("ppc",           CPU_POWERPC_DEFAULT,                DEFAULT)
 };
 
 typedef struct PowerPCCPUAlias {
@@ -9375,6 +9347,7 @@ static const PowerPCCPUAlias ppc_cpu_aliases[] = {
     { "RSC2", "POWER2" },
     { "P2SC", "POWER2" },
 
+    { "ppc", "ppc32" },
     { "default", "ppc" },
 };
 
commit fd5ed418c7703bb7403f89f1474b0fe633f989cf
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:04 2013 +0000

    target-ppc: Extract aliases from definitions list
    
    Move definitions that were 100% identical except for the name into a
    list of aliases so that we don't register duplicate CPU types.
    Drop the accompanying comments since they don't really add value.
    
    We need to support recursive lookup due to code names referencing a
    generic name referencing a specific model revision.
    
    List aliases separately for -cpu ?.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 3f75bef..862f40a 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8083,10 +8083,6 @@ static const ppc_def_t ppc_defs[] = {
     /* Generic MPC5xx core                                                   */
     POWERPC_DEF("MPC5xx",        CPU_POWERPC_MPC5xx,                 MPC5xx)
 #endif
-#if defined(TODO_USER_ONLY)
-    /* Codename for MPC5xx core                                              */
-    POWERPC_DEF("RCPU",          CPU_POWERPC_MPC5xx,                 MPC5xx)
-#endif
     /* MPC5xx microcontrollers                                               */
 #if defined(TODO_USER_ONLY)
     /* MGT560                                                                */
@@ -8145,10 +8141,6 @@ static const ppc_def_t ppc_defs[] = {
     /* Generic MPC8xx core                                                   */
     POWERPC_DEF("MPC8xx",        CPU_POWERPC_MPC8xx,                 MPC8xx)
 #endif
-#if defined(TODO_USER_ONLY)
-    /* Codename for MPC8xx core                                              */
-    POWERPC_DEF("PowerQUICC",    CPU_POWERPC_MPC8xx,                 MPC8xx)
-#endif
     /* MPC8xx microcontrollers                                               */
 #if defined(TODO_USER_ONLY)
     /* MGT823                                                                */
@@ -8216,8 +8208,6 @@ static const ppc_def_t ppc_defs[] = {
                     CPU_POWERPC_MPC52xx,      POWERPC_SVR_52xx,      G2LE)
     /* Generic MPC82xx core                                                  */
     POWERPC_DEF("MPC82xx",       CPU_POWERPC_MPC82xx,                G2)
-    /* Codename for MPC82xx                                                  */
-    POWERPC_DEF("PowerQUICC-II", CPU_POWERPC_MPC82xx,                G2)
     /* PowerPC G2 core                                                       */
     POWERPC_DEF("G2",            CPU_POWERPC_G2,                     G2)
     /* PowerPC G2 H4 core                                                    */
@@ -8612,8 +8602,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF_SVR("MPC8379E",
                     CPU_POWERPC_MPC837x,      POWERPC_SVR_8379E,     e300)
     /* e500 family                                                           */
-    /* PowerPC e500 core                                                     */
-    POWERPC_DEF("e500",          CPU_POWERPC_e500v2_v22,             e500v2)
     /* PowerPC e500v1 core                                                   */
     POWERPC_DEF("e500v1",        CPU_POWERPC_e500v1,                 e500v1)
     /* PowerPC e500 v1.0 core                                                */
@@ -8868,12 +8856,8 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("602",           CPU_POWERPC_602,                    602)
     /* PowerPC 603                                                           */
     POWERPC_DEF("603",           CPU_POWERPC_603,                    603)
-    /* Code name for PowerPC 603                                             */
-    POWERPC_DEF("Vanilla",       CPU_POWERPC_603,                    603)
     /* PowerPC 603e (aka PID6)                                               */
     POWERPC_DEF("603e",          CPU_POWERPC_603E,                   603E)
-    /* Code name for PowerPC 603e                                            */
-    POWERPC_DEF("Stretch",       CPU_POWERPC_603E,                   603E)
     /* PowerPC 603e v1.1                                                     */
     POWERPC_DEF("603e_v1.1",     CPU_POWERPC_603E_v11,               603E)
     /* PowerPC 603e v1.2                                                     */
@@ -8896,8 +8880,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("603e7t",        CPU_POWERPC_603E7t,                 603E)
     /* PowerPC 603e7v                                                        */
     POWERPC_DEF("603e7v",        CPU_POWERPC_603E7v,                 603E)
-    /* Code name for PowerPC 603ev                                           */
-    POWERPC_DEF("Vaillant",      CPU_POWERPC_603E7v,                 603E)
     /* PowerPC 603e7v1                                                       */
     POWERPC_DEF("603e7v1",       CPU_POWERPC_603E7v1,                603E)
     /* PowerPC 603e7v2                                                       */
@@ -8906,14 +8888,10 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("603p",          CPU_POWERPC_603P,                   603E)
     /* PowerPC 603r (aka PID7t)                                              */
     POWERPC_DEF("603r",          CPU_POWERPC_603R,                   603E)
-    /* Code name for PowerPC 603r                                            */
-    POWERPC_DEF("Goldeneye",     CPU_POWERPC_603R,                   603E)
     /* PowerPC 604                                                           */
     POWERPC_DEF("604",           CPU_POWERPC_604,                    604)
     /* PowerPC 604e (aka PID9)                                               */
     POWERPC_DEF("604e",          CPU_POWERPC_604E,                   604E)
-    /* Code name for PowerPC 604e                                            */
-    POWERPC_DEF("Sirocco",       CPU_POWERPC_604E,                   604E)
     /* PowerPC 604e v1.0                                                     */
     POWERPC_DEF("604e_v1.0",     CPU_POWERPC_604E_v10,               604E)
     /* PowerPC 604e v2.2                                                     */
@@ -8922,8 +8900,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("604e_v2.4",     CPU_POWERPC_604E_v24,               604E)
     /* PowerPC 604r (aka PIDA)                                               */
     POWERPC_DEF("604r",          CPU_POWERPC_604R,                   604E)
-    /* Code name for PowerPC 604r                                            */
-    POWERPC_DEF("Mach5",         CPU_POWERPC_604R,                   604E)
 #if defined(TODO)
     /* PowerPC 604ev                                                         */
     POWERPC_DEF("604ev",         CPU_POWERPC_604EV,                  604E)
@@ -8931,14 +8907,8 @@ static const ppc_def_t ppc_defs[] = {
     /* PowerPC 7xx family                                                    */
     /* Generic PowerPC 740 (G3)                                              */
     POWERPC_DEF("740",           CPU_POWERPC_7x0,                    740)
-    /* Code name for PowerPC 740                                             */
-    POWERPC_DEF("Arthur",        CPU_POWERPC_7x0,                    740)
     /* Generic PowerPC 750 (G3)                                              */
     POWERPC_DEF("750",           CPU_POWERPC_7x0,                    750)
-    /* Code name for PowerPC 750                                             */
-    POWERPC_DEF("Typhoon",       CPU_POWERPC_7x0,                    750)
-    /* PowerPC 740/750 is also known as G3                                   */
-    POWERPC_DEF("G3",            CPU_POWERPC_7x0,                    750)
     /* PowerPC 740 v1.0 (G3)                                                 */
     POWERPC_DEF("740_v1.0",      CPU_POWERPC_7x0_v10,                740)
     /* PowerPC 750 v1.0 (G3)                                                 */
@@ -8971,8 +8941,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("740p",          CPU_POWERPC_7x0P,                   740)
     /* PowerPC 750P (G3)                                                     */
     POWERPC_DEF("750p",          CPU_POWERPC_7x0P,                   750)
-    /* Code name for PowerPC 740P/750P (G3)                                  */
-    POWERPC_DEF("Conan/Doyle",   CPU_POWERPC_7x0P,                   750)
     /* PowerPC 750CL (G3 embedded)                                           */
     POWERPC_DEF("750cl",         CPU_POWERPC_750CL,                  750cl)
     /* PowerPC 750CL v1.0                                                    */
@@ -9035,8 +9003,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("750gx_v1.2",    CPU_POWERPC_750GX_v12,              750gx)
     /* PowerPC 750L (G3 embedded)                                            */
     POWERPC_DEF("750l",          CPU_POWERPC_750L,                   750)
-    /* Code name for PowerPC 750L (G3 embedded)                              */
-    POWERPC_DEF("LoneStar",      CPU_POWERPC_750L,                   750)
     /* PowerPC 750L v2.0 (G3 embedded)                                       */
     POWERPC_DEF("750l_v2.0",     CPU_POWERPC_750L_v20,               750)
     /* PowerPC 750L v2.1 (G3 embedded)                                       */
@@ -9051,8 +9017,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("745",           CPU_POWERPC_7x5,                    745)
     /* Generic PowerPC 755                                                   */
     POWERPC_DEF("755",           CPU_POWERPC_7x5,                    755)
-    /* Code name for PowerPC 745/755                                         */
-    POWERPC_DEF("Goldfinger",    CPU_POWERPC_7x5,                    755)
     /* PowerPC 745 v1.0                                                      */
     POWERPC_DEF("745_v1.0",      CPU_POWERPC_7x5_v10,                745)
     /* PowerPC 755 v1.0                                                      */
@@ -9106,10 +9070,6 @@ static const ppc_def_t ppc_defs[] = {
     /* PowerPC 74xx family                                                   */
     /* PowerPC 7400 (G4)                                                     */
     POWERPC_DEF("7400",          CPU_POWERPC_7400,                   7400)
-    /* Code name for PowerPC 7400                                            */
-    POWERPC_DEF("Max",           CPU_POWERPC_7400,                   7400)
-    /* PowerPC 74xx is also well known as G4                                 */
-    POWERPC_DEF("G4",            CPU_POWERPC_7400,                   7400)
     /* PowerPC 7400 v1.0 (G4)                                                */
     POWERPC_DEF("7400_v1.0",     CPU_POWERPC_7400_v10,               7400)
     /* PowerPC 7400 v1.1 (G4)                                                */
@@ -9130,8 +9090,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("7400_v2.9",     CPU_POWERPC_7400_v29,               7400)
     /* PowerPC 7410 (G4)                                                     */
     POWERPC_DEF("7410",          CPU_POWERPC_7410,                   7410)
-    /* Code name for PowerPC 7410                                            */
-    POWERPC_DEF("Nitro",         CPU_POWERPC_7410,                   7410)
     /* PowerPC 7410 v1.0 (G4)                                                */
     POWERPC_DEF("7410_v1.0",     CPU_POWERPC_7410_v10,               7410)
     /* PowerPC 7410 v1.1 (G4)                                                */
@@ -9154,8 +9112,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("7448_v2.1",     CPU_POWERPC_7448_v21,               7400)
     /* PowerPC 7450 (G4)                                                     */
     POWERPC_DEF("7450",          CPU_POWERPC_7450,                   7450)
-    /* Code name for PowerPC 7450                                            */
-    POWERPC_DEF("Vger",          CPU_POWERPC_7450,                   7450)
     /* PowerPC 7450 v1.0 (G4)                                                */
     POWERPC_DEF("7450_v1.0",     CPU_POWERPC_7450_v10,               7450)
     /* PowerPC 7450 v1.1 (G4)                                                */
@@ -9184,8 +9140,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("7445",          CPU_POWERPC_74x5,                   7445)
     /* PowerPC 7455 (G4)                                                     */
     POWERPC_DEF("7455",          CPU_POWERPC_74x5,                   7455)
-    /* Code name for PowerPC 7445/7455                                       */
-    POWERPC_DEF("Apollo6",       CPU_POWERPC_74x5,                   7455)
     /* PowerPC 7445 v1.0 (G4)                                                */
     POWERPC_DEF("7445_v1.0",     CPU_POWERPC_74x5_v10,               7445)
     /* PowerPC 7455 v1.0 (G4)                                                */
@@ -9210,8 +9164,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("7447",          CPU_POWERPC_74x7,                   7445)
     /* PowerPC 7457 (G4)                                                     */
     POWERPC_DEF("7457",          CPU_POWERPC_74x7,                   7455)
-    /* Code name for PowerPC 7447/7457                                       */
-    POWERPC_DEF("Apollo7",       CPU_POWERPC_74x7,                   7455)
     /* PowerPC 7447 v1.0 (G4)                                                */
     POWERPC_DEF("7447_v1.0",     CPU_POWERPC_74x7_v10,               7445)
     /* PowerPC 7457 v1.0 (G4)                                                */
@@ -9230,8 +9182,6 @@ static const ppc_def_t ppc_defs[] = {
     POWERPC_DEF("7447A_v1.0",    CPU_POWERPC_74x7A_v10,              7445)
     /* PowerPC 7457A v1.0 (G4)                                               */
     POWERPC_DEF("7457A_v1.0",    CPU_POWERPC_74x7A_v10,              7455)
-    /* Code name for PowerPC 7447A/7457A                                     */
-    POWERPC_DEF("Apollo7PM",     CPU_POWERPC_74x7A_v10,              7455)
     /* PowerPC 7447A v1.1 (G4)                                               */
     POWERPC_DEF("7447A_v1.1",    CPU_POWERPC_74x7A_v11,              7445)
     /* PowerPC 7457A v1.1 (G4)                                               */
@@ -9244,20 +9194,13 @@ static const ppc_def_t ppc_defs[] = {
 #if defined (TARGET_PPC64)
     /* PowerPC 620                                                           */
     POWERPC_DEF("620",           CPU_POWERPC_620,                    620)
-    /* Code name for PowerPC 620                                             */
-    POWERPC_DEF("Trident",       CPU_POWERPC_620,                    620)
 #if defined (TODO)
     /* PowerPC 630 (POWER3)                                                  */
     POWERPC_DEF("630",           CPU_POWERPC_630,                    630)
-    POWERPC_DEF("POWER3",        CPU_POWERPC_630,                    630)
-    /* Code names for POWER3                                                 */
-    POWERPC_DEF("Boxer",         CPU_POWERPC_630,                    630)
-    POWERPC_DEF("Dino",          CPU_POWERPC_630,                    630)
 #endif
 #if defined (TODO)
     /* PowerPC 631 (Power 3+)                                                */
     POWERPC_DEF("631",           CPU_POWERPC_631,                    631)
-    POWERPC_DEF("POWER3+",       CPU_POWERPC_631,                    631)
 #endif
 #if defined (TODO)
     /* POWER4                                                                */
@@ -9345,42 +9288,28 @@ static const ppc_def_t ppc_defs[] = {
      */
     /* What about A10 & A30 ? */
     POWERPC_DEF("RS64",          CPU_POWERPC_RS64,                   RS64)
-    POWERPC_DEF("Apache",        CPU_POWERPC_RS64,                   RS64)
-    POWERPC_DEF("A35",           CPU_POWERPC_RS64,                   RS64)
 #endif
 #if defined (TODO)
     /* RS64-II (NorthStar/A50)                                               */
     POWERPC_DEF("RS64-II",       CPU_POWERPC_RS64II,                 RS64)
-    POWERPC_DEF("NorthStar",     CPU_POWERPC_RS64II,                 RS64)
-    POWERPC_DEF("A50",           CPU_POWERPC_RS64II,                 RS64)
 #endif
 #if defined (TODO)
     /* RS64-III (Pulsar)                                                     */
     POWERPC_DEF("RS64-III",      CPU_POWERPC_RS64III,                RS64)
-    POWERPC_DEF("Pulsar",        CPU_POWERPC_RS64III,                RS64)
 #endif
 #if defined (TODO)
     /* RS64-IV (IceStar/IStar/SStar)                                         */
     POWERPC_DEF("RS64-IV",       CPU_POWERPC_RS64IV,                 RS64)
-    POWERPC_DEF("IceStar",       CPU_POWERPC_RS64IV,                 RS64)
-    POWERPC_DEF("IStar",         CPU_POWERPC_RS64IV,                 RS64)
-    POWERPC_DEF("SStar",         CPU_POWERPC_RS64IV,                 RS64)
 #endif
 #endif /* defined (TARGET_PPC64) */
     /* POWER                                                                 */
 #if defined (TODO)
     /* Original POWER                                                        */
     POWERPC_DEF("POWER",         CPU_POWERPC_POWER,                  POWER)
-    POWERPC_DEF("RIOS",          CPU_POWERPC_POWER,                  POWER)
-    POWERPC_DEF("RSC",           CPU_POWERPC_POWER,                  POWER)
-    POWERPC_DEF("RSC3308",       CPU_POWERPC_POWER,                  POWER)
-    POWERPC_DEF("RSC4608",       CPU_POWERPC_POWER,                  POWER)
 #endif
 #if defined (TODO)
     /* POWER2                                                                */
     POWERPC_DEF("POWER2",        CPU_POWERPC_POWER2,                 POWER)
-    POWERPC_DEF("RSC2",          CPU_POWERPC_POWER2,                 POWER)
-    POWERPC_DEF("P2SC",          CPU_POWERPC_POWER2,                 POWER)
 #endif
     /* PA semi cores                                                         */
 #if defined (TODO)
@@ -9393,8 +9322,60 @@ static const ppc_def_t ppc_defs[] = {
 #endif
     POWERPC_DEF("ppc32",         CPU_POWERPC_PPC32,                  PPC32)
     POWERPC_DEF("ppc",           CPU_POWERPC_DEFAULT,                DEFAULT)
-    /* Fallback                                                              */
-    POWERPC_DEF("default",       CPU_POWERPC_DEFAULT,                DEFAULT)
+};
+
+typedef struct PowerPCCPUAlias {
+    const char *alias;
+    const char *model;
+} PowerPCCPUAlias;
+
+static const PowerPCCPUAlias ppc_cpu_aliases[] = {
+    { "RCPU", "MPC5xx" },
+    { "PowerQUICC", "MPC8xx" },
+    { "PowerQUICC-II", "MPC82xx" },
+    { "e500", "e500v2_v22" },
+    { "Vanilla", "603" },
+    { "Stretch", "603e" },
+    { "Vaillant", "603e7v" },
+    { "Goldeneye", "603r" },
+    { "Sirocco", "604e" },
+    { "Mach5", "604r" },
+    { "Arthur", "740" },
+    { "Typhoon", "750" },
+    { "G3",      "750" },
+    { "Conan/Doyle", "750p" },
+    { "LoneStar", "750l" },
+    { "Goldfinger", "755" },
+    { "Max", "7400" },
+    { "G4",  "7400" },
+    { "Nitro", "7410" },
+    { "Vger", "7450" },
+    { "Apollo6", "7455" },
+    { "Apollo7", "7457" },
+    { "Apollo7PM", "7457A_v1.0" },
+#if defined(TARGET_PPC64)
+    { "Trident", "620" },
+    { "POWER3", "630" },
+    { "Boxer", "POWER3" },
+    { "Dino",  "POWER3" },
+    { "POWER3+", "631" },
+    { "Apache", "RS64" },
+    { "A35",    "RS64" },
+    { "NorthStar", "RS64-II" },
+    { "A50",       "RS64-II" },
+    { "Pulsar", "RS64-III" },
+    { "IceStar", "RS64-IV" },
+    { "IStar",   "RS64-IV" },
+    { "SStar",   "RS64-IV" },
+#endif
+    { "RIOS",    "POWER" },
+    { "RSC",     "POWER" },
+    { "RSC3308", "POWER" },
+    { "RSC4608", "POWER" },
+    { "RSC2", "POWER2" },
+    { "P2SC", "POWER2" },
+
+    { "default", "ppc" },
 };
 
 /*****************************************************************************/
@@ -10323,6 +10304,12 @@ static ObjectClass *ppc_cpu_class_by_name(const char *name)
         }
     }
 
+    for (i = 0; i < ARRAY_SIZE(ppc_cpu_aliases); i++) {
+        if (strcmp(ppc_cpu_aliases[i].alias, name) == 0) {
+            return ppc_cpu_class_by_name(ppc_cpu_aliases[i].model);
+        }
+    }
+
     list = object_class_get_list(TYPE_POWERPC_CPU, false);
     item = g_slist_find_custom(list, name, ppc_cpu_compare_class_name);
     if (item != NULL) {
@@ -10403,11 +10390,23 @@ void ppc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
         .cpu_fprintf = cpu_fprintf,
     };
     GSList *list;
+    int i;
 
     list = object_class_get_list(TYPE_POWERPC_CPU, false);
     list = g_slist_sort(list, ppc_cpu_list_compare);
     g_slist_foreach(list, ppc_cpu_list_entry, &s);
     g_slist_free(list);
+
+    cpu_fprintf(f, "\n");
+    for (i = 0; i < ARRAY_SIZE(ppc_cpu_aliases); i++) {
+        ObjectClass *oc = ppc_cpu_class_by_name(ppc_cpu_aliases[i].model);
+        if (oc == NULL) {
+            /* Hide aliases that point to a TODO or TODO_USER_ONLY model */
+            continue;
+        }
+        cpu_fprintf(f, "PowerPC %-16s\n",
+                    ppc_cpu_aliases[i].alias);
+    }
 }
 
 static void ppc_cpu_defs_entry(gpointer data, gpointer user_data)
commit c4d0a36c3630ad30058406747d3cd4cc6a6eae3c
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:03 2013 +0000

    target-ppc: Inline comma into POWERPC_DEF_SVR() macro
    
    To repurpose the POWERPC_DEF_SVR() macro outside of an array,
    move the comma into the macro. No functional change.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 98a64e1..3f75bef 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7714,7 +7714,7 @@ enum {
         .flags        = glue(POWERPC_FLAG_,_type),                            \
         .init_proc    = &glue(init_proc_,_type),                              \
         .check_pow    = &glue(check_pow_,_type),                              \
-    }
+    },
 #define POWERPC_DEF(_name, _pvr, _type)                                       \
 POWERPC_DEF_SVR(_name, _pvr, POWERPC_SVR_NONE, _type)
 
@@ -7722,1621 +7722,1621 @@ static const ppc_def_t ppc_defs[] = {
     /* Embedded PowerPC                                                      */
     /* PowerPC 401 family                                                    */
     /* Generic PowerPC 401 */
-    POWERPC_DEF("401",           CPU_POWERPC_401,                    401),
+    POWERPC_DEF("401",           CPU_POWERPC_401,                    401)
     /* PowerPC 401 cores                                                     */
     /* PowerPC 401A1 */
-    POWERPC_DEF("401A1",         CPU_POWERPC_401A1,                  401),
+    POWERPC_DEF("401A1",         CPU_POWERPC_401A1,                  401)
     /* PowerPC 401B2                                                         */
-    POWERPC_DEF("401B2",         CPU_POWERPC_401B2,                  401x2),
+    POWERPC_DEF("401B2",         CPU_POWERPC_401B2,                  401x2)
 #if defined (TODO)
     /* PowerPC 401B3                                                         */
-    POWERPC_DEF("401B3",         CPU_POWERPC_401B3,                  401x3),
+    POWERPC_DEF("401B3",         CPU_POWERPC_401B3,                  401x3)
 #endif
     /* PowerPC 401C2                                                         */
-    POWERPC_DEF("401C2",         CPU_POWERPC_401C2,                  401x2),
+    POWERPC_DEF("401C2",         CPU_POWERPC_401C2,                  401x2)
     /* PowerPC 401D2                                                         */
-    POWERPC_DEF("401D2",         CPU_POWERPC_401D2,                  401x2),
+    POWERPC_DEF("401D2",         CPU_POWERPC_401D2,                  401x2)
     /* PowerPC 401E2                                                         */
-    POWERPC_DEF("401E2",         CPU_POWERPC_401E2,                  401x2),
+    POWERPC_DEF("401E2",         CPU_POWERPC_401E2,                  401x2)
     /* PowerPC 401F2                                                         */
-    POWERPC_DEF("401F2",         CPU_POWERPC_401F2,                  401x2),
+    POWERPC_DEF("401F2",         CPU_POWERPC_401F2,                  401x2)
     /* PowerPC 401G2                                                         */
     /* XXX: to be checked */
-    POWERPC_DEF("401G2",         CPU_POWERPC_401G2,                  401x2),
+    POWERPC_DEF("401G2",         CPU_POWERPC_401G2,                  401x2)
     /* PowerPC 401 microcontrolers                                           */
 #if defined (TODO)
     /* PowerPC 401GF                                                         */
-    POWERPC_DEF("401GF",         CPU_POWERPC_401GF,                  401),
+    POWERPC_DEF("401GF",         CPU_POWERPC_401GF,                  401)
 #endif
     /* IOP480 (401 microcontroler)                                           */
-    POWERPC_DEF("IOP480",        CPU_POWERPC_IOP480,                 IOP480),
+    POWERPC_DEF("IOP480",        CPU_POWERPC_IOP480,                 IOP480)
     /* IBM Processor for Network Resources                                   */
-    POWERPC_DEF("Cobra",         CPU_POWERPC_COBRA,                  401),
+    POWERPC_DEF("Cobra",         CPU_POWERPC_COBRA,                  401)
 #if defined (TODO)
-    POWERPC_DEF("Xipchip",       CPU_POWERPC_XIPCHIP,                401),
+    POWERPC_DEF("Xipchip",       CPU_POWERPC_XIPCHIP,                401)
 #endif
     /* PowerPC 403 family                                                    */
     /* Generic PowerPC 403                                                   */
-    POWERPC_DEF("403",           CPU_POWERPC_403,                    403),
+    POWERPC_DEF("403",           CPU_POWERPC_403,                    403)
     /* PowerPC 403 microcontrolers                                           */
     /* PowerPC 403 GA                                                        */
-    POWERPC_DEF("403GA",         CPU_POWERPC_403GA,                  403),
+    POWERPC_DEF("403GA",         CPU_POWERPC_403GA,                  403)
     /* PowerPC 403 GB                                                        */
-    POWERPC_DEF("403GB",         CPU_POWERPC_403GB,                  403),
+    POWERPC_DEF("403GB",         CPU_POWERPC_403GB,                  403)
     /* PowerPC 403 GC                                                        */
-    POWERPC_DEF("403GC",         CPU_POWERPC_403GC,                  403),
+    POWERPC_DEF("403GC",         CPU_POWERPC_403GC,                  403)
     /* PowerPC 403 GCX                                                       */
-    POWERPC_DEF("403GCX",        CPU_POWERPC_403GCX,                 403GCX),
+    POWERPC_DEF("403GCX",        CPU_POWERPC_403GCX,                 403GCX)
 #if defined (TODO)
     /* PowerPC 403 GP                                                        */
-    POWERPC_DEF("403GP",         CPU_POWERPC_403GP,                  403),
+    POWERPC_DEF("403GP",         CPU_POWERPC_403GP,                  403)
 #endif
     /* PowerPC 405 family                                                    */
     /* Generic PowerPC 405                                                   */
-    POWERPC_DEF("405",           CPU_POWERPC_405,                    405),
+    POWERPC_DEF("405",           CPU_POWERPC_405,                    405)
     /* PowerPC 405 cores                                                     */
 #if defined (TODO)
     /* PowerPC 405 A3                                                        */
-    POWERPC_DEF("405A3",         CPU_POWERPC_405A3,                  405),
+    POWERPC_DEF("405A3",         CPU_POWERPC_405A3,                  405)
 #endif
 #if defined (TODO)
     /* PowerPC 405 A4                                                        */
-    POWERPC_DEF("405A4",         CPU_POWERPC_405A4,                  405),
+    POWERPC_DEF("405A4",         CPU_POWERPC_405A4,                  405)
 #endif
 #if defined (TODO)
     /* PowerPC 405 B3                                                        */
-    POWERPC_DEF("405B3",         CPU_POWERPC_405B3,                  405),
+    POWERPC_DEF("405B3",         CPU_POWERPC_405B3,                  405)
 #endif
 #if defined (TODO)
     /* PowerPC 405 B4                                                        */
-    POWERPC_DEF("405B4",         CPU_POWERPC_405B4,                  405),
+    POWERPC_DEF("405B4",         CPU_POWERPC_405B4,                  405)
 #endif
 #if defined (TODO)
     /* PowerPC 405 C3                                                        */
-    POWERPC_DEF("405C3",         CPU_POWERPC_405C3,                  405),
+    POWERPC_DEF("405C3",         CPU_POWERPC_405C3,                  405)
 #endif
 #if defined (TODO)
     /* PowerPC 405 C4                                                        */
-    POWERPC_DEF("405C4",         CPU_POWERPC_405C4,                  405),
+    POWERPC_DEF("405C4",         CPU_POWERPC_405C4,                  405)
 #endif
     /* PowerPC 405 D2                                                        */
-    POWERPC_DEF("405D2",         CPU_POWERPC_405D2,                  405),
+    POWERPC_DEF("405D2",         CPU_POWERPC_405D2,                  405)
 #if defined (TODO)
     /* PowerPC 405 D3                                                        */
-    POWERPC_DEF("405D3",         CPU_POWERPC_405D3,                  405),
+    POWERPC_DEF("405D3",         CPU_POWERPC_405D3,                  405)
 #endif
     /* PowerPC 405 D4                                                        */
-    POWERPC_DEF("405D4",         CPU_POWERPC_405D4,                  405),
+    POWERPC_DEF("405D4",         CPU_POWERPC_405D4,                  405)
 #if defined (TODO)
     /* PowerPC 405 D5                                                        */
-    POWERPC_DEF("405D5",         CPU_POWERPC_405D5,                  405),
+    POWERPC_DEF("405D5",         CPU_POWERPC_405D5,                  405)
 #endif
 #if defined (TODO)
     /* PowerPC 405 E4                                                        */
-    POWERPC_DEF("405E4",         CPU_POWERPC_405E4,                  405),
+    POWERPC_DEF("405E4",         CPU_POWERPC_405E4,                  405)
 #endif
 #if defined (TODO)
     /* PowerPC 405 F4                                                        */
-    POWERPC_DEF("405F4",         CPU_POWERPC_405F4,                  405),
+    POWERPC_DEF("405F4",         CPU_POWERPC_405F4,                  405)
 #endif
 #if defined (TODO)
     /* PowerPC 405 F5                                                        */
-    POWERPC_DEF("405F5",         CPU_POWERPC_405F5,                  405),
+    POWERPC_DEF("405F5",         CPU_POWERPC_405F5,                  405)
 #endif
 #if defined (TODO)
     /* PowerPC 405 F6                                                        */
-    POWERPC_DEF("405F6",         CPU_POWERPC_405F6,                  405),
+    POWERPC_DEF("405F6",         CPU_POWERPC_405F6,                  405)
 #endif
     /* PowerPC 405 microcontrolers                                           */
     /* PowerPC 405 CR                                                        */
-    POWERPC_DEF("405CR",         CPU_POWERPC_405CR,                  405),
+    POWERPC_DEF("405CR",         CPU_POWERPC_405CR,                  405)
     /* PowerPC 405 CRa                                                       */
-    POWERPC_DEF("405CRa",        CPU_POWERPC_405CRa,                 405),
+    POWERPC_DEF("405CRa",        CPU_POWERPC_405CRa,                 405)
     /* PowerPC 405 CRb                                                       */
-    POWERPC_DEF("405CRb",        CPU_POWERPC_405CRb,                 405),
+    POWERPC_DEF("405CRb",        CPU_POWERPC_405CRb,                 405)
     /* PowerPC 405 CRc                                                       */
-    POWERPC_DEF("405CRc",        CPU_POWERPC_405CRc,                 405),
+    POWERPC_DEF("405CRc",        CPU_POWERPC_405CRc,                 405)
     /* PowerPC 405 EP                                                        */
-    POWERPC_DEF("405EP",         CPU_POWERPC_405EP,                  405),
+    POWERPC_DEF("405EP",         CPU_POWERPC_405EP,                  405)
 #if defined(TODO)
     /* PowerPC 405 EXr                                                       */
-    POWERPC_DEF("405EXr",        CPU_POWERPC_405EXr,                 405),
+    POWERPC_DEF("405EXr",        CPU_POWERPC_405EXr,                 405)
 #endif
     /* PowerPC 405 EZ                                                        */
-    POWERPC_DEF("405EZ",         CPU_POWERPC_405EZ,                  405),
+    POWERPC_DEF("405EZ",         CPU_POWERPC_405EZ,                  405)
 #if defined(TODO)
     /* PowerPC 405 FX                                                        */
-    POWERPC_DEF("405FX",         CPU_POWERPC_405FX,                  405),
+    POWERPC_DEF("405FX",         CPU_POWERPC_405FX,                  405)
 #endif
     /* PowerPC 405 GP                                                        */
-    POWERPC_DEF("405GP",         CPU_POWERPC_405GP,                  405),
+    POWERPC_DEF("405GP",         CPU_POWERPC_405GP,                  405)
     /* PowerPC 405 GPa                                                       */
-    POWERPC_DEF("405GPa",        CPU_POWERPC_405GPa,                 405),
+    POWERPC_DEF("405GPa",        CPU_POWERPC_405GPa,                 405)
     /* PowerPC 405 GPb                                                       */
-    POWERPC_DEF("405GPb",        CPU_POWERPC_405GPb,                 405),
+    POWERPC_DEF("405GPb",        CPU_POWERPC_405GPb,                 405)
     /* PowerPC 405 GPc                                                       */
-    POWERPC_DEF("405GPc",        CPU_POWERPC_405GPc,                 405),
+    POWERPC_DEF("405GPc",        CPU_POWERPC_405GPc,                 405)
     /* PowerPC 405 GPd                                                       */
-    POWERPC_DEF("405GPd",        CPU_POWERPC_405GPd,                 405),
+    POWERPC_DEF("405GPd",        CPU_POWERPC_405GPd,                 405)
     /* PowerPC 405 GPe                                                       */
-    POWERPC_DEF("405GPe",        CPU_POWERPC_405GPe,                 405),
+    POWERPC_DEF("405GPe",        CPU_POWERPC_405GPe,                 405)
     /* PowerPC 405 GPR                                                       */
-    POWERPC_DEF("405GPR",        CPU_POWERPC_405GPR,                 405),
+    POWERPC_DEF("405GPR",        CPU_POWERPC_405GPR,                 405)
 #if defined(TODO)
     /* PowerPC 405 H                                                         */
-    POWERPC_DEF("405H",          CPU_POWERPC_405H,                   405),
+    POWERPC_DEF("405H",          CPU_POWERPC_405H,                   405)
 #endif
 #if defined(TODO)
     /* PowerPC 405 L                                                         */
-    POWERPC_DEF("405L",          CPU_POWERPC_405L,                   405),
+    POWERPC_DEF("405L",          CPU_POWERPC_405L,                   405)
 #endif
     /* PowerPC 405 LP                                                        */
-    POWERPC_DEF("405LP",         CPU_POWERPC_405LP,                  405),
+    POWERPC_DEF("405LP",         CPU_POWERPC_405LP,                  405)
 #if defined(TODO)
     /* PowerPC 405 PM                                                        */
-    POWERPC_DEF("405PM",         CPU_POWERPC_405PM,                  405),
+    POWERPC_DEF("405PM",         CPU_POWERPC_405PM,                  405)
 #endif
 #if defined(TODO)
     /* PowerPC 405 PS                                                        */
-    POWERPC_DEF("405PS",         CPU_POWERPC_405PS,                  405),
+    POWERPC_DEF("405PS",         CPU_POWERPC_405PS,                  405)
 #endif
 #if defined(TODO)
     /* PowerPC 405 S                                                         */
-    POWERPC_DEF("405S",          CPU_POWERPC_405S,                   405),
+    POWERPC_DEF("405S",          CPU_POWERPC_405S,                   405)
 #endif
     /* Npe405 H                                                              */
-    POWERPC_DEF("Npe405H",       CPU_POWERPC_NPE405H,                405),
+    POWERPC_DEF("Npe405H",       CPU_POWERPC_NPE405H,                405)
     /* Npe405 H2                                                             */
-    POWERPC_DEF("Npe405H2",      CPU_POWERPC_NPE405H2,               405),
+    POWERPC_DEF("Npe405H2",      CPU_POWERPC_NPE405H2,               405)
     /* Npe405 L                                                              */
-    POWERPC_DEF("Npe405L",       CPU_POWERPC_NPE405L,                405),
+    POWERPC_DEF("Npe405L",       CPU_POWERPC_NPE405L,                405)
     /* Npe4GS3                                                               */
-    POWERPC_DEF("Npe4GS3",       CPU_POWERPC_NPE4GS3,                405),
+    POWERPC_DEF("Npe4GS3",       CPU_POWERPC_NPE4GS3,                405)
 #if defined (TODO)
-    POWERPC_DEF("Npcxx1",        CPU_POWERPC_NPCxx1,                 405),
+    POWERPC_DEF("Npcxx1",        CPU_POWERPC_NPCxx1,                 405)
 #endif
 #if defined (TODO)
-    POWERPC_DEF("Npr161",        CPU_POWERPC_NPR161,                 405),
+    POWERPC_DEF("Npr161",        CPU_POWERPC_NPR161,                 405)
 #endif
 #if defined (TODO)
     /* PowerPC LC77700 (Sanyo)                                               */
-    POWERPC_DEF("LC77700",       CPU_POWERPC_LC77700,                405),
+    POWERPC_DEF("LC77700",       CPU_POWERPC_LC77700,                405)
 #endif
     /* PowerPC 401/403/405 based set-top-box microcontrolers                 */
 #if defined (TODO)
     /* STB010000                                                             */
-    POWERPC_DEF("STB01000",      CPU_POWERPC_STB01000,               401x2),
+    POWERPC_DEF("STB01000",      CPU_POWERPC_STB01000,               401x2)
 #endif
 #if defined (TODO)
     /* STB01010                                                              */
-    POWERPC_DEF("STB01010",      CPU_POWERPC_STB01010,               401x2),
+    POWERPC_DEF("STB01010",      CPU_POWERPC_STB01010,               401x2)
 #endif
 #if defined (TODO)
     /* STB0210                                                               */
-    POWERPC_DEF("STB0210",       CPU_POWERPC_STB0210,                401x3),
+    POWERPC_DEF("STB0210",       CPU_POWERPC_STB0210,                401x3)
 #endif
     /* STB03xx                                                               */
-    POWERPC_DEF("STB03",         CPU_POWERPC_STB03,                  405),
+    POWERPC_DEF("STB03",         CPU_POWERPC_STB03,                  405)
 #if defined (TODO)
     /* STB043x                                                               */
-    POWERPC_DEF("STB043",        CPU_POWERPC_STB043,                 405),
+    POWERPC_DEF("STB043",        CPU_POWERPC_STB043,                 405)
 #endif
 #if defined (TODO)
     /* STB045x                                                               */
-    POWERPC_DEF("STB045",        CPU_POWERPC_STB045,                 405),
+    POWERPC_DEF("STB045",        CPU_POWERPC_STB045,                 405)
 #endif
     /* STB04xx                                                               */
-    POWERPC_DEF("STB04",         CPU_POWERPC_STB04,                  405),
+    POWERPC_DEF("STB04",         CPU_POWERPC_STB04,                  405)
     /* STB25xx                                                               */
-    POWERPC_DEF("STB25",         CPU_POWERPC_STB25,                  405),
+    POWERPC_DEF("STB25",         CPU_POWERPC_STB25,                  405)
 #if defined (TODO)
     /* STB130                                                                */
-    POWERPC_DEF("STB130",        CPU_POWERPC_STB130,                 405),
+    POWERPC_DEF("STB130",        CPU_POWERPC_STB130,                 405)
 #endif
     /* Xilinx PowerPC 405 cores                                              */
-    POWERPC_DEF("x2vp4",         CPU_POWERPC_X2VP4,                  405),
-    POWERPC_DEF("x2vp7",         CPU_POWERPC_X2VP7,                  405),
-    POWERPC_DEF("x2vp20",        CPU_POWERPC_X2VP20,                 405),
-    POWERPC_DEF("x2vp50",        CPU_POWERPC_X2VP50,                 405),
+    POWERPC_DEF("x2vp4",         CPU_POWERPC_X2VP4,                  405)
+    POWERPC_DEF("x2vp7",         CPU_POWERPC_X2VP7,                  405)
+    POWERPC_DEF("x2vp20",        CPU_POWERPC_X2VP20,                 405)
+    POWERPC_DEF("x2vp50",        CPU_POWERPC_X2VP50,                 405)
 #if defined (TODO)
     /* Zarlink ZL10310                                                       */
-    POWERPC_DEF("zl10310",       CPU_POWERPC_ZL10310,                405),
+    POWERPC_DEF("zl10310",       CPU_POWERPC_ZL10310,                405)
 #endif
 #if defined (TODO)
     /* Zarlink ZL10311                                                       */
-    POWERPC_DEF("zl10311",       CPU_POWERPC_ZL10311,                405),
+    POWERPC_DEF("zl10311",       CPU_POWERPC_ZL10311,                405)
 #endif
 #if defined (TODO)
     /* Zarlink ZL10320                                                       */
-    POWERPC_DEF("zl10320",       CPU_POWERPC_ZL10320,                405),
+    POWERPC_DEF("zl10320",       CPU_POWERPC_ZL10320,                405)
 #endif
 #if defined (TODO)
     /* Zarlink ZL10321                                                       */
-    POWERPC_DEF("zl10321",       CPU_POWERPC_ZL10321,                405),
+    POWERPC_DEF("zl10321",       CPU_POWERPC_ZL10321,                405)
 #endif
     /* PowerPC 440 family                                                    */
 #if defined(TODO_USER_ONLY)
     /* Generic PowerPC 440                                                   */
-    POWERPC_DEF("440",           CPU_POWERPC_440,                    440GP),
+    POWERPC_DEF("440",           CPU_POWERPC_440,                    440GP)
 #endif
     /* PowerPC 440 cores                                                     */
 #if defined (TODO)
     /* PowerPC 440 A4                                                        */
-    POWERPC_DEF("440A4",         CPU_POWERPC_440A4,                  440x4),
+    POWERPC_DEF("440A4",         CPU_POWERPC_440A4,                  440x4)
 #endif
     /* PowerPC 440 Xilinx 5                                                  */
-    POWERPC_DEF("440-Xilinx",    CPU_POWERPC_440_XILINX,             440x5),
+    POWERPC_DEF("440-Xilinx",    CPU_POWERPC_440_XILINX,             440x5)
 #if defined (TODO)
     /* PowerPC 440 A5                                                        */
-    POWERPC_DEF("440A5",         CPU_POWERPC_440A5,                  440x5),
+    POWERPC_DEF("440A5",         CPU_POWERPC_440A5,                  440x5)
 #endif
 #if defined (TODO)
     /* PowerPC 440 B4                                                        */
-    POWERPC_DEF("440B4",         CPU_POWERPC_440B4,                  440x4),
+    POWERPC_DEF("440B4",         CPU_POWERPC_440B4,                  440x4)
 #endif
 #if defined (TODO)
     /* PowerPC 440 G4                                                        */
-    POWERPC_DEF("440G4",         CPU_POWERPC_440G4,                  440x4),
+    POWERPC_DEF("440G4",         CPU_POWERPC_440G4,                  440x4)
 #endif
 #if defined (TODO)
     /* PowerPC 440 F5                                                        */
-    POWERPC_DEF("440F5",         CPU_POWERPC_440F5,                  440x5),
+    POWERPC_DEF("440F5",         CPU_POWERPC_440F5,                  440x5)
 #endif
 #if defined (TODO)
     /* PowerPC 440 G5                                                        */
-    POWERPC_DEF("440G5",         CPU_POWERPC_440G5,                  440x5),
+    POWERPC_DEF("440G5",         CPU_POWERPC_440G5,                  440x5)
 #endif
 #if defined (TODO)
     /* PowerPC 440H4                                                         */
-    POWERPC_DEF("440H4",         CPU_POWERPC_440H4,                  440x4),
+    POWERPC_DEF("440H4",         CPU_POWERPC_440H4,                  440x4)
 #endif
 #if defined (TODO)
     /* PowerPC 440H6                                                         */
-    POWERPC_DEF("440H6",         CPU_POWERPC_440H6,                  440Gx5),
+    POWERPC_DEF("440H6",         CPU_POWERPC_440H6,                  440Gx5)
 #endif
     /* PowerPC 440 microcontrolers                                           */
     /* PowerPC 440 EP                                                        */
-    POWERPC_DEF("440EP",         CPU_POWERPC_440EP,                  440EP),
+    POWERPC_DEF("440EP",         CPU_POWERPC_440EP,                  440EP)
     /* PowerPC 440 EPa                                                       */
-    POWERPC_DEF("440EPa",        CPU_POWERPC_440EPa,                 440EP),
+    POWERPC_DEF("440EPa",        CPU_POWERPC_440EPa,                 440EP)
     /* PowerPC 440 EPb                                                       */
-    POWERPC_DEF("440EPb",        CPU_POWERPC_440EPb,                 440EP),
+    POWERPC_DEF("440EPb",        CPU_POWERPC_440EPb,                 440EP)
     /* PowerPC 440 EPX                                                       */
-    POWERPC_DEF("440EPX",        CPU_POWERPC_440EPX,                 440EP),
+    POWERPC_DEF("440EPX",        CPU_POWERPC_440EPX,                 440EP)
 #if defined(TODO_USER_ONLY)
     /* PowerPC 440 GP                                                        */
-    POWERPC_DEF("440GP",         CPU_POWERPC_440GP,                  440GP),
+    POWERPC_DEF("440GP",         CPU_POWERPC_440GP,                  440GP)
 #endif
 #if defined(TODO_USER_ONLY)
     /* PowerPC 440 GPb                                                       */
-    POWERPC_DEF("440GPb",        CPU_POWERPC_440GPb,                 440GP),
+    POWERPC_DEF("440GPb",        CPU_POWERPC_440GPb,                 440GP)
 #endif
 #if defined(TODO_USER_ONLY)
     /* PowerPC 440 GPc                                                       */
-    POWERPC_DEF("440GPc",        CPU_POWERPC_440GPc,                 440GP),
+    POWERPC_DEF("440GPc",        CPU_POWERPC_440GPc,                 440GP)
 #endif
 #if defined(TODO_USER_ONLY)
     /* PowerPC 440 GR                                                        */
-    POWERPC_DEF("440GR",         CPU_POWERPC_440GR,                  440x5),
+    POWERPC_DEF("440GR",         CPU_POWERPC_440GR,                  440x5)
 #endif
 #if defined(TODO_USER_ONLY)
     /* PowerPC 440 GRa                                                       */
-    POWERPC_DEF("440GRa",        CPU_POWERPC_440GRa,                 440x5),
+    POWERPC_DEF("440GRa",        CPU_POWERPC_440GRa,                 440x5)
 #endif
 #if defined(TODO_USER_ONLY)
     /* PowerPC 440 GRX                                                       */
-    POWERPC_DEF("440GRX",        CPU_POWERPC_440GRX,                 440x5),
+    POWERPC_DEF("440GRX",        CPU_POWERPC_440GRX,                 440x5)
 #endif
 #if defined(TODO_USER_ONLY)
     /* PowerPC 440 GX                                                        */
-    POWERPC_DEF("440GX",         CPU_POWERPC_440GX,                  440EP),
+    POWERPC_DEF("440GX",         CPU_POWERPC_440GX,                  440EP)
 #endif
 #if defined(TODO_USER_ONLY)
     /* PowerPC 440 GXa                                                       */
-    POWERPC_DEF("440GXa",        CPU_POWERPC_440GXa,                 440EP),
+    POWERPC_DEF("440GXa",        CPU_POWERPC_440GXa,                 440EP)
 #endif
 #if defined(TODO_USER_ONLY)
     /* PowerPC 440 GXb                                                       */
-    POWERPC_DEF("440GXb",        CPU_POWERPC_440GXb,                 440EP),
+    POWERPC_DEF("440GXb",        CPU_POWERPC_440GXb,                 440EP)
 #endif
 #if defined(TODO_USER_ONLY)
     /* PowerPC 440 GXc                                                       */
-    POWERPC_DEF("440GXc",        CPU_POWERPC_440GXc,                 440EP),
+    POWERPC_DEF("440GXc",        CPU_POWERPC_440GXc,                 440EP)
 #endif
 #if defined(TODO_USER_ONLY)
     /* PowerPC 440 GXf                                                       */
-    POWERPC_DEF("440GXf",        CPU_POWERPC_440GXf,                 440EP),
+    POWERPC_DEF("440GXf",        CPU_POWERPC_440GXf,                 440EP)
 #endif
 #if defined(TODO)
     /* PowerPC 440 S                                                         */
-    POWERPC_DEF("440S",          CPU_POWERPC_440S,                   440),
+    POWERPC_DEF("440S",          CPU_POWERPC_440S,                   440)
 #endif
 #if defined(TODO_USER_ONLY)
     /* PowerPC 440 SP                                                        */
-    POWERPC_DEF("440SP",         CPU_POWERPC_440SP,                  440EP),
+    POWERPC_DEF("440SP",         CPU_POWERPC_440SP,                  440EP)
 #endif
 #if defined(TODO_USER_ONLY)
     /* PowerPC 440 SP2                                                       */
-    POWERPC_DEF("440SP2",        CPU_POWERPC_440SP2,                 440EP),
+    POWERPC_DEF("440SP2",        CPU_POWERPC_440SP2,                 440EP)
 #endif
 #if defined(TODO_USER_ONLY)
     /* PowerPC 440 SPE                                                       */
-    POWERPC_DEF("440SPE",        CPU_POWERPC_440SPE,                 440EP),
+    POWERPC_DEF("440SPE",        CPU_POWERPC_440SPE,                 440EP)
 #endif
     /* PowerPC 460 family                                                    */
 #if defined (TODO)
     /* Generic PowerPC 464                                                   */
-    POWERPC_DEF("464",           CPU_POWERPC_464,                    460),
+    POWERPC_DEF("464",           CPU_POWERPC_464,                    460)
 #endif
     /* PowerPC 464 microcontrolers                                           */
 #if defined (TODO)
     /* PowerPC 464H90                                                        */
-    POWERPC_DEF("464H90",        CPU_POWERPC_464H90,                 460),
+    POWERPC_DEF("464H90",        CPU_POWERPC_464H90,                 460)
 #endif
 #if defined (TODO)
     /* PowerPC 464H90F                                                       */
-    POWERPC_DEF("464H90F",       CPU_POWERPC_464H90F,                460F),
+    POWERPC_DEF("464H90F",       CPU_POWERPC_464H90F,                460F)
 #endif
     /* Freescale embedded PowerPC cores                                      */
     /* MPC5xx family (aka RCPU)                                              */
 #if defined(TODO_USER_ONLY)
     /* Generic MPC5xx core                                                   */
-    POWERPC_DEF("MPC5xx",        CPU_POWERPC_MPC5xx,                 MPC5xx),
+    POWERPC_DEF("MPC5xx",        CPU_POWERPC_MPC5xx,                 MPC5xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* Codename for MPC5xx core                                              */
-    POWERPC_DEF("RCPU",          CPU_POWERPC_MPC5xx,                 MPC5xx),
+    POWERPC_DEF("RCPU",          CPU_POWERPC_MPC5xx,                 MPC5xx)
 #endif
     /* MPC5xx microcontrollers                                               */
 #if defined(TODO_USER_ONLY)
     /* MGT560                                                                */
-    POWERPC_DEF("MGT560",        CPU_POWERPC_MGT560,                 MPC5xx),
+    POWERPC_DEF("MGT560",        CPU_POWERPC_MGT560,                 MPC5xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC509                                                                */
-    POWERPC_DEF("MPC509",        CPU_POWERPC_MPC509,                 MPC5xx),
+    POWERPC_DEF("MPC509",        CPU_POWERPC_MPC509,                 MPC5xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC533                                                                */
-    POWERPC_DEF("MPC533",        CPU_POWERPC_MPC533,                 MPC5xx),
+    POWERPC_DEF("MPC533",        CPU_POWERPC_MPC533,                 MPC5xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC534                                                                */
-    POWERPC_DEF("MPC534",        CPU_POWERPC_MPC534,                 MPC5xx),
+    POWERPC_DEF("MPC534",        CPU_POWERPC_MPC534,                 MPC5xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC555                                                                */
-    POWERPC_DEF("MPC555",        CPU_POWERPC_MPC555,                 MPC5xx),
+    POWERPC_DEF("MPC555",        CPU_POWERPC_MPC555,                 MPC5xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC556                                                                */
-    POWERPC_DEF("MPC556",        CPU_POWERPC_MPC556,                 MPC5xx),
+    POWERPC_DEF("MPC556",        CPU_POWERPC_MPC556,                 MPC5xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC560                                                                */
-    POWERPC_DEF("MPC560",        CPU_POWERPC_MPC560,                 MPC5xx),
+    POWERPC_DEF("MPC560",        CPU_POWERPC_MPC560,                 MPC5xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC561                                                                */
-    POWERPC_DEF("MPC561",        CPU_POWERPC_MPC561,                 MPC5xx),
+    POWERPC_DEF("MPC561",        CPU_POWERPC_MPC561,                 MPC5xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC562                                                                */
-    POWERPC_DEF("MPC562",        CPU_POWERPC_MPC562,                 MPC5xx),
+    POWERPC_DEF("MPC562",        CPU_POWERPC_MPC562,                 MPC5xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC563                                                                */
-    POWERPC_DEF("MPC563",        CPU_POWERPC_MPC563,                 MPC5xx),
+    POWERPC_DEF("MPC563",        CPU_POWERPC_MPC563,                 MPC5xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC564                                                                */
-    POWERPC_DEF("MPC564",        CPU_POWERPC_MPC564,                 MPC5xx),
+    POWERPC_DEF("MPC564",        CPU_POWERPC_MPC564,                 MPC5xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC565                                                                */
-    POWERPC_DEF("MPC565",        CPU_POWERPC_MPC565,                 MPC5xx),
+    POWERPC_DEF("MPC565",        CPU_POWERPC_MPC565,                 MPC5xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC566                                                                */
-    POWERPC_DEF("MPC566",        CPU_POWERPC_MPC566,                 MPC5xx),
+    POWERPC_DEF("MPC566",        CPU_POWERPC_MPC566,                 MPC5xx)
 #endif
     /* MPC8xx family (aka PowerQUICC)                                        */
 #if defined(TODO_USER_ONLY)
     /* Generic MPC8xx core                                                   */
-    POWERPC_DEF("MPC8xx",        CPU_POWERPC_MPC8xx,                 MPC8xx),
+    POWERPC_DEF("MPC8xx",        CPU_POWERPC_MPC8xx,                 MPC8xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* Codename for MPC8xx core                                              */
-    POWERPC_DEF("PowerQUICC",    CPU_POWERPC_MPC8xx,                 MPC8xx),
+    POWERPC_DEF("PowerQUICC",    CPU_POWERPC_MPC8xx,                 MPC8xx)
 #endif
     /* MPC8xx microcontrollers                                               */
 #if defined(TODO_USER_ONLY)
     /* MGT823                                                                */
-    POWERPC_DEF("MGT823",        CPU_POWERPC_MGT823,                 MPC8xx),
+    POWERPC_DEF("MGT823",        CPU_POWERPC_MGT823,                 MPC8xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC821                                                                */
-    POWERPC_DEF("MPC821",        CPU_POWERPC_MPC821,                 MPC8xx),
+    POWERPC_DEF("MPC821",        CPU_POWERPC_MPC821,                 MPC8xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC823                                                                */
-    POWERPC_DEF("MPC823",        CPU_POWERPC_MPC823,                 MPC8xx),
+    POWERPC_DEF("MPC823",        CPU_POWERPC_MPC823,                 MPC8xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC850                                                                */
-    POWERPC_DEF("MPC850",        CPU_POWERPC_MPC850,                 MPC8xx),
+    POWERPC_DEF("MPC850",        CPU_POWERPC_MPC850,                 MPC8xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC852T                                                               */
-    POWERPC_DEF("MPC852T",       CPU_POWERPC_MPC852T,                MPC8xx),
+    POWERPC_DEF("MPC852T",       CPU_POWERPC_MPC852T,                MPC8xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC855T                                                               */
-    POWERPC_DEF("MPC855T",       CPU_POWERPC_MPC855T,                MPC8xx),
+    POWERPC_DEF("MPC855T",       CPU_POWERPC_MPC855T,                MPC8xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC857                                                                */
-    POWERPC_DEF("MPC857",        CPU_POWERPC_MPC857,                 MPC8xx),
+    POWERPC_DEF("MPC857",        CPU_POWERPC_MPC857,                 MPC8xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC859                                                                */
-    POWERPC_DEF("MPC859",        CPU_POWERPC_MPC859,                 MPC8xx),
+    POWERPC_DEF("MPC859",        CPU_POWERPC_MPC859,                 MPC8xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC860                                                                */
-    POWERPC_DEF("MPC860",        CPU_POWERPC_MPC860,                 MPC8xx),
+    POWERPC_DEF("MPC860",        CPU_POWERPC_MPC860,                 MPC8xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC862                                                                */
-    POWERPC_DEF("MPC862",        CPU_POWERPC_MPC862,                 MPC8xx),
+    POWERPC_DEF("MPC862",        CPU_POWERPC_MPC862,                 MPC8xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC866                                                                */
-    POWERPC_DEF("MPC866",        CPU_POWERPC_MPC866,                 MPC8xx),
+    POWERPC_DEF("MPC866",        CPU_POWERPC_MPC866,                 MPC8xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC870                                                                */
-    POWERPC_DEF("MPC870",        CPU_POWERPC_MPC870,                 MPC8xx),
+    POWERPC_DEF("MPC870",        CPU_POWERPC_MPC870,                 MPC8xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC875                                                                */
-    POWERPC_DEF("MPC875",        CPU_POWERPC_MPC875,                 MPC8xx),
+    POWERPC_DEF("MPC875",        CPU_POWERPC_MPC875,                 MPC8xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC880                                                                */
-    POWERPC_DEF("MPC880",        CPU_POWERPC_MPC880,                 MPC8xx),
+    POWERPC_DEF("MPC880",        CPU_POWERPC_MPC880,                 MPC8xx)
 #endif
 #if defined(TODO_USER_ONLY)
     /* MPC885                                                                */
-    POWERPC_DEF("MPC885",        CPU_POWERPC_MPC885,                 MPC8xx),
+    POWERPC_DEF("MPC885",        CPU_POWERPC_MPC885,                 MPC8xx)
 #endif
     /* MPC82xx family (aka PowerQUICC-II)                                    */
     /* Generic MPC52xx core                                                  */
     POWERPC_DEF_SVR("MPC52xx",
-                    CPU_POWERPC_MPC52xx,      POWERPC_SVR_52xx,      G2LE),
+                    CPU_POWERPC_MPC52xx,      POWERPC_SVR_52xx,      G2LE)
     /* Generic MPC82xx core                                                  */
-    POWERPC_DEF("MPC82xx",       CPU_POWERPC_MPC82xx,                G2),
+    POWERPC_DEF("MPC82xx",       CPU_POWERPC_MPC82xx,                G2)
     /* Codename for MPC82xx                                                  */
-    POWERPC_DEF("PowerQUICC-II", CPU_POWERPC_MPC82xx,                G2),
+    POWERPC_DEF("PowerQUICC-II", CPU_POWERPC_MPC82xx,                G2)
     /* PowerPC G2 core                                                       */
-    POWERPC_DEF("G2",            CPU_POWERPC_G2,                     G2),
+    POWERPC_DEF("G2",            CPU_POWERPC_G2,                     G2)
     /* PowerPC G2 H4 core                                                    */
-    POWERPC_DEF("G2H4",          CPU_POWERPC_G2H4,                   G2),
+    POWERPC_DEF("G2H4",          CPU_POWERPC_G2H4,                   G2)
     /* PowerPC G2 GP core                                                    */
-    POWERPC_DEF("G2GP",          CPU_POWERPC_G2gp,                   G2),
+    POWERPC_DEF("G2GP",          CPU_POWERPC_G2gp,                   G2)
     /* PowerPC G2 LS core                                                    */
-    POWERPC_DEF("G2LS",          CPU_POWERPC_G2ls,                   G2),
+    POWERPC_DEF("G2LS",          CPU_POWERPC_G2ls,                   G2)
     /* PowerPC G2 HiP3 core                                                  */
-    POWERPC_DEF("G2HiP3",        CPU_POWERPC_G2_HIP3,                G2),
+    POWERPC_DEF("G2HiP3",        CPU_POWERPC_G2_HIP3,                G2)
     /* PowerPC G2 HiP4 core                                                  */
-    POWERPC_DEF("G2HiP4",        CPU_POWERPC_G2_HIP4,                G2),
+    POWERPC_DEF("G2HiP4",        CPU_POWERPC_G2_HIP4,                G2)
     /* PowerPC MPC603 core                                                   */
-    POWERPC_DEF("MPC603",        CPU_POWERPC_MPC603,                 603E),
+    POWERPC_DEF("MPC603",        CPU_POWERPC_MPC603,                 603E)
     /* PowerPC G2le core (same as G2 plus little-endian mode support)        */
-    POWERPC_DEF("G2le",          CPU_POWERPC_G2LE,                   G2LE),
+    POWERPC_DEF("G2le",          CPU_POWERPC_G2LE,                   G2LE)
     /* PowerPC G2LE GP core                                                  */
-    POWERPC_DEF("G2leGP",        CPU_POWERPC_G2LEgp,                 G2LE),
+    POWERPC_DEF("G2leGP",        CPU_POWERPC_G2LEgp,                 G2LE)
     /* PowerPC G2LE LS core                                                  */
-    POWERPC_DEF("G2leLS",        CPU_POWERPC_G2LEls,                 G2LE),
+    POWERPC_DEF("G2leLS",        CPU_POWERPC_G2LEls,                 G2LE)
     /* PowerPC G2LE GP1 core                                                 */
-    POWERPC_DEF("G2leGP1",       CPU_POWERPC_G2LEgp1,                G2LE),
+    POWERPC_DEF("G2leGP1",       CPU_POWERPC_G2LEgp1,                G2LE)
     /* PowerPC G2LE GP3 core                                                 */
-    POWERPC_DEF("G2leGP3",       CPU_POWERPC_G2LEgp3,                G2LE),
+    POWERPC_DEF("G2leGP3",       CPU_POWERPC_G2LEgp3,                G2LE)
     /* PowerPC MPC603 microcontrollers                                       */
     /* MPC8240                                                               */
-    POWERPC_DEF("MPC8240",       CPU_POWERPC_MPC8240,                603E),
+    POWERPC_DEF("MPC8240",       CPU_POWERPC_MPC8240,                603E)
     /* PowerPC G2 microcontrollers                                           */
 #if defined(TODO)
     /* MPC5121                                                               */
     POWERPC_DEF_SVR("MPC5121",
-                    CPU_POWERPC_MPC5121,      POWERPC_SVR_5121,      G2LE),
+                    CPU_POWERPC_MPC5121,      POWERPC_SVR_5121,      G2LE)
 #endif
     /* MPC5200                                                               */
     POWERPC_DEF_SVR("MPC5200",
-                    CPU_POWERPC_MPC5200,      POWERPC_SVR_5200,      G2LE),
+                    CPU_POWERPC_MPC5200,      POWERPC_SVR_5200,      G2LE)
     /* MPC5200 v1.0                                                          */
     POWERPC_DEF_SVR("MPC5200_v10",
-                    CPU_POWERPC_MPC5200_v10,  POWERPC_SVR_5200_v10,  G2LE),
+                    CPU_POWERPC_MPC5200_v10,  POWERPC_SVR_5200_v10,  G2LE)
     /* MPC5200 v1.1                                                          */
     POWERPC_DEF_SVR("MPC5200_v11",
-                    CPU_POWERPC_MPC5200_v11,  POWERPC_SVR_5200_v11,  G2LE),
+                    CPU_POWERPC_MPC5200_v11,  POWERPC_SVR_5200_v11,  G2LE)
     /* MPC5200 v1.2                                                          */
     POWERPC_DEF_SVR("MPC5200_v12",
-                    CPU_POWERPC_MPC5200_v12,  POWERPC_SVR_5200_v12,  G2LE),
+                    CPU_POWERPC_MPC5200_v12,  POWERPC_SVR_5200_v12,  G2LE)
     /* MPC5200B                                                              */
     POWERPC_DEF_SVR("MPC5200B",
-                    CPU_POWERPC_MPC5200B,     POWERPC_SVR_5200B,     G2LE),
+                    CPU_POWERPC_MPC5200B,     POWERPC_SVR_5200B,     G2LE)
     /* MPC5200B v2.0                                                         */
     POWERPC_DEF_SVR("MPC5200B_v20",
-                    CPU_POWERPC_MPC5200B_v20, POWERPC_SVR_5200B_v20, G2LE),
+                    CPU_POWERPC_MPC5200B_v20, POWERPC_SVR_5200B_v20, G2LE)
     /* MPC5200B v2.1                                                         */
     POWERPC_DEF_SVR("MPC5200B_v21",
-                    CPU_POWERPC_MPC5200B_v21, POWERPC_SVR_5200B_v21, G2LE),
+                    CPU_POWERPC_MPC5200B_v21, POWERPC_SVR_5200B_v21, G2LE)
     /* MPC8241                                                               */
-    POWERPC_DEF("MPC8241",       CPU_POWERPC_MPC8241,                G2),
+    POWERPC_DEF("MPC8241",       CPU_POWERPC_MPC8241,                G2)
     /* MPC8245                                                               */
-    POWERPC_DEF("MPC8245",       CPU_POWERPC_MPC8245,                G2),
+    POWERPC_DEF("MPC8245",       CPU_POWERPC_MPC8245,                G2)
     /* MPC8247                                                               */
-    POWERPC_DEF("MPC8247",       CPU_POWERPC_MPC8247,                G2LE),
+    POWERPC_DEF("MPC8247",       CPU_POWERPC_MPC8247,                G2LE)
     /* MPC8248                                                               */
-    POWERPC_DEF("MPC8248",       CPU_POWERPC_MPC8248,                G2LE),
+    POWERPC_DEF("MPC8248",       CPU_POWERPC_MPC8248,                G2LE)
     /* MPC8250                                                               */
-    POWERPC_DEF("MPC8250",       CPU_POWERPC_MPC8250,                G2),
+    POWERPC_DEF("MPC8250",       CPU_POWERPC_MPC8250,                G2)
     /* MPC8250 HiP3                                                          */
-    POWERPC_DEF("MPC8250_HiP3",  CPU_POWERPC_MPC8250_HiP3,           G2),
+    POWERPC_DEF("MPC8250_HiP3",  CPU_POWERPC_MPC8250_HiP3,           G2)
     /* MPC8250 HiP4                                                          */
-    POWERPC_DEF("MPC8250_HiP4",  CPU_POWERPC_MPC8250_HiP4,           G2),
+    POWERPC_DEF("MPC8250_HiP4",  CPU_POWERPC_MPC8250_HiP4,           G2)
     /* MPC8255                                                               */
-    POWERPC_DEF("MPC8255",       CPU_POWERPC_MPC8255,                G2),
+    POWERPC_DEF("MPC8255",       CPU_POWERPC_MPC8255,                G2)
     /* MPC8255 HiP3                                                          */
-    POWERPC_DEF("MPC8255_HiP3",  CPU_POWERPC_MPC8255_HiP3,           G2),
+    POWERPC_DEF("MPC8255_HiP3",  CPU_POWERPC_MPC8255_HiP3,           G2)
     /* MPC8255 HiP4                                                          */
-    POWERPC_DEF("MPC8255_HiP4",  CPU_POWERPC_MPC8255_HiP4,           G2),
+    POWERPC_DEF("MPC8255_HiP4",  CPU_POWERPC_MPC8255_HiP4,           G2)
     /* MPC8260                                                               */
-    POWERPC_DEF("MPC8260",       CPU_POWERPC_MPC8260,                G2),
+    POWERPC_DEF("MPC8260",       CPU_POWERPC_MPC8260,                G2)
     /* MPC8260 HiP3                                                          */
-    POWERPC_DEF("MPC8260_HiP3",  CPU_POWERPC_MPC8260_HiP3,           G2),
+    POWERPC_DEF("MPC8260_HiP3",  CPU_POWERPC_MPC8260_HiP3,           G2)
     /* MPC8260 HiP4                                                          */
-    POWERPC_DEF("MPC8260_HiP4",  CPU_POWERPC_MPC8260_HiP4,           G2),
+    POWERPC_DEF("MPC8260_HiP4",  CPU_POWERPC_MPC8260_HiP4,           G2)
     /* MPC8264                                                               */
-    POWERPC_DEF("MPC8264",       CPU_POWERPC_MPC8264,                G2),
+    POWERPC_DEF("MPC8264",       CPU_POWERPC_MPC8264,                G2)
     /* MPC8264 HiP3                                                          */
-    POWERPC_DEF("MPC8264_HiP3",  CPU_POWERPC_MPC8264_HiP3,           G2),
+    POWERPC_DEF("MPC8264_HiP3",  CPU_POWERPC_MPC8264_HiP3,           G2)
     /* MPC8264 HiP4                                                          */
-    POWERPC_DEF("MPC8264_HiP4",  CPU_POWERPC_MPC8264_HiP4,           G2),
+    POWERPC_DEF("MPC8264_HiP4",  CPU_POWERPC_MPC8264_HiP4,           G2)
     /* MPC8265                                                               */
-    POWERPC_DEF("MPC8265",       CPU_POWERPC_MPC8265,                G2),
+    POWERPC_DEF("MPC8265",       CPU_POWERPC_MPC8265,                G2)
     /* MPC8265 HiP3                                                          */
-    POWERPC_DEF("MPC8265_HiP3",  CPU_POWERPC_MPC8265_HiP3,           G2),
+    POWERPC_DEF("MPC8265_HiP3",  CPU_POWERPC_MPC8265_HiP3,           G2)
     /* MPC8265 HiP4                                                          */
-    POWERPC_DEF("MPC8265_HiP4",  CPU_POWERPC_MPC8265_HiP4,           G2),
+    POWERPC_DEF("MPC8265_HiP4",  CPU_POWERPC_MPC8265_HiP4,           G2)
     /* MPC8266                                                               */
-    POWERPC_DEF("MPC8266",       CPU_POWERPC_MPC8266,                G2),
+    POWERPC_DEF("MPC8266",       CPU_POWERPC_MPC8266,                G2)
     /* MPC8266 HiP3                                                          */
-    POWERPC_DEF("MPC8266_HiP3",  CPU_POWERPC_MPC8266_HiP3,           G2),
+    POWERPC_DEF("MPC8266_HiP3",  CPU_POWERPC_MPC8266_HiP3,           G2)
     /* MPC8266 HiP4                                                          */
-    POWERPC_DEF("MPC8266_HiP4",  CPU_POWERPC_MPC8266_HiP4,           G2),
+    POWERPC_DEF("MPC8266_HiP4",  CPU_POWERPC_MPC8266_HiP4,           G2)
     /* MPC8270                                                               */
-    POWERPC_DEF("MPC8270",       CPU_POWERPC_MPC8270,                G2LE),
+    POWERPC_DEF("MPC8270",       CPU_POWERPC_MPC8270,                G2LE)
     /* MPC8271                                                               */
-    POWERPC_DEF("MPC8271",       CPU_POWERPC_MPC8271,                G2LE),
+    POWERPC_DEF("MPC8271",       CPU_POWERPC_MPC8271,                G2LE)
     /* MPC8272                                                               */
-    POWERPC_DEF("MPC8272",       CPU_POWERPC_MPC8272,                G2LE),
+    POWERPC_DEF("MPC8272",       CPU_POWERPC_MPC8272,                G2LE)
     /* MPC8275                                                               */
-    POWERPC_DEF("MPC8275",       CPU_POWERPC_MPC8275,                G2LE),
+    POWERPC_DEF("MPC8275",       CPU_POWERPC_MPC8275,                G2LE)
     /* MPC8280                                                               */
-    POWERPC_DEF("MPC8280",       CPU_POWERPC_MPC8280,                G2LE),
+    POWERPC_DEF("MPC8280",       CPU_POWERPC_MPC8280,                G2LE)
     /* e200 family                                                           */
     /* Generic PowerPC e200 core                                             */
-    POWERPC_DEF("e200",          CPU_POWERPC_e200,                   e200),
+    POWERPC_DEF("e200",          CPU_POWERPC_e200,                   e200)
     /* Generic MPC55xx core                                                  */
 #if defined (TODO)
     POWERPC_DEF_SVR("MPC55xx",
-                    CPU_POWERPC_MPC55xx,      POWERPC_SVR_55xx,      e200),
+                    CPU_POWERPC_MPC55xx,      POWERPC_SVR_55xx,      e200)
 #endif
 #if defined (TODO)
     /* PowerPC e200z0 core                                                   */
-    POWERPC_DEF("e200z0",        CPU_POWERPC_e200z0,                 e200),
+    POWERPC_DEF("e200z0",        CPU_POWERPC_e200z0,                 e200)
 #endif
 #if defined (TODO)
     /* PowerPC e200z1 core                                                   */
-    POWERPC_DEF("e200z1",        CPU_POWERPC_e200z1,                 e200),
+    POWERPC_DEF("e200z1",        CPU_POWERPC_e200z1,                 e200)
 #endif
 #if defined (TODO)
     /* PowerPC e200z3 core                                                   */
-    POWERPC_DEF("e200z3",        CPU_POWERPC_e200z3,                 e200),
+    POWERPC_DEF("e200z3",        CPU_POWERPC_e200z3,                 e200)
 #endif
     /* PowerPC e200z5 core                                                   */
-    POWERPC_DEF("e200z5",        CPU_POWERPC_e200z5,                 e200),
+    POWERPC_DEF("e200z5",        CPU_POWERPC_e200z5,                 e200)
     /* PowerPC e200z6 core                                                   */
-    POWERPC_DEF("e200z6",        CPU_POWERPC_e200z6,                 e200),
+    POWERPC_DEF("e200z6",        CPU_POWERPC_e200z6,                 e200)
     /* PowerPC e200 microcontrollers                                         */
 #if defined (TODO)
     /* MPC5514E                                                              */
     POWERPC_DEF_SVR("MPC5514E",
-                    CPU_POWERPC_MPC5514E,     POWERPC_SVR_5514E,     e200),
+                    CPU_POWERPC_MPC5514E,     POWERPC_SVR_5514E,     e200)
 #endif
 #if defined (TODO)
     /* MPC5514E v0                                                           */
     POWERPC_DEF_SVR("MPC5514E_v0",
-                    CPU_POWERPC_MPC5514E_v0,  POWERPC_SVR_5514E_v0,  e200),
+                    CPU_POWERPC_MPC5514E_v0,  POWERPC_SVR_5514E_v0,  e200)
 #endif
 #if defined (TODO)
     /* MPC5514E v1                                                           */
     POWERPC_DEF_SVR("MPC5514E_v1",
-                    CPU_POWERPC_MPC5514E_v1,  POWERPC_SVR_5514E_v1,  e200),
+                    CPU_POWERPC_MPC5514E_v1,  POWERPC_SVR_5514E_v1,  e200)
 #endif
 #if defined (TODO)
     /* MPC5514G                                                              */
     POWERPC_DEF_SVR("MPC5514G",
-                    CPU_POWERPC_MPC5514G,     POWERPC_SVR_5514G,     e200),
+                    CPU_POWERPC_MPC5514G,     POWERPC_SVR_5514G,     e200)
 #endif
 #if defined (TODO)
     /* MPC5514G v0                                                           */
     POWERPC_DEF_SVR("MPC5514G_v0",
-                    CPU_POWERPC_MPC5514G_v0,  POWERPC_SVR_5514G_v0,  e200),
+                    CPU_POWERPC_MPC5514G_v0,  POWERPC_SVR_5514G_v0,  e200)
 #endif
 #if defined (TODO)
     /* MPC5514G v1                                                           */
     POWERPC_DEF_SVR("MPC5514G_v1",
-                    CPU_POWERPC_MPC5514G_v1,  POWERPC_SVR_5514G_v1,  e200),
+                    CPU_POWERPC_MPC5514G_v1,  POWERPC_SVR_5514G_v1,  e200)
 #endif
 #if defined (TODO)
     /* MPC5515S                                                              */
     POWERPC_DEF_SVR("MPC5515S",
-                    CPU_POWERPC_MPC5515S,     POWERPC_SVR_5515S,     e200),
+                    CPU_POWERPC_MPC5515S,     POWERPC_SVR_5515S,     e200)
 #endif
 #if defined (TODO)
     /* MPC5516E                                                              */
     POWERPC_DEF_SVR("MPC5516E",
-                    CPU_POWERPC_MPC5516E,     POWERPC_SVR_5516E,     e200),
+                    CPU_POWERPC_MPC5516E,     POWERPC_SVR_5516E,     e200)
 #endif
 #if defined (TODO)
     /* MPC5516E v0                                                           */
     POWERPC_DEF_SVR("MPC5516E_v0",
-                    CPU_POWERPC_MPC5516E_v0,  POWERPC_SVR_5516E_v0,  e200),
+                    CPU_POWERPC_MPC5516E_v0,  POWERPC_SVR_5516E_v0,  e200)
 #endif
 #if defined (TODO)
     /* MPC5516E v1                                                           */
     POWERPC_DEF_SVR("MPC5516E_v1",
-                    CPU_POWERPC_MPC5516E_v1,  POWERPC_SVR_5516E_v1,  e200),
+                    CPU_POWERPC_MPC5516E_v1,  POWERPC_SVR_5516E_v1,  e200)
 #endif
 #if defined (TODO)
     /* MPC5516G                                                              */
     POWERPC_DEF_SVR("MPC5516G",
-                    CPU_POWERPC_MPC5516G,     POWERPC_SVR_5516G,     e200),
+                    CPU_POWERPC_MPC5516G,     POWERPC_SVR_5516G,     e200)
 #endif
 #if defined (TODO)
     /* MPC5516G v0                                                           */
     POWERPC_DEF_SVR("MPC5516G_v0",
-                    CPU_POWERPC_MPC5516G_v0,  POWERPC_SVR_5516G_v0,  e200),
+                    CPU_POWERPC_MPC5516G_v0,  POWERPC_SVR_5516G_v0,  e200)
 #endif
 #if defined (TODO)
     /* MPC5516G v1                                                           */
     POWERPC_DEF_SVR("MPC5516G_v1",
-                    CPU_POWERPC_MPC5516G_v1,  POWERPC_SVR_5516G_v1,  e200),
+                    CPU_POWERPC_MPC5516G_v1,  POWERPC_SVR_5516G_v1,  e200)
 #endif
 #if defined (TODO)
     /* MPC5516S                                                              */
     POWERPC_DEF_SVR("MPC5516S",
-                    CPU_POWERPC_MPC5516S,     POWERPC_SVR_5516S,     e200),
+                    CPU_POWERPC_MPC5516S,     POWERPC_SVR_5516S,     e200)
 #endif
 #if defined (TODO)
     /* MPC5533                                                               */
     POWERPC_DEF_SVR("MPC5533",
-                    CPU_POWERPC_MPC5533,      POWERPC_SVR_5533,      e200),
+                    CPU_POWERPC_MPC5533,      POWERPC_SVR_5533,      e200)
 #endif
 #if defined (TODO)
     /* MPC5534                                                               */
     POWERPC_DEF_SVR("MPC5534",
-                    CPU_POWERPC_MPC5534,      POWERPC_SVR_5534,      e200),
+                    CPU_POWERPC_MPC5534,      POWERPC_SVR_5534,      e200)
 #endif
 #if defined (TODO)
     /* MPC5553                                                               */
     POWERPC_DEF_SVR("MPC5553",
-                    CPU_POWERPC_MPC5553,      POWERPC_SVR_5553,      e200),
+                    CPU_POWERPC_MPC5553,      POWERPC_SVR_5553,      e200)
 #endif
 #if defined (TODO)
     /* MPC5554                                                               */
     POWERPC_DEF_SVR("MPC5554",
-                    CPU_POWERPC_MPC5554,      POWERPC_SVR_5554,      e200),
+                    CPU_POWERPC_MPC5554,      POWERPC_SVR_5554,      e200)
 #endif
 #if defined (TODO)
     /* MPC5561                                                               */
     POWERPC_DEF_SVR("MPC5561",
-                    CPU_POWERPC_MPC5561,      POWERPC_SVR_5561,      e200),
+                    CPU_POWERPC_MPC5561,      POWERPC_SVR_5561,      e200)
 #endif
 #if defined (TODO)
     /* MPC5565                                                               */
     POWERPC_DEF_SVR("MPC5565",
-                    CPU_POWERPC_MPC5565,      POWERPC_SVR_5565,      e200),
+                    CPU_POWERPC_MPC5565,      POWERPC_SVR_5565,      e200)
 #endif
 #if defined (TODO)
     /* MPC5566                                                               */
     POWERPC_DEF_SVR("MPC5566",
-                    CPU_POWERPC_MPC5566,      POWERPC_SVR_5566,      e200),
+                    CPU_POWERPC_MPC5566,      POWERPC_SVR_5566,      e200)
 #endif
 #if defined (TODO)
     /* MPC5567                                                               */
     POWERPC_DEF_SVR("MPC5567",
-                    CPU_POWERPC_MPC5567,      POWERPC_SVR_5567,      e200),
+                    CPU_POWERPC_MPC5567,      POWERPC_SVR_5567,      e200)
 #endif
     /* e300 family                                                           */
     /* Generic PowerPC e300 core                                             */
-    POWERPC_DEF("e300",          CPU_POWERPC_e300,                   e300),
+    POWERPC_DEF("e300",          CPU_POWERPC_e300,                   e300)
     /* PowerPC e300c1 core                                                   */
-    POWERPC_DEF("e300c1",        CPU_POWERPC_e300c1,                 e300),
+    POWERPC_DEF("e300c1",        CPU_POWERPC_e300c1,                 e300)
     /* PowerPC e300c2 core                                                   */
-    POWERPC_DEF("e300c2",        CPU_POWERPC_e300c2,                 e300),
+    POWERPC_DEF("e300c2",        CPU_POWERPC_e300c2,                 e300)
     /* PowerPC e300c3 core                                                   */
-    POWERPC_DEF("e300c3",        CPU_POWERPC_e300c3,                 e300),
+    POWERPC_DEF("e300c3",        CPU_POWERPC_e300c3,                 e300)
     /* PowerPC e300c4 core                                                   */
-    POWERPC_DEF("e300c4",        CPU_POWERPC_e300c4,                 e300),
+    POWERPC_DEF("e300c4",        CPU_POWERPC_e300c4,                 e300)
     /* PowerPC e300 microcontrollers                                         */
 #if defined (TODO)
     /* MPC8313                                                               */
     POWERPC_DEF_SVR("MPC8313",
-                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8313,      e300),
+                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8313,      e300)
 #endif
 #if defined (TODO)
     /* MPC8313E                                                              */
     POWERPC_DEF_SVR("MPC8313E",
-                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8313E,     e300),
+                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8313E,     e300)
 #endif
 #if defined (TODO)
     /* MPC8314                                                               */
     POWERPC_DEF_SVR("MPC8314",
-                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8314,      e300),
+                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8314,      e300)
 #endif
 #if defined (TODO)
     /* MPC8314E                                                              */
     POWERPC_DEF_SVR("MPC8314E",
-                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8314E,     e300),
+                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8314E,     e300)
 #endif
 #if defined (TODO)
     /* MPC8315                                                               */
     POWERPC_DEF_SVR("MPC8315",
-                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8315,      e300),
+                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8315,      e300)
 #endif
 #if defined (TODO)
     /* MPC8315E                                                              */
     POWERPC_DEF_SVR("MPC8315E",
-                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8315E,     e300),
+                    CPU_POWERPC_MPC831x,      POWERPC_SVR_8315E,     e300)
 #endif
 #if defined (TODO)
     /* MPC8321                                                               */
     POWERPC_DEF_SVR("MPC8321",
-                    CPU_POWERPC_MPC832x,      POWERPC_SVR_8321,      e300),
+                    CPU_POWERPC_MPC832x,      POWERPC_SVR_8321,      e300)
 #endif
 #if defined (TODO)
     /* MPC8321E                                                              */
     POWERPC_DEF_SVR("MPC8321E",
-                    CPU_POWERPC_MPC832x,      POWERPC_SVR_8321E,     e300),
+                    CPU_POWERPC_MPC832x,      POWERPC_SVR_8321E,     e300)
 #endif
 #if defined (TODO)
     /* MPC8323                                                               */
     POWERPC_DEF_SVR("MPC8323",
-                    CPU_POWERPC_MPC832x,      POWERPC_SVR_8323,      e300),
+                    CPU_POWERPC_MPC832x,      POWERPC_SVR_8323,      e300)
 #endif
 #if defined (TODO)
     /* MPC8323E                                                              */
     POWERPC_DEF_SVR("MPC8323E",
-                    CPU_POWERPC_MPC832x,      POWERPC_SVR_8323E,     e300),
+                    CPU_POWERPC_MPC832x,      POWERPC_SVR_8323E,     e300)
 #endif
     /* MPC8343                                                               */
     POWERPC_DEF_SVR("MPC8343",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8343,      e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8343,      e300)
     /* MPC8343A                                                              */
     POWERPC_DEF_SVR("MPC8343A",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8343A,     e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8343A,     e300)
     /* MPC8343E                                                              */
     POWERPC_DEF_SVR("MPC8343E",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8343E,     e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8343E,     e300)
     /* MPC8343EA                                                             */
     POWERPC_DEF_SVR("MPC8343EA",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8343EA,    e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8343EA,    e300)
     /* MPC8347                                                               */
     POWERPC_DEF_SVR("MPC8347",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347,      e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347,      e300)
     /* MPC8347T                                                              */
     POWERPC_DEF_SVR("MPC8347T",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347T,     e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347T,     e300)
     /* MPC8347P                                                              */
     POWERPC_DEF_SVR("MPC8347P",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347P,     e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347P,     e300)
     /* MPC8347A                                                              */
     POWERPC_DEF_SVR("MPC8347A",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347A,     e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347A,     e300)
     /* MPC8347AT                                                             */
     POWERPC_DEF_SVR("MPC8347AT",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347AT,    e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347AT,    e300)
     /* MPC8347AP                                                             */
     POWERPC_DEF_SVR("MPC8347AP",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347AP,    e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347AP,    e300)
     /* MPC8347E                                                              */
     POWERPC_DEF_SVR("MPC8347E",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347E,     e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347E,     e300)
     /* MPC8347ET                                                             */
     POWERPC_DEF_SVR("MPC8347ET",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347ET,    e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347ET,    e300)
     /* MPC8343EP                                                             */
     POWERPC_DEF_SVR("MPC8347EP",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EP,    e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EP,    e300)
     /* MPC8347EA                                                             */
     POWERPC_DEF_SVR("MPC8347EA",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EA,    e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EA,    e300)
     /* MPC8347EAT                                                            */
     POWERPC_DEF_SVR("MPC8347EAT",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EAT,   e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EAT,   e300)
     /* MPC8343EAP                                                            */
     POWERPC_DEF_SVR("MPC8347EAP",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EAP,   e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8347EAP,   e300)
     /* MPC8349                                                               */
     POWERPC_DEF_SVR("MPC8349",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8349,      e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8349,      e300)
     /* MPC8349A                                                              */
     POWERPC_DEF_SVR("MPC8349A",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8349A,     e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8349A,     e300)
     /* MPC8349E                                                              */
     POWERPC_DEF_SVR("MPC8349E",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8349E,     e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8349E,     e300)
     /* MPC8349EA                                                             */
     POWERPC_DEF_SVR("MPC8349EA",
-                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8349EA,    e300),
+                    CPU_POWERPC_MPC834x,      POWERPC_SVR_8349EA,    e300)
 #if defined (TODO)
     /* MPC8358E                                                              */
     POWERPC_DEF_SVR("MPC8358E",
-                    CPU_POWERPC_MPC835x,      POWERPC_SVR_8358E,     e300),
+                    CPU_POWERPC_MPC835x,      POWERPC_SVR_8358E,     e300)
 #endif
 #if defined (TODO)
     /* MPC8360E                                                              */
     POWERPC_DEF_SVR("MPC8360E",
-                    CPU_POWERPC_MPC836x,      POWERPC_SVR_8360E,     e300),
+                    CPU_POWERPC_MPC836x,      POWERPC_SVR_8360E,     e300)
 #endif
     /* MPC8377                                                               */
     POWERPC_DEF_SVR("MPC8377",
-                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8377,      e300),
+                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8377,      e300)
     /* MPC8377E                                                              */
     POWERPC_DEF_SVR("MPC8377E",
-                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8377E,     e300),
+                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8377E,     e300)
     /* MPC8378                                                               */
     POWERPC_DEF_SVR("MPC8378",
-                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8378,      e300),
+                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8378,      e300)
     /* MPC8378E                                                              */
     POWERPC_DEF_SVR("MPC8378E",
-                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8378E,     e300),
+                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8378E,     e300)
     /* MPC8379                                                               */
     POWERPC_DEF_SVR("MPC8379",
-                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8379,      e300),
+                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8379,      e300)
     /* MPC8379E                                                              */
     POWERPC_DEF_SVR("MPC8379E",
-                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8379E,     e300),
+                    CPU_POWERPC_MPC837x,      POWERPC_SVR_8379E,     e300)
     /* e500 family                                                           */
     /* PowerPC e500 core                                                     */
-    POWERPC_DEF("e500",          CPU_POWERPC_e500v2_v22,             e500v2),
+    POWERPC_DEF("e500",          CPU_POWERPC_e500v2_v22,             e500v2)
     /* PowerPC e500v1 core                                                   */
-    POWERPC_DEF("e500v1",        CPU_POWERPC_e500v1,                 e500v1),
+    POWERPC_DEF("e500v1",        CPU_POWERPC_e500v1,                 e500v1)
     /* PowerPC e500 v1.0 core                                                */
-    POWERPC_DEF("e500_v10",      CPU_POWERPC_e500v1_v10,             e500v1),
+    POWERPC_DEF("e500_v10",      CPU_POWERPC_e500v1_v10,             e500v1)
     /* PowerPC e500 v2.0 core                                                */
-    POWERPC_DEF("e500_v20",      CPU_POWERPC_e500v1_v20,             e500v1),
+    POWERPC_DEF("e500_v20",      CPU_POWERPC_e500v1_v20,             e500v1)
     /* PowerPC e500v2 core                                                   */
-    POWERPC_DEF("e500v2",        CPU_POWERPC_e500v2,                 e500v2),
+    POWERPC_DEF("e500v2",        CPU_POWERPC_e500v2,                 e500v2)
     /* PowerPC e500v2 v1.0 core                                              */
-    POWERPC_DEF("e500v2_v10",    CPU_POWERPC_e500v2_v10,             e500v2),
+    POWERPC_DEF("e500v2_v10",    CPU_POWERPC_e500v2_v10,             e500v2)
     /* PowerPC e500v2 v2.0 core                                              */
-    POWERPC_DEF("e500v2_v20",    CPU_POWERPC_e500v2_v20,             e500v2),
+    POWERPC_DEF("e500v2_v20",    CPU_POWERPC_e500v2_v20,             e500v2)
     /* PowerPC e500v2 v2.1 core                                              */
-    POWERPC_DEF("e500v2_v21",    CPU_POWERPC_e500v2_v21,             e500v2),
+    POWERPC_DEF("e500v2_v21",    CPU_POWERPC_e500v2_v21,             e500v2)
     /* PowerPC e500v2 v2.2 core                                              */
-    POWERPC_DEF("e500v2_v22",    CPU_POWERPC_e500v2_v22,             e500v2),
+    POWERPC_DEF("e500v2_v22",    CPU_POWERPC_e500v2_v22,             e500v2)
     /* PowerPC e500v2 v3.0 core                                              */
-    POWERPC_DEF("e500v2_v30",    CPU_POWERPC_e500v2_v30,             e500v2),
-    POWERPC_DEF_SVR("e500mc", CPU_POWERPC_e500mc, POWERPC_SVR_E500,  e500mc),
+    POWERPC_DEF("e500v2_v30",    CPU_POWERPC_e500v2_v30,             e500v2)
+    POWERPC_DEF_SVR("e500mc", CPU_POWERPC_e500mc, POWERPC_SVR_E500,  e500mc)
 #ifdef TARGET_PPC64
-    POWERPC_DEF_SVR("e5500",    CPU_POWERPC_e5500, POWERPC_SVR_E500, e5500),
+    POWERPC_DEF_SVR("e5500",    CPU_POWERPC_e5500, POWERPC_SVR_E500, e5500)
 #endif
     /* PowerPC e500 microcontrollers                                         */
     /* MPC8533                                                               */
     POWERPC_DEF_SVR("MPC8533",
-                    CPU_POWERPC_MPC8533,      POWERPC_SVR_8533,      e500v2),
+                    CPU_POWERPC_MPC8533,      POWERPC_SVR_8533,      e500v2)
     /* MPC8533 v1.0                                                          */
     POWERPC_DEF_SVR("MPC8533_v10",
-                    CPU_POWERPC_MPC8533_v10,  POWERPC_SVR_8533_v10,  e500v2),
+                    CPU_POWERPC_MPC8533_v10,  POWERPC_SVR_8533_v10,  e500v2)
     /* MPC8533 v1.1                                                          */
     POWERPC_DEF_SVR("MPC8533_v11",
-                    CPU_POWERPC_MPC8533_v11,  POWERPC_SVR_8533_v11,  e500v2),
+                    CPU_POWERPC_MPC8533_v11,  POWERPC_SVR_8533_v11,  e500v2)
     /* MPC8533E                                                              */
     POWERPC_DEF_SVR("MPC8533E",
-                    CPU_POWERPC_MPC8533E,     POWERPC_SVR_8533E,     e500v2),
+                    CPU_POWERPC_MPC8533E,     POWERPC_SVR_8533E,     e500v2)
     /* MPC8533E v1.0                                                         */
     POWERPC_DEF_SVR("MPC8533E_v10",
-                    CPU_POWERPC_MPC8533E_v10, POWERPC_SVR_8533E_v10, e500v2),
+                    CPU_POWERPC_MPC8533E_v10, POWERPC_SVR_8533E_v10, e500v2)
     POWERPC_DEF_SVR("MPC8533E_v11",
-                    CPU_POWERPC_MPC8533E_v11, POWERPC_SVR_8533E_v11, e500v2),
+                    CPU_POWERPC_MPC8533E_v11, POWERPC_SVR_8533E_v11, e500v2)
     /* MPC8540                                                               */
     POWERPC_DEF_SVR("MPC8540",
-                    CPU_POWERPC_MPC8540,      POWERPC_SVR_8540,      e500v1),
+                    CPU_POWERPC_MPC8540,      POWERPC_SVR_8540,      e500v1)
     /* MPC8540 v1.0                                                          */
     POWERPC_DEF_SVR("MPC8540_v10",
-                    CPU_POWERPC_MPC8540_v10,  POWERPC_SVR_8540_v10,  e500v1),
+                    CPU_POWERPC_MPC8540_v10,  POWERPC_SVR_8540_v10,  e500v1)
     /* MPC8540 v2.0                                                          */
     POWERPC_DEF_SVR("MPC8540_v20",
-                    CPU_POWERPC_MPC8540_v20,  POWERPC_SVR_8540_v20,  e500v1),
+                    CPU_POWERPC_MPC8540_v20,  POWERPC_SVR_8540_v20,  e500v1)
     /* MPC8540 v2.1                                                          */
     POWERPC_DEF_SVR("MPC8540_v21",
-                    CPU_POWERPC_MPC8540_v21,  POWERPC_SVR_8540_v21,  e500v1),
+                    CPU_POWERPC_MPC8540_v21,  POWERPC_SVR_8540_v21,  e500v1)
     /* MPC8541                                                               */
     POWERPC_DEF_SVR("MPC8541",
-                    CPU_POWERPC_MPC8541,      POWERPC_SVR_8541,      e500v1),
+                    CPU_POWERPC_MPC8541,      POWERPC_SVR_8541,      e500v1)
     /* MPC8541 v1.0                                                          */
     POWERPC_DEF_SVR("MPC8541_v10",
-                    CPU_POWERPC_MPC8541_v10,  POWERPC_SVR_8541_v10,  e500v1),
+                    CPU_POWERPC_MPC8541_v10,  POWERPC_SVR_8541_v10,  e500v1)
     /* MPC8541 v1.1                                                          */
     POWERPC_DEF_SVR("MPC8541_v11",
-                    CPU_POWERPC_MPC8541_v11,  POWERPC_SVR_8541_v11,  e500v1),
+                    CPU_POWERPC_MPC8541_v11,  POWERPC_SVR_8541_v11,  e500v1)
     /* MPC8541E                                                              */
     POWERPC_DEF_SVR("MPC8541E",
-                    CPU_POWERPC_MPC8541E,     POWERPC_SVR_8541E,     e500v1),
+                    CPU_POWERPC_MPC8541E,     POWERPC_SVR_8541E,     e500v1)
     /* MPC8541E v1.0                                                         */
     POWERPC_DEF_SVR("MPC8541E_v10",
-                    CPU_POWERPC_MPC8541E_v10, POWERPC_SVR_8541E_v10, e500v1),
+                    CPU_POWERPC_MPC8541E_v10, POWERPC_SVR_8541E_v10, e500v1)
     /* MPC8541E v1.1                                                         */
     POWERPC_DEF_SVR("MPC8541E_v11",
-                    CPU_POWERPC_MPC8541E_v11, POWERPC_SVR_8541E_v11, e500v1),
+                    CPU_POWERPC_MPC8541E_v11, POWERPC_SVR_8541E_v11, e500v1)
     /* MPC8543                                                               */
     POWERPC_DEF_SVR("MPC8543",
-                    CPU_POWERPC_MPC8543,      POWERPC_SVR_8543,      e500v2),
+                    CPU_POWERPC_MPC8543,      POWERPC_SVR_8543,      e500v2)
     /* MPC8543 v1.0                                                          */
     POWERPC_DEF_SVR("MPC8543_v10",
-                    CPU_POWERPC_MPC8543_v10,  POWERPC_SVR_8543_v10,  e500v2),
+                    CPU_POWERPC_MPC8543_v10,  POWERPC_SVR_8543_v10,  e500v2)
     /* MPC8543 v1.1                                                          */
     POWERPC_DEF_SVR("MPC8543_v11",
-                    CPU_POWERPC_MPC8543_v11,  POWERPC_SVR_8543_v11,  e500v2),
+                    CPU_POWERPC_MPC8543_v11,  POWERPC_SVR_8543_v11,  e500v2)
     /* MPC8543 v2.0                                                          */
     POWERPC_DEF_SVR("MPC8543_v20",
-                    CPU_POWERPC_MPC8543_v20,  POWERPC_SVR_8543_v20,  e500v2),
+                    CPU_POWERPC_MPC8543_v20,  POWERPC_SVR_8543_v20,  e500v2)
     /* MPC8543 v2.1                                                          */
     POWERPC_DEF_SVR("MPC8543_v21",
-                    CPU_POWERPC_MPC8543_v21,  POWERPC_SVR_8543_v21,  e500v2),
+                    CPU_POWERPC_MPC8543_v21,  POWERPC_SVR_8543_v21,  e500v2)
     /* MPC8543E                                                              */
     POWERPC_DEF_SVR("MPC8543E",
-                    CPU_POWERPC_MPC8543E,     POWERPC_SVR_8543E,     e500v2),
+                    CPU_POWERPC_MPC8543E,     POWERPC_SVR_8543E,     e500v2)
     /* MPC8543E v1.0                                                         */
     POWERPC_DEF_SVR("MPC8543E_v10",
-                    CPU_POWERPC_MPC8543E_v10, POWERPC_SVR_8543E_v10, e500v2),
+                    CPU_POWERPC_MPC8543E_v10, POWERPC_SVR_8543E_v10, e500v2)
     /* MPC8543E v1.1                                                         */
     POWERPC_DEF_SVR("MPC8543E_v11",
-                    CPU_POWERPC_MPC8543E_v11, POWERPC_SVR_8543E_v11, e500v2),
+                    CPU_POWERPC_MPC8543E_v11, POWERPC_SVR_8543E_v11, e500v2)
     /* MPC8543E v2.0                                                         */
     POWERPC_DEF_SVR("MPC8543E_v20",
-                    CPU_POWERPC_MPC8543E_v20, POWERPC_SVR_8543E_v20, e500v2),
+                    CPU_POWERPC_MPC8543E_v20, POWERPC_SVR_8543E_v20, e500v2)
     /* MPC8543E v2.1                                                         */
     POWERPC_DEF_SVR("MPC8543E_v21",
-                    CPU_POWERPC_MPC8543E_v21, POWERPC_SVR_8543E_v21, e500v2),
+                    CPU_POWERPC_MPC8543E_v21, POWERPC_SVR_8543E_v21, e500v2)
     /* MPC8544                                                               */
     POWERPC_DEF_SVR("MPC8544",
-                    CPU_POWERPC_MPC8544,      POWERPC_SVR_8544,      e500v2),
+                    CPU_POWERPC_MPC8544,      POWERPC_SVR_8544,      e500v2)
     /* MPC8544 v1.0                                                          */
     POWERPC_DEF_SVR("MPC8544_v10",
-                    CPU_POWERPC_MPC8544_v10,  POWERPC_SVR_8544_v10,  e500v2),
+                    CPU_POWERPC_MPC8544_v10,  POWERPC_SVR_8544_v10,  e500v2)
     /* MPC8544 v1.1                                                          */
     POWERPC_DEF_SVR("MPC8544_v11",
-                    CPU_POWERPC_MPC8544_v11,  POWERPC_SVR_8544_v11,  e500v2),
+                    CPU_POWERPC_MPC8544_v11,  POWERPC_SVR_8544_v11,  e500v2)
     /* MPC8544E                                                              */
     POWERPC_DEF_SVR("MPC8544E",
-                    CPU_POWERPC_MPC8544E,     POWERPC_SVR_8544E,     e500v2),
+                    CPU_POWERPC_MPC8544E,     POWERPC_SVR_8544E,     e500v2)
     /* MPC8544E v1.0                                                         */
     POWERPC_DEF_SVR("MPC8544E_v10",
-                    CPU_POWERPC_MPC8544E_v10, POWERPC_SVR_8544E_v10, e500v2),
+                    CPU_POWERPC_MPC8544E_v10, POWERPC_SVR_8544E_v10, e500v2)
     /* MPC8544E v1.1                                                         */
     POWERPC_DEF_SVR("MPC8544E_v11",
-                    CPU_POWERPC_MPC8544E_v11, POWERPC_SVR_8544E_v11, e500v2),
+                    CPU_POWERPC_MPC8544E_v11, POWERPC_SVR_8544E_v11, e500v2)
     /* MPC8545                                                               */
     POWERPC_DEF_SVR("MPC8545",
-                    CPU_POWERPC_MPC8545,      POWERPC_SVR_8545,      e500v2),
+                    CPU_POWERPC_MPC8545,      POWERPC_SVR_8545,      e500v2)
     /* MPC8545 v2.0                                                          */
     POWERPC_DEF_SVR("MPC8545_v20",
-                    CPU_POWERPC_MPC8545_v20,  POWERPC_SVR_8545_v20,  e500v2),
+                    CPU_POWERPC_MPC8545_v20,  POWERPC_SVR_8545_v20,  e500v2)
     /* MPC8545 v2.1                                                          */
     POWERPC_DEF_SVR("MPC8545_v21",
-                    CPU_POWERPC_MPC8545_v21,  POWERPC_SVR_8545_v21,  e500v2),
+                    CPU_POWERPC_MPC8545_v21,  POWERPC_SVR_8545_v21,  e500v2)
     /* MPC8545E                                                              */
     POWERPC_DEF_SVR("MPC8545E",
-                    CPU_POWERPC_MPC8545E,     POWERPC_SVR_8545E,     e500v2),
+                    CPU_POWERPC_MPC8545E,     POWERPC_SVR_8545E,     e500v2)
     /* MPC8545E v2.0                                                         */
     POWERPC_DEF_SVR("MPC8545E_v20",
-                    CPU_POWERPC_MPC8545E_v20, POWERPC_SVR_8545E_v20, e500v2),
+                    CPU_POWERPC_MPC8545E_v20, POWERPC_SVR_8545E_v20, e500v2)
     /* MPC8545E v2.1                                                         */
     POWERPC_DEF_SVR("MPC8545E_v21",
-                    CPU_POWERPC_MPC8545E_v21, POWERPC_SVR_8545E_v21, e500v2),
+                    CPU_POWERPC_MPC8545E_v21, POWERPC_SVR_8545E_v21, e500v2)
     /* MPC8547E                                                              */
     POWERPC_DEF_SVR("MPC8547E",
-                    CPU_POWERPC_MPC8547E,     POWERPC_SVR_8547E,     e500v2),
+                    CPU_POWERPC_MPC8547E,     POWERPC_SVR_8547E,     e500v2)
     /* MPC8547E v2.0                                                         */
     POWERPC_DEF_SVR("MPC8547E_v20",
-                    CPU_POWERPC_MPC8547E_v20, POWERPC_SVR_8547E_v20, e500v2),
+                    CPU_POWERPC_MPC8547E_v20, POWERPC_SVR_8547E_v20, e500v2)
     /* MPC8547E v2.1                                                         */
     POWERPC_DEF_SVR("MPC8547E_v21",
-                    CPU_POWERPC_MPC8547E_v21, POWERPC_SVR_8547E_v21, e500v2),
+                    CPU_POWERPC_MPC8547E_v21, POWERPC_SVR_8547E_v21, e500v2)
     /* MPC8548                                                               */
     POWERPC_DEF_SVR("MPC8548",
-                    CPU_POWERPC_MPC8548,      POWERPC_SVR_8548,      e500v2),
+                    CPU_POWERPC_MPC8548,      POWERPC_SVR_8548,      e500v2)
     /* MPC8548 v1.0                                                          */
     POWERPC_DEF_SVR("MPC8548_v10",
-                    CPU_POWERPC_MPC8548_v10,  POWERPC_SVR_8548_v10,  e500v2),
+                    CPU_POWERPC_MPC8548_v10,  POWERPC_SVR_8548_v10,  e500v2)
     /* MPC8548 v1.1                                                          */
     POWERPC_DEF_SVR("MPC8548_v11",
-                    CPU_POWERPC_MPC8548_v11,  POWERPC_SVR_8548_v11,  e500v2),
+                    CPU_POWERPC_MPC8548_v11,  POWERPC_SVR_8548_v11,  e500v2)
     /* MPC8548 v2.0                                                          */
     POWERPC_DEF_SVR("MPC8548_v20",
-                    CPU_POWERPC_MPC8548_v20,  POWERPC_SVR_8548_v20,  e500v2),
+                    CPU_POWERPC_MPC8548_v20,  POWERPC_SVR_8548_v20,  e500v2)
     /* MPC8548 v2.1                                                          */
     POWERPC_DEF_SVR("MPC8548_v21",
-                    CPU_POWERPC_MPC8548_v21,  POWERPC_SVR_8548_v21,  e500v2),
+                    CPU_POWERPC_MPC8548_v21,  POWERPC_SVR_8548_v21,  e500v2)
     /* MPC8548E                                                              */
     POWERPC_DEF_SVR("MPC8548E",
-                    CPU_POWERPC_MPC8548E,     POWERPC_SVR_8548E,     e500v2),
+                    CPU_POWERPC_MPC8548E,     POWERPC_SVR_8548E,     e500v2)
     /* MPC8548E v1.0                                                         */
     POWERPC_DEF_SVR("MPC8548E_v10",
-                    CPU_POWERPC_MPC8548E_v10, POWERPC_SVR_8548E_v10, e500v2),
+                    CPU_POWERPC_MPC8548E_v10, POWERPC_SVR_8548E_v10, e500v2)
     /* MPC8548E v1.1                                                         */
     POWERPC_DEF_SVR("MPC8548E_v11",
-                    CPU_POWERPC_MPC8548E_v11, POWERPC_SVR_8548E_v11, e500v2),
+                    CPU_POWERPC_MPC8548E_v11, POWERPC_SVR_8548E_v11, e500v2)
     /* MPC8548E v2.0                                                         */
     POWERPC_DEF_SVR("MPC8548E_v20",
-                    CPU_POWERPC_MPC8548E_v20, POWERPC_SVR_8548E_v20, e500v2),
+                    CPU_POWERPC_MPC8548E_v20, POWERPC_SVR_8548E_v20, e500v2)
     /* MPC8548E v2.1                                                         */
     POWERPC_DEF_SVR("MPC8548E_v21",
-                    CPU_POWERPC_MPC8548E_v21, POWERPC_SVR_8548E_v21, e500v2),
+                    CPU_POWERPC_MPC8548E_v21, POWERPC_SVR_8548E_v21, e500v2)
     /* MPC8555                                                               */
     POWERPC_DEF_SVR("MPC8555",
-                    CPU_POWERPC_MPC8555,      POWERPC_SVR_8555,      e500v2),
+                    CPU_POWERPC_MPC8555,      POWERPC_SVR_8555,      e500v2)
     /* MPC8555 v1.0                                                          */
     POWERPC_DEF_SVR("MPC8555_v10",
-                    CPU_POWERPC_MPC8555_v10,  POWERPC_SVR_8555_v10,  e500v2),
+                    CPU_POWERPC_MPC8555_v10,  POWERPC_SVR_8555_v10,  e500v2)
     /* MPC8555 v1.1                                                          */
     POWERPC_DEF_SVR("MPC8555_v11",
-                    CPU_POWERPC_MPC8555_v11,  POWERPC_SVR_8555_v11,  e500v2),
+                    CPU_POWERPC_MPC8555_v11,  POWERPC_SVR_8555_v11,  e500v2)
     /* MPC8555E                                                              */
     POWERPC_DEF_SVR("MPC8555E",
-                    CPU_POWERPC_MPC8555E,     POWERPC_SVR_8555E,     e500v2),
+                    CPU_POWERPC_MPC8555E,     POWERPC_SVR_8555E,     e500v2)
     /* MPC8555E v1.0                                                         */
     POWERPC_DEF_SVR("MPC8555E_v10",
-                    CPU_POWERPC_MPC8555E_v10, POWERPC_SVR_8555E_v10, e500v2),
+                    CPU_POWERPC_MPC8555E_v10, POWERPC_SVR_8555E_v10, e500v2)
     /* MPC8555E v1.1                                                         */
     POWERPC_DEF_SVR("MPC8555E_v11",
-                    CPU_POWERPC_MPC8555E_v11, POWERPC_SVR_8555E_v11, e500v2),
+                    CPU_POWERPC_MPC8555E_v11, POWERPC_SVR_8555E_v11, e500v2)
     /* MPC8560                                                               */
     POWERPC_DEF_SVR("MPC8560",
-                    CPU_POWERPC_MPC8560,      POWERPC_SVR_8560,      e500v2),
+                    CPU_POWERPC_MPC8560,      POWERPC_SVR_8560,      e500v2)
     /* MPC8560 v1.0                                                          */
     POWERPC_DEF_SVR("MPC8560_v10",
-                    CPU_POWERPC_MPC8560_v10,  POWERPC_SVR_8560_v10,  e500v2),
+                    CPU_POWERPC_MPC8560_v10,  POWERPC_SVR_8560_v10,  e500v2)
     /* MPC8560 v2.0                                                          */
     POWERPC_DEF_SVR("MPC8560_v20",
-                    CPU_POWERPC_MPC8560_v20,  POWERPC_SVR_8560_v20,  e500v2),
+                    CPU_POWERPC_MPC8560_v20,  POWERPC_SVR_8560_v20,  e500v2)
     /* MPC8560 v2.1                                                          */
     POWERPC_DEF_SVR("MPC8560_v21",
-                    CPU_POWERPC_MPC8560_v21,  POWERPC_SVR_8560_v21,  e500v2),
+                    CPU_POWERPC_MPC8560_v21,  POWERPC_SVR_8560_v21,  e500v2)
     /* MPC8567                                                               */
     POWERPC_DEF_SVR("MPC8567",
-                    CPU_POWERPC_MPC8567,      POWERPC_SVR_8567,      e500v2),
+                    CPU_POWERPC_MPC8567,      POWERPC_SVR_8567,      e500v2)
     /* MPC8567E                                                              */
     POWERPC_DEF_SVR("MPC8567E",
-                    CPU_POWERPC_MPC8567E,     POWERPC_SVR_8567E,     e500v2),
+                    CPU_POWERPC_MPC8567E,     POWERPC_SVR_8567E,     e500v2)
     /* MPC8568                                                               */
     POWERPC_DEF_SVR("MPC8568",
-                    CPU_POWERPC_MPC8568,      POWERPC_SVR_8568,      e500v2),
+                    CPU_POWERPC_MPC8568,      POWERPC_SVR_8568,      e500v2)
     /* MPC8568E                                                              */
     POWERPC_DEF_SVR("MPC8568E",
-                    CPU_POWERPC_MPC8568E,     POWERPC_SVR_8568E,     e500v2),
+                    CPU_POWERPC_MPC8568E,     POWERPC_SVR_8568E,     e500v2)
     /* MPC8572                                                               */
     POWERPC_DEF_SVR("MPC8572",
-                    CPU_POWERPC_MPC8572,      POWERPC_SVR_8572,      e500v2),
+                    CPU_POWERPC_MPC8572,      POWERPC_SVR_8572,      e500v2)
     /* MPC8572E                                                              */
     POWERPC_DEF_SVR("MPC8572E",
-                    CPU_POWERPC_MPC8572E,     POWERPC_SVR_8572E,     e500v2),
+                    CPU_POWERPC_MPC8572E,     POWERPC_SVR_8572E,     e500v2)
     /* e600 family                                                           */
     /* PowerPC e600 core                                                     */
-    POWERPC_DEF("e600",          CPU_POWERPC_e600,                   7400),
+    POWERPC_DEF("e600",          CPU_POWERPC_e600,                   7400)
     /* PowerPC e600 microcontrollers                                         */
 #if defined (TODO)
     /* MPC8610                                                               */
     POWERPC_DEF_SVR("MPC8610",
-                    CPU_POWERPC_MPC8610,      POWERPC_SVR_8610,      7400),
+                    CPU_POWERPC_MPC8610,      POWERPC_SVR_8610,      7400)
 #endif
     /* MPC8641                                                               */
     POWERPC_DEF_SVR("MPC8641",
-                    CPU_POWERPC_MPC8641,      POWERPC_SVR_8641,      7400),
+                    CPU_POWERPC_MPC8641,      POWERPC_SVR_8641,      7400)
     /* MPC8641D                                                              */
     POWERPC_DEF_SVR("MPC8641D",
-                    CPU_POWERPC_MPC8641D,     POWERPC_SVR_8641D,     7400),
+                    CPU_POWERPC_MPC8641D,     POWERPC_SVR_8641D,     7400)
     /* 32 bits "classic" PowerPC                                             */
     /* PowerPC 6xx family                                                    */
     /* PowerPC 601                                                           */
-    POWERPC_DEF("601",           CPU_POWERPC_601,                    601v),
+    POWERPC_DEF("601",           CPU_POWERPC_601,                    601v)
     /* PowerPC 601v0                                                         */
-    POWERPC_DEF("601_v0",        CPU_POWERPC_601_v0,                 601),
+    POWERPC_DEF("601_v0",        CPU_POWERPC_601_v0,                 601)
     /* PowerPC 601v1                                                         */
-    POWERPC_DEF("601_v1",        CPU_POWERPC_601_v1,                 601),
+    POWERPC_DEF("601_v1",        CPU_POWERPC_601_v1,                 601)
     /* PowerPC 601v                                                          */
-    POWERPC_DEF("601v",          CPU_POWERPC_601v,                   601v),
+    POWERPC_DEF("601v",          CPU_POWERPC_601v,                   601v)
     /* PowerPC 601v2                                                         */
-    POWERPC_DEF("601_v2",        CPU_POWERPC_601_v2,                 601v),
+    POWERPC_DEF("601_v2",        CPU_POWERPC_601_v2,                 601v)
     /* PowerPC 602                                                           */
-    POWERPC_DEF("602",           CPU_POWERPC_602,                    602),
+    POWERPC_DEF("602",           CPU_POWERPC_602,                    602)
     /* PowerPC 603                                                           */
-    POWERPC_DEF("603",           CPU_POWERPC_603,                    603),
+    POWERPC_DEF("603",           CPU_POWERPC_603,                    603)
     /* Code name for PowerPC 603                                             */
-    POWERPC_DEF("Vanilla",       CPU_POWERPC_603,                    603),
+    POWERPC_DEF("Vanilla",       CPU_POWERPC_603,                    603)
     /* PowerPC 603e (aka PID6)                                               */
-    POWERPC_DEF("603e",          CPU_POWERPC_603E,                   603E),
+    POWERPC_DEF("603e",          CPU_POWERPC_603E,                   603E)
     /* Code name for PowerPC 603e                                            */
-    POWERPC_DEF("Stretch",       CPU_POWERPC_603E,                   603E),
+    POWERPC_DEF("Stretch",       CPU_POWERPC_603E,                   603E)
     /* PowerPC 603e v1.1                                                     */
-    POWERPC_DEF("603e_v1.1",     CPU_POWERPC_603E_v11,               603E),
+    POWERPC_DEF("603e_v1.1",     CPU_POWERPC_603E_v11,               603E)
     /* PowerPC 603e v1.2                                                     */
-    POWERPC_DEF("603e_v1.2",     CPU_POWERPC_603E_v12,               603E),
+    POWERPC_DEF("603e_v1.2",     CPU_POWERPC_603E_v12,               603E)
     /* PowerPC 603e v1.3                                                     */
-    POWERPC_DEF("603e_v1.3",     CPU_POWERPC_603E_v13,               603E),
+    POWERPC_DEF("603e_v1.3",     CPU_POWERPC_603E_v13,               603E)
     /* PowerPC 603e v1.4                                                     */
-    POWERPC_DEF("603e_v1.4",     CPU_POWERPC_603E_v14,               603E),
+    POWERPC_DEF("603e_v1.4",     CPU_POWERPC_603E_v14,               603E)
     /* PowerPC 603e v2.2                                                     */
-    POWERPC_DEF("603e_v2.2",     CPU_POWERPC_603E_v22,               603E),
+    POWERPC_DEF("603e_v2.2",     CPU_POWERPC_603E_v22,               603E)
     /* PowerPC 603e v3                                                       */
-    POWERPC_DEF("603e_v3",       CPU_POWERPC_603E_v3,                603E),
+    POWERPC_DEF("603e_v3",       CPU_POWERPC_603E_v3,                603E)
     /* PowerPC 603e v4                                                       */
-    POWERPC_DEF("603e_v4",       CPU_POWERPC_603E_v4,                603E),
+    POWERPC_DEF("603e_v4",       CPU_POWERPC_603E_v4,                603E)
     /* PowerPC 603e v4.1                                                     */
-    POWERPC_DEF("603e_v4.1",     CPU_POWERPC_603E_v41,               603E),
+    POWERPC_DEF("603e_v4.1",     CPU_POWERPC_603E_v41,               603E)
     /* PowerPC 603e (aka PID7)                                               */
-    POWERPC_DEF("603e7",         CPU_POWERPC_603E7,                  603E),
+    POWERPC_DEF("603e7",         CPU_POWERPC_603E7,                  603E)
     /* PowerPC 603e7t                                                        */
-    POWERPC_DEF("603e7t",        CPU_POWERPC_603E7t,                 603E),
+    POWERPC_DEF("603e7t",        CPU_POWERPC_603E7t,                 603E)
     /* PowerPC 603e7v                                                        */
-    POWERPC_DEF("603e7v",        CPU_POWERPC_603E7v,                 603E),
+    POWERPC_DEF("603e7v",        CPU_POWERPC_603E7v,                 603E)
     /* Code name for PowerPC 603ev                                           */
-    POWERPC_DEF("Vaillant",      CPU_POWERPC_603E7v,                 603E),
+    POWERPC_DEF("Vaillant",      CPU_POWERPC_603E7v,                 603E)
     /* PowerPC 603e7v1                                                       */
-    POWERPC_DEF("603e7v1",       CPU_POWERPC_603E7v1,                603E),
+    POWERPC_DEF("603e7v1",       CPU_POWERPC_603E7v1,                603E)
     /* PowerPC 603e7v2                                                       */
-    POWERPC_DEF("603e7v2",       CPU_POWERPC_603E7v2,                603E),
+    POWERPC_DEF("603e7v2",       CPU_POWERPC_603E7v2,                603E)
     /* PowerPC 603p (aka PID7v)                                              */
-    POWERPC_DEF("603p",          CPU_POWERPC_603P,                   603E),
+    POWERPC_DEF("603p",          CPU_POWERPC_603P,                   603E)
     /* PowerPC 603r (aka PID7t)                                              */
-    POWERPC_DEF("603r",          CPU_POWERPC_603R,                   603E),
+    POWERPC_DEF("603r",          CPU_POWERPC_603R,                   603E)
     /* Code name for PowerPC 603r                                            */
-    POWERPC_DEF("Goldeneye",     CPU_POWERPC_603R,                   603E),
+    POWERPC_DEF("Goldeneye",     CPU_POWERPC_603R,                   603E)
     /* PowerPC 604                                                           */
-    POWERPC_DEF("604",           CPU_POWERPC_604,                    604),
+    POWERPC_DEF("604",           CPU_POWERPC_604,                    604)
     /* PowerPC 604e (aka PID9)                                               */
-    POWERPC_DEF("604e",          CPU_POWERPC_604E,                   604E),
+    POWERPC_DEF("604e",          CPU_POWERPC_604E,                   604E)
     /* Code name for PowerPC 604e                                            */
-    POWERPC_DEF("Sirocco",       CPU_POWERPC_604E,                   604E),
+    POWERPC_DEF("Sirocco",       CPU_POWERPC_604E,                   604E)
     /* PowerPC 604e v1.0                                                     */
-    POWERPC_DEF("604e_v1.0",     CPU_POWERPC_604E_v10,               604E),
+    POWERPC_DEF("604e_v1.0",     CPU_POWERPC_604E_v10,               604E)
     /* PowerPC 604e v2.2                                                     */
-    POWERPC_DEF("604e_v2.2",     CPU_POWERPC_604E_v22,               604E),
+    POWERPC_DEF("604e_v2.2",     CPU_POWERPC_604E_v22,               604E)
     /* PowerPC 604e v2.4                                                     */
-    POWERPC_DEF("604e_v2.4",     CPU_POWERPC_604E_v24,               604E),
+    POWERPC_DEF("604e_v2.4",     CPU_POWERPC_604E_v24,               604E)
     /* PowerPC 604r (aka PIDA)                                               */
-    POWERPC_DEF("604r",          CPU_POWERPC_604R,                   604E),
+    POWERPC_DEF("604r",          CPU_POWERPC_604R,                   604E)
     /* Code name for PowerPC 604r                                            */
-    POWERPC_DEF("Mach5",         CPU_POWERPC_604R,                   604E),
+    POWERPC_DEF("Mach5",         CPU_POWERPC_604R,                   604E)
 #if defined(TODO)
     /* PowerPC 604ev                                                         */
-    POWERPC_DEF("604ev",         CPU_POWERPC_604EV,                  604E),
+    POWERPC_DEF("604ev",         CPU_POWERPC_604EV,                  604E)
 #endif
     /* PowerPC 7xx family                                                    */
     /* Generic PowerPC 740 (G3)                                              */
-    POWERPC_DEF("740",           CPU_POWERPC_7x0,                    740),
+    POWERPC_DEF("740",           CPU_POWERPC_7x0,                    740)
     /* Code name for PowerPC 740                                             */
-    POWERPC_DEF("Arthur",        CPU_POWERPC_7x0,                    740),
+    POWERPC_DEF("Arthur",        CPU_POWERPC_7x0,                    740)
     /* Generic PowerPC 750 (G3)                                              */
-    POWERPC_DEF("750",           CPU_POWERPC_7x0,                    750),
+    POWERPC_DEF("750",           CPU_POWERPC_7x0,                    750)
     /* Code name for PowerPC 750                                             */
-    POWERPC_DEF("Typhoon",       CPU_POWERPC_7x0,                    750),
+    POWERPC_DEF("Typhoon",       CPU_POWERPC_7x0,                    750)
     /* PowerPC 740/750 is also known as G3                                   */
-    POWERPC_DEF("G3",            CPU_POWERPC_7x0,                    750),
+    POWERPC_DEF("G3",            CPU_POWERPC_7x0,                    750)
     /* PowerPC 740 v1.0 (G3)                                                 */
-    POWERPC_DEF("740_v1.0",      CPU_POWERPC_7x0_v10,                740),
+    POWERPC_DEF("740_v1.0",      CPU_POWERPC_7x0_v10,                740)
     /* PowerPC 750 v1.0 (G3)                                                 */
-    POWERPC_DEF("750_v1.0",      CPU_POWERPC_7x0_v10,                750),
+    POWERPC_DEF("750_v1.0",      CPU_POWERPC_7x0_v10,                750)
     /* PowerPC 740 v2.0 (G3)                                                 */
-    POWERPC_DEF("740_v2.0",      CPU_POWERPC_7x0_v20,                740),
+    POWERPC_DEF("740_v2.0",      CPU_POWERPC_7x0_v20,                740)
     /* PowerPC 750 v2.0 (G3)                                                 */
-    POWERPC_DEF("750_v2.0",      CPU_POWERPC_7x0_v20,                750),
+    POWERPC_DEF("750_v2.0",      CPU_POWERPC_7x0_v20,                750)
     /* PowerPC 740 v2.1 (G3)                                                 */
-    POWERPC_DEF("740_v2.1",      CPU_POWERPC_7x0_v21,                740),
+    POWERPC_DEF("740_v2.1",      CPU_POWERPC_7x0_v21,                740)
     /* PowerPC 750 v2.1 (G3)                                                 */
-    POWERPC_DEF("750_v2.1",      CPU_POWERPC_7x0_v21,                750),
+    POWERPC_DEF("750_v2.1",      CPU_POWERPC_7x0_v21,                750)
     /* PowerPC 740 v2.2 (G3)                                                 */
-    POWERPC_DEF("740_v2.2",      CPU_POWERPC_7x0_v22,                740),
+    POWERPC_DEF("740_v2.2",      CPU_POWERPC_7x0_v22,                740)
     /* PowerPC 750 v2.2 (G3)                                                 */
-    POWERPC_DEF("750_v2.2",      CPU_POWERPC_7x0_v22,                750),
+    POWERPC_DEF("750_v2.2",      CPU_POWERPC_7x0_v22,                750)
     /* PowerPC 740 v3.0 (G3)                                                 */
-    POWERPC_DEF("740_v3.0",      CPU_POWERPC_7x0_v30,                740),
+    POWERPC_DEF("740_v3.0",      CPU_POWERPC_7x0_v30,                740)
     /* PowerPC 750 v3.0 (G3)                                                 */
-    POWERPC_DEF("750_v3.0",      CPU_POWERPC_7x0_v30,                750),
+    POWERPC_DEF("750_v3.0",      CPU_POWERPC_7x0_v30,                750)
     /* PowerPC 740 v3.1 (G3)                                                 */
-    POWERPC_DEF("740_v3.1",      CPU_POWERPC_7x0_v31,                740),
+    POWERPC_DEF("740_v3.1",      CPU_POWERPC_7x0_v31,                740)
     /* PowerPC 750 v3.1 (G3)                                                 */
-    POWERPC_DEF("750_v3.1",      CPU_POWERPC_7x0_v31,                750),
+    POWERPC_DEF("750_v3.1",      CPU_POWERPC_7x0_v31,                750)
     /* PowerPC 740E (G3)                                                     */
-    POWERPC_DEF("740e",          CPU_POWERPC_740E,                   740),
+    POWERPC_DEF("740e",          CPU_POWERPC_740E,                   740)
     /* PowerPC 750E (G3)                                                     */
-    POWERPC_DEF("750e",          CPU_POWERPC_750E,                   750),
+    POWERPC_DEF("750e",          CPU_POWERPC_750E,                   750)
     /* PowerPC 740P (G3)                                                     */
-    POWERPC_DEF("740p",          CPU_POWERPC_7x0P,                   740),
+    POWERPC_DEF("740p",          CPU_POWERPC_7x0P,                   740)
     /* PowerPC 750P (G3)                                                     */
-    POWERPC_DEF("750p",          CPU_POWERPC_7x0P,                   750),
+    POWERPC_DEF("750p",          CPU_POWERPC_7x0P,                   750)
     /* Code name for PowerPC 740P/750P (G3)                                  */
-    POWERPC_DEF("Conan/Doyle",   CPU_POWERPC_7x0P,                   750),
+    POWERPC_DEF("Conan/Doyle",   CPU_POWERPC_7x0P,                   750)
     /* PowerPC 750CL (G3 embedded)                                           */
-    POWERPC_DEF("750cl",         CPU_POWERPC_750CL,                  750cl),
+    POWERPC_DEF("750cl",         CPU_POWERPC_750CL,                  750cl)
     /* PowerPC 750CL v1.0                                                    */
-    POWERPC_DEF("750cl_v1.0",    CPU_POWERPC_750CL_v10,              750cl),
+    POWERPC_DEF("750cl_v1.0",    CPU_POWERPC_750CL_v10,              750cl)
     /* PowerPC 750CL v2.0                                                    */
-    POWERPC_DEF("750cl_v2.0",    CPU_POWERPC_750CL_v20,              750cl),
+    POWERPC_DEF("750cl_v2.0",    CPU_POWERPC_750CL_v20,              750cl)
     /* PowerPC 750CX (G3 embedded)                                           */
-    POWERPC_DEF("750cx",         CPU_POWERPC_750CX,                  750cx),
+    POWERPC_DEF("750cx",         CPU_POWERPC_750CX,                  750cx)
     /* PowerPC 750CX v1.0 (G3 embedded)                                      */
-    POWERPC_DEF("750cx_v1.0",    CPU_POWERPC_750CX_v10,              750cx),
+    POWERPC_DEF("750cx_v1.0",    CPU_POWERPC_750CX_v10,              750cx)
     /* PowerPC 750CX v2.1 (G3 embedded)                                      */
-    POWERPC_DEF("750cx_v2.0",    CPU_POWERPC_750CX_v20,              750cx),
+    POWERPC_DEF("750cx_v2.0",    CPU_POWERPC_750CX_v20,              750cx)
     /* PowerPC 750CX v2.1 (G3 embedded)                                      */
-    POWERPC_DEF("750cx_v2.1",    CPU_POWERPC_750CX_v21,              750cx),
+    POWERPC_DEF("750cx_v2.1",    CPU_POWERPC_750CX_v21,              750cx)
     /* PowerPC 750CX v2.2 (G3 embedded)                                      */
-    POWERPC_DEF("750cx_v2.2",    CPU_POWERPC_750CX_v22,              750cx),
+    POWERPC_DEF("750cx_v2.2",    CPU_POWERPC_750CX_v22,              750cx)
     /* PowerPC 750CXe (G3 embedded)                                          */
-    POWERPC_DEF("750cxe",        CPU_POWERPC_750CXE,                 750cx),
+    POWERPC_DEF("750cxe",        CPU_POWERPC_750CXE,                 750cx)
     /* PowerPC 750CXe v2.1 (G3 embedded)                                     */
-    POWERPC_DEF("750cxe_v2.1",   CPU_POWERPC_750CXE_v21,             750cx),
+    POWERPC_DEF("750cxe_v2.1",   CPU_POWERPC_750CXE_v21,             750cx)
     /* PowerPC 750CXe v2.2 (G3 embedded)                                     */
-    POWERPC_DEF("750cxe_v2.2",   CPU_POWERPC_750CXE_v22,             750cx),
+    POWERPC_DEF("750cxe_v2.2",   CPU_POWERPC_750CXE_v22,             750cx)
     /* PowerPC 750CXe v2.3 (G3 embedded)                                     */
-    POWERPC_DEF("750cxe_v2.3",   CPU_POWERPC_750CXE_v23,             750cx),
+    POWERPC_DEF("750cxe_v2.3",   CPU_POWERPC_750CXE_v23,             750cx)
     /* PowerPC 750CXe v2.4 (G3 embedded)                                     */
-    POWERPC_DEF("750cxe_v2.4",   CPU_POWERPC_750CXE_v24,             750cx),
+    POWERPC_DEF("750cxe_v2.4",   CPU_POWERPC_750CXE_v24,             750cx)
     /* PowerPC 750CXe v2.4b (G3 embedded)                                    */
-    POWERPC_DEF("750cxe_v2.4b",  CPU_POWERPC_750CXE_v24b,            750cx),
+    POWERPC_DEF("750cxe_v2.4b",  CPU_POWERPC_750CXE_v24b,            750cx)
     /* PowerPC 750CXe v3.0 (G3 embedded)                                     */
-    POWERPC_DEF("750cxe_v3.0",   CPU_POWERPC_750CXE_v30,             750cx),
+    POWERPC_DEF("750cxe_v3.0",   CPU_POWERPC_750CXE_v30,             750cx)
     /* PowerPC 750CXe v3.1 (G3 embedded)                                     */
-    POWERPC_DEF("750cxe_v3.1",   CPU_POWERPC_750CXE_v31,             750cx),
+    POWERPC_DEF("750cxe_v3.1",   CPU_POWERPC_750CXE_v31,             750cx)
     /* PowerPC 750CXe v3.1b (G3 embedded)                                    */
-    POWERPC_DEF("750cxe_v3.1b",  CPU_POWERPC_750CXE_v31b,            750cx),
+    POWERPC_DEF("750cxe_v3.1b",  CPU_POWERPC_750CXE_v31b,            750cx)
     /* PowerPC 750CXr (G3 embedded)                                          */
-    POWERPC_DEF("750cxr",        CPU_POWERPC_750CXR,                 750cx),
+    POWERPC_DEF("750cxr",        CPU_POWERPC_750CXR,                 750cx)
     /* PowerPC 750FL (G3 embedded)                                           */
-    POWERPC_DEF("750fl",         CPU_POWERPC_750FL,                  750fx),
+    POWERPC_DEF("750fl",         CPU_POWERPC_750FL,                  750fx)
     /* PowerPC 750FX (G3 embedded)                                           */
-    POWERPC_DEF("750fx",         CPU_POWERPC_750FX,                  750fx),
+    POWERPC_DEF("750fx",         CPU_POWERPC_750FX,                  750fx)
     /* PowerPC 750FX v1.0 (G3 embedded)                                      */
-    POWERPC_DEF("750fx_v1.0",    CPU_POWERPC_750FX_v10,              750fx),
+    POWERPC_DEF("750fx_v1.0",    CPU_POWERPC_750FX_v10,              750fx)
     /* PowerPC 750FX v2.0 (G3 embedded)                                      */
-    POWERPC_DEF("750fx_v2.0",    CPU_POWERPC_750FX_v20,              750fx),
+    POWERPC_DEF("750fx_v2.0",    CPU_POWERPC_750FX_v20,              750fx)
     /* PowerPC 750FX v2.1 (G3 embedded)                                      */
-    POWERPC_DEF("750fx_v2.1",    CPU_POWERPC_750FX_v21,              750fx),
+    POWERPC_DEF("750fx_v2.1",    CPU_POWERPC_750FX_v21,              750fx)
     /* PowerPC 750FX v2.2 (G3 embedded)                                      */
-    POWERPC_DEF("750fx_v2.2",    CPU_POWERPC_750FX_v22,              750fx),
+    POWERPC_DEF("750fx_v2.2",    CPU_POWERPC_750FX_v22,              750fx)
     /* PowerPC 750FX v2.3 (G3 embedded)                                      */
-    POWERPC_DEF("750fx_v2.3",    CPU_POWERPC_750FX_v23,              750fx),
+    POWERPC_DEF("750fx_v2.3",    CPU_POWERPC_750FX_v23,              750fx)
     /* PowerPC 750GL (G3 embedded)                                           */
-    POWERPC_DEF("750gl",         CPU_POWERPC_750GL,                  750gx),
+    POWERPC_DEF("750gl",         CPU_POWERPC_750GL,                  750gx)
     /* PowerPC 750GX (G3 embedded)                                           */
-    POWERPC_DEF("750gx",         CPU_POWERPC_750GX,                  750gx),
+    POWERPC_DEF("750gx",         CPU_POWERPC_750GX,                  750gx)
     /* PowerPC 750GX v1.0 (G3 embedded)                                      */
-    POWERPC_DEF("750gx_v1.0",    CPU_POWERPC_750GX_v10,              750gx),
+    POWERPC_DEF("750gx_v1.0",    CPU_POWERPC_750GX_v10,              750gx)
     /* PowerPC 750GX v1.1 (G3 embedded)                                      */
-    POWERPC_DEF("750gx_v1.1",    CPU_POWERPC_750GX_v11,              750gx),
+    POWERPC_DEF("750gx_v1.1",    CPU_POWERPC_750GX_v11,              750gx)
     /* PowerPC 750GX v1.2 (G3 embedded)                                      */
-    POWERPC_DEF("750gx_v1.2",    CPU_POWERPC_750GX_v12,              750gx),
+    POWERPC_DEF("750gx_v1.2",    CPU_POWERPC_750GX_v12,              750gx)
     /* PowerPC 750L (G3 embedded)                                            */
-    POWERPC_DEF("750l",          CPU_POWERPC_750L,                   750),
+    POWERPC_DEF("750l",          CPU_POWERPC_750L,                   750)
     /* Code name for PowerPC 750L (G3 embedded)                              */
-    POWERPC_DEF("LoneStar",      CPU_POWERPC_750L,                   750),
+    POWERPC_DEF("LoneStar",      CPU_POWERPC_750L,                   750)
     /* PowerPC 750L v2.0 (G3 embedded)                                       */
-    POWERPC_DEF("750l_v2.0",     CPU_POWERPC_750L_v20,               750),
+    POWERPC_DEF("750l_v2.0",     CPU_POWERPC_750L_v20,               750)
     /* PowerPC 750L v2.1 (G3 embedded)                                       */
-    POWERPC_DEF("750l_v2.1",     CPU_POWERPC_750L_v21,               750),
+    POWERPC_DEF("750l_v2.1",     CPU_POWERPC_750L_v21,               750)
     /* PowerPC 750L v2.2 (G3 embedded)                                       */
-    POWERPC_DEF("750l_v2.2",     CPU_POWERPC_750L_v22,               750),
+    POWERPC_DEF("750l_v2.2",     CPU_POWERPC_750L_v22,               750)
     /* PowerPC 750L v3.0 (G3 embedded)                                       */
-    POWERPC_DEF("750l_v3.0",     CPU_POWERPC_750L_v30,               750),
+    POWERPC_DEF("750l_v3.0",     CPU_POWERPC_750L_v30,               750)
     /* PowerPC 750L v3.2 (G3 embedded)                                       */
-    POWERPC_DEF("750l_v3.2",     CPU_POWERPC_750L_v32,               750),
+    POWERPC_DEF("750l_v3.2",     CPU_POWERPC_750L_v32,               750)
     /* Generic PowerPC 745                                                   */
-    POWERPC_DEF("745",           CPU_POWERPC_7x5,                    745),
+    POWERPC_DEF("745",           CPU_POWERPC_7x5,                    745)
     /* Generic PowerPC 755                                                   */
-    POWERPC_DEF("755",           CPU_POWERPC_7x5,                    755),
+    POWERPC_DEF("755",           CPU_POWERPC_7x5,                    755)
     /* Code name for PowerPC 745/755                                         */
-    POWERPC_DEF("Goldfinger",    CPU_POWERPC_7x5,                    755),
+    POWERPC_DEF("Goldfinger",    CPU_POWERPC_7x5,                    755)
     /* PowerPC 745 v1.0                                                      */
-    POWERPC_DEF("745_v1.0",      CPU_POWERPC_7x5_v10,                745),
+    POWERPC_DEF("745_v1.0",      CPU_POWERPC_7x5_v10,                745)
     /* PowerPC 755 v1.0                                                      */
-    POWERPC_DEF("755_v1.0",      CPU_POWERPC_7x5_v10,                755),
+    POWERPC_DEF("755_v1.0",      CPU_POWERPC_7x5_v10,                755)
     /* PowerPC 745 v1.1                                                      */
-    POWERPC_DEF("745_v1.1",      CPU_POWERPC_7x5_v11,                745),
+    POWERPC_DEF("745_v1.1",      CPU_POWERPC_7x5_v11,                745)
     /* PowerPC 755 v1.1                                                      */
-    POWERPC_DEF("755_v1.1",      CPU_POWERPC_7x5_v11,                755),
+    POWERPC_DEF("755_v1.1",      CPU_POWERPC_7x5_v11,                755)
     /* PowerPC 745 v2.0                                                      */
-    POWERPC_DEF("745_v2.0",      CPU_POWERPC_7x5_v20,                745),
+    POWERPC_DEF("745_v2.0",      CPU_POWERPC_7x5_v20,                745)
     /* PowerPC 755 v2.0                                                      */
-    POWERPC_DEF("755_v2.0",      CPU_POWERPC_7x5_v20,                755),
+    POWERPC_DEF("755_v2.0",      CPU_POWERPC_7x5_v20,                755)
     /* PowerPC 745 v2.1                                                      */
-    POWERPC_DEF("745_v2.1",      CPU_POWERPC_7x5_v21,                745),
+    POWERPC_DEF("745_v2.1",      CPU_POWERPC_7x5_v21,                745)
     /* PowerPC 755 v2.1                                                      */
-    POWERPC_DEF("755_v2.1",      CPU_POWERPC_7x5_v21,                755),
+    POWERPC_DEF("755_v2.1",      CPU_POWERPC_7x5_v21,                755)
     /* PowerPC 745 v2.2                                                      */
-    POWERPC_DEF("745_v2.2",      CPU_POWERPC_7x5_v22,                745),
+    POWERPC_DEF("745_v2.2",      CPU_POWERPC_7x5_v22,                745)
     /* PowerPC 755 v2.2                                                      */
-    POWERPC_DEF("755_v2.2",      CPU_POWERPC_7x5_v22,                755),
+    POWERPC_DEF("755_v2.2",      CPU_POWERPC_7x5_v22,                755)
     /* PowerPC 745 v2.3                                                      */
-    POWERPC_DEF("745_v2.3",      CPU_POWERPC_7x5_v23,                745),
+    POWERPC_DEF("745_v2.3",      CPU_POWERPC_7x5_v23,                745)
     /* PowerPC 755 v2.3                                                      */
-    POWERPC_DEF("755_v2.3",      CPU_POWERPC_7x5_v23,                755),
+    POWERPC_DEF("755_v2.3",      CPU_POWERPC_7x5_v23,                755)
     /* PowerPC 745 v2.4                                                      */
-    POWERPC_DEF("745_v2.4",      CPU_POWERPC_7x5_v24,                745),
+    POWERPC_DEF("745_v2.4",      CPU_POWERPC_7x5_v24,                745)
     /* PowerPC 755 v2.4                                                      */
-    POWERPC_DEF("755_v2.4",      CPU_POWERPC_7x5_v24,                755),
+    POWERPC_DEF("755_v2.4",      CPU_POWERPC_7x5_v24,                755)
     /* PowerPC 745 v2.5                                                      */
-    POWERPC_DEF("745_v2.5",      CPU_POWERPC_7x5_v25,                745),
+    POWERPC_DEF("745_v2.5",      CPU_POWERPC_7x5_v25,                745)
     /* PowerPC 755 v2.5                                                      */
-    POWERPC_DEF("755_v2.5",      CPU_POWERPC_7x5_v25,                755),
+    POWERPC_DEF("755_v2.5",      CPU_POWERPC_7x5_v25,                755)
     /* PowerPC 745 v2.6                                                      */
-    POWERPC_DEF("745_v2.6",      CPU_POWERPC_7x5_v26,                745),
+    POWERPC_DEF("745_v2.6",      CPU_POWERPC_7x5_v26,                745)
     /* PowerPC 755 v2.6                                                      */
-    POWERPC_DEF("755_v2.6",      CPU_POWERPC_7x5_v26,                755),
+    POWERPC_DEF("755_v2.6",      CPU_POWERPC_7x5_v26,                755)
     /* PowerPC 745 v2.7                                                      */
-    POWERPC_DEF("745_v2.7",      CPU_POWERPC_7x5_v27,                745),
+    POWERPC_DEF("745_v2.7",      CPU_POWERPC_7x5_v27,                745)
     /* PowerPC 755 v2.7                                                      */
-    POWERPC_DEF("755_v2.7",      CPU_POWERPC_7x5_v27,                755),
+    POWERPC_DEF("755_v2.7",      CPU_POWERPC_7x5_v27,                755)
     /* PowerPC 745 v2.8                                                      */
-    POWERPC_DEF("745_v2.8",      CPU_POWERPC_7x5_v28,                745),
+    POWERPC_DEF("745_v2.8",      CPU_POWERPC_7x5_v28,                745)
     /* PowerPC 755 v2.8                                                      */
-    POWERPC_DEF("755_v2.8",      CPU_POWERPC_7x5_v28,                755),
+    POWERPC_DEF("755_v2.8",      CPU_POWERPC_7x5_v28,                755)
 #if defined (TODO)
     /* PowerPC 745P (G3)                                                     */
-    POWERPC_DEF("745p",          CPU_POWERPC_7x5P,                   745),
+    POWERPC_DEF("745p",          CPU_POWERPC_7x5P,                   745)
     /* PowerPC 755P (G3)                                                     */
-    POWERPC_DEF("755p",          CPU_POWERPC_7x5P,                   755),
+    POWERPC_DEF("755p",          CPU_POWERPC_7x5P,                   755)
 #endif
     /* PowerPC 74xx family                                                   */
     /* PowerPC 7400 (G4)                                                     */
-    POWERPC_DEF("7400",          CPU_POWERPC_7400,                   7400),
+    POWERPC_DEF("7400",          CPU_POWERPC_7400,                   7400)
     /* Code name for PowerPC 7400                                            */
-    POWERPC_DEF("Max",           CPU_POWERPC_7400,                   7400),
+    POWERPC_DEF("Max",           CPU_POWERPC_7400,                   7400)
     /* PowerPC 74xx is also well known as G4                                 */
-    POWERPC_DEF("G4",            CPU_POWERPC_7400,                   7400),
+    POWERPC_DEF("G4",            CPU_POWERPC_7400,                   7400)
     /* PowerPC 7400 v1.0 (G4)                                                */
-    POWERPC_DEF("7400_v1.0",     CPU_POWERPC_7400_v10,               7400),
+    POWERPC_DEF("7400_v1.0",     CPU_POWERPC_7400_v10,               7400)
     /* PowerPC 7400 v1.1 (G4)                                                */
-    POWERPC_DEF("7400_v1.1",     CPU_POWERPC_7400_v11,               7400),
+    POWERPC_DEF("7400_v1.1",     CPU_POWERPC_7400_v11,               7400)
     /* PowerPC 7400 v2.0 (G4)                                                */
-    POWERPC_DEF("7400_v2.0",     CPU_POWERPC_7400_v20,               7400),
+    POWERPC_DEF("7400_v2.0",     CPU_POWERPC_7400_v20,               7400)
     /* PowerPC 7400 v2.1 (G4)                                                */
-    POWERPC_DEF("7400_v2.1",     CPU_POWERPC_7400_v21,               7400),
+    POWERPC_DEF("7400_v2.1",     CPU_POWERPC_7400_v21,               7400)
     /* PowerPC 7400 v2.2 (G4)                                                */
-    POWERPC_DEF("7400_v2.2",     CPU_POWERPC_7400_v22,               7400),
+    POWERPC_DEF("7400_v2.2",     CPU_POWERPC_7400_v22,               7400)
     /* PowerPC 7400 v2.6 (G4)                                                */
-    POWERPC_DEF("7400_v2.6",     CPU_POWERPC_7400_v26,               7400),
+    POWERPC_DEF("7400_v2.6",     CPU_POWERPC_7400_v26,               7400)
     /* PowerPC 7400 v2.7 (G4)                                                */
-    POWERPC_DEF("7400_v2.7",     CPU_POWERPC_7400_v27,               7400),
+    POWERPC_DEF("7400_v2.7",     CPU_POWERPC_7400_v27,               7400)
     /* PowerPC 7400 v2.8 (G4)                                                */
-    POWERPC_DEF("7400_v2.8",     CPU_POWERPC_7400_v28,               7400),
+    POWERPC_DEF("7400_v2.8",     CPU_POWERPC_7400_v28,               7400)
     /* PowerPC 7400 v2.9 (G4)                                                */
-    POWERPC_DEF("7400_v2.9",     CPU_POWERPC_7400_v29,               7400),
+    POWERPC_DEF("7400_v2.9",     CPU_POWERPC_7400_v29,               7400)
     /* PowerPC 7410 (G4)                                                     */
-    POWERPC_DEF("7410",          CPU_POWERPC_7410,                   7410),
+    POWERPC_DEF("7410",          CPU_POWERPC_7410,                   7410)
     /* Code name for PowerPC 7410                                            */
-    POWERPC_DEF("Nitro",         CPU_POWERPC_7410,                   7410),
+    POWERPC_DEF("Nitro",         CPU_POWERPC_7410,                   7410)
     /* PowerPC 7410 v1.0 (G4)                                                */
-    POWERPC_DEF("7410_v1.0",     CPU_POWERPC_7410_v10,               7410),
+    POWERPC_DEF("7410_v1.0",     CPU_POWERPC_7410_v10,               7410)
     /* PowerPC 7410 v1.1 (G4)                                                */
-    POWERPC_DEF("7410_v1.1",     CPU_POWERPC_7410_v11,               7410),
+    POWERPC_DEF("7410_v1.1",     CPU_POWERPC_7410_v11,               7410)
     /* PowerPC 7410 v1.2 (G4)                                                */
-    POWERPC_DEF("7410_v1.2",     CPU_POWERPC_7410_v12,               7410),
+    POWERPC_DEF("7410_v1.2",     CPU_POWERPC_7410_v12,               7410)
     /* PowerPC 7410 v1.3 (G4)                                                */
-    POWERPC_DEF("7410_v1.3",     CPU_POWERPC_7410_v13,               7410),
+    POWERPC_DEF("7410_v1.3",     CPU_POWERPC_7410_v13,               7410)
     /* PowerPC 7410 v1.4 (G4)                                                */
-    POWERPC_DEF("7410_v1.4",     CPU_POWERPC_7410_v14,               7410),
+    POWERPC_DEF("7410_v1.4",     CPU_POWERPC_7410_v14,               7410)
     /* PowerPC 7448 (G4)                                                     */
-    POWERPC_DEF("7448",          CPU_POWERPC_7448,                   7400),
+    POWERPC_DEF("7448",          CPU_POWERPC_7448,                   7400)
     /* PowerPC 7448 v1.0 (G4)                                                */
-    POWERPC_DEF("7448_v1.0",     CPU_POWERPC_7448_v10,               7400),
+    POWERPC_DEF("7448_v1.0",     CPU_POWERPC_7448_v10,               7400)
     /* PowerPC 7448 v1.1 (G4)                                                */
-    POWERPC_DEF("7448_v1.1",     CPU_POWERPC_7448_v11,               7400),
+    POWERPC_DEF("7448_v1.1",     CPU_POWERPC_7448_v11,               7400)
     /* PowerPC 7448 v2.0 (G4)                                                */
-    POWERPC_DEF("7448_v2.0",     CPU_POWERPC_7448_v20,               7400),
+    POWERPC_DEF("7448_v2.0",     CPU_POWERPC_7448_v20,               7400)
     /* PowerPC 7448 v2.1 (G4)                                                */
-    POWERPC_DEF("7448_v2.1",     CPU_POWERPC_7448_v21,               7400),
+    POWERPC_DEF("7448_v2.1",     CPU_POWERPC_7448_v21,               7400)
     /* PowerPC 7450 (G4)                                                     */
-    POWERPC_DEF("7450",          CPU_POWERPC_7450,                   7450),
+    POWERPC_DEF("7450",          CPU_POWERPC_7450,                   7450)
     /* Code name for PowerPC 7450                                            */
-    POWERPC_DEF("Vger",          CPU_POWERPC_7450,                   7450),
+    POWERPC_DEF("Vger",          CPU_POWERPC_7450,                   7450)
     /* PowerPC 7450 v1.0 (G4)                                                */
-    POWERPC_DEF("7450_v1.0",     CPU_POWERPC_7450_v10,               7450),
+    POWERPC_DEF("7450_v1.0",     CPU_POWERPC_7450_v10,               7450)
     /* PowerPC 7450 v1.1 (G4)                                                */
-    POWERPC_DEF("7450_v1.1",     CPU_POWERPC_7450_v11,               7450),
+    POWERPC_DEF("7450_v1.1",     CPU_POWERPC_7450_v11,               7450)
     /* PowerPC 7450 v1.2 (G4)                                                */
-    POWERPC_DEF("7450_v1.2",     CPU_POWERPC_7450_v12,               7450),
+    POWERPC_DEF("7450_v1.2",     CPU_POWERPC_7450_v12,               7450)
     /* PowerPC 7450 v2.0 (G4)                                                */
-    POWERPC_DEF("7450_v2.0",     CPU_POWERPC_7450_v20,               7450),
+    POWERPC_DEF("7450_v2.0",     CPU_POWERPC_7450_v20,               7450)
     /* PowerPC 7450 v2.1 (G4)                                                */
-    POWERPC_DEF("7450_v2.1",     CPU_POWERPC_7450_v21,               7450),
+    POWERPC_DEF("7450_v2.1",     CPU_POWERPC_7450_v21,               7450)
     /* PowerPC 7441 (G4)                                                     */
-    POWERPC_DEF("7441",          CPU_POWERPC_74x1,                   7440),
+    POWERPC_DEF("7441",          CPU_POWERPC_74x1,                   7440)
     /* PowerPC 7451 (G4)                                                     */
-    POWERPC_DEF("7451",          CPU_POWERPC_74x1,                   7450),
+    POWERPC_DEF("7451",          CPU_POWERPC_74x1,                   7450)
     /* PowerPC 7441 v2.1 (G4)                                                */
-    POWERPC_DEF("7441_v2.1",     CPU_POWERPC_7450_v21,               7440),
+    POWERPC_DEF("7441_v2.1",     CPU_POWERPC_7450_v21,               7440)
     /* PowerPC 7441 v2.3 (G4)                                                */
-    POWERPC_DEF("7441_v2.3",     CPU_POWERPC_74x1_v23,               7440),
+    POWERPC_DEF("7441_v2.3",     CPU_POWERPC_74x1_v23,               7440)
     /* PowerPC 7451 v2.3 (G4)                                                */
-    POWERPC_DEF("7451_v2.3",     CPU_POWERPC_74x1_v23,               7450),
+    POWERPC_DEF("7451_v2.3",     CPU_POWERPC_74x1_v23,               7450)
     /* PowerPC 7441 v2.10 (G4)                                                */
-    POWERPC_DEF("7441_v2.10",    CPU_POWERPC_74x1_v210,              7440),
+    POWERPC_DEF("7441_v2.10",    CPU_POWERPC_74x1_v210,              7440)
     /* PowerPC 7451 v2.10 (G4)                                               */
-    POWERPC_DEF("7451_v2.10",    CPU_POWERPC_74x1_v210,              7450),
+    POWERPC_DEF("7451_v2.10",    CPU_POWERPC_74x1_v210,              7450)
     /* PowerPC 7445 (G4)                                                     */
-    POWERPC_DEF("7445",          CPU_POWERPC_74x5,                   7445),
+    POWERPC_DEF("7445",          CPU_POWERPC_74x5,                   7445)
     /* PowerPC 7455 (G4)                                                     */
-    POWERPC_DEF("7455",          CPU_POWERPC_74x5,                   7455),
+    POWERPC_DEF("7455",          CPU_POWERPC_74x5,                   7455)
     /* Code name for PowerPC 7445/7455                                       */
-    POWERPC_DEF("Apollo6",       CPU_POWERPC_74x5,                   7455),
+    POWERPC_DEF("Apollo6",       CPU_POWERPC_74x5,                   7455)
     /* PowerPC 7445 v1.0 (G4)                                                */
-    POWERPC_DEF("7445_v1.0",     CPU_POWERPC_74x5_v10,               7445),
+    POWERPC_DEF("7445_v1.0",     CPU_POWERPC_74x5_v10,               7445)
     /* PowerPC 7455 v1.0 (G4)                                                */
-    POWERPC_DEF("7455_v1.0",     CPU_POWERPC_74x5_v10,               7455),
+    POWERPC_DEF("7455_v1.0",     CPU_POWERPC_74x5_v10,               7455)
     /* PowerPC 7445 v2.1 (G4)                                                */
-    POWERPC_DEF("7445_v2.1",     CPU_POWERPC_74x5_v21,               7445),
+    POWERPC_DEF("7445_v2.1",     CPU_POWERPC_74x5_v21,               7445)
     /* PowerPC 7455 v2.1 (G4)                                                */
-    POWERPC_DEF("7455_v2.1",     CPU_POWERPC_74x5_v21,               7455),
+    POWERPC_DEF("7455_v2.1",     CPU_POWERPC_74x5_v21,               7455)
     /* PowerPC 7445 v3.2 (G4)                                                */
-    POWERPC_DEF("7445_v3.2",     CPU_POWERPC_74x5_v32,               7445),
+    POWERPC_DEF("7445_v3.2",     CPU_POWERPC_74x5_v32,               7445)
     /* PowerPC 7455 v3.2 (G4)                                                */
-    POWERPC_DEF("7455_v3.2",     CPU_POWERPC_74x5_v32,               7455),
+    POWERPC_DEF("7455_v3.2",     CPU_POWERPC_74x5_v32,               7455)
     /* PowerPC 7445 v3.3 (G4)                                                */
-    POWERPC_DEF("7445_v3.3",     CPU_POWERPC_74x5_v33,               7445),
+    POWERPC_DEF("7445_v3.3",     CPU_POWERPC_74x5_v33,               7445)
     /* PowerPC 7455 v3.3 (G4)                                                */
-    POWERPC_DEF("7455_v3.3",     CPU_POWERPC_74x5_v33,               7455),
+    POWERPC_DEF("7455_v3.3",     CPU_POWERPC_74x5_v33,               7455)
     /* PowerPC 7445 v3.4 (G4)                                                */
-    POWERPC_DEF("7445_v3.4",     CPU_POWERPC_74x5_v34,               7445),
+    POWERPC_DEF("7445_v3.4",     CPU_POWERPC_74x5_v34,               7445)
     /* PowerPC 7455 v3.4 (G4)                                                */
-    POWERPC_DEF("7455_v3.4",     CPU_POWERPC_74x5_v34,               7455),
+    POWERPC_DEF("7455_v3.4",     CPU_POWERPC_74x5_v34,               7455)
     /* PowerPC 7447 (G4)                                                     */
-    POWERPC_DEF("7447",          CPU_POWERPC_74x7,                   7445),
+    POWERPC_DEF("7447",          CPU_POWERPC_74x7,                   7445)
     /* PowerPC 7457 (G4)                                                     */
-    POWERPC_DEF("7457",          CPU_POWERPC_74x7,                   7455),
+    POWERPC_DEF("7457",          CPU_POWERPC_74x7,                   7455)
     /* Code name for PowerPC 7447/7457                                       */
-    POWERPC_DEF("Apollo7",       CPU_POWERPC_74x7,                   7455),
+    POWERPC_DEF("Apollo7",       CPU_POWERPC_74x7,                   7455)
     /* PowerPC 7447 v1.0 (G4)                                                */
-    POWERPC_DEF("7447_v1.0",     CPU_POWERPC_74x7_v10,               7445),
+    POWERPC_DEF("7447_v1.0",     CPU_POWERPC_74x7_v10,               7445)
     /* PowerPC 7457 v1.0 (G4)                                                */
-    POWERPC_DEF("7457_v1.0",     CPU_POWERPC_74x7_v10,               7455),
+    POWERPC_DEF("7457_v1.0",     CPU_POWERPC_74x7_v10,               7455)
     /* PowerPC 7447 v1.1 (G4)                                                */
-    POWERPC_DEF("7447_v1.1",     CPU_POWERPC_74x7_v11,               7445),
+    POWERPC_DEF("7447_v1.1",     CPU_POWERPC_74x7_v11,               7445)
     /* PowerPC 7457 v1.1 (G4)                                                */
-    POWERPC_DEF("7457_v1.1",     CPU_POWERPC_74x7_v11,               7455),
+    POWERPC_DEF("7457_v1.1",     CPU_POWERPC_74x7_v11,               7455)
     /* PowerPC 7457 v1.2 (G4)                                                */
-    POWERPC_DEF("7457_v1.2",     CPU_POWERPC_74x7_v12,               7455),
+    POWERPC_DEF("7457_v1.2",     CPU_POWERPC_74x7_v12,               7455)
     /* PowerPC 7447A (G4)                                                    */
-    POWERPC_DEF("7447A",         CPU_POWERPC_74x7A,                  7445),
+    POWERPC_DEF("7447A",         CPU_POWERPC_74x7A,                  7445)
     /* PowerPC 7457A (G4)                                                    */
-    POWERPC_DEF("7457A",         CPU_POWERPC_74x7A,                  7455),
+    POWERPC_DEF("7457A",         CPU_POWERPC_74x7A,                  7455)
     /* PowerPC 7447A v1.0 (G4)                                               */
-    POWERPC_DEF("7447A_v1.0",    CPU_POWERPC_74x7A_v10,              7445),
+    POWERPC_DEF("7447A_v1.0",    CPU_POWERPC_74x7A_v10,              7445)
     /* PowerPC 7457A v1.0 (G4)                                               */
-    POWERPC_DEF("7457A_v1.0",    CPU_POWERPC_74x7A_v10,              7455),
+    POWERPC_DEF("7457A_v1.0",    CPU_POWERPC_74x7A_v10,              7455)
     /* Code name for PowerPC 7447A/7457A                                     */
-    POWERPC_DEF("Apollo7PM",     CPU_POWERPC_74x7A_v10,              7455),
+    POWERPC_DEF("Apollo7PM",     CPU_POWERPC_74x7A_v10,              7455)
     /* PowerPC 7447A v1.1 (G4)                                               */
-    POWERPC_DEF("7447A_v1.1",    CPU_POWERPC_74x7A_v11,              7445),
+    POWERPC_DEF("7447A_v1.1",    CPU_POWERPC_74x7A_v11,              7445)
     /* PowerPC 7457A v1.1 (G4)                                               */
-    POWERPC_DEF("7457A_v1.1",    CPU_POWERPC_74x7A_v11,              7455),
+    POWERPC_DEF("7457A_v1.1",    CPU_POWERPC_74x7A_v11,              7455)
     /* PowerPC 7447A v1.2 (G4)                                               */
-    POWERPC_DEF("7447A_v1.2",    CPU_POWERPC_74x7A_v12,              7445),
+    POWERPC_DEF("7447A_v1.2",    CPU_POWERPC_74x7A_v12,              7445)
     /* PowerPC 7457A v1.2 (G4)                                               */
-    POWERPC_DEF("7457A_v1.2",    CPU_POWERPC_74x7A_v12,              7455),
+    POWERPC_DEF("7457A_v1.2",    CPU_POWERPC_74x7A_v12,              7455)
     /* 64 bits PowerPC                                                       */
 #if defined (TARGET_PPC64)
     /* PowerPC 620                                                           */
-    POWERPC_DEF("620",           CPU_POWERPC_620,                    620),
+    POWERPC_DEF("620",           CPU_POWERPC_620,                    620)
     /* Code name for PowerPC 620                                             */
-    POWERPC_DEF("Trident",       CPU_POWERPC_620,                    620),
+    POWERPC_DEF("Trident",       CPU_POWERPC_620,                    620)
 #if defined (TODO)
     /* PowerPC 630 (POWER3)                                                  */
-    POWERPC_DEF("630",           CPU_POWERPC_630,                    630),
-    POWERPC_DEF("POWER3",        CPU_POWERPC_630,                    630),
+    POWERPC_DEF("630",           CPU_POWERPC_630,                    630)
+    POWERPC_DEF("POWER3",        CPU_POWERPC_630,                    630)
     /* Code names for POWER3                                                 */
-    POWERPC_DEF("Boxer",         CPU_POWERPC_630,                    630),
-    POWERPC_DEF("Dino",          CPU_POWERPC_630,                    630),
+    POWERPC_DEF("Boxer",         CPU_POWERPC_630,                    630)
+    POWERPC_DEF("Dino",          CPU_POWERPC_630,                    630)
 #endif
 #if defined (TODO)
     /* PowerPC 631 (Power 3+)                                                */
-    POWERPC_DEF("631",           CPU_POWERPC_631,                    631),
-    POWERPC_DEF("POWER3+",       CPU_POWERPC_631,                    631),
+    POWERPC_DEF("631",           CPU_POWERPC_631,                    631)
+    POWERPC_DEF("POWER3+",       CPU_POWERPC_631,                    631)
 #endif
 #if defined (TODO)
     /* POWER4                                                                */
-    POWERPC_DEF("POWER4",        CPU_POWERPC_POWER4,                 POWER4),
+    POWERPC_DEF("POWER4",        CPU_POWERPC_POWER4,                 POWER4)
 #endif
 #if defined (TODO)
     /* POWER4p                                                               */
-    POWERPC_DEF("POWER4+",       CPU_POWERPC_POWER4P,                POWER4P),
+    POWERPC_DEF("POWER4+",       CPU_POWERPC_POWER4P,                POWER4P)
 #endif
 #if defined (TODO)
     /* POWER5                                                                */
-    POWERPC_DEF("POWER5",        CPU_POWERPC_POWER5,                 POWER5),
+    POWERPC_DEF("POWER5",        CPU_POWERPC_POWER5,                 POWER5)
     /* POWER5GR                                                              */
-    POWERPC_DEF("POWER5gr",      CPU_POWERPC_POWER5GR,               POWER5),
+    POWERPC_DEF("POWER5gr",      CPU_POWERPC_POWER5GR,               POWER5)
 #endif
 #if defined (TODO)
     /* POWER5+                                                               */
-    POWERPC_DEF("POWER5+",       CPU_POWERPC_POWER5P,                POWER5P),
+    POWERPC_DEF("POWER5+",       CPU_POWERPC_POWER5P,                POWER5P)
     /* POWER5GS                                                              */
-    POWERPC_DEF("POWER5gs",      CPU_POWERPC_POWER5GS,               POWER5P),
+    POWERPC_DEF("POWER5gs",      CPU_POWERPC_POWER5GS,               POWER5P)
 #endif
 #if defined (TODO)
     /* POWER6                                                                */
-    POWERPC_DEF("POWER6",        CPU_POWERPC_POWER6,                 POWER6),
+    POWERPC_DEF("POWER6",        CPU_POWERPC_POWER6,                 POWER6)
     /* POWER6 running in POWER5 mode                                         */
-    POWERPC_DEF("POWER6_5",      CPU_POWERPC_POWER6_5,               POWER5),
+    POWERPC_DEF("POWER6_5",      CPU_POWERPC_POWER6_5,               POWER5)
     /* POWER6A                                                               */
-    POWERPC_DEF("POWER6A",       CPU_POWERPC_POWER6A,                POWER6),
+    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_DEF("POWER7_v2.1",   CPU_POWERPC_POWER7_v21,             POWER7),
-    POWERPC_DEF("POWER7_v2.3",   CPU_POWERPC_POWER7_v23,             POWER7),
+    POWERPC_DEF("POWER7",        CPU_POWERPC_POWER7,                 POWER7)
+    POWERPC_DEF("POWER7_v2.0",   CPU_POWERPC_POWER7_v20,             POWER7)
+    POWERPC_DEF("POWER7_v2.1",   CPU_POWERPC_POWER7_v21,             POWER7)
+    POWERPC_DEF("POWER7_v2.3",   CPU_POWERPC_POWER7_v23,             POWER7)
     /* PowerPC 970                                                           */
-    POWERPC_DEF("970",           CPU_POWERPC_970,                    970),
+    POWERPC_DEF("970",           CPU_POWERPC_970,                    970)
     /* PowerPC 970FX (G5)                                                    */
-    POWERPC_DEF("970fx",         CPU_POWERPC_970FX,                  970FX),
+    POWERPC_DEF("970fx",         CPU_POWERPC_970FX,                  970FX)
     /* PowerPC 970FX v1.0 (G5)                                               */
-    POWERPC_DEF("970fx_v1.0",    CPU_POWERPC_970FX_v10,              970FX),
+    POWERPC_DEF("970fx_v1.0",    CPU_POWERPC_970FX_v10,              970FX)
     /* PowerPC 970FX v2.0 (G5)                                               */
-    POWERPC_DEF("970fx_v2.0",    CPU_POWERPC_970FX_v20,              970FX),
+    POWERPC_DEF("970fx_v2.0",    CPU_POWERPC_970FX_v20,              970FX)
     /* PowerPC 970FX v2.1 (G5)                                               */
-    POWERPC_DEF("970fx_v2.1",    CPU_POWERPC_970FX_v21,              970FX),
+    POWERPC_DEF("970fx_v2.1",    CPU_POWERPC_970FX_v21,              970FX)
     /* PowerPC 970FX v3.0 (G5)                                               */
-    POWERPC_DEF("970fx_v3.0",    CPU_POWERPC_970FX_v30,              970FX),
+    POWERPC_DEF("970fx_v3.0",    CPU_POWERPC_970FX_v30,              970FX)
     /* PowerPC 970FX v3.1 (G5)                                               */
-    POWERPC_DEF("970fx_v3.1",    CPU_POWERPC_970FX_v31,              970FX),
+    POWERPC_DEF("970fx_v3.1",    CPU_POWERPC_970FX_v31,              970FX)
     /* PowerPC 970GX (G5)                                                    */
-    POWERPC_DEF("970gx",         CPU_POWERPC_970GX,                  970GX),
+    POWERPC_DEF("970gx",         CPU_POWERPC_970GX,                  970GX)
     /* PowerPC 970MP                                                         */
-    POWERPC_DEF("970mp",         CPU_POWERPC_970MP,                  970MP),
+    POWERPC_DEF("970mp",         CPU_POWERPC_970MP,                  970MP)
     /* PowerPC 970MP v1.0                                                    */
-    POWERPC_DEF("970mp_v1.0",    CPU_POWERPC_970MP_v10,              970MP),
+    POWERPC_DEF("970mp_v1.0",    CPU_POWERPC_970MP_v10,              970MP)
     /* PowerPC 970MP v1.1                                                    */
-    POWERPC_DEF("970mp_v1.1",    CPU_POWERPC_970MP_v11,              970MP),
+    POWERPC_DEF("970mp_v1.1",    CPU_POWERPC_970MP_v11,              970MP)
 #if defined (TODO)
     /* PowerPC Cell                                                          */
-    POWERPC_DEF("Cell",          CPU_POWERPC_CELL,                   970),
+    POWERPC_DEF("Cell",          CPU_POWERPC_CELL,                   970)
 #endif
 #if defined (TODO)
     /* PowerPC Cell v1.0                                                     */
-    POWERPC_DEF("Cell_v1.0",     CPU_POWERPC_CELL_v10,               970),
+    POWERPC_DEF("Cell_v1.0",     CPU_POWERPC_CELL_v10,               970)
 #endif
 #if defined (TODO)
     /* PowerPC Cell v2.0                                                     */
-    POWERPC_DEF("Cell_v2.0",     CPU_POWERPC_CELL_v20,               970),
+    POWERPC_DEF("Cell_v2.0",     CPU_POWERPC_CELL_v20,               970)
 #endif
 #if defined (TODO)
     /* PowerPC Cell v3.0                                                     */
-    POWERPC_DEF("Cell_v3.0",     CPU_POWERPC_CELL_v30,               970),
+    POWERPC_DEF("Cell_v3.0",     CPU_POWERPC_CELL_v30,               970)
 #endif
 #if defined (TODO)
     /* PowerPC Cell v3.1                                                     */
-    POWERPC_DEF("Cell_v3.1",     CPU_POWERPC_CELL_v31,               970),
+    POWERPC_DEF("Cell_v3.1",     CPU_POWERPC_CELL_v31,               970)
 #endif
 #if defined (TODO)
     /* PowerPC Cell v3.2                                                     */
-    POWERPC_DEF("Cell_v3.2",     CPU_POWERPC_CELL_v32,               970),
+    POWERPC_DEF("Cell_v3.2",     CPU_POWERPC_CELL_v32,               970)
 #endif
 #if defined (TODO)
     /* RS64 (Apache/A35)                                                     */
@@ -9344,57 +9344,57 @@ static const ppc_def_t ppc_defs[] = {
      * and the PowerPC 64 one.
      */
     /* What about A10 & A30 ? */
-    POWERPC_DEF("RS64",          CPU_POWERPC_RS64,                   RS64),
-    POWERPC_DEF("Apache",        CPU_POWERPC_RS64,                   RS64),
-    POWERPC_DEF("A35",           CPU_POWERPC_RS64,                   RS64),
+    POWERPC_DEF("RS64",          CPU_POWERPC_RS64,                   RS64)
+    POWERPC_DEF("Apache",        CPU_POWERPC_RS64,                   RS64)
+    POWERPC_DEF("A35",           CPU_POWERPC_RS64,                   RS64)
 #endif
 #if defined (TODO)
     /* RS64-II (NorthStar/A50)                                               */
-    POWERPC_DEF("RS64-II",       CPU_POWERPC_RS64II,                 RS64),
-    POWERPC_DEF("NorthStar",     CPU_POWERPC_RS64II,                 RS64),
-    POWERPC_DEF("A50",           CPU_POWERPC_RS64II,                 RS64),
+    POWERPC_DEF("RS64-II",       CPU_POWERPC_RS64II,                 RS64)
+    POWERPC_DEF("NorthStar",     CPU_POWERPC_RS64II,                 RS64)
+    POWERPC_DEF("A50",           CPU_POWERPC_RS64II,                 RS64)
 #endif
 #if defined (TODO)
     /* RS64-III (Pulsar)                                                     */
-    POWERPC_DEF("RS64-III",      CPU_POWERPC_RS64III,                RS64),
-    POWERPC_DEF("Pulsar",        CPU_POWERPC_RS64III,                RS64),
+    POWERPC_DEF("RS64-III",      CPU_POWERPC_RS64III,                RS64)
+    POWERPC_DEF("Pulsar",        CPU_POWERPC_RS64III,                RS64)
 #endif
 #if defined (TODO)
     /* RS64-IV (IceStar/IStar/SStar)                                         */
-    POWERPC_DEF("RS64-IV",       CPU_POWERPC_RS64IV,                 RS64),
-    POWERPC_DEF("IceStar",       CPU_POWERPC_RS64IV,                 RS64),
-    POWERPC_DEF("IStar",         CPU_POWERPC_RS64IV,                 RS64),
-    POWERPC_DEF("SStar",         CPU_POWERPC_RS64IV,                 RS64),
+    POWERPC_DEF("RS64-IV",       CPU_POWERPC_RS64IV,                 RS64)
+    POWERPC_DEF("IceStar",       CPU_POWERPC_RS64IV,                 RS64)
+    POWERPC_DEF("IStar",         CPU_POWERPC_RS64IV,                 RS64)
+    POWERPC_DEF("SStar",         CPU_POWERPC_RS64IV,                 RS64)
 #endif
 #endif /* defined (TARGET_PPC64) */
     /* POWER                                                                 */
 #if defined (TODO)
     /* Original POWER                                                        */
-    POWERPC_DEF("POWER",         CPU_POWERPC_POWER,                  POWER),
-    POWERPC_DEF("RIOS",          CPU_POWERPC_POWER,                  POWER),
-    POWERPC_DEF("RSC",           CPU_POWERPC_POWER,                  POWER),
-    POWERPC_DEF("RSC3308",       CPU_POWERPC_POWER,                  POWER),
-    POWERPC_DEF("RSC4608",       CPU_POWERPC_POWER,                  POWER),
+    POWERPC_DEF("POWER",         CPU_POWERPC_POWER,                  POWER)
+    POWERPC_DEF("RIOS",          CPU_POWERPC_POWER,                  POWER)
+    POWERPC_DEF("RSC",           CPU_POWERPC_POWER,                  POWER)
+    POWERPC_DEF("RSC3308",       CPU_POWERPC_POWER,                  POWER)
+    POWERPC_DEF("RSC4608",       CPU_POWERPC_POWER,                  POWER)
 #endif
 #if defined (TODO)
     /* POWER2                                                                */
-    POWERPC_DEF("POWER2",        CPU_POWERPC_POWER2,                 POWER),
-    POWERPC_DEF("RSC2",          CPU_POWERPC_POWER2,                 POWER),
-    POWERPC_DEF("P2SC",          CPU_POWERPC_POWER2,                 POWER),
+    POWERPC_DEF("POWER2",        CPU_POWERPC_POWER2,                 POWER)
+    POWERPC_DEF("RSC2",          CPU_POWERPC_POWER2,                 POWER)
+    POWERPC_DEF("P2SC",          CPU_POWERPC_POWER2,                 POWER)
 #endif
     /* PA semi cores                                                         */
 #if defined (TODO)
     /* PA PA6T */
-    POWERPC_DEF("PA6T",          CPU_POWERPC_PA6T,                   PA6T),
+    POWERPC_DEF("PA6T",          CPU_POWERPC_PA6T,                   PA6T)
 #endif
     /* Generic PowerPCs                                                      */
 #if defined (TARGET_PPC64)
-    POWERPC_DEF("ppc64",         CPU_POWERPC_PPC64,                  PPC64),
+    POWERPC_DEF("ppc64",         CPU_POWERPC_PPC64,                  PPC64)
 #endif
-    POWERPC_DEF("ppc32",         CPU_POWERPC_PPC32,                  PPC32),
-    POWERPC_DEF("ppc",           CPU_POWERPC_DEFAULT,                DEFAULT),
+    POWERPC_DEF("ppc32",         CPU_POWERPC_PPC32,                  PPC32)
+    POWERPC_DEF("ppc",           CPU_POWERPC_DEFAULT,                DEFAULT)
     /* Fallback                                                              */
-    POWERPC_DEF("default",       CPU_POWERPC_DEFAULT,                DEFAULT),
+    POWERPC_DEF("default",       CPU_POWERPC_DEFAULT,                DEFAULT)
 };
 
 /*****************************************************************************/
commit 9a1350539a69f465c14109605d6648572794ceda
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:02 2013 +0000

    target-ppc: Drop nested TARGET_PPC64 guard for POWER7
    
    It is within a large TARGET_PPC64 section from 970 to 620,
    so an #endif /* TARGET_PPC64 */ is confusing. Clean this up.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index d00c737..98a64e1 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -6671,7 +6671,6 @@ 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 |   \
@@ -6755,7 +6754,6 @@ static void init_proc_POWER7 (CPUPPCState *env)
      * 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 |        \
commit 5e95acc8ff2a068b09494f2522744f89f662a515
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:01 2013 +0000

    target-ppc: Update error handling in ppc_cpu_realize()
    
    Commit fe828a4d4b7a5617cda7b24e95e327bfb71d790e added a new fatal error
    message while QOM realize'ification was in flight.
    
    Convert it to return an Error instead of exit()ing.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index d2706f7..d00c737 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -10043,9 +10043,9 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp)
 
 #if !defined(CONFIG_USER_ONLY)
     if (smp_threads > max_smt) {
-        fprintf(stderr, "Cannot support more than %d threads on PPC with %s\n",
-                max_smt, kvm_enabled() ? "KVM" : "TCG");
-        exit(1);
+        error_setg(errp, "Cannot support more than %d threads on PPC with %s",
+                   max_smt, kvm_enabled() ? "KVM" : "TCG");
+        return;
     }
 #endif
 
commit bfe6d5b0daf9fdafeb0dbb7c26774dbb1bbb4507
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Feb 17 23:16:00 2013 +0000

    target-ppc: Fix "G2leGP3" PVR
    
    Unlike derived PVR constants mapped to CPU_POWERPC_G2LEgp3, the
    "G2leGP3" model definition itself used the CPU_POWERPC_G2LEgp1 PVR.
    
    Fixing this will allow to alias CPU_POWERPC_G2LEgp3-using types to
    "G2leGP3".
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index a2e1fc9..d2706f7 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8243,7 +8243,7 @@ static const ppc_def_t ppc_defs[] = {
     /* PowerPC G2LE GP1 core                                                 */
     POWERPC_DEF("G2leGP1",       CPU_POWERPC_G2LEgp1,                G2LE),
     /* PowerPC G2LE GP3 core                                                 */
-    POWERPC_DEF("G2leGP3",       CPU_POWERPC_G2LEgp1,                G2LE),
+    POWERPC_DEF("G2leGP3",       CPU_POWERPC_G2LEgp3,                G2LE),
     /* PowerPC MPC603 microcontrollers                                       */
     /* MPC8240                                                               */
     POWERPC_DEF("MPC8240",       CPU_POWERPC_MPC8240,                603E),
commit 0136d715ad985fccb8fed4bb5081d5bd20bfe88c
Author: Andreas Färber <afaerber at suse.de>
Date:   Mon Feb 11 10:53:11 2013 +0000

    target-ppc: Fix CPU_POWERPC_MPC8547E
    
    It was defined to ..._MPC8545E_v21 rather than ..._MPC8547E_v21.
    Due to both resolving to CPU_POWERPC_e500v2_v21 this did not show.
    
    Fixing this nontheless helps with QOM'ifying CPU aliases.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index f5fc9b1..a2e1fc9 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7282,7 +7282,7 @@ enum {
 #define CPU_POWERPC_MPC8545E_v10     CPU_POWERPC_e500v2_v10
 #define CPU_POWERPC_MPC8545E_v20     CPU_POWERPC_e500v2_v20
 #define CPU_POWERPC_MPC8545E_v21     CPU_POWERPC_e500v2_v21
-#define CPU_POWERPC_MPC8547E         CPU_POWERPC_MPC8545E_v21
+#define CPU_POWERPC_MPC8547E         CPU_POWERPC_MPC8547E_v21
 #define CPU_POWERPC_MPC8547E_v10     CPU_POWERPC_e500v2_v10
 #define CPU_POWERPC_MPC8547E_v20     CPU_POWERPC_e500v2_v20
 #define CPU_POWERPC_MPC8547E_v21     CPU_POWERPC_e500v2_v21
commit 156dfaded87d718a9ea798083e1c3e5ea7526713
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Sun Feb 10 18:59:02 2013 +0000

    pseries: Add cleanup hook for PAPR virtual LAN device
    
    Currently the spapr-vlan device does not supply a cleanup call for its
    NetClientInfo structure.  With current qemu versions, that leads to a SEGV
    on exit, when net_cleanup() attempts to call the cleanup handlers on all
    net clients.
    
    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_llan.c b/hw/spapr_llan.c
index 6ef2936..0ace2eb 100644
--- a/hw/spapr_llan.c
+++ b/hw/spapr_llan.c
@@ -175,11 +175,19 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
     return size;
 }
 
+static void spapr_vlan_cleanup(NetClientState *nc)
+{
+    VIOsPAPRVLANDevice *dev = qemu_get_nic_opaque(nc);
+
+    dev->nic = NULL;
+}
+
 static NetClientInfo net_spapr_vlan_info = {
     .type = NET_CLIENT_OPTIONS_KIND_NIC,
     .size = sizeof(NICState),
     .can_receive = spapr_vlan_can_receive,
     .receive = spapr_vlan_receive,
+    .cleanup = spapr_vlan_cleanup,
 };
 
 static void spapr_vlan_reset(VIOsPAPRDevice *sdev)
commit d6258c93a7133bb2bf2ab4e91476bc0b631ba7f1
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Mar 5 23:21:35 2013 +0530

    virtio-serial: make flow control explicit in virtio-console
    
    virtio-console.c used to return a value less than the number of bytes
    asked to be written out to a chardev backend in case the backend is not
    writable.  virtio-serial-bus.c then implicitly enabled flow control for
    that port.
    
    Make this explicit instead.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: f5ec50b068c25422256e499cf4adc06d353bf394.1362505276.git.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 b3ee074..194de64 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -47,20 +47,21 @@ static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
     ret = qemu_chr_fe_write(vcon->chr, buf, len);
     trace_virtio_console_flush_buf(port->id, len, ret);
 
-    if (ret < 0) {
+    if (ret <= 0) {
+        VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
+
         /*
          * Ideally we'd get a better error code than just -1, but
          * that's what the chardev interface gives us right now.  If
          * we had a finer-grained message, like -EPIPE, we could close
-         * this connection.  Absent such error messages, the most we
-         * can do is to return 0 here.
-         *
-         * This will prevent stray -1 values to go to
-         * virtio-serial-bus.c and cause abort()s in
-         * do_flush_queued_data().
+         * this connection.
          */
         ret = 0;
-        qemu_chr_fe_add_watch(vcon->chr, G_IO_OUT, chr_write_unblocked, vcon);
+        if (!k->is_console) {
+            virtio_serial_throttle_port(port, true);
+            qemu_chr_fe_add_watch(vcon->chr, G_IO_OUT, chr_write_unblocked,
+                                  vcon);
+        }
     }
     return ret;
 }
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index aa7d0d7..f76c505 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -172,24 +172,7 @@ static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
                                   port->elem.out_sg[i].iov_base
                                   + port->iov_offset,
                                   buf_size);
-            if (ret < 0 && ret != -EAGAIN) {
-                /* We don't handle any other type of errors here */
-                abort();
-            }
-            if (ret == -EAGAIN || (ret >= 0 && ret < buf_size)) {
-		/*
-                 * this is a temporary check until chardevs can signal to
-                 * frontends that they are writable again. This prevents
-                 * the console from going into throttled mode (forever)
-                 * if virtio-console is connected to a pty without a
-                 * listener. Otherwise the guest spins forever.
-                 * We can revert this if
-                 * 1: chardevs can notify frondends
-                 * 2: the guest driver does not spin in these cases
-                 */
-                if (!vsc->is_console) {
-                    virtio_serial_throttle_port(port, true);
-                }
+            if (port->throttled) {
                 port->iov_idx = i;
                 if (ret > 0) {
                     port->iov_offset += ret;
commit 7df4d4578f70b565870f353ba0b72f2f23781a09
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Mar 5 23:21:34 2013 +0530

    virtio: console: add flow control
    
    The virtio-serial-bus already has the logic to make flow control work
    properly.  Hook into the char layer's new ability to signal a backend is
    writable again.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: abffa02235d55ca6e2489068c58971c8897e976c.1362505276.git.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 46072a0..b3ee074 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -20,6 +20,18 @@ typedef struct VirtConsole {
     CharDriverState *chr;
 } VirtConsole;
 
+/*
+ * Callback function that's called from chardevs when backend becomes
+ * writable.
+ */
+static gboolean chr_write_unblocked(GIOChannel *chan, GIOCondition cond,
+                                    void *opaque)
+{
+    VirtConsole *vcon = opaque;
+
+    virtio_serial_throttle_port(&vcon->port, false);
+    return FALSE;
+}
 
 /* Callback function that's called when the guest sends us data */
 static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
@@ -48,6 +60,7 @@ static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
          * do_flush_queued_data().
          */
         ret = 0;
+        qemu_chr_fe_add_watch(vcon->chr, G_IO_OUT, chr_write_unblocked, vcon);
     }
     return ret;
 }
commit fcfb4d6aae611d1f804d486d3c998000912c4c81
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 5 23:21:33 2013 +0530

    serial: add flow control to transmit
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 2976f10d4e66ed4a34011f6f0d6937026d22be5f.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/serial.c b/hw/serial.c
index f0ce9b0..eb38f22 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -256,16 +256,17 @@ static void serial_update_msl(SerialState *s)
         qemu_mod_timer(s->modem_status_poll, qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 100);
 }
 
-static void serial_xmit(void *opaque)
+static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
 {
     SerialState *s = opaque;
-    uint64_t new_xmit_ts = qemu_get_clock_ns(vm_clock);
 
     if (s->tsr_retry <= 0) {
         if (s->fcr & UART_FCR_FE) {
             s->tsr = fifo_get(s,XMIT_FIFO);
             if (!s->xmit_fifo.count)
                 s->lsr |= UART_LSR_THRE;
+        } else if ((s->lsr & UART_LSR_THRE)) {
+            return FALSE;
         } else {
             s->tsr = s->thr;
             s->lsr |= UART_LSR_THRE;
@@ -277,30 +278,25 @@ static void serial_xmit(void *opaque)
         /* in loopback mode, say that we just received a char */
         serial_receive1(s, &s->tsr, 1);
     } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
-        if ((s->tsr_retry > 0) && (s->tsr_retry <= MAX_XMIT_RETRY)) {
+        if (s->tsr_retry >= 0 && s->tsr_retry < MAX_XMIT_RETRY &&
+            qemu_chr_fe_add_watch(s->chr, G_IO_OUT, serial_xmit, s) > 0) {
             s->tsr_retry++;
-            qemu_mod_timer(s->transmit_timer,  new_xmit_ts + s->char_transmit_time);
-            return;
-        } else if (s->poll_msl < 0) {
-            /* If we exceed MAX_XMIT_RETRY and the backend is not a real serial port, then
-            drop any further failed writes instantly, until we get one that goes through.
-            This is to prevent guests that log to unconnected pipes or pty's from stalling. */
-            s->tsr_retry = -1;
+            return FALSE;
         }
-    }
-    else {
+        s->tsr_retry = 0;
+    } else {
         s->tsr_retry = 0;
     }
 
     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);
 
     if (s->lsr & UART_LSR_THRE) {
         s->lsr |= UART_LSR_TEMT;
         s->thr_ipending = 1;
         serial_update_irq(s);
     }
+
+    return FALSE;
 }
 
 
@@ -330,7 +326,7 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
                 s->lsr &= ~UART_LSR_THRE;
                 serial_update_irq(s);
             }
-            serial_xmit(s);
+            serial_xmit(NULL, G_IO_OUT, s);
         }
         break;
     case 1:
@@ -684,8 +680,6 @@ void serial_init_core(SerialState *s)
     s->modem_status_poll = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) serial_update_msl, 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);
 
     qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
diff --git a/hw/serial.h b/hw/serial.h
index 98ee424..e57375d 100644
--- a/hw/serial.h
+++ b/hw/serial.h
@@ -72,8 +72,6 @@ struct SerialState {
 
     struct QEMUTimer *fifo_timeout_timer;
     int timeout_ipending;           /* timeout interrupt pending state */
-    struct QEMUTimer *transmit_timer;
-
 
     uint64_t char_transmit_time;    /* time to transmit a char in ticks */
     int poll_msl;
commit 01f45d986fb0b7c2d4f0466efe3cde9708f325be
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 5 23:21:32 2013 +0530

    qemu-char: move text console init to console.c
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 17cefde0a8d7807294bab95e93c3328a20d3f2ed.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index cf02cab..b82d643 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3663,7 +3663,6 @@ static void register_types(void)
     register_char_driver("null", qemu_chr_open_null);
     register_char_driver("socket", qemu_chr_open_socket);
     register_char_driver("udp", qemu_chr_open_udp);
-    register_char_driver("vc", vc_init);
     register_char_driver("memory", qemu_chr_open_ringbuf);
 #ifdef _WIN32
     register_char_driver("file", qemu_chr_open_win_file_out);
diff --git a/ui/console.c b/ui/console.c
index 0d95f32..83a6fa3 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1739,3 +1739,10 @@ PixelFormat qemu_default_pixelformat(int bpp)
     }
     return pf;
 }
+
+static void register_types(void)
+{
+    register_char_driver("vc", text_console_init);
+}
+
+type_init(register_types);
commit 5ab8211b9e1215ed136164c6d9622f2c928f7a8d
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 5 23:21:31 2013 +0530

    qemu-char: move msmouse registeration to msmouse.c
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: b47d1153b0d7669743c9a6bb98ce30f4cf7f876b.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/msmouse.c b/hw/msmouse.c
index ef47aed..407ec87 100644
--- a/hw/msmouse.c
+++ b/hw/msmouse.c
@@ -25,7 +25,6 @@
 #include "qemu-common.h"
 #include "char/char.h"
 #include "ui/console.h"
-#include "msmouse.h"
 
 #define MSMOUSE_LO6(n) ((n) & 0x3f)
 #define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6)
@@ -64,7 +63,7 @@ static void msmouse_chr_close (struct CharDriverState *chr)
     g_free (chr);
 }
 
-CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts)
+static CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts)
 {
     CharDriverState *chr;
 
@@ -76,3 +75,10 @@ CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts)
 
     return chr;
 }
+
+static void register_types(void)
+{
+    register_char_driver("msmouse", qemu_chr_open_msmouse);
+}
+
+type_init(register_types);
diff --git a/hw/msmouse.h b/hw/msmouse.h
deleted file mode 100644
index 8cff3a7..0000000
--- a/hw/msmouse.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef HW_MSMOUSE_H
-#define HW_MSMOUSE_H 1
-
-/* msmouse.c */
-CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts);
-
-#endif
diff --git a/qemu-char.c b/qemu-char.c
index 6fcd2da..cf02cab 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -28,7 +28,6 @@
 #include "qemu/timer.h"
 #include "char/char.h"
 #include "hw/usb.h"
-#include "hw/msmouse.h"
 #include "qmp-commands.h"
 
 #include <unistd.h>
@@ -2179,6 +2178,7 @@ static CharDriverState *qemu_chr_open_win_stdio(QemuOpts *opts)
 }
 #endif /* !_WIN32 */
 
+
 /***********************************************************/
 /* UDP Net console */
 
@@ -3663,7 +3663,6 @@ static void register_types(void)
     register_char_driver("null", qemu_chr_open_null);
     register_char_driver("socket", qemu_chr_open_socket);
     register_char_driver("udp", qemu_chr_open_udp);
-    register_char_driver("msmouse", qemu_chr_open_msmouse);
     register_char_driver("vc", vc_init);
     register_char_driver("memory", qemu_chr_open_ringbuf);
 #ifdef _WIN32
commit 08744c98115cfa144ed3493556024e400b2e2573
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 5 23:21:30 2013 +0530

    qemu-char: move baum registration to baum.c
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 1b24baa1ec3a174d5cad31e079d829904b53077b.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/baum.c b/hw/baum.c
index 09dcb9c..d75b150 100644
--- a/hw/baum.c
+++ b/hw/baum.c
@@ -562,7 +562,7 @@ static void baum_close(struct CharDriverState *chr)
     g_free(baum);
 }
 
-CharDriverState *chr_baum_init(QemuOpts *opts)
+static CharDriverState *chr_baum_init(QemuOpts *opts)
 {
     BaumDriverState *baum;
     CharDriverState *chr;
@@ -625,3 +625,10 @@ fail_handle:
     g_free(baum);
     return NULL;
 }
+
+static void register_types(void)
+{
+    register_char_driver("braille", chr_baum_init);
+}
+
+type_init(register_types);
diff --git a/hw/baum.h b/hw/baum.h
deleted file mode 100644
index 7635884..0000000
--- a/hw/baum.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * QEMU Baum
- *
- * Copyright (c) 2008 Samuel Thibault
- *
- * 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 HW_BAUM_H
-#define HW_BAUM_H 1
-
-/* char device */
-CharDriverState *chr_baum_init(QemuOpts *opts);
-
-#endif
diff --git a/qemu-char.c b/qemu-char.c
index 2e9f92e..6fcd2da 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -28,7 +28,6 @@
 #include "qemu/timer.h"
 #include "char/char.h"
 #include "hw/usb.h"
-#include "hw/baum.h"
 #include "hw/msmouse.h"
 #include "qmp-commands.h"
 
@@ -3678,9 +3677,6 @@ static void register_types(void)
     register_char_driver("pipe", qemu_chr_open_pipe);
     register_char_driver("stdio", qemu_chr_open_stdio);
 #endif
-#ifdef CONFIG_BRLAPI
-    register_char_driver("braille", chr_baum_init);
-#endif
 #ifdef HAVE_CHARDEV_TTY
     register_char_driver("tty", qemu_chr_open_tty);
     register_char_driver("serial", qemu_chr_open_tty);
diff --git a/vl.c b/vl.c
index c03edf1..5dc0558 100644
--- a/vl.c
+++ b/vl.c
@@ -119,7 +119,6 @@ int main(int argc, char **argv)
 #include "hw/pcmcia.h"
 #include "hw/pc.h"
 #include "hw/isa.h"
-#include "hw/baum.h"
 #include "hw/bt.h"
 #include "hw/watchdog.h"
 #include "hw/smbios.h"
commit 26c60614524f41bc9016cbe27eaefe59473d3461
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 5 23:21:29 2013 +0530

    qemu-char: move spice registration to spice-qemu-char.c
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 49a8d12eeb117e5530b2fab02af7681b54f9245c.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index 9bcdf73..2e9f92e 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3690,12 +3690,6 @@ static void register_types(void)
     register_char_driver("parallel", qemu_chr_open_pp);
     register_char_driver("parport", qemu_chr_open_pp);
 #endif
-#ifdef CONFIG_SPICE
-    register_char_driver("spicevmc", qemu_chr_open_spice);
-#if SPICE_SERVER_VERSION >= 0x000c02
-    register_char_driver("spiceport", qemu_chr_open_spice_port);
-#endif
-#endif
 }
 
 type_init(register_types);
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index a4d7de8..aea3d24 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -307,3 +307,13 @@ void qemu_spice_register_ports(void)
     }
 }
 #endif
+
+static void register_types(void)
+{
+    register_char_driver("spicevmc", qemu_chr_open_spice);
+#if SPICE_SERVER_VERSION >= 0x000c02
+    register_char_driver("spiceport", qemu_chr_open_spice_port);
+#endif
+}
+
+type_init(register_types);
commit d654f34ec8bf006f9b57a067e0f272ab94ee8e06
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 5 23:21:28 2013 +0530

    qemu-char: make char drivers dynamically registerable
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 0ff4f5f2b8b7afdb85a0c241403ad73f472f0b81.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/char/char.h b/include/char/char.h
index e8b781c..2e24270 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -244,6 +244,8 @@ CharDriverState *qemu_chr_find(const char *name);
 
 QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
 
+void register_char_driver(const char *name, CharDriverState *(*open)(QemuOpts *));
+
 /* add an eventfd to the qemu devices that are polled */
 CharDriverState *qemu_chr_open_eventfd(int eventfd);
 
diff --git a/qemu-char.c b/qemu-char.c
index 2c7c929..9bcdf73 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3177,53 +3177,31 @@ static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
 
 #endif
 
-static const struct {
+typedef struct CharDriver {
     const char *name;
     CharDriverState *(*open)(QemuOpts *opts);
-} backend_table[] = {
-    { .name = "null",      .open = qemu_chr_open_null },
-    { .name = "socket",    .open = qemu_chr_open_socket },
-    { .name = "udp",       .open = qemu_chr_open_udp },
-    { .name = "msmouse",   .open = qemu_chr_open_msmouse },
-    { .name = "vc",        .open = vc_init },
-    { .name = "memory",    .open = qemu_chr_open_ringbuf },
-#ifdef _WIN32
-    { .name = "file",      .open = qemu_chr_open_win_file_out },
-    { .name = "pipe",      .open = qemu_chr_open_win_pipe },
-    { .name = "console",   .open = qemu_chr_open_win_con },
-    { .name = "serial",    .open = qemu_chr_open_win },
-    { .name = "stdio",     .open = qemu_chr_open_win_stdio },
-#else
-    { .name = "file",      .open = qemu_chr_open_file_out },
-    { .name = "pipe",      .open = qemu_chr_open_pipe },
-    { .name = "stdio",     .open = qemu_chr_open_stdio },
-#endif
-#ifdef CONFIG_BRLAPI
-    { .name = "braille",   .open = chr_baum_init },
-#endif
-#ifdef HAVE_CHARDEV_TTY
-    { .name = "tty",       .open = qemu_chr_open_tty },
-    { .name = "serial",    .open = qemu_chr_open_tty },
-    { .name = "pty",       .open = qemu_chr_open_pty },
-#endif
-#ifdef HAVE_CHARDEV_PARPORT
-    { .name = "parallel",  .open = qemu_chr_open_pp },
-    { .name = "parport",   .open = qemu_chr_open_pp },
-#endif
-#ifdef CONFIG_SPICE
-    { .name = "spicevmc",     .open = qemu_chr_open_spice },
-#if SPICE_SERVER_VERSION >= 0x000c02
-    { .name = "spiceport",    .open = qemu_chr_open_spice_port },
-#endif
-#endif
-};
+} CharDriver;
+
+static GSList *backends;
+
+void register_char_driver(const char *name, CharDriverState *(*open)(QemuOpts *))
+{
+    CharDriver *s;
+
+    s = g_malloc0(sizeof(*s));
+    s->name = g_strdup(name);
+    s->open = open;
+
+    backends = g_slist_append(backends, s);
+}
 
 CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
                                     void (*init)(struct CharDriverState *s),
                                     Error **errp)
 {
+    CharDriver *cd;
     CharDriverState *chr;
-    int i;
+    GSList *i;
 
     if (qemu_opts_id(opts) == NULL) {
         error_setg(errp, "chardev: no id specified");
@@ -3235,17 +3213,20 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
                    qemu_opts_id(opts));
         goto err;
     }
-    for (i = 0; i < ARRAY_SIZE(backend_table); i++) {
-        if (strcmp(backend_table[i].name, qemu_opt_get(opts, "backend")) == 0)
+    for (i = backends; i; i = i->next) {
+        cd = i->data;
+
+        if (strcmp(cd->name, qemu_opt_get(opts, "backend")) == 0) {
             break;
+        }
     }
-    if (i == ARRAY_SIZE(backend_table)) {
+    if (i == NULL) {
         error_setg(errp, "chardev: backend \"%s\" not found",
                    qemu_opt_get(opts, "backend"));
-        goto err;
+        return NULL;
     }
 
-    chr = backend_table[i].open(opts);
+    chr = cd->open(opts);
     if (!chr) {
         error_setg(errp, "chardev: opening backend \"%s\" failed",
                    qemu_opt_get(opts, "backend"));
@@ -3677,3 +3658,44 @@ void qmp_chardev_remove(const char *id, Error **errp)
     }
     qemu_chr_delete(chr);
 }
+
+static void register_types(void)
+{
+    register_char_driver("null", qemu_chr_open_null);
+    register_char_driver("socket", qemu_chr_open_socket);
+    register_char_driver("udp", qemu_chr_open_udp);
+    register_char_driver("msmouse", qemu_chr_open_msmouse);
+    register_char_driver("vc", vc_init);
+    register_char_driver("memory", qemu_chr_open_ringbuf);
+#ifdef _WIN32
+    register_char_driver("file", qemu_chr_open_win_file_out);
+    register_char_driver("pipe", qemu_chr_open_win_pipe);
+    register_char_driver("console", qemu_chr_open_win_con);
+    register_char_driver("serial", qemu_chr_open_win);
+    register_char_driver("stdio", qemu_chr_open_win_stdio);
+#else
+    register_char_driver("file", qemu_chr_open_file_out);
+    register_char_driver("pipe", qemu_chr_open_pipe);
+    register_char_driver("stdio", qemu_chr_open_stdio);
+#endif
+#ifdef CONFIG_BRLAPI
+    register_char_driver("braille", chr_baum_init);
+#endif
+#ifdef HAVE_CHARDEV_TTY
+    register_char_driver("tty", qemu_chr_open_tty);
+    register_char_driver("serial", qemu_chr_open_tty);
+    register_char_driver("pty", qemu_chr_open_pty);
+#endif
+#ifdef HAVE_CHARDEV_PARPORT
+    register_char_driver("parallel", qemu_chr_open_pp);
+    register_char_driver("parport", qemu_chr_open_pp);
+#endif
+#ifdef CONFIG_SPICE
+    register_char_driver("spicevmc", qemu_chr_open_spice);
+#if SPICE_SERVER_VERSION >= 0x000c02
+    register_char_driver("spiceport", qemu_chr_open_spice_port);
+#endif
+#endif
+}
+
+type_init(register_types);
commit 9f939df955a4152aad69a19a77e0898631bb2c18
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 5 23:21:27 2013 +0530

    qemu-char: remove use of QEMUTimer in favor of glib idle function
    
    qemu-char is now independent of the QEMU main loop.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 3cda0bbcfb94912df8a767983a52bb71a4a3231d.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/char/char.h b/include/char/char.h
index 09ac401..e8b781c 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -71,7 +71,7 @@ struct CharDriverState {
     void (*chr_guest_open)(struct CharDriverState *chr);
     void (*chr_guest_close)(struct CharDriverState *chr);
     void *opaque;
-    QEMUTimer *open_timer;
+    int idle_tag;
     char *label;
     char *filename;
     int opened;
diff --git a/qemu-char.c b/qemu-char.c
index 6dba943..2c7c929 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -122,20 +122,18 @@ void qemu_chr_be_event(CharDriverState *s, int event)
     s->chr_event(s->handler_opaque, event);
 }
 
-static void qemu_chr_fire_open_event(void *opaque)
+static gboolean qemu_chr_generic_open_bh(gpointer opaque)
 {
     CharDriverState *s = opaque;
     qemu_chr_be_event(s, CHR_EVENT_OPENED);
-    qemu_free_timer(s->open_timer);
-    s->open_timer = NULL;
+    s->idle_tag = 0;
+    return FALSE;
 }
 
 void qemu_chr_generic_open(CharDriverState *s)
 {
-    if (s->open_timer == NULL) {
-        s->open_timer = qemu_new_timer_ms(rt_clock,
-                                          qemu_chr_fire_open_event, s);
-        qemu_mod_timer(s->open_timer, qemu_get_clock_ms(rt_clock) - 1);
+    if (s->idle_tag == 0) {
+        s->idle_tag = g_idle_add(qemu_chr_generic_open_bh, s);
     }
 }
 
commit 8aa33cafc41a0fe8549d1dbcc65b75c31112dea8
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 5 23:21:26 2013 +0530

    qemu-char: use a glib timeout instead of qemu-timer
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 05a883ce5a98275b976bf0124610599859c2b7da.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index eb0ac81..6dba943 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -990,12 +990,50 @@ typedef struct {
     int connected;
     int polling;
     int read_bytes;
-    QEMUTimer *timer;
+    guint timer_tag;
 } PtyCharDriver;
 
 static void pty_chr_update_read_handler(CharDriverState *chr);
 static void pty_chr_state(CharDriverState *chr, int connected);
 
+static gboolean pty_chr_timer(gpointer opaque)
+{
+    struct CharDriverState *chr = opaque;
+    PtyCharDriver *s = chr->opaque;
+
+    if (s->connected) {
+        goto out;
+    }
+    if (s->polling) {
+        /* If we arrive here without polling being cleared due
+         * read returning -EIO, then we are (re-)connected */
+        pty_chr_state(chr, 1);
+        goto out;
+    }
+
+    /* Next poll ... */
+    pty_chr_update_read_handler(chr);
+
+out:
+    return FALSE;
+}
+
+static void pty_chr_rearm_timer(CharDriverState *chr, int ms)
+{
+    PtyCharDriver *s = chr->opaque;
+
+    if (s->timer_tag) {
+        g_source_remove(s->timer_tag);
+        s->timer_tag = 0;
+    }
+
+    if (ms == 1000) {
+        s->timer_tag = g_timeout_add_seconds(1, pty_chr_timer, chr);
+    } else {
+        s->timer_tag = g_timeout_add(ms, pty_chr_timer, chr);
+    }
+}
+
 static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     PtyCharDriver *s = chr->opaque;
@@ -1065,7 +1103,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_ms(rt_clock) + 10);
+    pty_chr_rearm_timer(chr, 10);
 }
 
 static void pty_chr_state(CharDriverState *chr, int connected)
@@ -1080,7 +1118,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_ms(rt_clock) + 1000);
+        pty_chr_rearm_timer(chr, 1000);
     } else {
         if (!s->connected)
             qemu_chr_generic_open(chr);
@@ -1088,23 +1126,6 @@ static void pty_chr_state(CharDriverState *chr, int connected)
     }
 }
 
-static void pty_chr_timer(void *opaque)
-{
-    struct CharDriverState *chr = opaque;
-    PtyCharDriver *s = chr->opaque;
-
-    if (s->connected)
-        return;
-    if (s->polling) {
-        /* If we arrive here without polling being cleared due
-         * read returning -EIO, then we are (re-)connected */
-        pty_chr_state(chr, 1);
-        return;
-    }
-
-    /* Next poll ... */
-    pty_chr_update_read_handler(chr);
-}
 
 static void pty_chr_close(struct CharDriverState *chr)
 {
@@ -1117,8 +1138,9 @@ static void pty_chr_close(struct CharDriverState *chr)
     fd = g_io_channel_unix_get_fd(s->fd);
     g_io_channel_unref(s->fd);
     close(fd);
-    qemu_del_timer(s->timer);
-    qemu_free_timer(s->timer);
+    if (s->timer_tag) {
+        g_source_remove(s->timer_tag);
+    }
     g_free(s);
     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
@@ -1170,7 +1192,7 @@ static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
     chr->chr_add_watch = pty_chr_add_watch;
 
     s->fd = io_channel_from_fd(master_fd);
-    s->timer = qemu_new_timer_ms(rt_clock, pty_chr_timer, chr);
+    s->timer_tag = 0;
 
     return chr;
 }
commit d3cc5bc416cdf25bae0f3f6de58830be8ac5b648
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Mar 5 23:21:25 2013 +0530

    char: add gio watch fn for tcp backends
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: b50e668c4f4146a654c5d4412440eb9e589f2c02.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index f1d089f..eb0ac81 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2462,6 +2462,12 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
 }
 #endif
 
+static GSource *tcp_chr_add_watch(CharDriverState *chr, GIOCondition cond)
+{
+    TCPCharDriver *s = chr->opaque;
+    return g_io_create_watch(s->chan, cond);
+}
+
 static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
 {
     CharDriverState *chr = opaque;
@@ -2670,6 +2676,7 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
     chr->chr_close = tcp_chr_close;
     chr->get_msgfd = tcp_get_msgfd;
     chr->chr_add_client = tcp_chr_add_client;
+    chr->chr_add_watch = tcp_chr_add_watch;
 
     if (is_listen) {
         s->listen_fd = fd;
commit e6a87ed837b52aea903c25693b1e3703824b9ef7
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 5 23:21:24 2013 +0530

    qemu-char: add pty watch
    
    This lets ptys support adding front end watchs.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 23380f37b22d407ba0b9e080f6ea0d66b279f2d2.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index 7091743..f1d089f 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1008,6 +1008,12 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
     return io_channel_send_all(s->fd, buf, len);
 }
 
+static GSource *pty_chr_add_watch(CharDriverState *chr, GIOCondition cond)
+{
+    PtyCharDriver *s = chr->opaque;
+    return g_io_create_watch(s->fd, cond);
+}
+
 static int pty_chr_read_poll(void *opaque)
 {
     CharDriverState *chr = opaque;
@@ -1161,6 +1167,7 @@ static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
     chr->chr_write = pty_chr_write;
     chr->chr_update_read_handler = pty_chr_update_read_handler;
     chr->chr_close = pty_chr_close;
+    chr->chr_add_watch = pty_chr_add_watch;
 
     s->fd = io_channel_from_fd(master_fd);
     s->timer = qemu_new_timer_ms(rt_clock, pty_chr_timer, chr);
commit 23673ca740e0eda66901ca801a5a901df378b063
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 5 23:21:23 2013 +0530

    qemu-char: add watch support
    
    This allows a front-end to request for a callback when the backend
    is writable again.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 96f93c0f741064604bbb6389ce962191120af8b7.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/char/char.h b/include/char/char.h
index c91ce3c..09ac401 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -56,6 +56,7 @@ typedef void IOEventHandler(void *opaque, int event);
 struct CharDriverState {
     void (*init)(struct CharDriverState *s);
     int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
+    GSource *(*chr_add_watch)(struct CharDriverState *s, GIOCondition cond);
     void (*chr_update_read_handler)(struct CharDriverState *s);
     int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg);
     int (*get_msgfd)(struct CharDriverState *s);
@@ -152,6 +153,9 @@ void qemu_chr_fe_close(struct CharDriverState *chr);
 void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...)
     GCC_FMT_ATTR(2, 3);
 
+guint qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
+                            GIOFunc func, void *user_data);
+
 /**
  * @qemu_chr_fe_write:
  *
diff --git a/qemu-char.c b/qemu-char.c
index 5a53491..7091743 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -686,7 +686,11 @@ static int io_channel_send_all(GIOChannel *fd, const void *_buf, int len1)
         status = g_io_channel_write_chars(fd, (const gchar *)buf, len,
                                           &bytes_written, NULL);
         if (status != G_IO_STATUS_NORMAL) {
-            if (status != G_IO_STATUS_AGAIN) {
+            if (status == G_IO_STATUS_AGAIN) {
+                errno = EAGAIN;
+                return -1;
+            } else {
+                errno = EINVAL;
                 return -1;
             }
         } else if (status == G_IO_STATUS_EOF) {
@@ -753,6 +757,12 @@ static int fd_chr_read_poll(void *opaque)
     return s->max_size;
 }
 
+static GSource *fd_chr_add_watch(CharDriverState *chr, GIOCondition cond)
+{
+    FDCharDriver *s = chr->opaque;
+    return g_io_create_watch(s->fd_out, cond);
+}
+
 static void fd_chr_update_read_handler(CharDriverState *chr)
 {
     FDCharDriver *s = chr->opaque;
@@ -796,8 +806,10 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
     s = g_malloc0(sizeof(FDCharDriver));
     s->fd_in = io_channel_from_fd(fd_in);
     s->fd_out = io_channel_from_fd(fd_out);
+    fcntl(fd_out, F_SETFL, O_NONBLOCK);
     s->chr = chr;
     chr->opaque = s;
+    chr->chr_add_watch = fd_chr_add_watch;
     chr->chr_write = fd_chr_write;
     chr->chr_update_read_handler = fd_chr_update_read_handler;
     chr->chr_close = fd_chr_close;
@@ -3279,6 +3291,24 @@ void qemu_chr_fe_close(struct CharDriverState *chr)
     }
 }
 
+guint qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
+                            GIOFunc func, void *user_data)
+{
+    GSource *src;
+    guint tag;
+
+    if (s->chr_add_watch == NULL) {
+        return -ENOSYS;
+    }
+
+    src = s->chr_add_watch(s, cond);
+    g_source_set_callback(src, (GSourceFunc)func, user_data, NULL);
+    tag = g_source_attach(src, NULL);
+    g_source_unref(src);
+
+    return tag;
+}
+
 void qemu_chr_delete(CharDriverState *chr)
 {
     QTAILQ_REMOVE(&chardevs, chr, next);
commit 2ea5a7af7bfa576a5936400ccca4144caca9640b
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 5 23:21:22 2013 +0530

    qemu-char: tcp: make use GIOChannel
    
    I didn't bother switching to g_io_channel_read/write because we need to use
    sendmsg on Unix.  No problem though since we're using an unbuffered channel.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 002f726576dfb51bca4854aa257b74d77c1cd4e8.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index 94ff332..5a53491 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2285,6 +2285,9 @@ return_err:
 /* TCP Net console */
 
 typedef struct {
+
+    GIOChannel *chan, *listen_chan;
+    guint tag, listen_tag;
     int fd, listen_fd;
     int connected;
     int max_size;
@@ -2294,13 +2297,13 @@ typedef struct {
     int msgfd;
 } TCPCharDriver;
 
-static void tcp_chr_accept(void *opaque);
+static gboolean tcp_chr_accept(GIOChannel *chan, GIOCondition cond, void *opaque);
 
 static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     TCPCharDriver *s = chr->opaque;
     if (s->connected) {
-        return send_all(s->fd, buf, len);
+        return io_channel_send_all(s->chan, buf, len);
     } else {
         /* XXX: indicate an error ? */
         return len;
@@ -2440,15 +2443,16 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
 }
 #endif
 
-static void tcp_chr_read(void *opaque)
+static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
 {
     CharDriverState *chr = opaque;
     TCPCharDriver *s = chr->opaque;
     uint8_t buf[READ_BUF_LEN];
     int len, size;
 
-    if (!s->connected || s->max_size <= 0)
-        return;
+    if (!s->connected || s->max_size <= 0) {
+        return FALSE;
+    }
     len = sizeof(buf);
     if (len > s->max_size)
         len = s->max_size;
@@ -2456,10 +2460,13 @@ static void tcp_chr_read(void *opaque)
     if (size == 0) {
         /* connection closed */
         s->connected = 0;
-        if (s->listen_fd >= 0) {
-            qemu_set_fd_handler2(s->listen_fd, NULL, tcp_chr_accept, NULL, chr);
+        if (s->listen_chan) {
+            s->listen_tag = g_io_add_watch(s->listen_chan, G_IO_IN, tcp_chr_accept, chr);
         }
-        qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+        g_source_remove(s->tag);
+        s->tag = 0;
+        g_io_channel_unref(s->chan);
+        s->chan = NULL;
         closesocket(s->fd);
         s->fd = -1;
         qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
@@ -2469,6 +2476,8 @@ static void tcp_chr_read(void *opaque)
         if (size > 0)
             qemu_chr_be_write(chr, buf, size);
     }
+
+    return TRUE;
 }
 
 #ifndef _WIN32
@@ -2484,9 +2493,8 @@ static void tcp_chr_connect(void *opaque)
     TCPCharDriver *s = chr->opaque;
 
     s->connected = 1;
-    if (s->fd >= 0) {
-        qemu_set_fd_handler2(s->fd, tcp_chr_read_poll,
-                             tcp_chr_read, NULL, chr);
+    if (s->chan) {
+        s->tag = io_add_watch_poll(s->chan, tcp_chr_read_poll, tcp_chr_read, chr);
     }
     qemu_chr_generic_open(chr);
 }
@@ -2516,13 +2524,15 @@ static int tcp_chr_add_client(CharDriverState *chr, int fd)
     if (s->do_nodelay)
         socket_set_nodelay(fd);
     s->fd = fd;
-    qemu_set_fd_handler2(s->listen_fd, NULL, NULL, NULL, NULL);
+    s->chan = io_channel_from_socket(fd);
+    g_source_remove(s->listen_tag);
+    s->listen_tag = 0;
     tcp_chr_connect(chr);
 
     return 0;
 }
 
-static void tcp_chr_accept(void *opaque)
+static gboolean tcp_chr_accept(GIOChannel *channel, GIOCondition cond, void *opaque)
 {
     CharDriverState *chr = opaque;
     TCPCharDriver *s = chr->opaque;
@@ -2547,7 +2557,7 @@ static void tcp_chr_accept(void *opaque)
 	}
         fd = qemu_accept(s->listen_fd, addr, &len);
         if (fd < 0 && errno != EINTR) {
-            return;
+            return FALSE;
         } else if (fd >= 0) {
             if (s->do_telnetopt)
                 tcp_chr_telnet_init(fd);
@@ -2556,17 +2566,29 @@ static void tcp_chr_accept(void *opaque)
     }
     if (tcp_chr_add_client(chr, fd) < 0)
 	close(fd);
+
+    return TRUE;
 }
 
 static void tcp_chr_close(CharDriverState *chr)
 {
     TCPCharDriver *s = chr->opaque;
     if (s->fd >= 0) {
-        qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+        if (s->tag) {
+            g_source_remove(s->tag);
+        }
+        if (s->chan) {
+            g_io_channel_unref(s->chan);
+        }
         closesocket(s->fd);
     }
     if (s->listen_fd >= 0) {
-        qemu_set_fd_handler2(s->listen_fd, NULL, NULL, NULL, NULL);
+        if (s->listen_tag) {
+            g_source_remove(s->listen_tag);
+        }
+        if (s->listen_chan) {
+            g_io_channel_unref(s->listen_chan);
+        }
         closesocket(s->listen_fd);
     }
     g_free(s);
@@ -2632,7 +2654,8 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
 
     if (is_listen) {
         s->listen_fd = fd;
-        qemu_set_fd_handler2(s->listen_fd, NULL, tcp_chr_accept, NULL, chr);
+        s->listen_chan = io_channel_from_socket(s->listen_fd);
+        s->listen_tag = g_io_add_watch(s->listen_chan, G_IO_IN, tcp_chr_accept, chr);
         if (is_telnet) {
             s->do_telnetopt = 1;
         }
@@ -2640,13 +2663,14 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
         s->connected = 1;
         s->fd = fd;
         socket_set_nodelay(fd);
+        s->chan = io_channel_from_socket(s->fd);
         tcp_chr_connect(chr);
     }
 
     if (is_listen && is_waitconnect) {
         printf("QEMU waiting for connection on: %s\n",
                chr->filename);
-        tcp_chr_accept(chr);
+        tcp_chr_accept(s->listen_chan, G_IO_IN, chr);
         socket_set_nonblock(s->listen_fd);
     }
     return chr;
commit 76a9644b711541472d9fb3a9b418acd55d9464a1
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 5 23:21:21 2013 +0530

    qemu-char: convert UDP to GIOChannel
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 775a2bd666a3d1fa008656bf97191b7573c6ffb5.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index 64b95d7..94ff332 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -654,6 +654,26 @@ static GIOChannel *io_channel_from_fd(int fd)
     return chan;
 }
 
+static GIOChannel *io_channel_from_socket(int fd)
+{
+    GIOChannel *chan;
+
+    if (fd == -1) {
+        return NULL;
+    }
+
+#ifdef _WIN32
+    chan = g_io_channel_win32_new_socket(fd);
+#else
+    chan = g_io_channel_unix_new(fd);
+#endif
+
+    g_io_channel_set_encoding(chan, NULL, NULL);
+    g_io_channel_set_buffered(chan, FALSE);
+
+    return chan;
+}
+
 static int io_channel_send_all(GIOChannel *fd, const void *_buf, int len1)
 {
     GIOStatus status;
@@ -2126,6 +2146,8 @@ static CharDriverState *qemu_chr_open_win_stdio(QemuOpts *opts)
 
 typedef struct {
     int fd;
+    GIOChannel *chan;
+    guint tag;
     uint8_t buf[READ_BUF_LEN];
     int bufcnt;
     int bufptr;
@@ -2135,8 +2157,17 @@ typedef struct {
 static int udp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     NetCharDriver *s = chr->opaque;
+    gsize bytes_written;
+    GIOStatus status;
+
+    status = g_io_channel_write_chars(s->chan, (const gchar *)buf, len, &bytes_written, NULL);
+    if (status == G_IO_STATUS_EOF) {
+        return 0;
+    } else if (status != G_IO_STATUS_NORMAL) {
+        return -1;
+    }
 
-    return send(s->fd, (const void *)buf, len, 0);
+    return bytes_written;
 }
 
 static int udp_chr_read_poll(void *opaque)
@@ -2157,17 +2188,22 @@ static int udp_chr_read_poll(void *opaque)
     return s->max_size;
 }
 
-static void udp_chr_read(void *opaque)
+static gboolean udp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
 {
     CharDriverState *chr = opaque;
     NetCharDriver *s = chr->opaque;
+    gsize bytes_read = 0;
+    GIOStatus status;
 
     if (s->max_size == 0)
-        return;
-    s->bufcnt = qemu_recv(s->fd, s->buf, sizeof(s->buf), 0);
+        return FALSE;
+    status = g_io_channel_read_chars(s->chan, (gchar *)s->buf, sizeof(s->buf),
+                                     &bytes_read, NULL);
+    s->bufcnt = bytes_read;
     s->bufptr = s->bufcnt;
-    if (s->bufcnt <= 0)
-        return;
+    if (status != G_IO_STATUS_NORMAL) {
+        return FALSE;
+    }
 
     s->bufptr = 0;
     while (s->max_size > 0 && s->bufptr < s->bufcnt) {
@@ -2175,23 +2211,32 @@ static void udp_chr_read(void *opaque)
         s->bufptr++;
         s->max_size = qemu_chr_be_can_write(chr);
     }
+
+    return TRUE;
 }
 
 static void udp_chr_update_read_handler(CharDriverState *chr)
 {
     NetCharDriver *s = chr->opaque;
 
-    if (s->fd >= 0) {
-        qemu_set_fd_handler2(s->fd, udp_chr_read_poll,
-                             udp_chr_read, NULL, chr);
+    if (s->tag) {
+        g_source_remove(s->tag);
+        s->tag = 0;
+    }
+
+    if (s->chan) {
+        s->tag = io_add_watch_poll(s->chan, udp_chr_read_poll, udp_chr_read, chr);
     }
 }
 
 static void udp_chr_close(CharDriverState *chr)
 {
     NetCharDriver *s = chr->opaque;
-    if (s->fd >= 0) {
-        qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+    if (s->tag) {
+        g_source_remove(s->tag);
+    }
+    if (s->chan) {
+        g_io_channel_unref(s->chan);
         closesocket(s->fd);
     }
     g_free(s);
@@ -2214,6 +2259,7 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
     }
 
     s->fd = fd;
+    s->chan = io_channel_from_socket(s->fd);
     s->bufcnt = 0;
     s->bufptr = 0;
     chr->opaque = s;
commit 093d3a20055282e282ba056addbe59b79e13a32f
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 5 23:21:20 2013 +0530

    qemu-char: convert pty to GIOChannel
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 339eebf3c59a450b0354056e9ac4b41f67230831.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index 4c63ccb..64b95d7 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -953,7 +953,8 @@ static void cfmakeraw (struct termios *termios_p)
 #define HAVE_CHARDEV_TTY 1
 
 typedef struct {
-    int fd;
+    GIOChannel *fd;
+    guint fd_tag;
     int connected;
     int polling;
     int read_bytes;
@@ -972,7 +973,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
         pty_chr_update_read_handler(chr);
         return 0;
     }
-    return send_all(s->fd, buf, len);
+    return io_channel_send_all(s->fd, buf, len);
 }
 
 static int pty_chr_read_poll(void *opaque)
@@ -984,36 +985,39 @@ static int pty_chr_read_poll(void *opaque)
     return s->read_bytes;
 }
 
-static void pty_chr_read(void *opaque)
+static gboolean pty_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
 {
     CharDriverState *chr = opaque;
     PtyCharDriver *s = chr->opaque;
-    int size, len;
+    gsize size, len;
     uint8_t buf[READ_BUF_LEN];
+    GIOStatus status;
 
     len = sizeof(buf);
     if (len > s->read_bytes)
         len = s->read_bytes;
     if (len == 0)
-        return;
-    size = read(s->fd, buf, len);
-    if ((size == -1 && errno == EIO) ||
-        (size == 0)) {
+        return FALSE;
+    status = g_io_channel_read_chars(s->fd, (gchar *)buf, len, &size, NULL);
+    if (status != G_IO_STATUS_NORMAL) {
         pty_chr_state(chr, 0);
-        return;
-    }
-    if (size > 0) {
+        return FALSE;
+    } else {
         pty_chr_state(chr, 1);
         qemu_chr_be_write(chr, buf, size);
     }
+    return TRUE;
 }
 
 static void pty_chr_update_read_handler(CharDriverState *chr)
 {
     PtyCharDriver *s = chr->opaque;
 
-    qemu_set_fd_handler2(s->fd, pty_chr_read_poll,
-                         pty_chr_read, NULL, chr);
+    if (s->fd_tag) {
+        g_source_remove(s->fd_tag);
+    }
+
+    s->fd_tag = io_add_watch_poll(s->fd, pty_chr_read_poll, pty_chr_read, chr);
     s->polling = 1;
     /*
      * Short timeout here: just need wait long enougth that qemu makes
@@ -1031,7 +1035,8 @@ static void pty_chr_state(CharDriverState *chr, int connected)
     PtyCharDriver *s = chr->opaque;
 
     if (!connected) {
-        qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+        g_source_remove(s->fd_tag);
+        s->fd_tag = 0;
         s->connected = 0;
         s->polling = 0;
         /* (re-)connect poll interval for idle guests: once per second.
@@ -1066,9 +1071,14 @@ static void pty_chr_timer(void *opaque)
 static void pty_chr_close(struct CharDriverState *chr)
 {
     PtyCharDriver *s = chr->opaque;
+    int fd;
 
-    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
-    close(s->fd);
+    if (s->fd_tag) {
+        g_source_remove(s->fd_tag);
+    }
+    fd = g_io_channel_unix_get_fd(s->fd);
+    g_io_channel_unref(s->fd);
+    close(fd);
     qemu_del_timer(s->timer);
     qemu_free_timer(s->timer);
     g_free(s);
@@ -1120,7 +1130,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->fd = master_fd;
+    s->fd = io_channel_from_fd(master_fd);
     s->timer = qemu_new_timer_ms(rt_clock, pty_chr_timer, chr);
 
     return chr;
commit a29753f8aa79a34a324afebe340182a51a5aef11
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 5 23:21:19 2013 +0530

    qemu-char: convert fd_chr to use a GIOChannel
    
    This uses the newly introduced IOWatchPoll source.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 0cb5d14510ee835a0ebc23676d10a2cce9280da5.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index 8aa0b41..4c63ccb 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -541,7 +541,6 @@ int send_all(int fd, const void *_buf, int len1)
 
 #ifndef _WIN32
 
-#if 0
 typedef struct IOWatchPoll
 {
     GSource *src;
@@ -679,60 +678,71 @@ static int io_channel_send_all(GIOChannel *fd, const void *_buf, int len1)
     }
     return len1 - len;
 }
-#endif
 
-typedef struct {
-    int fd_in, fd_out;
+typedef struct FDCharDriver {
+    CharDriverState *chr;
+    GIOChannel *fd_in, *fd_out;
+    guint fd_in_tag;
     int max_size;
+    QTAILQ_ENTRY(FDCharDriver) node;
 } FDCharDriver;
 
-
 static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     FDCharDriver *s = chr->opaque;
-    return send_all(s->fd_out, buf, len);
+    
+    return io_channel_send_all(s->fd_out, buf, len);
 }
 
-static int fd_chr_read_poll(void *opaque)
+static gboolean fd_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
 {
     CharDriverState *chr = opaque;
     FDCharDriver *s = chr->opaque;
-
-    s->max_size = qemu_chr_be_can_write(chr);
-    return s->max_size;
-}
-
-static void fd_chr_read(void *opaque)
-{
-    CharDriverState *chr = opaque;
-    FDCharDriver *s = chr->opaque;
-    int size, len;
+    int len;
     uint8_t buf[READ_BUF_LEN];
+    GIOStatus status;
+    gsize bytes_read;
 
     len = sizeof(buf);
-    if (len > s->max_size)
+    if (len > s->max_size) {
         len = s->max_size;
-    if (len == 0)
-        return;
-    size = read(s->fd_in, buf, len);
-    if (size == 0) {
-        /* FD has been closed. Remove it from the active list.  */
-        qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL);
+    }
+    if (len == 0) {
+        return FALSE;
+    }
+
+    status = g_io_channel_read_chars(chan, (gchar *)buf,
+                                     len, &bytes_read, NULL);
+    if (status == G_IO_STATUS_EOF) {
         qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
-        return;
+        return FALSE;
     }
-    if (size > 0) {
-        qemu_chr_be_write(chr, buf, size);
+    if (status == G_IO_STATUS_NORMAL) {
+        qemu_chr_be_write(chr, buf, bytes_read);
     }
+
+    return TRUE;
+}
+
+static int fd_chr_read_poll(void *opaque)
+{
+    CharDriverState *chr = opaque;
+    FDCharDriver *s = chr->opaque;
+
+    s->max_size = qemu_chr_be_can_write(chr);
+    return s->max_size;
 }
 
 static void fd_chr_update_read_handler(CharDriverState *chr)
 {
     FDCharDriver *s = chr->opaque;
 
-    if (s->fd_in >= 0) {
-        qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll,
-                             fd_chr_read, NULL, chr);
+    if (s->fd_in_tag) {
+        g_source_remove(s->fd_in_tag);
+    }
+
+    if (s->fd_in) {
+        s->fd_in_tag = io_add_watch_poll(s->fd_in, fd_chr_read_poll, fd_chr_read, chr);
     }
 }
 
@@ -740,8 +750,16 @@ static void fd_chr_close(struct CharDriverState *chr)
 {
     FDCharDriver *s = chr->opaque;
 
-    if (s->fd_in >= 0) {
-        qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL);
+    if (s->fd_in_tag) {
+        g_source_remove(s->fd_in_tag);
+        s->fd_in_tag = 0;
+    }
+
+    if (s->fd_in) {
+        g_io_channel_unref(s->fd_in);
+    }
+    if (s->fd_out) {
+        g_io_channel_unref(s->fd_out);
     }
 
     g_free(s);
@@ -756,8 +774,9 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
 
     chr = g_malloc0(sizeof(CharDriverState));
     s = g_malloc0(sizeof(FDCharDriver));
-    s->fd_in = fd_in;
-    s->fd_out = fd_out;
+    s->fd_in = io_channel_from_fd(fd_in);
+    s->fd_out = io_channel_from_fd(fd_out);
+    s->chr = chr;
     chr->opaque = s;
     chr->chr_write = fd_chr_write;
     chr->chr_update_read_handler = fd_chr_update_read_handler;
@@ -1230,22 +1249,24 @@ static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg)
     case CHR_IOCTL_SERIAL_SET_PARAMS:
         {
             QEMUSerialSetParams *ssp = arg;
-            tty_serial_init(s->fd_in, ssp->speed, ssp->parity,
+            tty_serial_init(g_io_channel_unix_get_fd(s->fd_in),
+                            ssp->speed, ssp->parity,
                             ssp->data_bits, ssp->stop_bits);
         }
         break;
     case CHR_IOCTL_SERIAL_SET_BREAK:
         {
             int enable = *(int *)arg;
-            if (enable)
-                tcsendbreak(s->fd_in, 1);
+            if (enable) {
+                tcsendbreak(g_io_channel_unix_get_fd(s->fd_in), 1);
+            }
         }
         break;
     case CHR_IOCTL_SERIAL_GET_TIOCM:
         {
             int sarg = 0;
             int *targ = (int *)arg;
-            ioctl(s->fd_in, TIOCMGET, &sarg);
+            ioctl(g_io_channel_unix_get_fd(s->fd_in), TIOCMGET, &sarg);
             *targ = 0;
             if (sarg & TIOCM_CTS)
                 *targ |= CHR_TIOCM_CTS;
@@ -1265,7 +1286,7 @@ static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg)
         {
             int sarg = *(int *)arg;
             int targ = 0;
-            ioctl(s->fd_in, TIOCMGET, &targ);
+            ioctl(g_io_channel_unix_get_fd(s->fd_in), TIOCMGET, &targ);
             targ &= ~(CHR_TIOCM_CTS | CHR_TIOCM_CAR | CHR_TIOCM_DSR
                      | CHR_TIOCM_RI | CHR_TIOCM_DTR | CHR_TIOCM_RTS);
             if (sarg & CHR_TIOCM_CTS)
@@ -1280,7 +1301,7 @@ static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg)
                 targ |= TIOCM_DTR;
             if (sarg & CHR_TIOCM_RTS)
                 targ |= TIOCM_RTS;
-            ioctl(s->fd_in, TIOCMSET, &targ);
+            ioctl(g_io_channel_unix_get_fd(s->fd_in), TIOCMSET, &targ);
         }
         break;
     default:
@@ -1295,7 +1316,7 @@ static void qemu_chr_close_tty(CharDriverState *chr)
     int fd = -1;
 
     if (s) {
-        fd = s->fd_in;
+        fd = g_io_channel_unix_get_fd(s->fd_in);
     }
 
     fd_chr_close(chr);
commit 96c6384776d631839a9c8fe02bf135f9ba22586c
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 5 23:21:18 2013 +0530

    char: add IOWatchPoll support
    
    This is a special GSource that supports CharDriverState style
    poll callbacks.
    
    For reviewability and bisectability, this code is #if 0'd out in this
    patch to avoid unused warnings since all of the functions are static.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 9b59ac17b9d0bb3972a73fed04d415f07b391936.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index 0a74c10..8aa0b41 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -541,6 +541,146 @@ int send_all(int fd, const void *_buf, int len1)
 
 #ifndef _WIN32
 
+#if 0
+typedef struct IOWatchPoll
+{
+    GSource *src;
+    int max_size;
+
+    IOCanReadHandler *fd_can_read;
+    void *opaque;
+
+    QTAILQ_ENTRY(IOWatchPoll) node;
+} IOWatchPoll;
+
+static QTAILQ_HEAD(, IOWatchPoll) io_watch_poll_list =
+    QTAILQ_HEAD_INITIALIZER(io_watch_poll_list);
+
+static IOWatchPoll *io_watch_poll_from_source(GSource *source)
+{
+    IOWatchPoll *i;
+
+    QTAILQ_FOREACH(i, &io_watch_poll_list, node) {
+        if (i->src == source) {
+            return i;
+        }
+    }
+
+    return NULL;
+}
+
+static gboolean io_watch_poll_prepare(GSource *source, gint *timeout_)
+{
+    IOWatchPoll *iwp = io_watch_poll_from_source(source);
+
+    iwp->max_size = iwp->fd_can_read(iwp->opaque);
+    if (iwp->max_size == 0) {
+        return FALSE;
+    }
+
+    return g_io_watch_funcs.prepare(source, timeout_);
+}
+
+static gboolean io_watch_poll_check(GSource *source)
+{
+    IOWatchPoll *iwp = io_watch_poll_from_source(source);
+
+    if (iwp->max_size == 0) {
+        return FALSE;
+    }
+
+    return g_io_watch_funcs.check(source);
+}
+
+static gboolean io_watch_poll_dispatch(GSource *source, GSourceFunc callback,
+                                       gpointer user_data)
+{
+    return g_io_watch_funcs.dispatch(source, callback, user_data);
+}
+
+static void io_watch_poll_finalize(GSource *source)
+{
+    IOWatchPoll *iwp = io_watch_poll_from_source(source);
+    QTAILQ_REMOVE(&io_watch_poll_list, iwp, node);
+    g_io_watch_funcs.finalize(source);
+}
+
+static GSourceFuncs io_watch_poll_funcs = {
+    .prepare = io_watch_poll_prepare,
+    .check = io_watch_poll_check,
+    .dispatch = io_watch_poll_dispatch,
+    .finalize = io_watch_poll_finalize,
+};
+
+/* Can only be used for read */
+static guint io_add_watch_poll(GIOChannel *channel,
+                               IOCanReadHandler *fd_can_read,
+                               GIOFunc fd_read,
+                               gpointer user_data)
+{
+    IOWatchPoll *iwp;
+    GSource *src;
+    guint tag;
+
+    src = g_io_create_watch(channel, G_IO_IN | G_IO_ERR | G_IO_HUP);
+    g_source_set_funcs(src, &io_watch_poll_funcs);
+    g_source_set_callback(src, (GSourceFunc)fd_read, user_data, NULL);
+    tag = g_source_attach(src, NULL);
+    g_source_unref(src);
+
+    iwp = g_malloc0(sizeof(*iwp));
+    iwp->src = src;
+    iwp->max_size = 0;
+    iwp->fd_can_read = fd_can_read;
+    iwp->opaque = user_data;
+
+    QTAILQ_INSERT_HEAD(&io_watch_poll_list, iwp, node);
+
+    return tag;
+}
+
+static GIOChannel *io_channel_from_fd(int fd)
+{
+    GIOChannel *chan;
+
+    if (fd == -1) {
+        return NULL;
+    }
+
+    chan = g_io_channel_unix_new(fd);
+
+    g_io_channel_set_encoding(chan, NULL, NULL);
+    g_io_channel_set_buffered(chan, FALSE);
+
+    return chan;
+}
+
+static int io_channel_send_all(GIOChannel *fd, const void *_buf, int len1)
+{
+    GIOStatus status;
+    gsize bytes_written;
+    int len;
+    const uint8_t *buf = _buf;
+
+    len = len1;
+    while (len > 0) {
+        status = g_io_channel_write_chars(fd, (const gchar *)buf, len,
+                                          &bytes_written, NULL);
+        if (status != G_IO_STATUS_NORMAL) {
+            if (status != G_IO_STATUS_AGAIN) {
+                return -1;
+            }
+        } else if (status == G_IO_STATUS_EOF) {
+            break;
+        } else {
+            buf += bytes_written;
+            len -= bytes_written;
+        }
+    }
+    return len1 - len;
+}
+#endif
+
 typedef struct {
     int fd_in, fd_out;
     int max_size;
commit ed7a154063266a30a31752d3b18d484ddc7f5aa9
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 5 23:21:17 2013 +0530

    qemu-char: remove dead/confusing logic with nb_stdio_clients
    
    This code is very old dating back to 2007.  What is puzzling is that
    STDIO_MAX_CLIENTS was always #define to 1 meaning that all of the code to deal
    with more than one client was unreachable.
    
    Just remove the whole mess of it.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: d276bccdbf4e7463020c5f539f61ae3bfbc88d1d.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index 36295b1..0a74c10 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -539,9 +539,6 @@ int send_all(int fd, const void *_buf, int len1)
 }
 #endif /* !_WIN32 */
 
-#define STDIO_MAX_CLIENTS 1
-static int stdio_nb_clients;
-
 #ifndef _WIN32
 
 typedef struct {
@@ -594,11 +591,8 @@ static void fd_chr_update_read_handler(CharDriverState *chr)
     FDCharDriver *s = chr->opaque;
 
     if (s->fd_in >= 0) {
-        if (display_type == DT_NOGRAPHIC && s->fd_in == 0) {
-        } else {
-            qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll,
-                                 fd_chr_read, NULL, chr);
-        }
+        qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll,
+                             fd_chr_read, NULL, chr);
     }
 }
 
@@ -607,10 +601,7 @@ static void fd_chr_close(struct CharDriverState *chr)
     FDCharDriver *s = chr->opaque;
 
     if (s->fd_in >= 0) {
-        if (display_type == DT_NOGRAPHIC && s->fd_in == 0) {
-        } else {
-            qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL);
-        }
+        qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL);
     }
 
     g_free(s);
@@ -677,53 +668,6 @@ static CharDriverState *qemu_chr_open_pipe(QemuOpts *opts)
     return qemu_chr_open_fd(fd_in, fd_out);
 }
 
-
-/* for STDIO, we handle the case where several clients use it
-   (nographic mode) */
-
-#define TERM_FIFO_MAX_SIZE 1
-
-static uint8_t term_fifo[TERM_FIFO_MAX_SIZE];
-static int term_fifo_size;
-
-static int stdio_read_poll(void *opaque)
-{
-    CharDriverState *chr = opaque;
-
-    /* try to flush the queue if needed */
-    if (term_fifo_size != 0 && qemu_chr_be_can_write(chr) > 0) {
-        qemu_chr_be_write(chr, term_fifo, 1);
-        term_fifo_size = 0;
-    }
-    /* see if we can absorb more chars */
-    if (term_fifo_size == 0)
-        return 1;
-    else
-        return 0;
-}
-
-static void stdio_read(void *opaque)
-{
-    int size;
-    uint8_t buf[1];
-    CharDriverState *chr = opaque;
-
-    size = read(0, buf, 1);
-    if (size == 0) {
-        /* stdin has been closed. Remove it from the active list.  */
-        qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL);
-        qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
-        return;
-    }
-    if (size > 0) {
-        if (qemu_chr_be_can_write(chr) > 0) {
-            qemu_chr_be_write(chr, buf, 1);
-        } else if (term_fifo_size == 0) {
-            term_fifo[term_fifo_size++] = buf[0];
-        }
-    }
-}
-
 /* init terminal so that we can grab keys */
 static struct termios oldtty;
 static int old_fd0_flags;
@@ -760,8 +704,6 @@ static void qemu_chr_set_echo_stdio(CharDriverState *chr, bool echo)
 static void qemu_chr_close_stdio(struct CharDriverState *chr)
 {
     term_exit();
-    stdio_nb_clients--;
-    qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL);
     fd_chr_close(chr);
 }
 
@@ -769,25 +711,18 @@ static CharDriverState *qemu_chr_open_stdio(QemuOpts *opts)
 {
     CharDriverState *chr;
 
-    if (stdio_nb_clients >= STDIO_MAX_CLIENTS) {
-        return NULL;
-    }
     if (is_daemonized()) {
         error_report("cannot use stdio with -daemonize");
         return NULL;
     }
-    if (stdio_nb_clients == 0) {
-        old_fd0_flags = fcntl(0, F_GETFL);
-        tcgetattr (0, &oldtty);
-        fcntl(0, F_SETFL, O_NONBLOCK);
-        atexit(term_exit);
-    }
+    old_fd0_flags = fcntl(0, F_GETFL);
+    tcgetattr (0, &oldtty);
+    fcntl(0, F_SETFL, O_NONBLOCK);
+    atexit(term_exit);
 
     chr = qemu_chr_open_fd(0, 1);
     chr->chr_close = qemu_chr_close_stdio;
     chr->chr_set_echo = qemu_chr_set_echo_stdio;
-    qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr);
-    stdio_nb_clients++;
     stdio_allow_signal = qemu_opt_get_bool(opts, "signal",
                                            display_type != DT_NOGRAPHIC);
     qemu_chr_fe_set_echo(chr, false);
@@ -1448,8 +1383,6 @@ static CharDriverState *qemu_chr_open_pp_fd(int fd)
 
 #else /* _WIN32 */
 
-static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS];
-
 typedef struct {
     int max_size;
     HANDLE hcom, hrecv, hsend;
@@ -1951,7 +1884,6 @@ static void win_stdio_close(CharDriverState *chr)
 
     g_free(chr->opaque);
     g_free(chr);
-    stdio_nb_clients--;
 }
 
 static CharDriverState *qemu_chr_open_win_stdio(QemuOpts *opts)
@@ -1961,11 +1893,6 @@ static CharDriverState *qemu_chr_open_win_stdio(QemuOpts *opts)
     DWORD              dwMode;
     int                is_console = 0;
 
-    if (stdio_nb_clients >= STDIO_MAX_CLIENTS
-        || ((display_type != DT_NOGRAPHIC) && (stdio_nb_clients != 0))) {
-        return NULL;
-    }
-
     chr   = g_malloc0(sizeof(CharDriverState));
     stdio = g_malloc0(sizeof(WinStdioCharState));
 
@@ -1981,37 +1908,34 @@ static CharDriverState *qemu_chr_open_win_stdio(QemuOpts *opts)
     chr->chr_write = win_stdio_write;
     chr->chr_close = win_stdio_close;
 
-    if (stdio_nb_clients == 0) {
-        if (is_console) {
-            if (qemu_add_wait_object(stdio->hStdIn,
-                                     win_stdio_wait_func, chr)) {
-                fprintf(stderr, "qemu_add_wait_object: failed\n");
-            }
-        } else {
-            DWORD   dwId;
-
-            stdio->hInputReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-            stdio->hInputDoneEvent  = CreateEvent(NULL, FALSE, FALSE, NULL);
-            stdio->hInputThread     = CreateThread(NULL, 0, win_stdio_thread,
-                                            chr, 0, &dwId);
-
-            if (stdio->hInputThread == INVALID_HANDLE_VALUE
-                || stdio->hInputReadyEvent == INVALID_HANDLE_VALUE
-                || stdio->hInputDoneEvent == INVALID_HANDLE_VALUE) {
-                fprintf(stderr, "cannot create stdio thread or event\n");
-                exit(1);
-            }
-            if (qemu_add_wait_object(stdio->hInputReadyEvent,
-                                     win_stdio_thread_wait_func, chr)) {
-                fprintf(stderr, "qemu_add_wait_object: failed\n");
-            }
+    if (is_console) {
+        if (qemu_add_wait_object(stdio->hStdIn,
+                                 win_stdio_wait_func, chr)) {
+            fprintf(stderr, "qemu_add_wait_object: failed\n");
+        }
+    } else {
+        DWORD   dwId;
+            
+        stdio->hInputReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+        stdio->hInputDoneEvent  = CreateEvent(NULL, FALSE, FALSE, NULL);
+        stdio->hInputThread     = CreateThread(NULL, 0, win_stdio_thread,
+                                               chr, 0, &dwId);
+
+        if (stdio->hInputThread == INVALID_HANDLE_VALUE
+            || stdio->hInputReadyEvent == INVALID_HANDLE_VALUE
+            || stdio->hInputDoneEvent == INVALID_HANDLE_VALUE) {
+            fprintf(stderr, "cannot create stdio thread or event\n");
+            exit(1);
+        }
+        if (qemu_add_wait_object(stdio->hInputReadyEvent,
+                                 win_stdio_thread_wait_func, chr)) {
+            fprintf(stderr, "qemu_add_wait_object: failed\n");
         }
     }
 
     dwMode |= ENABLE_LINE_INPUT;
 
-    stdio_clients[stdio_nb_clients++] = chr;
-    if (stdio_nb_clients == 1 && is_console) {
+    if (is_console) {
         /* set the terminal in raw mode */
         /* ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS */
         dwMode |= ENABLE_PROCESSED_INPUT;
commit baca6f183d78a0c864a5ccc0ec64e26ba960e604
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 5 23:21:16 2013 +0530

    char-socket: fix error reporting
    
    Right now the inet connect code tries all available addresses but until one
    doesn't fail.  It passes local_err each time without clearing it from the
    previous failure.  This can trigger an assert since the inet connect code
    tries to set an error on an object != NULL.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Message-id: 16c806d60aa5e9660ed7751bb4e37dcd278f97f0.1362505276.git.amit.shah at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 1350ccc..3f12296 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -373,6 +373,10 @@ int inet_connect_opts(QemuOpts *opts, Error **errp,
     }
 
     for (e = res; e != NULL; e = e->ai_next) {
+        if (error_is_set(errp)) {
+            error_free(*errp);
+            *errp = NULL;
+        }
         if (connect_state != NULL) {
             connect_state->current_addr = e;
         }
commit db2d5eba652ecb7420ac4ef79fc747ef391ad0d9
Author: Lei Li <lilei at linux.vnet.ibm.com>
Date:   Thu Mar 7 15:50:26 2013 +0800

    Fix the wrong description in qemu manual
    
    Fix LP#1151450 the wrong description in qemu manual:
    
    'qemu-system-x86_84' should be 'qemu-system-x86_64'.
    
    Signed-off-by: Lei Li <lilei at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index 6f9334a..cd76f2a 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2132,7 +2132,7 @@ gluster[+transport]://[server[:port]]/volname/image[?socket=...]
 
 Example
 @example
-qemu-system-x86_84 --drive file=gluster://192.0.2.1/testvol/a.img
+qemu-system-x86_64 --drive file=gluster://192.0.2.1/testvol/a.img
 @end example
 
 See also @url{http://www.gluster.org}.
commit d37e12a07c06b13610b7fabb6b8e009d7a759bc8
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 1 16:57:41 2013 +0000

    pci_host: Drop write-only address_space field
    
    The address_space field of PCIHostState was only ever written, never used.
    Drop it completely.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/pci/pci_host.h b/hw/pci/pci_host.h
index 1845d4d..236cd0f 100644
--- a/hw/pci/pci_host.h
+++ b/hw/pci/pci_host.h
@@ -40,7 +40,6 @@ struct PCIHostState {
     MemoryRegion conf_mem;
     MemoryRegion data_mem;
     MemoryRegion mmcfg;
-    MemoryRegion *address_space;
     uint32_t config_reg;
     PCIBus *bus;
 };
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 6c77e49..9246983 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -244,7 +244,6 @@ static PCIBus *i440fx_common_init(const char *device_name,
 
     dev = qdev_create(NULL, "i440FX-pcihost");
     s = PCI_HOST_BRIDGE(dev);
-    s->address_space = address_space_mem;
     b = pci_bus_new(dev, NULL, pci_address_space,
                     address_space_io, 0);
     s->bus = b;
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index e06dded..2920911 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -567,7 +567,6 @@ static void ppc_prep_init(QEMUMachineInitArgs *args)
 
     dev = qdev_create(NULL, "raven-pcihost");
     pcihost = PCI_HOST_BRIDGE(dev);
-    pcihost->address_space = get_system_memory();
     object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev), NULL);
     qdev_init_nofail(dev);
     pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
commit 7f9c9d12856e65e272297a619705864d9e6346f8
Author: Stefan Berger <stefanb at linux.vnet.ibm.com>
Date:   Fri Mar 1 07:53:55 2013 -0500

    rng-random: Use qemu_open / qemu_close
    
    In the rng backend use qemu_open and qemu_close rather than POSIX
    open/close.
    
    Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/backends/rng-random.c b/backends/rng-random.c
index 0d11088..acd20af 100644
--- a/backends/rng-random.c
+++ b/backends/rng-random.c
@@ -74,7 +74,7 @@ static void rng_random_opened(RngBackend *b, Error **errp)
         error_set(errp, QERR_INVALID_PARAMETER_VALUE,
                   "filename", "a valid filename");
     } else {
-        s->fd = open(s->filename, O_RDONLY | O_NONBLOCK);
+        s->fd = qemu_open(s->filename, O_RDONLY | O_NONBLOCK);
 
         if (s->fd == -1) {
             error_set(errp, QERR_OPEN_FILE_FAILED, s->filename);
@@ -130,7 +130,7 @@ static void rng_random_finalize(Object *obj)
     qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
 
     if (s->fd != -1) {
-        close(s->fd);
+        qemu_close(s->fd);
     }
 
     g_free(s->filename);
commit 358689fe299c306f1d81bea57a5067d0abb56699
Author: Michal Privoznik <mprivozn at redhat.com>
Date:   Fri Mar 1 08:43:18 2013 +0100

    configure: Require at least spice-protocol-0.12.3
    
    As of 5a49d3e9 we assume SPICE_PORT_EVENT_BREAK to be defined.
    However, it is defined not in 0.12.2 what we require now, but in
    0.12.3.  Therefore in order to prevent build failure we must
    adjust our minimal requirements.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/configure b/configure
index 87b2e73..f2c46b2 100755
--- a/configure
+++ b/configure
@@ -2871,7 +2871,7 @@ EOF
   spice_cflags=$($pkg_config --cflags spice-protocol spice-server 2>/dev/null)
   spice_libs=$($pkg_config --libs spice-protocol spice-server 2>/dev/null)
   if $pkg_config --atleast-version=0.12.0 spice-server >/dev/null 2>&1 && \
-     $pkg_config --atleast-version=0.12.2 spice-protocol > /dev/null 2>&1 && \
+     $pkg_config --atleast-version=0.12.3 spice-protocol > /dev/null 2>&1 && \
      compile_prog "$spice_cflags" "$spice_libs" ; then
     spice="yes"
     libs_softmmu="$libs_softmmu $spice_libs"
commit 4bd1afbdb3a228683dafa77a9fb3093f0dfab1de
Author: Lei Li <lilei at linux.vnet.ibm.com>
Date:   Wed Mar 6 22:29:16 2013 +0800

    osdep: replace setsockopt by qemu_setsockopt
    
    Fix the compiler warning when cross build qemu-ga
    for windows by using qemu_setsockopt() instead of
    setsockopt().
    
    util/osdep.c: In function 'socket_set_nodelay':
    util/osdep.c:69:5: warning: passing argument 4 of 'setsockopt' from
                       incompatible pointer type [enabled by default]
    In file included from /home/lei/qemu_b/include/sysemu/os-win32.h:30:0,
                     from /home/lei/qemu_b/include/qemu-common.h:46,
                     from util/osdep.c:48:
    /usr/i686-w64-mingw32/sys-root/mingw/include/winsock2.h:990:63: note:
                     expected 'const char *' but argument is of type 'int *'
    
    Signed-off-by: Lei Li <lilei at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/util/osdep.c b/util/osdep.c
index c408261..bd59ac9 100644
--- a/util/osdep.c
+++ b/util/osdep.c
@@ -57,7 +57,7 @@ static const char *qemu_version = QEMU_VERSION;
 int socket_set_cork(int fd, int v)
 {
 #if defined(SOL_TCP) && defined(TCP_CORK)
-    return setsockopt(fd, SOL_TCP, TCP_CORK, &v, sizeof(v));
+    return qemu_setsockopt(fd, SOL_TCP, TCP_CORK, &v, sizeof(v));
 #else
     return 0;
 #endif
@@ -66,7 +66,7 @@ int socket_set_cork(int fd, int v)
 int socket_set_nodelay(int fd)
 {
     int v = 1;
-    return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
+    return qemu_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
 }
 
 int qemu_madvise(void *addr, size_t len, int advice)
commit 58427a0f42679c875b077b7adc5db36897973865
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Mar 4 18:11:47 2013 +0100

    lm32: remove unused function
    
    The milkymist-minimac device in fact does not exist at all.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Acked-by: Michael Walle <michael at walle.cc>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/milkymist-hw.h b/hw/milkymist-hw.h
index c8bd7e9..5def311 100644
--- a/hw/milkymist-hw.h
+++ b/hw/milkymist-hw.h
@@ -170,22 +170,6 @@ static inline DeviceState *milkymist_ac97_create(hwaddr base,
     return dev;
 }
 
-static inline DeviceState *milkymist_minimac_create(hwaddr 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(SYS_BUS_DEVICE(dev), 0, base);
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, rx_irq);
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, tx_irq);
-
-    return dev;
-}
-
 static inline DeviceState *milkymist_minimac2_create(hwaddr base,
         hwaddr buffers_base, qemu_irq rx_irq, qemu_irq tx_irq)
 {
commit eeb29fb9aa733f97d85857c210d6580a92a1b532
Author: Cole Robinson <crobinso at redhat.com>
Date:   Tue Feb 26 19:31:32 2013 -0500

    rtc-test: Fix test failures with recent glib
    
    As of glib 2.35.4, glib changed its logic for ordering test cases:
    
    https://bugzilla.gnome.org/show_bug.cgi?id=694487
    
    This was causing failures in rtc-test. Group the reordered test
    cases into their own suite, which maintains the original ordering.
    
    CC: qemu-stable at nongnu.org
    Signed-off-by: Cole Robinson <crobinso at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/tests/rtc-test.c b/tests/rtc-test.c
index c5fd042..9ab583b 100644
--- a/tests/rtc-test.c
+++ b/tests/rtc-test.c
@@ -565,8 +565,8 @@ int main(int argc, char **argv)
     qtest_add_func("/rtc/basic/bcd-12h", basic_12h_bcd);
     qtest_add_func("/rtc/set-year/20xx", set_year_20xx);
     qtest_add_func("/rtc/set-year/1980", set_year_1980);
-    qtest_add_func("/rtc/register_b_set_flag", register_b_set_flag);
-    qtest_add_func("/rtc/fuzz-registers", fuzz_registers);
+    qtest_add_func("/rtc/misc/register_b_set_flag", register_b_set_flag);
+    qtest_add_func("/rtc/misc/fuzz-registers", fuzz_registers);
     ret = g_test_run();
 
     if (s) {
commit 4652b792f01b559e005186b703ed9b1a11cbf8e3
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Feb 22 21:05:01 2013 +0100

    configure: Create link to icon bitmap for out-of-tree builds
    
    This allows to pick up the icon when starting QEMU directly from an
    out-of-tree build directory.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/configure b/configure
index 2f98c5a..87b2e73 100755
--- a/configure
+++ b/configure
@@ -4369,6 +4369,7 @@ FILES="$FILES tests/tcg/lm32/Makefile po/Makefile"
 FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
 FILES="$FILES pc-bios/spapr-rtas/Makefile"
 FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
+FILES="$FILES pc-bios/qemu-icon.bmp"
 for bios_file in \
     $source_path/pc-bios/*.bin \
     $source_path/pc-bios/*.aml \
commit 0bc472a9d6b80567c212023c5eae413f4dfb53ad
Author: Kuo-Jung Su <dantesu at gmail.com>
Date:   Tue Mar 5 21:27:24 2013 +0000

    hw/nand.c: correct the sense of the BUSY/READY status bit
    
    The BIT6 of Status Register(SR):
    
    SR[6] behaves the same as R/B# pin
        SR[6] = 0 indicates the device is busy;
        SR[6] = 1 means the device is ready
    
    Some NAND flash controller (i.e. ftnandc021) relies on the SR[6]
    to determine if the NAND flash erase/program is success or error timeout.
    
    P.S:
    The exmaple NAND flash datasheet could be found at following link:
    http://www.mxic.com.tw/QuickPlace/hq/PageLibrary4825740B00298A3B.nsf/h_Index/8FEA549237D2F7674825795800104C26/$File/MX30LF1G08AA,%203V,%201Gb,%20v1.1.pdf
    
    Signed-off-by: Kuo-Jung Su <dantesu at gmail.com>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/nand.c b/hw/nand.c
index 4a71265..61e918f 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -46,7 +46,7 @@
 # define NAND_IOSTATUS_PLANE1	(1 << 2)
 # define NAND_IOSTATUS_PLANE2	(1 << 3)
 # define NAND_IOSTATUS_PLANE3	(1 << 4)
-# define NAND_IOSTATUS_BUSY	(1 << 6)
+# define NAND_IOSTATUS_READY    (1 << 6)
 # define NAND_IOSTATUS_UNPROTCT	(1 << 7)
 
 # define MAX_PAGE		0x800
@@ -231,6 +231,7 @@ static void nand_reset(DeviceState *dev)
     s->iolen = 0;
     s->offset = 0;
     s->status &= NAND_IOSTATUS_UNPROTCT;
+    s->status |= NAND_IOSTATUS_READY;
 }
 
 static inline void nand_pushio_byte(NANDFlashState *s, uint8_t value)
commit 0c92e0e6b64c9061f7365a2712b9055ea35b52f9
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Feb 25 12:16:05 2013 +0100

    scsi-disk: handle io_canceled uniformly and correctly
    
    Always check it immediately after calling bdrv_acct_done, and
    always do a "goto done" in case the "done" label has to free
    some memory---as is the case for scsi_unmap_complete in the
    previous patch.
    
    This patch could fix problems that happen when a request is
    split into multiple parts, and one of them is canceled.  Then
    the next part is fired, but the HBA's cancellation callbacks have
    fired already.  Whether this happens or not, depends on how the
    block/ driver implements AIO cancellation.  It it does a simple
    bdrv_drain_all() or similar, then it will not have a problem.
    If it only cancels the given AIOCB, this scenario could happen.
    
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 6c0ddff..4a0673c 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -178,6 +178,9 @@ static void scsi_aio_complete(void *opaque, int ret)
     assert(r->req.aiocb != NULL);
     r->req.aiocb = NULL;
     bdrv_acct_done(s->qdev.conf.bs, &r->acct);
+    if (r->req.io_canceled) {
+        goto done;
+    }
 
     if (ret < 0) {
         if (scsi_handle_rw_error(r, -ret)) {
@@ -223,6 +226,10 @@ static void scsi_write_do_fua(SCSIDiskReq *r)
 {
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
 
+    if (r->req.io_canceled) {
+        goto done;
+    }
+
     if (scsi_is_cmd_fua(&r->req.cmd)) {
         bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
         r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_aio_complete, r);
@@ -230,6 +237,8 @@ static void scsi_write_do_fua(SCSIDiskReq *r)
     }
 
     scsi_req_complete(&r->req, GOOD);
+
+done:
     if (!r->req.io_canceled) {
         scsi_req_unref(&r->req);
     }
@@ -243,6 +252,9 @@ static void scsi_dma_complete(void *opaque, int ret)
     assert(r->req.aiocb != NULL);
     r->req.aiocb = NULL;
     bdrv_acct_done(s->qdev.conf.bs, &r->acct);
+    if (r->req.io_canceled) {
+        goto done;
+    }
 
     if (ret < 0) {
         if (scsi_handle_rw_error(r, -ret)) {
@@ -274,6 +286,9 @@ static void scsi_read_complete(void * opaque, int ret)
     assert(r->req.aiocb != NULL);
     r->req.aiocb = NULL;
     bdrv_acct_done(s->qdev.conf.bs, &r->acct);
+    if (r->req.io_canceled) {
+        goto done;
+    }
 
     if (ret < 0) {
         if (scsi_handle_rw_error(r, -ret)) {
@@ -305,6 +320,9 @@ static void scsi_do_read(void *opaque, int ret)
         r->req.aiocb = NULL;
         bdrv_acct_done(s->qdev.conf.bs, &r->acct);
     }
+    if (r->req.io_canceled) {
+        goto done;
+    }
 
     if (ret < 0) {
         if (scsi_handle_rw_error(r, -ret)) {
@@ -312,10 +330,6 @@ static void scsi_do_read(void *opaque, int ret)
         }
     }
 
-    if (r->req.io_canceled) {
-        return;
-    }
-
     /* The request is used as the AIO opaque value, so add a ref.  */
     scsi_req_ref(&r->req);
 
@@ -423,6 +437,9 @@ static void scsi_write_complete(void * opaque, int ret)
         r->req.aiocb = NULL;
         bdrv_acct_done(s->qdev.conf.bs, &r->acct);
     }
+    if (r->req.io_canceled) {
+        goto done;
+    }
 
     if (ret < 0) {
         if (scsi_handle_rw_error(r, -ret)) {
commit d0242eadc5bba4f3abe34bc5d536bbfb81aa9891
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Feb 25 12:14:34 2013 +0100

    scsi-disk: do not complete canceled UNMAP requests
    
    Canceled requests should never be completed, and doing that could cause
    accesses to a NULL hba_private field.
    
    Cc: qemu-stable at nongnu.org
    Reported-by: Stefan Priebe <s.priebe at profihost.ag>
    Tested-by: Stefan Priebe <s.priebe at profihost.ag>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index d411586..6c0ddff 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1478,13 +1478,17 @@ static void scsi_unmap_complete(void *opaque, int ret)
     uint32_t nb_sectors;
 
     r->req.aiocb = NULL;
+    if (r->req.io_canceled) {
+        goto done;
+    }
+
     if (ret < 0) {
         if (scsi_handle_rw_error(r, -ret)) {
             goto done;
         }
     }
 
-    if (data->count > 0 && !r->req.io_canceled) {
+    if (data->count > 0) {
         sector_num = ldq_be_p(&data->inbuf[0]);
         nb_sectors = ldl_be_p(&data->inbuf[8]) & 0xffffffffULL;
         if (!check_lba_range(s, sector_num, nb_sectors)) {
@@ -1501,10 +1505,9 @@ static void scsi_unmap_complete(void *opaque, int ret)
         return;
     }
 
+    scsi_req_complete(&r->req, GOOD);
+
 done:
-    if (data->count == 0) {
-        scsi_req_complete(&r->req, GOOD);
-    }
     if (!r->req.io_canceled) {
         scsi_req_unref(&r->req);
     }
commit 6f6710aa99ac53b59ff0f14380830cb9ab6bdc14
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Feb 25 12:12:58 2013 +0100

    scsi: do not call scsi_read_data/scsi_write_data for a canceled request
    
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index a97f1cd..01e1dec 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -1508,6 +1508,10 @@ void scsi_req_unref(SCSIRequest *req)
    will start the next chunk or complete the command.  */
 void scsi_req_continue(SCSIRequest *req)
 {
+    if (req->io_canceled) {
+        trace_scsi_req_continue_canceled(req->dev->id, req->lun, req->tag);
+        return;
+    }
     trace_scsi_req_continue(req->dev->id, req->lun, req->tag);
     if (req->cmd.mode == SCSI_XFER_TO_DEV) {
         req->ops->write_data(req);
diff --git a/trace-events b/trace-events
index a27ae43..3064fc7 100644
--- a/trace-events
+++ b/trace-events
@@ -460,6 +460,7 @@ scsi_req_data(int target, int lun, int tag, int len) "target %d lun %d tag %d le
 scsi_req_data_canceled(int target, int lun, int tag, int len) "target %d lun %d tag %d len %d"
 scsi_req_dequeue(int target, int lun, int tag) "target %d lun %d tag %d"
 scsi_req_continue(int target, int lun, int tag) "target %d lun %d tag %d"
+scsi_req_continue_canceled(int target, int lun, int tag) "target %d lun %d tag %d"
 scsi_req_parsed(int target, int lun, int tag, int cmd, int mode, int xfer) "target %d lun %d tag %d command %d dir %d length %d"
 scsi_req_parsed_lba(int target, int lun, int tag, int cmd, uint64_t lba) "target %d lun %d tag %d command %d lba %"PRIu64
 scsi_req_parse_bad(int target, int lun, int tag, int cmd) "target %d lun %d tag %d command %d"
commit 3c33ea9640758bb625e110a77673e5abfd184e54
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 18:14:28 2013 +0100

    iscsi: look for pkg-config file too
    
    Due to library conflicts, Fedora will have to put libiscsi in
    /usr/lib/iscsi.  Simplify configuration by using a pkg-config
    file.  The Fedora package will distribute one, and the patch
    to add it has been sent to upstream libiscsi as well.
    
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/configure b/configure
index 2f98c5a..a9a7c99 100755
--- a/configure
+++ b/configure
@@ -2803,7 +2803,13 @@ if test "$libiscsi" != "no" ; then
 #include <iscsi/iscsi.h>
 int main(void) { iscsi_unmap_sync(NULL,0,0,0,NULL,0); return 0; }
 EOF
-  if compile_prog "" "-liscsi" ; then
+  if $pkg_config --atleast-version=1.7.0 libiscsi --modversion >/dev/null 2>&1; then
+    libiscsi="yes"
+    libiscsi_cflags=$($pkg_config --cflags libiscsi 2>/dev/null)
+    libiscsi_libs=$($pkg_config --libs libiscsi 2>/dev/null)
+    CFLAGS="$CFLAGS $libiscsi_cflags"
+    LIBS="$LIBS $libiscsi_libs"
+  elif compile_prog "" "-liscsi" ; then
     libiscsi="yes"
     LIBS="$LIBS -liscsi"
   else
commit cb1b83e740384b4e0d950f3d7c81c02b8ce86c2e
Author: Peter Lieven <pl at dlhnet.de>
Date:   Mon Feb 18 14:50:46 2013 +0100

    iscsi: add iscsi_truncate support
    
    this patch adds iscsi_truncate which effectively allows for
    online resizing of iscsi volumes. for this to work you have
    to resize the volume on your storage and then call
    block_resize command in qemu which will issue a
    readcapacity16 to update the capacity.
    
    v4:
      - factor out complete readcapacity logic into a separate function
      - handle capacity change check condition in readcapacity function
        (this happens if the block_resize cmd is the first iscsi task
        executed after a resize on the storage)
    
    v3:
      - remove switch statement in iscsi_open
      - create separate patch for brdv_drain_all() in bdrv_truncate()
    
    v2:
      - add a general bdrv_drain_all() before bdrv_truncate() to avoid
        in-flight AIOs while the device is truncated
      - since no AIOs are in flight we can use a sync libiscsi call
        to re-read the capacity
      - factor out the readcapacity16 logic as it is redundant
        to iscsi_open() and iscsi_truncate().
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    [allow any type of unit attention check condition in iscsi_readcapacity_sync(),
     as in Message-ID: <51263A2A.6070304 at dlhnet.de> - Paolo]
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/iscsi.c b/block/iscsi.c
index 439af6f..3d52921 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -938,6 +938,71 @@ static void iscsi_nop_timed_event(void *opaque)
 }
 #endif
 
+static int iscsi_readcapacity_sync(IscsiLun *iscsilun)
+{
+    struct scsi_task *task = NULL;
+    struct scsi_readcapacity10 *rc10 = NULL;
+    struct scsi_readcapacity16 *rc16 = NULL;
+    int ret = 0;
+    int retries = ISCSI_CMD_RETRIES; 
+
+try_again:
+    switch (iscsilun->type) {
+    case TYPE_DISK:
+        task = iscsi_readcapacity16_sync(iscsilun->iscsi, iscsilun->lun);
+        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
+            if (task != NULL && task->status == SCSI_STATUS_CHECK_CONDITION
+                    && task->sense.key == SCSI_SENSE_UNIT_ATTENTION
+                    && retries-- > 0) {
+                scsi_free_scsi_task(task);
+                goto try_again;
+            }
+            error_report("iSCSI: failed to send readcapacity16 command.");
+            ret = -EINVAL;
+            goto out;
+        }
+        rc16 = scsi_datain_unmarshall(task);
+        if (rc16 == NULL) {
+            error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
+            ret = -EINVAL;
+            goto out;
+        }
+        iscsilun->block_size = rc16->block_length;
+        iscsilun->num_blocks = rc16->returned_lba + 1;
+        break;
+    case TYPE_ROM:
+        task = iscsi_readcapacity10_sync(iscsilun->iscsi, iscsilun->lun, 0, 0);
+        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
+            error_report("iSCSI: failed to send readcapacity10 command.");
+            ret = -EINVAL;
+            goto out;
+        }
+        rc10 = scsi_datain_unmarshall(task);
+        if (rc10 == NULL) {
+            error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
+            ret = -EINVAL;
+            goto out;
+        }
+        iscsilun->block_size = rc10->block_size;
+        if (rc10->lba == 0) {
+            /* blank disk loaded */
+            iscsilun->num_blocks = 0;
+        } else {
+            iscsilun->num_blocks = rc10->lba + 1;
+        }
+        break;
+    default:
+        break;
+    }
+
+out:
+    if (task) {
+        scsi_free_scsi_task(task);
+    }
+
+    return ret;
+}
+
 /*
  * We support iscsi url's on the form
  * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
@@ -949,8 +1014,6 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
     struct iscsi_url *iscsi_url = NULL;
     struct scsi_task *task = NULL;
     struct scsi_inquiry_standard *inq = NULL;
-    struct scsi_readcapacity10 *rc10 = NULL;
-    struct scsi_readcapacity16 *rc16 = NULL;
     char *initiator_name = NULL;
     int ret;
 
@@ -1040,50 +1103,9 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
 
     iscsilun->type = inq->periperal_device_type;
 
-    scsi_free_scsi_task(task);
-
-    switch (iscsilun->type) {
-    case TYPE_DISK:
-        task = iscsi_readcapacity16_sync(iscsi, iscsilun->lun);
-        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
-            error_report("iSCSI: failed to send readcapacity16 command.");
-            ret = -EINVAL;
-            goto out;
-        }
-        rc16 = scsi_datain_unmarshall(task);
-        if (rc16 == NULL) {
-            error_report("iSCSI: Failed to unmarshall readcapacity16 data.");
-            ret = -EINVAL;
-            goto out;
-        }
-        iscsilun->block_size = rc16->block_length;
-        iscsilun->num_blocks = rc16->returned_lba + 1;
-        break;
-    case TYPE_ROM:
-        task = iscsi_readcapacity10_sync(iscsi, iscsilun->lun, 0, 0);
-        if (task == NULL || task->status != SCSI_STATUS_GOOD) {
-            error_report("iSCSI: failed to send readcapacity10 command.");
-            ret = -EINVAL;
-            goto out;
-        }
-        rc10 = scsi_datain_unmarshall(task);
-        if (rc10 == NULL) {
-            error_report("iSCSI: Failed to unmarshall readcapacity10 data.");
-            ret = -EINVAL;
-            goto out;
-        }
-        iscsilun->block_size = rc10->block_size;
-        if (rc10->lba == 0) {
-            /* blank disk loaded */
-            iscsilun->num_blocks = 0;
-        } else {
-            iscsilun->num_blocks = rc10->lba + 1;
-        }
-        break;
-    default:
-        break;
+    if ((ret = iscsi_readcapacity_sync(iscsilun)) != 0) {
+        goto out;
     }
-
     bs->total_sectors    = iscsilun->num_blocks *
                            iscsilun->block_size / BDRV_SECTOR_SIZE ;
 
@@ -1096,8 +1118,6 @@ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags)
         bs->sg = 1;
     }
 
-    ret = 0;
-
 #if defined(LIBISCSI_FEATURE_NOP_COUNTER)
     /* Set up a timer for sending out iSCSI NOPs */
     iscsilun->nop_timer = qemu_new_timer_ms(rt_clock, iscsi_nop_timed_event, iscsilun);
@@ -1138,6 +1158,26 @@ static void iscsi_close(BlockDriverState *bs)
     memset(iscsilun, 0, sizeof(IscsiLun));
 }
 
+static int iscsi_truncate(BlockDriverState *bs, int64_t offset)
+{
+    IscsiLun *iscsilun = bs->opaque;
+    int ret = 0;
+
+    if (iscsilun->type != TYPE_DISK) {
+        return -ENOTSUP;
+    }
+
+    if ((ret = iscsi_readcapacity_sync(iscsilun)) != 0) {
+        return ret;
+    }
+
+    if (offset > iscsi_getlength(bs)) {
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
 static int iscsi_has_zero_init(BlockDriverState *bs)
 {
     return 0;
@@ -1208,6 +1248,7 @@ static BlockDriver bdrv_iscsi = {
     .create_options  = iscsi_create_options,
 
     .bdrv_getlength  = iscsi_getlength,
+    .bdrv_truncate   = iscsi_truncate,
 
     .bdrv_aio_readv  = iscsi_aio_readv,
     .bdrv_aio_writev = iscsi_aio_writev,
commit 1dde716ed6719c341c1bfa427781f0715af90cbc
Author: Peter Lieven <pl at dlhnet.de>
Date:   Thu Feb 21 16:15:54 2013 +0100

    iscsi: retry read, write, flush and unmap on unit attention check conditions
    
    the storage might return a check condition status for various reasons.
    (e.g. bus reset, capacity change, thin-provisioning info etc.)
    
    currently all these informative status responses lead to an I/O error
    which is populated to the guest. this patch introduces a retry mechanism
    to avoid this.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/block/iscsi.c b/block/iscsi.c
index deb3b68..439af6f 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -60,8 +60,11 @@ typedef struct IscsiAIOCB {
     uint8_t *buf;
     int status;
     int canceled;
+    int retries;
     size_t read_size;
     size_t read_offset;
+    int64_t sector_num;
+    int nb_sectors;
 #ifdef __linux__
     sg_io_hdr_t *ioh;
 #endif
@@ -69,6 +72,7 @@ typedef struct IscsiAIOCB {
 
 #define NOP_INTERVAL 5000
 #define MAX_NOP_FAILURES 3
+#define ISCSI_CMD_RETRIES 5
 
 static void
 iscsi_bh_cb(void *p)
@@ -191,6 +195,8 @@ iscsi_process_write(void *arg)
     iscsi_set_events(iscsilun);
 }
 
+static int
+iscsi_aio_writev_acb(IscsiAIOCB *acb);
 
 static void
 iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
@@ -208,7 +214,19 @@ iscsi_aio_write16_cb(struct iscsi_context *iscsi, int status,
     }
 
     acb->status = 0;
-    if (status < 0) {
+    if (status != 0) {
+        if (status == SCSI_STATUS_CHECK_CONDITION
+            && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
+            && acb->retries-- > 0) {
+            if (acb->task != NULL) {
+                scsi_free_scsi_task(acb->task);
+                acb->task = NULL;
+            }
+            if (iscsi_aio_writev_acb(acb) == 0) {
+                iscsi_set_events(acb->iscsilun);
+                return;
+            }
+        }
         error_report("Failed to write16 data to iSCSI lun. %s",
                      iscsi_get_error(iscsi));
         acb->status = -EIO;
@@ -222,15 +240,10 @@ static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun)
     return sector * BDRV_SECTOR_SIZE / iscsilun->block_size;
 }
 
-static BlockDriverAIOCB *
-iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
-                 QEMUIOVector *qiov, int nb_sectors,
-                 BlockDriverCompletionFunc *cb,
-                 void *opaque)
+static int
+iscsi_aio_writev_acb(IscsiAIOCB *acb)
 {
-    IscsiLun *iscsilun = bs->opaque;
-    struct iscsi_context *iscsi = iscsilun->iscsi;
-    IscsiAIOCB *acb;
+    struct iscsi_context *iscsi = acb->iscsilun->iscsi;
     size_t size;
     uint32_t num_sectors;
     uint64_t lba;
@@ -239,19 +252,13 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
 #endif
     int ret;
 
-    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
-    trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb);
-
-    acb->iscsilun = iscsilun;
-    acb->qiov     = qiov;
-
     acb->canceled   = 0;
     acb->bh         = NULL;
     acb->status     = -EINPROGRESS;
     acb->buf        = NULL;
 
     /* this will allow us to get rid of 'buf' completely */
-    size = nb_sectors * BDRV_SECTOR_SIZE;
+    size = acb->nb_sectors * BDRV_SECTOR_SIZE;
 
 #if !defined(LIBISCSI_FEATURE_IOVECTOR)
     data.size = MIN(size, acb->qiov->size);
@@ -270,48 +277,76 @@ iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
     if (acb->task == NULL) {
         error_report("iSCSI: Failed to allocate task for scsi WRITE16 "
                      "command. %s", iscsi_get_error(iscsi));
-        qemu_aio_release(acb);
-        return NULL;
+        return -1;
     }
     memset(acb->task, 0, sizeof(struct scsi_task));
 
     acb->task->xfer_dir = SCSI_XFER_WRITE;
     acb->task->cdb_size = 16;
     acb->task->cdb[0] = 0x8a;
-    lba = sector_qemu2lun(sector_num, iscsilun);
+    lba = sector_qemu2lun(acb->sector_num, acb->iscsilun);
     *(uint32_t *)&acb->task->cdb[2]  = htonl(lba >> 32);
     *(uint32_t *)&acb->task->cdb[6]  = htonl(lba & 0xffffffff);
-    num_sectors = size / iscsilun->block_size;
+    num_sectors = size / acb->iscsilun->block_size;
     *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);
     acb->task->expxferlen = size;
 
 #if defined(LIBISCSI_FEATURE_IOVECTOR)
-    ret = iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
+    ret = iscsi_scsi_command_async(iscsi, acb->iscsilun->lun, acb->task,
                                    iscsi_aio_write16_cb,
                                    NULL,
                                    acb);
 #else
-    ret = iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
+    ret = iscsi_scsi_command_async(iscsi, acb->iscsilun->lun, acb->task,
                                    iscsi_aio_write16_cb,
                                    &data,
                                    acb);
 #endif
     if (ret != 0) {
-        scsi_free_scsi_task(acb->task);
         g_free(acb->buf);
-        qemu_aio_release(acb);
-        return NULL;
+        return -1;
     }
 
 #if defined(LIBISCSI_FEATURE_IOVECTOR)
     scsi_task_set_iov_out(acb->task, (struct scsi_iovec*) acb->qiov->iov, acb->qiov->niov);
 #endif
 
-    iscsi_set_events(iscsilun);
+    return 0;
+}
+
+static BlockDriverAIOCB *
+iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,
+                 QEMUIOVector *qiov, int nb_sectors,
+                 BlockDriverCompletionFunc *cb,
+                 void *opaque)
+{
+    IscsiLun *iscsilun = bs->opaque;
+    IscsiAIOCB *acb;
+
+    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
+    trace_iscsi_aio_writev(iscsilun->iscsi, sector_num, nb_sectors, opaque, acb);
+
+    acb->iscsilun    = iscsilun;
+    acb->qiov        = qiov;
+    acb->nb_sectors  = nb_sectors;
+    acb->sector_num  = sector_num;
+    acb->retries     = ISCSI_CMD_RETRIES;
+
+    if (iscsi_aio_writev_acb(acb) != 0) {
+        if (acb->task) {
+            scsi_free_scsi_task(acb->task);
+        }
+        qemu_aio_release(acb);
+        return NULL;
+    }
 
+    iscsi_set_events(iscsilun);
     return &acb->common;
 }
 
+static int
+iscsi_aio_readv_acb(IscsiAIOCB *acb);
+
 static void
 iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
                     void *command_data, void *opaque)
@@ -326,6 +361,18 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
 
     acb->status = 0;
     if (status != 0) {
+        if (status == SCSI_STATUS_CHECK_CONDITION
+            && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
+            && acb->retries-- > 0) {
+            if (acb->task != NULL) {
+                scsi_free_scsi_task(acb->task);
+                acb->task = NULL;
+            }
+            if (iscsi_aio_readv_acb(acb) == 0) {
+                iscsi_set_events(acb->iscsilun);
+                return;
+            }
+        }
         error_report("Failed to read16 data from iSCSI lun. %s",
                      iscsi_get_error(iscsi));
         acb->status = -EIO;
@@ -334,35 +381,20 @@ iscsi_aio_read16_cb(struct iscsi_context *iscsi, int status,
     iscsi_schedule_bh(acb);
 }
 
-static BlockDriverAIOCB *
-iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
-                QEMUIOVector *qiov, int nb_sectors,
-                BlockDriverCompletionFunc *cb,
-                void *opaque)
+static int
+iscsi_aio_readv_acb(IscsiAIOCB *acb)
 {
-    IscsiLun *iscsilun = bs->opaque;
-    struct iscsi_context *iscsi = iscsilun->iscsi;
-    IscsiAIOCB *acb;
-    size_t qemu_read_size;
+    struct iscsi_context *iscsi = acb->iscsilun->iscsi;
+    uint64_t lba;
+    uint32_t num_sectors;
+    int ret;
 #if !defined(LIBISCSI_FEATURE_IOVECTOR)
     int i;
 #endif
-    int ret;
-    uint64_t lba;
-    uint32_t num_sectors;
-
-    qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors;
-
-    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
-    trace_iscsi_aio_readv(iscsi, sector_num, nb_sectors, opaque, acb);
-
-    acb->iscsilun = iscsilun;
-    acb->qiov     = qiov;
 
     acb->canceled    = 0;
     acb->bh          = NULL;
     acb->status      = -EINPROGRESS;
-    acb->read_size   = qemu_read_size;
     acb->buf         = NULL;
 
     /* If LUN blocksize is bigger than BDRV_BLOCK_SIZE a read from QEMU
@@ -370,30 +402,29 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
      * data.
      */
     acb->read_offset = 0;
-    if (iscsilun->block_size > BDRV_SECTOR_SIZE) {
-        uint64_t bdrv_offset = BDRV_SECTOR_SIZE * sector_num;
+    if (acb->iscsilun->block_size > BDRV_SECTOR_SIZE) {
+        uint64_t bdrv_offset = BDRV_SECTOR_SIZE * acb->sector_num;
 
-        acb->read_offset  = bdrv_offset % iscsilun->block_size;
+        acb->read_offset  = bdrv_offset % acb->iscsilun->block_size;
     }
 
-    num_sectors  = (qemu_read_size + iscsilun->block_size
+    num_sectors  = (acb->read_size + acb->iscsilun->block_size
                     + acb->read_offset - 1)
-                    / iscsilun->block_size;
+                    / acb->iscsilun->block_size;
 
     acb->task = malloc(sizeof(struct scsi_task));
     if (acb->task == NULL) {
         error_report("iSCSI: Failed to allocate task for scsi READ16 "
                      "command. %s", iscsi_get_error(iscsi));
-        qemu_aio_release(acb);
-        return NULL;
+        return -1;
     }
     memset(acb->task, 0, sizeof(struct scsi_task));
 
     acb->task->xfer_dir = SCSI_XFER_READ;
-    lba = sector_qemu2lun(sector_num, iscsilun);
-    acb->task->expxferlen = qemu_read_size;
+    lba = sector_qemu2lun(acb->sector_num, acb->iscsilun);
+    acb->task->expxferlen = acb->read_size;
 
-    switch (iscsilun->type) {
+    switch (acb->iscsilun->type) {
     case TYPE_DISK:
         acb->task->cdb_size = 16;
         acb->task->cdb[0]  = 0x88;
@@ -409,14 +440,12 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
         break;
     }
 
-    ret = iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,
+    ret = iscsi_scsi_command_async(iscsi, acb->iscsilun->lun, acb->task,
                                    iscsi_aio_read16_cb,
                                    NULL,
                                    acb);
     if (ret != 0) {
-        scsi_free_scsi_task(acb->task);
-        qemu_aio_release(acb);
-        return NULL;
+        return -1;
     }
 
 #if defined(LIBISCSI_FEATURE_IOVECTOR)
@@ -428,12 +457,42 @@ iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
                 acb->qiov->iov[i].iov_base);
     }
 #endif
+    return 0;
+}
 
-    iscsi_set_events(iscsilun);
+static BlockDriverAIOCB *
+iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num,
+                QEMUIOVector *qiov, int nb_sectors,
+                BlockDriverCompletionFunc *cb,
+                void *opaque)
+{
+    IscsiLun *iscsilun = bs->opaque;
+    IscsiAIOCB *acb;
 
+    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
+    trace_iscsi_aio_readv(iscsilun->iscsi, sector_num, nb_sectors, opaque, acb);
+
+    acb->nb_sectors  = nb_sectors;
+    acb->sector_num  = sector_num;
+    acb->iscsilun    = iscsilun;
+    acb->qiov        = qiov;
+    acb->read_size   = BDRV_SECTOR_SIZE * (size_t)acb->nb_sectors;
+    acb->retries     = ISCSI_CMD_RETRIES;
+
+    if (iscsi_aio_readv_acb(acb) != 0) {
+        if (acb->task) {
+            scsi_free_scsi_task(acb->task);
+        }
+        qemu_aio_release(acb);
+        return NULL;
+    }
+
+    iscsi_set_events(iscsilun);
     return &acb->common;
 }
 
+static int
+iscsi_aio_flush_acb(IscsiAIOCB *acb);
 
 static void
 iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
@@ -446,7 +505,19 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
     }
 
     acb->status = 0;
-    if (status < 0) {
+    if (status != 0) {
+        if (status == SCSI_STATUS_CHECK_CONDITION
+            && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
+            && acb->retries-- > 0) {
+            if (acb->task != NULL) {
+                scsi_free_scsi_task(acb->task);
+                acb->task = NULL;
+            }
+            if (iscsi_aio_flush_acb(acb) == 0) {
+                iscsi_set_events(acb->iscsilun);
+                return;
+            }
+        }
         error_report("Failed to sync10 data on iSCSI lun. %s",
                      iscsi_get_error(iscsi));
         acb->status = -EIO;
@@ -455,29 +526,43 @@ iscsi_synccache10_cb(struct iscsi_context *iscsi, int status,
     iscsi_schedule_bh(acb);
 }
 
-static BlockDriverAIOCB *
-iscsi_aio_flush(BlockDriverState *bs,
-                BlockDriverCompletionFunc *cb, void *opaque)
+static int
+iscsi_aio_flush_acb(IscsiAIOCB *acb)
 {
-    IscsiLun *iscsilun = bs->opaque;
-    struct iscsi_context *iscsi = iscsilun->iscsi;
-    IscsiAIOCB *acb;
-
-    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
+    struct iscsi_context *iscsi = acb->iscsilun->iscsi;
 
-    acb->iscsilun = iscsilun;
     acb->canceled   = 0;
     acb->bh         = NULL;
     acb->status     = -EINPROGRESS;
     acb->buf        = NULL;
 
-    acb->task = iscsi_synchronizecache10_task(iscsi, iscsilun->lun,
+    acb->task = iscsi_synchronizecache10_task(iscsi, acb->iscsilun->lun,
                                          0, 0, 0, 0,
                                          iscsi_synccache10_cb,
                                          acb);
     if (acb->task == NULL) {
         error_report("iSCSI: Failed to send synchronizecache10 command. %s",
                      iscsi_get_error(iscsi));
+        return -1;
+    }
+
+    return 0;
+}
+
+static BlockDriverAIOCB *
+iscsi_aio_flush(BlockDriverState *bs,
+                BlockDriverCompletionFunc *cb, void *opaque)
+{
+    IscsiLun *iscsilun = bs->opaque;
+
+    IscsiAIOCB *acb;
+
+    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
+
+    acb->iscsilun    = iscsilun;
+    acb->retries     = ISCSI_CMD_RETRIES;
+
+    if (iscsi_aio_flush_acb(acb) != 0) {
         qemu_aio_release(acb);
         return NULL;
     }
@@ -487,6 +572,8 @@ iscsi_aio_flush(BlockDriverState *bs,
     return &acb->common;
 }
 
+static int iscsi_aio_discard_acb(IscsiAIOCB *acb);
+
 static void
 iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
                      void *command_data, void *opaque)
@@ -498,7 +585,19 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
     }
 
     acb->status = 0;
-    if (status < 0) {
+    if (status != 0) {
+        if (status == SCSI_STATUS_CHECK_CONDITION
+            && acb->task->sense.key == SCSI_SENSE_UNIT_ATTENTION
+            && acb->retries-- > 0) {
+            if (acb->task != NULL) {
+                scsi_free_scsi_task(acb->task);
+                acb->task = NULL;
+            }
+            if (iscsi_aio_discard_acb(acb) == 0) {
+                iscsi_set_events(acb->iscsilun);
+                return;
+            }
+        }
         error_report("Failed to unmap data on iSCSI lun. %s",
                      iscsi_get_error(iscsi));
         acb->status = -EIO;
@@ -507,34 +606,50 @@ iscsi_unmap_cb(struct iscsi_context *iscsi, int status,
     iscsi_schedule_bh(acb);
 }
 
-static BlockDriverAIOCB *
-iscsi_aio_discard(BlockDriverState *bs,
-                  int64_t sector_num, int nb_sectors,
-                  BlockDriverCompletionFunc *cb, void *opaque)
-{
-    IscsiLun *iscsilun = bs->opaque;
-    struct iscsi_context *iscsi = iscsilun->iscsi;
-    IscsiAIOCB *acb;
+static int iscsi_aio_discard_acb(IscsiAIOCB *acb) {
+    struct iscsi_context *iscsi = acb->iscsilun->iscsi;
     struct unmap_list list[1];
 
-    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
-
-    acb->iscsilun = iscsilun;
     acb->canceled   = 0;
     acb->bh         = NULL;
     acb->status     = -EINPROGRESS;
     acb->buf        = NULL;
 
-    list[0].lba = sector_qemu2lun(sector_num, iscsilun);
-    list[0].num = nb_sectors * BDRV_SECTOR_SIZE / iscsilun->block_size;
+    list[0].lba = sector_qemu2lun(acb->sector_num, acb->iscsilun);
+    list[0].num = acb->nb_sectors * BDRV_SECTOR_SIZE / acb->iscsilun->block_size;
 
-    acb->task = iscsi_unmap_task(iscsi, iscsilun->lun,
+    acb->task = iscsi_unmap_task(iscsi, acb->iscsilun->lun,
                                  0, 0, &list[0], 1,
                                  iscsi_unmap_cb,
                                  acb);
     if (acb->task == NULL) {
         error_report("iSCSI: Failed to send unmap command. %s",
                      iscsi_get_error(iscsi));
+        return -1;
+    }
+
+    return 0;
+}
+
+static BlockDriverAIOCB *
+iscsi_aio_discard(BlockDriverState *bs,
+                  int64_t sector_num, int nb_sectors,
+                  BlockDriverCompletionFunc *cb, void *opaque)
+{
+    IscsiLun *iscsilun = bs->opaque;
+    IscsiAIOCB *acb;
+
+    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);
+
+    acb->iscsilun    = iscsilun;
+    acb->nb_sectors  = nb_sectors;
+    acb->sector_num  = sector_num;
+    acb->retries     = ISCSI_CMD_RETRIES;
+
+    if (iscsi_aio_discard_acb(acb) != 0) {
+        if (acb->task) {
+            scsi_free_scsi_task(acb->task);
+        }
         qemu_aio_release(acb);
         return NULL;
     }
commit 76c48503c4c87afabf0c93acf78480f65276844d
Merge: 597e2ce ed4659d
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 5 15:11:30 2013 +0100

    Merge branch 'target-arm.next' of git://git.linaro.org/people/pmaydell/qemu-arm
    
    * 'target-arm.next' of git://git.linaro.org/people/pmaydell/qemu-arm:
      MAINTAINERS: add entry for ARM KVM guest cores
      configure: Enable KVM on ARM
      hw/kvm/arm_gic: Implement support for KVM in-kernel ARM GIC
      target-arm: Use MemoryListener to identify GIC base address for KVM
      hw/arm_gic: Convert ARM GIC classes to use init/realize
      hw/arm_gic: Add presave/postload hooks
      ARM KVM: save and load VFP registers from kernel
      ARM: KVM: Add support for KVM on ARM architecture
      target-arm: Drop CPUARMState* argument from bank_number()
      linux-headers: resync from mainline to add ARM KVM headers
      oslib-posix: Align to permit transparent hugepages on ARM Linux
      target-arm: Don't decode RFE or SRS on M profile cores
      target-arm: Factor out handling of SRS instruction

commit 597e2cec8096e0703506abcbbf66938b5ac04368
Author: Richard Henderson <rth at twiddle.net>
Date:   Sun Feb 10 10:30:50 2013 -0800

    mipsn32-linux-user: Configure the architecture properly
    
    N32 is a 64-bit cpu with a 32-bit address space.  We have
    existing cpp defines for this situation, but weren't using them.
    
    This does mean that the linux-user/mipsn32 directory must be
    merged with the linux-user/mips64 directory, and differences
    must be resolved via ifdefs.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 08dcc26..3e1d781 100755
--- a/configure
+++ b/configure
@@ -4012,9 +4012,10 @@ case "$target_arch2" in
     target_nptl="yes"
   ;;
   mipsn32|mipsn32el)
-    TARGET_ARCH=mipsn32
+    TARGET_ARCH=mips64
     TARGET_BASE_ARCH=mips
     echo "TARGET_ABI_MIPSN32=y" >> $config_target_mak
+    echo "TARGET_ABI32=y" >> $config_target_mak
   ;;
   mips64|mips64el)
     TARGET_ARCH=mips64
diff --git a/linux-user/mips64/syscall.h b/linux-user/mips64/syscall.h
index e436ea5..cd707df 100644
--- a/linux-user/mips64/syscall.h
+++ b/linux-user/mips64/syscall.h
@@ -3,16 +3,16 @@
    stack during a system call. */
 
 struct target_pt_regs {
-	/* Saved main processor registers. */
-	abi_ulong regs[32];
+        /* Saved main processor registers. */
+        target_ulong regs[32];
 
-	/* Saved special registers. */
-	abi_ulong cp0_status;
-	abi_ulong lo;
-	abi_ulong hi;
-	abi_ulong cp0_badvaddr;
-	abi_ulong cp0_cause;
-	abi_ulong cp0_epc;
+        /* Saved special registers. */
+        target_ulong cp0_status;
+        target_ulong lo;
+        target_ulong hi;
+        target_ulong cp0_badvaddr;
+        target_ulong cp0_cause;
+        target_ulong cp0_epc;
 };
 
 /* Target errno definitions taken from asm-mips/errno.h */
diff --git a/linux-user/mips64/syscall_nr.h b/linux-user/mips64/syscall_nr.h
index 36d27b5..0f4a6b1 100644
--- a/linux-user/mips64/syscall_nr.h
+++ b/linux-user/mips64/syscall_nr.h
@@ -1,306 +1,620 @@
+#ifdef TARGET_ABI32
+/*
+ * Linux N32 syscalls are in the range from 6000 to 6999.
+ */
+#define TARGET_NR_Linux                 6000
+#define TARGET_NR_read                  (TARGET_NR_Linux +   0)
+#define TARGET_NR_write                 (TARGET_NR_Linux +   1)
+#define TARGET_NR_open                  (TARGET_NR_Linux +   2)
+#define TARGET_NR_close                 (TARGET_NR_Linux +   3)
+#define TARGET_NR_stat                  (TARGET_NR_Linux +   4)
+#define TARGET_NR_fstat                 (TARGET_NR_Linux +   5)
+#define TARGET_NR_lstat                 (TARGET_NR_Linux +   6)
+#define TARGET_NR_poll                  (TARGET_NR_Linux +   7)
+#define TARGET_NR_lseek                 (TARGET_NR_Linux +   8)
+#define TARGET_NR_mmap                  (TARGET_NR_Linux +   9)
+#define TARGET_NR_mprotect              (TARGET_NR_Linux +  10)
+#define TARGET_NR_munmap                (TARGET_NR_Linux +  11)
+#define TARGET_NR_brk                   (TARGET_NR_Linux +  12)
+#define TARGET_NR_rt_sigaction          (TARGET_NR_Linux +  13)
+#define TARGET_NR_rt_sigprocmask        (TARGET_NR_Linux +  14)
+#define TARGET_NR_ioctl                 (TARGET_NR_Linux +  15)
+#define TARGET_NR_pread64               (TARGET_NR_Linux +  16)
+#define TARGET_NR_pwrite64              (TARGET_NR_Linux +  17)
+#define TARGET_NR_readv                 (TARGET_NR_Linux +  18)
+#define TARGET_NR_writev                (TARGET_NR_Linux +  19)
+#define TARGET_NR_access                (TARGET_NR_Linux +  20)
+#define TARGET_NR_pipe                  (TARGET_NR_Linux +  21)
+#define TARGET_NR__newselect            (TARGET_NR_Linux +  22)
+#define TARGET_NR_sched_yield           (TARGET_NR_Linux +  23)
+#define TARGET_NR_mremap                (TARGET_NR_Linux +  24)
+#define TARGET_NR_msync                 (TARGET_NR_Linux +  25)
+#define TARGET_NR_mincore               (TARGET_NR_Linux +  26)
+#define TARGET_NR_madvise               (TARGET_NR_Linux +  27)
+#define TARGET_NR_shmget                (TARGET_NR_Linux +  28)
+#define TARGET_NR_shmat                 (TARGET_NR_Linux +  29)
+#define TARGET_NR_shmctl                (TARGET_NR_Linux +  30)
+#define TARGET_NR_dup                   (TARGET_NR_Linux +  31)
+#define TARGET_NR_dup2                  (TARGET_NR_Linux +  32)
+#define TARGET_NR_pause                 (TARGET_NR_Linux +  33)
+#define TARGET_NR_nanosleep             (TARGET_NR_Linux +  34)
+#define TARGET_NR_getitimer             (TARGET_NR_Linux +  35)
+#define TARGET_NR_setitimer             (TARGET_NR_Linux +  36)
+#define TARGET_NR_alarm                 (TARGET_NR_Linux +  37)
+#define TARGET_NR_getpid                (TARGET_NR_Linux +  38)
+#define TARGET_NR_sendfile              (TARGET_NR_Linux +  39)
+#define TARGET_NR_socket                (TARGET_NR_Linux +  40)
+#define TARGET_NR_connect               (TARGET_NR_Linux +  41)
+#define TARGET_NR_accept                (TARGET_NR_Linux +  42)
+#define TARGET_NR_sendto                (TARGET_NR_Linux +  43)
+#define TARGET_NR_recvfrom              (TARGET_NR_Linux +  44)
+#define TARGET_NR_sendmsg               (TARGET_NR_Linux +  45)
+#define TARGET_NR_recvmsg               (TARGET_NR_Linux +  46)
+#define TARGET_NR_shutdown              (TARGET_NR_Linux +  47)
+#define TARGET_NR_bind                  (TARGET_NR_Linux +  48)
+#define TARGET_NR_listen                (TARGET_NR_Linux +  49)
+#define TARGET_NR_getsockname           (TARGET_NR_Linux +  50)
+#define TARGET_NR_getpeername           (TARGET_NR_Linux +  51)
+#define TARGET_NR_socketpair            (TARGET_NR_Linux +  52)
+#define TARGET_NR_setsockopt            (TARGET_NR_Linux +  53)
+#define TARGET_NR_getsockopt            (TARGET_NR_Linux +  54)
+#define TARGET_NR_clone                 (TARGET_NR_Linux +  55)
+#define TARGET_NR_fork                  (TARGET_NR_Linux +  56)
+#define TARGET_NR_execve                (TARGET_NR_Linux +  57)
+#define TARGET_NR_exit                  (TARGET_NR_Linux +  58)
+#define TARGET_NR_wait4                 (TARGET_NR_Linux +  59)
+#define TARGET_NR_kill                  (TARGET_NR_Linux +  60)
+#define TARGET_NR_uname                 (TARGET_NR_Linux +  61)
+#define TARGET_NR_semget                (TARGET_NR_Linux +  62)
+#define TARGET_NR_semop                 (TARGET_NR_Linux +  63)
+#define TARGET_NR_semctl                (TARGET_NR_Linux +  64)
+#define TARGET_NR_shmdt                 (TARGET_NR_Linux +  65)
+#define TARGET_NR_msgget                (TARGET_NR_Linux +  66)
+#define TARGET_NR_msgsnd                (TARGET_NR_Linux +  67)
+#define TARGET_NR_msgrcv                (TARGET_NR_Linux +  68)
+#define TARGET_NR_msgctl                (TARGET_NR_Linux +  69)
+#define TARGET_NR_fcntl                 (TARGET_NR_Linux +  70)
+#define TARGET_NR_flock                 (TARGET_NR_Linux +  71)
+#define TARGET_NR_fsync                 (TARGET_NR_Linux +  72)
+#define TARGET_NR_fdatasync             (TARGET_NR_Linux +  73)
+#define TARGET_NR_truncate              (TARGET_NR_Linux +  74)
+#define TARGET_NR_ftruncate             (TARGET_NR_Linux +  75)
+#define TARGET_NR_getdents              (TARGET_NR_Linux +  76)
+#define TARGET_NR_getcwd                (TARGET_NR_Linux +  77)
+#define TARGET_NR_chdir                 (TARGET_NR_Linux +  78)
+#define TARGET_NR_fchdir                (TARGET_NR_Linux +  79)
+#define TARGET_NR_rename                (TARGET_NR_Linux +  80)
+#define TARGET_NR_mkdir                 (TARGET_NR_Linux +  81)
+#define TARGET_NR_rmdir                 (TARGET_NR_Linux +  82)
+#define TARGET_NR_creat                 (TARGET_NR_Linux +  83)
+#define TARGET_NR_link                  (TARGET_NR_Linux +  84)
+#define TARGET_NR_unlink                (TARGET_NR_Linux +  85)
+#define TARGET_NR_symlink               (TARGET_NR_Linux +  86)
+#define TARGET_NR_readlink              (TARGET_NR_Linux +  87)
+#define TARGET_NR_chmod                 (TARGET_NR_Linux +  88)
+#define TARGET_NR_fchmod                (TARGET_NR_Linux +  89)
+#define TARGET_NR_chown                 (TARGET_NR_Linux +  90)
+#define TARGET_NR_fchown                (TARGET_NR_Linux +  91)
+#define TARGET_NR_lchown                (TARGET_NR_Linux +  92)
+#define TARGET_NR_umask                 (TARGET_NR_Linux +  93)
+#define TARGET_NR_gettimeofday          (TARGET_NR_Linux +  94)
+#define TARGET_NR_getrlimit             (TARGET_NR_Linux +  95)
+#define TARGET_NR_getrusage             (TARGET_NR_Linux +  96)
+#define TARGET_NR_sysinfo               (TARGET_NR_Linux +  97)
+#define TARGET_NR_times                 (TARGET_NR_Linux +  98)
+#define TARGET_NR_ptrace                (TARGET_NR_Linux +  99)
+#define TARGET_NR_getuid                (TARGET_NR_Linux + 100)
+#define TARGET_NR_syslog                (TARGET_NR_Linux + 101)
+#define TARGET_NR_getgid                (TARGET_NR_Linux + 102)
+#define TARGET_NR_setuid                (TARGET_NR_Linux + 103)
+#define TARGET_NR_setgid                (TARGET_NR_Linux + 104)
+#define TARGET_NR_geteuid               (TARGET_NR_Linux + 105)
+#define TARGET_NR_getegid               (TARGET_NR_Linux + 106)
+#define TARGET_NR_setpgid               (TARGET_NR_Linux + 107)
+#define TARGET_NR_getppid               (TARGET_NR_Linux + 108)
+#define TARGET_NR_getpgrp               (TARGET_NR_Linux + 109)
+#define TARGET_NR_setsid                (TARGET_NR_Linux + 110)
+#define TARGET_NR_setreuid              (TARGET_NR_Linux + 111)
+#define TARGET_NR_setregid              (TARGET_NR_Linux + 112)
+#define TARGET_NR_getgroups             (TARGET_NR_Linux + 113)
+#define TARGET_NR_setgroups             (TARGET_NR_Linux + 114)
+#define TARGET_NR_setresuid             (TARGET_NR_Linux + 115)
+#define TARGET_NR_getresuid             (TARGET_NR_Linux + 116)
+#define TARGET_NR_setresgid             (TARGET_NR_Linux + 117)
+#define TARGET_NR_getresgid             (TARGET_NR_Linux + 118)
+#define TARGET_NR_getpgid               (TARGET_NR_Linux + 119)
+#define TARGET_NR_setfsuid              (TARGET_NR_Linux + 120)
+#define TARGET_NR_setfsgid              (TARGET_NR_Linux + 121)
+#define TARGET_NR_getsid                (TARGET_NR_Linux + 122)
+#define TARGET_NR_capget                (TARGET_NR_Linux + 123)
+#define TARGET_NR_capset                (TARGET_NR_Linux + 124)
+#define TARGET_NR_rt_sigpending         (TARGET_NR_Linux + 125)
+#define TARGET_NR_rt_sigtimedwait       (TARGET_NR_Linux + 126)
+#define TARGET_NR_rt_sigqueueinfo       (TARGET_NR_Linux + 127)
+#define TARGET_NR_rt_sigsuspend         (TARGET_NR_Linux + 128)
+#define TARGET_NR_sigaltstack           (TARGET_NR_Linux + 129)
+#define TARGET_NR_utime                 (TARGET_NR_Linux + 130)
+#define TARGET_NR_mknod                 (TARGET_NR_Linux + 131)
+#define TARGET_NR_personality           (TARGET_NR_Linux + 132)
+#define TARGET_NR_ustat                 (TARGET_NR_Linux + 133)
+#define TARGET_NR_statfs                (TARGET_NR_Linux + 134)
+#define TARGET_NR_fstatfs               (TARGET_NR_Linux + 135)
+#define TARGET_NR_sysfs                 (TARGET_NR_Linux + 136)
+#define TARGET_NR_getpriority           (TARGET_NR_Linux + 137)
+#define TARGET_NR_setpriority           (TARGET_NR_Linux + 138)
+#define TARGET_NR_sched_setparam        (TARGET_NR_Linux + 139)
+#define TARGET_NR_sched_getparam        (TARGET_NR_Linux + 140)
+#define TARGET_NR_sched_setscheduler    (TARGET_NR_Linux + 141)
+#define TARGET_NR_sched_getscheduler    (TARGET_NR_Linux + 142)
+#define TARGET_NR_sched_get_priority_max        (TARGET_NR_Linux + 143)
+#define TARGET_NR_sched_get_priority_min        (TARGET_NR_Linux + 144)
+#define TARGET_NR_sched_rr_get_interval (TARGET_NR_Linux + 145)
+#define TARGET_NR_mlock                 (TARGET_NR_Linux + 146)
+#define TARGET_NR_munlock               (TARGET_NR_Linux + 147)
+#define TARGET_NR_mlockall              (TARGET_NR_Linux + 148)
+#define TARGET_NR_munlockall            (TARGET_NR_Linux + 149)
+#define TARGET_NR_vhangup               (TARGET_NR_Linux + 150)
+#define TARGET_NR_pivot_root            (TARGET_NR_Linux + 151)
+#define TARGET_NR__sysctl               (TARGET_NR_Linux + 152)
+#define TARGET_NR_prctl                 (TARGET_NR_Linux + 153)
+#define TARGET_NR_adjtimex              (TARGET_NR_Linux + 154)
+#define TARGET_NR_setrlimit             (TARGET_NR_Linux + 155)
+#define TARGET_NR_chroot                (TARGET_NR_Linux + 156)
+#define TARGET_NR_sync                  (TARGET_NR_Linux + 157)
+#define TARGET_NR_acct                  (TARGET_NR_Linux + 158)
+#define TARGET_NR_settimeofday          (TARGET_NR_Linux + 159)
+#define TARGET_NR_mount                 (TARGET_NR_Linux + 160)
+#define TARGET_NR_umount2               (TARGET_NR_Linux + 161)
+#define TARGET_NR_swapon                (TARGET_NR_Linux + 162)
+#define TARGET_NR_swapoff               (TARGET_NR_Linux + 163)
+#define TARGET_NR_reboot                (TARGET_NR_Linux + 164)
+#define TARGET_NR_sethostname           (TARGET_NR_Linux + 165)
+#define TARGET_NR_setdomainname         (TARGET_NR_Linux + 166)
+#define TARGET_NR_create_module         (TARGET_NR_Linux + 167)
+#define TARGET_NR_init_module           (TARGET_NR_Linux + 168)
+#define TARGET_NR_delete_module         (TARGET_NR_Linux + 169)
+#define TARGET_NR_get_kernel_syms       (TARGET_NR_Linux + 170)
+#define TARGET_NR_query_module          (TARGET_NR_Linux + 171)
+#define TARGET_NR_quotactl              (TARGET_NR_Linux + 172)
+#define TARGET_NR_nfsservctl            (TARGET_NR_Linux + 173)
+#define TARGET_NR_getpmsg               (TARGET_NR_Linux + 174)
+#define TARGET_NR_putpmsg               (TARGET_NR_Linux + 175)
+#define TARGET_NR_afs_syscall           (TARGET_NR_Linux + 176)
+#define TARGET_NR_reserved177           (TARGET_NR_Linux + 177)
+#define TARGET_NR_gettid                (TARGET_NR_Linux + 178)
+#define TARGET_NR_readahead             (TARGET_NR_Linux + 179)
+#define TARGET_NR_setxattr              (TARGET_NR_Linux + 180)
+#define TARGET_NR_lsetxattr             (TARGET_NR_Linux + 181)
+#define TARGET_NR_fsetxattr             (TARGET_NR_Linux + 182)
+#define TARGET_NR_getxattr              (TARGET_NR_Linux + 183)
+#define TARGET_NR_lgetxattr             (TARGET_NR_Linux + 184)
+#define TARGET_NR_fgetxattr             (TARGET_NR_Linux + 185)
+#define TARGET_NR_listxattr             (TARGET_NR_Linux + 186)
+#define TARGET_NR_llistxattr            (TARGET_NR_Linux + 187)
+#define TARGET_NR_flistxattr            (TARGET_NR_Linux + 188)
+#define TARGET_NR_removexattr           (TARGET_NR_Linux + 189)
+#define TARGET_NR_lremovexattr          (TARGET_NR_Linux + 190)
+#define TARGET_NR_fremovexattr          (TARGET_NR_Linux + 191)
+#define TARGET_NR_tkill                 (TARGET_NR_Linux + 192)
+#define TARGET_NR_reserved193           (TARGET_NR_Linux + 193)
+#define TARGET_NR_futex                 (TARGET_NR_Linux + 194)
+#define TARGET_NR_sched_setaffinity     (TARGET_NR_Linux + 195)
+#define TARGET_NR_sched_getaffinity     (TARGET_NR_Linux + 196)
+#define TARGET_NR_cacheflush            (TARGET_NR_Linux + 197)
+#define TARGET_NR_cachectl              (TARGET_NR_Linux + 198)
+#define TARGET_NR_sysmips               (TARGET_NR_Linux + 199)
+#define TARGET_NR_io_setup              (TARGET_NR_Linux + 200)
+#define TARGET_NR_io_destroy            (TARGET_NR_Linux + 201)
+#define TARGET_NR_io_getevents          (TARGET_NR_Linux + 202)
+#define TARGET_NR_io_submit             (TARGET_NR_Linux + 203)
+#define TARGET_NR_io_cancel             (TARGET_NR_Linux + 204)
+#define TARGET_NR_exit_group            (TARGET_NR_Linux + 205)
+#define TARGET_NR_lookup_dcookie        (TARGET_NR_Linux + 206)
+#define TARGET_NR_epoll_create          (TARGET_NR_Linux + 207)
+#define TARGET_NR_epoll_ctl             (TARGET_NR_Linux + 208)
+#define TARGET_NR_epoll_wait            (TARGET_NR_Linux + 209)
+#define TARGET_NR_remap_file_pages      (TARGET_NR_Linux + 210)
+#define TARGET_NR_rt_sigreturn          (TARGET_NR_Linux + 211)
+#define TARGET_NR_fcntl64               (TARGET_NR_Linux + 212)
+#define TARGET_NR_set_tid_address       (TARGET_NR_Linux + 213)
+#define TARGET_NR_restart_syscall       (TARGET_NR_Linux + 214)
+#define TARGET_NR_semtimedop            (TARGET_NR_Linux + 215)
+#define TARGET_NR_fadvise64             (TARGET_NR_Linux + 216)
+#define TARGET_NR_statfs64              (TARGET_NR_Linux + 217)
+#define TARGET_NR_fstatfs64             (TARGET_NR_Linux + 218)
+#define TARGET_NR_sendfile64            (TARGET_NR_Linux + 219)
+#define TARGET_NR_timer_create          (TARGET_NR_Linux + 220)
+#define TARGET_NR_timer_settime         (TARGET_NR_Linux + 221)
+#define TARGET_NR_timer_gettime         (TARGET_NR_Linux + 222)
+#define TARGET_NR_timer_getoverrun      (TARGET_NR_Linux + 223)
+#define TARGET_NR_timer_delete          (TARGET_NR_Linux + 224)
+#define TARGET_NR_clock_settime         (TARGET_NR_Linux + 225)
+#define TARGET_NR_clock_gettime         (TARGET_NR_Linux + 226)
+#define TARGET_NR_clock_getres          (TARGET_NR_Linux + 227)
+#define TARGET_NR_clock_nanosleep       (TARGET_NR_Linux + 228)
+#define TARGET_NR_tgkill                (TARGET_NR_Linux + 229)
+#define TARGET_NR_utimes                (TARGET_NR_Linux + 230)
+#define TARGET_NR_mbind                 (TARGET_NR_Linux + 231)
+#define TARGET_NR_get_mempolicy         (TARGET_NR_Linux + 232)
+#define TARGET_NR_set_mempolicy         (TARGET_NR_Linux + 233)
+#define TARGET_NR_mq_open               (TARGET_NR_Linux + 234)
+#define TARGET_NR_mq_unlink             (TARGET_NR_Linux + 235)
+#define TARGET_NR_mq_timedsend          (TARGET_NR_Linux + 236)
+#define TARGET_NR_mq_timedreceive       (TARGET_NR_Linux + 237)
+#define TARGET_NR_mq_notify             (TARGET_NR_Linux + 238)
+#define TARGET_NR_mq_getsetattr         (TARGET_NR_Linux + 239)
+#define TARGET_NR_vserver               (TARGET_NR_Linux + 240)
+#define TARGET_NR_waitid                (TARGET_NR_Linux + 241)
+/* #define TARGET_NR_sys_setaltroot     (TARGET_NR_Linux + 242) */
+#define TARGET_NR_add_key               (TARGET_NR_Linux + 243)
+#define TARGET_NR_request_key           (TARGET_NR_Linux + 244)
+#define TARGET_NR_keyctl                (TARGET_NR_Linux + 245)
+#define TARGET_NR_set_thread_area       (TARGET_NR_Linux + 246)
+#define TARGET_NR_inotify_init          (TARGET_NR_Linux + 247)
+#define TARGET_NR_inotify_add_watch     (TARGET_NR_Linux + 248)
+#define TARGET_NR_inotify_rm_watch      (TARGET_NR_Linux + 249)
+#define TARGET_NR_migrate_pages         (TARGET_NR_Linux + 250)
+#define TARGET_NR_openat                (TARGET_NR_Linux + 251)
+#define TARGET_NR_mkdirat               (TARGET_NR_Linux + 252)
+#define TARGET_NR_mknodat               (TARGET_NR_Linux + 253)
+#define TARGET_NR_fchownat              (TARGET_NR_Linux + 254)
+#define TARGET_NR_futimesat             (TARGET_NR_Linux + 255)
+#define TARGET_NR_newfstatat            (TARGET_NR_Linux + 256)
+#define TARGET_NR_unlinkat              (TARGET_NR_Linux + 257)
+#define TARGET_NR_renameat              (TARGET_NR_Linux + 258)
+#define TARGET_NR_linkat                (TARGET_NR_Linux + 259)
+#define TARGET_NR_symlinkat             (TARGET_NR_Linux + 260)
+#define TARGET_NR_readlinkat            (TARGET_NR_Linux + 261)
+#define TARGET_NR_fchmodat              (TARGET_NR_Linux + 262)
+#define TARGET_NR_faccessat             (TARGET_NR_Linux + 263)
+#define TARGET_NR_pselect6              (TARGET_NR_Linux + 264)
+#define TARGET_NR_ppoll                 (TARGET_NR_Linux + 265)
+#define TARGET_NR_unshare               (TARGET_NR_Linux + 266)
+#define TARGET_NR_splice                (TARGET_NR_Linux + 267)
+#define TARGET_NR_sync_file_range       (TARGET_NR_Linux + 268)
+#define TARGET_NR_tee                   (TARGET_NR_Linux + 269)
+#define TARGET_NR_vmsplice              (TARGET_NR_Linux + 270)
+#define TARGET_NR_move_pages            (TARGET_NR_Linux + 271)
+#define TARGET_NR_set_robust_list       (TARGET_NR_Linux + 272)
+#define TARGET_NR_get_robust_list       (TARGET_NR_Linux + 273)
+#define TARGET_NR_kexec_load            (TARGET_NR_Linux + 274)
+#define TARGET_NR_getcpu                (TARGET_NR_Linux + 275)
+#define TARGET_NR_epoll_pwait           (TARGET_NR_Linux + 276)
+#define TARGET_NR_ioprio_set            (TARGET_NR_Linux + 277)
+#define TARGET_NR_ioprio_get            (TARGET_NR_Linux + 278)
+#define TARGET_NR_utimensat             (TARGET_NR_Linux + 279)
+#define TARGET_NR_signalfd              (TARGET_NR_Linux + 280)
+#define TARGET_NR_timerfd               (TARGET_NR_Linux + 281)
+#define TARGET_NR_eventfd               (TARGET_NR_Linux + 282)
+#define TARGET_NR_fallocate             (TARGET_NR_Linux + 283)
+#define TARGET_NR_timerfd_create        (TARGET_NR_Linux + 284)
+#define TARGET_NR_timerfd_gettime       (TARGET_NR_Linux + 285)
+#define TARGET_NR_timerfd_settime       (TARGET_NR_Linux + 286)
+#define TARGET_NR_signalfd4             (TARGET_NR_Linux + 287)
+#define TARGET_NR_eventfd2              (TARGET_NR_Linux + 288)
+#define TARGET_NR_epoll_create1         (TARGET_NR_Linux + 289)
+#define TARGET_NR_dup3                  (TARGET_NR_Linux + 290)
+#define TARGET_NR_pipe2                 (TARGET_NR_Linux + 291)
+#define TARGET_NR_inotify_init1         (TARGET_NR_Linux + 292)
+#define TARGET_NR_preadv                (TARGET_NR_Linux + 293)
+#define TARGET_NR_pwritev               (TARGET_NR_Linux + 294)
+#define TARGET_NR_rt_tgsigqueueinfo     (TARGET_NR_Linux + 295)
+#define TARGET_NR_perf_event_open       (TARGET_NR_Linux + 296)
+#define TARGET_NR_accept4               (TARGET_NR_Linux + 297)
+#define TARGET_NR_recvmmsg              (TARGET_NR_Linux + 298)
+#define TARGET_NR_getdents64            (TARGET_NR_Linux + 299)
+#define TARGET_NR_fanotify_init         (TARGET_NR_Linux + 300)
+#define TARGET_NR_fanotify_mark         (TARGET_NR_Linux + 301)
+#define TARGET_NR_prlimit64             (TARGET_NR_Linux + 302)
+#define TARGET_NR_name_to_handle_at     (TARGET_NR_Linux + 303)
+#define TARGET_NR_open_by_handle_at     (TARGET_NR_Linux + 304)
+#define TARGET_NR_clock_adjtime         (TARGET_NR_Linux + 305)
+#define TARGET_NR_syncfs                (TARGET_NR_Linux + 306)
+#else
 /*
  * Linux 64-bit syscalls are in the range from 5000 to 5999.
  */
-#define TARGET_NR_Linux			5000
-#define TARGET_NR_read			(TARGET_NR_Linux +   0)
-#define TARGET_NR_write			(TARGET_NR_Linux +   1)
-#define TARGET_NR_open			(TARGET_NR_Linux +   2)
-#define TARGET_NR_close			(TARGET_NR_Linux +   3)
-#define TARGET_NR_stat			(TARGET_NR_Linux +   4)
-#define TARGET_NR_fstat			(TARGET_NR_Linux +   5)
-#define TARGET_NR_lstat			(TARGET_NR_Linux +   6)
-#define TARGET_NR_poll			(TARGET_NR_Linux +   7)
-#define TARGET_NR_lseek			(TARGET_NR_Linux +   8)
-#define TARGET_NR_mmap			(TARGET_NR_Linux +   9)
-#define TARGET_NR_mprotect			(TARGET_NR_Linux +  10)
-#define TARGET_NR_munmap			(TARGET_NR_Linux +  11)
-#define TARGET_NR_brk			(TARGET_NR_Linux +  12)
-#define TARGET_NR_rt_sigaction		(TARGET_NR_Linux +  13)
-#define TARGET_NR_rt_sigprocmask		(TARGET_NR_Linux +  14)
-#define TARGET_NR_ioctl			(TARGET_NR_Linux +  15)
-#define TARGET_NR_pread64			(TARGET_NR_Linux +  16)
-#define TARGET_NR_pwrite64			(TARGET_NR_Linux +  17)
-#define TARGET_NR_readv			(TARGET_NR_Linux +  18)
-#define TARGET_NR_writev			(TARGET_NR_Linux +  19)
-#define TARGET_NR_access			(TARGET_NR_Linux +  20)
-#define TARGET_NR_pipe			(TARGET_NR_Linux +  21)
-#define TARGET_NR__newselect			(TARGET_NR_Linux +  22)
-#define TARGET_NR_sched_yield		(TARGET_NR_Linux +  23)
-#define TARGET_NR_mremap			(TARGET_NR_Linux +  24)
-#define TARGET_NR_msync			(TARGET_NR_Linux +  25)
-#define TARGET_NR_mincore			(TARGET_NR_Linux +  26)
-#define TARGET_NR_madvise			(TARGET_NR_Linux +  27)
-#define TARGET_NR_shmget			(TARGET_NR_Linux +  28)
-#define TARGET_NR_shmat			(TARGET_NR_Linux +  29)
-#define TARGET_NR_shmctl			(TARGET_NR_Linux +  30)
-#define TARGET_NR_dup			(TARGET_NR_Linux +  31)
-#define TARGET_NR_dup2			(TARGET_NR_Linux +  32)
-#define TARGET_NR_pause			(TARGET_NR_Linux +  33)
-#define TARGET_NR_nanosleep			(TARGET_NR_Linux +  34)
-#define TARGET_NR_getitimer			(TARGET_NR_Linux +  35)
-#define TARGET_NR_setitimer			(TARGET_NR_Linux +  36)
-#define TARGET_NR_alarm			(TARGET_NR_Linux +  37)
-#define TARGET_NR_getpid			(TARGET_NR_Linux +  38)
-#define TARGET_NR_sendfile			(TARGET_NR_Linux +  39)
-#define TARGET_NR_socket			(TARGET_NR_Linux +  40)
-#define TARGET_NR_connect			(TARGET_NR_Linux +  41)
-#define TARGET_NR_accept			(TARGET_NR_Linux +  42)
-#define TARGET_NR_sendto			(TARGET_NR_Linux +  43)
-#define TARGET_NR_recvfrom			(TARGET_NR_Linux +  44)
-#define TARGET_NR_sendmsg			(TARGET_NR_Linux +  45)
-#define TARGET_NR_recvmsg			(TARGET_NR_Linux +  46)
-#define TARGET_NR_shutdown			(TARGET_NR_Linux +  47)
-#define TARGET_NR_bind			(TARGET_NR_Linux +  48)
-#define TARGET_NR_listen			(TARGET_NR_Linux +  49)
-#define TARGET_NR_getsockname		(TARGET_NR_Linux +  50)
-#define TARGET_NR_getpeername		(TARGET_NR_Linux +  51)
-#define TARGET_NR_socketpair			(TARGET_NR_Linux +  52)
-#define TARGET_NR_setsockopt			(TARGET_NR_Linux +  53)
-#define TARGET_NR_getsockopt			(TARGET_NR_Linux +  54)
-#define TARGET_NR_clone			(TARGET_NR_Linux +  55)
-#define TARGET_NR_fork			(TARGET_NR_Linux +  56)
-#define TARGET_NR_execve			(TARGET_NR_Linux +  57)
-#define TARGET_NR_exit			(TARGET_NR_Linux +  58)
-#define TARGET_NR_wait4			(TARGET_NR_Linux +  59)
-#define TARGET_NR_kill			(TARGET_NR_Linux +  60)
-#define TARGET_NR_uname			(TARGET_NR_Linux +  61)
-#define TARGET_NR_semget			(TARGET_NR_Linux +  62)
-#define TARGET_NR_semop			(TARGET_NR_Linux +  63)
-#define TARGET_NR_semctl			(TARGET_NR_Linux +  64)
-#define TARGET_NR_shmdt			(TARGET_NR_Linux +  65)
-#define TARGET_NR_msgget			(TARGET_NR_Linux +  66)
-#define TARGET_NR_msgsnd			(TARGET_NR_Linux +  67)
-#define TARGET_NR_msgrcv			(TARGET_NR_Linux +  68)
-#define TARGET_NR_msgctl			(TARGET_NR_Linux +  69)
-#define TARGET_NR_fcntl			(TARGET_NR_Linux +  70)
-#define TARGET_NR_flock			(TARGET_NR_Linux +  71)
-#define TARGET_NR_fsync			(TARGET_NR_Linux +  72)
-#define TARGET_NR_fdatasync			(TARGET_NR_Linux +  73)
-#define TARGET_NR_truncate			(TARGET_NR_Linux +  74)
-#define TARGET_NR_ftruncate			(TARGET_NR_Linux +  75)
-#define TARGET_NR_getdents			(TARGET_NR_Linux +  76)
-#define TARGET_NR_getcwd			(TARGET_NR_Linux +  77)
-#define TARGET_NR_chdir			(TARGET_NR_Linux +  78)
-#define TARGET_NR_fchdir			(TARGET_NR_Linux +  79)
-#define TARGET_NR_rename			(TARGET_NR_Linux +  80)
-#define TARGET_NR_mkdir			(TARGET_NR_Linux +  81)
-#define TARGET_NR_rmdir			(TARGET_NR_Linux +  82)
-#define TARGET_NR_creat			(TARGET_NR_Linux +  83)
-#define TARGET_NR_link			(TARGET_NR_Linux +  84)
-#define TARGET_NR_unlink			(TARGET_NR_Linux +  85)
-#define TARGET_NR_symlink			(TARGET_NR_Linux +  86)
-#define TARGET_NR_readlink			(TARGET_NR_Linux +  87)
-#define TARGET_NR_chmod			(TARGET_NR_Linux +  88)
-#define TARGET_NR_fchmod			(TARGET_NR_Linux +  89)
-#define TARGET_NR_chown			(TARGET_NR_Linux +  90)
-#define TARGET_NR_fchown			(TARGET_NR_Linux +  91)
-#define TARGET_NR_lchown			(TARGET_NR_Linux +  92)
-#define TARGET_NR_umask			(TARGET_NR_Linux +  93)
-#define TARGET_NR_gettimeofday		(TARGET_NR_Linux +  94)
-#define TARGET_NR_getrlimit			(TARGET_NR_Linux +  95)
-#define TARGET_NR_getrusage			(TARGET_NR_Linux +  96)
-#define TARGET_NR_sysinfo			(TARGET_NR_Linux +  97)
-#define TARGET_NR_times			(TARGET_NR_Linux +  98)
-#define TARGET_NR_ptrace			(TARGET_NR_Linux +  99)
-#define TARGET_NR_getuid			(TARGET_NR_Linux + 100)
-#define TARGET_NR_syslog			(TARGET_NR_Linux + 101)
-#define TARGET_NR_getgid			(TARGET_NR_Linux + 102)
-#define TARGET_NR_setuid			(TARGET_NR_Linux + 103)
-#define TARGET_NR_setgid			(TARGET_NR_Linux + 104)
-#define TARGET_NR_geteuid			(TARGET_NR_Linux + 105)
-#define TARGET_NR_getegid			(TARGET_NR_Linux + 106)
-#define TARGET_NR_setpgid			(TARGET_NR_Linux + 107)
-#define TARGET_NR_getppid			(TARGET_NR_Linux + 108)
-#define TARGET_NR_getpgrp			(TARGET_NR_Linux + 109)
-#define TARGET_NR_setsid			(TARGET_NR_Linux + 110)
-#define TARGET_NR_setreuid			(TARGET_NR_Linux + 111)
-#define TARGET_NR_setregid			(TARGET_NR_Linux + 112)
-#define TARGET_NR_getgroups			(TARGET_NR_Linux + 113)
-#define TARGET_NR_setgroups			(TARGET_NR_Linux + 114)
-#define TARGET_NR_setresuid			(TARGET_NR_Linux + 115)
-#define TARGET_NR_getresuid			(TARGET_NR_Linux + 116)
-#define TARGET_NR_setresgid			(TARGET_NR_Linux + 117)
-#define TARGET_NR_getresgid			(TARGET_NR_Linux + 118)
-#define TARGET_NR_getpgid			(TARGET_NR_Linux + 119)
-#define TARGET_NR_setfsuid			(TARGET_NR_Linux + 120)
-#define TARGET_NR_setfsgid			(TARGET_NR_Linux + 121)
-#define TARGET_NR_getsid			(TARGET_NR_Linux + 122)
-#define TARGET_NR_capget			(TARGET_NR_Linux + 123)
-#define TARGET_NR_capset			(TARGET_NR_Linux + 124)
-#define TARGET_NR_rt_sigpending		(TARGET_NR_Linux + 125)
-#define TARGET_NR_rt_sigtimedwait		(TARGET_NR_Linux + 126)
-#define TARGET_NR_rt_sigqueueinfo		(TARGET_NR_Linux + 127)
-#define TARGET_NR_rt_sigsuspend		(TARGET_NR_Linux + 128)
-#define TARGET_NR_sigaltstack		(TARGET_NR_Linux + 129)
-#define TARGET_NR_utime			(TARGET_NR_Linux + 130)
-#define TARGET_NR_mknod			(TARGET_NR_Linux + 131)
-#define TARGET_NR_personality		(TARGET_NR_Linux + 132)
-#define TARGET_NR_ustat			(TARGET_NR_Linux + 133)
-#define TARGET_NR_statfs			(TARGET_NR_Linux + 134)
-#define TARGET_NR_fstatfs			(TARGET_NR_Linux + 135)
-#define TARGET_NR_sysfs			(TARGET_NR_Linux + 136)
-#define TARGET_NR_getpriority		(TARGET_NR_Linux + 137)
-#define TARGET_NR_setpriority		(TARGET_NR_Linux + 138)
-#define TARGET_NR_sched_setparam		(TARGET_NR_Linux + 139)
-#define TARGET_NR_sched_getparam		(TARGET_NR_Linux + 140)
-#define TARGET_NR_sched_setscheduler		(TARGET_NR_Linux + 141)
-#define TARGET_NR_sched_getscheduler		(TARGET_NR_Linux + 142)
-#define TARGET_NR_sched_get_priority_max	(TARGET_NR_Linux + 143)
-#define TARGET_NR_sched_get_priority_min	(TARGET_NR_Linux + 144)
-#define TARGET_NR_sched_rr_get_interval	(TARGET_NR_Linux + 145)
-#define TARGET_NR_mlock			(TARGET_NR_Linux + 146)
-#define TARGET_NR_munlock			(TARGET_NR_Linux + 147)
-#define TARGET_NR_mlockall			(TARGET_NR_Linux + 148)
-#define TARGET_NR_munlockall			(TARGET_NR_Linux + 149)
-#define TARGET_NR_vhangup			(TARGET_NR_Linux + 150)
-#define TARGET_NR_pivot_root			(TARGET_NR_Linux + 151)
-#define TARGET_NR__sysctl			(TARGET_NR_Linux + 152)
-#define TARGET_NR_prctl			(TARGET_NR_Linux + 153)
-#define TARGET_NR_adjtimex			(TARGET_NR_Linux + 154)
-#define TARGET_NR_setrlimit			(TARGET_NR_Linux + 155)
-#define TARGET_NR_chroot			(TARGET_NR_Linux + 156)
-#define TARGET_NR_sync			(TARGET_NR_Linux + 157)
-#define TARGET_NR_acct			(TARGET_NR_Linux + 158)
-#define TARGET_NR_settimeofday		(TARGET_NR_Linux + 159)
-#define TARGET_NR_mount			(TARGET_NR_Linux + 160)
-#define TARGET_NR_umount2			(TARGET_NR_Linux + 161)
-#define TARGET_NR_swapon			(TARGET_NR_Linux + 162)
-#define TARGET_NR_swapoff			(TARGET_NR_Linux + 163)
-#define TARGET_NR_reboot			(TARGET_NR_Linux + 164)
-#define TARGET_NR_sethostname		(TARGET_NR_Linux + 165)
-#define TARGET_NR_setdomainname		(TARGET_NR_Linux + 166)
-#define TARGET_NR_create_module		(TARGET_NR_Linux + 167)
-#define TARGET_NR_init_module		(TARGET_NR_Linux + 168)
-#define TARGET_NR_delete_module		(TARGET_NR_Linux + 169)
-#define TARGET_NR_get_kernel_syms		(TARGET_NR_Linux + 170)
-#define TARGET_NR_query_module		(TARGET_NR_Linux + 171)
-#define TARGET_NR_quotactl			(TARGET_NR_Linux + 172)
-#define TARGET_NR_nfsservctl			(TARGET_NR_Linux + 173)
-#define TARGET_NR_getpmsg			(TARGET_NR_Linux + 174)
-#define TARGET_NR_putpmsg			(TARGET_NR_Linux + 175)
-#define TARGET_NR_afs_syscall		(TARGET_NR_Linux + 176)
-#define TARGET_NR_reserved177		(TARGET_NR_Linux + 177)
-#define TARGET_NR_gettid			(TARGET_NR_Linux + 178)
-#define TARGET_NR_readahead			(TARGET_NR_Linux + 179)
-#define TARGET_NR_setxattr			(TARGET_NR_Linux + 180)
-#define TARGET_NR_lsetxattr			(TARGET_NR_Linux + 181)
-#define TARGET_NR_fsetxattr			(TARGET_NR_Linux + 182)
-#define TARGET_NR_getxattr			(TARGET_NR_Linux + 183)
-#define TARGET_NR_lgetxattr			(TARGET_NR_Linux + 184)
-#define TARGET_NR_fgetxattr			(TARGET_NR_Linux + 185)
-#define TARGET_NR_listxattr			(TARGET_NR_Linux + 186)
-#define TARGET_NR_llistxattr			(TARGET_NR_Linux + 187)
-#define TARGET_NR_flistxattr			(TARGET_NR_Linux + 188)
-#define TARGET_NR_removexattr		(TARGET_NR_Linux + 189)
-#define TARGET_NR_lremovexattr		(TARGET_NR_Linux + 190)
-#define TARGET_NR_fremovexattr		(TARGET_NR_Linux + 191)
-#define TARGET_NR_tkill			(TARGET_NR_Linux + 192)
-#define TARGET_NR_reserved193		(TARGET_NR_Linux + 193)
-#define TARGET_NR_futex			(TARGET_NR_Linux + 194)
-#define TARGET_NR_sched_setaffinity		(TARGET_NR_Linux + 195)
-#define TARGET_NR_sched_getaffinity		(TARGET_NR_Linux + 196)
-#define TARGET_NR_cacheflush			(TARGET_NR_Linux + 197)
-#define TARGET_NR_cachectl			(TARGET_NR_Linux + 198)
-#define TARGET_NR_sysmips			(TARGET_NR_Linux + 199)
-#define TARGET_NR_io_setup			(TARGET_NR_Linux + 200)
-#define TARGET_NR_io_destroy			(TARGET_NR_Linux + 201)
-#define TARGET_NR_io_getevents		(TARGET_NR_Linux + 202)
-#define TARGET_NR_io_submit			(TARGET_NR_Linux + 203)
-#define TARGET_NR_io_cancel			(TARGET_NR_Linux + 204)
-#define TARGET_NR_exit_group			(TARGET_NR_Linux + 205)
-#define TARGET_NR_lookup_dcookie		(TARGET_NR_Linux + 206)
-#define TARGET_NR_epoll_create		(TARGET_NR_Linux + 207)
-#define TARGET_NR_epoll_ctl			(TARGET_NR_Linux + 208)
-#define TARGET_NR_epoll_wait			(TARGET_NR_Linux + 209)
-#define TARGET_NR_remap_file_pages		(TARGET_NR_Linux + 210)
-#define TARGET_NR_rt_sigreturn		(TARGET_NR_Linux + 211)
-#define TARGET_NR_set_tid_address		(TARGET_NR_Linux + 212)
-#define TARGET_NR_restart_syscall		(TARGET_NR_Linux + 213)
-#define TARGET_NR_semtimedop			(TARGET_NR_Linux + 214)
-#define TARGET_NR_fadvise64			(TARGET_NR_Linux + 215)
-#define TARGET_NR_timer_create		(TARGET_NR_Linux + 216)
-#define TARGET_NR_timer_settime		(TARGET_NR_Linux + 217)
-#define TARGET_NR_timer_gettime		(TARGET_NR_Linux + 218)
-#define TARGET_NR_timer_getoverrun		(TARGET_NR_Linux + 219)
-#define TARGET_NR_timer_delete		(TARGET_NR_Linux + 220)
-#define TARGET_NR_clock_settime		(TARGET_NR_Linux + 221)
-#define TARGET_NR_clock_gettime		(TARGET_NR_Linux + 222)
-#define TARGET_NR_clock_getres		(TARGET_NR_Linux + 223)
-#define TARGET_NR_clock_nanosleep		(TARGET_NR_Linux + 224)
-#define TARGET_NR_tgkill			(TARGET_NR_Linux + 225)
-#define TARGET_NR_utimes			(TARGET_NR_Linux + 226)
-#define TARGET_NR_mbind			(TARGET_NR_Linux + 227)
-#define TARGET_NR_get_mempolicy		(TARGET_NR_Linux + 228)
-#define TARGET_NR_set_mempolicy		(TARGET_NR_Linux + 229)
-#define TARGET_NR_mq_open			(TARGET_NR_Linux + 230)
-#define TARGET_NR_mq_unlink			(TARGET_NR_Linux + 231)
-#define TARGET_NR_mq_timedsend		(TARGET_NR_Linux + 232)
-#define TARGET_NR_mq_timedreceive		(TARGET_NR_Linux + 233)
-#define TARGET_NR_mq_notify			(TARGET_NR_Linux + 234)
-#define TARGET_NR_mq_getsetattr		(TARGET_NR_Linux + 235)
-#define TARGET_NR_vserver			(TARGET_NR_Linux + 236)
-#define TARGET_NR_waitid			(TARGET_NR_Linux + 237)
-/* #define TARGET_NR_sys_setaltroot		(TARGET_NR_Linux + 238) */
-#define TARGET_NR_add_key			(TARGET_NR_Linux + 239)
-#define TARGET_NR_request_key		(TARGET_NR_Linux + 240)
-#define TARGET_NR_keyctl			(TARGET_NR_Linux + 241)
-#define TARGET_NR_set_thread_area		(TARGET_NR_Linux + 242)
-#define TARGET_NR_inotify_init		(TARGET_NR_Linux + 243)
-#define TARGET_NR_inotify_add_watch		(TARGET_NR_Linux + 244)
-#define TARGET_NR_inotify_rm_watch		(TARGET_NR_Linux + 245)
-#define TARGET_NR_migrate_pages		(TARGET_NR_Linux + 246)
-#define TARGET_NR_openat			(TARGET_NR_Linux + 247)
-#define TARGET_NR_mkdirat			(TARGET_NR_Linux + 248)
-#define TARGET_NR_mknodat			(TARGET_NR_Linux + 249)
-#define TARGET_NR_fchownat			(TARGET_NR_Linux + 250)
-#define TARGET_NR_futimesat			(TARGET_NR_Linux + 251)
-#define TARGET_NR_newfstatat			(TARGET_NR_Linux + 252)
-#define TARGET_NR_unlinkat			(TARGET_NR_Linux + 253)
-#define TARGET_NR_renameat			(TARGET_NR_Linux + 254)
-#define TARGET_NR_linkat			(TARGET_NR_Linux + 255)
-#define TARGET_NR_symlinkat			(TARGET_NR_Linux + 256)
-#define TARGET_NR_readlinkat			(TARGET_NR_Linux + 257)
-#define TARGET_NR_fchmodat			(TARGET_NR_Linux + 258)
-#define TARGET_NR_faccessat			(TARGET_NR_Linux + 259)
-#define TARGET_NR_pselect6			(TARGET_NR_Linux + 260)
-#define TARGET_NR_ppoll			(TARGET_NR_Linux + 261)
-#define TARGET_NR_unshare			(TARGET_NR_Linux + 262)
-#define TARGET_NR_splice			(TARGET_NR_Linux + 263)
-#define TARGET_NR_sync_file_range		(TARGET_NR_Linux + 264)
-#define TARGET_NR_tee			(TARGET_NR_Linux + 265)
-#define TARGET_NR_vmsplice			(TARGET_NR_Linux + 266)
-#define TARGET_NR_move_pages			(TARGET_NR_Linux + 267)
-#define TARGET_NR_set_robust_list		(TARGET_NR_Linux + 268)
-#define TARGET_NR_get_robust_list		(TARGET_NR_Linux + 269)
-#define TARGET_NR_kexec_load			(TARGET_NR_Linux + 270)
-#define TARGET_NR_getcpu			(TARGET_NR_Linux + 271)
-#define TARGET_NR_epoll_pwait		(TARGET_NR_Linux + 272)
-#define TARGET_NR_ioprio_set			(TARGET_NR_Linux + 273)
-#define TARGET_NR_ioprio_get			(TARGET_NR_Linux + 274)
-#define TARGET_NR_utimensat			(TARGET_NR_Linux + 275)
-#define TARGET_NR_signalfd			(TARGET_NR_Linux + 276)
-#define TARGET_NR_timerfd			(TARGET_NR_Linux + 277)
-#define TARGET_NR_eventfd			(TARGET_NR_Linux + 278)
-#define TARGET_NR_fallocate			(TARGET_NR_Linux + 279)
-#define TARGET_NR_timerfd_create		(TARGET_NR_Linux + 280)
-#define TARGET_NR_timerfd_gettime		(TARGET_NR_Linux + 281)
-#define TARGET_NR_timerfd_settime		(TARGET_NR_Linux + 282)
-#define TARGET_NR_signalfd4			(TARGET_NR_Linux + 283)
-#define TARGET_NR_eventfd2			(TARGET_NR_Linux + 284)
-#define TARGET_NR_epoll_create1		(TARGET_NR_Linux + 285)
-#define TARGET_NR_dup3				(TARGET_NR_Linux + 286)
-#define TARGET_NR_pipe2			(TARGET_NR_Linux + 287)
-#define TARGET_NR_inotify_init1		(TARGET_NR_Linux + 288)
-#define TARGET_NR_preadv                        (TARGET_NR_Linux + 289)
-#define TARGET_NR_pwritev                       (TARGET_NR_Linux + 290)
-#define TARGET_NR_rt_tgsigqueueinfo             (TARGET_NR_Linux + 291)
-#define TARGET_NR_perf_event_open               (TARGET_NR_Linux + 292)
-#define TARGET_NR_accept4                       (TARGET_NR_Linux + 293)
-#define TARGET_NR_recvmmsg                      (TARGET_NR_Linux + 294)
-#define TARGET_NR_fanotify_init                 (TARGET_NR_Linux + 295)
-#define TARGET_NR_fanotify_mark                 (TARGET_NR_Linux + 296)
-#define TARGET_NR_prlimit64                     (TARGET_NR_Linux + 297)
-#define TARGET_NR_name_to_handle_at             (TARGET_NR_Linux + 298)
-#define TARGET_NR_open_by_handle_at             (TARGET_NR_Linux + 299)
-#define TARGET_NR_clock_adjtime                 (TARGET_NR_Linux + 300)
-#define TARGET_NR_syncfs                        (TARGET_NR_Linux + 301)
+#define TARGET_NR_Linux                 5000
+#define TARGET_NR_read                  (TARGET_NR_Linux +   0)
+#define TARGET_NR_write                 (TARGET_NR_Linux +   1)
+#define TARGET_NR_open                  (TARGET_NR_Linux +   2)
+#define TARGET_NR_close                 (TARGET_NR_Linux +   3)
+#define TARGET_NR_stat                  (TARGET_NR_Linux +   4)
+#define TARGET_NR_fstat                 (TARGET_NR_Linux +   5)
+#define TARGET_NR_lstat                 (TARGET_NR_Linux +   6)
+#define TARGET_NR_poll                  (TARGET_NR_Linux +   7)
+#define TARGET_NR_lseek                 (TARGET_NR_Linux +   8)
+#define TARGET_NR_mmap                  (TARGET_NR_Linux +   9)
+#define TARGET_NR_mprotect              (TARGET_NR_Linux +  10)
+#define TARGET_NR_munmap                (TARGET_NR_Linux +  11)
+#define TARGET_NR_brk                   (TARGET_NR_Linux +  12)
+#define TARGET_NR_rt_sigaction          (TARGET_NR_Linux +  13)
+#define TARGET_NR_rt_sigprocmask        (TARGET_NR_Linux +  14)
+#define TARGET_NR_ioctl                 (TARGET_NR_Linux +  15)
+#define TARGET_NR_pread64               (TARGET_NR_Linux +  16)
+#define TARGET_NR_pwrite64              (TARGET_NR_Linux +  17)
+#define TARGET_NR_readv                 (TARGET_NR_Linux +  18)
+#define TARGET_NR_writev                (TARGET_NR_Linux +  19)
+#define TARGET_NR_access                (TARGET_NR_Linux +  20)
+#define TARGET_NR_pipe                  (TARGET_NR_Linux +  21)
+#define TARGET_NR__newselect            (TARGET_NR_Linux +  22)
+#define TARGET_NR_sched_yield           (TARGET_NR_Linux +  23)
+#define TARGET_NR_mremap                (TARGET_NR_Linux +  24)
+#define TARGET_NR_msync                 (TARGET_NR_Linux +  25)
+#define TARGET_NR_mincore               (TARGET_NR_Linux +  26)
+#define TARGET_NR_madvise               (TARGET_NR_Linux +  27)
+#define TARGET_NR_shmget                (TARGET_NR_Linux +  28)
+#define TARGET_NR_shmat                 (TARGET_NR_Linux +  29)
+#define TARGET_NR_shmctl                (TARGET_NR_Linux +  30)
+#define TARGET_NR_dup                   (TARGET_NR_Linux +  31)
+#define TARGET_NR_dup2                  (TARGET_NR_Linux +  32)
+#define TARGET_NR_pause                 (TARGET_NR_Linux +  33)
+#define TARGET_NR_nanosleep             (TARGET_NR_Linux +  34)
+#define TARGET_NR_getitimer             (TARGET_NR_Linux +  35)
+#define TARGET_NR_setitimer             (TARGET_NR_Linux +  36)
+#define TARGET_NR_alarm                 (TARGET_NR_Linux +  37)
+#define TARGET_NR_getpid                (TARGET_NR_Linux +  38)
+#define TARGET_NR_sendfile              (TARGET_NR_Linux +  39)
+#define TARGET_NR_socket                (TARGET_NR_Linux +  40)
+#define TARGET_NR_connect               (TARGET_NR_Linux +  41)
+#define TARGET_NR_accept                (TARGET_NR_Linux +  42)
+#define TARGET_NR_sendto                (TARGET_NR_Linux +  43)
+#define TARGET_NR_recvfrom              (TARGET_NR_Linux +  44)
+#define TARGET_NR_sendmsg               (TARGET_NR_Linux +  45)
+#define TARGET_NR_recvmsg               (TARGET_NR_Linux +  46)
+#define TARGET_NR_shutdown              (TARGET_NR_Linux +  47)
+#define TARGET_NR_bind                  (TARGET_NR_Linux +  48)
+#define TARGET_NR_listen                (TARGET_NR_Linux +  49)
+#define TARGET_NR_getsockname           (TARGET_NR_Linux +  50)
+#define TARGET_NR_getpeername           (TARGET_NR_Linux +  51)
+#define TARGET_NR_socketpair            (TARGET_NR_Linux +  52)
+#define TARGET_NR_setsockopt            (TARGET_NR_Linux +  53)
+#define TARGET_NR_getsockopt            (TARGET_NR_Linux +  54)
+#define TARGET_NR_clone                 (TARGET_NR_Linux +  55)
+#define TARGET_NR_fork                  (TARGET_NR_Linux +  56)
+#define TARGET_NR_execve                (TARGET_NR_Linux +  57)
+#define TARGET_NR_exit                  (TARGET_NR_Linux +  58)
+#define TARGET_NR_wait4                 (TARGET_NR_Linux +  59)
+#define TARGET_NR_kill                  (TARGET_NR_Linux +  60)
+#define TARGET_NR_uname                 (TARGET_NR_Linux +  61)
+#define TARGET_NR_semget                (TARGET_NR_Linux +  62)
+#define TARGET_NR_semop                 (TARGET_NR_Linux +  63)
+#define TARGET_NR_semctl                (TARGET_NR_Linux +  64)
+#define TARGET_NR_shmdt                 (TARGET_NR_Linux +  65)
+#define TARGET_NR_msgget                (TARGET_NR_Linux +  66)
+#define TARGET_NR_msgsnd                (TARGET_NR_Linux +  67)
+#define TARGET_NR_msgrcv                (TARGET_NR_Linux +  68)
+#define TARGET_NR_msgctl                (TARGET_NR_Linux +  69)
+#define TARGET_NR_fcntl                 (TARGET_NR_Linux +  70)
+#define TARGET_NR_flock                 (TARGET_NR_Linux +  71)
+#define TARGET_NR_fsync                 (TARGET_NR_Linux +  72)
+#define TARGET_NR_fdatasync             (TARGET_NR_Linux +  73)
+#define TARGET_NR_truncate              (TARGET_NR_Linux +  74)
+#define TARGET_NR_ftruncate             (TARGET_NR_Linux +  75)
+#define TARGET_NR_getdents              (TARGET_NR_Linux +  76)
+#define TARGET_NR_getcwd                (TARGET_NR_Linux +  77)
+#define TARGET_NR_chdir                 (TARGET_NR_Linux +  78)
+#define TARGET_NR_fchdir                (TARGET_NR_Linux +  79)
+#define TARGET_NR_rename                (TARGET_NR_Linux +  80)
+#define TARGET_NR_mkdir                 (TARGET_NR_Linux +  81)
+#define TARGET_NR_rmdir                 (TARGET_NR_Linux +  82)
+#define TARGET_NR_creat                 (TARGET_NR_Linux +  83)
+#define TARGET_NR_link                  (TARGET_NR_Linux +  84)
+#define TARGET_NR_unlink                (TARGET_NR_Linux +  85)
+#define TARGET_NR_symlink               (TARGET_NR_Linux +  86)
+#define TARGET_NR_readlink              (TARGET_NR_Linux +  87)
+#define TARGET_NR_chmod                 (TARGET_NR_Linux +  88)
+#define TARGET_NR_fchmod                (TARGET_NR_Linux +  89)
+#define TARGET_NR_chown                 (TARGET_NR_Linux +  90)
+#define TARGET_NR_fchown                (TARGET_NR_Linux +  91)
+#define TARGET_NR_lchown                (TARGET_NR_Linux +  92)
+#define TARGET_NR_umask                 (TARGET_NR_Linux +  93)
+#define TARGET_NR_gettimeofday          (TARGET_NR_Linux +  94)
+#define TARGET_NR_getrlimit             (TARGET_NR_Linux +  95)
+#define TARGET_NR_getrusage             (TARGET_NR_Linux +  96)
+#define TARGET_NR_sysinfo               (TARGET_NR_Linux +  97)
+#define TARGET_NR_times                 (TARGET_NR_Linux +  98)
+#define TARGET_NR_ptrace                (TARGET_NR_Linux +  99)
+#define TARGET_NR_getuid                (TARGET_NR_Linux + 100)
+#define TARGET_NR_syslog                (TARGET_NR_Linux + 101)
+#define TARGET_NR_getgid                (TARGET_NR_Linux + 102)
+#define TARGET_NR_setuid                (TARGET_NR_Linux + 103)
+#define TARGET_NR_setgid                (TARGET_NR_Linux + 104)
+#define TARGET_NR_geteuid               (TARGET_NR_Linux + 105)
+#define TARGET_NR_getegid               (TARGET_NR_Linux + 106)
+#define TARGET_NR_setpgid               (TARGET_NR_Linux + 107)
+#define TARGET_NR_getppid               (TARGET_NR_Linux + 108)
+#define TARGET_NR_getpgrp               (TARGET_NR_Linux + 109)
+#define TARGET_NR_setsid                (TARGET_NR_Linux + 110)
+#define TARGET_NR_setreuid              (TARGET_NR_Linux + 111)
+#define TARGET_NR_setregid              (TARGET_NR_Linux + 112)
+#define TARGET_NR_getgroups             (TARGET_NR_Linux + 113)
+#define TARGET_NR_setgroups             (TARGET_NR_Linux + 114)
+#define TARGET_NR_setresuid             (TARGET_NR_Linux + 115)
+#define TARGET_NR_getresuid             (TARGET_NR_Linux + 116)
+#define TARGET_NR_setresgid             (TARGET_NR_Linux + 117)
+#define TARGET_NR_getresgid             (TARGET_NR_Linux + 118)
+#define TARGET_NR_getpgid               (TARGET_NR_Linux + 119)
+#define TARGET_NR_setfsuid              (TARGET_NR_Linux + 120)
+#define TARGET_NR_setfsgid              (TARGET_NR_Linux + 121)
+#define TARGET_NR_getsid                (TARGET_NR_Linux + 122)
+#define TARGET_NR_capget                (TARGET_NR_Linux + 123)
+#define TARGET_NR_capset                (TARGET_NR_Linux + 124)
+#define TARGET_NR_rt_sigpending         (TARGET_NR_Linux + 125)
+#define TARGET_NR_rt_sigtimedwait       (TARGET_NR_Linux + 126)
+#define TARGET_NR_rt_sigqueueinfo       (TARGET_NR_Linux + 127)
+#define TARGET_NR_rt_sigsuspend         (TARGET_NR_Linux + 128)
+#define TARGET_NR_sigaltstack           (TARGET_NR_Linux + 129)
+#define TARGET_NR_utime                 (TARGET_NR_Linux + 130)
+#define TARGET_NR_mknod                 (TARGET_NR_Linux + 131)
+#define TARGET_NR_personality           (TARGET_NR_Linux + 132)
+#define TARGET_NR_ustat                 (TARGET_NR_Linux + 133)
+#define TARGET_NR_statfs                (TARGET_NR_Linux + 134)
+#define TARGET_NR_fstatfs               (TARGET_NR_Linux + 135)
+#define TARGET_NR_sysfs                 (TARGET_NR_Linux + 136)
+#define TARGET_NR_getpriority           (TARGET_NR_Linux + 137)
+#define TARGET_NR_setpriority           (TARGET_NR_Linux + 138)
+#define TARGET_NR_sched_setparam        (TARGET_NR_Linux + 139)
+#define TARGET_NR_sched_getparam        (TARGET_NR_Linux + 140)
+#define TARGET_NR_sched_setscheduler    (TARGET_NR_Linux + 141)
+#define TARGET_NR_sched_getscheduler    (TARGET_NR_Linux + 142)
+#define TARGET_NR_sched_get_priority_max        (TARGET_NR_Linux + 143)
+#define TARGET_NR_sched_get_priority_min        (TARGET_NR_Linux + 144)
+#define TARGET_NR_sched_rr_get_interval (TARGET_NR_Linux + 145)
+#define TARGET_NR_mlock                 (TARGET_NR_Linux + 146)
+#define TARGET_NR_munlock               (TARGET_NR_Linux + 147)
+#define TARGET_NR_mlockall              (TARGET_NR_Linux + 148)
+#define TARGET_NR_munlockall            (TARGET_NR_Linux + 149)
+#define TARGET_NR_vhangup               (TARGET_NR_Linux + 150)
+#define TARGET_NR_pivot_root            (TARGET_NR_Linux + 151)
+#define TARGET_NR__sysctl               (TARGET_NR_Linux + 152)
+#define TARGET_NR_prctl                 (TARGET_NR_Linux + 153)
+#define TARGET_NR_adjtimex              (TARGET_NR_Linux + 154)
+#define TARGET_NR_setrlimit             (TARGET_NR_Linux + 155)
+#define TARGET_NR_chroot                (TARGET_NR_Linux + 156)
+#define TARGET_NR_sync                  (TARGET_NR_Linux + 157)
+#define TARGET_NR_acct                  (TARGET_NR_Linux + 158)
+#define TARGET_NR_settimeofday          (TARGET_NR_Linux + 159)
+#define TARGET_NR_mount                 (TARGET_NR_Linux + 160)
+#define TARGET_NR_umount2               (TARGET_NR_Linux + 161)
+#define TARGET_NR_swapon                (TARGET_NR_Linux + 162)
+#define TARGET_NR_swapoff               (TARGET_NR_Linux + 163)
+#define TARGET_NR_reboot                (TARGET_NR_Linux + 164)
+#define TARGET_NR_sethostname           (TARGET_NR_Linux + 165)
+#define TARGET_NR_setdomainname         (TARGET_NR_Linux + 166)
+#define TARGET_NR_create_module         (TARGET_NR_Linux + 167)
+#define TARGET_NR_init_module           (TARGET_NR_Linux + 168)
+#define TARGET_NR_delete_module         (TARGET_NR_Linux + 169)
+#define TARGET_NR_get_kernel_syms       (TARGET_NR_Linux + 170)
+#define TARGET_NR_query_module          (TARGET_NR_Linux + 171)
+#define TARGET_NR_quotactl              (TARGET_NR_Linux + 172)
+#define TARGET_NR_nfsservctl            (TARGET_NR_Linux + 173)
+#define TARGET_NR_getpmsg               (TARGET_NR_Linux + 174)
+#define TARGET_NR_putpmsg               (TARGET_NR_Linux + 175)
+#define TARGET_NR_afs_syscall           (TARGET_NR_Linux + 176)
+#define TARGET_NR_reserved177           (TARGET_NR_Linux + 177)
+#define TARGET_NR_gettid                (TARGET_NR_Linux + 178)
+#define TARGET_NR_readahead             (TARGET_NR_Linux + 179)
+#define TARGET_NR_setxattr              (TARGET_NR_Linux + 180)
+#define TARGET_NR_lsetxattr             (TARGET_NR_Linux + 181)
+#define TARGET_NR_fsetxattr             (TARGET_NR_Linux + 182)
+#define TARGET_NR_getxattr              (TARGET_NR_Linux + 183)
+#define TARGET_NR_lgetxattr             (TARGET_NR_Linux + 184)
+#define TARGET_NR_fgetxattr             (TARGET_NR_Linux + 185)
+#define TARGET_NR_listxattr             (TARGET_NR_Linux + 186)
+#define TARGET_NR_llistxattr            (TARGET_NR_Linux + 187)
+#define TARGET_NR_flistxattr            (TARGET_NR_Linux + 188)
+#define TARGET_NR_removexattr           (TARGET_NR_Linux + 189)
+#define TARGET_NR_lremovexattr          (TARGET_NR_Linux + 190)
+#define TARGET_NR_fremovexattr          (TARGET_NR_Linux + 191)
+#define TARGET_NR_tkill                 (TARGET_NR_Linux + 192)
+#define TARGET_NR_reserved193           (TARGET_NR_Linux + 193)
+#define TARGET_NR_futex                 (TARGET_NR_Linux + 194)
+#define TARGET_NR_sched_setaffinity     (TARGET_NR_Linux + 195)
+#define TARGET_NR_sched_getaffinity     (TARGET_NR_Linux + 196)
+#define TARGET_NR_cacheflush            (TARGET_NR_Linux + 197)
+#define TARGET_NR_cachectl              (TARGET_NR_Linux + 198)
+#define TARGET_NR_sysmips               (TARGET_NR_Linux + 199)
+#define TARGET_NR_io_setup              (TARGET_NR_Linux + 200)
+#define TARGET_NR_io_destroy            (TARGET_NR_Linux + 201)
+#define TARGET_NR_io_getevents          (TARGET_NR_Linux + 202)
+#define TARGET_NR_io_submit             (TARGET_NR_Linux + 203)
+#define TARGET_NR_io_cancel             (TARGET_NR_Linux + 204)
+#define TARGET_NR_exit_group            (TARGET_NR_Linux + 205)
+#define TARGET_NR_lookup_dcookie        (TARGET_NR_Linux + 206)
+#define TARGET_NR_epoll_create          (TARGET_NR_Linux + 207)
+#define TARGET_NR_epoll_ctl             (TARGET_NR_Linux + 208)
+#define TARGET_NR_epoll_wait            (TARGET_NR_Linux + 209)
+#define TARGET_NR_remap_file_pages      (TARGET_NR_Linux + 210)
+#define TARGET_NR_rt_sigreturn          (TARGET_NR_Linux + 211)
+#define TARGET_NR_set_tid_address       (TARGET_NR_Linux + 212)
+#define TARGET_NR_restart_syscall       (TARGET_NR_Linux + 213)
+#define TARGET_NR_semtimedop            (TARGET_NR_Linux + 214)
+#define TARGET_NR_fadvise64             (TARGET_NR_Linux + 215)
+#define TARGET_NR_timer_create          (TARGET_NR_Linux + 216)
+#define TARGET_NR_timer_settime         (TARGET_NR_Linux + 217)
+#define TARGET_NR_timer_gettime         (TARGET_NR_Linux + 218)
+#define TARGET_NR_timer_getoverrun      (TARGET_NR_Linux + 219)
+#define TARGET_NR_timer_delete          (TARGET_NR_Linux + 220)
+#define TARGET_NR_clock_settime         (TARGET_NR_Linux + 221)
+#define TARGET_NR_clock_gettime         (TARGET_NR_Linux + 222)
+#define TARGET_NR_clock_getres          (TARGET_NR_Linux + 223)
+#define TARGET_NR_clock_nanosleep       (TARGET_NR_Linux + 224)
+#define TARGET_NR_tgkill                (TARGET_NR_Linux + 225)
+#define TARGET_NR_utimes                (TARGET_NR_Linux + 226)
+#define TARGET_NR_mbind                 (TARGET_NR_Linux + 227)
+#define TARGET_NR_get_mempolicy         (TARGET_NR_Linux + 228)
+#define TARGET_NR_set_mempolicy         (TARGET_NR_Linux + 229)
+#define TARGET_NR_mq_open               (TARGET_NR_Linux + 230)
+#define TARGET_NR_mq_unlink             (TARGET_NR_Linux + 231)
+#define TARGET_NR_mq_timedsend          (TARGET_NR_Linux + 232)
+#define TARGET_NR_mq_timedreceive       (TARGET_NR_Linux + 233)
+#define TARGET_NR_mq_notify             (TARGET_NR_Linux + 234)
+#define TARGET_NR_mq_getsetattr         (TARGET_NR_Linux + 235)
+#define TARGET_NR_vserver               (TARGET_NR_Linux + 236)
+#define TARGET_NR_waitid                (TARGET_NR_Linux + 237)
+/* #define TARGET_NR_sys_setaltroot     (TARGET_NR_Linux + 238) */
+#define TARGET_NR_add_key               (TARGET_NR_Linux + 239)
+#define TARGET_NR_request_key           (TARGET_NR_Linux + 240)
+#define TARGET_NR_keyctl                (TARGET_NR_Linux + 241)
+#define TARGET_NR_set_thread_area       (TARGET_NR_Linux + 242)
+#define TARGET_NR_inotify_init          (TARGET_NR_Linux + 243)
+#define TARGET_NR_inotify_add_watch     (TARGET_NR_Linux + 244)
+#define TARGET_NR_inotify_rm_watch      (TARGET_NR_Linux + 245)
+#define TARGET_NR_migrate_pages         (TARGET_NR_Linux + 246)
+#define TARGET_NR_openat                (TARGET_NR_Linux + 247)
+#define TARGET_NR_mkdirat               (TARGET_NR_Linux + 248)
+#define TARGET_NR_mknodat               (TARGET_NR_Linux + 249)
+#define TARGET_NR_fchownat              (TARGET_NR_Linux + 250)
+#define TARGET_NR_futimesat             (TARGET_NR_Linux + 251)
+#define TARGET_NR_newfstatat            (TARGET_NR_Linux + 252)
+#define TARGET_NR_unlinkat              (TARGET_NR_Linux + 253)
+#define TARGET_NR_renameat              (TARGET_NR_Linux + 254)
+#define TARGET_NR_linkat                (TARGET_NR_Linux + 255)
+#define TARGET_NR_symlinkat             (TARGET_NR_Linux + 256)
+#define TARGET_NR_readlinkat            (TARGET_NR_Linux + 257)
+#define TARGET_NR_fchmodat              (TARGET_NR_Linux + 258)
+#define TARGET_NR_faccessat             (TARGET_NR_Linux + 259)
+#define TARGET_NR_pselect6              (TARGET_NR_Linux + 260)
+#define TARGET_NR_ppoll                 (TARGET_NR_Linux + 261)
+#define TARGET_NR_unshare               (TARGET_NR_Linux + 262)
+#define TARGET_NR_splice                (TARGET_NR_Linux + 263)
+#define TARGET_NR_sync_file_range       (TARGET_NR_Linux + 264)
+#define TARGET_NR_tee                   (TARGET_NR_Linux + 265)
+#define TARGET_NR_vmsplice              (TARGET_NR_Linux + 266)
+#define TARGET_NR_move_pages            (TARGET_NR_Linux + 267)
+#define TARGET_NR_set_robust_list       (TARGET_NR_Linux + 268)
+#define TARGET_NR_get_robust_list       (TARGET_NR_Linux + 269)
+#define TARGET_NR_kexec_load            (TARGET_NR_Linux + 270)
+#define TARGET_NR_getcpu                (TARGET_NR_Linux + 271)
+#define TARGET_NR_epoll_pwait           (TARGET_NR_Linux + 272)
+#define TARGET_NR_ioprio_set            (TARGET_NR_Linux + 273)
+#define TARGET_NR_ioprio_get            (TARGET_NR_Linux + 274)
+#define TARGET_NR_utimensat             (TARGET_NR_Linux + 275)
+#define TARGET_NR_signalfd              (TARGET_NR_Linux + 276)
+#define TARGET_NR_timerfd               (TARGET_NR_Linux + 277)
+#define TARGET_NR_eventfd               (TARGET_NR_Linux + 278)
+#define TARGET_NR_fallocate             (TARGET_NR_Linux + 279)
+#define TARGET_NR_timerfd_create        (TARGET_NR_Linux + 280)
+#define TARGET_NR_timerfd_gettime       (TARGET_NR_Linux + 281)
+#define TARGET_NR_timerfd_settime       (TARGET_NR_Linux + 282)
+#define TARGET_NR_signalfd4             (TARGET_NR_Linux + 283)
+#define TARGET_NR_eventfd2              (TARGET_NR_Linux + 284)
+#define TARGET_NR_epoll_create1         (TARGET_NR_Linux + 285)
+#define TARGET_NR_dup3                  (TARGET_NR_Linux + 286)
+#define TARGET_NR_pipe2                 (TARGET_NR_Linux + 287)
+#define TARGET_NR_inotify_init1         (TARGET_NR_Linux + 288)
+#define TARGET_NR_preadv                (TARGET_NR_Linux + 289)
+#define TARGET_NR_pwritev               (TARGET_NR_Linux + 290)
+#define TARGET_NR_rt_tgsigqueueinfo     (TARGET_NR_Linux + 291)
+#define TARGET_NR_perf_event_open       (TARGET_NR_Linux + 292)
+#define TARGET_NR_accept4               (TARGET_NR_Linux + 293)
+#define TARGET_NR_recvmmsg              (TARGET_NR_Linux + 294)
+#define TARGET_NR_fanotify_init         (TARGET_NR_Linux + 295)
+#define TARGET_NR_fanotify_mark         (TARGET_NR_Linux + 296)
+#define TARGET_NR_prlimit64             (TARGET_NR_Linux + 297)
+#define TARGET_NR_name_to_handle_at     (TARGET_NR_Linux + 298)
+#define TARGET_NR_open_by_handle_at     (TARGET_NR_Linux + 299)
+#define TARGET_NR_clock_adjtime         (TARGET_NR_Linux + 300)
+#define TARGET_NR_syncfs                (TARGET_NR_Linux + 301)
+#endif
diff --git a/linux-user/mipsn32/syscall.h b/linux-user/mipsn32/syscall.h
deleted file mode 100644
index ebe98f2..0000000
--- a/linux-user/mipsn32/syscall.h
+++ /dev/null
@@ -1,224 +0,0 @@
-
-/* this struct defines the way the registers are stored on the
-   stack during a system call. */
-
-struct target_pt_regs {
-	/* Saved main processor registers. */
-	target_ulong regs[32];
-
-	/* Saved special registers. */
-	target_ulong cp0_status;
-	target_ulong lo;
-	target_ulong hi;
-	target_ulong cp0_badvaddr;
-	target_ulong cp0_cause;
-	target_ulong cp0_epc;
-};
-
-/* Target errno definitions taken from asm-mips/errno.h */
-#undef TARGET_ENOMSG
-#define TARGET_ENOMSG          35      /* Identifier removed */
-#undef TARGET_EIDRM
-#define TARGET_EIDRM           36      /* Identifier removed */
-#undef TARGET_ECHRNG
-#define TARGET_ECHRNG          37      /* Channel number out of range */
-#undef TARGET_EL2NSYNC
-#define TARGET_EL2NSYNC        38      /* Level 2 not synchronized */
-#undef TARGET_EL3HLT
-#define TARGET_EL3HLT          39      /* Level 3 halted */
-#undef TARGET_EL3RST
-#define TARGET_EL3RST          40      /* Level 3 reset */
-#undef TARGET_ELNRNG
-#define TARGET_ELNRNG          41      /* Link number out of range */
-#undef TARGET_EUNATCH
-#define TARGET_EUNATCH         42      /* Protocol driver not attached */
-#undef TARGET_ENOCSI
-#define TARGET_ENOCSI          43      /* No CSI structure available */
-#undef TARGET_EL2HLT
-#define TARGET_EL2HLT          44      /* Level 2 halted */
-#undef TARGET_EDEADLK
-#define TARGET_EDEADLK         45      /* Resource deadlock would occur */
-#undef TARGET_ENOLCK
-#define TARGET_ENOLCK          46      /* No record locks available */
-#undef TARGET_EBADE
-#define TARGET_EBADE           50      /* Invalid exchange */
-#undef TARGET_EBADR
-#define TARGET_EBADR           51      /* Invalid request descriptor */
-#undef TARGET_EXFULL
-#define TARGET_EXFULL          52      /* TARGET_Exchange full */
-#undef TARGET_ENOANO
-#define TARGET_ENOANO          53      /* No anode */
-#undef TARGET_EBADRQC
-#define TARGET_EBADRQC         54      /* Invalid request code */
-#undef TARGET_EBADSLT
-#define TARGET_EBADSLT         55      /* Invalid slot */
-#undef TARGET_EDEADLOCK
-#define TARGET_EDEADLOCK       56      /* File locking deadlock error */
-#undef TARGET_EBFONT
-#define TARGET_EBFONT          59      /* Bad font file format */
-#undef TARGET_ENOSTR
-#define TARGET_ENOSTR          60      /* Device not a stream */
-#undef TARGET_ENODATA
-#define TARGET_ENODATA         61      /* No data available */
-#undef TARGET_ETIME
-#define TARGET_ETIME           62      /* Timer expired */
-#undef TARGET_ENOSR
-#define TARGET_ENOSR           63      /* Out of streams resources */
-#undef TARGET_ENONET
-#define TARGET_ENONET          64      /* Machine is not on the network */
-#undef TARGET_ENOPKG
-#define TARGET_ENOPKG          65      /* Package not installed */
-#undef TARGET_EREMOTE
-#define TARGET_EREMOTE         66      /* Object is remote */
-#undef TARGET_ENOLINK
-#define TARGET_ENOLINK         67      /* Link has been severed */
-#undef TARGET_EADV
-#define TARGET_EADV            68      /* Advertise error */
-#undef TARGET_ESRMNT
-#define TARGET_ESRMNT          69      /* Srmount error */
-#undef TARGET_ECOMM
-#define TARGET_ECOMM           70      /* Communication error on send */
-#undef TARGET_EPROTO
-#define TARGET_EPROTO          71      /* Protocol error */
-#undef TARGET_EDOTDOT
-#define TARGET_EDOTDOT         73      /* RFS specific error */
-#undef TARGET_EMULTIHOP
-#define TARGET_EMULTIHOP       74      /* Multihop attempted */
-#undef TARGET_EBADMSG
-#define TARGET_EBADMSG         77      /* Not a data message */
-#undef TARGET_ENAMETOOLONG
-#define TARGET_ENAMETOOLONG    78      /* File name too long */
-#undef TARGET_EOVERFLOW
-#define TARGET_EOVERFLOW       79      /* Value too large for defined data type */
-#undef TARGET_ENOTUNIQ
-#define TARGET_ENOTUNIQ        80      /* Name not unique on network */
-#undef TARGET_EBADFD
-#define TARGET_EBADFD          81      /* File descriptor in bad state */
-#undef TARGET_EREMCHG
-#define TARGET_EREMCHG         82      /* Remote address changed */
-#undef TARGET_ELIBACC
-#define TARGET_ELIBACC         83      /* Can not access a needed shared library */
-#undef TARGET_ELIBBAD
-#define TARGET_ELIBBAD         84      /* Accessing a corrupted shared library */
-#undef TARGET_ELIBSCN
-#define TARGET_ELIBSCN         85      /* .lib section in a.out corrupted */
-#undef TARGET_ELIBMAX
-#define TARGET_ELIBMAX         86      /* Attempting to link in too many shared libraries */
-#undef TARGET_ELIBEXEC
-#define TARGET_ELIBEXEC        87      /* Cannot exec a shared library directly */
-#undef TARGET_EILSEQ
-#define TARGET_EILSEQ          88      /* Illegal byte sequence */
-#undef TARGET_ENOSYS
-#define TARGET_ENOSYS          89      /* Function not implemented */
-#undef TARGET_ELOOP
-#define TARGET_ELOOP           90      /* Too many symbolic links encountered */
-#undef TARGET_ERESTART
-#define TARGET_ERESTART        91      /* Interrupted system call should be restarted */
-#undef TARGET_ESTRPIPE
-#define TARGET_ESTRPIPE        92      /* Streams pipe error */
-#undef TARGET_ENOTEMPTY
-#define TARGET_ENOTEMPTY       93      /* Directory not empty */
-#undef TARGET_EUSERS
-#define TARGET_EUSERS          94      /* Too many users */
-#undef TARGET_ENOTSOCK
-#define TARGET_ENOTSOCK        95      /* Socket operation on non-socket */
-#undef TARGET_EDESTADDRREQ
-#define TARGET_EDESTADDRREQ    96      /* Destination address required */
-#undef TARGET_EMSGSIZE
-#define TARGET_EMSGSIZE        97      /* Message too long */
-#undef TARGET_EPROTOTYPE
-#define TARGET_EPROTOTYPE      98      /* Protocol wrong type for socket */
-#undef TARGET_ENOPROTOOPT
-#define TARGET_ENOPROTOOPT     99      /* Protocol not available */
-#undef TARGET_EPROTONOSUPPORT
-#define TARGET_EPROTONOSUPPORT 120     /* Protocol not supported */
-#undef TARGET_ESOCKTNOSUPPORT
-#define TARGET_ESOCKTNOSUPPORT 121     /* Socket type not supported */
-#undef TARGET_EOPNOTSUPP
-#define TARGET_EOPNOTSUPP      122     /* Operation not supported on transport endpoint */
-#undef TARGET_EPFNOSUPPORT
-#define TARGET_EPFNOSUPPORT    123     /* Protocol family not supported */
-#undef TARGET_EAFNOSUPPORT
-#define TARGET_EAFNOSUPPORT    124     /* Address family not supported by protocol */
-#undef TARGET_EADDRINUSE
-#define TARGET_EADDRINUSE      125     /* Address already in use */
-#undef TARGET_EADDRNOTAVAIL
-#define TARGET_EADDRNOTAVAIL   126     /* Cannot assign requested address */
-#undef TARGET_ENETDOWN
-#define TARGET_ENETDOWN        127     /* Network is down */
-#undef TARGET_ENETUNREACH
-#define TARGET_ENETUNREACH     128     /* Network is unreachable */
-#undef TARGET_ENETRESET
-#define TARGET_ENETRESET       129     /* Network dropped connection because of reset */
-#undef TARGET_ECONNABORTED
-#define TARGET_ECONNABORTED    130     /* Software caused connection abort */
-#undef TARGET_ECONNRESET
-#define TARGET_ECONNRESET      131     /* Connection reset by peer */
-#undef TARGET_ENOBUFS
-#define TARGET_ENOBUFS         132     /* No buffer space available */
-#undef TARGET_EISCONN
-#define TARGET_EISCONN         133     /* Transport endpoint is already connected */
-#undef TARGET_ENOTCONN
-#define TARGET_ENOTCONN        134     /* Transport endpoint is not connected */
-#undef TARGET_EUCLEAN
-#define TARGET_EUCLEAN         135     /* Structure needs cleaning */
-#undef TARGET_ENOTNAM
-#define TARGET_ENOTNAM         137     /* Not a XENIX named type file */
-#undef TARGET_ENAVAIL
-#define TARGET_ENAVAIL         138     /* No XENIX semaphores available */
-#undef TARGET_EISNAM
-#define TARGET_EISNAM          139     /* Is a named type file */
-#undef TARGET_EREMOTEIO
-#define TARGET_EREMOTEIO       140     /* Remote I/O error */
-#undef TARGET_EINIT
-#define TARGET_EINIT           141     /* Reserved */
-#undef TARGET_EREMDEV
-#define TARGET_EREMDEV         142     /* TARGET_Error 142 */
-#undef TARGET_ESHUTDOWN
-#define TARGET_ESHUTDOWN       143     /* Cannot send after transport endpoint shutdown */
-#undef TARGET_ETOOMANYREFS
-#define TARGET_ETOOMANYREFS    144     /* Too many references: cannot splice */
-#undef TARGET_ETIMEDOUT
-#define TARGET_ETIMEDOUT       145     /* Connection timed out */
-#undef TARGET_ECONNREFUSED
-#define TARGET_ECONNREFUSED    146     /* Connection refused */
-#undef TARGET_EHOSTDOWN
-#define TARGET_EHOSTDOWN       147     /* Host is down */
-#undef TARGET_EHOSTUNREACH
-#define TARGET_EHOSTUNREACH    148     /* No route to host */
-#undef TARGET_EALREADY
-#define TARGET_EALREADY        149     /* Operation already in progress */
-#undef TARGET_EINPROGRESS
-#define TARGET_EINPROGRESS     150     /* Operation now in progress */
-#undef TARGET_ESTALE
-#define TARGET_ESTALE          151     /* Stale NFS file handle */
-#undef TARGET_ECANCELED
-#define TARGET_ECANCELED       158     /* AIO operation canceled */
-/*
- * These error are Linux extensions.
- */
-#undef TARGET_ENOMEDIUM
-#define TARGET_ENOMEDIUM       159     /* No medium found */
-#undef TARGET_EMEDIUMTYPE
-#define TARGET_EMEDIUMTYPE     160     /* Wrong medium type */
-#undef TARGET_ENOKEY
-#define TARGET_ENOKEY          161     /* Required key not available */
-#undef TARGET_EKEYEXPIRED
-#define TARGET_EKEYEXPIRED     162     /* Key has expired */
-#undef TARGET_EKEYREVOKED
-#define TARGET_EKEYREVOKED     163     /* Key has been revoked */
-#undef TARGET_EKEYREJECTED
-#define TARGET_EKEYREJECTED    164     /* Key was rejected by service */
-
-/* for robust mutexes */
-#undef TARGET_EOWNERDEAD
-#define TARGET_EOWNERDEAD      165     /* Owner died */
-#undef TARGET_ENOTRECOVERABLE
-#define TARGET_ENOTRECOVERABLE 166     /* State not recoverable */
-
-
-
-/* Nasty hack: define a fake errno value for use by sigreturn. */
-#define TARGET_QEMU_ESIGRETURN 255
-
-#define UNAME_MACHINE "mips64"
diff --git a/linux-user/mipsn32/syscall_nr.h b/linux-user/mipsn32/syscall_nr.h
deleted file mode 100644
index 4e1aca3..0000000
--- a/linux-user/mipsn32/syscall_nr.h
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * Linux N32 syscalls are in the range from 6000 to 6999.
- */
-#define TARGET_NR_Linux			6000
-#define TARGET_NR_read			(TARGET_NR_Linux +   0)
-#define TARGET_NR_write			(TARGET_NR_Linux +   1)
-#define TARGET_NR_open			(TARGET_NR_Linux +   2)
-#define TARGET_NR_close			(TARGET_NR_Linux +   3)
-#define TARGET_NR_stat			(TARGET_NR_Linux +   4)
-#define TARGET_NR_fstat			(TARGET_NR_Linux +   5)
-#define TARGET_NR_lstat			(TARGET_NR_Linux +   6)
-#define TARGET_NR_poll			(TARGET_NR_Linux +   7)
-#define TARGET_NR_lseek			(TARGET_NR_Linux +   8)
-#define TARGET_NR_mmap			(TARGET_NR_Linux +   9)
-#define TARGET_NR_mprotect			(TARGET_NR_Linux +  10)
-#define TARGET_NR_munmap			(TARGET_NR_Linux +  11)
-#define TARGET_NR_brk			(TARGET_NR_Linux +  12)
-#define TARGET_NR_rt_sigaction		(TARGET_NR_Linux +  13)
-#define TARGET_NR_rt_sigprocmask		(TARGET_NR_Linux +  14)
-#define TARGET_NR_ioctl			(TARGET_NR_Linux +  15)
-#define TARGET_NR_pread64			(TARGET_NR_Linux +  16)
-#define TARGET_NR_pwrite64			(TARGET_NR_Linux +  17)
-#define TARGET_NR_readv			(TARGET_NR_Linux +  18)
-#define TARGET_NR_writev			(TARGET_NR_Linux +  19)
-#define TARGET_NR_access			(TARGET_NR_Linux +  20)
-#define TARGET_NR_pipe			(TARGET_NR_Linux +  21)
-#define TARGET_NR__newselect			(TARGET_NR_Linux +  22)
-#define TARGET_NR_sched_yield		(TARGET_NR_Linux +  23)
-#define TARGET_NR_mremap			(TARGET_NR_Linux +  24)
-#define TARGET_NR_msync			(TARGET_NR_Linux +  25)
-#define TARGET_NR_mincore			(TARGET_NR_Linux +  26)
-#define TARGET_NR_madvise			(TARGET_NR_Linux +  27)
-#define TARGET_NR_shmget			(TARGET_NR_Linux +  28)
-#define TARGET_NR_shmat			(TARGET_NR_Linux +  29)
-#define TARGET_NR_shmctl			(TARGET_NR_Linux +  30)
-#define TARGET_NR_dup			(TARGET_NR_Linux +  31)
-#define TARGET_NR_dup2			(TARGET_NR_Linux +  32)
-#define TARGET_NR_pause			(TARGET_NR_Linux +  33)
-#define TARGET_NR_nanosleep			(TARGET_NR_Linux +  34)
-#define TARGET_NR_getitimer			(TARGET_NR_Linux +  35)
-#define TARGET_NR_setitimer			(TARGET_NR_Linux +  36)
-#define TARGET_NR_alarm			(TARGET_NR_Linux +  37)
-#define TARGET_NR_getpid			(TARGET_NR_Linux +  38)
-#define TARGET_NR_sendfile			(TARGET_NR_Linux +  39)
-#define TARGET_NR_socket			(TARGET_NR_Linux +  40)
-#define TARGET_NR_connect			(TARGET_NR_Linux +  41)
-#define TARGET_NR_accept			(TARGET_NR_Linux +  42)
-#define TARGET_NR_sendto			(TARGET_NR_Linux +  43)
-#define TARGET_NR_recvfrom			(TARGET_NR_Linux +  44)
-#define TARGET_NR_sendmsg			(TARGET_NR_Linux +  45)
-#define TARGET_NR_recvmsg			(TARGET_NR_Linux +  46)
-#define TARGET_NR_shutdown			(TARGET_NR_Linux +  47)
-#define TARGET_NR_bind			(TARGET_NR_Linux +  48)
-#define TARGET_NR_listen			(TARGET_NR_Linux +  49)
-#define TARGET_NR_getsockname		(TARGET_NR_Linux +  50)
-#define TARGET_NR_getpeername		(TARGET_NR_Linux +  51)
-#define TARGET_NR_socketpair			(TARGET_NR_Linux +  52)
-#define TARGET_NR_setsockopt			(TARGET_NR_Linux +  53)
-#define TARGET_NR_getsockopt			(TARGET_NR_Linux +  54)
-#define TARGET_NR_clone			(TARGET_NR_Linux +  55)
-#define TARGET_NR_fork			(TARGET_NR_Linux +  56)
-#define TARGET_NR_execve			(TARGET_NR_Linux +  57)
-#define TARGET_NR_exit			(TARGET_NR_Linux +  58)
-#define TARGET_NR_wait4			(TARGET_NR_Linux +  59)
-#define TARGET_NR_kill			(TARGET_NR_Linux +  60)
-#define TARGET_NR_uname			(TARGET_NR_Linux +  61)
-#define TARGET_NR_semget			(TARGET_NR_Linux +  62)
-#define TARGET_NR_semop			(TARGET_NR_Linux +  63)
-#define TARGET_NR_semctl			(TARGET_NR_Linux +  64)
-#define TARGET_NR_shmdt			(TARGET_NR_Linux +  65)
-#define TARGET_NR_msgget			(TARGET_NR_Linux +  66)
-#define TARGET_NR_msgsnd			(TARGET_NR_Linux +  67)
-#define TARGET_NR_msgrcv			(TARGET_NR_Linux +  68)
-#define TARGET_NR_msgctl			(TARGET_NR_Linux +  69)
-#define TARGET_NR_fcntl			(TARGET_NR_Linux +  70)
-#define TARGET_NR_flock			(TARGET_NR_Linux +  71)
-#define TARGET_NR_fsync			(TARGET_NR_Linux +  72)
-#define TARGET_NR_fdatasync			(TARGET_NR_Linux +  73)
-#define TARGET_NR_truncate			(TARGET_NR_Linux +  74)
-#define TARGET_NR_ftruncate			(TARGET_NR_Linux +  75)
-#define TARGET_NR_getdents			(TARGET_NR_Linux +  76)
-#define TARGET_NR_getcwd			(TARGET_NR_Linux +  77)
-#define TARGET_NR_chdir			(TARGET_NR_Linux +  78)
-#define TARGET_NR_fchdir			(TARGET_NR_Linux +  79)
-#define TARGET_NR_rename			(TARGET_NR_Linux +  80)
-#define TARGET_NR_mkdir			(TARGET_NR_Linux +  81)
-#define TARGET_NR_rmdir			(TARGET_NR_Linux +  82)
-#define TARGET_NR_creat			(TARGET_NR_Linux +  83)
-#define TARGET_NR_link			(TARGET_NR_Linux +  84)
-#define TARGET_NR_unlink			(TARGET_NR_Linux +  85)
-#define TARGET_NR_symlink			(TARGET_NR_Linux +  86)
-#define TARGET_NR_readlink			(TARGET_NR_Linux +  87)
-#define TARGET_NR_chmod			(TARGET_NR_Linux +  88)
-#define TARGET_NR_fchmod			(TARGET_NR_Linux +  89)
-#define TARGET_NR_chown			(TARGET_NR_Linux +  90)
-#define TARGET_NR_fchown			(TARGET_NR_Linux +  91)
-#define TARGET_NR_lchown			(TARGET_NR_Linux +  92)
-#define TARGET_NR_umask			(TARGET_NR_Linux +  93)
-#define TARGET_NR_gettimeofday		(TARGET_NR_Linux +  94)
-#define TARGET_NR_getrlimit			(TARGET_NR_Linux +  95)
-#define TARGET_NR_getrusage			(TARGET_NR_Linux +  96)
-#define TARGET_NR_sysinfo			(TARGET_NR_Linux +  97)
-#define TARGET_NR_times			(TARGET_NR_Linux +  98)
-#define TARGET_NR_ptrace			(TARGET_NR_Linux +  99)
-#define TARGET_NR_getuid			(TARGET_NR_Linux + 100)
-#define TARGET_NR_syslog			(TARGET_NR_Linux + 101)
-#define TARGET_NR_getgid			(TARGET_NR_Linux + 102)
-#define TARGET_NR_setuid			(TARGET_NR_Linux + 103)
-#define TARGET_NR_setgid			(TARGET_NR_Linux + 104)
-#define TARGET_NR_geteuid			(TARGET_NR_Linux + 105)
-#define TARGET_NR_getegid			(TARGET_NR_Linux + 106)
-#define TARGET_NR_setpgid			(TARGET_NR_Linux + 107)
-#define TARGET_NR_getppid			(TARGET_NR_Linux + 108)
-#define TARGET_NR_getpgrp			(TARGET_NR_Linux + 109)
-#define TARGET_NR_setsid			(TARGET_NR_Linux + 110)
-#define TARGET_NR_setreuid			(TARGET_NR_Linux + 111)
-#define TARGET_NR_setregid			(TARGET_NR_Linux + 112)
-#define TARGET_NR_getgroups			(TARGET_NR_Linux + 113)
-#define TARGET_NR_setgroups			(TARGET_NR_Linux + 114)
-#define TARGET_NR_setresuid			(TARGET_NR_Linux + 115)
-#define TARGET_NR_getresuid			(TARGET_NR_Linux + 116)
-#define TARGET_NR_setresgid			(TARGET_NR_Linux + 117)
-#define TARGET_NR_getresgid			(TARGET_NR_Linux + 118)
-#define TARGET_NR_getpgid			(TARGET_NR_Linux + 119)
-#define TARGET_NR_setfsuid			(TARGET_NR_Linux + 120)
-#define TARGET_NR_setfsgid			(TARGET_NR_Linux + 121)
-#define TARGET_NR_getsid			(TARGET_NR_Linux + 122)
-#define TARGET_NR_capget			(TARGET_NR_Linux + 123)
-#define TARGET_NR_capset			(TARGET_NR_Linux + 124)
-#define TARGET_NR_rt_sigpending		(TARGET_NR_Linux + 125)
-#define TARGET_NR_rt_sigtimedwait		(TARGET_NR_Linux + 126)
-#define TARGET_NR_rt_sigqueueinfo		(TARGET_NR_Linux + 127)
-#define TARGET_NR_rt_sigsuspend		(TARGET_NR_Linux + 128)
-#define TARGET_NR_sigaltstack		(TARGET_NR_Linux + 129)
-#define TARGET_NR_utime			(TARGET_NR_Linux + 130)
-#define TARGET_NR_mknod			(TARGET_NR_Linux + 131)
-#define TARGET_NR_personality		(TARGET_NR_Linux + 132)
-#define TARGET_NR_ustat			(TARGET_NR_Linux + 133)
-#define TARGET_NR_statfs			(TARGET_NR_Linux + 134)
-#define TARGET_NR_fstatfs			(TARGET_NR_Linux + 135)
-#define TARGET_NR_sysfs			(TARGET_NR_Linux + 136)
-#define TARGET_NR_getpriority		(TARGET_NR_Linux + 137)
-#define TARGET_NR_setpriority		(TARGET_NR_Linux + 138)
-#define TARGET_NR_sched_setparam		(TARGET_NR_Linux + 139)
-#define TARGET_NR_sched_getparam		(TARGET_NR_Linux + 140)
-#define TARGET_NR_sched_setscheduler		(TARGET_NR_Linux + 141)
-#define TARGET_NR_sched_getscheduler		(TARGET_NR_Linux + 142)
-#define TARGET_NR_sched_get_priority_max	(TARGET_NR_Linux + 143)
-#define TARGET_NR_sched_get_priority_min	(TARGET_NR_Linux + 144)
-#define TARGET_NR_sched_rr_get_interval	(TARGET_NR_Linux + 145)
-#define TARGET_NR_mlock			(TARGET_NR_Linux + 146)
-#define TARGET_NR_munlock			(TARGET_NR_Linux + 147)
-#define TARGET_NR_mlockall			(TARGET_NR_Linux + 148)
-#define TARGET_NR_munlockall			(TARGET_NR_Linux + 149)
-#define TARGET_NR_vhangup			(TARGET_NR_Linux + 150)
-#define TARGET_NR_pivot_root			(TARGET_NR_Linux + 151)
-#define TARGET_NR__sysctl			(TARGET_NR_Linux + 152)
-#define TARGET_NR_prctl			(TARGET_NR_Linux + 153)
-#define TARGET_NR_adjtimex			(TARGET_NR_Linux + 154)
-#define TARGET_NR_setrlimit			(TARGET_NR_Linux + 155)
-#define TARGET_NR_chroot			(TARGET_NR_Linux + 156)
-#define TARGET_NR_sync			(TARGET_NR_Linux + 157)
-#define TARGET_NR_acct			(TARGET_NR_Linux + 158)
-#define TARGET_NR_settimeofday		(TARGET_NR_Linux + 159)
-#define TARGET_NR_mount			(TARGET_NR_Linux + 160)
-#define TARGET_NR_umount2			(TARGET_NR_Linux + 161)
-#define TARGET_NR_swapon			(TARGET_NR_Linux + 162)
-#define TARGET_NR_swapoff			(TARGET_NR_Linux + 163)
-#define TARGET_NR_reboot			(TARGET_NR_Linux + 164)
-#define TARGET_NR_sethostname		(TARGET_NR_Linux + 165)
-#define TARGET_NR_setdomainname		(TARGET_NR_Linux + 166)
-#define TARGET_NR_create_module		(TARGET_NR_Linux + 167)
-#define TARGET_NR_init_module		(TARGET_NR_Linux + 168)
-#define TARGET_NR_delete_module		(TARGET_NR_Linux + 169)
-#define TARGET_NR_get_kernel_syms		(TARGET_NR_Linux + 170)
-#define TARGET_NR_query_module		(TARGET_NR_Linux + 171)
-#define TARGET_NR_quotactl			(TARGET_NR_Linux + 172)
-#define TARGET_NR_nfsservctl			(TARGET_NR_Linux + 173)
-#define TARGET_NR_getpmsg			(TARGET_NR_Linux + 174)
-#define TARGET_NR_putpmsg			(TARGET_NR_Linux + 175)
-#define TARGET_NR_afs_syscall		(TARGET_NR_Linux + 176)
-#define TARGET_NR_reserved177		(TARGET_NR_Linux + 177)
-#define TARGET_NR_gettid			(TARGET_NR_Linux + 178)
-#define TARGET_NR_readahead			(TARGET_NR_Linux + 179)
-#define TARGET_NR_setxattr			(TARGET_NR_Linux + 180)
-#define TARGET_NR_lsetxattr			(TARGET_NR_Linux + 181)
-#define TARGET_NR_fsetxattr			(TARGET_NR_Linux + 182)
-#define TARGET_NR_getxattr			(TARGET_NR_Linux + 183)
-#define TARGET_NR_lgetxattr			(TARGET_NR_Linux + 184)
-#define TARGET_NR_fgetxattr			(TARGET_NR_Linux + 185)
-#define TARGET_NR_listxattr			(TARGET_NR_Linux + 186)
-#define TARGET_NR_llistxattr			(TARGET_NR_Linux + 187)
-#define TARGET_NR_flistxattr			(TARGET_NR_Linux + 188)
-#define TARGET_NR_removexattr		(TARGET_NR_Linux + 189)
-#define TARGET_NR_lremovexattr		(TARGET_NR_Linux + 190)
-#define TARGET_NR_fremovexattr		(TARGET_NR_Linux + 191)
-#define TARGET_NR_tkill			(TARGET_NR_Linux + 192)
-#define TARGET_NR_reserved193		(TARGET_NR_Linux + 193)
-#define TARGET_NR_futex			(TARGET_NR_Linux + 194)
-#define TARGET_NR_sched_setaffinity		(TARGET_NR_Linux + 195)
-#define TARGET_NR_sched_getaffinity		(TARGET_NR_Linux + 196)
-#define TARGET_NR_cacheflush			(TARGET_NR_Linux + 197)
-#define TARGET_NR_cachectl			(TARGET_NR_Linux + 198)
-#define TARGET_NR_sysmips			(TARGET_NR_Linux + 199)
-#define TARGET_NR_io_setup			(TARGET_NR_Linux + 200)
-#define TARGET_NR_io_destroy			(TARGET_NR_Linux + 201)
-#define TARGET_NR_io_getevents		(TARGET_NR_Linux + 202)
-#define TARGET_NR_io_submit			(TARGET_NR_Linux + 203)
-#define TARGET_NR_io_cancel			(TARGET_NR_Linux + 204)
-#define TARGET_NR_exit_group			(TARGET_NR_Linux + 205)
-#define TARGET_NR_lookup_dcookie		(TARGET_NR_Linux + 206)
-#define TARGET_NR_epoll_create		(TARGET_NR_Linux + 207)
-#define TARGET_NR_epoll_ctl			(TARGET_NR_Linux + 208)
-#define TARGET_NR_epoll_wait			(TARGET_NR_Linux + 209)
-#define TARGET_NR_remap_file_pages		(TARGET_NR_Linux + 210)
-#define TARGET_NR_rt_sigreturn		(TARGET_NR_Linux + 211)
-#define TARGET_NR_fcntl64			(TARGET_NR_Linux + 212)
-#define TARGET_NR_set_tid_address		(TARGET_NR_Linux + 213)
-#define TARGET_NR_restart_syscall		(TARGET_NR_Linux + 214)
-#define TARGET_NR_semtimedop			(TARGET_NR_Linux + 215)
-#define TARGET_NR_fadvise64			(TARGET_NR_Linux + 216)
-#define TARGET_NR_statfs64			(TARGET_NR_Linux + 217)
-#define TARGET_NR_fstatfs64			(TARGET_NR_Linux + 218)
-#define TARGET_NR_sendfile64			(TARGET_NR_Linux + 219)
-#define TARGET_NR_timer_create		(TARGET_NR_Linux + 220)
-#define TARGET_NR_timer_settime		(TARGET_NR_Linux + 221)
-#define TARGET_NR_timer_gettime		(TARGET_NR_Linux + 222)
-#define TARGET_NR_timer_getoverrun		(TARGET_NR_Linux + 223)
-#define TARGET_NR_timer_delete		(TARGET_NR_Linux + 224)
-#define TARGET_NR_clock_settime		(TARGET_NR_Linux + 225)
-#define TARGET_NR_clock_gettime		(TARGET_NR_Linux + 226)
-#define TARGET_NR_clock_getres		(TARGET_NR_Linux + 227)
-#define TARGET_NR_clock_nanosleep		(TARGET_NR_Linux + 228)
-#define TARGET_NR_tgkill			(TARGET_NR_Linux + 229)
-#define TARGET_NR_utimes			(TARGET_NR_Linux + 230)
-#define TARGET_NR_mbind			(TARGET_NR_Linux + 231)
-#define TARGET_NR_get_mempolicy		(TARGET_NR_Linux + 232)
-#define TARGET_NR_set_mempolicy		(TARGET_NR_Linux + 233)
-#define TARGET_NR_mq_open			(TARGET_NR_Linux + 234)
-#define TARGET_NR_mq_unlink			(TARGET_NR_Linux + 235)
-#define TARGET_NR_mq_timedsend		(TARGET_NR_Linux + 236)
-#define TARGET_NR_mq_timedreceive		(TARGET_NR_Linux + 237)
-#define TARGET_NR_mq_notify			(TARGET_NR_Linux + 238)
-#define TARGET_NR_mq_getsetattr		(TARGET_NR_Linux + 239)
-#define TARGET_NR_vserver			(TARGET_NR_Linux + 240)
-#define TARGET_NR_waitid			(TARGET_NR_Linux + 241)
-/* #define TARGET_NR_sys_setaltroot		(TARGET_NR_Linux + 242) */
-#define TARGET_NR_add_key			(TARGET_NR_Linux + 243)
-#define TARGET_NR_request_key		(TARGET_NR_Linux + 244)
-#define TARGET_NR_keyctl			(TARGET_NR_Linux + 245)
-#define TARGET_NR_set_thread_area		(TARGET_NR_Linux + 246)
-#define TARGET_NR_inotify_init		(TARGET_NR_Linux + 247)
-#define TARGET_NR_inotify_add_watch		(TARGET_NR_Linux + 248)
-#define TARGET_NR_inotify_rm_watch		(TARGET_NR_Linux + 249)
-#define TARGET_NR_migrate_pages		(TARGET_NR_Linux + 250)
-#define TARGET_NR_openat			(TARGET_NR_Linux + 251)
-#define TARGET_NR_mkdirat			(TARGET_NR_Linux + 252)
-#define TARGET_NR_mknodat			(TARGET_NR_Linux + 253)
-#define TARGET_NR_fchownat			(TARGET_NR_Linux + 254)
-#define TARGET_NR_futimesat			(TARGET_NR_Linux + 255)
-#define TARGET_NR_newfstatat			(TARGET_NR_Linux + 256)
-#define TARGET_NR_unlinkat			(TARGET_NR_Linux + 257)
-#define TARGET_NR_renameat			(TARGET_NR_Linux + 258)
-#define TARGET_NR_linkat			(TARGET_NR_Linux + 259)
-#define TARGET_NR_symlinkat			(TARGET_NR_Linux + 260)
-#define TARGET_NR_readlinkat			(TARGET_NR_Linux + 261)
-#define TARGET_NR_fchmodat			(TARGET_NR_Linux + 262)
-#define TARGET_NR_faccessat			(TARGET_NR_Linux + 263)
-#define TARGET_NR_pselect6			(TARGET_NR_Linux + 264)
-#define TARGET_NR_ppoll			(TARGET_NR_Linux + 265)
-#define TARGET_NR_unshare			(TARGET_NR_Linux + 266)
-#define TARGET_NR_splice			(TARGET_NR_Linux + 267)
-#define TARGET_NR_sync_file_range		(TARGET_NR_Linux + 268)
-#define TARGET_NR_tee			(TARGET_NR_Linux + 269)
-#define TARGET_NR_vmsplice			(TARGET_NR_Linux + 270)
-#define TARGET_NR_move_pages			(TARGET_NR_Linux + 271)
-#define TARGET_NR_set_robust_list		(TARGET_NR_Linux + 272)
-#define TARGET_NR_get_robust_list		(TARGET_NR_Linux + 273)
-#define TARGET_NR_kexec_load			(TARGET_NR_Linux + 274)
-#define TARGET_NR_getcpu			(TARGET_NR_Linux + 275)
-#define TARGET_NR_epoll_pwait		(TARGET_NR_Linux + 276)
-#define TARGET_NR_ioprio_set			(TARGET_NR_Linux + 277)
-#define TARGET_NR_ioprio_get			(TARGET_NR_Linux + 278)
-#define TARGET_NR_utimensat			(TARGET_NR_Linux + 279)
-#define TARGET_NR_signalfd			(TARGET_NR_Linux + 280)
-#define TARGET_NR_timerfd			(TARGET_NR_Linux + 281)
-#define TARGET_NR_eventfd			(TARGET_NR_Linux + 282)
-#define TARGET_NR_fallocate			(TARGET_NR_Linux + 283)
-#define TARGET_NR_timerfd_create		(TARGET_NR_Linux + 284)
-#define TARGET_NR_timerfd_gettime		(TARGET_NR_Linux + 285)
-#define TARGET_NR_timerfd_settime		(TARGET_NR_Linux + 286)
-#define TARGET_NR_signalfd4			(TARGET_NR_Linux + 287)
-#define TARGET_NR_eventfd2			(TARGET_NR_Linux + 288)
-#define TARGET_NR_epoll_create1		(TARGET_NR_Linux + 289)
-#define TARGET_NR_dup3				(TARGET_NR_Linux + 290)
-#define TARGET_NR_pipe2			(TARGET_NR_Linux + 291)
-#define TARGET_NR_inotify_init1		(TARGET_NR_Linux + 292)
-#define TARGET_NR_preadv                        (TARGET_NR_Linux + 293)
-#define TARGET_NR_pwritev                       (TARGET_NR_Linux + 294)
-#define TARGET_NR_rt_tgsigqueueinfo             (TARGET_NR_Linux + 295)
-#define TARGET_NR_perf_event_open               (TARGET_NR_Linux + 296)
-#define TARGET_NR_accept4                       (TARGET_NR_Linux + 297)
-#define TARGET_NR_recvmmsg                      (TARGET_NR_Linux + 298)
-#define TARGET_NR_getdents64                    (TARGET_NR_Linux + 299)
-#define TARGET_NR_fanotify_init                 (TARGET_NR_Linux + 300)
-#define TARGET_NR_fanotify_mark                 (TARGET_NR_Linux + 301)
-#define TARGET_NR_prlimit64                     (TARGET_NR_Linux + 302)
-#define TARGET_NR_name_to_handle_at             (TARGET_NR_Linux + 303)
-#define TARGET_NR_open_by_handle_at             (TARGET_NR_Linux + 304)
-#define TARGET_NR_clock_adjtime                 (TARGET_NR_Linux + 305)
-#define TARGET_NR_syncfs                        (TARGET_NR_Linux + 306)
diff --git a/linux-user/mipsn32/target_signal.h b/linux-user/mipsn32/target_signal.h
deleted file mode 100644
index ff20d9e..0000000
--- a/linux-user/mipsn32/target_signal.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef TARGET_SIGNAL_H
-#define TARGET_SIGNAL_H
-
-#include "cpu.h"
-
-/* this struct defines a stack used during syscall handling */
-
-typedef struct target_sigaltstack {
-	int32_t ss_sp;
-	uint32_t ss_size;
-	int32_t ss_flags;
-} target_stack_t;
-
-
-/*
- * sigaltstack controls
- */
-#define TARGET_SS_ONSTACK     1
-#define TARGET_SS_DISABLE     2
-
-#define TARGET_MINSIGSTKSZ    2048
-#define TARGET_SIGSTKSZ       8192
-
-static inline target_ulong get_sp_from_cpustate(CPUMIPSState *state)
-{
-    return state->active_tc.gpr[29];
-}
-
-#endif /* TARGET_SIGNAL_H */
diff --git a/linux-user/mipsn32/termbits.h b/linux-user/mipsn32/termbits.h
deleted file mode 100644
index d3a6cf8..0000000
--- a/linux-user/mipsn32/termbits.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/* from asm/termbits.h */
-
-#define TARGET_NCCS 23
-
-struct target_termios {
-    unsigned int c_iflag;               /* input mode flags */
-    unsigned int c_oflag;               /* output mode flags */
-    unsigned int c_cflag;               /* control mode flags */
-    unsigned int c_lflag;               /* local mode flags */
-    unsigned char c_line;                    /* line discipline */
-    unsigned char c_cc[TARGET_NCCS];                /* control characters */
-};
-
-/* c_iflag bits */
-#define TARGET_IGNBRK  0000001
-#define TARGET_BRKINT  0000002
-#define TARGET_IGNPAR  0000004
-#define TARGET_PARMRK  0000010
-#define TARGET_INPCK   0000020
-#define TARGET_ISTRIP  0000040
-#define TARGET_INLCR   0000100
-#define TARGET_IGNCR   0000200
-#define TARGET_ICRNL   0000400
-#define TARGET_IUCLC   0001000
-#define TARGET_IXON    0002000
-#define TARGET_IXANY   0004000
-#define TARGET_IXOFF   0010000
-#define TARGET_IMAXBEL 0020000
-#define TARGET_IUTF8   0040000
-
-/* c_oflag bits */
-#define TARGET_OPOST   0000001
-#define TARGET_OLCUC   0000002
-#define TARGET_ONLCR   0000004
-#define TARGET_OCRNL   0000010
-#define TARGET_ONOCR   0000020
-#define TARGET_ONLRET  0000040
-#define TARGET_OFILL   0000100
-#define TARGET_OFDEL   0000200
-#define TARGET_NLDLY   0000400
-#define   TARGET_NL0   0000000
-#define   TARGET_NL1   0000400
-#define TARGET_CRDLY   0003000
-#define   TARGET_CR0   0000000
-#define   TARGET_CR1   0001000
-#define   TARGET_CR2   0002000
-#define   TARGET_CR3   0003000
-#define TARGET_TABDLY  0014000
-#define   TARGET_TAB0  0000000
-#define   TARGET_TAB1  0004000
-#define   TARGET_TAB2  0010000
-#define   TARGET_TAB3  0014000
-#define   TARGET_XTABS 0014000
-#define TARGET_BSDLY   0020000
-#define   TARGET_BS0   0000000
-#define   TARGET_BS1   0020000
-#define TARGET_VTDLY   0040000
-#define   TARGET_VT0   0000000
-#define   TARGET_VT1   0040000
-#define TARGET_FFDLY   0100000
-#define   TARGET_FF0   0000000
-#define   TARGET_FF1   0100000
-
-/* c_cflag bit meaning */
-#define TARGET_CBAUD   0010017
-#define  TARGET_B0     0000000         /* hang up */
-#define  TARGET_B50    0000001
-#define  TARGET_B75    0000002
-#define  TARGET_B110   0000003
-#define  TARGET_B134   0000004
-#define  TARGET_B150   0000005
-#define  TARGET_B200   0000006
-#define  TARGET_B300   0000007
-#define  TARGET_B600   0000010
-#define  TARGET_B1200  0000011
-#define  TARGET_B1800  0000012
-#define  TARGET_B2400  0000013
-#define  TARGET_B4800  0000014
-#define  TARGET_B9600  0000015
-#define  TARGET_B19200 0000016
-#define  TARGET_B38400 0000017
-#define TARGET_EXTA B19200
-#define TARGET_EXTB B38400
-#define TARGET_CSIZE   0000060
-#define   TARGET_CS5   0000000
-#define   TARGET_CS6   0000020
-#define   TARGET_CS7   0000040
-#define   TARGET_CS8   0000060
-#define TARGET_CSTOPB  0000100
-#define TARGET_CREAD   0000200
-#define TARGET_PARENB  0000400
-#define TARGET_PARODD  0001000
-#define TARGET_HUPCL   0002000
-#define TARGET_CLOCAL  0004000
-#define TARGET_CBAUDEX 0010000
-#define  TARGET_BOTHER   0010000
-#define  TARGET_B57600   0010001
-#define  TARGET_B115200  0010002
-#define  TARGET_B230400  0010003
-#define  TARGET_B460800  0010004
-#define  TARGET_B500000  0010005
-#define  TARGET_B576000  0010006
-#define  TARGET_B921600  0010007
-#define  TARGET_B1000000 0010010
-#define  TARGET_B1152000 0010011
-#define  TARGET_B1500000 0010012
-#define  TARGET_B2000000 0010013
-#define  TARGET_B2500000 0010014
-#define  TARGET_B3000000 0010015
-#define  TARGET_B3500000 0010016
-#define  TARGET_B4000000 0010017
-#define TARGET_CIBAUD    002003600000  /* input baud rate (not used) */
-#define TARGET_CMSPAR    010000000000  /* mark or space (stick) parity */
-#define TARGET_CRTSCTS   020000000000  /* flow control */
-
-/* c_lflag bits */
-#define TARGET_ISIG    0000001
-#define TARGET_ICANON  0000002
-#define TARGET_XCASE   0000004
-#define TARGET_ECHO    0000010
-#define TARGET_ECHOE   0000020
-#define TARGET_ECHOK   0000040
-#define TARGET_ECHONL  0000100
-#define TARGET_NOFLSH  0000200
-#define TARGET_IEXTEN  0000400
-#define TARGET_ECHOCTL 0001000
-#define TARGET_ECHOPRT 0002000
-#define TARGET_ECHOKE  0004000
-#define TARGET_FLUSHO  0010000
-#define TARGET_PENDIN  0040000
-#define TARGET_TOSTOP  0100000
-#define TARGET_ITOSTOP TARGET_TOSTOP
-
-/* c_cc character offsets */
-#define TARGET_VINTR	0
-#define TARGET_VQUIT	1
-#define TARGET_VERASE	2
-#define TARGET_VKILL	3
-#define TARGET_VMIN	4
-#define TARGET_VTIME	5
-#define TARGET_VEOL2	6
-#define TARGET_VSWTC	7
-#define TARGET_VSTART	8
-#define TARGET_VSTOP	9
-#define TARGET_VSUSP	10
-/* VDSUSP not supported */
-#define TARGET_VREPRINT	12
-#define TARGET_VDISCARD	13
-#define TARGET_VWERASE	14
-#define TARGET_VLNEXT	15
-#define TARGET_VEOF	16
-#define TARGET_VEOL	17
-
-/* ioctls */
-
-#define TARGET_TCGETA		0x5401
-#define TARGET_TCSETA		0x5402	/* Clashes with SNDCTL_TMR_START sound ioctl */
-#define TARGET_TCSETAW		0x5403
-#define TARGET_TCSETAF		0x5404
-
-#define TARGET_TCSBRK		0x5405
-#define TARGET_TCXONC		0x5406
-#define TARGET_TCFLSH		0x5407
-
-#define TARGET_TCGETS		0x540d
-#define TARGET_TCSETS		0x540e
-#define TARGET_TCSETSW		0x540f
-#define TARGET_TCSETSF		0x5410
-
-#define TARGET_TIOCEXCL	0x740d		/* set exclusive use of tty */
-#define TARGET_TIOCNXCL	0x740e		/* reset exclusive use of tty */
-#define TARGET_TIOCOUTQ	0x7472		/* output queue size */
-#define TARGET_TIOCSTI	0x5472		/* simulate terminal input */
-#define TARGET_TIOCMGET	0x741d		/* get all modem bits */
-#define TARGET_TIOCMBIS	0x741b		/* bis modem bits */
-#define TARGET_TIOCMBIC	0x741c		/* bic modem bits */
-#define TARGET_TIOCMSET	0x741a		/* set all modem bits */
-#define TARGET_TIOCPKT		0x5470		/* pty: set/clear packet mode */
-#define	 TARGET_TIOCPKT_DATA		0x00	/* data packet */
-#define	 TARGET_TIOCPKT_FLUSHREAD	0x01	/* flush packet */
-#define	 TARGET_TIOCPKT_FLUSHWRITE	0x02	/* flush packet */
-#define	 TARGET_TIOCPKT_STOP		0x04	/* stop output */
-#define	 TARGET_TIOCPKT_START		0x08	/* start output */
-#define	 TARGET_TIOCPKT_NOSTOP		0x10	/* no more ^S, ^Q */
-#define	 TARGET_TIOCPKT_DOSTOP		0x20	/* now do ^S ^Q */
-/* #define  TIOCPKT_IOCTL		0x40	state change of pty driver */
-#define TARGET_TIOCSWINSZ	TARGET_IOW('t', 103, struct winsize)	/* set window size */
-#define TARGET_TIOCGWINSZ	TARGET_IOR('t', 104, struct winsize)	/* get window size */
-#define TARGET_TIOCNOTTY	0x5471		/* void tty association */
-#define TARGET_TIOCSETD	0x7401
-#define TARGET_TIOCGETD	0x7400
-
-#define TARGET_FIOCLEX		0x6601
-#define TARGET_FIONCLEX	0x6602
-#define TARGET_FIOASYNC	0x667d
-#define TARGET_FIONBIO		0x667e
-#define TARGET_FIOQSIZE	0x667f
-
-#define TARGET_TIOCGLTC	0x7474			/* get special local chars */
-#define TARGET_TIOCSLTC	0x7475			/* set special local chars */
-#define TARGET_TIOCSPGRP	TARGET_IOW('t', 118, int)	/* set pgrp of tty */
-#define TARGET_TIOCGPGRP	TARGET_IOR('t', 119, int)	/* get pgrp of tty */
-#define TARGET_TIOCCONS	TARGET_IOW('t', 120, int)	/* become virtual console */
-
-#define TARGET_FIONREAD	0x467f
-#define TARGET_TIOCINQ		TARGET_FIONREAD
-
-#define TARGET_TIOCGETP        0x7408
-#define TARGET_TIOCSETP        0x7409
-#define TARGET_TIOCSETN        0x740a			/* TIOCSETP wo flush */
-
-/* #define TARGET_TIOCSETA	TARGET_IOW('t', 20, struct termios) set termios struct */
-/* #define TARGET_TIOCSETAW	TARGET_IOW('t', 21, struct termios) drain output, set */
-/* #define TARGET_TIOCSETAF	TARGET_IOW('t', 22, struct termios) drn out, fls in, set */
-/* #define TARGET_TIOCGETD	TARGET_IOR('t', 26, int)	get line discipline */
-/* #define TARGET_TIOCSETD	TARGET_IOW('t', 27, int)	set line discipline */
-						/* 127-124 compat */
-
-#define TARGET_TIOCSBRK	0x5427  /* BSD compatibility */
-#define TARGET_TIOCCBRK	0x5428  /* BSD compatibility */
-#define TARGET_TIOCGSID	0x7416  /* Return the session ID of FD */
-#define TARGET_TIOCGPTN	TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TARGET_TIOCSPTLCK	TARGET_IOW('T',0x31, int)  /* Lock/unlock Pty */
-
-/* I hope the range from 0x5480 on is free ... */
-#define TARGET_TIOCSCTTY	0x5480		/* become controlling tty */
-#define TARGET_TIOCGSOFTCAR	0x5481
-#define TARGET_TIOCSSOFTCAR	0x5482
-#define TARGET_TIOCLINUX	0x5483
-#define TARGET_TIOCGSERIAL	0x5484
-#define TARGET_TIOCSSERIAL	0x5485
-#define TARGET_TCSBRKP		0x5486	/* Needed for POSIX tcsendbreak() */
-#define TARGET_TIOCSERCONFIG	0x5488
-#define TARGET_TIOCSERGWILD	0x5489
-#define TARGET_TIOCSERSWILD	0x548a
-#define TARGET_TIOCGLCKTRMIOS	0x548b
-#define TARGET_TIOCSLCKTRMIOS	0x548c
-#define TARGET_TIOCSERGSTRUCT	0x548d /* For debugging only */
-#define TARGET_TIOCSERGETLSR   0x548e /* Get line status register */
-#define TARGET_TIOCSERGETMULTI 0x548f /* Get multiport config  */
-#define TARGET_TIOCSERSETMULTI 0x5490 /* Set multiport config */
-#define TARGET_TIOCMIWAIT      0x5491 /* wait for a change on serial input line(s) */
-#define TARGET_TIOCGICOUNT     0x5492 /* read serial port inline interrupt counts */
-#define TARGET_TIOCGHAYESESP	0x5493 /* Get Hayes ESP configuration */
-#define TARGET_TIOCSHAYESESP	0x5494 /* Set Hayes ESP configuration */
commit 68473f15d4c9948986618f63828825beafcaf1cf
Author: Richard Henderson <rth at twiddle.net>
Date:   Sun Feb 10 10:30:46 2013 -0800

    mips64-linux-user: Enable 64-bit address mode and fpu
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/translate.c b/target-mips/translate.c
index a51f430..694f07c 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15944,6 +15944,14 @@ void cpu_state_reset(CPUMIPSState *env)
 
 #if defined(CONFIG_USER_ONLY)
     env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
+# ifdef TARGET_MIPS64
+    /* Enable 64-bit register mode.  */
+    env->CP0_Status |= (1 << CP0St_PX);
+# endif
+# ifdef TARGET_ABI_MIPSN64
+    /* Enable 64-bit address mode.  */
+    env->CP0_Status |= (1 << CP0St_UX);
+# endif
     /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
        hardware registers.  */
     env->CP0_HWREna |= 0x0000000F;
@@ -15953,6 +15961,10 @@ void cpu_state_reset(CPUMIPSState *env)
     if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
         env->CP0_Status |= (1 << CP0St_MX);
     }
+    /* Enable 64-bit FPU if the target cpu supports it.  */
+    if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
+        env->CP0_Status |= (1 << CP0St_FR);
+    }
 #else
     if (env->hflags & MIPS_HFLAG_BMASK) {
         /* If the exception was raised from a delay slot,
commit ff4f7382815d31933fe0cbedce03270e4b62b771
Author: Richard Henderson <rth at twiddle.net>
Date:   Sun Feb 10 10:30:45 2013 -0800

    mips-linux-user: Fix n32 and n64 syscalls
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/linux-user/main.c b/linux-user/main.c
index cb14c0b..d8b0cd6 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1787,8 +1787,8 @@ void cpu_loop(CPUPPCState *env)
 
 #ifdef TARGET_MIPS
 
-#define MIPS_SYS(name, args) args,
-
+# ifdef TARGET_ABI_MIPSO32
+#  define MIPS_SYS(name, args) args,
 static const uint8_t mips_syscall_args[] = {
 	MIPS_SYS(sys_syscall	, 8)	/* 4000 */
 	MIPS_SYS(sys_exit	, 1)
@@ -2134,8 +2134,8 @@ static const uint8_t mips_syscall_args[] = {
         MIPS_SYS(sys_clock_adjtime, 2)
         MIPS_SYS(sys_syncfs, 1)
 };
-
-#undef MIPS_SYS
+#  undef MIPS_SYS
+# endif /* O32 */
 
 static int do_store_exclusive(CPUMIPSState *env)
 {
@@ -2217,8 +2217,11 @@ void cpu_loop(CPUMIPSState *env)
 {
     CPUState *cs = CPU(mips_env_get_cpu(env));
     target_siginfo_t info;
-    int trapnr, ret;
+    int trapnr;
+    abi_long ret;
+# ifdef TARGET_ABI_MIPSO32
     unsigned int syscall_num;
+# endif
 
     for(;;) {
         cpu_exec_start(cs);
@@ -2226,8 +2229,9 @@ void cpu_loop(CPUMIPSState *env)
         cpu_exec_end(cs);
         switch(trapnr) {
         case EXCP_SYSCALL:
-            syscall_num = env->active_tc.gpr[2] - 4000;
             env->active_tc.PC += 4;
+# ifdef TARGET_ABI_MIPSO32
+            syscall_num = env->active_tc.gpr[2] - 4000;
             if (syscall_num >= sizeof(mips_syscall_args)) {
                 ret = -TARGET_ENOSYS;
             } else {
@@ -2266,12 +2270,19 @@ void cpu_loop(CPUMIPSState *env)
                                  arg5, arg6, arg7, arg8);
             }
 done_syscall:
+# else
+            ret = do_syscall(env, env->active_tc.gpr[2],
+                             env->active_tc.gpr[4], env->active_tc.gpr[5],
+                             env->active_tc.gpr[6], env->active_tc.gpr[7],
+                             env->active_tc.gpr[8], env->active_tc.gpr[9],
+                             env->active_tc.gpr[10], env->active_tc.gpr[11]);
+# endif /* O32 */
             if (ret == -TARGET_QEMU_ESIGRETURN) {
                 /* Returning from a successful sigreturn syscall.
                    Avoid clobbering register state.  */
                 break;
             }
-            if ((unsigned int)ret >= (unsigned int)(-1133)) {
+            if ((abi_ulong)ret >= (abi_ulong)-1133) {
                 env->active_tc.gpr[7] = 1; /* error flag */
                 ret = -ret;
             } else {
commit 084d0497a0edf060d8f61c798217b6d0622a5feb
Author: Richard Henderson <rth at twiddle.net>
Date:   Sun Feb 10 10:30:44 2013 -0800

    mips-linux-user: Save and restore fpu and dsp from sigcontext
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 7da676f..1055507 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -2508,18 +2508,17 @@ struct target_rt_sigframe {
 /* Install trampoline to jump back from signal handler */
 static inline int install_sigtramp(unsigned int *tramp,   unsigned int syscall)
 {
-    int err;
+    int err = 0;
 
     /*
-    * Set up the return code ...
-    *
-    *         li      v0, __NR__foo_sigreturn
-    *         syscall
-    */
+     * Set up the return code ...
+     *
+     *         li      v0, __NR__foo_sigreturn
+     *         syscall
+     */
 
-    err = __put_user(0x24020000 + syscall, tramp + 0);
+    err |= __put_user(0x24020000 + syscall, tramp + 0);
     err |= __put_user(0x0000000c          , tramp + 1);
-    /* flush_cache_sigtramp((unsigned long) tramp); */
     return err;
 }
 
@@ -2527,74 +2526,37 @@ static inline int
 setup_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
 {
     int err = 0;
+    int i;
 
     err |= __put_user(regs->active_tc.PC, &sc->sc_pc);
 
-#define save_gp_reg(i) do {   						\
-        err |= __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);	\
-    } while(0)
-    __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
-    save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
-    save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
-    save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
-    save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
-    save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
-    save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
-    save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
-    save_gp_reg(31);
-#undef save_gp_reg
+    __put_user(0, &sc->sc_regs[0]);
+    for (i = 1; i < 32; ++i) {
+        err |= __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
+    }
 
     err |= __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
     err |= __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
 
-    /* Not used yet, but might be useful if we ever have DSP suppport */
-#if 0
-    if (cpu_has_dsp) {
-	err |= __put_user(mfhi1(), &sc->sc_hi1);
-	err |= __put_user(mflo1(), &sc->sc_lo1);
-	err |= __put_user(mfhi2(), &sc->sc_hi2);
-	err |= __put_user(mflo2(), &sc->sc_lo2);
-	err |= __put_user(mfhi3(), &sc->sc_hi3);
-	err |= __put_user(mflo3(), &sc->sc_lo3);
-	err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
-    }
-    /* same with 64 bit */
-#ifdef CONFIG_64BIT
-    err |= __put_user(regs->hi, &sc->sc_hi[0]);
-    err |= __put_user(regs->lo, &sc->sc_lo[0]);
-    if (cpu_has_dsp) {
-	err |= __put_user(mfhi1(), &sc->sc_hi[1]);
-	err |= __put_user(mflo1(), &sc->sc_lo[1]);
-	err |= __put_user(mfhi2(), &sc->sc_hi[2]);
-	err |= __put_user(mflo2(), &sc->sc_lo[2]);
-	err |= __put_user(mfhi3(), &sc->sc_hi[3]);
-	err |= __put_user(mflo3(), &sc->sc_lo[3]);
-	err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
+    /* Rather than checking for dsp existence, always copy.  The storage
+       would just be garbage otherwise.  */
+    err |= __put_user(regs->active_tc.HI[1], &sc->sc_hi1);
+    err |= __put_user(regs->active_tc.HI[2], &sc->sc_hi2);
+    err |= __put_user(regs->active_tc.HI[3], &sc->sc_hi3);
+    err |= __put_user(regs->active_tc.LO[1], &sc->sc_lo1);
+    err |= __put_user(regs->active_tc.LO[2], &sc->sc_lo2);
+    err |= __put_user(regs->active_tc.LO[3], &sc->sc_lo3);
+    {
+        uint32_t dsp = cpu_rddsp(0x3ff, regs);
+        err |= __put_user(dsp, &sc->sc_dsp);
     }
-#endif
-#endif
-
-#if 0
-    err |= __put_user(!!used_math(), &sc->sc_used_math);
 
-    if (!used_math())
-	goto out;
+    err |= __put_user(1, &sc->sc_used_math);
 
-    /*
-    * Save FPU state to signal context.  Signal handler will "inherit"
-    * current FPU state.
-    */
-    preempt_disable();
-
-    if (!is_fpu_owner()) {
-	own_fpu();
-	restore_fp(current);
+    for (i = 0; i < 32; ++i) {
+        err |= __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
     }
-    err |= save_fp_context(sc);
 
-    preempt_enable();
-    out:
-#endif
     return err;
 }
 
@@ -2602,68 +2564,33 @@ static inline int
 restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
 {
     int err = 0;
+    int i;
 
     err |= __get_user(regs->CP0_EPC, &sc->sc_pc);
 
     err |= __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
     err |= __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
 
-#define restore_gp_reg(i) do {   							\
-        err |= __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);		\
-    } while(0)
-    restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
-    restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
-    restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
-    restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
-    restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
-    restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
-    restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
-    restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
-    restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
-    restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
-    restore_gp_reg(31);
-#undef restore_gp_reg
-
-#if 0
-    if (cpu_has_dsp) {
-	err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
-	err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
-	err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
-	err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
-	err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
-	err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
-	err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
-    }
-#ifdef CONFIG_64BIT
-    err |= __get_user(regs->hi, &sc->sc_hi[0]);
-    err |= __get_user(regs->lo, &sc->sc_lo[0]);
-    if (cpu_has_dsp) {
-	err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);
-	err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);
-	err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);
-	err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);
-	err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);
-	err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);
-	err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
+    for (i = 1; i < 32; ++i) {
+        err |= __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);
     }
-#endif
-
-    err |= __get_user(used_math, &sc->sc_used_math);
-    conditional_used_math(used_math);
 
-    preempt_disable();
+    err |= __get_user(regs->active_tc.HI[1], &sc->sc_hi1);
+    err |= __get_user(regs->active_tc.HI[2], &sc->sc_hi2);
+    err |= __get_user(regs->active_tc.HI[3], &sc->sc_hi3);
+    err |= __get_user(regs->active_tc.LO[1], &sc->sc_lo1);
+    err |= __get_user(regs->active_tc.LO[2], &sc->sc_lo2);
+    err |= __get_user(regs->active_tc.LO[3], &sc->sc_lo3);
+    {
+        uint32_t dsp;
+        err |= __get_user(dsp, &sc->sc_dsp);
+        cpu_wrdsp(dsp, 0x3ff, regs);
+    }
 
-    if (used_math()) {
-	/* restore fpu context if we have used it before */
-	own_fpu();
-	err |= restore_fp_context(sc);
-    } else {
-	/* signal handler may have used FPU.  Give it up. */
-	lose_fpu();
+    for (i = 0; i < 32; ++i) {
+        err |= __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
     }
 
-    preempt_enable();
-#endif
     return err;
 }
 
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 0e198b1..ca63148 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -504,6 +504,9 @@ void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf);
 #define cpu_signal_handler cpu_mips_signal_handler
 #define cpu_list mips_cpu_list
 
+extern void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env);
+extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env);
+
 #define CPU_SAVE_VERSION 3
 
 /* MMU modes definitions. We carefully match the indices with our
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index ffa9396..472be35 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -3643,7 +3643,7 @@ void helper_dmthlip(target_ulong rs, target_ulong ac, CPUMIPSState *env)
 }
 #endif
 
-void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env)
+void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env)
 {
     uint8_t  mask[6];
     uint8_t  i;
@@ -3709,7 +3709,12 @@ void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env)
     env->active_tc.DSPControl = dsp;
 }
 
-target_ulong helper_rddsp(target_ulong masknum, CPUMIPSState *env)
+void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env)
+{
+    return cpu_wrdsp(rs, mask_num, env);
+}
+
+uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env)
 {
     uint8_t  mask[6];
     uint32_t ruler, i;
@@ -3718,7 +3723,7 @@ target_ulong helper_rddsp(target_ulong masknum, CPUMIPSState *env)
 
     ruler = 0x01;
     for (i = 0; i < 6; i++) {
-        mask[i] = (masknum & ruler) >> i ;
+        mask[i] = (mask_num & ruler) >> i ;
         ruler = ruler << 1;
     }
 
@@ -3760,6 +3765,11 @@ target_ulong helper_rddsp(target_ulong masknum, CPUMIPSState *env)
     return temp;
 }
 
+target_ulong helper_rddsp(target_ulong mask_num, CPUMIPSState *env)
+{
+    return cpu_rddsp(mask_num, env);
+}
+
 
 #undef MIPSDSP_LHI
 #undef MIPSDSP_LLO
commit 51cd14d3f56f15cb82e63d694a023ce2b02334f9
Author: Richard Henderson <rth at twiddle.net>
Date:   Sun Feb 10 10:30:43 2013 -0800

    mips-linux-user: Enable mips64 and mipsn32 linux-user targets
    
    At this point we can enable compilation, though things
    still don't work.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    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 19738ac..08dcc26 100755
--- a/configure
+++ b/configure
@@ -986,6 +986,10 @@ microblaze-linux-user \
 microblazeel-linux-user \
 mips-linux-user \
 mipsel-linux-user \
+mips64-linux-user \
+mips64el-linux-user \
+mipsn32-linux-user \
+mipsn32el-linux-user \
 or32-linux-user \
 ppc-linux-user \
 ppc64-linux-user \
commit ff97090469eb4a5f21a1f482b27382b8205d1232
Author: Richard Henderson <rth at twiddle.net>
Date:   Sun Feb 10 10:30:42 2013 -0800

    mips-linux-user: Share o32 code for n32 and n64 signals
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/linux-user/signal.c b/linux-user/signal.c
index b2f1d29..7da676f 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -2438,8 +2438,9 @@ void sparc64_get_context(CPUSPARCState *env)
     force_sig(TARGET_SIGSEGV);
 }
 #endif
-#elif defined(TARGET_ABI_MIPSO32)
+#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
 
+# if defined(TARGET_ABI_MIPSO32)
 struct target_sigcontext {
     uint32_t   sc_regmask;     /* Unused */
     uint32_t   sc_status;
@@ -2461,6 +2462,25 @@ struct target_sigcontext {
     target_ulong   sc_hi3;
     target_ulong   sc_lo3;
 };
+# else /* N32 || N64 */
+struct target_sigcontext {
+    uint64_t sc_regs[32];
+    uint64_t sc_fpregs[32];
+    uint64_t sc_mdhi;
+    uint64_t sc_hi1;
+    uint64_t sc_hi2;
+    uint64_t sc_hi3;
+    uint64_t sc_mdlo;
+    uint64_t sc_lo1;
+    uint64_t sc_lo2;
+    uint64_t sc_lo3;
+    uint64_t sc_pc;
+    uint32_t sc_fpc_csr;
+    uint32_t sc_used_math;
+    uint32_t sc_dsp;
+    uint32_t sc_reserved;
+};
+# endif /* O32 */
 
 struct sigframe {
     uint32_t sf_ass[4];			/* argument save space for o32 */
@@ -2646,6 +2666,7 @@ restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
 #endif
     return err;
 }
+
 /*
  * Determine which stack to use..
  */
@@ -2672,6 +2693,7 @@ get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
     return (sp - frame_size) & ~7;
 }
 
+# if defined(TARGET_ABI_MIPSO32)
 /* compare linux/arch/mips/kernel/signal.c:setup_frame() */
 static void setup_frame(int sig, struct target_sigaction * ka,
                         target_sigset_t *set, CPUMIPSState *regs)
@@ -2769,6 +2791,7 @@ badframe:
     force_sig(TARGET_SIGSEGV/*, current*/);
     return 0;
 }
+# endif /* O32 */
 
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
                            target_siginfo_t *info,
@@ -5499,10 +5522,15 @@ void process_pending_signals(CPUArchState *cpu_env)
         }
 #endif
         /* prepare the stack frame of the virtual CPU */
+#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
+        /* These targets do not have traditional signals.  */
+        setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
+#else
         if (sa->sa_flags & TARGET_SA_SIGINFO)
             setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
         else
             setup_frame(sig, sa, &target_old_set, cpu_env);
+#endif
 	if (sa->sa_flags & TARGET_SA_RESETHAND)
             sa->_sa_handler = TARGET_SIG_DFL;
     }
commit 2c3c6689b32529b56261bbbca36ba8544a34dd60
Author: Richard Henderson <rth at twiddle.net>
Date:   Sun Feb 10 10:30:41 2013 -0800

    mips-linux-user: Delete n32 and n64 signal stubs
    
    Deleting these first makes the next patch much easier to read.
    This doesn't cause any sort of compilation failure because we
    have not yet enabled n32/n64 compilation.  This is dead code.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 67c2311..b2f1d29 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -2438,64 +2438,6 @@ void sparc64_get_context(CPUSPARCState *env)
     force_sig(TARGET_SIGSEGV);
 }
 #endif
-#elif defined(TARGET_ABI_MIPSN64)
-
-# warning signal handling not implemented
-
-static void setup_frame(int sig, struct target_sigaction *ka,
-                        target_sigset_t *set, CPUMIPSState *env)
-{
-    fprintf(stderr, "setup_frame: not implemented\n");
-}
-
-static void setup_rt_frame(int sig, struct target_sigaction *ka,
-                           target_siginfo_t *info,
-                           target_sigset_t *set, CPUMIPSState *env)
-{
-    fprintf(stderr, "setup_rt_frame: not implemented\n");
-}
-
-long do_sigreturn(CPUMIPSState *env)
-{
-    fprintf(stderr, "do_sigreturn: not implemented\n");
-    return -TARGET_ENOSYS;
-}
-
-long do_rt_sigreturn(CPUMIPSState *env)
-{
-    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
-    return -TARGET_ENOSYS;
-}
-
-#elif defined(TARGET_ABI_MIPSN32)
-
-# warning signal handling not implemented
-
-static void setup_frame(int sig, struct target_sigaction *ka,
-                        target_sigset_t *set, CPUMIPSState *env)
-{
-    fprintf(stderr, "setup_frame: not implemented\n");
-}
-
-static void setup_rt_frame(int sig, struct target_sigaction *ka,
-                           target_siginfo_t *info,
-                           target_sigset_t *set, CPUMIPSState *env)
-{
-    fprintf(stderr, "setup_rt_frame: not implemented\n");
-}
-
-long do_sigreturn(CPUMIPSState *env)
-{
-    fprintf(stderr, "do_sigreturn: not implemented\n");
-    return -TARGET_ENOSYS;
-}
-
-long do_rt_sigreturn(CPUMIPSState *env)
-{
-    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
-    return -TARGET_ENOSYS;
-}
-
 #elif defined(TARGET_ABI_MIPSO32)
 
 struct target_sigcontext {
commit ed4659d10fa2ec16ace367e4fffe6f7ced73112c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 5 00:34:43 2013 +0000

    MAINTAINERS: add entry for ARM KVM guest cores
    
    Add an entry indicating maintainer status for the ARM KVM code.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/MAINTAINERS b/MAINTAINERS
index 21043e4..2439614 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -140,6 +140,11 @@ S: Supported
 F: kvm-*
 F: */kvm.*
 
+ARM
+M: Peter Maydell <peter.maydell at linaro.org>
+S: Maintained
+F: target-arm/kvm.c
+
 PPC
 M: Alexander Graf <agraf at suse.de>
 S: Maintained
commit 68b05c427b0d220e38bfa21ee6df7970f158b377
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 5 00:34:43 2013 +0000

    configure: Enable KVM on ARM
    
    Enable KVM on ARM hosts, now that all the necessary components
    for it exist.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/configure b/configure
index 19738ac..b4deb9b 100755
--- a/configure
+++ b/configure
@@ -4129,7 +4129,7 @@ case "$target_arch2" in
     echo "CONFIG_NO_XEN=y" >> $config_target_mak
 esac
 case "$target_arch2" in
-  i386|x86_64|ppcemb|ppc|ppc64|s390x)
+  arm|i386|x86_64|ppcemb|ppc|ppc64|s390x)
     # Make sure the target and host cpus are compatible
     if test "$kvm" = "yes" -a "$target_softmmu" = "yes" -a \
       \( "$target_arch2" = "$cpu" -o \
commit ed46676160d94d279e32ce955fd60b76c7a1b370
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 5 00:34:43 2013 +0000

    hw/kvm/arm_gic: Implement support for KVM in-kernel ARM GIC
    
    Implement support for using the KVM in-kernel GIC for ARM.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/a15mpcore.c b/hw/a15mpcore.c
index fe6c34c..97abe41 100644
--- a/hw/a15mpcore.c
+++ b/hw/a15mpcore.c
@@ -19,6 +19,7 @@
  */
 
 #include "sysbus.h"
+#include "sysemu/kvm.h"
 
 /* A15MP private memory region.  */
 
@@ -40,8 +41,13 @@ static int a15mp_priv_init(SysBusDevice *dev)
 {
     A15MPPrivState *s = FROM_SYSBUS(A15MPPrivState, dev);
     SysBusDevice *busdev;
+    const char *gictype = "arm_gic";
 
-    s->gic = qdev_create(NULL, "arm_gic");
+    if (kvm_irqchip_in_kernel()) {
+        gictype = "kvm-arm-gic";
+    }
+
+    s->gic = qdev_create(NULL, gictype);
     qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
     qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
     qdev_prop_set_uint32(s->gic, "revision", 2);
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 4c10985..0e7df60 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -32,5 +32,6 @@ obj-y += collie.o
 obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-y += kzm.o
 obj-$(CONFIG_FDT) += ../device_tree.o
+obj-$(CONFIG_KVM) += kvm/arm_gic.o
 
 obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/kvm/arm_gic.c b/hw/kvm/arm_gic.c
new file mode 100644
index 0000000..22b40b4
--- /dev/null
+++ b/hw/kvm/arm_gic.c
@@ -0,0 +1,167 @@
+/*
+ * ARM Generic Interrupt Controller using KVM in-kernel support
+ *
+ * Copyright (c) 2012 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * 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/>.
+ */
+
+#include "hw/sysbus.h"
+#include "sysemu/kvm.h"
+#include "kvm_arm.h"
+#include "hw/arm_gic_internal.h"
+
+#define TYPE_KVM_ARM_GIC "kvm-arm-gic"
+#define KVM_ARM_GIC(obj) \
+     OBJECT_CHECK(GICState, (obj), TYPE_KVM_ARM_GIC)
+#define KVM_ARM_GIC_CLASS(klass) \
+     OBJECT_CLASS_CHECK(KVMARMGICClass, (klass), TYPE_KVM_ARM_GIC)
+#define KVM_ARM_GIC_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(KVMARMGICClass, (obj), TYPE_KVM_ARM_GIC)
+
+typedef struct KVMARMGICClass {
+    ARMGICCommonClass parent_class;
+    DeviceRealize parent_realize;
+    void (*parent_reset)(DeviceState *dev);
+} KVMARMGICClass;
+
+static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
+{
+    /* Meaning of the 'irq' parameter:
+     *  [0..N-1] : external interrupts
+     *  [N..N+31] : PPI (internal) interrupts for CPU 0
+     *  [N+32..N+63] : PPI (internal interrupts for CPU 1
+     *  ...
+     * Convert this to the kernel's desired encoding, which
+     * has separate fields in the irq number for type,
+     * CPU number and interrupt number.
+     */
+    GICState *s = (GICState *)opaque;
+    int kvm_irq, irqtype, cpu;
+
+    if (irq < (s->num_irq - GIC_INTERNAL)) {
+        /* External interrupt. The kernel numbers these like the GIC
+         * hardware, with external interrupt IDs starting after the
+         * internal ones.
+         */
+        irqtype = KVM_ARM_IRQ_TYPE_SPI;
+        cpu = 0;
+        irq += GIC_INTERNAL;
+    } else {
+        /* Internal interrupt: decode into (cpu, interrupt id) */
+        irqtype = KVM_ARM_IRQ_TYPE_PPI;
+        irq -= (s->num_irq - GIC_INTERNAL);
+        cpu = irq / GIC_INTERNAL;
+        irq %= GIC_INTERNAL;
+    }
+    kvm_irq = (irqtype << KVM_ARM_IRQ_TYPE_SHIFT)
+        | (cpu << KVM_ARM_IRQ_VCPU_SHIFT) | irq;
+
+    kvm_set_irq(kvm_state, kvm_irq, !!level);
+}
+
+static void kvm_arm_gic_put(GICState *s)
+{
+    /* TODO: there isn't currently a kernel interface to set the GIC state */
+}
+
+static void kvm_arm_gic_get(GICState *s)
+{
+    /* TODO: there isn't currently a kernel interface to get the GIC state */
+}
+
+static void kvm_arm_gic_reset(DeviceState *dev)
+{
+    GICState *s = ARM_GIC_COMMON(dev);
+    KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
+
+    kgc->parent_reset(dev);
+    kvm_arm_gic_put(s);
+}
+
+static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
+{
+    int i;
+    GICState *s = KVM_ARM_GIC(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
+
+    kgc->parent_realize(dev, errp);
+    if (error_is_set(errp)) {
+        return;
+    }
+
+    i = s->num_irq - GIC_INTERNAL;
+    /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
+     * GPIO array layout is thus:
+     *  [0..N-1] SPIs
+     *  [N..N+31] PPIs for CPU 0
+     *  [N+32..N+63] PPIs for CPU 1
+     *   ...
+     */
+    i += (GIC_INTERNAL * s->num_cpu);
+    qdev_init_gpio_in(dev, kvm_arm_gic_set_irq, i);
+    /* We never use our outbound IRQ lines but provide them so that
+     * we maintain the same interface as the non-KVM GIC.
+     */
+    for (i = 0; i < s->num_cpu; i++) {
+        sysbus_init_irq(sbd, &s->parent_irq[i]);
+    }
+    /* Distributor */
+    memory_region_init_reservation(&s->iomem, "kvm-gic_dist", 0x1000);
+    sysbus_init_mmio(sbd, &s->iomem);
+    kvm_arm_register_device(&s->iomem,
+                            (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
+                            | KVM_VGIC_V2_ADDR_TYPE_DIST);
+    /* CPU interface for current core. Unlike arm_gic, we don't
+     * provide the "interface for core #N" memory regions, because
+     * cores with a VGIC don't have those.
+     */
+    memory_region_init_reservation(&s->cpuiomem[0], "kvm-gic_cpu", 0x1000);
+    sysbus_init_mmio(sbd, &s->cpuiomem[0]);
+    kvm_arm_register_device(&s->cpuiomem[0],
+                            (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
+                            | KVM_VGIC_V2_ADDR_TYPE_CPU);
+}
+
+static void kvm_arm_gic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ARMGICCommonClass *agcc = ARM_GIC_COMMON_CLASS(klass);
+    KVMARMGICClass *kgc = KVM_ARM_GIC_CLASS(klass);
+
+    agcc->pre_save = kvm_arm_gic_get;
+    agcc->post_load = kvm_arm_gic_put;
+    kgc->parent_realize = dc->realize;
+    kgc->parent_reset = dc->reset;
+    dc->realize = kvm_arm_gic_realize;
+    dc->reset = kvm_arm_gic_reset;
+    dc->no_user = 1;
+}
+
+static const TypeInfo kvm_arm_gic_info = {
+    .name = TYPE_KVM_ARM_GIC,
+    .parent = TYPE_ARM_GIC_COMMON,
+    .instance_size = sizeof(GICState),
+    .class_init = kvm_arm_gic_class_init,
+    .class_size = sizeof(KVMARMGICClass),
+};
+
+static void kvm_arm_gic_register_types(void)
+{
+    type_register_static(&kvm_arm_gic_info);
+}
+
+type_init(kvm_arm_gic_register_types)
commit eb035b48d5ff26a155f37106f693acb8b8487d80
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 5 00:34:42 2013 +0000

    target-arm: Use MemoryListener to identify GIC base address for KVM
    
    When using an in-kernel GIC with KVM, we need to tell the kernel where
    the GIC's memory mapped registers live. Do this by registering a
    MemoryListener which tracks where the board model maps the A15's
    private peripherals, so we can finish the GIC initialisation
    when the GIC is actually mapped.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index 9173d0a..82e2e08 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -19,6 +19,7 @@
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/kvm.h"
+#include "kvm_arm.h"
 #include "cpu.h"
 #include "hw/arm-misc.h"
 
@@ -67,6 +68,92 @@ int kvm_arch_init_vcpu(CPUState *cs)
     return ret;
 }
 
+/* We track all the KVM devices which need their memory addresses
+ * passing to the kernel in a list of these structures.
+ * When board init is complete we run through the list and
+ * tell the kernel the base addresses of the memory regions.
+ * We use a MemoryListener to track mapping and unmapping of
+ * the regions during board creation, so the board models don't
+ * need to do anything special for the KVM case.
+ */
+typedef struct KVMDevice {
+    struct kvm_arm_device_addr kda;
+    MemoryRegion *mr;
+    QSLIST_ENTRY(KVMDevice) entries;
+} KVMDevice;
+
+static QSLIST_HEAD(kvm_devices_head, KVMDevice) kvm_devices_head;
+
+static void kvm_arm_devlistener_add(MemoryListener *listener,
+                                    MemoryRegionSection *section)
+{
+    KVMDevice *kd;
+
+    QSLIST_FOREACH(kd, &kvm_devices_head, entries) {
+        if (section->mr == kd->mr) {
+            kd->kda.addr = section->offset_within_address_space;
+        }
+    }
+}
+
+static void kvm_arm_devlistener_del(MemoryListener *listener,
+                                    MemoryRegionSection *section)
+{
+    KVMDevice *kd;
+
+    QSLIST_FOREACH(kd, &kvm_devices_head, entries) {
+        if (section->mr == kd->mr) {
+            kd->kda.addr = -1;
+        }
+    }
+}
+
+static MemoryListener devlistener = {
+    .region_add = kvm_arm_devlistener_add,
+    .region_del = kvm_arm_devlistener_del,
+};
+
+static void kvm_arm_machine_init_done(Notifier *notifier, void *data)
+{
+    KVMDevice *kd, *tkd;
+
+    memory_listener_unregister(&devlistener);
+    QSLIST_FOREACH_SAFE(kd, &kvm_devices_head, entries, tkd) {
+        if (kd->kda.addr != -1) {
+            if (kvm_vm_ioctl(kvm_state, KVM_ARM_SET_DEVICE_ADDR,
+                             &kd->kda) < 0) {
+                fprintf(stderr, "KVM_ARM_SET_DEVICE_ADDRESS failed: %s\n",
+                        strerror(errno));
+                abort();
+            }
+        }
+        g_free(kd);
+    }
+}
+
+static Notifier notify = {
+    .notify = kvm_arm_machine_init_done,
+};
+
+void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid)
+{
+    KVMDevice *kd;
+
+    if (!kvm_irqchip_in_kernel()) {
+        return;
+    }
+
+    if (QSLIST_EMPTY(&kvm_devices_head)) {
+        memory_listener_register(&devlistener, NULL);
+        qemu_add_machine_init_done_notifier(&notify);
+    }
+    kd = g_new0(KVMDevice, 1);
+    kd->mr = mr;
+    kd->kda.id = devid;
+    kd->kda.addr = -1;
+    QSLIST_INSERT_HEAD(&kvm_devices_head, kd, entries);
+}
+
 typedef struct Reg {
     uint64_t id;
     int offset;
diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h
new file mode 100644
index 0000000..b1c54ff
--- /dev/null
+++ b/target-arm/kvm_arm.h
@@ -0,0 +1,32 @@
+/*
+ * QEMU KVM support -- ARM specific functions.
+ *
+ * Copyright (c) 2012 Linaro Limited
+ *
+ * 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 QEMU_KVM_ARM_H
+#define QEMU_KVM_ARM_H
+
+#include "sysemu/kvm.h"
+#include "exec/memory.h"
+
+/**
+ * kvm_arm_register_device:
+ * @mr: memory region for this device
+ * @devid: the KVM device ID
+ *
+ * Remember the memory region @mr, and when it is mapped by the
+ * machine model, tell the kernel that base address using the
+ * KVM_SET_DEVICE_ADDRESS ioctl. @devid should be the ID of
+ * the device as defined by KVM_SET_DEVICE_ADDRESS.
+ * The machine model may map and unmap the device multiple times;
+ * the kernel will only be told the final address at the point
+ * where machine init is complete.
+ */
+void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid);
+
+#endif
commit 53111180946a56d314a9c1d07d09b9ef91e847b9
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 5 00:34:42 2013 +0000

    hw/arm_gic: Convert ARM GIC classes to use init/realize
    
    Convert the ARM GIC classes to use init/realize rather than
    SysBusDevice::init. (We have to do them all in one patch to
    avoid unconverted subclasses calling a nonexistent SysBusDevice
    init function in the base class and crashing.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>

diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 90e43d0..250e720 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -659,14 +659,18 @@ void gic_init_irqs_and_distributor(GICState *s, int num_irq)
     memory_region_init_io(&s->iomem, &gic_dist_ops, s, "gic_dist", 0x1000);
 }
 
-static int arm_gic_init(SysBusDevice *dev)
+static void arm_gic_realize(DeviceState *dev, Error **errp)
 {
-    /* Device instance init function for the GIC sysbus device */
+    /* Device instance realize function for the GIC sysbus device */
     int i;
-    GICState *s = FROM_SYSBUS(GICState, dev);
+    GICState *s = ARM_GIC(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     ARMGICClass *agc = ARM_GIC_GET_CLASS(s);
 
-    agc->parent_init(dev);
+    agc->parent_realize(dev, errp);
+    if (error_is_set(errp)) {
+        return;
+    }
 
     gic_init_irqs_and_distributor(s, s->num_irq);
 
@@ -686,22 +690,21 @@ static int arm_gic_init(SysBusDevice *dev)
                               "gic_cpu", 0x100);
     }
     /* Distributor */
-    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_mmio(sbd, &s->iomem);
     /* cpu interfaces (one for "current cpu" plus one per cpu) */
     for (i = 0; i <= NUM_CPU(s); i++) {
-        sysbus_init_mmio(dev, &s->cpuiomem[i]);
+        sysbus_init_mmio(sbd, &s->cpuiomem[i]);
     }
-    return 0;
 }
 
 static void arm_gic_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
     ARMGICClass *agc = ARM_GIC_CLASS(klass);
-    agc->parent_init = sbc->init;
-    sbc->init = arm_gic_init;
+
     dc->no_user = 1;
+    agc->parent_realize = dc->realize;
+    dc->realize = arm_gic_realize;
 }
 
 static const TypeInfo arm_gic_info = {
diff --git a/hw/arm_gic_common.c b/hw/arm_gic_common.c
index 2947622..20da9d2 100644
--- a/hw/arm_gic_common.c
+++ b/hw/arm_gic_common.c
@@ -104,31 +104,35 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static int arm_gic_common_init(SysBusDevice *dev)
+static void arm_gic_common_realize(DeviceState *dev, Error **errp)
 {
-    GICState *s = FROM_SYSBUS(GICState, dev);
+    GICState *s = ARM_GIC_COMMON(dev);
     int num_irq = s->num_irq;
 
     if (s->num_cpu > NCPU) {
-        hw_error("requested %u CPUs exceeds GIC maximum %d\n",
-                 s->num_cpu, NCPU);
+        error_setg(errp, "requested %u CPUs exceeds GIC maximum %d",
+                   s->num_cpu, NCPU);
+        return;
     }
     s->num_irq += GIC_BASE_IRQ;
     if (s->num_irq > GIC_MAXIRQ) {
-        hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
-                 num_irq, GIC_MAXIRQ);
+        error_setg(errp,
+                   "requested %u interrupt lines exceeds GIC maximum %d",
+                   num_irq, GIC_MAXIRQ);
+        return;
     }
     /* ITLinesNumber is represented as (N / 32) - 1 (see
      * gic_dist_readb) so this is an implementation imposed
      * restriction, not an architectural one:
      */
     if (s->num_irq < 32 || (s->num_irq % 32)) {
-        hw_error("%d interrupt lines unsupported: not divisible by 32\n",
-                 num_irq);
+        error_setg(errp,
+                   "%d interrupt lines unsupported: not divisible by 32",
+                   num_irq);
+        return;
     }
 
     register_savevm(NULL, "arm_gic", -1, 3, gic_save, gic_load, s);
-    return 0;
 }
 
 static void arm_gic_common_reset(DeviceState *dev)
@@ -173,12 +177,12 @@ static Property arm_gic_common_properties[] = {
 
 static void arm_gic_common_class_init(ObjectClass *klass, void *data)
 {
-    SysBusDeviceClass *sc = SYS_BUS_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
+
     dc->reset = arm_gic_common_reset;
+    dc->realize = arm_gic_common_realize;
     dc->props = arm_gic_common_properties;
     dc->no_user = 1;
-    sc->init = arm_gic_common_init;
 }
 
 static const TypeInfo arm_gic_common_type = {
diff --git a/hw/arm_gic_internal.h b/hw/arm_gic_internal.h
index 3640be0..3ba37f3 100644
--- a/hw/arm_gic_internal.h
+++ b/hw/arm_gic_internal.h
@@ -132,7 +132,7 @@ typedef struct ARMGICCommonClass {
 
 typedef struct ARMGICClass {
     ARMGICCommonClass parent_class;
-    int (*parent_init)(SysBusDevice *dev);
+    DeviceRealize parent_realize;
 } ARMGICClass;
 
 #endif /* !QEMU_ARM_GIC_INTERNAL_H */
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index d5798d0..3c79674 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -41,7 +41,7 @@ typedef struct NVICClass {
     /*< private >*/
     ARMGICClass parent_class;
     /*< public >*/
-    int (*parent_init)(SysBusDevice *dev);
+    DeviceRealize parent_realize;
     void (*parent_reset)(DeviceState *dev);
 } NVICClass;
 
@@ -465,7 +465,7 @@ static void armv7m_nvic_reset(DeviceState *dev)
     systick_reset(s);
 }
 
-static int armv7m_nvic_init(SysBusDevice *dev)
+static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
 {
     nvic_state *s = NVIC(dev);
     NVICClass *nc = NVIC_GET_CLASS(s);
@@ -475,7 +475,10 @@ static int armv7m_nvic_init(SysBusDevice *dev)
     /* Tell the common code we're an NVIC */
     s->gic.revision = 0xffffffff;
     s->num_irq = s->gic.num_irq;
-    nc->parent_init(dev);
+    nc->parent_realize(dev, errp);
+    if (error_is_set(errp)) {
+        return;
+    }
     gic_init_irqs_and_distributor(&s->gic, s->num_irq);
     /* The NVIC and system controller register area looks like this:
      *  0..0xff : system control registers, including systick
@@ -503,7 +506,6 @@ static int armv7m_nvic_init(SysBusDevice *dev)
      */
     memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->container);
     s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
-    return 0;
 }
 
 static void armv7m_nvic_instance_init(Object *obj)
@@ -526,13 +528,12 @@ static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
 {
     NVICClass *nc = NVIC_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
 
     nc->parent_reset = dc->reset;
-    nc->parent_init = sdc->init;
-    sdc->init = armv7m_nvic_init;
+    nc->parent_realize = dc->realize;
     dc->vmsd  = &vmstate_nvic;
     dc->reset = armv7m_nvic_reset;
+    dc->realize = armv7m_nvic_realize;
 }
 
 static const TypeInfo armv7m_nvic_info = {
commit 9ecb992674cec86091b4fce3bd66faee8b56b165
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 5 00:34:41 2013 +0000

    hw/arm_gic: Add presave/postload hooks
    
    Add presave/postload hooks to the ARM GIC common base class.
    These will be used by the KVM in-kernel GIC subclass to sync
    state between kernel and userspace when migrating.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/arm_gic_common.c b/hw/arm_gic_common.c
index 40e8dd7..2947622 100644
--- a/hw/arm_gic_common.c
+++ b/hw/arm_gic_common.c
@@ -23,9 +23,14 @@
 static void gic_save(QEMUFile *f, void *opaque)
 {
     GICState *s = (GICState *)opaque;
+    ARMGICCommonClass *c = ARM_GIC_COMMON_GET_CLASS(s);
     int i;
     int j;
 
+    if (c->pre_save) {
+        c->pre_save(s);
+    }
+
     qemu_put_be32(f, s->enabled);
     for (i = 0; i < s->num_cpu; i++) {
         qemu_put_be32(f, s->cpu_enabled[i]);
@@ -57,6 +62,7 @@ static void gic_save(QEMUFile *f, void *opaque)
 static int gic_load(QEMUFile *f, void *opaque, int version_id)
 {
     GICState *s = (GICState *)opaque;
+    ARMGICCommonClass *c = ARM_GIC_COMMON_GET_CLASS(s);
     int i;
     int j;
 
@@ -91,6 +97,10 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
         s->irq_state[i].trigger = qemu_get_byte(f);
     }
 
+    if (c->post_load) {
+        c->post_load(s);
+    }
+
     return 0;
 }
 
diff --git a/hw/arm_gic_internal.h b/hw/arm_gic_internal.h
index 699352c..3640be0 100644
--- a/hw/arm_gic_internal.h
+++ b/hw/arm_gic_internal.h
@@ -118,6 +118,8 @@ void gic_init_irqs_and_distributor(GICState *s, int num_irq);
 
 typedef struct ARMGICCommonClass {
     SysBusDeviceClass parent_class;
+    void (*pre_save)(GICState *s);
+    void (*post_load)(GICState *s);
 } ARMGICCommonClass;
 
 #define TYPE_ARM_GIC "arm_gic"
commit 81635574f6e7f4d18ea059ecbeeec93c3ffc284c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 5 00:34:41 2013 +0000

    ARM KVM: save and load VFP registers from kernel
    
    Add support for saving and restoring VFP register state from the
    kernel. This includes a check that the KVM-created CPU has full
    VFP support (as the TCG Cortex-A15 model always does), since for
    the moment ARM QEMU doesn't have any way to tweak optional features
    on created CPUs.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index 499b427..9173d0a 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -43,10 +43,28 @@ unsigned long kvm_arch_vcpu_id(CPUState *cpu)
 int kvm_arch_init_vcpu(CPUState *cs)
 {
     struct kvm_vcpu_init init;
+    int ret;
+    uint64_t v;
+    struct kvm_one_reg r;
 
     init.target = KVM_ARM_TARGET_CORTEX_A15;
     memset(init.features, 0, sizeof(init.features));
-    return kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_INIT, &init);
+    ret = kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_INIT, &init);
+    if (ret) {
+        return ret;
+    }
+    /* Query the kernel to make sure it supports 32 VFP
+     * registers: QEMU's "cortex-a15" CPU is always a
+     * VFP-D32 core. The simplest way to do this is just
+     * to attempt to read register d31.
+     */
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP | 31;
+    r.addr = (uintptr_t)(&v);
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
+    if (ret == ENOENT) {
+        return EINVAL;
+    }
+    return ret;
 }
 
 typedef struct Reg {
@@ -72,6 +90,13 @@ typedef struct Reg {
         offsetof(CPUARMState, QEMUFIELD)         \
     }
 
+#define VFPSYSREG(R)                                       \
+    {                                                      \
+        KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP | \
+        KVM_REG_ARM_VFP_##R,                               \
+        offsetof(CPUARMState, vfp.xregs[ARM_VFP_##R])      \
+    }
+
 static const Reg regs[] = {
     /* R0_usr .. R14_usr */
     COREREG(usr_regs.uregs[0], regs[0]),
@@ -119,6 +144,13 @@ static const Reg regs[] = {
     CP15REG(1, 0, 0, 0, cp15.c1_sys), /* SCTLR */
     CP15REG(2, 0, 0, 2, cp15.c2_control), /* TTBCR */
     CP15REG(3, 0, 0, 0, cp15.c3), /* DACR */
+    /* VFP system registers */
+    VFPSYSREG(FPSID),
+    VFPSYSREG(MVFR1),
+    VFPSYSREG(MVFR0),
+    VFPSYSREG(FPEXC),
+    VFPSYSREG(FPINST),
+    VFPSYSREG(FPINST2),
 };
 
 int kvm_arch_put_registers(CPUState *cs, int level)
@@ -128,7 +160,7 @@ int kvm_arch_put_registers(CPUState *cs, int level)
     struct kvm_one_reg r;
     int mode, bn;
     int ret, i;
-    uint32_t cpsr;
+    uint32_t cpsr, fpscr;
     uint64_t ttbr;
 
     /* Make sure the banked regs are properly set */
@@ -179,6 +211,26 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         (2 << KVM_REG_ARM_CRM_SHIFT) | (1 << KVM_REG_ARM_OPC1_SHIFT);
     r.addr = (uintptr_t)(&ttbr);
     ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
+    if (ret) {
+        return ret;
+    }
+
+    /* VFP registers */
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
+    for (i = 0; i < 32; i++) {
+        r.addr = (uintptr_t)(&env->vfp.regs[i]);
+        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
+        if (ret) {
+            return ret;
+        }
+        r.id++;
+    }
+
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
+        KVM_REG_ARM_VFP_FPSCR;
+    fpscr = vfp_get_fpscr(env);
+    r.addr = (uintptr_t)&fpscr;
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
 
     return ret;
 }
@@ -190,7 +242,7 @@ int kvm_arch_get_registers(CPUState *cs)
     struct kvm_one_reg r;
     int mode, bn;
     int ret, i;
-    uint32_t cpsr;
+    uint32_t cpsr, fpscr;
     uint64_t ttbr;
 
     for (i = 0; i < ARRAY_SIZE(regs); i++) {
@@ -255,6 +307,26 @@ int kvm_arch_get_registers(CPUState *cs)
     env->cp15.c2_mask = ~(0xffffffffu >> env->cp15.c2_control);
     env->cp15.c2_base_mask = ~(0x3fffu >> env->cp15.c2_control);
 
+    /* VFP registers */
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
+    for (i = 0; i < 32; i++) {
+        r.addr = (uintptr_t)(&env->vfp.regs[i]);
+        ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
+        if (ret) {
+            return ret;
+        }
+        r.id++;
+    }
+
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
+        KVM_REG_ARM_VFP_FPSCR;
+    r.addr = (uintptr_t)&fpscr;
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
+    if (ret) {
+        return ret;
+    }
+    vfp_set_fpscr(env, fpscr);
+
     return 0;
 }
 
commit 494b00c76afb906a2d093b71c8772331c2a19a89
Author: Christoffer Dall <cdall at cs.columbia.edu>
Date:   Tue Mar 5 00:34:41 2013 +0000

    ARM: KVM: Add support for KVM on ARM architecture
    
    Add basic support for KVM on ARM architecture.
    
    Signed-off-by: Christoffer Dall <cdall at cs.columbia.edu>
    [PMM: Minor tweaks and code cleanup, switch to ONE_REG]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/arm_pic.c b/hw/arm_pic.c
index ffb4d41..394bc93 100644
--- a/hw/arm_pic.c
+++ b/hw/arm_pic.c
@@ -9,6 +9,7 @@
 
 #include "hw.h"
 #include "arm-misc.h"
+#include "sysemu/kvm.h"
 
 /* Input 0 is IRQ and input 1 is FIQ.  */
 static void arm_pic_cpu_handler(void *opaque, int irq, int level)
@@ -34,7 +35,32 @@ static void arm_pic_cpu_handler(void *opaque, int irq, int level)
     }
 }
 
+static void kvm_arm_pic_cpu_handler(void *opaque, int irq, int level)
+{
+#ifdef CONFIG_KVM
+    ARMCPU *cpu = opaque;
+    CPUState *cs = CPU(cpu);
+    int kvm_irq = KVM_ARM_IRQ_TYPE_CPU << KVM_ARM_IRQ_TYPE_SHIFT;
+
+    switch (irq) {
+    case ARM_PIC_CPU_IRQ:
+        kvm_irq |= KVM_ARM_IRQ_CPU_IRQ;
+        break;
+    case ARM_PIC_CPU_FIQ:
+        kvm_irq |= KVM_ARM_IRQ_CPU_FIQ;
+        break;
+    default:
+        hw_error("kvm_arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
+    }
+    kvm_irq |= cs->cpu_index << KVM_ARM_IRQ_VCPU_SHIFT;
+    kvm_set_irq(kvm_state, kvm_irq, level ? 1 : 0);
+#endif
+}
+
 qemu_irq *arm_pic_init_cpu(ARMCPU *cpu)
 {
+    if (kvm_enabled()) {
+        return qemu_allocate_irqs(kvm_arm_pic_cpu_handler, cpu, 2);
+    }
     return qemu_allocate_irqs(arm_pic_cpu_handler, cpu, 2);
 }
diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
index b6f1a9e..d89b57c 100644
--- a/target-arm/Makefile.objs
+++ b/target-arm/Makefile.objs
@@ -1,4 +1,5 @@
 obj-y += arm-semi.o
 obj-$(CONFIG_SOFTMMU) += machine.o
+obj-$(CONFIG_KVM) += kvm.o
 obj-y += translate.o op_helper.o helper.o cpu.o
 obj-y += neon_helper.o iwmmxt_helper.o
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 2902ba5..c28a0d9 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -237,6 +237,7 @@ void arm_translate_init(void);
 void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu);
 int cpu_arm_exec(CPUARMState *s);
 void do_interrupt(CPUARMState *);
+int bank_number(int mode);
 void switch_mode(CPUARMState *, int);
 uint32_t do_arm_semihosting(CPUARMState *env);
 
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 7fa4ba0..6cad936 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1617,7 +1617,7 @@ uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode)
 #else
 
 /* Map CPU modes onto saved register banks.  */
-static inline int bank_number(int mode)
+int bank_number(int mode)
 {
     switch (mode) {
     case ARM_CPU_MODE_USR:
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
new file mode 100644
index 0000000..499b427
--- /dev/null
+++ b/target-arm/kvm.c
@@ -0,0 +1,334 @@
+/*
+ * ARM implementation of KVM hooks
+ *
+ * Copyright Christoffer Dall 2009-2010
+ *
+ * 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 <stdio.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <linux/kvm.h>
+
+#include "qemu-common.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
+#include "cpu.h"
+#include "hw/arm-misc.h"
+
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+    KVM_CAP_LAST_INFO
+};
+
+int kvm_arch_init(KVMState *s)
+{
+    /* For ARM interrupt delivery is always asynchronous,
+     * whether we are using an in-kernel VGIC or not.
+     */
+    kvm_async_interrupts_allowed = true;
+    return 0;
+}
+
+unsigned long kvm_arch_vcpu_id(CPUState *cpu)
+{
+    return cpu->cpu_index;
+}
+
+int kvm_arch_init_vcpu(CPUState *cs)
+{
+    struct kvm_vcpu_init init;
+
+    init.target = KVM_ARM_TARGET_CORTEX_A15;
+    memset(init.features, 0, sizeof(init.features));
+    return kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_INIT, &init);
+}
+
+typedef struct Reg {
+    uint64_t id;
+    int offset;
+} Reg;
+
+#define COREREG(KERNELNAME, QEMUFIELD)                       \
+    {                                                        \
+        KVM_REG_ARM | KVM_REG_SIZE_U32 |                     \
+        KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \
+        offsetof(CPUARMState, QEMUFIELD)                     \
+    }
+
+#define CP15REG(CRN, CRM, OPC1, OPC2, QEMUFIELD) \
+    {                                            \
+        KVM_REG_ARM | KVM_REG_SIZE_U32 |         \
+        (15 << KVM_REG_ARM_COPROC_SHIFT) |       \
+        ((CRN) << KVM_REG_ARM_32_CRN_SHIFT) |    \
+        ((CRM) << KVM_REG_ARM_CRM_SHIFT) |       \
+        ((OPC1) << KVM_REG_ARM_OPC1_SHIFT) |     \
+        ((OPC2) << KVM_REG_ARM_32_OPC2_SHIFT),   \
+        offsetof(CPUARMState, QEMUFIELD)         \
+    }
+
+static const Reg regs[] = {
+    /* R0_usr .. R14_usr */
+    COREREG(usr_regs.uregs[0], regs[0]),
+    COREREG(usr_regs.uregs[1], regs[1]),
+    COREREG(usr_regs.uregs[2], regs[2]),
+    COREREG(usr_regs.uregs[3], regs[3]),
+    COREREG(usr_regs.uregs[4], regs[4]),
+    COREREG(usr_regs.uregs[5], regs[5]),
+    COREREG(usr_regs.uregs[6], regs[6]),
+    COREREG(usr_regs.uregs[7], regs[7]),
+    COREREG(usr_regs.uregs[8], usr_regs[0]),
+    COREREG(usr_regs.uregs[9], usr_regs[1]),
+    COREREG(usr_regs.uregs[10], usr_regs[2]),
+    COREREG(usr_regs.uregs[11], usr_regs[3]),
+    COREREG(usr_regs.uregs[12], usr_regs[4]),
+    COREREG(usr_regs.uregs[13], banked_r13[0]),
+    COREREG(usr_regs.uregs[14], banked_r14[0]),
+    /* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */
+    COREREG(svc_regs[0], banked_r13[1]),
+    COREREG(svc_regs[1], banked_r14[1]),
+    COREREG(svc_regs[2], banked_spsr[1]),
+    COREREG(abt_regs[0], banked_r13[2]),
+    COREREG(abt_regs[1], banked_r14[2]),
+    COREREG(abt_regs[2], banked_spsr[2]),
+    COREREG(und_regs[0], banked_r13[3]),
+    COREREG(und_regs[1], banked_r14[3]),
+    COREREG(und_regs[2], banked_spsr[3]),
+    COREREG(irq_regs[0], banked_r13[4]),
+    COREREG(irq_regs[1], banked_r14[4]),
+    COREREG(irq_regs[2], banked_spsr[4]),
+    /* R8_fiq .. R14_fiq and SPSR_fiq */
+    COREREG(fiq_regs[0], fiq_regs[0]),
+    COREREG(fiq_regs[1], fiq_regs[1]),
+    COREREG(fiq_regs[2], fiq_regs[2]),
+    COREREG(fiq_regs[3], fiq_regs[3]),
+    COREREG(fiq_regs[4], fiq_regs[4]),
+    COREREG(fiq_regs[5], banked_r13[5]),
+    COREREG(fiq_regs[6], banked_r14[5]),
+    COREREG(fiq_regs[7], banked_spsr[5]),
+    /* R15 */
+    COREREG(usr_regs.uregs[15], regs[15]),
+    /* A non-comprehensive set of cp15 registers.
+     * TODO: drive this from the cp_regs hashtable instead.
+     */
+    CP15REG(1, 0, 0, 0, cp15.c1_sys), /* SCTLR */
+    CP15REG(2, 0, 0, 2, cp15.c2_control), /* TTBCR */
+    CP15REG(3, 0, 0, 0, cp15.c3), /* DACR */
+};
+
+int kvm_arch_put_registers(CPUState *cs, int level)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+    struct kvm_one_reg r;
+    int mode, bn;
+    int ret, i;
+    uint32_t cpsr;
+    uint64_t ttbr;
+
+    /* Make sure the banked regs are properly set */
+    mode = env->uncached_cpsr & CPSR_M;
+    bn = bank_number(mode);
+    if (mode == ARM_CPU_MODE_FIQ) {
+        memcpy(env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
+    } else {
+        memcpy(env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
+    }
+    env->banked_r13[bn] = env->regs[13];
+    env->banked_r14[bn] = env->regs[14];
+    env->banked_spsr[bn] = env->spsr;
+
+    /* Now we can safely copy stuff down to the kernel */
+    for (i = 0; i < ARRAY_SIZE(regs); i++) {
+        r.id = regs[i].id;
+        r.addr = (uintptr_t)(env) + regs[i].offset;
+        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
+        if (ret) {
+            return ret;
+        }
+    }
+
+    /* Special cases which aren't a single CPUARMState field */
+    cpsr = cpsr_read(env);
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 |
+        KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr);
+    r.addr = (uintptr_t)(&cpsr);
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
+    if (ret) {
+        return ret;
+    }
+
+    /* TTBR0: cp15 crm=2 opc1=0 */
+    ttbr = ((uint64_t)env->cp15.c2_base0_hi << 32) | env->cp15.c2_base0;
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | (15 << KVM_REG_ARM_COPROC_SHIFT) |
+        (2 << KVM_REG_ARM_CRM_SHIFT) | (0 << KVM_REG_ARM_OPC1_SHIFT);
+    r.addr = (uintptr_t)(&ttbr);
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
+    if (ret) {
+        return ret;
+    }
+
+    /* TTBR1: cp15 crm=2 opc1=1 */
+    ttbr = ((uint64_t)env->cp15.c2_base1_hi << 32) | env->cp15.c2_base1;
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | (15 << KVM_REG_ARM_COPROC_SHIFT) |
+        (2 << KVM_REG_ARM_CRM_SHIFT) | (1 << KVM_REG_ARM_OPC1_SHIFT);
+    r.addr = (uintptr_t)(&ttbr);
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
+
+    return ret;
+}
+
+int kvm_arch_get_registers(CPUState *cs)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+    struct kvm_one_reg r;
+    int mode, bn;
+    int ret, i;
+    uint32_t cpsr;
+    uint64_t ttbr;
+
+    for (i = 0; i < ARRAY_SIZE(regs); i++) {
+        r.id = regs[i].id;
+        r.addr = (uintptr_t)(env) + regs[i].offset;
+        ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
+        if (ret) {
+            return ret;
+        }
+    }
+
+    /* Special cases which aren't a single CPUARMState field */
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 |
+        KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr);
+    r.addr = (uintptr_t)(&cpsr);
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
+    if (ret) {
+        return ret;
+    }
+    cpsr_write(env, cpsr, 0xffffffff);
+
+    /* TTBR0: cp15 crm=2 opc1=0 */
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | (15 << KVM_REG_ARM_COPROC_SHIFT) |
+        (2 << KVM_REG_ARM_CRM_SHIFT) | (0 << KVM_REG_ARM_OPC1_SHIFT);
+    r.addr = (uintptr_t)(&ttbr);
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
+    if (ret) {
+        return ret;
+    }
+    env->cp15.c2_base0_hi = ttbr >> 32;
+    env->cp15.c2_base0 = ttbr;
+
+    /* TTBR1: cp15 crm=2 opc1=1 */
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | (15 << KVM_REG_ARM_COPROC_SHIFT) |
+        (2 << KVM_REG_ARM_CRM_SHIFT) | (1 << KVM_REG_ARM_OPC1_SHIFT);
+    r.addr = (uintptr_t)(&ttbr);
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
+    if (ret) {
+        return ret;
+    }
+    env->cp15.c2_base1_hi = ttbr >> 32;
+    env->cp15.c2_base1 = ttbr;
+
+    /* Make sure the current mode regs are properly set */
+    mode = env->uncached_cpsr & CPSR_M;
+    bn = bank_number(mode);
+    if (mode == ARM_CPU_MODE_FIQ) {
+        memcpy(env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
+    } else {
+        memcpy(env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
+    }
+    env->regs[13] = env->banked_r13[bn];
+    env->regs[14] = env->banked_r14[bn];
+    env->spsr = env->banked_spsr[bn];
+
+    /* The main GET_ONE_REG loop above set c2_control, but we need to
+     * update some extra cached precomputed values too.
+     * When this is driven from the cp_regs hashtable then this ugliness
+     * can disappear because we'll use the access function which sets
+     * these values automatically.
+     */
+    env->cp15.c2_mask = ~(0xffffffffu >> env->cp15.c2_control);
+    env->cp15.c2_base_mask = ~(0x3fffu >> env->cp15.c2_control);
+
+    return 0;
+}
+
+void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
+{
+}
+
+void kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
+{
+}
+
+int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
+{
+    return 0;
+}
+
+void kvm_arch_reset_vcpu(CPUState *cs)
+{
+}
+
+bool kvm_arch_stop_on_emulation_error(CPUState *cs)
+{
+    return true;
+}
+
+int kvm_arch_process_async_events(CPUState *cs)
+{
+    return 0;
+}
+
+int kvm_arch_on_sigbus_vcpu(CPUState *cs, int code, void *addr)
+{
+    return 1;
+}
+
+int kvm_arch_on_sigbus(int code, void *addr)
+{
+    return 1;
+}
+
+void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg)
+{
+    qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
+}
+
+int kvm_arch_insert_sw_breakpoint(CPUState *cs,
+                                  struct kvm_sw_breakpoint *bp)
+{
+    qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
+    return -EINVAL;
+}
+
+int kvm_arch_insert_hw_breakpoint(target_ulong addr,
+                                  target_ulong len, int type)
+{
+    qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
+    return -EINVAL;
+}
+
+int kvm_arch_remove_hw_breakpoint(target_ulong addr,
+                                  target_ulong len, int type)
+{
+    qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
+    return -EINVAL;
+}
+
+int kvm_arch_remove_sw_breakpoint(CPUState *cs,
+                                  struct kvm_sw_breakpoint *bp)
+{
+    qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
+    return -EINVAL;
+}
+
+void kvm_arch_remove_all_hw_breakpoints(void)
+{
+    qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
+}
commit f5206413affd658e2fdcf893c810d715b2c7fec6
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 5 00:34:40 2013 +0000

    target-arm: Drop CPUARMState* argument from bank_number()
    
    Drop the CPUARMState* argument from bank_number(), since we only
    use it for passing to cpu_abort(). Use hw_error() instead.
    This avoids propagating further interfaces using env pointers.
    
    In the long term this function's callers need auditing to fix
    problems where badly behaved guests can pass invalid bank numbers.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index e97e1a5..7fa4ba0 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1617,7 +1617,7 @@ uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode)
 #else
 
 /* Map CPU modes onto saved register banks.  */
-static inline int bank_number(CPUARMState *env, int mode)
+static inline int bank_number(int mode)
 {
     switch (mode) {
     case ARM_CPU_MODE_USR:
@@ -1634,8 +1634,7 @@ static inline int bank_number(CPUARMState *env, int mode)
     case ARM_CPU_MODE_FIQ:
         return 5;
     }
-    cpu_abort(env, "Bad mode %x\n", mode);
-    return -1;
+    hw_error("bank number requested for bad CPSR mode value 0x%x\n", mode);
 }
 
 void switch_mode(CPUARMState *env, int mode)
@@ -1655,12 +1654,12 @@ void switch_mode(CPUARMState *env, int mode)
         memcpy (env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
     }
 
-    i = bank_number(env, old_mode);
+    i = bank_number(old_mode);
     env->banked_r13[i] = env->regs[13];
     env->banked_r14[i] = env->regs[14];
     env->banked_spsr[i] = env->spsr;
 
-    i = bank_number(env, mode);
+    i = bank_number(mode);
     env->regs[13] = env->banked_r13[i];
     env->regs[14] = env->banked_r14[i];
     env->spsr = env->banked_spsr[i];
@@ -2530,7 +2529,7 @@ void HELPER(set_r13_banked)(CPUARMState *env, uint32_t mode, uint32_t val)
     if ((env->uncached_cpsr & CPSR_M) == mode) {
         env->regs[13] = val;
     } else {
-        env->banked_r13[bank_number(env, mode)] = val;
+        env->banked_r13[bank_number(mode)] = val;
     }
 }
 
@@ -2539,7 +2538,7 @@ uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode)
     if ((env->uncached_cpsr & CPSR_M) == mode) {
         return env->regs[13];
     } else {
-        return env->banked_r13[bank_number(env, mode)];
+        return env->banked_r13[bank_number(mode)];
     }
 }
 
commit eadd0e4413c9b69015c798909f48ec48ab0c7bd4
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 5 00:34:40 2013 +0000

    linux-headers: resync from mainline to add ARM KVM headers
    
    Resync QEMU's copy of the Linux kernel headers from
    git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
    commit 2ef14f4. This adds the ARM KVM headers, since ARM KVM
    support has just hit mainline via Russell's ARM tree.
    
    This is not a pure sync -- I have removed by hand some changes
    that would have reverted updates for s390x and ppc which have not
    yet hit mainline.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/linux-headers/asm-arm/kvm.h b/linux-headers/asm-arm/kvm.h
new file mode 100644
index 0000000..023bfeb
--- /dev/null
+++ b/linux-headers/asm-arm/kvm.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall at virtualopensystems.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __ARM_KVM_H__
+#define __ARM_KVM_H__
+
+#include <linux/types.h>
+#include <asm/ptrace.h>
+
+#define __KVM_HAVE_GUEST_DEBUG
+#define __KVM_HAVE_IRQ_LINE
+
+#define KVM_REG_SIZE(id)						\
+	(1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
+
+/* Valid for svc_regs, abt_regs, und_regs, irq_regs in struct kvm_regs */
+#define KVM_ARM_SVC_sp		svc_regs[0]
+#define KVM_ARM_SVC_lr		svc_regs[1]
+#define KVM_ARM_SVC_spsr	svc_regs[2]
+#define KVM_ARM_ABT_sp		abt_regs[0]
+#define KVM_ARM_ABT_lr		abt_regs[1]
+#define KVM_ARM_ABT_spsr	abt_regs[2]
+#define KVM_ARM_UND_sp		und_regs[0]
+#define KVM_ARM_UND_lr		und_regs[1]
+#define KVM_ARM_UND_spsr	und_regs[2]
+#define KVM_ARM_IRQ_sp		irq_regs[0]
+#define KVM_ARM_IRQ_lr		irq_regs[1]
+#define KVM_ARM_IRQ_spsr	irq_regs[2]
+
+/* Valid only for fiq_regs in struct kvm_regs */
+#define KVM_ARM_FIQ_r8		fiq_regs[0]
+#define KVM_ARM_FIQ_r9		fiq_regs[1]
+#define KVM_ARM_FIQ_r10		fiq_regs[2]
+#define KVM_ARM_FIQ_fp		fiq_regs[3]
+#define KVM_ARM_FIQ_ip		fiq_regs[4]
+#define KVM_ARM_FIQ_sp		fiq_regs[5]
+#define KVM_ARM_FIQ_lr		fiq_regs[6]
+#define KVM_ARM_FIQ_spsr	fiq_regs[7]
+
+struct kvm_regs {
+	struct pt_regs usr_regs;/* R0_usr - R14_usr, PC, CPSR */
+	__u32 svc_regs[3];	/* SP_svc, LR_svc, SPSR_svc */
+	__u32 abt_regs[3];	/* SP_abt, LR_abt, SPSR_abt */
+	__u32 und_regs[3];	/* SP_und, LR_und, SPSR_und */
+	__u32 irq_regs[3];	/* SP_irq, LR_irq, SPSR_irq */
+	__u32 fiq_regs[8];	/* R8_fiq - R14_fiq, SPSR_fiq */
+};
+
+/* Supported Processor Types */
+#define KVM_ARM_TARGET_CORTEX_A15	0
+#define KVM_ARM_NUM_TARGETS		1
+
+/* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
+#define KVM_ARM_DEVICE_TYPE_SHIFT	0
+#define KVM_ARM_DEVICE_TYPE_MASK	(0xffff << KVM_ARM_DEVICE_TYPE_SHIFT)
+#define KVM_ARM_DEVICE_ID_SHIFT		16
+#define KVM_ARM_DEVICE_ID_MASK		(0xffff << KVM_ARM_DEVICE_ID_SHIFT)
+
+/* Supported device IDs */
+#define KVM_ARM_DEVICE_VGIC_V2		0
+
+/* Supported VGIC address types  */
+#define KVM_VGIC_V2_ADDR_TYPE_DIST	0
+#define KVM_VGIC_V2_ADDR_TYPE_CPU	1
+
+#define KVM_VGIC_V2_DIST_SIZE		0x1000
+#define KVM_VGIC_V2_CPU_SIZE		0x2000
+
+#define KVM_ARM_VCPU_POWER_OFF		0 /* CPU is started in OFF state */
+
+struct kvm_vcpu_init {
+	__u32 target;
+	__u32 features[7];
+};
+
+struct kvm_sregs {
+};
+
+struct kvm_fpu {
+};
+
+struct kvm_guest_debug_arch {
+};
+
+struct kvm_debug_exit_arch {
+};
+
+struct kvm_sync_regs {
+};
+
+struct kvm_arch_memory_slot {
+};
+
+/* If you need to interpret the index values, here is the key: */
+#define KVM_REG_ARM_COPROC_MASK		0x000000000FFF0000
+#define KVM_REG_ARM_COPROC_SHIFT	16
+#define KVM_REG_ARM_32_OPC2_MASK	0x0000000000000007
+#define KVM_REG_ARM_32_OPC2_SHIFT	0
+#define KVM_REG_ARM_OPC1_MASK		0x0000000000000078
+#define KVM_REG_ARM_OPC1_SHIFT		3
+#define KVM_REG_ARM_CRM_MASK		0x0000000000000780
+#define KVM_REG_ARM_CRM_SHIFT		7
+#define KVM_REG_ARM_32_CRN_MASK		0x0000000000007800
+#define KVM_REG_ARM_32_CRN_SHIFT	11
+
+/* Normal registers are mapped as coprocessor 16. */
+#define KVM_REG_ARM_CORE		(0x0010 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_CORE_REG(name)	(offsetof(struct kvm_regs, name) / 4)
+
+/* Some registers need more space to represent values. */
+#define KVM_REG_ARM_DEMUX		(0x0011 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_DEMUX_ID_MASK	0x000000000000FF00
+#define KVM_REG_ARM_DEMUX_ID_SHIFT	8
+#define KVM_REG_ARM_DEMUX_ID_CCSIDR	(0x00 << KVM_REG_ARM_DEMUX_ID_SHIFT)
+#define KVM_REG_ARM_DEMUX_VAL_MASK	0x00000000000000FF
+#define KVM_REG_ARM_DEMUX_VAL_SHIFT	0
+
+/* VFP registers: we could overload CP10 like ARM does, but that's ugly. */
+#define KVM_REG_ARM_VFP			(0x0012 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_VFP_MASK		0x000000000000FFFF
+#define KVM_REG_ARM_VFP_BASE_REG	0x0
+#define KVM_REG_ARM_VFP_FPSID		0x1000
+#define KVM_REG_ARM_VFP_FPSCR		0x1001
+#define KVM_REG_ARM_VFP_MVFR1		0x1006
+#define KVM_REG_ARM_VFP_MVFR0		0x1007
+#define KVM_REG_ARM_VFP_FPEXC		0x1008
+#define KVM_REG_ARM_VFP_FPINST		0x1009
+#define KVM_REG_ARM_VFP_FPINST2		0x100A
+
+
+/* KVM_IRQ_LINE irq field index values */
+#define KVM_ARM_IRQ_TYPE_SHIFT		24
+#define KVM_ARM_IRQ_TYPE_MASK		0xff
+#define KVM_ARM_IRQ_VCPU_SHIFT		16
+#define KVM_ARM_IRQ_VCPU_MASK		0xff
+#define KVM_ARM_IRQ_NUM_SHIFT		0
+#define KVM_ARM_IRQ_NUM_MASK		0xffff
+
+/* irq_type field */
+#define KVM_ARM_IRQ_TYPE_CPU		0
+#define KVM_ARM_IRQ_TYPE_SPI		1
+#define KVM_ARM_IRQ_TYPE_PPI		2
+
+/* out-of-kernel GIC cpu interrupt injection irq_number field */
+#define KVM_ARM_IRQ_CPU_IRQ		0
+#define KVM_ARM_IRQ_CPU_FIQ		1
+
+/* Highest supported SPI, from VGIC_NR_IRQS */
+#define KVM_ARM_IRQ_GIC_MAX		127
+
+/* PSCI interface */
+#define KVM_PSCI_FN_BASE		0x95c1ba5e
+#define KVM_PSCI_FN(n)			(KVM_PSCI_FN_BASE + (n))
+
+#define KVM_PSCI_FN_CPU_SUSPEND		KVM_PSCI_FN(0)
+#define KVM_PSCI_FN_CPU_OFF		KVM_PSCI_FN(1)
+#define KVM_PSCI_FN_CPU_ON		KVM_PSCI_FN(2)
+#define KVM_PSCI_FN_MIGRATE		KVM_PSCI_FN(3)
+
+#define KVM_PSCI_RET_SUCCESS		0
+#define KVM_PSCI_RET_NI			((unsigned long)-1)
+#define KVM_PSCI_RET_INVAL		((unsigned long)-2)
+#define KVM_PSCI_RET_DENIED		((unsigned long)-3)
+
+#endif /* __ARM_KVM_H__ */
diff --git a/linux-headers/asm-arm/kvm_para.h b/linux-headers/asm-arm/kvm_para.h
new file mode 100644
index 0000000..14fab8f
--- /dev/null
+++ b/linux-headers/asm-arm/kvm_para.h
@@ -0,0 +1 @@
+#include <asm-generic/kvm_para.h>
diff --git a/linux-headers/asm-generic/kvm_para.h b/linux-headers/asm-generic/kvm_para.h
new file mode 100644
index 0000000..486f0af
--- /dev/null
+++ b/linux-headers/asm-generic/kvm_para.h
@@ -0,0 +1,4 @@
+/*
+ * There isn't anything here, but the file must not be empty or patch
+ * will delete it.
+ */
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 5af9357..caca979 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -115,6 +115,7 @@ struct kvm_irq_level {
 	 * ACPI gsi notion of irq.
 	 * For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47..
 	 * For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23..
+	 * For ARM: See Documentation/virtual/kvm/api.txt
 	 */
 	union {
 		__u32 irq;
@@ -662,6 +663,8 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_PPC_HTAB_FD 84
 #define KVM_CAP_S390_CSS_SUPPORT 85
 #define KVM_CAP_PPC_EPR 86
+#define KVM_CAP_ARM_PSCI 87
+#define KVM_CAP_ARM_SET_DEVICE_ADDR 88
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -791,6 +794,11 @@ struct kvm_dirty_tlb {
 #define KVM_REG_SIZE_U512	0x0060000000000000ULL
 #define KVM_REG_SIZE_U1024	0x0070000000000000ULL
 
+struct kvm_reg_list {
+	__u64 n; /* number of regs */
+	__u64 reg[0];
+};
+
 struct kvm_one_reg {
 	__u64 id;
 	__u64 addr;
@@ -804,6 +812,11 @@ struct kvm_msi {
 	__u8  pad[16];
 };
 
+struct kvm_arm_device_addr {
+	__u64 id;
+	__u64 addr;
+};
+
 /*
  * ioctls for VM fds
  */
@@ -889,6 +902,8 @@ struct kvm_s390_ucas_mapping {
 #define KVM_ALLOCATE_RMA	  _IOR(KVMIO,  0xa9, struct kvm_allocate_rma)
 /* Available with KVM_CAP_PPC_HTAB_FD */
 #define KVM_PPC_GET_HTAB_FD	  _IOW(KVMIO,  0xaa, struct kvm_get_htab_fd)
+/* Available with KVM_CAP_ARM_SET_DEVICE_ADDR */
+#define KVM_ARM_SET_DEVICE_ADDR	  _IOW(KVMIO,  0xab, struct kvm_arm_device_addr)
 
 /*
  * ioctls for vcpu fds
@@ -959,6 +974,8 @@ struct kvm_s390_ucas_mapping {
 #define KVM_SET_ONE_REG		  _IOW(KVMIO,  0xac, struct kvm_one_reg)
 /* VM is being stopped by host */
 #define KVM_KVMCLOCK_CTRL	  _IO(KVMIO,   0xad)
+#define KVM_ARM_VCPU_INIT	  _IOW(KVMIO,  0xae, struct kvm_vcpu_init)
+#define KVM_GET_REG_LIST	  _IOWR(KVMIO, 0xb0, struct kvm_reg_list)
 
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU	(1 << 0)
 #define KVM_DEV_ASSIGN_PCI_2_3		(1 << 1)
commit 2e07b297e0b450fe38bab115f71749e032d7191c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 5 00:34:40 2013 +0000

    oslib-posix: Align to permit transparent hugepages on ARM Linux
    
    ARM Linux (like x86-64 Linux) can use transparent hugepages for
    KVM if memory blocks are 2MiB aligned; set QEMU_VMALLOC_ALIGN
    accordingly.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index b4152fb..433dd68 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -35,7 +35,7 @@
 extern int daemon(int, int);
 #endif
 
-#if defined(__linux__) && defined(__x86_64__)
+#if defined(__linux__) && (defined(__x86_64__) || defined(__arm__))
    /* Use 2 MiB alignment so transparent hugepages can be used by KVM.
       Valgrind does not support alignments larger than 1 MiB,
       therefore we need special code which handles running on Valgrind. */
commit 00115976bb066d4b33dbb07a92f8bde5ec8b9518
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 5 00:31:17 2013 +0000

    target-arm: Don't decode RFE or SRS on M profile cores
    
    M profile cores do not have the RFE or SRS instructions, so
    correctly UNDEF these insn patterns on those cores.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index e16c113..35a21be 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -8180,9 +8180,10 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
         } else {
             /* Load/store multiple, RFE, SRS.  */
             if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
-                /* Not available in user mode.  */
-                if (IS_USER(s))
+                /* RFE, SRS: not available in user mode or on M profile */
+                if (IS_USER(s) || IS_M(env)) {
                     goto illegal_op;
+                }
                 if (insn & (1 << 20)) {
                     /* rfe */
                     addr = load_reg(s, rn);
commit 81465888c5306cd94abb9847e560796fd13d3c2f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 5 00:31:17 2013 +0000

    target-arm: Factor out handling of SRS instruction
    
    Factor out the handling of the SRS instruction rather than
    duplicating it between the Thumb and ARM decoders. This in
    passing fixes two bugs in the Thumb decoder's SRS handling
    which didn't exist in the ARM decoder:
     * (LP:1079080) storing CPSR rather than SPSR (fixed in the
       ARM decoder in commit c67b6b71 in 2009)
     * failing to free the 'addr' TCG temp in the writeback case
    
    Reported-by: Cesson Vincent <vcesson at stmi.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index db63c6e..e16c113 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6601,6 +6601,70 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
 }
 #endif
 
+/* gen_srs:
+ * @env: CPUARMState
+ * @s: DisasContext
+ * @mode: mode field from insn (which stack to store to)
+ * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
+ * @writeback: true if writeback bit set
+ *
+ * Generate code for the SRS (Store Return State) insn.
+ */
+static void gen_srs(DisasContext *s,
+                    uint32_t mode, uint32_t amode, bool writeback)
+{
+    int32_t offset;
+    TCGv_i32 addr = tcg_temp_new_i32();
+    TCGv_i32 tmp = tcg_const_i32(mode);
+    gen_helper_get_r13_banked(addr, cpu_env, tmp);
+    tcg_temp_free_i32(tmp);
+    switch (amode) {
+    case 0: /* DA */
+        offset = -4;
+        break;
+    case 1: /* IA */
+        offset = 0;
+        break;
+    case 2: /* DB */
+        offset = -8;
+        break;
+    case 3: /* IB */
+        offset = 4;
+        break;
+    default:
+        abort();
+    }
+    tcg_gen_addi_i32(addr, addr, offset);
+    tmp = load_reg(s, 14);
+    gen_st32(tmp, addr, 0);
+    tmp = load_cpu_field(spsr);
+    tcg_gen_addi_i32(addr, addr, 4);
+    gen_st32(tmp, addr, 0);
+    if (writeback) {
+        switch (amode) {
+        case 0:
+            offset = -8;
+            break;
+        case 1:
+            offset = 4;
+            break;
+        case 2:
+            offset = -4;
+            break;
+        case 3:
+            offset = 0;
+            break;
+        default:
+            abort();
+        }
+        tcg_gen_addi_i32(addr, addr, offset);
+        tmp = tcg_const_i32(mode);
+        gen_helper_set_r13_banked(cpu_env, tmp, addr);
+        tcg_temp_free_i32(tmp);
+    }
+    tcg_temp_free_i32(addr);
+}
+
 static void disas_arm_insn(CPUARMState * env, DisasContext *s)
 {
     unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
@@ -6693,49 +6757,11 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
             }
         } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
             /* srs */
-            int32_t offset;
-            if (IS_USER(s))
+            if (IS_USER(s)) {
                 goto illegal_op;
-            ARCH(6);
-            op1 = (insn & 0x1f);
-            addr = tcg_temp_new_i32();
-            tmp = tcg_const_i32(op1);
-            gen_helper_get_r13_banked(addr, cpu_env, tmp);
-            tcg_temp_free_i32(tmp);
-            i = (insn >> 23) & 3;
-            switch (i) {
-            case 0: offset = -4; break; /* DA */
-            case 1: offset = 0; break; /* IA */
-            case 2: offset = -8; break; /* DB */
-            case 3: offset = 4; break; /* IB */
-            default: abort();
             }
-            if (offset)
-                tcg_gen_addi_i32(addr, addr, offset);
-            tmp = load_reg(s, 14);
-            gen_st32(tmp, addr, 0);
-            tmp = load_cpu_field(spsr);
-            tcg_gen_addi_i32(addr, addr, 4);
-            gen_st32(tmp, addr, 0);
-            if (insn & (1 << 21)) {
-                /* Base writeback.  */
-                switch (i) {
-                case 0: offset = -8; break;
-                case 1: offset = 4; break;
-                case 2: offset = -4; break;
-                case 3: offset = 0; break;
-                default: abort();
-                }
-                if (offset)
-                    tcg_gen_addi_i32(addr, addr, offset);
-                tmp = tcg_const_i32(op1);
-                gen_helper_set_r13_banked(cpu_env, tmp, addr);
-                tcg_temp_free_i32(tmp);
-                tcg_temp_free_i32(addr);
-            } else {
-                tcg_temp_free_i32(addr);
-            }
-            return;
+            ARCH(6);
+            gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
         } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
             /* rfe */
             int32_t offset;
@@ -8180,32 +8206,8 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
                     gen_rfe(s, tmp, tmp2);
                 } else {
                     /* srs */
-                    op = (insn & 0x1f);
-                    addr = tcg_temp_new_i32();
-                    tmp = tcg_const_i32(op);
-                    gen_helper_get_r13_banked(addr, cpu_env, tmp);
-                    tcg_temp_free_i32(tmp);
-                    if ((insn & (1 << 24)) == 0) {
-                        tcg_gen_addi_i32(addr, addr, -8);
-                    }
-                    tmp = load_reg(s, 14);
-                    gen_st32(tmp, addr, 0);
-                    tcg_gen_addi_i32(addr, addr, 4);
-                    tmp = tcg_temp_new_i32();
-                    gen_helper_cpsr_read(tmp, cpu_env);
-                    gen_st32(tmp, addr, 0);
-                    if (insn & (1 << 21)) {
-                        if ((insn & (1 << 24)) == 0) {
-                            tcg_gen_addi_i32(addr, addr, -4);
-                        } else {
-                            tcg_gen_addi_i32(addr, addr, 4);
-                        }
-                        tmp = tcg_const_i32(op);
-                        gen_helper_set_r13_banked(cpu_env, tmp, addr);
-                        tcg_temp_free_i32(tmp);
-                    } else {
-                        tcg_temp_free_i32(addr);
-                    }
+                    gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
+                            insn & (1 << 21));
                 }
             } else {
                 int i, loaded_base = 0;
commit 26135ead80fa1fd13e95c162dacfd06f2ba82981
Author: Richard Sandiford <rdsandiford at googlemail.com>
Date:   Mon Jan 21 20:43:31 2013 +0000

    target-mips: Fix accumulator selection for MIPS16 and microMIPS
    
    Add accumulator arguments to gen_HILO and gen_muldiv, rather than
    extracting the accumulator directly from ctx->opcode.  The extraction
    was only right for the standard encoding: MIPS16 doesn't have access
    to the DSP registers, while microMIPS encodes the accumulator register
    in a different field (bits 14 and 15).
    
    Passing the accumulator register is probably an over-generalisation
    for division and 64-bit multiplication, which never access anything
    other than HI and LO, and which always pass 0 as the new argument.
    Separating them felt a bit fussy though.
    
    Signed-off-by: Richard Sandiford <rdsandiford at googlemail.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/translate.c b/target-mips/translate.c
index 6ce2f03..a51f430 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -2582,10 +2582,9 @@ static void gen_shift(DisasContext *ctx, uint32_t opc,
 }
 
 /* Arithmetic on HI/LO registers */
-static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
+static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
 {
     const char *opn = "hilo";
-    unsigned int acc;
 
     if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
         /* Treat as NOP. */
@@ -2593,12 +2592,6 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
         return;
     }
 
-    if (opc == OPC_MFHI || opc == OPC_MFLO) {
-        acc = ((ctx->opcode) >> 21) & 0x03;
-    } else {
-        acc = ((ctx->opcode) >> 11) & 0x03;
-    }
-
     if (acc != 0) {
         check_dsp(ctx);
     }
@@ -2661,12 +2654,11 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
     MIPS_DEBUG("%s %s", opn, regnames[reg]);
 }
 
-static void gen_muldiv (DisasContext *ctx, uint32_t opc,
-                        int rs, int rt)
+static void gen_muldiv(DisasContext *ctx, uint32_t opc,
+                       int acc, int rs, int rt)
 {
     const char *opn = "mul/div";
     TCGv t0, t1;
-    unsigned int acc;
 
     t0 = tcg_temp_new();
     t1 = tcg_temp_new();
@@ -2674,6 +2666,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
     gen_load_gpr(t0, rs);
     gen_load_gpr(t1, rt);
 
+    if (acc != 0) {
+        check_dsp(ctx);
+    }
+
     switch (opc) {
     case OPC_DIV:
         {
@@ -2688,10 +2684,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
             tcg_gen_or_tl(t2, t2, t3);
             tcg_gen_movi_tl(t3, 0);
             tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
-            tcg_gen_div_tl(cpu_LO[0], t0, t1);
-            tcg_gen_rem_tl(cpu_HI[0], t0, t1);
-            tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
-            tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
+            tcg_gen_div_tl(cpu_LO[acc], t0, t1);
+            tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
+            tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
+            tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
             tcg_temp_free(t3);
             tcg_temp_free(t2);
         }
@@ -2704,10 +2700,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
             tcg_gen_ext32u_tl(t0, t0);
             tcg_gen_ext32u_tl(t1, t1);
             tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
-            tcg_gen_divu_tl(cpu_LO[0], t0, t1);
-            tcg_gen_remu_tl(cpu_HI[0], t0, t1);
-            tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
-            tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
+            tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
+            tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
+            tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
+            tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
             tcg_temp_free(t3);
             tcg_temp_free(t2);
         }
@@ -2717,11 +2713,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
         {
             TCGv_i32 t2 = tcg_temp_new_i32();
             TCGv_i32 t3 = tcg_temp_new_i32();
-            acc = ((ctx->opcode) >> 11) & 0x03;
-            if (acc != 0) {
-                check_dsp(ctx);
-            }
-
             tcg_gen_trunc_tl_i32(t2, t0);
             tcg_gen_trunc_tl_i32(t3, t1);
             tcg_gen_muls2_i32(t2, t3, t2, t3);
@@ -2736,11 +2727,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
         {
             TCGv_i32 t2 = tcg_temp_new_i32();
             TCGv_i32 t3 = tcg_temp_new_i32();
-            acc = ((ctx->opcode) >> 11) & 0x03;
-            if (acc != 0) {
-                check_dsp(ctx);
-            }
-
             tcg_gen_trunc_tl_i32(t2, t0);
             tcg_gen_trunc_tl_i32(t3, t1);
             tcg_gen_mulu2_i32(t2, t3, t2, t3);
@@ -2763,8 +2749,8 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
             tcg_gen_or_tl(t2, t2, t3);
             tcg_gen_movi_tl(t3, 0);
             tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
-            tcg_gen_div_tl(cpu_LO[0], t0, t1);
-            tcg_gen_rem_tl(cpu_HI[0], t0, t1);
+            tcg_gen_div_tl(cpu_LO[acc], t0, t1);
+            tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
             tcg_temp_free(t3);
             tcg_temp_free(t2);
         }
@@ -2775,19 +2761,19 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
             TCGv t2 = tcg_const_tl(0);
             TCGv t3 = tcg_const_tl(1);
             tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
-            tcg_gen_divu_i64(cpu_LO[0], t0, t1);
-            tcg_gen_remu_i64(cpu_HI[0], t0, t1);
+            tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
+            tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
             tcg_temp_free(t3);
             tcg_temp_free(t2);
         }
         opn = "ddivu";
         break;
     case OPC_DMULT:
-        tcg_gen_muls2_i64(cpu_LO[0], cpu_HI[0], t0, t1);
+        tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
         opn = "dmult";
         break;
     case OPC_DMULTU:
-        tcg_gen_mulu2_i64(cpu_LO[0], cpu_HI[0], t0, t1);
+        tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
         opn = "dmultu";
         break;
 #endif
@@ -2795,10 +2781,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
         {
             TCGv_i64 t2 = tcg_temp_new_i64();
             TCGv_i64 t3 = tcg_temp_new_i64();
-            acc = ((ctx->opcode) >> 11) & 0x03;
-            if (acc != 0) {
-                check_dsp(ctx);
-            }
 
             tcg_gen_ext_tl_i64(t2, t0);
             tcg_gen_ext_tl_i64(t3, t1);
@@ -2819,10 +2801,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
         {
             TCGv_i64 t2 = tcg_temp_new_i64();
             TCGv_i64 t3 = tcg_temp_new_i64();
-            acc = ((ctx->opcode) >> 11) & 0x03;
-            if (acc != 0) {
-                check_dsp(ctx);
-            }
 
             tcg_gen_ext32u_tl(t0, t0);
             tcg_gen_ext32u_tl(t1, t1);
@@ -2845,10 +2823,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
         {
             TCGv_i64 t2 = tcg_temp_new_i64();
             TCGv_i64 t3 = tcg_temp_new_i64();
-            acc = ((ctx->opcode) >> 11) & 0x03;
-            if (acc != 0) {
-                check_dsp(ctx);
-            }
 
             tcg_gen_ext_tl_i64(t2, t0);
             tcg_gen_ext_tl_i64(t3, t1);
@@ -2869,10 +2843,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
         {
             TCGv_i64 t2 = tcg_temp_new_i64();
             TCGv_i64 t3 = tcg_temp_new_i64();
-            acc = ((ctx->opcode) >> 11) & 0x03;
-            if (acc != 0) {
-                check_dsp(ctx);
-            }
 
             tcg_gen_ext32u_tl(t0, t0);
             tcg_gen_ext32u_tl(t1, t1);
@@ -10135,7 +10105,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
             gen_logic(ctx, OPC_NOR, rx, ry, 0);
             break;
         case RR_MFHI:
-            gen_HILO(ctx, OPC_MFHI, rx);
+            gen_HILO(ctx, OPC_MFHI, 0, rx);
             break;
         case RR_CNVT:
             switch (cnvt_op) {
@@ -10167,7 +10137,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
             }
             break;
         case RR_MFLO:
-            gen_HILO(ctx, OPC_MFLO, rx);
+            gen_HILO(ctx, OPC_MFLO, 0, rx);
             break;
 #if defined (TARGET_MIPS64)
         case RR_DSRA:
@@ -10188,33 +10158,33 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
             break;
 #endif
         case RR_MULT:
-            gen_muldiv(ctx, OPC_MULT, rx, ry);
+            gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
             break;
         case RR_MULTU:
-            gen_muldiv(ctx, OPC_MULTU, rx, ry);
+            gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
             break;
         case RR_DIV:
-            gen_muldiv(ctx, OPC_DIV, rx, ry);
+            gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
             break;
         case RR_DIVU:
-            gen_muldiv(ctx, OPC_DIVU, rx, ry);
+            gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
             break;
 #if defined (TARGET_MIPS64)
         case RR_DMULT:
             check_mips_64(ctx);
-            gen_muldiv(ctx, OPC_DMULT, rx, ry);
+            gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
             break;
         case RR_DMULTU:
             check_mips_64(ctx);
-            gen_muldiv(ctx, OPC_DMULTU, rx, ry);
+            gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
             break;
         case RR_DDIV:
             check_mips_64(ctx);
-            gen_muldiv(ctx, OPC_DDIV, rx, ry);
+            gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
             break;
         case RR_DDIVU:
             check_mips_64(ctx);
-            gen_muldiv(ctx, OPC_DDIVU, rx, ry);
+            gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
             break;
 #endif
         default:
@@ -10923,11 +10893,11 @@ static void gen_pool16c_insn(DisasContext *ctx, int *is_branch)
         break;
     case MFHI16 + 0:
     case MFHI16 + 1:
-        gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
+        gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
         break;
     case MFLO16 + 0:
     case MFLO16 + 1:
-        gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
+        gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
         break;
     case BREAK16:
         generate_exception(ctx, EXCP_BREAK);
@@ -11125,30 +11095,34 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
             break;
         case MULT:
             mips32_op = OPC_MULT;
-            goto do_muldiv;
+            goto do_mul;
         case MULTU:
             mips32_op = OPC_MULTU;
-            goto do_muldiv;
+            goto do_mul;
         case DIV:
             mips32_op = OPC_DIV;
-            goto do_muldiv;
+            goto do_div;
         case DIVU:
             mips32_op = OPC_DIVU;
-            goto do_muldiv;
+            goto do_div;
+        do_div:
+            check_insn(ctx, ISA_MIPS32);
+            gen_muldiv(ctx, mips32_op, 0, rs, rt);
+            break;
         case MADD:
             mips32_op = OPC_MADD;
-            goto do_muldiv;
+            goto do_mul;
         case MADDU:
             mips32_op = OPC_MADDU;
-            goto do_muldiv;
+            goto do_mul;
         case MSUB:
             mips32_op = OPC_MSUB;
-            goto do_muldiv;
+            goto do_mul;
         case MSUBU:
             mips32_op = OPC_MSUBU;
-        do_muldiv:
+        do_mul:
             check_insn(ctx, ISA_MIPS32);
-            gen_muldiv(ctx, mips32_op, rs, rt);
+            gen_muldiv(ctx, mips32_op, (ctx->opcode >> 14) & 3, rs, rt);
             break;
         default:
             goto pool32axf_invalid;
@@ -11285,18 +11259,18 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
         }
         break;
     case 0x35:
-        switch (minor) {
+        switch (minor & 3) {
         case MFHI32:
-            gen_HILO(ctx, OPC_MFHI, rs);
+            gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
             break;
         case MFLO32:
-            gen_HILO(ctx, OPC_MFLO, rs);
+            gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
             break;
         case MTHI32:
-            gen_HILO(ctx, OPC_MTHI, rs);
+            gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
             break;
         case MTLO32:
-            gen_HILO(ctx, OPC_MTLO, rs);
+            gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
             break;
         default:
             goto pool32axf_invalid;
@@ -14469,13 +14443,19 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         case OPC_XOR:
             gen_logic(ctx, op1, rd, rs, rt);
             break;
-        case OPC_MULT ... OPC_DIVU:
+        case OPC_MULT:
+        case OPC_MULTU:
             if (sa) {
                 check_insn(ctx, INSN_VR54XX);
                 op1 = MASK_MUL_VR54XX(ctx->opcode);
                 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
-            } else
-                gen_muldiv(ctx, op1, rs, rt);
+            } else {
+                gen_muldiv(ctx, op1, rd & 3, rs, rt);
+            }
+            break;
+        case OPC_DIV:
+        case OPC_DIVU:
+            gen_muldiv(ctx, op1, 0, rs, rt);
             break;
         case OPC_JR ... OPC_JALR:
             gen_compute_branch(ctx, op1, 4, rs, rd, sa);
@@ -14487,11 +14467,11 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
             break;
         case OPC_MFHI:          /* Move from HI/LO */
         case OPC_MFLO:
-            gen_HILO(ctx, op1, rd);
+            gen_HILO(ctx, op1, rs & 3, rd);
             break;
         case OPC_MTHI:
         case OPC_MTLO:          /* Move to HI/LO */
-            gen_HILO(ctx, op1, rs);
+            gen_HILO(ctx, op1, rd & 3, rs);
             break;
         case OPC_PMON:          /* Pmon entry point, also R4010 selsl */
 #ifdef MIPS_STRICT_STANDARD
@@ -14611,7 +14591,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         case OPC_DMULT ... OPC_DDIVU:
             check_insn(ctx, ISA_MIPS3);
             check_mips_64(ctx);
-            gen_muldiv(ctx, op1, rs, rt);
+            gen_muldiv(ctx, op1, 0, rs, rt);
             break;
 #endif
         default:            /* Invalid */
@@ -14626,7 +14606,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
         case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
         case OPC_MSUB ... OPC_MSUBU:
             check_insn(ctx, ISA_MIPS32);
-            gen_muldiv(ctx, op1, rs, rt);
+            gen_muldiv(ctx, op1, rd & 3, rs, rt);
             break;
         case OPC_MUL:
             gen_arith(ctx, op1, rd, rs, rt);
commit 54b2f42cb1eef758b6070e805a5d6f7a84315ace
Author: Meador Inge <meadori at codesourcery.com>
Date:   Thu Jan 10 16:50:22 2013 -0600

    target-mips: Translate breaks and traps into the appropriate signal
    
    GCC and GAS are capable of generating traps or breaks to check for
    division by zero.  Additionally, GAS is capable of generating traps
    or breaks to check for overflow on certain division and multiplication
    operations.  The Linux kernel translates these traps and breaks into
    signals.  This patch implements the corresponding feature in QEMU.
    
    Signed-off-by: Meador Inge <meadori at codesourcery.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/linux-user/main.c b/linux-user/main.c
index 29845f9..cb14c0b 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2186,6 +2186,33 @@ static int do_store_exclusive(CPUMIPSState *env)
     return segv;
 }
 
+/* Break codes */
+enum {
+    BRK_OVERFLOW = 6,
+    BRK_DIVZERO = 7
+};
+
+static int do_break(CPUMIPSState *env, target_siginfo_t *info,
+                    unsigned int code)
+{
+    int ret = -1;
+
+    switch (code) {
+    case BRK_OVERFLOW:
+    case BRK_DIVZERO:
+        info->si_signo = TARGET_SIGFPE;
+        info->si_errno = 0;
+        info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV;
+        queue_signal(env, info->si_signo, &*info);
+        ret = 0;
+        break;
+    default:
+        break;
+    }
+
+    return ret;
+}
+
 void cpu_loop(CPUMIPSState *env)
 {
     CPUState *cs = CPU(mips_env_get_cpu(env));
@@ -2302,8 +2329,55 @@ done_syscall:
             info.si_code = TARGET_ILL_ILLOPC;
             queue_signal(env, info.si_signo, &info);
             break;
+        /* The code below was inspired by the MIPS Linux kernel trap
+         * handling code in arch/mips/kernel/traps.c.
+         */
+        case EXCP_BREAK:
+            {
+                abi_ulong trap_instr;
+                unsigned int code;
+
+                ret = get_user_ual(trap_instr, env->active_tc.PC);
+                if (ret != 0) {
+                    goto error;
+                }
+
+                /* As described in the original Linux kernel code, the
+                 * below checks on 'code' are to work around an old
+                 * assembly bug.
+                 */
+                code = ((trap_instr >> 6) & ((1 << 20) - 1));
+                if (code >= (1 << 10)) {
+                    code >>= 10;
+                }
+
+                if (do_break(env, &info, code) != 0) {
+                    goto error;
+                }
+            }
+            break;
+        case EXCP_TRAP:
+            {
+                abi_ulong trap_instr;
+                unsigned int code = 0;
+
+                ret = get_user_ual(trap_instr, env->active_tc.PC);
+                if (ret != 0) {
+                    goto error;
+                }
+
+                /* The immediate versions don't provide a code.  */
+                if (!(trap_instr & 0xFC000000)) {
+                    code = ((trap_instr >> 6) & ((1 << 10) - 1));
+                }
+
+                if (do_break(env, &info, code) != 0) {
+                    goto error;
+                }
+            }
+            break;
         default:
-            //        error:
+error:
             fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
                     trapnr);
             cpu_dump_state(env, stderr, fprintf, 0);
commit 20c334a797bf46a4ee59a6e42be6d5e7c3cda585
Author: Petar Jovanovic <petar.jovanovic at imgtec.com>
Date:   Mon Feb 25 16:45:40 2013 +0100

    target-mips: fix DSP overflow macro and affected routines
    
    The previous implementation incorrectly used same macro to detect overflow
    for addition and subtraction. This patch makes distinction between these
    two, and creates separate macros. The affected routines are changed
    accordingly.
    
    This change also includes additions to the existing tests for SUBQ_S_PH and
    SUBQ_S_W that would trigger the fixed issue, and it removes dead code from
    the test file. The last test case in subq_s_w.c is a bug found/reported/
    isolated by Klaus Peichl from Dolby.
    
    Signed-off-by: Petar Jovanovic <petar.jovanovic at imgtec.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 841f47b..ffa9396 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -44,7 +44,8 @@ typedef union {
 
 /*** MIPS DSP internal functions begin ***/
 #define MIPSDSP_ABS(x) (((x) >= 0) ? x : -x)
-#define MIPSDSP_OVERFLOW(a, b, c, d) (!(!((a ^ b ^ -1) & (a ^ c) & d)))
+#define MIPSDSP_OVERFLOW_ADD(a, b, c, d) (~(a ^ b) & (a ^ c) & d)
+#define MIPSDSP_OVERFLOW_SUB(a, b, c, d) ((a ^ b) & (a ^ c) & d)
 
 static inline void set_DSPControl_overflow_flag(uint32_t flag, int position,
                                                 CPUMIPSState *env)
@@ -142,7 +143,7 @@ static inline int16_t mipsdsp_add_i16(int16_t a, int16_t b, CPUMIPSState *env)
 
     tempI = a + b;
 
-    if (MIPSDSP_OVERFLOW(a, b, tempI, 0x8000)) {
+    if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x8000)) {
         set_DSPControl_overflow_flag(1, 20, env);
     }
 
@@ -156,7 +157,7 @@ static inline int16_t mipsdsp_sat_add_i16(int16_t a, int16_t b,
 
     tempS = a + b;
 
-    if (MIPSDSP_OVERFLOW(a, b, tempS, 0x8000)) {
+    if (MIPSDSP_OVERFLOW_ADD(a, b, tempS, 0x8000)) {
         if (a > 0) {
             tempS = 0x7FFF;
         } else {
@@ -175,7 +176,7 @@ static inline int32_t mipsdsp_sat_add_i32(int32_t a, int32_t b,
 
     tempI = a + b;
 
-    if (MIPSDSP_OVERFLOW(a, b, tempI, 0x80000000)) {
+    if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x80000000)) {
         if (a > 0) {
             tempI = 0x7FFFFFFF;
         } else {
@@ -858,7 +859,7 @@ static inline uint16_t mipsdsp_sub_i16(int16_t a, int16_t b, CPUMIPSState *env)
     int16_t  temp;
 
     temp = a - b;
-    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) {
+    if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x8000)) {
         set_DSPControl_overflow_flag(1, 20, env);
     }
 
@@ -871,8 +872,8 @@ static inline uint16_t mipsdsp_sat16_sub(int16_t a, int16_t b,
     int16_t  temp;
 
     temp = a - b;
-    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x8000)) {
-        if (a > 0) {
+    if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x8000)) {
+        if (a >= 0) {
             temp = 0x7FFF;
         } else {
             temp = 0x8000;
@@ -889,8 +890,8 @@ static inline uint32_t mipsdsp_sat32_sub(int32_t a, int32_t b,
     int32_t  temp;
 
     temp = a - b;
-    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) {
-        if (a > 0) {
+    if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x80000000)) {
+        if (a >= 0) {
             temp = 0x7FFFFFFF;
         } else {
             temp = 0x80000000;
@@ -1004,7 +1005,7 @@ static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env)
     int32_t temp;
 
     temp = a - b;
-    if (MIPSDSP_OVERFLOW(a, -b, temp, 0x80000000)) {
+    if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x80000000)) {
         set_DSPControl_overflow_flag(1, 20, env);
     }
 
@@ -1017,7 +1018,7 @@ static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env)
 
     temp = a + b;
 
-    if (MIPSDSP_OVERFLOW(a, b, temp, 0x80000000)) {
+    if (MIPSDSP_OVERFLOW_ADD(a, b, temp, 0x80000000)) {
         set_DSPControl_overflow_flag(1, 20, env);
     }
 
@@ -2488,37 +2489,42 @@ DP_QH(dpsq_s_w_qh, 0, 1);
 #endif
 
 #define DP_L_W(name, is_add) \
-void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,     \
-                   CPUMIPSState *env)                                 \
-{                                                                     \
-    int32_t temp63;                                                   \
-    int64_t dotp, acc;                                                \
-    uint64_t temp;                                                    \
-                                                                      \
-    dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env);                      \
-    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                   \
-          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);            \
-    if (!is_add) {                                                    \
-        dotp = -dotp;                                                 \
-    }                                                                 \
-                                                                      \
-    temp = acc + dotp;                                                \
-    if (MIPSDSP_OVERFLOW((uint64_t)acc, (uint64_t)dotp, temp,         \
-                         (0x01ull << 63))) {                          \
-        temp63 = (temp >> 63) & 0x01;                                 \
-        if (temp63 == 1) {                                            \
-            temp = (0x01ull << 63) - 1;                               \
-        } else {                                                      \
-            temp = 0x01ull << 63;                                     \
-        }                                                             \
-                                                                      \
-        set_DSPControl_overflow_flag(1, 16 + ac, env);                \
-    }                                                                 \
-                                                                      \
-    env->active_tc.HI[ac] = (target_long)(int32_t)                    \
-        ((temp & MIPSDSP_LHI) >> 32);                                 \
-    env->active_tc.LO[ac] = (target_long)(int32_t)                    \
-        (temp & MIPSDSP_LLO);                                         \
+void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt,      \
+                   CPUMIPSState *env)                                  \
+{                                                                      \
+    int32_t temp63;                                                    \
+    int64_t dotp, acc;                                                 \
+    uint64_t temp;                                                     \
+    bool overflow;                                                     \
+                                                                       \
+    dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env);                       \
+    acc = ((uint64_t)env->active_tc.HI[ac] << 32) |                    \
+          ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);             \
+    if (is_add) {                                                      \
+        temp = acc + dotp;                                             \
+        overflow = MIPSDSP_OVERFLOW_ADD((uint64_t)acc, (uint64_t)dotp, \
+                                        temp, (0x01ull << 63));        \
+    } else {                                                           \
+        temp = acc - dotp;                                             \
+        overflow = MIPSDSP_OVERFLOW_SUB((uint64_t)acc, (uint64_t)dotp, \
+                                        temp, (0x01ull << 63));        \
+    }                                                                  \
+                                                                       \
+    if (overflow) {                                                    \
+        temp63 = (temp >> 63) & 0x01;                                  \
+        if (temp63 == 1) {                                             \
+            temp = (0x01ull << 63) - 1;                                \
+        } else {                                                       \
+            temp = 0x01ull << 63;                                      \
+        }                                                              \
+                                                                       \
+        set_DSPControl_overflow_flag(1, 16 + ac, env);                 \
+    }                                                                  \
+                                                                       \
+    env->active_tc.HI[ac] = (target_long)(int32_t)                     \
+        ((temp & MIPSDSP_LHI) >> 32);                                  \
+    env->active_tc.LO[ac] = (target_long)(int32_t)                     \
+        (temp & MIPSDSP_LLO);                                          \
 }
 
 DP_L_W(dpaq_sa_l_w, 1);
diff --git a/tests/tcg/mips/mips32-dsp/subq_s_ph.c b/tests/tcg/mips/mips32-dsp/subq_s_ph.c
index 8e36dad..64c89eb 100644
--- a/tests/tcg/mips/mips32-dsp/subq_s_ph.c
+++ b/tests/tcg/mips/mips32-dsp/subq_s_ph.c
@@ -12,7 +12,8 @@ int main()
     resultdsp = 0x01;
 
     __asm
-        ("subq_s.ph %0, %2, %3\n\t"
+        ("wrdsp $0\n\t"
+         "subq_s.ph %0, %2, %3\n\t"
          "rddsp %1\n\t"
          : "=r"(rd), "=r"(dsp)
          : "r"(rs), "r"(rt)
@@ -27,7 +28,24 @@ int main()
     resultdsp = 0x01;
 
     __asm
-        ("subq_s.ph %0, %2, %3\n\t"
+        ("wrdsp $0\n\t"
+         "subq_s.ph %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
+    dsp = (dsp >> 20) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    rs = 0x12340000;
+    rt = 0x87658000;
+    result    = 0x7FFF7FFF;
+    resultdsp = 0x01;
+
+    __asm
+        ("wrdsp $0\n\t"
+         "subq_s.ph %0, %2, %3\n\t"
          "rddsp %1\n\t"
          : "=r"(rd), "=r"(dsp)
          : "r"(rs), "r"(rt)
diff --git a/tests/tcg/mips/mips32-dsp/subq_s_w.c b/tests/tcg/mips/mips32-dsp/subq_s_w.c
index 09022e9..9d456a9 100644
--- a/tests/tcg/mips/mips32-dsp/subq_s_w.c
+++ b/tests/tcg/mips/mips32-dsp/subq_s_w.c
@@ -12,7 +12,8 @@ int main()
     resultdsp = 0x01;
 
     __asm
-        ("subq_s.w %0, %2, %3\n\t"
+        ("wrdsp $0\n\t"
+         "subq_s.w %0, %2, %3\n\t"
          "rddsp %1\n\t"
          : "=r"(rd), "=r"(dsp)
          : "r"(rs), "r"(rt)
@@ -24,10 +25,11 @@ int main()
     rs = 0x66666;
     rt = 0x55555;
     result    = 0x11111;
-    resultdsp = 0x01;
+    resultdsp = 0x0;
 
     __asm
-        ("subq_s.w %0, %2, %3\n\t"
+        ("wrdsp $0\n\t"
+         "subq_s.w %0, %2, %3\n\t"
          "rddsp %1\n\t"
          : "=r"(rd), "=r"(dsp)
          : "r"(rs), "r"(rt)
@@ -36,23 +38,37 @@ int main()
     assert(dsp == resultdsp);
     assert(rd  == result);
 
-
-#if 0
-    rs = 0x35555555;
-    rt = 0xf5555555;
-    result    = 0x80000000;
+    rs = 0x0;
+    rt = 0x80000000;
+    result    = 0x7FFFFFFF;
     resultdsp = 0x01;
 
     __asm
-        ("subq_s.w %0, %2, %3\n\t"
+        ("wrdsp $0\n\t"
+         "subq_s.w %0, %2, %3\n\t"
          "rddsp %1\n\t"
          : "=r"(rd), "=r"(dsp)
          : "r"(rs), "r"(rt)
         );
+    dsp = (dsp >> 20) & 0x01;
+    assert(dsp == resultdsp);
+    assert(rd  == result);
+
+    rs = 0x80000000;
+    rt = 0x80000000;
+    result    = 0;
+    resultdsp = 0x00;
 
+    __asm
+        ("wrdsp $0\n\t"
+         "subq_s.w %0, %2, %3\n\t"
+         "rddsp %1\n\t"
+         : "=r"(rd), "=r"(dsp)
+         : "r"(rs), "r"(rt)
+        );
     dsp = (dsp >> 20) & 0x01;
     assert(dsp == resultdsp);
     assert(rd  == result);
-#endif
+
     return 0;
 }
commit 71df81afc618da79008a7071a666cf97b62e1237
Merge: a690060 272d2d8
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 4 08:22:48 2013 -0600

    Merge remote-tracking branch 'stefanha/block' into staging
    
    # By MORITA Kazutaka (5) and others
    # Via Stefan Hajnoczi
    * stefanha/block:
      block: for HMP commit() operations on 'all', skip non-COW drives
      sheepdog: add support for connecting to unix domain socket
      sheepdog: use inet_connect to simplify connect code
      sheepdog: accept URIs
      move socket_set_nodelay to osdep.c
      slirp/tcp_subr.c: fix coding style in tcp_connect
      dataplane: remove EventPoll in favor of AioContext
      virtio-blk: fix unplug + virsh reboot
      ide/macio: Fix macio DMA initialisation.

commit a6900601caf2286a704bdc42da33e98c65feb3a9
Merge: e482ded 554f199
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 4 08:22:41 2013 -0600

    Merge remote-tracking branch 'mst/tags/for_anthony' into staging
    
    virtio,vhost,pci,e1000
    
    Mostly bugfixes, but also some ICH work by Laszlo.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    
    # gpg: Signature made Thu 28 Feb 2013 07:13:56 AM CST using RSA key ID D28D5469
    # gpg: Can't check signature: public key not found
    
    # By Michael S. Tsirkin (2) and others
    # Via Michael S. Tsirkin
    * mst/tags/for_anthony:
      Set virtio-serial device to have a default of 2 MSI vectors.
      ICH9 LPC: Reset Control Register, basic implementation
      Fix guest OS hang when 64bit PCI bar present
      e1000: unbreak the guest network migration to 1.3
      vhost: memory sync fixes

commit e482dedc503819a009e245996f7cdb13eed6b165
Merge: bf5363e 5c75fb1
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 4 08:20:32 2013 -0600

    Merge remote-tracking branch 'kraxel/seabios-1.7.2.1' into staging
    
    # By Gerd Hoffmann
    # Via Gerd Hoffmann
    * kraxel/seabios-1.7.2.1:
      update seabios to 1.7.2.1

commit bf5363efcff81226d779d1cc1117cb277b458ecb
Merge: 806f352 af347aa
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 4 08:20:06 2013 -0600

    Merge remote-tracking branch 'stefanha/net' into staging
    
    # By Jason Wang (2) and others
    # Via Stefan Hajnoczi
    * stefanha/net:
      qmp: netdev_add is like -netdev, not -net, fix documentation
      doc: document -netdev hubport
      net: reduce the unnecessary memory allocation of multiqueue
      tap: set IFF_ONE_QUEUE per default
      tap: forbid creating multiqueue tap when hub is used
      net: fix unbounded NetQueue
      net: fix qemu_flush_queued_packets() in presence of a hub

commit 272d2d8e1241b92ab9be87b2c8fb590fd84987a8
Author: Jeff Cody <jcody at redhat.com>
Date:   Tue Feb 26 09:55:48 2013 -0500

    block: for HMP commit() operations on 'all', skip non-COW drives
    
    During a commit of 'all' using the HMP non-live commit, the operation
    is aborted and returns error on the first error enountered.  When
    non-COW drives are in use (e.g. ejected floppy, cdrom, or drives without
    a backing parent), that means a commit all will return an error of either
    -ENOMEDIUM or -ENOTSUP.  This is not desirable, so for the 'all' commit
    case, only attempt the commit if both bs->drv and bs->backing_hd are
    present.
    
    More succinctly: 'commit all' now means a commit on all COW drives.
    
    This means an individual commit to a specific non-COW drive will still
    return the appropriate error (-ENOMEDIUM if eject / not present, -ENOTSUP
    if no backing file).
    
    Reported-by: Jan Kiszka <jan.kiszka at web.de>
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Reviewed-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block.c b/block.c
index 4582961..124a9eb 100644
--- a/block.c
+++ b/block.c
@@ -1640,9 +1640,11 @@ int bdrv_commit_all(void)
     BlockDriverState *bs;
 
     QTAILQ_FOREACH(bs, &bdrv_states, list) {
-        int ret = bdrv_commit(bs);
-        if (ret < 0) {
-            return ret;
+        if (bs->drv && bs->backing_hd) {
+            int ret = bdrv_commit(bs);
+            if (ret < 0) {
+                return ret;
+            }
         }
     }
     return 0;
commit 1b8bbb46e7593b92ded74cc2a5461202c2b6c05c
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date:   Fri Feb 22 12:39:53 2013 +0900

    sheepdog: add support for connecting to unix domain socket
    
    This patch adds support for a unix domain socket for a connection
    between qemu and local sheepdog server.  You can use the unix domain
    socket with the following syntax:
    
     $ qemu sheepdog+unix:///<vdiname>?socket=<socket path>[#snapid]
    
    Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index b5cbdfe..c711c28 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -299,6 +299,7 @@ typedef struct BDRVSheepdogState {
     uint32_t cache_flags;
 
     char *host_spec;
+    bool is_unix;
     int fd;
 
     CoMutex lock;
@@ -451,7 +452,18 @@ static int connect_to_sdog(BDRVSheepdogState *s)
     int fd;
     Error *err = NULL;
 
-    fd = inet_connect(s->host_spec, &err);
+    if (s->is_unix) {
+        fd = unix_connect(s->host_spec, &err);
+    } else {
+        fd = inet_connect(s->host_spec, &err);
+
+        if (err == NULL) {
+            int ret = socket_set_nodelay(fd);
+            if (ret < 0) {
+                error_report("%s", strerror(errno));
+            }
+        }
+    }
 
     if (err != NULL) {
         qerror_report_err(err);
@@ -757,7 +769,7 @@ static int aio_flush_request(void *opaque)
  */
 static int get_sheep_fd(BDRVSheepdogState *s)
 {
-    int ret, fd;
+    int fd;
 
     fd = connect_to_sdog(s);
     if (fd < 0) {
@@ -766,13 +778,6 @@ static int get_sheep_fd(BDRVSheepdogState *s)
 
     socket_set_nonblock(fd);
 
-    ret = socket_set_nodelay(fd);
-    if (ret) {
-        error_report("%s", strerror(errno));
-        closesocket(fd);
-        return -errno;
-    }
-
     qemu_aio_set_fd_handler(fd, co_read_response, NULL, aio_flush_request, s);
     return fd;
 }
@@ -789,15 +794,42 @@ static int sd_parse_uri(BDRVSheepdogState *s, const char *filename,
         return -EINVAL;
     }
 
+    /* transport */
+    if (!strcmp(uri->scheme, "sheepdog")) {
+        s->is_unix = false;
+    } else if (!strcmp(uri->scheme, "sheepdog+tcp")) {
+        s->is_unix = false;
+    } else if (!strcmp(uri->scheme, "sheepdog+unix")) {
+        s->is_unix = true;
+    } else {
+        ret = -EINVAL;
+        goto out;
+    }
+
     if (uri->path == NULL || !strcmp(uri->path, "/")) {
         ret = -EINVAL;
         goto out;
     }
     pstrcpy(vdi, SD_MAX_VDI_LEN, uri->path + 1);
 
-    /* sheepdog[+tcp]://[host:port]/vdiname */
-    s->host_spec = g_strdup_printf("%s:%d", uri->server ?: SD_DEFAULT_ADDR,
-                                   uri->port ?: SD_DEFAULT_PORT);
+    qp = query_params_parse(uri->query);
+    if (qp->n > 1 || (s->is_unix && !qp->n) || (!s->is_unix && qp->n)) {
+        ret = -EINVAL;
+        goto out;
+    }
+
+    if (s->is_unix) {
+        /* sheepdog+unix:///vdiname?socket=path */
+        if (uri->server || uri->port || strcmp(qp->p[0].name, "socket")) {
+            ret = -EINVAL;
+            goto out;
+        }
+        s->host_spec = g_strdup(qp->p[0].value);
+    } else {
+        /* sheepdog[+tcp]://[host:port]/vdiname */
+        s->host_spec = g_strdup_printf("%s:%d", uri->server ?: SD_DEFAULT_ADDR,
+                                       uri->port ?: SD_DEFAULT_PORT);
+    }
 
     /* snapshot tag */
     if (uri->fragment) {
@@ -2098,9 +2130,35 @@ static BlockDriver bdrv_sheepdog_tcp = {
     .create_options = sd_create_options,
 };
 
+static BlockDriver bdrv_sheepdog_unix = {
+    .format_name    = "sheepdog",
+    .protocol_name  = "sheepdog+unix",
+    .instance_size  = sizeof(BDRVSheepdogState),
+    .bdrv_file_open = sd_open,
+    .bdrv_close     = sd_close,
+    .bdrv_create    = sd_create,
+    .bdrv_getlength = sd_getlength,
+    .bdrv_truncate  = sd_truncate,
+
+    .bdrv_co_readv  = sd_co_readv,
+    .bdrv_co_writev = sd_co_writev,
+    .bdrv_co_flush_to_disk  = sd_co_flush_to_disk,
+
+    .bdrv_snapshot_create   = sd_snapshot_create,
+    .bdrv_snapshot_goto     = sd_snapshot_goto,
+    .bdrv_snapshot_delete   = sd_snapshot_delete,
+    .bdrv_snapshot_list     = sd_snapshot_list,
+
+    .bdrv_save_vmstate  = sd_save_vmstate,
+    .bdrv_load_vmstate  = sd_load_vmstate,
+
+    .create_options = sd_create_options,
+};
+
 static void bdrv_sheepdog_init(void)
 {
     bdrv_register(&bdrv_sheepdog);
     bdrv_register(&bdrv_sheepdog_tcp);
+    bdrv_register(&bdrv_sheepdog_unix);
 }
 block_init(bdrv_sheepdog_init);
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 2083e29..af84bef 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -865,6 +865,12 @@ qemu-img create -b sheepdog:///@var{base}#@var{tag} sheepdog:///@var{image}
 where @var{base} is a image name of the source snapshot and @var{tag}
 is its tag name.
 
+You can use an unix socket instead of an inet socket:
+
+ at example
+qemu-system-i386 sheepdog+unix:///@var{image}?socket=@var{path}
+ at end example
+
 If the Sheepdog daemon doesn't run on the local host, you need to
 specify one of the Sheepdog servers to connect to.
 @example
diff --git a/qemu-options.hx b/qemu-options.hx
index e8fb78c..f598d7a 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2100,7 +2100,7 @@ devices.
 
 Syntax for specifying a sheepdog device
 @example
-sheepdog[+tcp]://[host:port]/vdiname[#snapid|#tag]
+sheepdog[+tcp|+unix]://[host:port]/vdiname[?socket=path][#snapid|#tag]
 @end example
 
 Example
commit 25af257d219ed2708b3bcf7f1fabf93234d27620
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date:   Fri Feb 22 12:39:52 2013 +0900

    sheepdog: use inet_connect to simplify connect code
    
    This uses the form "<host>:<port>" for the representation of the
    sheepdog server to use inet_connect.
    
    Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index bfa8a00..b5cbdfe 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -22,7 +22,7 @@
 #define SD_PROTO_VER 0x01
 
 #define SD_DEFAULT_ADDR "localhost"
-#define SD_DEFAULT_PORT "7000"
+#define SD_DEFAULT_PORT 7000
 
 #define SD_OP_CREATE_AND_WRITE_OBJ  0x01
 #define SD_OP_READ_OBJ       0x02
@@ -298,8 +298,7 @@ typedef struct BDRVSheepdogState {
     bool is_snapshot;
     uint32_t cache_flags;
 
-    char *addr;
-    char *port;
+    char *host_spec;
     int fd;
 
     CoMutex lock;
@@ -447,56 +446,18 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
     return acb;
 }
 
-static int connect_to_sdog(const char *addr, const char *port)
+static int connect_to_sdog(BDRVSheepdogState *s)
 {
-    char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
-    int fd, ret;
-    struct addrinfo hints, *res, *res0;
-
-    if (!addr) {
-        addr = SD_DEFAULT_ADDR;
-        port = SD_DEFAULT_PORT;
-    }
+    int fd;
+    Error *err = NULL;
 
-    memset(&hints, 0, sizeof(hints));
-    hints.ai_socktype = SOCK_STREAM;
+    fd = inet_connect(s->host_spec, &err);
 
-    ret = getaddrinfo(addr, port, &hints, &res0);
-    if (ret) {
-        error_report("unable to get address info %s, %s",
-                     addr, strerror(errno));
-        return -errno;
+    if (err != NULL) {
+        qerror_report_err(err);
+        error_free(err);
     }
 
-    for (res = res0; res; res = res->ai_next) {
-        ret = getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
-                          sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
-        if (ret) {
-            continue;
-        }
-
-        fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
-        if (fd < 0) {
-            continue;
-        }
-
-    reconnect:
-        ret = connect(fd, res->ai_addr, res->ai_addrlen);
-        if (ret < 0) {
-            if (errno == EINTR) {
-                goto reconnect;
-            }
-            close(fd);
-            break;
-        }
-
-        dprintf("connected to %s:%s\n", addr, port);
-        goto success;
-    }
-    fd = -errno;
-    error_report("failed connect to %s:%s", addr, port);
-success:
-    freeaddrinfo(res0);
     return fd;
 }
 
@@ -798,9 +759,8 @@ static int get_sheep_fd(BDRVSheepdogState *s)
 {
     int ret, fd;
 
-    fd = connect_to_sdog(s->addr, s->port);
+    fd = connect_to_sdog(s);
     if (fd < 0) {
-        error_report("%s", strerror(errno));
         return fd;
     }
 
@@ -836,12 +796,8 @@ static int sd_parse_uri(BDRVSheepdogState *s, const char *filename,
     pstrcpy(vdi, SD_MAX_VDI_LEN, uri->path + 1);
 
     /* sheepdog[+tcp]://[host:port]/vdiname */
-    s->addr = g_strdup(uri->server ?: SD_DEFAULT_ADDR);
-    if (uri->port) {
-        s->port = g_strdup_printf("%d", uri->port);
-    } else {
-        s->port = g_strdup(SD_DEFAULT_PORT);
-    }
+    s->host_spec = g_strdup_printf("%s:%d", uri->server ?: SD_DEFAULT_ADDR,
+                                   uri->port ?: SD_DEFAULT_PORT);
 
     /* snapshot tag */
     if (uri->fragment) {
@@ -935,7 +891,7 @@ static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid,
     unsigned int wlen, rlen = 0;
     char buf[SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN];
 
-    fd = connect_to_sdog(s->addr, s->port);
+    fd = connect_to_sdog(s);
     if (fd < 0) {
         return fd;
     }
@@ -1178,9 +1134,8 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
         s->is_snapshot = true;
     }
 
-    fd = connect_to_sdog(s->addr, s->port);
+    fd = connect_to_sdog(s);
     if (fd < 0) {
-        error_report("failed to connect");
         ret = fd;
         goto out;
     }
@@ -1213,9 +1168,8 @@ out:
     return ret;
 }
 
-static int do_sd_create(char *filename, int64_t vdi_size,
-                        uint32_t base_vid, uint32_t *vdi_id, int snapshot,
-                        const char *addr, const char *port)
+static int do_sd_create(BDRVSheepdogState *s, char *filename, int64_t vdi_size,
+                        uint32_t base_vid, uint32_t *vdi_id, int snapshot)
 {
     SheepdogVdiReq hdr;
     SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr;
@@ -1223,7 +1177,7 @@ static int do_sd_create(char *filename, int64_t vdi_size,
     unsigned int wlen, rlen = 0;
     char buf[SD_MAX_VDI_LEN];
 
-    fd = connect_to_sdog(addr, port);
+    fd = connect_to_sdog(s);
     if (fd < 0) {
         return fd;
     }
@@ -1390,7 +1344,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
         bdrv_delete(bs);
     }
 
-    ret = do_sd_create(vdi, vdi_size, base_vid, &vid, 0, s->addr, s->port);
+    ret = do_sd_create(s, vdi, vdi_size, base_vid, &vid, 0);
     if (!prealloc || ret) {
         goto out;
     }
@@ -1411,7 +1365,7 @@ static void sd_close(BlockDriverState *bs)
 
     dprintf("%s\n", s->name);
 
-    fd = connect_to_sdog(s->addr, s->port);
+    fd = connect_to_sdog(s);
     if (fd < 0) {
         return;
     }
@@ -1435,8 +1389,7 @@ static void sd_close(BlockDriverState *bs)
 
     qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL, NULL);
     closesocket(s->fd);
-    g_free(s->addr);
-    g_free(s->port);
+    g_free(s->host_spec);
 }
 
 static int64_t sd_getlength(BlockDriverState *bs)
@@ -1460,7 +1413,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
         return -EINVAL;
     }
 
-    fd = connect_to_sdog(s->addr, s->port);
+    fd = connect_to_sdog(s);
     if (fd < 0) {
         return fd;
     }
@@ -1536,17 +1489,15 @@ static int sd_create_branch(BDRVSheepdogState *s)
 
     buf = g_malloc(SD_INODE_SIZE);
 
-    ret = do_sd_create(s->name, s->inode.vdi_size, s->inode.vdi_id, &vid, 1,
-                       s->addr, s->port);
+    ret = do_sd_create(s, s->name, s->inode.vdi_size, s->inode.vdi_id, &vid, 1);
     if (ret) {
         goto out;
     }
 
     dprintf("%" PRIx32 " is created.\n", vid);
 
-    fd = connect_to_sdog(s->addr, s->port);
+    fd = connect_to_sdog(s);
     if (fd < 0) {
-        error_report("failed to connect");
         ret = fd;
         goto out;
     }
@@ -1805,7 +1756,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id);
 
     /* refresh inode. */
-    fd = connect_to_sdog(s->addr, s->port);
+    fd = connect_to_sdog(s);
     if (fd < 0) {
         ret = fd;
         goto cleanup;
@@ -1818,8 +1769,8 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
         goto cleanup;
     }
 
-    ret = do_sd_create(s->name, s->inode.vdi_size, s->inode.vdi_id, &new_vid, 1,
-                       s->addr, s->port);
+    ret = do_sd_create(s, s->name, s->inode.vdi_size, s->inode.vdi_id, &new_vid,
+                       1);
     if (ret < 0) {
         error_report("failed to create inode for snapshot. %s",
                      strerror(errno));
@@ -1874,9 +1825,8 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
         goto out;
     }
 
-    fd = connect_to_sdog(s->addr, s->port);
+    fd = connect_to_sdog(s);
     if (fd < 0) {
-        error_report("failed to connect");
         ret = fd;
         goto out;
     }
@@ -1938,7 +1888,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
 
     vdi_inuse = g_malloc(max);
 
-    fd = connect_to_sdog(s->addr, s->port);
+    fd = connect_to_sdog(s);
     if (fd < 0) {
         ret = fd;
         goto out;
@@ -1965,9 +1915,8 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
     hval = fnv_64a_buf(s->name, strlen(s->name), FNV1A_64_INIT);
     start_nr = hval & (SD_NR_VDIS - 1);
 
-    fd = connect_to_sdog(s->addr, s->port);
+    fd = connect_to_sdog(s);
     if (fd < 0) {
-        error_report("failed to connect");
         ret = fd;
         goto out;
     }
@@ -2024,7 +1973,7 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
     uint32_t vdi_index;
     uint64_t offset;
 
-    fd = connect_to_sdog(s->addr, s->port);
+    fd = connect_to_sdog(s);
     if (fd < 0) {
         return fd;
     }
commit 5d6768e3b8908a60f0a3016b7fa24194f6b47c80
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date:   Fri Feb 22 12:39:51 2013 +0900

    sheepdog: accept URIs
    
    The URI syntax is consistent with the NBD and Gluster syntax.  The
    syntax is
    
      sheepdog[+tcp]://[host:port]/vdiname[#snapid|#tag]
    
    Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index 51e75ad..bfa8a00 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -13,6 +13,7 @@
  */
 
 #include "qemu-common.h"
+#include "qemu/uri.h"
 #include "qemu/error-report.h"
 #include "qemu/sockets.h"
 #include "block/block_int.h"
@@ -816,8 +817,52 @@ static int get_sheep_fd(BDRVSheepdogState *s)
     return fd;
 }
 
+static int sd_parse_uri(BDRVSheepdogState *s, const char *filename,
+                        char *vdi, uint32_t *snapid, char *tag)
+{
+    URI *uri;
+    QueryParams *qp = NULL;
+    int ret = 0;
+
+    uri = uri_parse(filename);
+    if (!uri) {
+        return -EINVAL;
+    }
+
+    if (uri->path == NULL || !strcmp(uri->path, "/")) {
+        ret = -EINVAL;
+        goto out;
+    }
+    pstrcpy(vdi, SD_MAX_VDI_LEN, uri->path + 1);
+
+    /* sheepdog[+tcp]://[host:port]/vdiname */
+    s->addr = g_strdup(uri->server ?: SD_DEFAULT_ADDR);
+    if (uri->port) {
+        s->port = g_strdup_printf("%d", uri->port);
+    } else {
+        s->port = g_strdup(SD_DEFAULT_PORT);
+    }
+
+    /* snapshot tag */
+    if (uri->fragment) {
+        *snapid = strtoul(uri->fragment, NULL, 10);
+        if (*snapid == 0) {
+            pstrcpy(tag, SD_MAX_VDI_TAG_LEN, uri->fragment);
+        }
+    } else {
+        *snapid = CURRENT_VDI_ID; /* search current vdi */
+    }
+
+out:
+    if (qp) {
+        query_params_free(qp);
+    }
+    uri_free(uri);
+    return ret;
+}
+
 /*
- * Parse a filename
+ * Parse a filename (old syntax)
  *
  * filename must be one of the following formats:
  *   1. [vdiname]
@@ -836,9 +881,11 @@ static int get_sheep_fd(BDRVSheepdogState *s)
 static int parse_vdiname(BDRVSheepdogState *s, const char *filename,
                          char *vdi, uint32_t *snapid, char *tag)
 {
-    char *p, *q;
-    int nr_sep;
+    char *p, *q, *uri;
+    const char *host_spec, *vdi_spec;
+    int nr_sep, ret;
 
+    strstart(filename, "sheepdog:", (const char **)&filename);
     p = q = g_strdup(filename);
 
     /* count the number of separators */
@@ -851,38 +898,32 @@ static int parse_vdiname(BDRVSheepdogState *s, const char *filename,
     }
     p = q;
 
-    /* use the first two tokens as hostname and port number. */
+    /* use the first two tokens as host_spec. */
     if (nr_sep >= 2) {
-        s->addr = p;
+        host_spec = p;
         p = strchr(p, ':');
-        *p++ = '\0';
-
-        s->port = p;
+        p++;
         p = strchr(p, ':');
         *p++ = '\0';
     } else {
-        s->addr = NULL;
-        s->port = 0;
+        host_spec = "";
     }
 
-    pstrcpy(vdi, SD_MAX_VDI_LEN, p);
+    vdi_spec = p;
 
-    p = strchr(vdi, ':');
+    p = strchr(vdi_spec, ':');
     if (p) {
-        *p++ = '\0';
-        *snapid = strtoul(p, NULL, 10);
-        if (*snapid == 0) {
-            pstrcpy(tag, SD_MAX_VDI_TAG_LEN, p);
-        }
-    } else {
-        *snapid = CURRENT_VDI_ID; /* search current vdi */
+        *p++ = '#';
     }
 
-    if (s->addr == NULL) {
-        g_free(q);
-    }
+    uri = g_strdup_printf("sheepdog://%s/%s", host_spec, vdi_spec);
 
-    return 0;
+    ret = sd_parse_uri(s, uri, vdi, snapid, tag);
+
+    g_free(q);
+    g_free(uri);
+
+    return ret;
 }
 
 static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid,
@@ -1097,16 +1138,19 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
     uint32_t snapid;
     char *buf = NULL;
 
-    strstart(filename, "sheepdog:", (const char **)&filename);
-
     QLIST_INIT(&s->inflight_aio_head);
     QLIST_INIT(&s->pending_aio_head);
     s->fd = -1;
 
     memset(vdi, 0, sizeof(vdi));
     memset(tag, 0, sizeof(tag));
-    if (parse_vdiname(s, filename, vdi, &snapid, tag) < 0) {
-        ret = -EINVAL;
+
+    if (strstr(filename, "://")) {
+        ret = sd_parse_uri(s, filename, vdi, &snapid, tag);
+    } else {
+        ret = parse_vdiname(s, filename, vdi, &snapid, tag);
+    }
+    if (ret < 0) {
         goto out;
     }
     s->fd = get_sheep_fd(s);
@@ -1275,17 +1319,17 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
     char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
     uint32_t snapid;
     bool prealloc = false;
-    const char *vdiname;
 
     s = g_malloc0(sizeof(BDRVSheepdogState));
 
-    strstart(filename, "sheepdog:", &vdiname);
-
     memset(vdi, 0, sizeof(vdi));
     memset(tag, 0, sizeof(tag));
-    if (parse_vdiname(s, vdiname, vdi, &snapid, tag) < 0) {
-        error_report("invalid filename");
-        ret = -EINVAL;
+    if (strstr(filename, "://")) {
+        ret = sd_parse_uri(s, filename, vdi, &snapid, tag);
+    } else {
+        ret = parse_vdiname(s, filename, vdi, &snapid, tag);
+    }
+    if (ret < 0) {
         goto out;
     }
 
@@ -1392,6 +1436,7 @@ static void sd_close(BlockDriverState *bs)
     qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL, NULL);
     closesocket(s->fd);
     g_free(s->addr);
+    g_free(s->port);
 }
 
 static int64_t sd_getlength(BlockDriverState *bs)
@@ -2054,7 +2099,7 @@ static QEMUOptionParameter sd_create_options[] = {
     { NULL }
 };
 
-BlockDriver bdrv_sheepdog = {
+static BlockDriver bdrv_sheepdog = {
     .format_name    = "sheepdog",
     .protocol_name  = "sheepdog",
     .instance_size  = sizeof(BDRVSheepdogState),
@@ -2079,8 +2124,34 @@ BlockDriver bdrv_sheepdog = {
     .create_options = sd_create_options,
 };
 
+static BlockDriver bdrv_sheepdog_tcp = {
+    .format_name    = "sheepdog",
+    .protocol_name  = "sheepdog+tcp",
+    .instance_size  = sizeof(BDRVSheepdogState),
+    .bdrv_file_open = sd_open,
+    .bdrv_close     = sd_close,
+    .bdrv_create    = sd_create,
+    .bdrv_getlength = sd_getlength,
+    .bdrv_truncate  = sd_truncate,
+
+    .bdrv_co_readv  = sd_co_readv,
+    .bdrv_co_writev = sd_co_writev,
+    .bdrv_co_flush_to_disk  = sd_co_flush_to_disk,
+
+    .bdrv_snapshot_create   = sd_snapshot_create,
+    .bdrv_snapshot_goto     = sd_snapshot_goto,
+    .bdrv_snapshot_delete   = sd_snapshot_delete,
+    .bdrv_snapshot_list     = sd_snapshot_list,
+
+    .bdrv_save_vmstate  = sd_save_vmstate,
+    .bdrv_load_vmstate  = sd_load_vmstate,
+
+    .create_options = sd_create_options,
+};
+
 static void bdrv_sheepdog_init(void)
 {
     bdrv_register(&bdrv_sheepdog);
+    bdrv_register(&bdrv_sheepdog_tcp);
 }
 block_init(bdrv_sheepdog_init);
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 747e052..2083e29 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -830,7 +830,7 @@ QEMU-based virtual machines.
 
 You can create a Sheepdog disk image with the command:
 @example
-qemu-img create sheepdog:@var{image} @var{size}
+qemu-img create sheepdog:///@var{image} @var{size}
 @end example
 where @var{image} is the Sheepdog image name and @var{size} is its
 size.
@@ -838,29 +838,29 @@ size.
 To import the existing @var{filename} to Sheepdog, you can use a
 convert command.
 @example
-qemu-img convert @var{filename} sheepdog:@var{image}
+qemu-img convert @var{filename} sheepdog:///@var{image}
 @end example
 
 You can boot from the Sheepdog disk image with the command:
 @example
-qemu-system-i386 sheepdog:@var{image}
+qemu-system-i386 sheepdog:///@var{image}
 @end example
 
 You can also create a snapshot of the Sheepdog image like qcow2.
 @example
-qemu-img snapshot -c @var{tag} sheepdog:@var{image}
+qemu-img snapshot -c @var{tag} sheepdog:///@var{image}
 @end example
 where @var{tag} is a tag name of the newly created snapshot.
 
 To boot from the Sheepdog snapshot, specify the tag name of the
 snapshot.
 @example
-qemu-system-i386 sheepdog:@var{image}:@var{tag}
+qemu-system-i386 sheepdog:///@var{image}#@var{tag}
 @end example
 
 You can create a cloned image from the existing snapshot.
 @example
-qemu-img create -b sheepdog:@var{base}:@var{tag} sheepdog:@var{image}
+qemu-img create -b sheepdog:///@var{base}#@var{tag} sheepdog:///@var{image}
 @end example
 where @var{base} is a image name of the source snapshot and @var{tag}
 is its tag name.
@@ -868,8 +868,8 @@ is its tag name.
 If the Sheepdog daemon doesn't run on the local host, you need to
 specify one of the Sheepdog servers to connect to.
 @example
-qemu-img create sheepdog:@var{hostname}:@var{port}:@var{image} @var{size}
-qemu-system-i386 sheepdog:@var{hostname}:@var{port}:@var{image}
+qemu-img create sheepdog://@var{hostname}:@var{port}/@var{image} @var{size}
+qemu-system-i386 sheepdog://@var{hostname}:@var{port}/@var{image}
 @end example
 
 @node disk_images_iscsi
diff --git a/qemu-options.hx b/qemu-options.hx
index 797d992..e8fb78c 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2099,23 +2099,13 @@ QEMU supports using either local sheepdog devices or remote networked
 devices.
 
 Syntax for specifying a sheepdog device
- at table @list
-``sheepdog:<vdiname>''
-
-``sheepdog:<vdiname>:<snapid>''
-
-``sheepdog:<vdiname>:<tag>''
-
-``sheepdog:<host>:<port>:<vdiname>''
-
-``sheepdog:<host>:<port>:<vdiname>:<snapid>''
-
-``sheepdog:<host>:<port>:<vdiname>:<tag>''
- at end table
+ at example
+sheepdog[+tcp]://[host:port]/vdiname[#snapid|#tag]
+ at end example
 
 Example
 @example
-qemu-system-i386 --drive file=sheepdog:192.0.2.1:30000:MyVirtualMachine
+qemu-system-i386 --drive file=sheepdog://192.0.2.1:30000/MyVirtualMachine
 @end example
 
 See also @url{http://http://www.osrg.net/sheepdog/}.
commit bf1c852aa9cbe21beeb7c37d03e167c33ac196b2
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date:   Fri Feb 22 12:39:50 2013 +0900

    move socket_set_nodelay to osdep.c
    
    Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index d466b23..51e75ad 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -787,15 +787,6 @@ static int aio_flush_request(void *opaque)
         !QLIST_EMPTY(&s->pending_aio_head);
 }
 
-static int set_nodelay(int fd)
-{
-    int ret, opt;
-
-    opt = 1;
-    ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof(opt));
-    return ret;
-}
-
 /*
  * Return a socket discriptor to read/write objects.
  *
@@ -814,7 +805,7 @@ static int get_sheep_fd(BDRVSheepdogState *s)
 
     socket_set_nonblock(fd);
 
-    ret = set_nodelay(fd);
+    ret = socket_set_nodelay(fd);
     if (ret) {
         error_report("%s", strerror(errno));
         closesocket(fd);
diff --git a/gdbstub.c b/gdbstub.c
index 32dfea9..e414ad9 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2841,7 +2841,7 @@ static void gdb_accept(void)
     GDBState *s;
     struct sockaddr_in sockaddr;
     socklen_t len;
-    int val, fd;
+    int fd;
 
     for(;;) {
         len = sizeof(sockaddr);
@@ -2858,8 +2858,7 @@ static void gdb_accept(void)
     }
 
     /* set short latency */
-    val = 1;
-    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
+    socket_set_nodelay(fd);
 
     s = g_malloc0(sizeof(GDBState));
     s->c_cpu = first_cpu;
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index 803ae17..6125bf7 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -34,6 +34,7 @@ int inet_aton(const char *cp, struct in_addr *ia);
 int qemu_socket(int domain, int type, int protocol);
 int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
 int socket_set_cork(int fd, int v);
+int socket_set_nodelay(int fd);
 void socket_set_block(int fd);
 void socket_set_nonblock(int fd);
 int send_all(int fd, const void *buf, int len1);
diff --git a/qemu-char.c b/qemu-char.c
index 160decc..36295b1 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2365,12 +2365,6 @@ static void tcp_chr_telnet_init(int fd)
     send(fd, (char *)buf, 3, 0);
 }
 
-static void socket_set_nodelay(int fd)
-{
-    int val = 1;
-    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
-}
-
 static int tcp_chr_add_client(CharDriverState *chr, int fd)
 {
     TCPCharDriver *s = chr->opaque;
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 317dc07..7b7ad60 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -430,8 +430,7 @@ void tcp_connect(struct socket *inso)
     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int));
     opt = 1;
     setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int));
-    opt = 1;
-    setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof(int));
+    socket_set_nodelay(s);
 
     so->so_fport = addr.sin_port;
     so->so_faddr = addr.sin_addr;
diff --git a/util/osdep.c b/util/osdep.c
index 5b51a03..c408261 100644
--- a/util/osdep.c
+++ b/util/osdep.c
@@ -63,6 +63,12 @@ int socket_set_cork(int fd, int v)
 #endif
 }
 
+int socket_set_nodelay(int fd)
+{
+    int v = 1;
+    return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
+}
+
 int qemu_madvise(void *addr, size_t len, int advice)
 {
     if (advice == QEMU_MADV_INVALID) {
commit 4ef7b8944cc5eae66159c60066b21466e2dc1ee4
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date:   Fri Feb 22 12:39:49 2013 +0900

    slirp/tcp_subr.c: fix coding style in tcp_connect
    
    Fix coding style in tcp_connect before the next patch.
    
    Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 1542e43..317dc07 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -384,83 +384,87 @@ int tcp_fconnect(struct socket *so)
  * the time it gets to accept(), so... We simply accept
  * here and SYN the local-host.
  */
-void
-tcp_connect(struct socket *inso)
+void tcp_connect(struct socket *inso)
 {
-	Slirp *slirp = inso->slirp;
-	struct socket *so;
-	struct sockaddr_in addr;
-	socklen_t addrlen = sizeof(struct sockaddr_in);
-	struct tcpcb *tp;
-	int s, opt;
+    Slirp *slirp = inso->slirp;
+    struct socket *so;
+    struct sockaddr_in addr;
+    socklen_t addrlen = sizeof(struct sockaddr_in);
+    struct tcpcb *tp;
+    int s, opt;
 
-	DEBUG_CALL("tcp_connect");
-	DEBUG_ARG("inso = %lx", (long)inso);
+    DEBUG_CALL("tcp_connect");
+    DEBUG_ARG("inso = %lx", (long)inso);
 
-	/*
-	 * If it's an SS_ACCEPTONCE socket, no need to socreate()
-	 * another socket, just use the accept() socket.
-	 */
-	if (inso->so_state & SS_FACCEPTONCE) {
-		/* FACCEPTONCE already have a tcpcb */
-		so = inso;
-	} else {
-		if ((so = socreate(slirp)) == NULL) {
-			/* If it failed, get rid of the pending connection */
-			closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen));
-			return;
-		}
-		if (tcp_attach(so) < 0) {
-			free(so); /* NOT sofree */
-			return;
-		}
-		so->so_laddr = inso->so_laddr;
-		so->so_lport = inso->so_lport;
-	}
+    /*
+     * If it's an SS_ACCEPTONCE socket, no need to socreate()
+     * another socket, just use the accept() socket.
+     */
+    if (inso->so_state & SS_FACCEPTONCE) {
+        /* FACCEPTONCE already have a tcpcb */
+        so = inso;
+    } else {
+        so = socreate(slirp);
+        if (so == NULL) {
+            /* If it failed, get rid of the pending connection */
+            closesocket(accept(inso->s, (struct sockaddr *)&addr, &addrlen));
+            return;
+        }
+        if (tcp_attach(so) < 0) {
+            free(so); /* NOT sofree */
+            return;
+        }
+        so->so_laddr = inso->so_laddr;
+        so->so_lport = inso->so_lport;
+    }
 
-	(void) tcp_mss(sototcpcb(so), 0);
+    tcp_mss(sototcpcb(so), 0);
 
-	if ((s = accept(inso->s,(struct sockaddr *)&addr,&addrlen)) < 0) {
-		tcp_close(sototcpcb(so)); /* This will sofree() as well */
-		return;
-	}
-	socket_set_nonblock(s);
-	opt = 1;
-	setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
-	opt = 1;
-	setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
-	opt = 1;
-	setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&opt,sizeof(int));
-
-	so->so_fport = addr.sin_port;
-	so->so_faddr = addr.sin_addr;
-	/* Translate connections from localhost to the real hostname */
-        if (so->so_faddr.s_addr == 0 ||
-            (so->so_faddr.s_addr & loopback_mask) ==
-            (loopback_addr.s_addr & loopback_mask)) {
-            so->so_faddr = slirp->vhost_addr;
-        }
+    s = accept(inso->s, (struct sockaddr *)&addr, &addrlen);
+    if (s < 0) {
+        tcp_close(sototcpcb(so)); /* This will sofree() as well */
+        return;
+    }
+    socket_set_nonblock(s);
+    opt = 1;
+    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int));
+    opt = 1;
+    setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int));
+    opt = 1;
+    setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof(int));
+
+    so->so_fport = addr.sin_port;
+    so->so_faddr = addr.sin_addr;
+    /* Translate connections from localhost to the real hostname */
+    if (so->so_faddr.s_addr == 0 ||
+        (so->so_faddr.s_addr & loopback_mask) ==
+        (loopback_addr.s_addr & loopback_mask)) {
+        so->so_faddr = slirp->vhost_addr;
+    }
 
-	/* Close the accept() socket, set right state */
-	if (inso->so_state & SS_FACCEPTONCE) {
-		closesocket(so->s); /* If we only accept once, close the accept() socket */
-		so->so_state = SS_NOFDREF; /* Don't select it yet, even though we have an FD */
-					   /* if it's not FACCEPTONCE, it's already NOFDREF */
-	}
-	so->s = s;
-	so->so_state |= SS_INCOMING;
+    /* Close the accept() socket, set right state */
+    if (inso->so_state & SS_FACCEPTONCE) {
+        /* If we only accept once, close the accept() socket */
+        closesocket(so->s);
+
+        /* Don't select it yet, even though we have an FD */
+        /* if it's not FACCEPTONCE, it's already NOFDREF */
+        so->so_state = SS_NOFDREF;
+    }
+    so->s = s;
+    so->so_state |= SS_INCOMING;
 
-	so->so_iptos = tcp_tos(so);
-	tp = sototcpcb(so);
+    so->so_iptos = tcp_tos(so);
+    tp = sototcpcb(so);
 
-	tcp_template(tp);
+    tcp_template(tp);
 
-	tp->t_state = TCPS_SYN_SENT;
-	tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
-	tp->iss = slirp->tcp_iss;
-	slirp->tcp_iss += TCP_ISSINCR/2;
-	tcp_sendseqinit(tp);
-	tcp_output(tp);
+    tp->t_state = TCPS_SYN_SENT;
+    tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
+    tp->iss = slirp->tcp_iss;
+    slirp->tcp_iss += TCP_ISSINCR/2;
+    tcp_sendseqinit(tp);
+    tcp_output(tp);
 }
 
 /*
commit 2c20e711de308cdebc91ae4b7a983396b56f1de0
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Feb 22 10:40:34 2013 +0100

    dataplane: remove EventPoll in favor of AioContext
    
    During the review of the dataplane code, the EventPoll API morphed itself
    (not concidentially) into something very very similar to an AioContext.
    Thus, it is trivial to convert virtio-blk-dataplane to use AioContext,
    and a first baby step towards letting dataplane talk directly to the
    QEMU block layer.
    
    The only interesting note is the value-copy of EventNotifiers.  At least
    in my opinion this is part of the EventNotifier API and is even portable
    to Windows.  Of course, in this case you should not close the notifier's
    underlying file descriptors or handle with event_notifier_cleanup.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/dataplane/Makefile.objs b/hw/dataplane/Makefile.objs
index 3e47d05..701111c 100644
--- a/hw/dataplane/Makefile.objs
+++ b/hw/dataplane/Makefile.objs
@@ -1 +1 @@
-obj-$(CONFIG_VIRTIO_BLK_DATA_PLANE) += hostmem.o vring.o event-poll.o ioq.o virtio-blk.o
+obj-$(CONFIG_VIRTIO_BLK_DATA_PLANE) += hostmem.o vring.o ioq.o virtio-blk.o
diff --git a/hw/dataplane/event-poll.c b/hw/dataplane/event-poll.c
deleted file mode 100644
index 2b55c6e..0000000
--- a/hw/dataplane/event-poll.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Event loop with file descriptor polling
- *
- * Copyright 2012 IBM, Corp.
- * Copyright 2012 Red Hat, Inc. and/or its affiliates
- *
- * Authors:
- *   Stefan Hajnoczi <stefanha 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 <sys/epoll.h>
-#include "hw/dataplane/event-poll.h"
-
-/* Add an event notifier and its callback for polling */
-void event_poll_add(EventPoll *poll, EventHandler *handler,
-                    EventNotifier *notifier, EventCallback *callback)
-{
-    struct epoll_event event = {
-        .events = EPOLLIN,
-        .data.ptr = handler,
-    };
-    handler->notifier = notifier;
-    handler->callback = callback;
-    if (epoll_ctl(poll->epoll_fd, EPOLL_CTL_ADD,
-                  event_notifier_get_fd(notifier), &event) != 0) {
-        fprintf(stderr, "failed to add event handler to epoll: %m\n");
-        exit(1);
-    }
-}
-
-/* Event callback for stopping event_poll() */
-static void handle_stop(EventHandler *handler)
-{
-    /* Do nothing */
-}
-
-void event_poll_init(EventPoll *poll)
-{
-    /* Create epoll file descriptor */
-    poll->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
-    if (poll->epoll_fd < 0) {
-        fprintf(stderr, "epoll_create1 failed: %m\n");
-        exit(1);
-    }
-
-    /* Set up stop notifier */
-    if (event_notifier_init(&poll->stop_notifier, 0) < 0) {
-        fprintf(stderr, "failed to init stop notifier\n");
-        exit(1);
-    }
-    event_poll_add(poll, &poll->stop_handler,
-                   &poll->stop_notifier, handle_stop);
-}
-
-void event_poll_cleanup(EventPoll *poll)
-{
-    event_notifier_cleanup(&poll->stop_notifier);
-    close(poll->epoll_fd);
-    poll->epoll_fd = -1;
-}
-
-/* Block until the next event and invoke its callback */
-void event_poll(EventPoll *poll)
-{
-    EventHandler *handler;
-    struct epoll_event event;
-    int nevents;
-
-    /* Wait for the next event.  Only do one event per call to keep the
-     * function simple, this could be changed later. */
-    do {
-        nevents = epoll_wait(poll->epoll_fd, &event, 1, -1);
-    } while (nevents < 0 && errno == EINTR);
-    if (unlikely(nevents != 1)) {
-        fprintf(stderr, "epoll_wait failed: %m\n");
-        exit(1); /* should never happen */
-    }
-
-    /* Find out which event handler has become active */
-    handler = event.data.ptr;
-
-    /* Clear the eventfd */
-    event_notifier_test_and_clear(handler->notifier);
-
-    /* Handle the event */
-    handler->callback(handler);
-}
-
-/* Stop event_poll()
- *
- * This function can be used from another thread.
- */
-void event_poll_notify(EventPoll *poll)
-{
-    event_notifier_set(&poll->stop_notifier);
-}
diff --git a/hw/dataplane/event-poll.h b/hw/dataplane/event-poll.h
deleted file mode 100644
index 3e8d3ec..0000000
--- a/hw/dataplane/event-poll.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Event loop with file descriptor polling
- *
- * Copyright 2012 IBM, Corp.
- * Copyright 2012 Red Hat, Inc. and/or its affiliates
- *
- * Authors:
- *   Stefan Hajnoczi <stefanha 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.
- *
- */
-
-#ifndef EVENT_POLL_H
-#define EVENT_POLL_H
-
-#include "qemu/event_notifier.h"
-
-typedef struct EventHandler EventHandler;
-typedef void EventCallback(EventHandler *handler);
-struct EventHandler {
-    EventNotifier *notifier;        /* eventfd */
-    EventCallback *callback;        /* callback function */
-};
-
-typedef struct {
-    int epoll_fd;                   /* epoll(2) file descriptor */
-    EventNotifier stop_notifier;    /* stop poll notifier */
-    EventHandler stop_handler;      /* stop poll handler */
-} EventPoll;
-
-void event_poll_add(EventPoll *poll, EventHandler *handler,
-                    EventNotifier *notifier, EventCallback *callback);
-void event_poll_init(EventPoll *poll);
-void event_poll_cleanup(EventPoll *poll);
-void event_poll(EventPoll *poll);
-void event_poll_notify(EventPoll *poll);
-
-#endif /* EVENT_POLL_H */
diff --git a/hw/dataplane/virtio-blk.c b/hw/dataplane/virtio-blk.c
index 3f2da22..aa9b040 100644
--- a/hw/dataplane/virtio-blk.c
+++ b/hw/dataplane/virtio-blk.c
@@ -14,13 +14,13 @@
 
 #include "trace.h"
 #include "qemu/iov.h"
-#include "event-poll.h"
 #include "qemu/thread.h"
 #include "vring.h"
 #include "ioq.h"
 #include "migration/migration.h"
 #include "hw/virtio-blk.h"
 #include "hw/dataplane/virtio-blk.h"
+#include "block/aio.h"
 
 enum {
     SEG_MAX = 126,                  /* maximum number of I/O segments */
@@ -51,9 +51,14 @@ struct VirtIOBlockDataPlane {
     Vring vring;                    /* virtqueue vring */
     EventNotifier *guest_notifier;  /* irq */
 
-    EventPoll event_poll;           /* event poller */
-    EventHandler io_handler;        /* Linux AIO completion handler */
-    EventHandler notify_handler;    /* virtqueue notify handler */
+    /* Note that these EventNotifiers are assigned by value.  This is
+     * fine as long as you do not call event_notifier_cleanup on them
+     * (because you don't own the file descriptor or handle; you just
+     * use it).
+     */
+    AioContext *ctx;
+    EventNotifier io_notifier;      /* Linux AIO completion */
+    EventNotifier host_notifier;    /* doorbell */
 
     IOQueue ioqueue;                /* Linux AIO queue (should really be per
                                        dataplane thread) */
@@ -256,10 +261,10 @@ static int process_request(IOQueue *ioq, struct iovec iov[],
     }
 }
 
-static void handle_notify(EventHandler *handler)
+static void handle_notify(EventNotifier *e)
 {
-    VirtIOBlockDataPlane *s = container_of(handler, VirtIOBlockDataPlane,
-                                           notify_handler);
+    VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane,
+                                           host_notifier);
 
     /* There is one array of iovecs into which all new requests are extracted
      * from the vring.  Requests are read from the vring and the translated
@@ -286,6 +291,7 @@ static void handle_notify(EventHandler *handler)
     unsigned int out_num = 0, in_num = 0;
     unsigned int num_queued;
 
+    event_notifier_test_and_clear(&s->host_notifier);
     for (;;) {
         /* Disable guest->host notifies to avoid unnecessary vmexits */
         vring_disable_notification(s->vdev, &s->vring);
@@ -334,11 +340,12 @@ static void handle_notify(EventHandler *handler)
     }
 }
 
-static void handle_io(EventHandler *handler)
+static void handle_io(EventNotifier *e)
 {
-    VirtIOBlockDataPlane *s = container_of(handler, VirtIOBlockDataPlane,
-                                           io_handler);
+    VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane,
+                                           io_notifier);
 
+    event_notifier_test_and_clear(&s->io_notifier);
     if (ioq_run_completion(&s->ioqueue, complete_request, s) > 0) {
         notify_guest(s);
     }
@@ -348,7 +355,7 @@ static void handle_io(EventHandler *handler)
      * requests.
      */
     if (unlikely(vring_more_avail(&s->vring))) {
-        handle_notify(&s->notify_handler);
+        handle_notify(&s->host_notifier);
     }
 }
 
@@ -357,7 +364,7 @@ static void *data_plane_thread(void *opaque)
     VirtIOBlockDataPlane *s = opaque;
 
     do {
-        event_poll(&s->event_poll);
+        aio_poll(s->ctx, true);
     } while (!s->stopping || s->num_reqs > 0);
     return NULL;
 }
@@ -445,7 +452,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
         return;
     }
 
-    event_poll_init(&s->event_poll);
+    s->ctx = aio_context_new();
 
     /* Set up guest notifier (irq) */
     if (s->vdev->binding->set_guest_notifiers(s->vdev->binding_opaque, 1,
@@ -462,17 +469,16 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
         fprintf(stderr, "virtio-blk failed to set host notifier\n");
         exit(1);
     }
-    event_poll_add(&s->event_poll, &s->notify_handler,
-                   virtio_queue_get_host_notifier(vq),
-                   handle_notify);
+    s->host_notifier = *virtio_queue_get_host_notifier(vq);
+    aio_set_event_notifier(s->ctx, &s->host_notifier, handle_notify, NULL);
 
     /* Set up ioqueue */
     ioq_init(&s->ioqueue, s->fd, REQ_MAX);
     for (i = 0; i < ARRAY_SIZE(s->requests); i++) {
         ioq_put_iocb(&s->ioqueue, &s->requests[i].iocb);
     }
-    event_poll_add(&s->event_poll, &s->io_handler,
-                   ioq_get_notifier(&s->ioqueue), handle_io);
+    s->io_notifier = *ioq_get_notifier(&s->ioqueue);
+    aio_set_event_notifier(s->ctx, &s->io_notifier, handle_io, NULL);
 
     s->started = true;
     trace_virtio_blk_data_plane_start(s);
@@ -498,15 +504,17 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
         qemu_bh_delete(s->start_bh);
         s->start_bh = NULL;
     } else {
-        event_poll_notify(&s->event_poll);
+        aio_notify(s->ctx);
         qemu_thread_join(&s->thread);
     }
 
+    aio_set_event_notifier(s->ctx, &s->io_notifier, NULL, NULL);
     ioq_cleanup(&s->ioqueue);
 
+    aio_set_event_notifier(s->ctx, &s->host_notifier, NULL, NULL);
     s->vdev->binding->set_host_notifier(s->vdev->binding_opaque, 0, false);
 
-    event_poll_cleanup(&s->event_poll);
+    aio_context_unref(s->ctx);
 
     /* Clean up guest notifier (irq) */
     s->vdev->binding->set_guest_notifiers(s->vdev->binding_opaque, 1, false);
commit 69b302b2044a9a0f6d157d25b39a91ff7124c61f
Author: Christian Borntraeger <borntraeger at de.ibm.com>
Date:   Fri Feb 22 14:37:10 2013 +0100

    virtio-blk: fix unplug + virsh reboot
    
    virtio-blk registers a vmstate change handler. Unfortunately this
    handler is not unregistered on unplug, leading to some random
    crashes if the system is restarted, e.g. via virsh reboot.
    Lets unregister the vmstate change handler if the device is removed.
    
    Signed-off-by: Christian Borntraeger <borntraeger at de.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 34913ee..f5e6ee9 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -36,6 +36,7 @@ typedef struct VirtIOBlock
     VirtIOBlkConf *blk;
     unsigned short sector_mask;
     DeviceState *qdev;
+    VMChangeStateEntry *change;
 #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
     VirtIOBlockDataPlane *dataplane;
 #endif
@@ -681,7 +682,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
     }
 #endif
 
-    qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
+    s->change = qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
     s->qdev = dev;
     register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
                     virtio_blk_save, virtio_blk_load, s);
@@ -702,6 +703,7 @@ void virtio_blk_exit(VirtIODevice *vdev)
     virtio_blk_data_plane_destroy(s->dataplane);
     s->dataplane = NULL;
 #endif
+    qemu_del_vm_change_state_handler(s->change);
     unregister_savevm(s->qdev, "virtio-blk", s);
     blockdev_mark_auto_del(s->bs);
     virtio_cleanup(vdev);
commit 02d583c7232d65920634f7553700eb348f84e472
Author: Mark Cave-Ayland <mark.cave-ayland at ilande.co.uk>
Date:   Sun Feb 24 20:46:11 2013 +0000

    ide/macio: Fix macio DMA initialisation.
    
    Commit 07a7484e5d713f1eb7c1c37b18a8ab0d56d88875 accidentally introduced a bug
    in the initialisation of the second macio DMA device which could cause some
    DMA operations to segfault QEMU.
    
    CC: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Mark Cave-Ayland <mark.cave-ayland at ilande.co.uk>
    Acked-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/macio.c b/hw/macio.c
index 74bdcd1..0c6a6b8 100644
--- a/hw/macio.c
+++ b/hw/macio.c
@@ -188,7 +188,7 @@ static int macio_newworld_initfn(PCIDevice *d)
     sysbus_dev = SYS_BUS_DEVICE(&ns->ide[1]);
     sysbus_connect_irq(sysbus_dev, 0, ns->irqs[3]);
     sysbus_connect_irq(sysbus_dev, 1, ns->irqs[4]);
-    macio_ide_register_dma(&ns->ide[0], s->dbdma, 0x1a);
+    macio_ide_register_dma(&ns->ide[1], s->dbdma, 0x1a);
     ret = qdev_init(DEVICE(&ns->ide[1]));
     if (ret < 0) {
         return ret;
commit 806f352d3d6f7b326b0ab3a49c622b124459dc8d
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Feb 22 18:10:05 2013 +0000

    gen-icount.h: Rename gen_icount_start/end to gen_tb_start/end
    
    The gen_icount_start/end functions are now somewhat misnamed since they
    are useful for generic "start/end of TB" code, used for more than just
    icount. Rename them to gen_tb_start/end.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h
index 384153b..4e3b17b 100644
--- a/include/exec/gen-icount.h
+++ b/include/exec/gen-icount.h
@@ -9,7 +9,7 @@ static TCGArg *icount_arg;
 static int icount_label;
 static int exitreq_label;
 
-static inline void gen_icount_start(void)
+static inline void gen_tb_start(void)
 {
     TCGv_i32 count;
     TCGv_i32 flag;
@@ -36,7 +36,7 @@ static inline void gen_icount_start(void)
     tcg_temp_free_i32(count);
 }
 
-static void gen_icount_end(TranslationBlock *tb, int num_insns)
+static void gen_tb_end(TranslationBlock *tb, int num_insns)
 {
     gen_set_label(exitreq_label);
     tcg_gen_exit_tb((tcg_target_long)tb + TB_EXIT_REQUESTED);
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index f8f7695..657f5e1 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3411,7 +3411,7 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env,
     if (max_insns == 0)
         max_insns = CF_COUNT_MASK;
 
-    gen_icount_start();
+    gen_tb_start();
     do {
         if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
             QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
@@ -3478,7 +3478,7 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env,
         abort();
     }
 
-    gen_icount_end(tb, num_insns);
+    gen_tb_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index f2f649d..db63c6e 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9808,7 +9808,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
     if (max_insns == 0)
         max_insns = CF_COUNT_MASK;
 
-    gen_icount_start();
+    gen_tb_start();
 
     tcg_clear_temp_count();
 
@@ -10011,7 +10011,7 @@ static inline void gen_intermediate_code_internal(CPUARMState *env,
     }
 
 done_generating:
-    gen_icount_end(tb, num_insns);
+    gen_tb_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
 
 #ifdef DEBUG_DISAS
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 14c167f..ec71ef4 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3250,7 +3250,7 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
         max_insns = CF_COUNT_MASK;
     }
 
-    gen_icount_start();
+    gen_tb_start();
     do {
         check_breakpoint(env, dc);
 
@@ -3391,7 +3391,7 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb,
             break;
         }
     }
-    gen_icount_end(tb, num_insns);
+    gen_tb_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 3b92f3b..705147a 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -8324,7 +8324,7 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
     if (max_insns == 0)
         max_insns = CF_COUNT_MASK;
 
-    gen_icount_start();
+    gen_tb_start();
     for(;;) {
         if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
             QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
@@ -8382,7 +8382,7 @@ static inline void gen_intermediate_code_internal(CPUX86State *env,
     }
     if (tb->cflags & CF_LAST_IO)
         gen_io_end();
-    gen_icount_end(tb, num_insns);
+    gen_tb_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     /* we don't forget to fill the last values */
     if (search_pc) {
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index ccaf838..695d9c5 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -1040,7 +1040,7 @@ static void gen_intermediate_code_internal(CPULM32State *env,
         max_insns = CF_COUNT_MASK;
     }
 
-    gen_icount_start();
+    gen_tb_start();
     do {
         check_breakpoint(env, dc);
 
@@ -1102,7 +1102,7 @@ static void gen_intermediate_code_internal(CPULM32State *env,
         }
     }
 
-    gen_icount_end(tb, num_insns);
+    gen_tb_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 3f1478c..20a86d8 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2999,7 +2999,7 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
     if (max_insns == 0)
         max_insns = CF_COUNT_MASK;
 
-    gen_icount_start();
+    gen_tb_start();
     do {
         pc_offset = dc->pc - pc_start;
         gen_throws_exception = NULL;
@@ -3063,7 +3063,7 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb,
             break;
         }
     }
-    gen_icount_end(tb, num_insns);
+    gen_tb_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
 
 #ifdef DEBUG_DISAS
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 687b7d1..a74da8e 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1770,7 +1770,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
     if (max_insns == 0)
         max_insns = CF_COUNT_MASK;
 
-    gen_icount_start();
+    gen_tb_start();
     do
     {
 #if SIM_COMPAT
@@ -1894,7 +1894,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
                 break;
         }
     }
-    gen_icount_end(tb, num_insns);
+    gen_tb_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
diff --git a/target-mips/translate.c b/target-mips/translate.c
index f10a533..6ce2f03 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -15596,7 +15596,7 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
     if (max_insns == 0)
         max_insns = CF_COUNT_MASK;
     LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
-    gen_icount_start();
+    gen_tb_start();
     while (ctx.bstate == BS_NONE) {
         if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
             QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
@@ -15694,7 +15694,7 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
         }
     }
 done_generating:
-    gen_icount_end(tb, num_insns);
+    gen_tb_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 23e853e..0eafd02 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1696,7 +1696,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
         max_insns = CF_COUNT_MASK;
     }
 
-    gen_icount_start();
+    gen_tb_start();
 
     do {
         check_breakpoint(cpu, dc);
@@ -1779,7 +1779,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
         }
     }
 
-    gen_icount_end(tb, num_insns);
+    gen_tb_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 80d5366..fa9e9e3 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9557,7 +9557,7 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
     if (max_insns == 0)
         max_insns = CF_COUNT_MASK;
 
-    gen_icount_start();
+    gen_tb_start();
     /* Set env in case of segfault during code fetch */
     while (ctx.exception == POWERPC_EXCP_NONE
             && tcg_ctx.gen_opc_ptr < gen_opc_end) {
@@ -9669,7 +9669,7 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
         /* Generate the return instruction */
         tcg_gen_exit_tb(0);
     }
-    gen_icount_end(tb, num_insns);
+    gen_tb_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (unlikely(search_pc)) {
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index bdf69a3..88e481c 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -4769,7 +4769,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
         max_insns = CF_COUNT_MASK;
     }
 
-    gen_icount_start();
+    gen_tb_start();
 
     do {
         if (search_pc) {
@@ -4845,7 +4845,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
         abort();
     }
 
-    gen_icount_end(tb, num_insns);
+    gen_tb_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index d255066..7f300e3 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -1959,7 +1959,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
     max_insns = tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0)
         max_insns = CF_COUNT_MASK;
-    gen_icount_start();
+    gen_tb_start();
     while (ctx.bstate == BS_NONE && tcg_ctx.gen_opc_ptr < gen_opc_end) {
         if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
             QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
@@ -2029,7 +2029,7 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb,
 	}
     }
 
-    gen_icount_end(tb, num_insns);
+    gen_tb_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
         i = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 12276d5..eb6e800 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5249,7 +5249,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
     max_insns = tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0)
         max_insns = CF_COUNT_MASK;
-    gen_icount_start();
+    gen_tb_start();
     do {
         if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
             QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
@@ -5319,7 +5319,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
             tcg_gen_exit_tb(0);
         }
     }
-    gen_icount_end(tb, num_insns);
+    gen_tb_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (spc) {
         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index d5039e2..151e35e 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -1921,7 +1921,7 @@ static inline void gen_intermediate_code_internal(CPUUniCore32State *env,
     }
 #endif
 
-    gen_icount_start();
+    gen_tb_start();
     do {
         if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
             QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
@@ -2041,7 +2041,7 @@ static inline void gen_intermediate_code_internal(CPUUniCore32State *env,
     }
 
 done_generating:
-    gen_icount_end(tb, num_insns);
+    gen_tb_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
 
 #ifdef DEBUG_DISAS
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 11e06a3..06d68db 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -2913,7 +2913,7 @@ static void gen_intermediate_code_internal(
         dc.next_icount = tcg_temp_local_new_i32();
     }
 
-    gen_icount_start();
+    gen_tb_start();
 
     if (env->singlestep_enabled && env->exception_taken) {
         env->exception_taken = 0;
@@ -2991,7 +2991,7 @@ static void gen_intermediate_code_internal(
     if (dc.is_jmp == DISAS_NEXT) {
         gen_jumpi(&dc, dc.pc, 0);
     }
-    gen_icount_end(tb, insn_count);
+    gen_tb_end(tb, insn_count);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
 
     if (search_pc) {
commit 3a808cc407744c30daa7470b5f191cde1fbc1aae
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Feb 22 18:10:04 2013 +0000

    translate-all.c: Remove cpu_unlink_tb()
    
    The (unsafe) function cpu_unlink_tb() is now unused, so we can simply
    remove it and any code that was only used by it.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/translate-all.c b/translate-all.c
index 9741d96..90ea002 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1349,55 +1349,6 @@ static TranslationBlock *tb_find_pc(uintptr_t tc_ptr)
     return &tcg_ctx.tb_ctx.tbs[m_max];
 }
 
-static void tb_reset_jump_recursive(TranslationBlock *tb);
-
-static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
-{
-    TranslationBlock *tb1, *tb_next, **ptb;
-    unsigned int n1;
-
-    tb1 = tb->jmp_next[n];
-    if (tb1 != NULL) {
-        /* find head of list */
-        for (;;) {
-            n1 = (uintptr_t)tb1 & 3;
-            tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3);
-            if (n1 == 2) {
-                break;
-            }
-            tb1 = tb1->jmp_next[n1];
-        }
-        /* we are now sure now that tb jumps to tb1 */
-        tb_next = tb1;
-
-        /* remove tb from the jmp_first list */
-        ptb = &tb_next->jmp_first;
-        for (;;) {
-            tb1 = *ptb;
-            n1 = (uintptr_t)tb1 & 3;
-            tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3);
-            if (n1 == n && tb1 == tb) {
-                break;
-            }
-            ptb = &tb1->jmp_next[n1];
-        }
-        *ptb = tb->jmp_next[n];
-        tb->jmp_next[n] = NULL;
-
-        /* suppress the jump to next tb in generated code */
-        tb_reset_jump(tb, n);
-
-        /* suppress jumps in the tb on which we could have jumped */
-        tb_reset_jump_recursive(tb_next);
-    }
-}
-
-static void tb_reset_jump_recursive(TranslationBlock *tb)
-{
-    tb_reset_jump_recursive2(tb, 0);
-    tb_reset_jump_recursive2(tb, 1);
-}
-
 #if defined(TARGET_HAS_ICE) && !defined(CONFIG_USER_ONLY)
 void tb_invalidate_phys_addr(hwaddr addr)
 {
@@ -1416,26 +1367,6 @@ void tb_invalidate_phys_addr(hwaddr addr)
 }
 #endif /* TARGET_HAS_ICE && !defined(CONFIG_USER_ONLY) */
 
-void cpu_unlink_tb(CPUState *cpu)
-{
-    /* FIXME: TB unchaining isn't SMP safe.  For now just ignore the
-       problem and hope the cpu will stop of its own accord.  For userspace
-       emulation this often isn't actually as bad as it sounds.  Often
-       signals are used primarily to interrupt blocking syscalls.  */
-    TranslationBlock *tb;
-    static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
-
-    spin_lock(&interrupt_lock);
-    tb = cpu->current_tb;
-    /* if the cpu is currently executing code, we must unlink it and
-       all the potentially executing TB */
-    if (tb) {
-        cpu->current_tb = NULL;
-        tb_reset_jump_recursive(tb);
-    }
-    spin_unlock(&interrupt_lock);
-}
-
 void tb_check_watchpoint(CPUArchState *env)
 {
     TranslationBlock *tb;
commit 378df4b23753a11be650af7664ca76bc75cb9f01
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Feb 22 18:10:03 2013 +0000

    Handle CPU interrupts by inline checking of a flag
    
    Fix some of the nasty TCG race conditions and crashes by implementing
    cpu_exit() as setting a flag which is checked at the start of each TB.
    This avoids crashes if a thread or signal handler calls cpu_exit()
    while the execution thread is itself modifying the TB graph (which
    may happen in system emulation mode as well as in linux-user mode
    with a multithreaded guest binary).
    
    This fixes the crashes seen in LP:668799; however there are another
    class of crashes described in LP:1098729 which stem from the fact
    that in linux-user with a multithreaded guest all threads will
    use and modify the same global TCG date structures (including the
    generated code buffer) without any kind of locking. This means that
    multithreaded guest binaries are still in the "unsupported"
    category.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpu-exec.c b/cpu-exec.c
index f9ea080..9092145 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -64,6 +64,12 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr)
         TranslationBlock *tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
         cpu_pc_from_tb(env, tb);
     }
+    if ((next_tb & TB_EXIT_MASK) == TB_EXIT_REQUESTED) {
+        /* We were asked to stop executing TBs (probably a pending
+         * interrupt. We've now stopped, so clear the flag.
+         */
+        cpu->tcg_exit_req = 0;
+    }
     return next_tb;
 }
 
@@ -608,7 +614,20 @@ int cpu_exec(CPUArchState *env)
                     tc_ptr = tb->tc_ptr;
                     /* execute the generated code */
                     next_tb = cpu_tb_exec(cpu, tc_ptr);
-                    if ((next_tb & TB_EXIT_MASK) == TB_EXIT_ICOUNT_EXPIRED) {
+                    switch (next_tb & TB_EXIT_MASK) {
+                    case TB_EXIT_REQUESTED:
+                        /* Something asked us to stop executing
+                         * chained TBs; just continue round the main
+                         * loop. Whatever requested the exit will also
+                         * have set something else (eg exit_request or
+                         * interrupt_request) which we will handle
+                         * next time around the loop.
+                         */
+                        tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
+                        next_tb = 0;
+                        break;
+                    case TB_EXIT_ICOUNT_EXPIRED:
+                    {
                         /* Instruction counter expired.  */
                         int insns_left;
                         tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
@@ -632,6 +651,10 @@ int cpu_exec(CPUArchState *env)
                             next_tb = 0;
                             cpu_loop_exit(env);
                         }
+                        break;
+                    }
+                    default:
+                        break;
                     }
                 }
                 cpu->current_tb = NULL;
diff --git a/exec.c b/exec.c
index a41bcb8..46a2830 100644
--- a/exec.c
+++ b/exec.c
@@ -495,7 +495,7 @@ void cpu_exit(CPUArchState *env)
     CPUState *cpu = ENV_GET_CPU(env);
 
     cpu->exit_request = 1;
-    cpu_unlink_tb(cpu);
+    cpu->tcg_exit_req = 1;
 }
 
 void cpu_abort(CPUArchState *env, const char *fmt, ...)
diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h
index c858a73..384153b 100644
--- a/include/exec/gen-icount.h
+++ b/include/exec/gen-icount.h
@@ -7,10 +7,19 @@
 
 static TCGArg *icount_arg;
 static int icount_label;
+static int exitreq_label;
 
 static inline void gen_icount_start(void)
 {
     TCGv_i32 count;
+    TCGv_i32 flag;
+
+    exitreq_label = gen_new_label();
+    flag = tcg_temp_local_new_i32();
+    tcg_gen_ld_i32(flag, cpu_env,
+                   offsetof(CPUState, tcg_exit_req) - ENV_OFFSET);
+    tcg_gen_brcondi_i32(TCG_COND_NE, flag, 0, exitreq_label);
+    tcg_temp_free_i32(flag);
 
     if (!use_icount)
         return;
@@ -29,6 +38,9 @@ static inline void gen_icount_start(void)
 
 static void gen_icount_end(TranslationBlock *tb, int num_insns)
 {
+    gen_set_label(exitreq_label);
+    tcg_gen_exit_tb((tcg_target_long)tb + TB_EXIT_REQUESTED);
+
     if (use_icount) {
         *icount_arg = num_insns;
         gen_set_label(icount_label);
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index ee1a7c8..ab2657c 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -71,6 +71,8 @@ struct kvm_run;
  * @created: Indicates whether the CPU thread has been successfully created.
  * @stop: Indicates a pending stop request.
  * @stopped: Indicates the CPU has been artificially stopped.
+ * @tcg_exit_req: Set to force TCG to stop executing linked TBs for this
+ *           CPU and return to its top level loop.
  * @env_ptr: Pointer to subclass-specific CPUArchState field.
  * @current_tb: Currently executing TB.
  * @kvm_fd: vCPU file descriptor for KVM.
@@ -100,6 +102,7 @@ struct CPUState {
     bool stop;
     bool stopped;
     volatile sig_atomic_t exit_request;
+    volatile sig_atomic_t tcg_exit_req;
 
     void *env_ptr; /* CPUArchState */
     struct TranslationBlock *current_tb;
diff --git a/tcg/tcg.h b/tcg/tcg.h
index f5d0aed..df375cf 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -703,6 +703,10 @@ TCGv_i64 tcg_const_local_i64(int64_t val);
  *        would hit zero midway through it. In this case the next-TB pointer
  *        returned is the TB we were about to execute, and the caller must
  *        arrange to execute the remaining count of instructions.
+ *  3:    we stopped because the CPU's exit_request flag was set
+ *        (usually meaning that there is an interrupt that needs to be
+ *        handled). The next-TB pointer returned is the TB we were
+ *        about to execute when we noticed the pending exit request.
  *
  * If the bottom two bits indicate an exit-via-index then the CPU
  * state is correctly synchronised and ready for execution of the next
@@ -719,6 +723,7 @@ TCGv_i64 tcg_const_local_i64(int64_t val);
 #define TB_EXIT_IDX0 0
 #define TB_EXIT_IDX1 1
 #define TB_EXIT_ICOUNT_EXPIRED 2
+#define TB_EXIT_REQUESTED 3
 
 #if !defined(tcg_qemu_tb_exec)
 # define tcg_qemu_tb_exec(env, tb_ptr) \
diff --git a/translate-all.c b/translate-all.c
index b50fb89..9741d96 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1475,7 +1475,7 @@ static void tcg_handle_interrupt(CPUArchState *env, int mask)
             cpu_abort(env, "Raised interrupt while not in I/O function");
         }
     } else {
-        cpu_unlink_tb(cpu);
+        cpu->tcg_exit_req = 1;
     }
 }
 
@@ -1626,7 +1626,7 @@ void cpu_interrupt(CPUArchState *env, int mask)
     CPUState *cpu = ENV_GET_CPU(env);
 
     env->interrupt_request |= mask;
-    cpu_unlink_tb(cpu);
+    cpu->tcg_exit_req = 1;
 }
 
 /*
commit 77211379d73ea0c89c0b5bb6eee74b17cb06f9a8
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Feb 22 18:10:02 2013 +0000

    cpu-exec: wrap tcg_qemu_tb_exec() in a fn to restore the PC
    
    If tcg_qemu_tb_exec() returns a value whose low bits don't indicate a
    link to an indexed next TB, this means that the TB execution never
    started (eg because the instruction counter hit zero).  In this case the
    guest PC has to be reset to the address of the start of the TB.
    Refactor the cpu-exec code to make all tcg_qemu_tb_exec() calls pass
    through a wrapper function which does this restoration if necessary.
    
    Note that the apparent change in cpu_exec_nocache() from calling
    cpu_pc_from_tb() with the old TB to calling it with the TB returned by
    do_tcg_qemu_tb_exec() is safe, because in the nocache case we can
    guarantee that the TB we try to execute is not linked to any others,
    so the only possible returned TB is the one we started at. That is,
    we should arguably previously have included in cpu_exec_nocache() an
    assert(next_tb & ~TB_EXIT_MASK) == tb), since the API requires restore
    from next_tb but we were using tb.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpu-exec.c b/cpu-exec.c
index 2c6b091..f9ea080 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -51,13 +51,28 @@ void cpu_resume_from_signal(CPUArchState *env, void *puc)
 }
 #endif
 
+/* Execute a TB, and fix up the CPU state afterwards if necessary */
+static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr)
+{
+    CPUArchState *env = cpu->env_ptr;
+    tcg_target_ulong next_tb = tcg_qemu_tb_exec(env, tb_ptr);
+    if ((next_tb & TB_EXIT_MASK) > TB_EXIT_IDX1) {
+        /* We didn't start executing this TB (eg because the instruction
+         * counter hit zero); we must restore the guest PC to the address
+         * of the start of the TB.
+         */
+        TranslationBlock *tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
+        cpu_pc_from_tb(env, tb);
+    }
+    return next_tb;
+}
+
 /* Execute the code without caching the generated code. An interpreter
    could be used if available. */
 static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
                              TranslationBlock *orig_tb)
 {
     CPUState *cpu = ENV_GET_CPU(env);
-    tcg_target_ulong next_tb;
     TranslationBlock *tb;
 
     /* Should never happen.
@@ -69,14 +84,8 @@ static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
                      max_cycles);
     cpu->current_tb = tb;
     /* execute the generated code */
-    next_tb = tcg_qemu_tb_exec(env, tb->tc_ptr);
+    cpu_tb_exec(cpu, tb->tc_ptr);
     cpu->current_tb = NULL;
-
-    if ((next_tb & TB_EXIT_MASK) == TB_EXIT_ICOUNT_EXPIRED) {
-        /* Restore PC.  This may happen if async event occurs before
-           the TB starts executing.  */
-        cpu_pc_from_tb(env, tb);
-    }
     tb_phys_invalidate(tb, -1);
     tb_free(tb);
 }
@@ -598,13 +607,11 @@ int cpu_exec(CPUArchState *env)
                 if (likely(!cpu->exit_request)) {
                     tc_ptr = tb->tc_ptr;
                     /* execute the generated code */
-                    next_tb = tcg_qemu_tb_exec(env, tc_ptr);
+                    next_tb = cpu_tb_exec(cpu, tc_ptr);
                     if ((next_tb & TB_EXIT_MASK) == TB_EXIT_ICOUNT_EXPIRED) {
                         /* Instruction counter expired.  */
                         int insns_left;
                         tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
-                        /* Restore PC.  */
-                        cpu_pc_from_tb(env, tb);
                         insns_left = env->icount_decr.u32;
                         if (env->icount_extra && insns_left >= 0) {
                             /* Refill decrementer and continue execution.  */
commit fadf982584b040527aeee0ede270a4d01463d293
Author: Andreas Färber <afaerber at suse.de>
Date:   Fri Feb 22 18:10:01 2013 +0000

    cpu: Introduce ENV_OFFSET macros
    
    Introduce ENV_OFFSET macros which can be used in non-target-specific
    code that needs to generate TCG instructions which reference CPUState
    fields given the cpu_env register that TCG targets set up with a
    pointer to the CPUArchState struct.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h
index c0f6c6d..252bd14 100644
--- a/target-alpha/cpu-qom.h
+++ b/target-alpha/cpu-qom.h
@@ -72,5 +72,6 @@ static inline AlphaCPU *alpha_env_get_cpu(CPUAlphaState *env)
 
 #define ENV_GET_CPU(e) CPU(alpha_env_get_cpu(e))
 
+#define ENV_OFFSET offsetof(AlphaCPU, env)
 
 #endif
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index aff7bf3..7539727 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -109,6 +109,8 @@ static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
 
 #define ENV_GET_CPU(e) CPU(arm_env_get_cpu(e))
 
+#define ENV_OFFSET offsetof(ARMCPU, env)
+
 void register_cp_regs_for_features(ARMCPU *cpu);
 
 #endif
diff --git a/target-cris/cpu-qom.h b/target-cris/cpu-qom.h
index 2bac71f..11e5286 100644
--- a/target-cris/cpu-qom.h
+++ b/target-cris/cpu-qom.h
@@ -71,5 +71,6 @@ static inline CRISCPU *cris_env_get_cpu(CPUCRISState *env)
 
 #define ENV_GET_CPU(e) CPU(cris_env_get_cpu(e))
 
+#define ENV_OFFSET offsetof(CRISCPU, env)
 
 #endif
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index 48e6b54..b7bdcb6 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -74,5 +74,6 @@ static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
 
 #define ENV_GET_CPU(e) CPU(x86_env_get_cpu(e))
 
+#define ENV_OFFSET offsetof(X86CPU, env)
 
 #endif
diff --git a/target-lm32/cpu-qom.h b/target-lm32/cpu-qom.h
index d7525b3..c0b6ce5 100644
--- a/target-lm32/cpu-qom.h
+++ b/target-lm32/cpu-qom.h
@@ -69,5 +69,6 @@ static inline LM32CPU *lm32_env_get_cpu(CPULM32State *env)
 
 #define ENV_GET_CPU(e) CPU(lm32_env_get_cpu(e))
 
+#define ENV_OFFSET offsetof(LM32CPU, env)
 
 #endif
diff --git a/target-m68k/cpu-qom.h b/target-m68k/cpu-qom.h
index 20e5684..f4c33b2 100644
--- a/target-m68k/cpu-qom.h
+++ b/target-m68k/cpu-qom.h
@@ -68,5 +68,6 @@ static inline M68kCPU *m68k_env_get_cpu(CPUM68KState *env)
 
 #define ENV_GET_CPU(e) CPU(m68k_env_get_cpu(e))
 
+#define ENV_OFFSET offsetof(M68kCPU, env)
 
 #endif
diff --git a/target-microblaze/cpu-qom.h b/target-microblaze/cpu-qom.h
index 5ea911c..a0248a5 100644
--- a/target-microblaze/cpu-qom.h
+++ b/target-microblaze/cpu-qom.h
@@ -68,5 +68,6 @@ static inline MicroBlazeCPU *mb_env_get_cpu(CPUMBState *env)
 
 #define ENV_GET_CPU(e) CPU(mb_env_get_cpu(e))
 
+#define ENV_OFFSET offsetof(MicroBlazeCPU, env)
 
 #endif
diff --git a/target-mips/cpu-qom.h b/target-mips/cpu-qom.h
index 55aa692..c6bcddf 100644
--- a/target-mips/cpu-qom.h
+++ b/target-mips/cpu-qom.h
@@ -72,5 +72,6 @@ static inline MIPSCPU *mips_env_get_cpu(CPUMIPSState *env)
 
 #define ENV_GET_CPU(e) CPU(mips_env_get_cpu(e))
 
+#define ENV_OFFSET offsetof(MIPSCPU, env)
 
 #endif
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 419f007..4cfd1c7 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -340,6 +340,8 @@ static inline OpenRISCCPU *openrisc_env_get_cpu(CPUOpenRISCState *env)
 
 #define ENV_GET_CPU(e) CPU(openrisc_env_get_cpu(e))
 
+#define ENV_OFFSET offsetof(OpenRISCCPU, env)
+
 OpenRISCCPU *cpu_openrisc_init(const char *cpu_model);
 
 void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index 2b82cdb..4e8ceca 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -78,7 +78,8 @@ static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)
 
 #define ENV_GET_CPU(e) CPU(ppc_env_get_cpu(e))
 
-PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr);
+#define ENV_OFFSET offsetof(PowerPCCPU, env)
 
+PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr);
 
 #endif
diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h
index 237184f..f6e5145 100644
--- a/target-s390x/cpu-qom.h
+++ b/target-s390x/cpu-qom.h
@@ -69,5 +69,6 @@ static inline S390CPU *s390_env_get_cpu(CPUS390XState *env)
 
 #define ENV_GET_CPU(e) CPU(s390_env_get_cpu(e))
 
+#define ENV_OFFSET offsetof(S390CPU, env)
 
 #endif
diff --git a/target-sh4/cpu-qom.h b/target-sh4/cpu-qom.h
index d368db1..f4e8976 100644
--- a/target-sh4/cpu-qom.h
+++ b/target-sh4/cpu-qom.h
@@ -68,5 +68,6 @@ static inline SuperHCPU *sh_env_get_cpu(CPUSH4State *env)
 
 #define ENV_GET_CPU(e) CPU(sh_env_get_cpu(e))
 
+#define ENV_OFFSET offsetof(SuperHCPU, env)
 
 #endif
diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h
index 89cd1cf..efeeca0 100644
--- a/target-sparc/cpu-qom.h
+++ b/target-sparc/cpu-qom.h
@@ -73,5 +73,6 @@ static inline SPARCCPU *sparc_env_get_cpu(CPUSPARCState *env)
 
 #define ENV_GET_CPU(e) CPU(sparc_env_get_cpu(e))
 
+#define ENV_OFFSET offsetof(SPARCCPU, env)
 
 #endif
diff --git a/target-unicore32/cpu-qom.h b/target-unicore32/cpu-qom.h
index 625c614..c6590bd 100644
--- a/target-unicore32/cpu-qom.h
+++ b/target-unicore32/cpu-qom.h
@@ -58,5 +58,6 @@ static inline UniCore32CPU *uc32_env_get_cpu(CPUUniCore32State *env)
 
 #define ENV_GET_CPU(e) CPU(uc32_env_get_cpu(e))
 
+#define ENV_OFFSET offsetof(UniCore32CPU, env)
 
 #endif
diff --git a/target-xtensa/cpu-qom.h b/target-xtensa/cpu-qom.h
index 270de16..c78136b 100644
--- a/target-xtensa/cpu-qom.h
+++ b/target-xtensa/cpu-qom.h
@@ -78,5 +78,6 @@ static inline XtensaCPU *xtensa_env_get_cpu(const CPUXtensaState *env)
 
 #define ENV_GET_CPU(e) CPU(xtensa_env_get_cpu(e))
 
+#define ENV_OFFSET offsetof(XtensaCPU, env)
 
 #endif
commit 0980011b4f66482d2733ab2dd0f2f61747772c6b
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Feb 22 18:10:00 2013 +0000

    tcg: Document tcg_qemu_tb_exec() and provide constants for low bit uses
    
    Document tcg_qemu_tb_exec(). In particular, its return value is a
    combination of a pointer to the next translation block and some
    extra information in the low two bits. Provide some #defines for
    the values passed in these bits to improve code clarity.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cpu-exec.c b/cpu-exec.c
index afbe497..2c6b091 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -72,7 +72,7 @@ static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
     next_tb = tcg_qemu_tb_exec(env, tb->tc_ptr);
     cpu->current_tb = NULL;
 
-    if ((next_tb & 3) == 2) {
+    if ((next_tb & TB_EXIT_MASK) == TB_EXIT_ICOUNT_EXPIRED) {
         /* Restore PC.  This may happen if async event occurs before
            the TB starts executing.  */
         cpu_pc_from_tb(env, tb);
@@ -584,7 +584,8 @@ int cpu_exec(CPUArchState *env)
                    spans two pages, we cannot safely do a direct
                    jump. */
                 if (next_tb != 0 && tb->page_addr[1] == -1) {
-                    tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
+                    tb_add_jump((TranslationBlock *)(next_tb & ~TB_EXIT_MASK),
+                                next_tb & TB_EXIT_MASK, tb);
                 }
                 spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
 
@@ -598,10 +599,10 @@ int cpu_exec(CPUArchState *env)
                     tc_ptr = tb->tc_ptr;
                     /* execute the generated code */
                     next_tb = tcg_qemu_tb_exec(env, tc_ptr);
-                    if ((next_tb & 3) == 2) {
+                    if ((next_tb & TB_EXIT_MASK) == TB_EXIT_ICOUNT_EXPIRED) {
                         /* Instruction counter expired.  */
                         int insns_left;
-                        tb = (TranslationBlock *)(next_tb & ~3);
+                        tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
                         /* Restore PC.  */
                         cpu_pc_from_tb(env, tb);
                         insns_left = env->icount_decr.u32;
diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h
index 8043b3b..c858a73 100644
--- a/include/exec/gen-icount.h
+++ b/include/exec/gen-icount.h
@@ -32,7 +32,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((tcg_target_long)tb + 2);
+        tcg_gen_exit_tb((tcg_target_long)tb + TB_EXIT_ICOUNT_EXPIRED);
     }
 }
 
diff --git a/tcg/tcg.h b/tcg/tcg.h
index b195396..f5d0aed 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -677,7 +677,49 @@ TCGv_i64 tcg_const_i64(int64_t val);
 TCGv_i32 tcg_const_local_i32(int32_t val);
 TCGv_i64 tcg_const_local_i64(int64_t val);
 
-/* TCG targets may use a different definition of tcg_qemu_tb_exec. */
+/**
+ * tcg_qemu_tb_exec:
+ * @env: CPUArchState * for the CPU
+ * @tb_ptr: address of generated code for the TB to execute
+ *
+ * Start executing code from a given translation block.
+ * Where translation blocks have been linked, execution
+ * may proceed from the given TB into successive ones.
+ * Control eventually returns only when some action is needed
+ * from the top-level loop: either control must pass to a TB
+ * which has not yet been directly linked, or an asynchronous
+ * event such as an interrupt needs handling.
+ *
+ * The return value is a pointer to the next TB to execute
+ * (if known; otherwise zero). This pointer is assumed to be
+ * 4-aligned, and the bottom two bits are used to return further
+ * information:
+ *  0, 1: the link between this TB and the next is via the specified
+ *        TB index (0 or 1). That is, we left the TB via (the equivalent
+ *        of) "goto_tb <index>". The main loop uses this to determine
+ *        how to link the TB just executed to the next.
+ *  2:    we are using instruction counting code generation, and we
+ *        did not start executing this TB because the instruction counter
+ *        would hit zero midway through it. In this case the next-TB pointer
+ *        returned is the TB we were about to execute, and the caller must
+ *        arrange to execute the remaining count of instructions.
+ *
+ * If the bottom two bits indicate an exit-via-index then the CPU
+ * state is correctly synchronised and ready for execution of the next
+ * TB (and in particular the guest PC is the address to execute next).
+ * Otherwise, we gave up on execution of this TB before it started, and
+ * the caller must fix up the CPU state by calling cpu_pc_from_tb()
+ * with the next-TB pointer we return.
+ *
+ * Note that TCG targets may use a different definition of tcg_qemu_tb_exec
+ * to this default (which just calls the prologue.code emitted by
+ * tcg_target_qemu_prologue()).
+ */
+#define TB_EXIT_MASK 3
+#define TB_EXIT_IDX0 0
+#define TB_EXIT_IDX1 1
+#define TB_EXIT_ICOUNT_EXPIRED 2
+
 #if !defined(tcg_qemu_tb_exec)
 # define tcg_qemu_tb_exec(env, tb_ptr) \
     ((tcg_target_ulong (*)(void *, void *))tcg_ctx.code_gen_prologue)(env, \
commit 07ca08bac88f116e9beb05d48d07b406ace8fbc0
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Wed Feb 27 16:09:38 2013 +0000

    tcg-sparc: fix build
    
    Fix build breakage by 803d805bcef4ea7b7d6ef0b4929263e1160d6b3c:
    make tcg_out_addsub2() always available.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 6d489fc..025af9b 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -776,6 +776,7 @@ static void tcg_out_setcond2_i32(TCGContext *s, TCGCond cond, TCGArg ret,
         break;
     }
 }
+#endif
 
 static void tcg_out_addsub2(TCGContext *s, TCGArg rl, TCGArg rh,
                             TCGArg al, TCGArg ah, TCGArg bl, int blconst,
@@ -792,7 +793,6 @@ static void tcg_out_addsub2(TCGContext *s, TCGArg rl, TCGArg rh,
     tcg_out_arithc(s, rh, ah, bh, bhconst, oph);
     tcg_out_mov(s, TCG_TYPE_I32, rl, tmp);
 }
-#endif
 
 /* Generate global QEMU prologue and epilogue code */
 static void tcg_target_qemu_prologue(TCGContext *s)
commit 7a2771d1541ec9a0c585e9b853e5f4dc036919ad
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Feb 5 15:22:56 2013 +0100

    sh: move files referencing CPU to hw/sh4/
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/sh4/Makefile.objs b/hw/sh4/Makefile.objs
index b2e1f1e..72b6a1f 100644
--- a/hw/sh4/Makefile.objs
+++ b/hw/sh4/Makefile.objs
@@ -1,7 +1,9 @@
-obj-y = sh7750.o sh7750_regnames.o tc58128.o
+obj-y = tc58128.o
 obj-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
 obj-y += ide/mmio.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
 obj-y += shix.o r2d.o
+
+obj-y += sh7750.o sh7750_regnames.o
diff --git a/hw/sh4/sh7750.c b/hw/sh4/sh7750.c
new file mode 100644
index 0000000..6778c94
--- /dev/null
+++ b/hw/sh4/sh7750.c
@@ -0,0 +1,838 @@
+/*
+ * SH7750 device
+ *
+ * Copyright (c) 2007 Magnus Damm
+ * Copyright (c) 2005 Samuel Tardieu
+ *
+ * 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 <stdio.h>
+#include "hw/hw.h"
+#include "hw/sh.h"
+#include "sysemu/sysemu.h"
+#include "hw/sh7750_regs.h"
+#include "hw/sh7750_regnames.h"
+#include "hw/sh_intc.h"
+#include "cpu.h"
+#include "exec/address-spaces.h"
+
+#define NB_DEVICES 4
+
+typedef struct SH7750State {
+    MemoryRegion iomem;
+    MemoryRegion iomem_1f0;
+    MemoryRegion iomem_ff0;
+    MemoryRegion iomem_1f8;
+    MemoryRegion iomem_ff8;
+    MemoryRegion iomem_1fc;
+    MemoryRegion iomem_ffc;
+    MemoryRegion mmct_iomem;
+    /* CPU */
+    CPUSH4State *cpu;
+    /* Peripheral frequency in Hz */
+    uint32_t periph_freq;
+    /* SDRAM controller */
+    uint32_t bcr1;
+    uint16_t bcr2;
+    uint16_t bcr3;
+    uint32_t bcr4;
+    uint16_t rfcr;
+    /* PCMCIA controller */
+    uint16_t pcr;
+    /* IO ports */
+    uint16_t gpioic;
+    uint32_t pctra;
+    uint32_t pctrb;
+    uint16_t portdira;		/* Cached */
+    uint16_t portpullupa;	/* Cached */
+    uint16_t portdirb;		/* Cached */
+    uint16_t portpullupb;	/* Cached */
+    uint16_t pdtra;
+    uint16_t pdtrb;
+    uint16_t periph_pdtra;	/* Imposed by the peripherals */
+    uint16_t periph_portdira;	/* Direction seen from the peripherals */
+    uint16_t periph_pdtrb;	/* Imposed by the peripherals */
+    uint16_t periph_portdirb;	/* Direction seen from the peripherals */
+    sh7750_io_device *devices[NB_DEVICES];	/* External peripherals */
+
+    /* Cache */
+    uint32_t ccr;
+
+    struct intc_desc intc;
+} SH7750State;
+
+static inline int has_bcr3_and_bcr4(SH7750State * s)
+{
+	return (s->cpu->features & SH_FEATURE_BCR3_AND_BCR4);
+}
+/**********************************************************************
+ I/O ports
+**********************************************************************/
+
+int sh7750_register_io_device(SH7750State * s, sh7750_io_device * device)
+{
+    int i;
+
+    for (i = 0; i < NB_DEVICES; i++) {
+	if (s->devices[i] == NULL) {
+	    s->devices[i] = device;
+	    return 0;
+	}
+    }
+    return -1;
+}
+
+static uint16_t portdir(uint32_t v)
+{
+#define EVENPORTMASK(n) ((v & (1<<((n)<<1))) >> (n))
+    return
+	EVENPORTMASK(15) | EVENPORTMASK(14) | EVENPORTMASK(13) |
+	EVENPORTMASK(12) | EVENPORTMASK(11) | EVENPORTMASK(10) |
+	EVENPORTMASK(9) | EVENPORTMASK(8) | EVENPORTMASK(7) |
+	EVENPORTMASK(6) | EVENPORTMASK(5) | EVENPORTMASK(4) |
+	EVENPORTMASK(3) | EVENPORTMASK(2) | EVENPORTMASK(1) |
+	EVENPORTMASK(0);
+}
+
+static uint16_t portpullup(uint32_t v)
+{
+#define ODDPORTMASK(n) ((v & (1<<(((n)<<1)+1))) >> (n))
+    return
+	ODDPORTMASK(15) | ODDPORTMASK(14) | ODDPORTMASK(13) |
+	ODDPORTMASK(12) | ODDPORTMASK(11) | ODDPORTMASK(10) |
+	ODDPORTMASK(9) | ODDPORTMASK(8) | ODDPORTMASK(7) | ODDPORTMASK(6) |
+	ODDPORTMASK(5) | ODDPORTMASK(4) | ODDPORTMASK(3) | ODDPORTMASK(2) |
+	ODDPORTMASK(1) | ODDPORTMASK(0);
+}
+
+static uint16_t porta_lines(SH7750State * s)
+{
+    return (s->portdira & s->pdtra) |	/* CPU */
+	(s->periph_portdira & s->periph_pdtra) |	/* Peripherals */
+	(~(s->portdira | s->periph_portdira) & s->portpullupa);	/* Pullups */
+}
+
+static uint16_t portb_lines(SH7750State * s)
+{
+    return (s->portdirb & s->pdtrb) |	/* CPU */
+	(s->periph_portdirb & s->periph_pdtrb) |	/* Peripherals */
+	(~(s->portdirb | s->periph_portdirb) & s->portpullupb);	/* Pullups */
+}
+
+static void gen_port_interrupts(SH7750State * s)
+{
+    /* XXXXX interrupts not generated */
+}
+
+static void porta_changed(SH7750State * s, uint16_t prev)
+{
+    uint16_t currenta, changes;
+    int i, r = 0;
+
+#if 0
+    fprintf(stderr, "porta changed from 0x%04x to 0x%04x\n",
+	    prev, porta_lines(s));
+    fprintf(stderr, "pdtra=0x%04x, pctra=0x%08x\n", s->pdtra, s->pctra);
+#endif
+    currenta = porta_lines(s);
+    if (currenta == prev)
+	return;
+    changes = currenta ^ prev;
+
+    for (i = 0; i < NB_DEVICES; i++) {
+	if (s->devices[i] && (s->devices[i]->portamask_trigger & changes)) {
+	    r |= s->devices[i]->port_change_cb(currenta, portb_lines(s),
+					       &s->periph_pdtra,
+					       &s->periph_portdira,
+					       &s->periph_pdtrb,
+					       &s->periph_portdirb);
+	}
+    }
+
+    if (r)
+	gen_port_interrupts(s);
+}
+
+static void portb_changed(SH7750State * s, uint16_t prev)
+{
+    uint16_t currentb, changes;
+    int i, r = 0;
+
+    currentb = portb_lines(s);
+    if (currentb == prev)
+	return;
+    changes = currentb ^ prev;
+
+    for (i = 0; i < NB_DEVICES; i++) {
+	if (s->devices[i] && (s->devices[i]->portbmask_trigger & changes)) {
+	    r |= s->devices[i]->port_change_cb(portb_lines(s), currentb,
+					       &s->periph_pdtra,
+					       &s->periph_portdira,
+					       &s->periph_pdtrb,
+					       &s->periph_portdirb);
+	}
+    }
+
+    if (r)
+	gen_port_interrupts(s);
+}
+
+/**********************************************************************
+ Memory
+**********************************************************************/
+
+static void error_access(const char *kind, hwaddr addr)
+{
+    fprintf(stderr, "%s to %s (0x" TARGET_FMT_plx ") not supported\n",
+	    kind, regname(addr), addr);
+}
+
+static void ignore_access(const char *kind, hwaddr addr)
+{
+    fprintf(stderr, "%s to %s (0x" TARGET_FMT_plx ") ignored\n",
+	    kind, regname(addr), addr);
+}
+
+static uint32_t sh7750_mem_readb(void *opaque, hwaddr addr)
+{
+    switch (addr) {
+    default:
+	error_access("byte read", addr);
+        abort();
+    }
+}
+
+static uint32_t sh7750_mem_readw(void *opaque, hwaddr addr)
+{
+    SH7750State *s = opaque;
+
+    switch (addr) {
+    case SH7750_BCR2_A7:
+	return s->bcr2;
+    case SH7750_BCR3_A7:
+	if(!has_bcr3_and_bcr4(s))
+	    error_access("word read", addr);
+	return s->bcr3;
+    case SH7750_FRQCR_A7:
+	return 0;
+    case SH7750_PCR_A7:
+	return s->pcr;
+    case SH7750_RFCR_A7:
+	fprintf(stderr,
+		"Read access to refresh count register, incrementing\n");
+	return s->rfcr++;
+    case SH7750_PDTRA_A7:
+	return porta_lines(s);
+    case SH7750_PDTRB_A7:
+	return portb_lines(s);
+    case SH7750_RTCOR_A7:
+    case SH7750_RTCNT_A7:
+    case SH7750_RTCSR_A7:
+	ignore_access("word read", addr);
+	return 0;
+    default:
+	error_access("word read", addr);
+        abort();
+    }
+}
+
+static uint32_t sh7750_mem_readl(void *opaque, hwaddr addr)
+{
+    SH7750State *s = opaque;
+
+    switch (addr) {
+    case SH7750_BCR1_A7:
+	return s->bcr1;
+    case SH7750_BCR4_A7:
+	if(!has_bcr3_and_bcr4(s))
+	    error_access("long read", addr);
+	return s->bcr4;
+    case SH7750_WCR1_A7:
+    case SH7750_WCR2_A7:
+    case SH7750_WCR3_A7:
+    case SH7750_MCR_A7:
+        ignore_access("long read", addr);
+        return 0;
+    case SH7750_MMUCR_A7:
+	return s->cpu->mmucr;
+    case SH7750_PTEH_A7:
+	return s->cpu->pteh;
+    case SH7750_PTEL_A7:
+	return s->cpu->ptel;
+    case SH7750_TTB_A7:
+	return s->cpu->ttb;
+    case SH7750_TEA_A7:
+	return s->cpu->tea;
+    case SH7750_TRA_A7:
+	return s->cpu->tra;
+    case SH7750_EXPEVT_A7:
+	return s->cpu->expevt;
+    case SH7750_INTEVT_A7:
+	return s->cpu->intevt;
+    case SH7750_CCR_A7:
+	return s->ccr;
+    case 0x1f000030:		/* Processor version */
+	return s->cpu->pvr;
+    case 0x1f000040:		/* Cache version */
+	return s->cpu->cvr;
+    case 0x1f000044:		/* Processor revision */
+	return s->cpu->prr;
+    default:
+	error_access("long read", addr);
+        abort();
+    }
+}
+
+#define is_in_sdrmx(a, x) (a >= SH7750_SDMR ## x ## _A7 \
+			&& a <= (SH7750_SDMR ## x ## _A7 + SH7750_SDMR ## x ## _REGNB))
+static void sh7750_mem_writeb(void *opaque, hwaddr addr,
+			      uint32_t mem_value)
+{
+
+    if (is_in_sdrmx(addr, 2) || is_in_sdrmx(addr, 3)) {
+	ignore_access("byte write", addr);
+	return;
+    }
+
+    error_access("byte write", addr);
+    abort();
+}
+
+static void sh7750_mem_writew(void *opaque, hwaddr addr,
+			      uint32_t mem_value)
+{
+    SH7750State *s = opaque;
+    uint16_t temp;
+
+    switch (addr) {
+	/* SDRAM controller */
+    case SH7750_BCR2_A7:
+        s->bcr2 = mem_value;
+        return;
+    case SH7750_BCR3_A7:
+	if(!has_bcr3_and_bcr4(s))
+	    error_access("word write", addr);
+	s->bcr3 = mem_value;
+	return;
+    case SH7750_PCR_A7:
+	s->pcr = mem_value;
+	return;
+    case SH7750_RTCNT_A7:
+    case SH7750_RTCOR_A7:
+    case SH7750_RTCSR_A7:
+	ignore_access("word write", addr);
+	return;
+	/* IO ports */
+    case SH7750_PDTRA_A7:
+	temp = porta_lines(s);
+	s->pdtra = mem_value;
+	porta_changed(s, temp);
+	return;
+    case SH7750_PDTRB_A7:
+	temp = portb_lines(s);
+	s->pdtrb = mem_value;
+	portb_changed(s, temp);
+	return;
+    case SH7750_RFCR_A7:
+	fprintf(stderr, "Write access to refresh count register\n");
+	s->rfcr = mem_value;
+	return;
+    case SH7750_GPIOIC_A7:
+	s->gpioic = mem_value;
+	if (mem_value != 0) {
+	    fprintf(stderr, "I/O interrupts not implemented\n");
+            abort();
+	}
+	return;
+    default:
+	error_access("word write", addr);
+        abort();
+    }
+}
+
+static void sh7750_mem_writel(void *opaque, hwaddr addr,
+			      uint32_t mem_value)
+{
+    SH7750State *s = opaque;
+    uint16_t temp;
+
+    switch (addr) {
+	/* SDRAM controller */
+    case SH7750_BCR1_A7:
+        s->bcr1 = mem_value;
+        return;
+    case SH7750_BCR4_A7:
+	if(!has_bcr3_and_bcr4(s))
+	    error_access("long write", addr);
+	s->bcr4 = mem_value;
+	return;
+    case SH7750_WCR1_A7:
+    case SH7750_WCR2_A7:
+    case SH7750_WCR3_A7:
+    case SH7750_MCR_A7:
+	ignore_access("long write", addr);
+	return;
+	/* IO ports */
+    case SH7750_PCTRA_A7:
+	temp = porta_lines(s);
+	s->pctra = mem_value;
+	s->portdira = portdir(mem_value);
+	s->portpullupa = portpullup(mem_value);
+	porta_changed(s, temp);
+	return;
+    case SH7750_PCTRB_A7:
+	temp = portb_lines(s);
+	s->pctrb = mem_value;
+	s->portdirb = portdir(mem_value);
+	s->portpullupb = portpullup(mem_value);
+	portb_changed(s, temp);
+	return;
+    case SH7750_MMUCR_A7:
+        if (mem_value & MMUCR_TI) {
+            cpu_sh4_invalidate_tlb(s->cpu);
+        }
+        s->cpu->mmucr = mem_value & ~MMUCR_TI;
+        return;
+    case SH7750_PTEH_A7:
+        /* If asid changes, clear all registered tlb entries. */
+	if ((s->cpu->pteh & 0xff) != (mem_value & 0xff))
+	    tlb_flush(s->cpu, 1);
+	s->cpu->pteh = mem_value;
+	return;
+    case SH7750_PTEL_A7:
+	s->cpu->ptel = mem_value;
+	return;
+    case SH7750_PTEA_A7:
+	s->cpu->ptea = mem_value & 0x0000000f;
+	return;
+    case SH7750_TTB_A7:
+	s->cpu->ttb = mem_value;
+	return;
+    case SH7750_TEA_A7:
+	s->cpu->tea = mem_value;
+	return;
+    case SH7750_TRA_A7:
+	s->cpu->tra = mem_value & 0x000007ff;
+	return;
+    case SH7750_EXPEVT_A7:
+	s->cpu->expevt = mem_value & 0x000007ff;
+	return;
+    case SH7750_INTEVT_A7:
+	s->cpu->intevt = mem_value & 0x000007ff;
+	return;
+    case SH7750_CCR_A7:
+	s->ccr = mem_value;
+	return;
+    default:
+	error_access("long write", addr);
+        abort();
+    }
+}
+
+static const MemoryRegionOps sh7750_mem_ops = {
+    .old_mmio = {
+        .read = {sh7750_mem_readb,
+                 sh7750_mem_readw,
+                 sh7750_mem_readl },
+        .write = {sh7750_mem_writeb,
+                  sh7750_mem_writew,
+                  sh7750_mem_writel },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+/* sh775x interrupt controller tables for sh_intc.c
+ * stolen from linux/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+ */
+
+enum {
+	UNUSED = 0,
+
+	/* interrupt sources */
+	IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6, IRL_7,
+	IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E,
+	IRL0, IRL1, IRL2, IRL3,
+	HUDI, GPIOI,
+	DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
+	DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
+	DMAC_DMAE,
+	PCIC0_PCISERR, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+	PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3,
+	TMU3, TMU4, TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
+	RTC_ATI, RTC_PRI, RTC_CUI,
+	SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI,
+	SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI,
+	WDT,
+	REF_RCMI, REF_ROVI,
+
+	/* interrupt groups */
+	DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
+	/* irl bundle */
+	IRL,
+
+	NR_SOURCES,
+};
+
+static struct intc_vect vectors[] = {
+	INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
+	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
+	INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
+	INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
+	INTC_VECT(RTC_CUI, 0x4c0),
+	INTC_VECT(SCI1_ERI, 0x4e0), INTC_VECT(SCI1_RXI, 0x500),
+	INTC_VECT(SCI1_TXI, 0x520), INTC_VECT(SCI1_TEI, 0x540),
+	INTC_VECT(SCIF_ERI, 0x700), INTC_VECT(SCIF_RXI, 0x720),
+	INTC_VECT(SCIF_BRI, 0x740), INTC_VECT(SCIF_TXI, 0x760),
+	INTC_VECT(WDT, 0x560),
+	INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
+};
+
+static struct intc_group groups[] = {
+	INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
+	INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
+	INTC_GROUP(SCI1, SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI),
+	INTC_GROUP(SCIF, SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI),
+	INTC_GROUP(REF, REF_RCMI, REF_ROVI),
+};
+
+static struct intc_prio_reg prio_registers[] = {
+	{ 0xffd00004, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
+	{ 0xffd00008, 0, 16, 4, /* IPRB */ { WDT, REF, SCI1, 0 } },
+	{ 0xffd0000c, 0, 16, 4, /* IPRC */ { GPIOI, DMAC, SCIF, HUDI } },
+	{ 0xffd00010, 0, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } },
+	{ 0xfe080000, 0, 32, 4, /* INTPRI00 */ { 0, 0, 0, 0,
+						 TMU4, TMU3,
+						 PCIC1, PCIC0_PCISERR } },
+};
+
+/* SH7750, SH7750S, SH7751 and SH7091 all have 4-channel DMA controllers */
+
+static struct intc_vect vectors_dma4[] = {
+	INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
+	INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
+	INTC_VECT(DMAC_DMAE, 0x6c0),
+};
+
+static struct intc_group groups_dma4[] = {
+	INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
+		   DMAC_DMTE3, DMAC_DMAE),
+};
+
+/* SH7750R and SH7751R both have 8-channel DMA controllers */
+
+static struct intc_vect vectors_dma8[] = {
+	INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
+	INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
+	INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0),
+	INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0),
+	INTC_VECT(DMAC_DMAE, 0x6c0),
+};
+
+static struct intc_group groups_dma8[] = {
+	INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
+		   DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
+		   DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
+};
+
+/* SH7750R, SH7751 and SH7751R all have two extra timer channels */
+
+static struct intc_vect vectors_tmu34[] = {
+	INTC_VECT(TMU3, 0xb00), INTC_VECT(TMU4, 0xb80),
+};
+
+static struct intc_mask_reg mask_registers[] = {
+	{ 0xfe080040, 0xfe080060, 32, /* INTMSK00 / INTMSKCLR00 */
+	  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, TMU4, TMU3,
+	    PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+	    PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2,
+	    PCIC1_PCIDMA3, PCIC0_PCISERR } },
+};
+
+/* SH7750S, SH7750R, SH7751 and SH7751R all have IRLM priority registers */
+
+static struct intc_vect vectors_irlm[] = {
+	INTC_VECT(IRL0, 0x240), INTC_VECT(IRL1, 0x2a0),
+	INTC_VECT(IRL2, 0x300), INTC_VECT(IRL3, 0x360),
+};
+
+/* SH7751 and SH7751R both have PCI */
+
+static struct intc_vect vectors_pci[] = {
+	INTC_VECT(PCIC0_PCISERR, 0xa00), INTC_VECT(PCIC1_PCIERR, 0xae0),
+	INTC_VECT(PCIC1_PCIPWDWN, 0xac0), INTC_VECT(PCIC1_PCIPWON, 0xaa0),
+	INTC_VECT(PCIC1_PCIDMA0, 0xa80), INTC_VECT(PCIC1_PCIDMA1, 0xa60),
+	INTC_VECT(PCIC1_PCIDMA2, 0xa40), INTC_VECT(PCIC1_PCIDMA3, 0xa20),
+};
+
+static struct intc_group groups_pci[] = {
+	INTC_GROUP(PCIC1, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
+		   PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3),
+};
+
+static struct intc_vect vectors_irl[] = {
+	INTC_VECT(IRL_0, 0x200),
+	INTC_VECT(IRL_1, 0x220),
+	INTC_VECT(IRL_2, 0x240),
+	INTC_VECT(IRL_3, 0x260),
+	INTC_VECT(IRL_4, 0x280),
+	INTC_VECT(IRL_5, 0x2a0),
+	INTC_VECT(IRL_6, 0x2c0),
+	INTC_VECT(IRL_7, 0x2e0),
+	INTC_VECT(IRL_8, 0x300),
+	INTC_VECT(IRL_9, 0x320),
+	INTC_VECT(IRL_A, 0x340),
+	INTC_VECT(IRL_B, 0x360),
+	INTC_VECT(IRL_C, 0x380),
+	INTC_VECT(IRL_D, 0x3a0),
+	INTC_VECT(IRL_E, 0x3c0),
+};
+
+static struct intc_group groups_irl[] = {
+	INTC_GROUP(IRL, IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6,
+		IRL_7, IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E),
+};
+
+/**********************************************************************
+ Memory mapped cache and TLB
+**********************************************************************/
+
+#define MM_REGION_MASK   0x07000000
+#define MM_ICACHE_ADDR   (0)
+#define MM_ICACHE_DATA   (1)
+#define MM_ITLB_ADDR     (2)
+#define MM_ITLB_DATA     (3)
+#define MM_OCACHE_ADDR   (4)
+#define MM_OCACHE_DATA   (5)
+#define MM_UTLB_ADDR     (6)
+#define MM_UTLB_DATA     (7)
+#define MM_REGION_TYPE(addr)  ((addr & MM_REGION_MASK) >> 24)
+
+static uint64_t invalid_read(void *opaque, hwaddr addr)
+{
+    abort();
+
+    return 0;
+}
+
+static uint64_t sh7750_mmct_read(void *opaque, hwaddr addr,
+                                 unsigned size)
+{
+    SH7750State *s = opaque;
+    uint32_t ret = 0;
+
+    if (size != 4) {
+        return invalid_read(opaque, addr);
+    }
+
+    switch (MM_REGION_TYPE(addr)) {
+    case MM_ICACHE_ADDR:
+    case MM_ICACHE_DATA:
+        /* do nothing */
+	break;
+    case MM_ITLB_ADDR:
+        ret = cpu_sh4_read_mmaped_itlb_addr(s->cpu, addr);
+        break;
+    case MM_ITLB_DATA:
+        ret = cpu_sh4_read_mmaped_itlb_data(s->cpu, addr);
+        break;
+    case MM_OCACHE_ADDR:
+    case MM_OCACHE_DATA:
+        /* do nothing */
+	break;
+    case MM_UTLB_ADDR:
+        ret = cpu_sh4_read_mmaped_utlb_addr(s->cpu, addr);
+        break;
+    case MM_UTLB_DATA:
+        ret = cpu_sh4_read_mmaped_utlb_data(s->cpu, addr);
+        break;
+    default:
+        abort();
+    }
+
+    return ret;
+}
+
+static void invalid_write(void *opaque, hwaddr addr,
+                          uint64_t mem_value)
+{
+    abort();
+}
+
+static void sh7750_mmct_write(void *opaque, hwaddr addr,
+                              uint64_t mem_value, unsigned size)
+{
+    SH7750State *s = opaque;
+
+    if (size != 4) {
+        invalid_write(opaque, addr, mem_value);
+    }
+
+    switch (MM_REGION_TYPE(addr)) {
+    case MM_ICACHE_ADDR:
+    case MM_ICACHE_DATA:
+        /* do nothing */
+	break;
+    case MM_ITLB_ADDR:
+        cpu_sh4_write_mmaped_itlb_addr(s->cpu, addr, mem_value);
+        break;
+    case MM_ITLB_DATA:
+        cpu_sh4_write_mmaped_itlb_data(s->cpu, addr, mem_value);
+        abort();
+	break;
+    case MM_OCACHE_ADDR:
+    case MM_OCACHE_DATA:
+        /* do nothing */
+	break;
+    case MM_UTLB_ADDR:
+        cpu_sh4_write_mmaped_utlb_addr(s->cpu, addr, mem_value);
+	break;
+    case MM_UTLB_DATA:
+        cpu_sh4_write_mmaped_utlb_data(s->cpu, addr, mem_value);
+	break;
+    default:
+        abort();
+	break;
+    }
+}
+
+static const MemoryRegionOps sh7750_mmct_ops = {
+    .read = sh7750_mmct_read,
+    .write = sh7750_mmct_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+SH7750State *sh7750_init(CPUSH4State * cpu, MemoryRegion *sysmem)
+{
+    SH7750State *s;
+
+    s = g_malloc0(sizeof(SH7750State));
+    s->cpu = cpu;
+    s->periph_freq = 60000000;	/* 60MHz */
+    memory_region_init_io(&s->iomem, &sh7750_mem_ops, s,
+                          "memory", 0x1fc01000);
+
+    memory_region_init_alias(&s->iomem_1f0, "memory-1f0",
+                             &s->iomem, 0x1f000000, 0x1000);
+    memory_region_add_subregion(sysmem, 0x1f000000, &s->iomem_1f0);
+
+    memory_region_init_alias(&s->iomem_ff0, "memory-ff0",
+                             &s->iomem, 0x1f000000, 0x1000);
+    memory_region_add_subregion(sysmem, 0xff000000, &s->iomem_ff0);
+
+    memory_region_init_alias(&s->iomem_1f8, "memory-1f8",
+                             &s->iomem, 0x1f800000, 0x1000);
+    memory_region_add_subregion(sysmem, 0x1f800000, &s->iomem_1f8);
+
+    memory_region_init_alias(&s->iomem_ff8, "memory-ff8",
+                             &s->iomem, 0x1f800000, 0x1000);
+    memory_region_add_subregion(sysmem, 0xff800000, &s->iomem_ff8);
+
+    memory_region_init_alias(&s->iomem_1fc, "memory-1fc",
+                             &s->iomem, 0x1fc00000, 0x1000);
+    memory_region_add_subregion(sysmem, 0x1fc00000, &s->iomem_1fc);
+
+    memory_region_init_alias(&s->iomem_ffc, "memory-ffc",
+                             &s->iomem, 0x1fc00000, 0x1000);
+    memory_region_add_subregion(sysmem, 0xffc00000, &s->iomem_ffc);
+
+    memory_region_init_io(&s->mmct_iomem, &sh7750_mmct_ops, s,
+                          "cache-and-tlb", 0x08000000);
+    memory_region_add_subregion(sysmem, 0xf0000000, &s->mmct_iomem);
+
+    sh_intc_init(sysmem, &s->intc, NR_SOURCES,
+		 _INTC_ARRAY(mask_registers),
+		 _INTC_ARRAY(prio_registers));
+
+    sh_intc_register_sources(&s->intc,
+			     _INTC_ARRAY(vectors),
+			     _INTC_ARRAY(groups));
+
+    cpu->intc_handle = &s->intc;
+
+    sh_serial_init(sysmem, 0x1fe00000,
+                   0, s->periph_freq, serial_hds[0],
+                   s->intc.irqs[SCI1_ERI],
+                   s->intc.irqs[SCI1_RXI],
+                   s->intc.irqs[SCI1_TXI],
+                   s->intc.irqs[SCI1_TEI],
+                   NULL);
+    sh_serial_init(sysmem, 0x1fe80000,
+                   SH_SERIAL_FEAT_SCIF,
+                   s->periph_freq, serial_hds[1],
+                   s->intc.irqs[SCIF_ERI],
+                   s->intc.irqs[SCIF_RXI],
+                   s->intc.irqs[SCIF_TXI],
+                   NULL,
+                   s->intc.irqs[SCIF_BRI]);
+
+    tmu012_init(sysmem, 0x1fd80000,
+		TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
+		s->periph_freq,
+		s->intc.irqs[TMU0],
+		s->intc.irqs[TMU1],
+		s->intc.irqs[TMU2_TUNI],
+		s->intc.irqs[TMU2_TICPI]);
+
+    if (cpu->id & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) {
+        sh_intc_register_sources(&s->intc,
+				 _INTC_ARRAY(vectors_dma4),
+				 _INTC_ARRAY(groups_dma4));
+    }
+
+    if (cpu->id & (SH_CPU_SH7750R | SH_CPU_SH7751R)) {
+        sh_intc_register_sources(&s->intc,
+				 _INTC_ARRAY(vectors_dma8),
+				 _INTC_ARRAY(groups_dma8));
+    }
+
+    if (cpu->id & (SH_CPU_SH7750R | SH_CPU_SH7751 | SH_CPU_SH7751R)) {
+        sh_intc_register_sources(&s->intc,
+				 _INTC_ARRAY(vectors_tmu34),
+				 NULL, 0);
+        tmu012_init(sysmem, 0x1e100000, 0, s->periph_freq,
+		    s->intc.irqs[TMU3],
+		    s->intc.irqs[TMU4],
+		    NULL, NULL);
+    }
+
+    if (cpu->id & (SH_CPU_SH7751_ALL)) {
+        sh_intc_register_sources(&s->intc,
+				 _INTC_ARRAY(vectors_pci),
+				 _INTC_ARRAY(groups_pci));
+    }
+
+    if (cpu->id & (SH_CPU_SH7750S | SH_CPU_SH7750R | SH_CPU_SH7751_ALL)) {
+        sh_intc_register_sources(&s->intc,
+				 _INTC_ARRAY(vectors_irlm),
+				 NULL, 0);
+    }
+
+    sh_intc_register_sources(&s->intc,
+				_INTC_ARRAY(vectors_irl),
+				_INTC_ARRAY(groups_irl));
+    return s;
+}
+
+qemu_irq sh7750_irl(SH7750State *s)
+{
+    sh_intc_toggle_source(sh_intc_source(&s->intc, IRL), 1, 0); /* enable */
+    return qemu_allocate_irqs(sh_intc_set_irl, sh_intc_source(&s->intc, IRL),
+                               1)[0];
+}
diff --git a/hw/sh4/sh7750_regnames.c b/hw/sh4/sh7750_regnames.c
new file mode 100644
index 0000000..389698d
--- /dev/null
+++ b/hw/sh4/sh7750_regnames.c
@@ -0,0 +1,97 @@
+#include "hw/hw.h"
+#include "hw/sh.h"
+#include "hw/sh7750_regs.h"
+#include "hw/sh7750_regnames.h"
+
+#define REGNAME(r) {r, #r},
+
+typedef struct {
+    uint32_t regaddr;
+    const char *regname;
+} regname_t;
+
+static regname_t regnames[] = {
+    REGNAME(SH7750_PTEH_A7)
+	REGNAME(SH7750_PTEL_A7)
+	REGNAME(SH7750_PTEA_A7)
+	REGNAME(SH7750_TTB_A7)
+	REGNAME(SH7750_TEA_A7)
+	REGNAME(SH7750_MMUCR_A7)
+	REGNAME(SH7750_CCR_A7)
+	REGNAME(SH7750_QACR0_A7)
+	REGNAME(SH7750_QACR1_A7)
+	REGNAME(SH7750_TRA_A7)
+	REGNAME(SH7750_EXPEVT_A7)
+	REGNAME(SH7750_INTEVT_A7)
+	REGNAME(SH7750_STBCR_A7)
+	REGNAME(SH7750_STBCR2_A7)
+	REGNAME(SH7750_FRQCR_A7)
+	REGNAME(SH7750_WTCNT_A7)
+	REGNAME(SH7750_WTCSR_A7)
+	REGNAME(SH7750_R64CNT_A7)
+	REGNAME(SH7750_RSECCNT_A7)
+	REGNAME(SH7750_RMINCNT_A7)
+	REGNAME(SH7750_RHRCNT_A7)
+	REGNAME(SH7750_RWKCNT_A7)
+	REGNAME(SH7750_RDAYCNT_A7)
+	REGNAME(SH7750_RMONCNT_A7)
+	REGNAME(SH7750_RYRCNT_A7)
+	REGNAME(SH7750_RSECAR_A7)
+	REGNAME(SH7750_RMINAR_A7)
+	REGNAME(SH7750_RHRAR_A7)
+	REGNAME(SH7750_RWKAR_A7)
+	REGNAME(SH7750_RDAYAR_A7)
+	REGNAME(SH7750_RMONAR_A7)
+	REGNAME(SH7750_RCR1_A7)
+	REGNAME(SH7750_RCR2_A7)
+	REGNAME(SH7750_BCR1_A7)
+	REGNAME(SH7750_BCR2_A7)
+	REGNAME(SH7750_WCR1_A7)
+	REGNAME(SH7750_WCR2_A7)
+	REGNAME(SH7750_WCR3_A7)
+	REGNAME(SH7750_MCR_A7)
+	REGNAME(SH7750_PCR_A7)
+	REGNAME(SH7750_RTCSR_A7)
+	REGNAME(SH7750_RTCNT_A7)
+	REGNAME(SH7750_RTCOR_A7)
+	REGNAME(SH7750_RFCR_A7)
+	REGNAME(SH7750_SAR0_A7)
+	REGNAME(SH7750_SAR1_A7)
+	REGNAME(SH7750_SAR2_A7)
+	REGNAME(SH7750_SAR3_A7)
+	REGNAME(SH7750_DAR0_A7)
+	REGNAME(SH7750_DAR1_A7)
+	REGNAME(SH7750_DAR2_A7)
+	REGNAME(SH7750_DAR3_A7)
+	REGNAME(SH7750_DMATCR0_A7)
+	REGNAME(SH7750_DMATCR1_A7)
+	REGNAME(SH7750_DMATCR2_A7)
+	REGNAME(SH7750_DMATCR3_A7)
+	REGNAME(SH7750_CHCR0_A7)
+	REGNAME(SH7750_CHCR1_A7)
+	REGNAME(SH7750_CHCR2_A7)
+	REGNAME(SH7750_CHCR3_A7)
+	REGNAME(SH7750_DMAOR_A7)
+	REGNAME(SH7750_PCTRA_A7)
+	REGNAME(SH7750_PDTRA_A7)
+	REGNAME(SH7750_PCTRB_A7)
+	REGNAME(SH7750_PDTRB_A7)
+	REGNAME(SH7750_GPIOIC_A7)
+	REGNAME(SH7750_ICR_A7)
+	REGNAME(SH7750_BCR3_A7)
+	REGNAME(SH7750_BCR4_A7)
+	REGNAME(SH7750_SDMR2_A7)
+	REGNAME(SH7750_SDMR3_A7) {(uint32_t) - 1, NULL}
+};
+
+const char *regname(uint32_t addr)
+{
+    unsigned int i;
+
+    for (i = 0; regnames[i].regaddr != (uint32_t) - 1; i++) {
+	if (regnames[i].regaddr == addr)
+	    return regnames[i].regname;
+    }
+
+    return "<unknown reg>";
+}
diff --git a/hw/sh7750.c b/hw/sh7750.c
deleted file mode 100644
index 6778c94..0000000
--- a/hw/sh7750.c
+++ /dev/null
@@ -1,838 +0,0 @@
-/*
- * SH7750 device
- *
- * Copyright (c) 2007 Magnus Damm
- * Copyright (c) 2005 Samuel Tardieu
- *
- * 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 <stdio.h>
-#include "hw/hw.h"
-#include "hw/sh.h"
-#include "sysemu/sysemu.h"
-#include "hw/sh7750_regs.h"
-#include "hw/sh7750_regnames.h"
-#include "hw/sh_intc.h"
-#include "cpu.h"
-#include "exec/address-spaces.h"
-
-#define NB_DEVICES 4
-
-typedef struct SH7750State {
-    MemoryRegion iomem;
-    MemoryRegion iomem_1f0;
-    MemoryRegion iomem_ff0;
-    MemoryRegion iomem_1f8;
-    MemoryRegion iomem_ff8;
-    MemoryRegion iomem_1fc;
-    MemoryRegion iomem_ffc;
-    MemoryRegion mmct_iomem;
-    /* CPU */
-    CPUSH4State *cpu;
-    /* Peripheral frequency in Hz */
-    uint32_t periph_freq;
-    /* SDRAM controller */
-    uint32_t bcr1;
-    uint16_t bcr2;
-    uint16_t bcr3;
-    uint32_t bcr4;
-    uint16_t rfcr;
-    /* PCMCIA controller */
-    uint16_t pcr;
-    /* IO ports */
-    uint16_t gpioic;
-    uint32_t pctra;
-    uint32_t pctrb;
-    uint16_t portdira;		/* Cached */
-    uint16_t portpullupa;	/* Cached */
-    uint16_t portdirb;		/* Cached */
-    uint16_t portpullupb;	/* Cached */
-    uint16_t pdtra;
-    uint16_t pdtrb;
-    uint16_t periph_pdtra;	/* Imposed by the peripherals */
-    uint16_t periph_portdira;	/* Direction seen from the peripherals */
-    uint16_t periph_pdtrb;	/* Imposed by the peripherals */
-    uint16_t periph_portdirb;	/* Direction seen from the peripherals */
-    sh7750_io_device *devices[NB_DEVICES];	/* External peripherals */
-
-    /* Cache */
-    uint32_t ccr;
-
-    struct intc_desc intc;
-} SH7750State;
-
-static inline int has_bcr3_and_bcr4(SH7750State * s)
-{
-	return (s->cpu->features & SH_FEATURE_BCR3_AND_BCR4);
-}
-/**********************************************************************
- I/O ports
-**********************************************************************/
-
-int sh7750_register_io_device(SH7750State * s, sh7750_io_device * device)
-{
-    int i;
-
-    for (i = 0; i < NB_DEVICES; i++) {
-	if (s->devices[i] == NULL) {
-	    s->devices[i] = device;
-	    return 0;
-	}
-    }
-    return -1;
-}
-
-static uint16_t portdir(uint32_t v)
-{
-#define EVENPORTMASK(n) ((v & (1<<((n)<<1))) >> (n))
-    return
-	EVENPORTMASK(15) | EVENPORTMASK(14) | EVENPORTMASK(13) |
-	EVENPORTMASK(12) | EVENPORTMASK(11) | EVENPORTMASK(10) |
-	EVENPORTMASK(9) | EVENPORTMASK(8) | EVENPORTMASK(7) |
-	EVENPORTMASK(6) | EVENPORTMASK(5) | EVENPORTMASK(4) |
-	EVENPORTMASK(3) | EVENPORTMASK(2) | EVENPORTMASK(1) |
-	EVENPORTMASK(0);
-}
-
-static uint16_t portpullup(uint32_t v)
-{
-#define ODDPORTMASK(n) ((v & (1<<(((n)<<1)+1))) >> (n))
-    return
-	ODDPORTMASK(15) | ODDPORTMASK(14) | ODDPORTMASK(13) |
-	ODDPORTMASK(12) | ODDPORTMASK(11) | ODDPORTMASK(10) |
-	ODDPORTMASK(9) | ODDPORTMASK(8) | ODDPORTMASK(7) | ODDPORTMASK(6) |
-	ODDPORTMASK(5) | ODDPORTMASK(4) | ODDPORTMASK(3) | ODDPORTMASK(2) |
-	ODDPORTMASK(1) | ODDPORTMASK(0);
-}
-
-static uint16_t porta_lines(SH7750State * s)
-{
-    return (s->portdira & s->pdtra) |	/* CPU */
-	(s->periph_portdira & s->periph_pdtra) |	/* Peripherals */
-	(~(s->portdira | s->periph_portdira) & s->portpullupa);	/* Pullups */
-}
-
-static uint16_t portb_lines(SH7750State * s)
-{
-    return (s->portdirb & s->pdtrb) |	/* CPU */
-	(s->periph_portdirb & s->periph_pdtrb) |	/* Peripherals */
-	(~(s->portdirb | s->periph_portdirb) & s->portpullupb);	/* Pullups */
-}
-
-static void gen_port_interrupts(SH7750State * s)
-{
-    /* XXXXX interrupts not generated */
-}
-
-static void porta_changed(SH7750State * s, uint16_t prev)
-{
-    uint16_t currenta, changes;
-    int i, r = 0;
-
-#if 0
-    fprintf(stderr, "porta changed from 0x%04x to 0x%04x\n",
-	    prev, porta_lines(s));
-    fprintf(stderr, "pdtra=0x%04x, pctra=0x%08x\n", s->pdtra, s->pctra);
-#endif
-    currenta = porta_lines(s);
-    if (currenta == prev)
-	return;
-    changes = currenta ^ prev;
-
-    for (i = 0; i < NB_DEVICES; i++) {
-	if (s->devices[i] && (s->devices[i]->portamask_trigger & changes)) {
-	    r |= s->devices[i]->port_change_cb(currenta, portb_lines(s),
-					       &s->periph_pdtra,
-					       &s->periph_portdira,
-					       &s->periph_pdtrb,
-					       &s->periph_portdirb);
-	}
-    }
-
-    if (r)
-	gen_port_interrupts(s);
-}
-
-static void portb_changed(SH7750State * s, uint16_t prev)
-{
-    uint16_t currentb, changes;
-    int i, r = 0;
-
-    currentb = portb_lines(s);
-    if (currentb == prev)
-	return;
-    changes = currentb ^ prev;
-
-    for (i = 0; i < NB_DEVICES; i++) {
-	if (s->devices[i] && (s->devices[i]->portbmask_trigger & changes)) {
-	    r |= s->devices[i]->port_change_cb(portb_lines(s), currentb,
-					       &s->periph_pdtra,
-					       &s->periph_portdira,
-					       &s->periph_pdtrb,
-					       &s->periph_portdirb);
-	}
-    }
-
-    if (r)
-	gen_port_interrupts(s);
-}
-
-/**********************************************************************
- Memory
-**********************************************************************/
-
-static void error_access(const char *kind, hwaddr addr)
-{
-    fprintf(stderr, "%s to %s (0x" TARGET_FMT_plx ") not supported\n",
-	    kind, regname(addr), addr);
-}
-
-static void ignore_access(const char *kind, hwaddr addr)
-{
-    fprintf(stderr, "%s to %s (0x" TARGET_FMT_plx ") ignored\n",
-	    kind, regname(addr), addr);
-}
-
-static uint32_t sh7750_mem_readb(void *opaque, hwaddr addr)
-{
-    switch (addr) {
-    default:
-	error_access("byte read", addr);
-        abort();
-    }
-}
-
-static uint32_t sh7750_mem_readw(void *opaque, hwaddr addr)
-{
-    SH7750State *s = opaque;
-
-    switch (addr) {
-    case SH7750_BCR2_A7:
-	return s->bcr2;
-    case SH7750_BCR3_A7:
-	if(!has_bcr3_and_bcr4(s))
-	    error_access("word read", addr);
-	return s->bcr3;
-    case SH7750_FRQCR_A7:
-	return 0;
-    case SH7750_PCR_A7:
-	return s->pcr;
-    case SH7750_RFCR_A7:
-	fprintf(stderr,
-		"Read access to refresh count register, incrementing\n");
-	return s->rfcr++;
-    case SH7750_PDTRA_A7:
-	return porta_lines(s);
-    case SH7750_PDTRB_A7:
-	return portb_lines(s);
-    case SH7750_RTCOR_A7:
-    case SH7750_RTCNT_A7:
-    case SH7750_RTCSR_A7:
-	ignore_access("word read", addr);
-	return 0;
-    default:
-	error_access("word read", addr);
-        abort();
-    }
-}
-
-static uint32_t sh7750_mem_readl(void *opaque, hwaddr addr)
-{
-    SH7750State *s = opaque;
-
-    switch (addr) {
-    case SH7750_BCR1_A7:
-	return s->bcr1;
-    case SH7750_BCR4_A7:
-	if(!has_bcr3_and_bcr4(s))
-	    error_access("long read", addr);
-	return s->bcr4;
-    case SH7750_WCR1_A7:
-    case SH7750_WCR2_A7:
-    case SH7750_WCR3_A7:
-    case SH7750_MCR_A7:
-        ignore_access("long read", addr);
-        return 0;
-    case SH7750_MMUCR_A7:
-	return s->cpu->mmucr;
-    case SH7750_PTEH_A7:
-	return s->cpu->pteh;
-    case SH7750_PTEL_A7:
-	return s->cpu->ptel;
-    case SH7750_TTB_A7:
-	return s->cpu->ttb;
-    case SH7750_TEA_A7:
-	return s->cpu->tea;
-    case SH7750_TRA_A7:
-	return s->cpu->tra;
-    case SH7750_EXPEVT_A7:
-	return s->cpu->expevt;
-    case SH7750_INTEVT_A7:
-	return s->cpu->intevt;
-    case SH7750_CCR_A7:
-	return s->ccr;
-    case 0x1f000030:		/* Processor version */
-	return s->cpu->pvr;
-    case 0x1f000040:		/* Cache version */
-	return s->cpu->cvr;
-    case 0x1f000044:		/* Processor revision */
-	return s->cpu->prr;
-    default:
-	error_access("long read", addr);
-        abort();
-    }
-}
-
-#define is_in_sdrmx(a, x) (a >= SH7750_SDMR ## x ## _A7 \
-			&& a <= (SH7750_SDMR ## x ## _A7 + SH7750_SDMR ## x ## _REGNB))
-static void sh7750_mem_writeb(void *opaque, hwaddr addr,
-			      uint32_t mem_value)
-{
-
-    if (is_in_sdrmx(addr, 2) || is_in_sdrmx(addr, 3)) {
-	ignore_access("byte write", addr);
-	return;
-    }
-
-    error_access("byte write", addr);
-    abort();
-}
-
-static void sh7750_mem_writew(void *opaque, hwaddr addr,
-			      uint32_t mem_value)
-{
-    SH7750State *s = opaque;
-    uint16_t temp;
-
-    switch (addr) {
-	/* SDRAM controller */
-    case SH7750_BCR2_A7:
-        s->bcr2 = mem_value;
-        return;
-    case SH7750_BCR3_A7:
-	if(!has_bcr3_and_bcr4(s))
-	    error_access("word write", addr);
-	s->bcr3 = mem_value;
-	return;
-    case SH7750_PCR_A7:
-	s->pcr = mem_value;
-	return;
-    case SH7750_RTCNT_A7:
-    case SH7750_RTCOR_A7:
-    case SH7750_RTCSR_A7:
-	ignore_access("word write", addr);
-	return;
-	/* IO ports */
-    case SH7750_PDTRA_A7:
-	temp = porta_lines(s);
-	s->pdtra = mem_value;
-	porta_changed(s, temp);
-	return;
-    case SH7750_PDTRB_A7:
-	temp = portb_lines(s);
-	s->pdtrb = mem_value;
-	portb_changed(s, temp);
-	return;
-    case SH7750_RFCR_A7:
-	fprintf(stderr, "Write access to refresh count register\n");
-	s->rfcr = mem_value;
-	return;
-    case SH7750_GPIOIC_A7:
-	s->gpioic = mem_value;
-	if (mem_value != 0) {
-	    fprintf(stderr, "I/O interrupts not implemented\n");
-            abort();
-	}
-	return;
-    default:
-	error_access("word write", addr);
-        abort();
-    }
-}
-
-static void sh7750_mem_writel(void *opaque, hwaddr addr,
-			      uint32_t mem_value)
-{
-    SH7750State *s = opaque;
-    uint16_t temp;
-
-    switch (addr) {
-	/* SDRAM controller */
-    case SH7750_BCR1_A7:
-        s->bcr1 = mem_value;
-        return;
-    case SH7750_BCR4_A7:
-	if(!has_bcr3_and_bcr4(s))
-	    error_access("long write", addr);
-	s->bcr4 = mem_value;
-	return;
-    case SH7750_WCR1_A7:
-    case SH7750_WCR2_A7:
-    case SH7750_WCR3_A7:
-    case SH7750_MCR_A7:
-	ignore_access("long write", addr);
-	return;
-	/* IO ports */
-    case SH7750_PCTRA_A7:
-	temp = porta_lines(s);
-	s->pctra = mem_value;
-	s->portdira = portdir(mem_value);
-	s->portpullupa = portpullup(mem_value);
-	porta_changed(s, temp);
-	return;
-    case SH7750_PCTRB_A7:
-	temp = portb_lines(s);
-	s->pctrb = mem_value;
-	s->portdirb = portdir(mem_value);
-	s->portpullupb = portpullup(mem_value);
-	portb_changed(s, temp);
-	return;
-    case SH7750_MMUCR_A7:
-        if (mem_value & MMUCR_TI) {
-            cpu_sh4_invalidate_tlb(s->cpu);
-        }
-        s->cpu->mmucr = mem_value & ~MMUCR_TI;
-        return;
-    case SH7750_PTEH_A7:
-        /* If asid changes, clear all registered tlb entries. */
-	if ((s->cpu->pteh & 0xff) != (mem_value & 0xff))
-	    tlb_flush(s->cpu, 1);
-	s->cpu->pteh = mem_value;
-	return;
-    case SH7750_PTEL_A7:
-	s->cpu->ptel = mem_value;
-	return;
-    case SH7750_PTEA_A7:
-	s->cpu->ptea = mem_value & 0x0000000f;
-	return;
-    case SH7750_TTB_A7:
-	s->cpu->ttb = mem_value;
-	return;
-    case SH7750_TEA_A7:
-	s->cpu->tea = mem_value;
-	return;
-    case SH7750_TRA_A7:
-	s->cpu->tra = mem_value & 0x000007ff;
-	return;
-    case SH7750_EXPEVT_A7:
-	s->cpu->expevt = mem_value & 0x000007ff;
-	return;
-    case SH7750_INTEVT_A7:
-	s->cpu->intevt = mem_value & 0x000007ff;
-	return;
-    case SH7750_CCR_A7:
-	s->ccr = mem_value;
-	return;
-    default:
-	error_access("long write", addr);
-        abort();
-    }
-}
-
-static const MemoryRegionOps sh7750_mem_ops = {
-    .old_mmio = {
-        .read = {sh7750_mem_readb,
-                 sh7750_mem_readw,
-                 sh7750_mem_readl },
-        .write = {sh7750_mem_writeb,
-                  sh7750_mem_writew,
-                  sh7750_mem_writel },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-/* sh775x interrupt controller tables for sh_intc.c
- * stolen from linux/arch/sh/kernel/cpu/sh4/setup-sh7750.c
- */
-
-enum {
-	UNUSED = 0,
-
-	/* interrupt sources */
-	IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6, IRL_7,
-	IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E,
-	IRL0, IRL1, IRL2, IRL3,
-	HUDI, GPIOI,
-	DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
-	DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
-	DMAC_DMAE,
-	PCIC0_PCISERR, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
-	PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3,
-	TMU3, TMU4, TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
-	RTC_ATI, RTC_PRI, RTC_CUI,
-	SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI,
-	SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI,
-	WDT,
-	REF_RCMI, REF_ROVI,
-
-	/* interrupt groups */
-	DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
-	/* irl bundle */
-	IRL,
-
-	NR_SOURCES,
-};
-
-static struct intc_vect vectors[] = {
-	INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
-	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
-	INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
-	INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
-	INTC_VECT(RTC_CUI, 0x4c0),
-	INTC_VECT(SCI1_ERI, 0x4e0), INTC_VECT(SCI1_RXI, 0x500),
-	INTC_VECT(SCI1_TXI, 0x520), INTC_VECT(SCI1_TEI, 0x540),
-	INTC_VECT(SCIF_ERI, 0x700), INTC_VECT(SCIF_RXI, 0x720),
-	INTC_VECT(SCIF_BRI, 0x740), INTC_VECT(SCIF_TXI, 0x760),
-	INTC_VECT(WDT, 0x560),
-	INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
-};
-
-static struct intc_group groups[] = {
-	INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
-	INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
-	INTC_GROUP(SCI1, SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI),
-	INTC_GROUP(SCIF, SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI),
-	INTC_GROUP(REF, REF_RCMI, REF_ROVI),
-};
-
-static struct intc_prio_reg prio_registers[] = {
-	{ 0xffd00004, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
-	{ 0xffd00008, 0, 16, 4, /* IPRB */ { WDT, REF, SCI1, 0 } },
-	{ 0xffd0000c, 0, 16, 4, /* IPRC */ { GPIOI, DMAC, SCIF, HUDI } },
-	{ 0xffd00010, 0, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } },
-	{ 0xfe080000, 0, 32, 4, /* INTPRI00 */ { 0, 0, 0, 0,
-						 TMU4, TMU3,
-						 PCIC1, PCIC0_PCISERR } },
-};
-
-/* SH7750, SH7750S, SH7751 and SH7091 all have 4-channel DMA controllers */
-
-static struct intc_vect vectors_dma4[] = {
-	INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
-	INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
-	INTC_VECT(DMAC_DMAE, 0x6c0),
-};
-
-static struct intc_group groups_dma4[] = {
-	INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
-		   DMAC_DMTE3, DMAC_DMAE),
-};
-
-/* SH7750R and SH7751R both have 8-channel DMA controllers */
-
-static struct intc_vect vectors_dma8[] = {
-	INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
-	INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
-	INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0),
-	INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0),
-	INTC_VECT(DMAC_DMAE, 0x6c0),
-};
-
-static struct intc_group groups_dma8[] = {
-	INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
-		   DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
-		   DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
-};
-
-/* SH7750R, SH7751 and SH7751R all have two extra timer channels */
-
-static struct intc_vect vectors_tmu34[] = {
-	INTC_VECT(TMU3, 0xb00), INTC_VECT(TMU4, 0xb80),
-};
-
-static struct intc_mask_reg mask_registers[] = {
-	{ 0xfe080040, 0xfe080060, 32, /* INTMSK00 / INTMSKCLR00 */
-	  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	    0, 0, 0, 0, 0, 0, TMU4, TMU3,
-	    PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
-	    PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2,
-	    PCIC1_PCIDMA3, PCIC0_PCISERR } },
-};
-
-/* SH7750S, SH7750R, SH7751 and SH7751R all have IRLM priority registers */
-
-static struct intc_vect vectors_irlm[] = {
-	INTC_VECT(IRL0, 0x240), INTC_VECT(IRL1, 0x2a0),
-	INTC_VECT(IRL2, 0x300), INTC_VECT(IRL3, 0x360),
-};
-
-/* SH7751 and SH7751R both have PCI */
-
-static struct intc_vect vectors_pci[] = {
-	INTC_VECT(PCIC0_PCISERR, 0xa00), INTC_VECT(PCIC1_PCIERR, 0xae0),
-	INTC_VECT(PCIC1_PCIPWDWN, 0xac0), INTC_VECT(PCIC1_PCIPWON, 0xaa0),
-	INTC_VECT(PCIC1_PCIDMA0, 0xa80), INTC_VECT(PCIC1_PCIDMA1, 0xa60),
-	INTC_VECT(PCIC1_PCIDMA2, 0xa40), INTC_VECT(PCIC1_PCIDMA3, 0xa20),
-};
-
-static struct intc_group groups_pci[] = {
-	INTC_GROUP(PCIC1, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
-		   PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3),
-};
-
-static struct intc_vect vectors_irl[] = {
-	INTC_VECT(IRL_0, 0x200),
-	INTC_VECT(IRL_1, 0x220),
-	INTC_VECT(IRL_2, 0x240),
-	INTC_VECT(IRL_3, 0x260),
-	INTC_VECT(IRL_4, 0x280),
-	INTC_VECT(IRL_5, 0x2a0),
-	INTC_VECT(IRL_6, 0x2c0),
-	INTC_VECT(IRL_7, 0x2e0),
-	INTC_VECT(IRL_8, 0x300),
-	INTC_VECT(IRL_9, 0x320),
-	INTC_VECT(IRL_A, 0x340),
-	INTC_VECT(IRL_B, 0x360),
-	INTC_VECT(IRL_C, 0x380),
-	INTC_VECT(IRL_D, 0x3a0),
-	INTC_VECT(IRL_E, 0x3c0),
-};
-
-static struct intc_group groups_irl[] = {
-	INTC_GROUP(IRL, IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6,
-		IRL_7, IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E),
-};
-
-/**********************************************************************
- Memory mapped cache and TLB
-**********************************************************************/
-
-#define MM_REGION_MASK   0x07000000
-#define MM_ICACHE_ADDR   (0)
-#define MM_ICACHE_DATA   (1)
-#define MM_ITLB_ADDR     (2)
-#define MM_ITLB_DATA     (3)
-#define MM_OCACHE_ADDR   (4)
-#define MM_OCACHE_DATA   (5)
-#define MM_UTLB_ADDR     (6)
-#define MM_UTLB_DATA     (7)
-#define MM_REGION_TYPE(addr)  ((addr & MM_REGION_MASK) >> 24)
-
-static uint64_t invalid_read(void *opaque, hwaddr addr)
-{
-    abort();
-
-    return 0;
-}
-
-static uint64_t sh7750_mmct_read(void *opaque, hwaddr addr,
-                                 unsigned size)
-{
-    SH7750State *s = opaque;
-    uint32_t ret = 0;
-
-    if (size != 4) {
-        return invalid_read(opaque, addr);
-    }
-
-    switch (MM_REGION_TYPE(addr)) {
-    case MM_ICACHE_ADDR:
-    case MM_ICACHE_DATA:
-        /* do nothing */
-	break;
-    case MM_ITLB_ADDR:
-        ret = cpu_sh4_read_mmaped_itlb_addr(s->cpu, addr);
-        break;
-    case MM_ITLB_DATA:
-        ret = cpu_sh4_read_mmaped_itlb_data(s->cpu, addr);
-        break;
-    case MM_OCACHE_ADDR:
-    case MM_OCACHE_DATA:
-        /* do nothing */
-	break;
-    case MM_UTLB_ADDR:
-        ret = cpu_sh4_read_mmaped_utlb_addr(s->cpu, addr);
-        break;
-    case MM_UTLB_DATA:
-        ret = cpu_sh4_read_mmaped_utlb_data(s->cpu, addr);
-        break;
-    default:
-        abort();
-    }
-
-    return ret;
-}
-
-static void invalid_write(void *opaque, hwaddr addr,
-                          uint64_t mem_value)
-{
-    abort();
-}
-
-static void sh7750_mmct_write(void *opaque, hwaddr addr,
-                              uint64_t mem_value, unsigned size)
-{
-    SH7750State *s = opaque;
-
-    if (size != 4) {
-        invalid_write(opaque, addr, mem_value);
-    }
-
-    switch (MM_REGION_TYPE(addr)) {
-    case MM_ICACHE_ADDR:
-    case MM_ICACHE_DATA:
-        /* do nothing */
-	break;
-    case MM_ITLB_ADDR:
-        cpu_sh4_write_mmaped_itlb_addr(s->cpu, addr, mem_value);
-        break;
-    case MM_ITLB_DATA:
-        cpu_sh4_write_mmaped_itlb_data(s->cpu, addr, mem_value);
-        abort();
-	break;
-    case MM_OCACHE_ADDR:
-    case MM_OCACHE_DATA:
-        /* do nothing */
-	break;
-    case MM_UTLB_ADDR:
-        cpu_sh4_write_mmaped_utlb_addr(s->cpu, addr, mem_value);
-	break;
-    case MM_UTLB_DATA:
-        cpu_sh4_write_mmaped_utlb_data(s->cpu, addr, mem_value);
-	break;
-    default:
-        abort();
-	break;
-    }
-}
-
-static const MemoryRegionOps sh7750_mmct_ops = {
-    .read = sh7750_mmct_read,
-    .write = sh7750_mmct_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-SH7750State *sh7750_init(CPUSH4State * cpu, MemoryRegion *sysmem)
-{
-    SH7750State *s;
-
-    s = g_malloc0(sizeof(SH7750State));
-    s->cpu = cpu;
-    s->periph_freq = 60000000;	/* 60MHz */
-    memory_region_init_io(&s->iomem, &sh7750_mem_ops, s,
-                          "memory", 0x1fc01000);
-
-    memory_region_init_alias(&s->iomem_1f0, "memory-1f0",
-                             &s->iomem, 0x1f000000, 0x1000);
-    memory_region_add_subregion(sysmem, 0x1f000000, &s->iomem_1f0);
-
-    memory_region_init_alias(&s->iomem_ff0, "memory-ff0",
-                             &s->iomem, 0x1f000000, 0x1000);
-    memory_region_add_subregion(sysmem, 0xff000000, &s->iomem_ff0);
-
-    memory_region_init_alias(&s->iomem_1f8, "memory-1f8",
-                             &s->iomem, 0x1f800000, 0x1000);
-    memory_region_add_subregion(sysmem, 0x1f800000, &s->iomem_1f8);
-
-    memory_region_init_alias(&s->iomem_ff8, "memory-ff8",
-                             &s->iomem, 0x1f800000, 0x1000);
-    memory_region_add_subregion(sysmem, 0xff800000, &s->iomem_ff8);
-
-    memory_region_init_alias(&s->iomem_1fc, "memory-1fc",
-                             &s->iomem, 0x1fc00000, 0x1000);
-    memory_region_add_subregion(sysmem, 0x1fc00000, &s->iomem_1fc);
-
-    memory_region_init_alias(&s->iomem_ffc, "memory-ffc",
-                             &s->iomem, 0x1fc00000, 0x1000);
-    memory_region_add_subregion(sysmem, 0xffc00000, &s->iomem_ffc);
-
-    memory_region_init_io(&s->mmct_iomem, &sh7750_mmct_ops, s,
-                          "cache-and-tlb", 0x08000000);
-    memory_region_add_subregion(sysmem, 0xf0000000, &s->mmct_iomem);
-
-    sh_intc_init(sysmem, &s->intc, NR_SOURCES,
-		 _INTC_ARRAY(mask_registers),
-		 _INTC_ARRAY(prio_registers));
-
-    sh_intc_register_sources(&s->intc,
-			     _INTC_ARRAY(vectors),
-			     _INTC_ARRAY(groups));
-
-    cpu->intc_handle = &s->intc;
-
-    sh_serial_init(sysmem, 0x1fe00000,
-                   0, s->periph_freq, serial_hds[0],
-                   s->intc.irqs[SCI1_ERI],
-                   s->intc.irqs[SCI1_RXI],
-                   s->intc.irqs[SCI1_TXI],
-                   s->intc.irqs[SCI1_TEI],
-                   NULL);
-    sh_serial_init(sysmem, 0x1fe80000,
-                   SH_SERIAL_FEAT_SCIF,
-                   s->periph_freq, serial_hds[1],
-                   s->intc.irqs[SCIF_ERI],
-                   s->intc.irqs[SCIF_RXI],
-                   s->intc.irqs[SCIF_TXI],
-                   NULL,
-                   s->intc.irqs[SCIF_BRI]);
-
-    tmu012_init(sysmem, 0x1fd80000,
-		TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
-		s->periph_freq,
-		s->intc.irqs[TMU0],
-		s->intc.irqs[TMU1],
-		s->intc.irqs[TMU2_TUNI],
-		s->intc.irqs[TMU2_TICPI]);
-
-    if (cpu->id & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) {
-        sh_intc_register_sources(&s->intc,
-				 _INTC_ARRAY(vectors_dma4),
-				 _INTC_ARRAY(groups_dma4));
-    }
-
-    if (cpu->id & (SH_CPU_SH7750R | SH_CPU_SH7751R)) {
-        sh_intc_register_sources(&s->intc,
-				 _INTC_ARRAY(vectors_dma8),
-				 _INTC_ARRAY(groups_dma8));
-    }
-
-    if (cpu->id & (SH_CPU_SH7750R | SH_CPU_SH7751 | SH_CPU_SH7751R)) {
-        sh_intc_register_sources(&s->intc,
-				 _INTC_ARRAY(vectors_tmu34),
-				 NULL, 0);
-        tmu012_init(sysmem, 0x1e100000, 0, s->periph_freq,
-		    s->intc.irqs[TMU3],
-		    s->intc.irqs[TMU4],
-		    NULL, NULL);
-    }
-
-    if (cpu->id & (SH_CPU_SH7751_ALL)) {
-        sh_intc_register_sources(&s->intc,
-				 _INTC_ARRAY(vectors_pci),
-				 _INTC_ARRAY(groups_pci));
-    }
-
-    if (cpu->id & (SH_CPU_SH7750S | SH_CPU_SH7750R | SH_CPU_SH7751_ALL)) {
-        sh_intc_register_sources(&s->intc,
-				 _INTC_ARRAY(vectors_irlm),
-				 NULL, 0);
-    }
-
-    sh_intc_register_sources(&s->intc,
-				_INTC_ARRAY(vectors_irl),
-				_INTC_ARRAY(groups_irl));
-    return s;
-}
-
-qemu_irq sh7750_irl(SH7750State *s)
-{
-    sh_intc_toggle_source(sh_intc_source(&s->intc, IRL), 1, 0); /* enable */
-    return qemu_allocate_irqs(sh_intc_set_irl, sh_intc_source(&s->intc, IRL),
-                               1)[0];
-}
diff --git a/hw/sh7750_regnames.c b/hw/sh7750_regnames.c
deleted file mode 100644
index 389698d..0000000
--- a/hw/sh7750_regnames.c
+++ /dev/null
@@ -1,97 +0,0 @@
-#include "hw/hw.h"
-#include "hw/sh.h"
-#include "hw/sh7750_regs.h"
-#include "hw/sh7750_regnames.h"
-
-#define REGNAME(r) {r, #r},
-
-typedef struct {
-    uint32_t regaddr;
-    const char *regname;
-} regname_t;
-
-static regname_t regnames[] = {
-    REGNAME(SH7750_PTEH_A7)
-	REGNAME(SH7750_PTEL_A7)
-	REGNAME(SH7750_PTEA_A7)
-	REGNAME(SH7750_TTB_A7)
-	REGNAME(SH7750_TEA_A7)
-	REGNAME(SH7750_MMUCR_A7)
-	REGNAME(SH7750_CCR_A7)
-	REGNAME(SH7750_QACR0_A7)
-	REGNAME(SH7750_QACR1_A7)
-	REGNAME(SH7750_TRA_A7)
-	REGNAME(SH7750_EXPEVT_A7)
-	REGNAME(SH7750_INTEVT_A7)
-	REGNAME(SH7750_STBCR_A7)
-	REGNAME(SH7750_STBCR2_A7)
-	REGNAME(SH7750_FRQCR_A7)
-	REGNAME(SH7750_WTCNT_A7)
-	REGNAME(SH7750_WTCSR_A7)
-	REGNAME(SH7750_R64CNT_A7)
-	REGNAME(SH7750_RSECCNT_A7)
-	REGNAME(SH7750_RMINCNT_A7)
-	REGNAME(SH7750_RHRCNT_A7)
-	REGNAME(SH7750_RWKCNT_A7)
-	REGNAME(SH7750_RDAYCNT_A7)
-	REGNAME(SH7750_RMONCNT_A7)
-	REGNAME(SH7750_RYRCNT_A7)
-	REGNAME(SH7750_RSECAR_A7)
-	REGNAME(SH7750_RMINAR_A7)
-	REGNAME(SH7750_RHRAR_A7)
-	REGNAME(SH7750_RWKAR_A7)
-	REGNAME(SH7750_RDAYAR_A7)
-	REGNAME(SH7750_RMONAR_A7)
-	REGNAME(SH7750_RCR1_A7)
-	REGNAME(SH7750_RCR2_A7)
-	REGNAME(SH7750_BCR1_A7)
-	REGNAME(SH7750_BCR2_A7)
-	REGNAME(SH7750_WCR1_A7)
-	REGNAME(SH7750_WCR2_A7)
-	REGNAME(SH7750_WCR3_A7)
-	REGNAME(SH7750_MCR_A7)
-	REGNAME(SH7750_PCR_A7)
-	REGNAME(SH7750_RTCSR_A7)
-	REGNAME(SH7750_RTCNT_A7)
-	REGNAME(SH7750_RTCOR_A7)
-	REGNAME(SH7750_RFCR_A7)
-	REGNAME(SH7750_SAR0_A7)
-	REGNAME(SH7750_SAR1_A7)
-	REGNAME(SH7750_SAR2_A7)
-	REGNAME(SH7750_SAR3_A7)
-	REGNAME(SH7750_DAR0_A7)
-	REGNAME(SH7750_DAR1_A7)
-	REGNAME(SH7750_DAR2_A7)
-	REGNAME(SH7750_DAR3_A7)
-	REGNAME(SH7750_DMATCR0_A7)
-	REGNAME(SH7750_DMATCR1_A7)
-	REGNAME(SH7750_DMATCR2_A7)
-	REGNAME(SH7750_DMATCR3_A7)
-	REGNAME(SH7750_CHCR0_A7)
-	REGNAME(SH7750_CHCR1_A7)
-	REGNAME(SH7750_CHCR2_A7)
-	REGNAME(SH7750_CHCR3_A7)
-	REGNAME(SH7750_DMAOR_A7)
-	REGNAME(SH7750_PCTRA_A7)
-	REGNAME(SH7750_PDTRA_A7)
-	REGNAME(SH7750_PCTRB_A7)
-	REGNAME(SH7750_PDTRB_A7)
-	REGNAME(SH7750_GPIOIC_A7)
-	REGNAME(SH7750_ICR_A7)
-	REGNAME(SH7750_BCR3_A7)
-	REGNAME(SH7750_BCR4_A7)
-	REGNAME(SH7750_SDMR2_A7)
-	REGNAME(SH7750_SDMR3_A7) {(uint32_t) - 1, NULL}
-};
-
-const char *regname(uint32_t addr)
-{
-    unsigned int i;
-
-    for (i = 0; regnames[i].regaddr != (uint32_t) - 1; i++) {
-	if (regnames[i].regaddr == addr)
-	    return regnames[i].regname;
-    }
-
-    return "<unknown reg>";
-}
commit 9f64bd8aec7c31c76fa0954aaee1475d482662b4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Feb 5 12:20:00 2013 +0100

    ppc: move more files to hw/ppc
    
    These sPAPR files do not implement devices, move them over.
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index acc9961..4de0209 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -1,10 +1,9 @@
 # PREP target
 obj-y += mc146818rtc.o
 # IBM pSeries (sPAPR)
-obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_rtas.o
 obj-$(CONFIG_PSERIES) += spapr_vty.o spapr_llan.o spapr_vscsi.o
-obj-$(CONFIG_PSERIES) += spapr_pci.o pci/pci-hotplug.o spapr_iommu.o
-obj-$(CONFIG_PSERIES) += spapr_events.o spapr_nvram.o
+obj-$(CONFIG_PSERIES) += spapr_pci.o pci/pci-hotplug.o
+obj-$(CONFIG_PSERIES) += spapr_nvram.o
 # PowerPC 4xx boards
 obj-y += ppc4xx_pci.o
 # PowerPC OpenPIC
@@ -18,7 +17,8 @@ obj-y := $(addprefix ../,$(obj-y))
 # shared objects
 obj-y += ppc.o ppc_booke.o
 # IBM pSeries (sPAPR)
-obj-$(CONFIG_PSERIES) += spapr.o xics.o spapr_vio.o
+obj-$(CONFIG_PSERIES) += spapr.o xics.o spapr_vio.o spapr_events.o
+obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
 # PowerPC 4xx boards
 obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
 # PReP
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
new file mode 100644
index 0000000..ce78f09
--- /dev/null
+++ b/hw/ppc/spapr_events.c
@@ -0,0 +1,321 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * RTAS events handling
+ *
+ * Copyright (c) 2012 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/sysemu.h"
+#include "char/char.h"
+#include "hw/qdev.h"
+#include "sysemu/device_tree.h"
+
+#include "hw/spapr.h"
+#include "hw/spapr_vio.h"
+
+#include <libfdt.h>
+
+struct rtas_error_log {
+    uint32_t summary;
+#define RTAS_LOG_VERSION_MASK                   0xff000000
+#define   RTAS_LOG_VERSION_6                    0x06000000
+#define RTAS_LOG_SEVERITY_MASK                  0x00e00000
+#define   RTAS_LOG_SEVERITY_ALREADY_REPORTED    0x00c00000
+#define   RTAS_LOG_SEVERITY_FATAL               0x00a00000
+#define   RTAS_LOG_SEVERITY_ERROR               0x00800000
+#define   RTAS_LOG_SEVERITY_ERROR_SYNC          0x00600000
+#define   RTAS_LOG_SEVERITY_WARNING             0x00400000
+#define   RTAS_LOG_SEVERITY_EVENT               0x00200000
+#define   RTAS_LOG_SEVERITY_NO_ERROR            0x00000000
+#define RTAS_LOG_DISPOSITION_MASK               0x00180000
+#define   RTAS_LOG_DISPOSITION_FULLY_RECOVERED  0x00000000
+#define   RTAS_LOG_DISPOSITION_LIMITED_RECOVERY 0x00080000
+#define   RTAS_LOG_DISPOSITION_NOT_RECOVERED    0x00100000
+#define RTAS_LOG_OPTIONAL_PART_PRESENT          0x00040000
+#define RTAS_LOG_INITIATOR_MASK                 0x0000f000
+#define   RTAS_LOG_INITIATOR_UNKNOWN            0x00000000
+#define   RTAS_LOG_INITIATOR_CPU                0x00001000
+#define   RTAS_LOG_INITIATOR_PCI                0x00002000
+#define   RTAS_LOG_INITIATOR_MEMORY             0x00004000
+#define   RTAS_LOG_INITIATOR_HOTPLUG            0x00006000
+#define RTAS_LOG_TARGET_MASK                    0x00000f00
+#define   RTAS_LOG_TARGET_UNKNOWN               0x00000000
+#define   RTAS_LOG_TARGET_CPU                   0x00000100
+#define   RTAS_LOG_TARGET_PCI                   0x00000200
+#define   RTAS_LOG_TARGET_MEMORY                0x00000400
+#define   RTAS_LOG_TARGET_HOTPLUG               0x00000600
+#define RTAS_LOG_TYPE_MASK                      0x000000ff
+#define   RTAS_LOG_TYPE_OTHER                   0x00000000
+#define   RTAS_LOG_TYPE_RETRY                   0x00000001
+#define   RTAS_LOG_TYPE_TCE_ERR                 0x00000002
+#define   RTAS_LOG_TYPE_INTERN_DEV_FAIL         0x00000003
+#define   RTAS_LOG_TYPE_TIMEOUT                 0x00000004
+#define   RTAS_LOG_TYPE_DATA_PARITY             0x00000005
+#define   RTAS_LOG_TYPE_ADDR_PARITY             0x00000006
+#define   RTAS_LOG_TYPE_CACHE_PARITY            0x00000007
+#define   RTAS_LOG_TYPE_ADDR_INVALID            0x00000008
+#define   RTAS_LOG_TYPE_ECC_UNCORR              0x00000009
+#define   RTAS_LOG_TYPE_ECC_CORR                0x0000000a
+#define   RTAS_LOG_TYPE_EPOW                    0x00000040
+    uint32_t extended_length;
+} QEMU_PACKED;
+
+struct rtas_event_log_v6 {
+    uint8_t b0;
+#define RTAS_LOG_V6_B0_VALID                          0x80
+#define RTAS_LOG_V6_B0_UNRECOVERABLE_ERROR            0x40
+#define RTAS_LOG_V6_B0_RECOVERABLE_ERROR              0x20
+#define RTAS_LOG_V6_B0_DEGRADED_OPERATION             0x10
+#define RTAS_LOG_V6_B0_PREDICTIVE_ERROR               0x08
+#define RTAS_LOG_V6_B0_NEW_LOG                        0x04
+#define RTAS_LOG_V6_B0_BIGENDIAN                      0x02
+    uint8_t _resv1;
+    uint8_t b2;
+#define RTAS_LOG_V6_B2_POWERPC_FORMAT                 0x80
+#define RTAS_LOG_V6_B2_LOG_FORMAT_MASK                0x0f
+#define   RTAS_LOG_V6_B2_LOG_FORMAT_PLATFORM_EVENT    0x0e
+    uint8_t _resv2[9];
+    uint32_t company;
+#define RTAS_LOG_V6_COMPANY_IBM                 0x49424d00 /* IBM<null> */
+} QEMU_PACKED;
+
+struct rtas_event_log_v6_section_header {
+    uint16_t section_id;
+    uint16_t section_length;
+    uint8_t section_version;
+    uint8_t section_subtype;
+    uint16_t creator_component_id;
+} QEMU_PACKED;
+
+struct rtas_event_log_v6_maina {
+#define RTAS_LOG_V6_SECTION_ID_MAINA                0x5048 /* PH */
+    struct rtas_event_log_v6_section_header hdr;
+    uint32_t creation_date; /* BCD: YYYYMMDD */
+    uint32_t creation_time; /* BCD: HHMMSS00 */
+    uint8_t _platform1[8];
+    char creator_id;
+    uint8_t _resv1[2];
+    uint8_t section_count;
+    uint8_t _resv2[4];
+    uint8_t _platform2[8];
+    uint32_t plid;
+    uint8_t _platform3[4];
+} QEMU_PACKED;
+
+struct rtas_event_log_v6_mainb {
+#define RTAS_LOG_V6_SECTION_ID_MAINB                0x5548 /* UH */
+    struct rtas_event_log_v6_section_header hdr;
+    uint8_t subsystem_id;
+    uint8_t _platform1;
+    uint8_t event_severity;
+    uint8_t event_subtype;
+    uint8_t _platform2[4];
+    uint8_t _resv1[2];
+    uint16_t action_flags;
+    uint8_t _resv2[4];
+} QEMU_PACKED;
+
+struct rtas_event_log_v6_epow {
+#define RTAS_LOG_V6_SECTION_ID_EPOW                 0x4550 /* EP */
+    struct rtas_event_log_v6_section_header hdr;
+    uint8_t sensor_value;
+#define RTAS_LOG_V6_EPOW_ACTION_RESET                    0
+#define RTAS_LOG_V6_EPOW_ACTION_WARN_COOLING             1
+#define RTAS_LOG_V6_EPOW_ACTION_WARN_POWER               2
+#define RTAS_LOG_V6_EPOW_ACTION_SYSTEM_SHUTDOWN          3
+#define RTAS_LOG_V6_EPOW_ACTION_SYSTEM_HALT              4
+#define RTAS_LOG_V6_EPOW_ACTION_MAIN_ENCLOSURE           5
+#define RTAS_LOG_V6_EPOW_ACTION_POWER_OFF                7
+    uint8_t event_modifier;
+#define RTAS_LOG_V6_EPOW_MODIFIER_NORMAL                 1
+#define RTAS_LOG_V6_EPOW_MODIFIER_ON_UPS                 2
+#define RTAS_LOG_V6_EPOW_MODIFIER_CRITICAL               3
+#define RTAS_LOG_V6_EPOW_MODIFIER_TEMPERATURE            4
+    uint8_t extended_modifier;
+#define RTAS_LOG_V6_EPOW_XMODIFIER_SYSTEM_WIDE           0
+#define RTAS_LOG_V6_EPOW_XMODIFIER_PARTITION_SPECIFIC    1
+    uint8_t _resv;
+    uint64_t reason_code;
+} QEMU_PACKED;
+
+struct epow_log_full {
+    struct rtas_error_log hdr;
+    struct rtas_event_log_v6 v6hdr;
+    struct rtas_event_log_v6_maina maina;
+    struct rtas_event_log_v6_mainb mainb;
+    struct rtas_event_log_v6_epow epow;
+} QEMU_PACKED;
+
+#define EVENT_MASK_INTERNAL_ERRORS           0x80000000
+#define EVENT_MASK_EPOW                      0x40000000
+#define EVENT_MASK_HOTPLUG                   0x10000000
+#define EVENT_MASK_IO                        0x08000000
+
+#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)
+
+void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq)
+{
+    uint32_t epow_irq_ranges[] = {cpu_to_be32(epow_irq), cpu_to_be32(1)};
+    uint32_t epow_interrupts[] = {cpu_to_be32(epow_irq), 0};
+
+    _FDT((fdt_begin_node(fdt, "event-sources")));
+
+    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
+    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
+    _FDT((fdt_property(fdt, "interrupt-ranges",
+                       epow_irq_ranges, sizeof(epow_irq_ranges))));
+
+    _FDT((fdt_begin_node(fdt, "epow-events")));
+    _FDT((fdt_property(fdt, "interrupts",
+                       epow_interrupts, sizeof(epow_interrupts))));
+    _FDT((fdt_end_node(fdt)));
+
+    _FDT((fdt_end_node(fdt)));
+}
+
+static struct epow_log_full *pending_epow;
+static uint32_t next_plid;
+
+static void spapr_powerdown_req(Notifier *n, void *opaque)
+{
+    sPAPREnvironment *spapr = container_of(n, sPAPREnvironment, epow_notifier);
+    struct rtas_error_log *hdr;
+    struct rtas_event_log_v6 *v6hdr;
+    struct rtas_event_log_v6_maina *maina;
+    struct rtas_event_log_v6_mainb *mainb;
+    struct rtas_event_log_v6_epow *epow;
+    struct tm tm;
+    int year;
+
+    if (pending_epow) {
+        /* For now, we just throw away earlier events if two come
+         * along before any are consumed.  This is sufficient for our
+         * powerdown messages, but we'll need more if we do more
+         * general error/event logging */
+        g_free(pending_epow);
+    }
+    pending_epow = g_malloc0(sizeof(*pending_epow));
+    hdr = &pending_epow->hdr;
+    v6hdr = &pending_epow->v6hdr;
+    maina = &pending_epow->maina;
+    mainb = &pending_epow->mainb;
+    epow = &pending_epow->epow;
+
+    hdr->summary = cpu_to_be32(RTAS_LOG_VERSION_6
+                               | RTAS_LOG_SEVERITY_EVENT
+                               | RTAS_LOG_DISPOSITION_NOT_RECOVERED
+                               | RTAS_LOG_OPTIONAL_PART_PRESENT
+                               | RTAS_LOG_TYPE_EPOW);
+    hdr->extended_length = cpu_to_be32(sizeof(*pending_epow)
+                                       - sizeof(pending_epow->hdr));
+
+    v6hdr->b0 = RTAS_LOG_V6_B0_VALID | RTAS_LOG_V6_B0_NEW_LOG
+        | RTAS_LOG_V6_B0_BIGENDIAN;
+    v6hdr->b2 = RTAS_LOG_V6_B2_POWERPC_FORMAT
+        | RTAS_LOG_V6_B2_LOG_FORMAT_PLATFORM_EVENT;
+    v6hdr->company = cpu_to_be32(RTAS_LOG_V6_COMPANY_IBM);
+
+    maina->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINA);
+    maina->hdr.section_length = cpu_to_be16(sizeof(*maina));
+    /* FIXME: section version, subtype and creator id? */
+    qemu_get_timedate(&tm, spapr->rtc_offset);
+    year = tm.tm_year + 1900;
+    maina->creation_date = cpu_to_be32((to_bcd(year / 100) << 24)
+                                       | (to_bcd(year % 100) << 16)
+                                       | (to_bcd(tm.tm_mon + 1) << 8)
+                                       | to_bcd(tm.tm_mday));
+    maina->creation_time = cpu_to_be32((to_bcd(tm.tm_hour) << 24)
+                                       | (to_bcd(tm.tm_min) << 16)
+                                       | (to_bcd(tm.tm_sec) << 8));
+    maina->creator_id = 'H'; /* Hypervisor */
+    maina->section_count = 3; /* Main-A, Main-B and EPOW */
+    maina->plid = next_plid++;
+
+    mainb->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINB);
+    mainb->hdr.section_length = cpu_to_be16(sizeof(*mainb));
+    /* FIXME: section version, subtype and creator id? */
+    mainb->subsystem_id = 0xa0; /* External environment */
+    mainb->event_severity = 0x00; /* Informational / non-error */
+    mainb->event_subtype = 0xd0; /* Normal shutdown */
+
+    epow->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_EPOW);
+    epow->hdr.section_length = cpu_to_be16(sizeof(*epow));
+    epow->hdr.section_version = 2; /* includes extended modifier */
+    /* FIXME: section subtype and creator id? */
+    epow->sensor_value = RTAS_LOG_V6_EPOW_ACTION_SYSTEM_SHUTDOWN;
+    epow->event_modifier = RTAS_LOG_V6_EPOW_MODIFIER_NORMAL;
+    epow->extended_modifier = RTAS_LOG_V6_EPOW_XMODIFIER_PARTITION_SPECIFIC;
+
+    qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->epow_irq));
+}
+
+static void check_exception(sPAPREnvironment *spapr,
+                            uint32_t token, uint32_t nargs,
+                            target_ulong args,
+                            uint32_t nret, target_ulong rets)
+{
+    uint32_t mask, buf, len;
+    uint64_t xinfo;
+
+    if ((nargs < 6) || (nargs > 7) || nret != 1) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    xinfo = rtas_ld(args, 1);
+    mask = rtas_ld(args, 2);
+    buf = rtas_ld(args, 4);
+    len = rtas_ld(args, 5);
+    if (nargs == 7) {
+        xinfo |= (uint64_t)rtas_ld(args, 6) << 32;
+    }
+
+    if ((mask & EVENT_MASK_EPOW) && pending_epow) {
+        if (sizeof(*pending_epow) < len) {
+            len = sizeof(*pending_epow);
+        }
+
+        cpu_physical_memory_write(buf, pending_epow, len);
+        g_free(pending_epow);
+        pending_epow = NULL;
+        rtas_st(rets, 0, 0);
+    } else {
+        rtas_st(rets, 0, 1);
+    }
+}
+
+void spapr_events_init(sPAPREnvironment *spapr)
+{
+    spapr->epow_irq = spapr_allocate_msi(0);
+    spapr->epow_notifier.notify = spapr_powerdown_req;
+    qemu_register_powerdown_notifier(&spapr->epow_notifier);
+    spapr_rtas_register("check-exception", check_exception);
+}
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
new file mode 100644
index 0000000..7b89594
--- /dev/null
+++ b/hw/ppc/spapr_hcall.c
@@ -0,0 +1,741 @@
+#include "sysemu/sysemu.h"
+#include "cpu.h"
+#include "sysemu/sysemu.h"
+#include "helper_regs.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
+
+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(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                            target_ulong opcode, target_ulong *args)
+{
+    CPUPPCState *env = &cpu->env;
+    target_ulong flags = args[0];
+    target_ulong pte_index = args[1];
+    target_ulong pteh = args[2];
+    target_ulong ptel = args[3];
+    target_ulong page_shift = 12;
+    target_ulong raddr;
+    target_ulong i;
+    uint8_t *hpte;
+
+    /* only handle 4k and 16M pages for now */
+    if (pteh & HPTE_V_LARGE) {
+#if 0 /* We don't support 64k pages yet */
+        if ((ptel & 0xf000) == 0x1000) {
+            /* 64k page */
+        } else
+#endif
+        if ((ptel & 0xff000) == 0) {
+            /* 16M page */
+            page_shift = 24;
+            /* lowest AVA bit must be 0 for 16M pages */
+            if (pteh & 0x80) {
+                return H_PARAMETER;
+            }
+        } else {
+            return H_PARAMETER;
+        }
+    }
+
+    raddr = (ptel & HPTE_R_RPN) & ~((1ULL << page_shift) - 1);
+
+    if (raddr < spapr->ram_limit) {
+        /* Regular RAM - should have WIMG=0010 */
+        if ((ptel & HPTE_R_WIMG) != HPTE_R_M) {
+            return H_PARAMETER;
+        }
+    } else {
+        /* Looks like an IO address */
+        /* FIXME: What WIMG combinations could be sensible for IO?
+         * For now we allow WIMG=010x, but are there others? */
+        /* FIXME: Should we check against registered IO addresses? */
+        if ((ptel & (HPTE_R_W | HPTE_R_I | HPTE_R_M)) != HPTE_R_I) {
+            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) {
+                break;
+            }
+            hpte += HASH_PTE_SIZE_64;
+        }
+    } else {
+        i = 0;
+        hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
+        if (ldq_p(hpte) & 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);
+
+    args[0] = pte_index + i;
+    return H_SUCCESS;
+}
+
+enum {
+    REMOVE_SUCCESS = 0,
+    REMOVE_NOT_FOUND = 1,
+    REMOVE_PARM = 2,
+    REMOVE_HW = 3,
+};
+
+static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex,
+                                target_ulong avpn,
+                                target_ulong flags,
+                                target_ulong *vp, target_ulong *rp)
+{
+    uint8_t *hpte;
+    target_ulong v, r, rb;
+
+    if ((ptex * HASH_PTE_SIZE_64) & ~env->htab_mask) {
+        return REMOVE_PARM;
+    }
+
+    hpte = env->external_htab + (ptex * HASH_PTE_SIZE_64);
+
+    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)) {
+        return REMOVE_NOT_FOUND;
+    }
+    *vp = v;
+    *rp = r;
+    stq_p(hpte, 0);
+    rb = compute_tlbie_rb(v, r, ptex);
+    ppc_tlb_invalidate_one(env, rb);
+    return REMOVE_SUCCESS;
+}
+
+static target_ulong h_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                             target_ulong opcode, target_ulong *args)
+{
+    CPUPPCState *env = &cpu->env;
+    target_ulong flags = args[0];
+    target_ulong pte_index = args[1];
+    target_ulong avpn = args[2];
+    int ret;
+
+    ret = remove_hpte(env, pte_index, avpn, flags,
+                      &args[0], &args[1]);
+
+    switch (ret) {
+    case REMOVE_SUCCESS:
+        return H_SUCCESS;
+
+    case REMOVE_NOT_FOUND:
+        return H_NOT_FOUND;
+
+    case REMOVE_PARM:
+        return H_PARAMETER;
+
+    case REMOVE_HW:
+        return H_HARDWARE;
+    }
+
+    assert(0);
+}
+
+#define H_BULK_REMOVE_TYPE             0xc000000000000000ULL
+#define   H_BULK_REMOVE_REQUEST        0x4000000000000000ULL
+#define   H_BULK_REMOVE_RESPONSE       0x8000000000000000ULL
+#define   H_BULK_REMOVE_END            0xc000000000000000ULL
+#define H_BULK_REMOVE_CODE             0x3000000000000000ULL
+#define   H_BULK_REMOVE_SUCCESS        0x0000000000000000ULL
+#define   H_BULK_REMOVE_NOT_FOUND      0x1000000000000000ULL
+#define   H_BULK_REMOVE_PARM           0x2000000000000000ULL
+#define   H_BULK_REMOVE_HW             0x3000000000000000ULL
+#define H_BULK_REMOVE_RC               0x0c00000000000000ULL
+#define H_BULK_REMOVE_FLAGS            0x0300000000000000ULL
+#define   H_BULK_REMOVE_ABSOLUTE       0x0000000000000000ULL
+#define   H_BULK_REMOVE_ANDCOND        0x0100000000000000ULL
+#define   H_BULK_REMOVE_AVPN           0x0200000000000000ULL
+#define H_BULK_REMOVE_PTEX             0x00ffffffffffffffULL
+
+#define H_BULK_REMOVE_MAX_BATCH        4
+
+static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                  target_ulong opcode, target_ulong *args)
+{
+    CPUPPCState *env = &cpu->env;
+    int i;
+
+    for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) {
+        target_ulong *tsh = &args[i*2];
+        target_ulong tsl = args[i*2 + 1];
+        target_ulong v, r, ret;
+
+        if ((*tsh & H_BULK_REMOVE_TYPE) == H_BULK_REMOVE_END) {
+            break;
+        } else if ((*tsh & H_BULK_REMOVE_TYPE) != H_BULK_REMOVE_REQUEST) {
+            return H_PARAMETER;
+        }
+
+        *tsh &= H_BULK_REMOVE_PTEX | H_BULK_REMOVE_FLAGS;
+        *tsh |= H_BULK_REMOVE_RESPONSE;
+
+        if ((*tsh & H_BULK_REMOVE_ANDCOND) && (*tsh & H_BULK_REMOVE_AVPN)) {
+            *tsh |= H_BULK_REMOVE_PARM;
+            return H_PARAMETER;
+        }
+
+        ret = remove_hpte(env, *tsh & H_BULK_REMOVE_PTEX, tsl,
+                          (*tsh & H_BULK_REMOVE_FLAGS) >> 26,
+                          &v, &r);
+
+        *tsh |= ret << 60;
+
+        switch (ret) {
+        case REMOVE_SUCCESS:
+            *tsh |= (r & (HPTE_R_C | HPTE_R_R)) << 43;
+            break;
+
+        case REMOVE_PARM:
+            return H_PARAMETER;
+
+        case REMOVE_HW:
+            return H_HARDWARE;
+        }
+    }
+
+    return H_SUCCESS;
+}
+
+static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                              target_ulong opcode, target_ulong *args)
+{
+    CPUPPCState *env = &cpu->env;
+    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);
+
+    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)) {
+        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);
+    return H_SUCCESS;
+}
+
+static target_ulong h_set_dabr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                               target_ulong opcode, target_ulong *args)
+{
+    /* FIXME: actually implement this */
+    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(CPUPPCState *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_be_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_addr = vpa;
+
+    tmp = ldub_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET);
+    tmp |= VPA_SHARED_PROC_VAL;
+    stb_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET, tmp);
+
+    return H_SUCCESS;
+}
+
+static target_ulong deregister_vpa(CPUPPCState *env, target_ulong vpa)
+{
+    if (env->slb_shadow_addr) {
+        return H_RESOURCE;
+    }
+
+    if (env->dtl_addr) {
+        return H_RESOURCE;
+    }
+
+    env->vpa_addr = 0;
+    return H_SUCCESS;
+}
+
+static target_ulong register_slb_shadow(CPUPPCState *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_be_phys(addr + 0x4);
+    if (size < 0x8) {
+        return H_PARAMETER;
+    }
+
+    if ((addr / 4096) != ((addr + size - 1) / 4096)) {
+        return H_PARAMETER;
+    }
+
+    if (!env->vpa_addr) {
+        return H_RESOURCE;
+    }
+
+    env->slb_shadow_addr = addr;
+    env->slb_shadow_size = size;
+
+    return H_SUCCESS;
+}
+
+static target_ulong deregister_slb_shadow(CPUPPCState *env, target_ulong addr)
+{
+    env->slb_shadow_addr = 0;
+    env->slb_shadow_size = 0;
+    return H_SUCCESS;
+}
+
+static target_ulong register_dtl(CPUPPCState *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_be_phys(addr + 0x4);
+
+    if (size < 48) {
+        return H_PARAMETER;
+    }
+
+    if (!env->vpa_addr) {
+        return H_RESOURCE;
+    }
+
+    env->dtl_addr = addr;
+    env->dtl_size = size;
+
+    return H_SUCCESS;
+}
+
+static target_ulong deregister_dtl(CPUPPCState *env, target_ulong addr)
+{
+    env->dtl_addr = 0;
+    env->dtl_size = 0;
+
+    return H_SUCCESS;
+}
+
+static target_ulong h_register_vpa(PowerPCCPU *cpu, 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;
+    CPUPPCState *tenv;
+    CPUState *tcpu;
+
+    tcpu = qemu_get_cpu(procno);
+    if (!tcpu) {
+        return H_PARAMETER;
+    }
+    tenv = tcpu->env_ptr;
+
+    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(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                           target_ulong opcode, target_ulong *args)
+{
+    CPUPPCState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
+
+    env->msr |= (1ULL << MSR_EE);
+    hreg_compute_hflags(env);
+    if (!cpu_has_work(cs)) {
+        env->halted = 1;
+        env->exception_index = EXCP_HLT;
+        cs->exit_request = 1;
+    }
+    return H_SUCCESS;
+}
+
+static target_ulong h_rtas(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                           target_ulong opcode, target_ulong *args)
+{
+    target_ulong rtas_r3 = args[0];
+    uint32_t token = ldl_be_phys(rtas_r3);
+    uint32_t nargs = ldl_be_phys(rtas_r3 + 4);
+    uint32_t nret = ldl_be_phys(rtas_r3 + 8);
+
+    return spapr_rtas_call(spapr, token, nargs, rtas_r3 + 12,
+                           nret, rtas_r3 + 12 + 4*nargs);
+}
+
+static target_ulong h_logical_load(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                   target_ulong opcode, target_ulong *args)
+{
+    target_ulong size = args[0];
+    target_ulong addr = args[1];
+
+    switch (size) {
+    case 1:
+        args[0] = ldub_phys(addr);
+        return H_SUCCESS;
+    case 2:
+        args[0] = lduw_phys(addr);
+        return H_SUCCESS;
+    case 4:
+        args[0] = ldl_phys(addr);
+        return H_SUCCESS;
+    case 8:
+        args[0] = ldq_phys(addr);
+        return H_SUCCESS;
+    }
+    return H_PARAMETER;
+}
+
+static target_ulong h_logical_store(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                    target_ulong opcode, target_ulong *args)
+{
+    target_ulong size = args[0];
+    target_ulong addr = args[1];
+    target_ulong val  = args[2];
+
+    switch (size) {
+    case 1:
+        stb_phys(addr, val);
+        return H_SUCCESS;
+    case 2:
+        stw_phys(addr, val);
+        return H_SUCCESS;
+    case 4:
+        stl_phys(addr, val);
+        return H_SUCCESS;
+    case 8:
+        stq_phys(addr, val);
+        return H_SUCCESS;
+    }
+    return H_PARAMETER;
+}
+
+static target_ulong h_logical_memop(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                    target_ulong opcode, target_ulong *args)
+{
+    target_ulong dst   = args[0]; /* Destination address */
+    target_ulong src   = args[1]; /* Source address */
+    target_ulong esize = args[2]; /* Element size (0=1,1=2,2=4,3=8) */
+    target_ulong count = args[3]; /* Element count */
+    target_ulong op    = args[4]; /* 0 = copy, 1 = invert */
+    uint64_t tmp;
+    unsigned int mask = (1 << esize) - 1;
+    int step = 1 << esize;
+
+    if (count > 0x80000000) {
+        return H_PARAMETER;
+    }
+
+    if ((dst & mask) || (src & mask) || (op > 1)) {
+        return H_PARAMETER;
+    }
+
+    if (dst >= src && dst < (src + (count << esize))) {
+            dst = dst + ((count - 1) << esize);
+            src = src + ((count - 1) << esize);
+            step = -step;
+    }
+
+    while (count--) {
+        switch (esize) {
+        case 0:
+            tmp = ldub_phys(src);
+            break;
+        case 1:
+            tmp = lduw_phys(src);
+            break;
+        case 2:
+            tmp = ldl_phys(src);
+            break;
+        case 3:
+            tmp = ldq_phys(src);
+            break;
+        default:
+            return H_PARAMETER;
+        }
+        if (op == 1) {
+            tmp = ~tmp;
+        }
+        switch (esize) {
+        case 0:
+            stb_phys(dst, tmp);
+            break;
+        case 1:
+            stw_phys(dst, tmp);
+            break;
+        case 2:
+            stl_phys(dst, tmp);
+            break;
+        case 3:
+            stq_phys(dst, tmp);
+            break;
+        }
+        dst = dst + step;
+        src = src + step;
+    }
+
+    return H_SUCCESS;
+}
+
+static target_ulong h_logical_icbi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                   target_ulong opcode, target_ulong *args)
+{
+    /* Nothing to do on emulation, KVM will trap this in the kernel */
+    return H_SUCCESS;
+}
+
+static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                                   target_ulong opcode, target_ulong *args)
+{
+    /* Nothing to do on emulation, KVM will trap this in the kernel */
+    return H_SUCCESS;
+}
+
+static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
+static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1];
+
+void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
+{
+    spapr_hcall_fn *slot;
+
+    if (opcode <= MAX_HCALL_OPCODE) {
+        assert((opcode & 0x3) == 0);
+
+        slot = &papr_hypercall_table[opcode / 4];
+    } else {
+        assert((opcode >= KVMPPC_HCALL_BASE) && (opcode <= KVMPPC_HCALL_MAX));
+
+        slot = &kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
+    }
+
+    assert(!(*slot));
+    *slot = fn;
+}
+
+target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode,
+                             target_ulong *args)
+{
+    if ((opcode <= MAX_HCALL_OPCODE)
+        && ((opcode & 0x3) == 0)) {
+        spapr_hcall_fn fn = papr_hypercall_table[opcode / 4];
+
+        if (fn) {
+            return fn(cpu, 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(cpu, spapr, opcode, args);
+        }
+    }
+
+    hcall_dprintf("Unimplemented hcall 0x" TARGET_FMT_lx "\n", opcode);
+    return H_FUNCTION;
+}
+
+static void hypercall_register_types(void)
+{
+    /* hcall-pft */
+    spapr_register_hypercall(H_ENTER, h_enter);
+    spapr_register_hypercall(H_REMOVE, h_remove);
+    spapr_register_hypercall(H_PROTECT, h_protect);
+
+    /* hcall-bulk */
+    spapr_register_hypercall(H_BULK_REMOVE, h_bulk_remove);
+
+    /* 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);
+
+    /* "debugger" hcalls (also used by SLOF). Note: We do -not- differenciate
+     * here between the "CI" and the "CACHE" variants, they will use whatever
+     * mapping attributes qemu is using. When using KVM, the kernel will
+     * enforce the attributes more strongly
+     */
+    spapr_register_hypercall(H_LOGICAL_CI_LOAD, h_logical_load);
+    spapr_register_hypercall(H_LOGICAL_CI_STORE, h_logical_store);
+    spapr_register_hypercall(H_LOGICAL_CACHE_LOAD, h_logical_load);
+    spapr_register_hypercall(H_LOGICAL_CACHE_STORE, h_logical_store);
+    spapr_register_hypercall(H_LOGICAL_ICBI, h_logical_icbi);
+    spapr_register_hypercall(H_LOGICAL_DCBF, h_logical_dcbf);
+    spapr_register_hypercall(KVMPPC_H_LOGICAL_MEMOP, h_logical_memop);
+
+    /* qemu/KVM-PPC specific hcalls */
+    spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
+}
+
+type_init(hypercall_register_types)
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
new file mode 100644
index 0000000..8d500bf
--- /dev/null
+++ b/hw/ppc/spapr_iommu.c
@@ -0,0 +1,293 @@
+/*
+ * QEMU sPAPR IOMMU (TCE) code
+ *
+ * Copyright (c) 2010 David Gibson, IBM Corporation <dwg at au1.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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/hw.h"
+#include "sysemu/kvm.h"
+#include "hw/qdev.h"
+#include "kvm_ppc.h"
+#include "sysemu/dma.h"
+#include "exec/address-spaces.h"
+
+#include "hw/spapr.h"
+
+#include <libfdt.h>
+
+/* #define DEBUG_TCE */
+
+enum sPAPRTCEAccess {
+    SPAPR_TCE_FAULT = 0,
+    SPAPR_TCE_RO = 1,
+    SPAPR_TCE_WO = 2,
+    SPAPR_TCE_RW = 3,
+};
+
+typedef struct sPAPRTCETable sPAPRTCETable;
+
+struct sPAPRTCETable {
+    DMAContext dma;
+    uint32_t liobn;
+    uint32_t window_size;
+    sPAPRTCE *table;
+    bool bypass;
+    int fd;
+    QLIST_ENTRY(sPAPRTCETable) list;
+};
+
+
+QLIST_HEAD(spapr_tce_tables, sPAPRTCETable) spapr_tce_tables;
+
+static sPAPRTCETable *spapr_tce_find_by_liobn(uint32_t liobn)
+{
+    sPAPRTCETable *tcet;
+
+    QLIST_FOREACH(tcet, &spapr_tce_tables, list) {
+        if (tcet->liobn == liobn) {
+            return tcet;
+        }
+    }
+
+    return NULL;
+}
+
+static int spapr_tce_translate(DMAContext *dma,
+                               dma_addr_t addr,
+                               hwaddr *paddr,
+                               hwaddr *len,
+                               DMADirection dir)
+{
+    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
+    enum sPAPRTCEAccess access = (dir == DMA_DIRECTION_FROM_DEVICE)
+        ? SPAPR_TCE_WO : SPAPR_TCE_RO;
+    uint64_t tce;
+
+#ifdef DEBUG_TCE
+    fprintf(stderr, "spapr_tce_translate liobn=0x%" PRIx32 " addr=0x"
+            DMA_ADDR_FMT "\n", tcet->liobn, addr);
+#endif
+
+    if (tcet->bypass) {
+        *paddr = addr;
+        *len = (hwaddr)-1;
+        return 0;
+    }
+
+    /* Check if we are in bound */
+    if (addr >= tcet->window_size) {
+#ifdef DEBUG_TCE
+        fprintf(stderr, "spapr_tce_translate out of bounds\n");
+#endif
+        return -EFAULT;
+    }
+
+    tce = tcet->table[addr >> SPAPR_TCE_PAGE_SHIFT].tce;
+
+    /* Check TCE */
+    if (!(tce & access)) {
+        return -EPERM;
+    }
+
+    /* How much til end of page ? */
+    *len = ((~addr) & SPAPR_TCE_PAGE_MASK) + 1;
+
+    /* Translate */
+    *paddr = (tce & ~SPAPR_TCE_PAGE_MASK) |
+        (addr & SPAPR_TCE_PAGE_MASK);
+
+#ifdef DEBUG_TCE
+    fprintf(stderr, " ->  *paddr=0x" TARGET_FMT_plx ", *len=0x"
+            TARGET_FMT_plx "\n", *paddr, *len);
+#endif
+
+    return 0;
+}
+
+DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size)
+{
+    sPAPRTCETable *tcet;
+
+    if (spapr_tce_find_by_liobn(liobn)) {
+        fprintf(stderr, "Attempted to create TCE table with duplicate"
+                " LIOBN 0x%x\n", liobn);
+        return NULL;
+    }
+
+    if (!window_size) {
+        return NULL;
+    }
+
+    tcet = g_malloc0(sizeof(*tcet));
+    dma_context_init(&tcet->dma, &address_space_memory, spapr_tce_translate, NULL, NULL);
+
+    tcet->liobn = liobn;
+    tcet->window_size = window_size;
+
+    if (kvm_enabled()) {
+        tcet->table = kvmppc_create_spapr_tce(liobn,
+                                              window_size,
+                                              &tcet->fd);
+    }
+
+    if (!tcet->table) {
+        size_t table_size = (window_size >> SPAPR_TCE_PAGE_SHIFT)
+            * sizeof(sPAPRTCE);
+        tcet->table = g_malloc0(table_size);
+    }
+
+#ifdef DEBUG_TCE
+    fprintf(stderr, "spapr_iommu: New TCE table, liobn=0x%x, context @ %p, "
+            "table @ %p, fd=%d\n", liobn, &tcet->dma, tcet->table, tcet->fd);
+#endif
+
+    QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
+
+    return &tcet->dma;
+}
+
+void spapr_tce_free(DMAContext *dma)
+{
+
+    if (dma) {
+        sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
+
+        QLIST_REMOVE(tcet, list);
+
+        if (!kvm_enabled() ||
+            (kvmppc_remove_spapr_tce(tcet->table, tcet->fd,
+                                     tcet->window_size) != 0)) {
+            g_free(tcet->table);
+        }
+
+        g_free(tcet);
+    }
+}
+
+void spapr_tce_set_bypass(DMAContext *dma, bool bypass)
+{
+    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
+
+    tcet->bypass = bypass;
+}
+
+void spapr_tce_reset(DMAContext *dma)
+{
+    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
+    size_t table_size = (tcet->window_size >> SPAPR_TCE_PAGE_SHIFT)
+        * sizeof(sPAPRTCE);
+
+    tcet->bypass = false;
+    memset(tcet->table, 0, table_size);
+}
+
+static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
+                                target_ulong tce)
+{
+    sPAPRTCE *tcep;
+
+    if (ioba >= tcet->window_size) {
+        hcall_dprintf("spapr_vio_put_tce on out-of-boards IOBA 0x"
+                      TARGET_FMT_lx "\n", ioba);
+        return H_PARAMETER;
+    }
+
+    tcep = tcet->table + (ioba >> SPAPR_TCE_PAGE_SHIFT);
+    tcep->tce = tce;
+
+    return H_SUCCESS;
+}
+
+static target_ulong h_put_tce(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                              target_ulong opcode, target_ulong *args)
+{
+    target_ulong liobn = args[0];
+    target_ulong ioba = args[1];
+    target_ulong tce = args[2];
+    sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
+
+    if (liobn & 0xFFFFFFFF00000000ULL) {
+        hcall_dprintf("spapr_vio_put_tce on out-of-boundsw LIOBN "
+                      TARGET_FMT_lx "\n", liobn);
+        return H_PARAMETER;
+    }
+
+    ioba &= ~(SPAPR_TCE_PAGE_SIZE - 1);
+
+    if (tcet) {
+        return put_tce_emu(tcet, ioba, tce);
+    }
+#ifdef DEBUG_TCE
+    fprintf(stderr, "%s on liobn=" TARGET_FMT_lx /*%s*/
+            "  ioba 0x" TARGET_FMT_lx "  TCE 0x" TARGET_FMT_lx "\n",
+            __func__, liobn, /*dev->qdev.id, */ioba, tce);
+#endif
+
+    return H_PARAMETER;
+}
+
+void spapr_iommu_init(void)
+{
+    QLIST_INIT(&spapr_tce_tables);
+
+    /* hcall-tce */
+    spapr_register_hypercall(H_PUT_TCE, h_put_tce);
+}
+
+int spapr_dma_dt(void *fdt, int node_off, const char *propname,
+                 uint32_t liobn, uint64_t window, uint32_t size)
+{
+    uint32_t dma_prop[5];
+    int ret;
+
+    dma_prop[0] = cpu_to_be32(liobn);
+    dma_prop[1] = cpu_to_be32(window >> 32);
+    dma_prop[2] = cpu_to_be32(window & 0xFFFFFFFF);
+    dma_prop[3] = 0; /* window size is 32 bits */
+    dma_prop[4] = cpu_to_be32(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, propname, dma_prop, sizeof(dma_prop));
+    if (ret < 0) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
+                      DMAContext *iommu)
+{
+    if (!iommu) {
+        return 0;
+    }
+
+    if (iommu->translate == spapr_tce_translate) {
+        sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, iommu);
+        return spapr_dma_dt(fdt, node_off, propname,
+                tcet->liobn, 0, tcet->window_size);
+    }
+
+    return -1;
+}
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
new file mode 100644
index 0000000..5ec787f
--- /dev/null
+++ b/hw/ppc/spapr_rtas.c
@@ -0,0 +1,334 @@
+/*
+ * 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/sysemu.h"
+#include "char/char.h"
+#include "hw/qdev.h"
+#include "sysemu/device_tree.h"
+
+#include "hw/spapr.h"
+#include "hw/spapr_vio.h"
+
+#include <libfdt.h>
+
+#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 = vty_lookup(spapr, 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, spapr->rtc_offset);
+
+    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_set_time_of_day(sPAPREnvironment *spapr,
+                                 uint32_t token, uint32_t nargs,
+                                 target_ulong args,
+                                 uint32_t nret, target_ulong rets)
+{
+    struct tm tm;
+
+    tm.tm_year = rtas_ld(args, 0) - 1900;
+    tm.tm_mon = rtas_ld(args, 1) - 1;
+    tm.tm_mday = rtas_ld(args, 2);
+    tm.tm_hour = rtas_ld(args, 3);
+    tm.tm_min = rtas_ld(args, 4);
+    tm.tm_sec = rtas_ld(args, 5);
+
+    /* Just generate a monitor event for the change */
+    rtc_change_mon_event(&tm);
+    spapr->rtc_offset = qemu_timedate_diff(&tm);
+
+    rtas_st(rets, 0, 0); /* Success */
+}
+
+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 void rtas_system_reboot(sPAPREnvironment *spapr,
+                               uint32_t token, uint32_t nargs,
+                               target_ulong args,
+                               uint32_t nret, target_ulong rets)
+{
+    if (nargs != 0 || nret != 1) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+    qemu_system_reset_request();
+    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;
+    CPUPPCState *env;
+    CPUState *cpu;
+
+    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) {
+        cpu = CPU(ppc_env_get_cpu(env));
+        if (cpu->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 *cpu;
+    CPUPPCState *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) {
+        cpu = CPU(ppc_env_get_cpu(env));
+
+        if (cpu->cpu_index != id) {
+            continue;
+        }
+
+        if (!env->halted) {
+            rtas_st(rets, 0, -1);
+            return;
+        }
+
+        /* This will make sure qemu state is up to date with kvm, and
+         * mark it dirty so our changes get flushed back before the
+         * new cpu enters */
+        kvm_cpu_synchronize_state(env);
+
+        env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
+        env->nip = start;
+        env->gpr[3] = r3;
+        env->halted = 0;
+
+        qemu_cpu_kick(cpu);
+
+        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;
+} 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;
+        }
+    }
+
+    /* 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;
+}
+
+int spapr_rtas_register(const char *name, spapr_rtas_fn fn)
+{
+    int i;
+
+    for (i = 0; i < (rtas_next - rtas_table); i++) {
+        if (strcmp(name, rtas_table[i].name) == 0) {
+            fprintf(stderr, "RTAS call \"%s\" registered twice\n", name);
+            exit(1);
+        }
+    }
+
+    assert(rtas_next < (rtas_table + TOKEN_MAX));
+
+    rtas_next->name = name;
+    rtas_next->fn = fn;
+
+    return (rtas_next++ - rtas_table) + TOKEN_BASE;
+}
+
+int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
+                                 hwaddr 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->name) {
+            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;
+}
+
+static void core_rtas_register_types(void)
+{
+    spapr_rtas_register("display-character", rtas_display_character);
+    spapr_rtas_register("get-time-of-day", rtas_get_time_of_day);
+    spapr_rtas_register("set-time-of-day", rtas_set_time_of_day);
+    spapr_rtas_register("power-off", rtas_power_off);
+    spapr_rtas_register("system-reboot", rtas_system_reboot);
+    spapr_rtas_register("query-cpu-stopped-state",
+                        rtas_query_cpu_stopped_state);
+    spapr_rtas_register("start-cpu", rtas_start_cpu);
+}
+
+type_init(core_rtas_register_types)
diff --git a/hw/spapr_events.c b/hw/spapr_events.c
deleted file mode 100644
index ce78f09..0000000
--- a/hw/spapr_events.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
- *
- * RTAS events handling
- *
- * Copyright (c) 2012 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/sysemu.h"
-#include "char/char.h"
-#include "hw/qdev.h"
-#include "sysemu/device_tree.h"
-
-#include "hw/spapr.h"
-#include "hw/spapr_vio.h"
-
-#include <libfdt.h>
-
-struct rtas_error_log {
-    uint32_t summary;
-#define RTAS_LOG_VERSION_MASK                   0xff000000
-#define   RTAS_LOG_VERSION_6                    0x06000000
-#define RTAS_LOG_SEVERITY_MASK                  0x00e00000
-#define   RTAS_LOG_SEVERITY_ALREADY_REPORTED    0x00c00000
-#define   RTAS_LOG_SEVERITY_FATAL               0x00a00000
-#define   RTAS_LOG_SEVERITY_ERROR               0x00800000
-#define   RTAS_LOG_SEVERITY_ERROR_SYNC          0x00600000
-#define   RTAS_LOG_SEVERITY_WARNING             0x00400000
-#define   RTAS_LOG_SEVERITY_EVENT               0x00200000
-#define   RTAS_LOG_SEVERITY_NO_ERROR            0x00000000
-#define RTAS_LOG_DISPOSITION_MASK               0x00180000
-#define   RTAS_LOG_DISPOSITION_FULLY_RECOVERED  0x00000000
-#define   RTAS_LOG_DISPOSITION_LIMITED_RECOVERY 0x00080000
-#define   RTAS_LOG_DISPOSITION_NOT_RECOVERED    0x00100000
-#define RTAS_LOG_OPTIONAL_PART_PRESENT          0x00040000
-#define RTAS_LOG_INITIATOR_MASK                 0x0000f000
-#define   RTAS_LOG_INITIATOR_UNKNOWN            0x00000000
-#define   RTAS_LOG_INITIATOR_CPU                0x00001000
-#define   RTAS_LOG_INITIATOR_PCI                0x00002000
-#define   RTAS_LOG_INITIATOR_MEMORY             0x00004000
-#define   RTAS_LOG_INITIATOR_HOTPLUG            0x00006000
-#define RTAS_LOG_TARGET_MASK                    0x00000f00
-#define   RTAS_LOG_TARGET_UNKNOWN               0x00000000
-#define   RTAS_LOG_TARGET_CPU                   0x00000100
-#define   RTAS_LOG_TARGET_PCI                   0x00000200
-#define   RTAS_LOG_TARGET_MEMORY                0x00000400
-#define   RTAS_LOG_TARGET_HOTPLUG               0x00000600
-#define RTAS_LOG_TYPE_MASK                      0x000000ff
-#define   RTAS_LOG_TYPE_OTHER                   0x00000000
-#define   RTAS_LOG_TYPE_RETRY                   0x00000001
-#define   RTAS_LOG_TYPE_TCE_ERR                 0x00000002
-#define   RTAS_LOG_TYPE_INTERN_DEV_FAIL         0x00000003
-#define   RTAS_LOG_TYPE_TIMEOUT                 0x00000004
-#define   RTAS_LOG_TYPE_DATA_PARITY             0x00000005
-#define   RTAS_LOG_TYPE_ADDR_PARITY             0x00000006
-#define   RTAS_LOG_TYPE_CACHE_PARITY            0x00000007
-#define   RTAS_LOG_TYPE_ADDR_INVALID            0x00000008
-#define   RTAS_LOG_TYPE_ECC_UNCORR              0x00000009
-#define   RTAS_LOG_TYPE_ECC_CORR                0x0000000a
-#define   RTAS_LOG_TYPE_EPOW                    0x00000040
-    uint32_t extended_length;
-} QEMU_PACKED;
-
-struct rtas_event_log_v6 {
-    uint8_t b0;
-#define RTAS_LOG_V6_B0_VALID                          0x80
-#define RTAS_LOG_V6_B0_UNRECOVERABLE_ERROR            0x40
-#define RTAS_LOG_V6_B0_RECOVERABLE_ERROR              0x20
-#define RTAS_LOG_V6_B0_DEGRADED_OPERATION             0x10
-#define RTAS_LOG_V6_B0_PREDICTIVE_ERROR               0x08
-#define RTAS_LOG_V6_B0_NEW_LOG                        0x04
-#define RTAS_LOG_V6_B0_BIGENDIAN                      0x02
-    uint8_t _resv1;
-    uint8_t b2;
-#define RTAS_LOG_V6_B2_POWERPC_FORMAT                 0x80
-#define RTAS_LOG_V6_B2_LOG_FORMAT_MASK                0x0f
-#define   RTAS_LOG_V6_B2_LOG_FORMAT_PLATFORM_EVENT    0x0e
-    uint8_t _resv2[9];
-    uint32_t company;
-#define RTAS_LOG_V6_COMPANY_IBM                 0x49424d00 /* IBM<null> */
-} QEMU_PACKED;
-
-struct rtas_event_log_v6_section_header {
-    uint16_t section_id;
-    uint16_t section_length;
-    uint8_t section_version;
-    uint8_t section_subtype;
-    uint16_t creator_component_id;
-} QEMU_PACKED;
-
-struct rtas_event_log_v6_maina {
-#define RTAS_LOG_V6_SECTION_ID_MAINA                0x5048 /* PH */
-    struct rtas_event_log_v6_section_header hdr;
-    uint32_t creation_date; /* BCD: YYYYMMDD */
-    uint32_t creation_time; /* BCD: HHMMSS00 */
-    uint8_t _platform1[8];
-    char creator_id;
-    uint8_t _resv1[2];
-    uint8_t section_count;
-    uint8_t _resv2[4];
-    uint8_t _platform2[8];
-    uint32_t plid;
-    uint8_t _platform3[4];
-} QEMU_PACKED;
-
-struct rtas_event_log_v6_mainb {
-#define RTAS_LOG_V6_SECTION_ID_MAINB                0x5548 /* UH */
-    struct rtas_event_log_v6_section_header hdr;
-    uint8_t subsystem_id;
-    uint8_t _platform1;
-    uint8_t event_severity;
-    uint8_t event_subtype;
-    uint8_t _platform2[4];
-    uint8_t _resv1[2];
-    uint16_t action_flags;
-    uint8_t _resv2[4];
-} QEMU_PACKED;
-
-struct rtas_event_log_v6_epow {
-#define RTAS_LOG_V6_SECTION_ID_EPOW                 0x4550 /* EP */
-    struct rtas_event_log_v6_section_header hdr;
-    uint8_t sensor_value;
-#define RTAS_LOG_V6_EPOW_ACTION_RESET                    0
-#define RTAS_LOG_V6_EPOW_ACTION_WARN_COOLING             1
-#define RTAS_LOG_V6_EPOW_ACTION_WARN_POWER               2
-#define RTAS_LOG_V6_EPOW_ACTION_SYSTEM_SHUTDOWN          3
-#define RTAS_LOG_V6_EPOW_ACTION_SYSTEM_HALT              4
-#define RTAS_LOG_V6_EPOW_ACTION_MAIN_ENCLOSURE           5
-#define RTAS_LOG_V6_EPOW_ACTION_POWER_OFF                7
-    uint8_t event_modifier;
-#define RTAS_LOG_V6_EPOW_MODIFIER_NORMAL                 1
-#define RTAS_LOG_V6_EPOW_MODIFIER_ON_UPS                 2
-#define RTAS_LOG_V6_EPOW_MODIFIER_CRITICAL               3
-#define RTAS_LOG_V6_EPOW_MODIFIER_TEMPERATURE            4
-    uint8_t extended_modifier;
-#define RTAS_LOG_V6_EPOW_XMODIFIER_SYSTEM_WIDE           0
-#define RTAS_LOG_V6_EPOW_XMODIFIER_PARTITION_SPECIFIC    1
-    uint8_t _resv;
-    uint64_t reason_code;
-} QEMU_PACKED;
-
-struct epow_log_full {
-    struct rtas_error_log hdr;
-    struct rtas_event_log_v6 v6hdr;
-    struct rtas_event_log_v6_maina maina;
-    struct rtas_event_log_v6_mainb mainb;
-    struct rtas_event_log_v6_epow epow;
-} QEMU_PACKED;
-
-#define EVENT_MASK_INTERNAL_ERRORS           0x80000000
-#define EVENT_MASK_EPOW                      0x40000000
-#define EVENT_MASK_HOTPLUG                   0x10000000
-#define EVENT_MASK_IO                        0x08000000
-
-#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)
-
-void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq)
-{
-    uint32_t epow_irq_ranges[] = {cpu_to_be32(epow_irq), cpu_to_be32(1)};
-    uint32_t epow_interrupts[] = {cpu_to_be32(epow_irq), 0};
-
-    _FDT((fdt_begin_node(fdt, "event-sources")));
-
-    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
-    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
-    _FDT((fdt_property(fdt, "interrupt-ranges",
-                       epow_irq_ranges, sizeof(epow_irq_ranges))));
-
-    _FDT((fdt_begin_node(fdt, "epow-events")));
-    _FDT((fdt_property(fdt, "interrupts",
-                       epow_interrupts, sizeof(epow_interrupts))));
-    _FDT((fdt_end_node(fdt)));
-
-    _FDT((fdt_end_node(fdt)));
-}
-
-static struct epow_log_full *pending_epow;
-static uint32_t next_plid;
-
-static void spapr_powerdown_req(Notifier *n, void *opaque)
-{
-    sPAPREnvironment *spapr = container_of(n, sPAPREnvironment, epow_notifier);
-    struct rtas_error_log *hdr;
-    struct rtas_event_log_v6 *v6hdr;
-    struct rtas_event_log_v6_maina *maina;
-    struct rtas_event_log_v6_mainb *mainb;
-    struct rtas_event_log_v6_epow *epow;
-    struct tm tm;
-    int year;
-
-    if (pending_epow) {
-        /* For now, we just throw away earlier events if two come
-         * along before any are consumed.  This is sufficient for our
-         * powerdown messages, but we'll need more if we do more
-         * general error/event logging */
-        g_free(pending_epow);
-    }
-    pending_epow = g_malloc0(sizeof(*pending_epow));
-    hdr = &pending_epow->hdr;
-    v6hdr = &pending_epow->v6hdr;
-    maina = &pending_epow->maina;
-    mainb = &pending_epow->mainb;
-    epow = &pending_epow->epow;
-
-    hdr->summary = cpu_to_be32(RTAS_LOG_VERSION_6
-                               | RTAS_LOG_SEVERITY_EVENT
-                               | RTAS_LOG_DISPOSITION_NOT_RECOVERED
-                               | RTAS_LOG_OPTIONAL_PART_PRESENT
-                               | RTAS_LOG_TYPE_EPOW);
-    hdr->extended_length = cpu_to_be32(sizeof(*pending_epow)
-                                       - sizeof(pending_epow->hdr));
-
-    v6hdr->b0 = RTAS_LOG_V6_B0_VALID | RTAS_LOG_V6_B0_NEW_LOG
-        | RTAS_LOG_V6_B0_BIGENDIAN;
-    v6hdr->b2 = RTAS_LOG_V6_B2_POWERPC_FORMAT
-        | RTAS_LOG_V6_B2_LOG_FORMAT_PLATFORM_EVENT;
-    v6hdr->company = cpu_to_be32(RTAS_LOG_V6_COMPANY_IBM);
-
-    maina->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINA);
-    maina->hdr.section_length = cpu_to_be16(sizeof(*maina));
-    /* FIXME: section version, subtype and creator id? */
-    qemu_get_timedate(&tm, spapr->rtc_offset);
-    year = tm.tm_year + 1900;
-    maina->creation_date = cpu_to_be32((to_bcd(year / 100) << 24)
-                                       | (to_bcd(year % 100) << 16)
-                                       | (to_bcd(tm.tm_mon + 1) << 8)
-                                       | to_bcd(tm.tm_mday));
-    maina->creation_time = cpu_to_be32((to_bcd(tm.tm_hour) << 24)
-                                       | (to_bcd(tm.tm_min) << 16)
-                                       | (to_bcd(tm.tm_sec) << 8));
-    maina->creator_id = 'H'; /* Hypervisor */
-    maina->section_count = 3; /* Main-A, Main-B and EPOW */
-    maina->plid = next_plid++;
-
-    mainb->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINB);
-    mainb->hdr.section_length = cpu_to_be16(sizeof(*mainb));
-    /* FIXME: section version, subtype and creator id? */
-    mainb->subsystem_id = 0xa0; /* External environment */
-    mainb->event_severity = 0x00; /* Informational / non-error */
-    mainb->event_subtype = 0xd0; /* Normal shutdown */
-
-    epow->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_EPOW);
-    epow->hdr.section_length = cpu_to_be16(sizeof(*epow));
-    epow->hdr.section_version = 2; /* includes extended modifier */
-    /* FIXME: section subtype and creator id? */
-    epow->sensor_value = RTAS_LOG_V6_EPOW_ACTION_SYSTEM_SHUTDOWN;
-    epow->event_modifier = RTAS_LOG_V6_EPOW_MODIFIER_NORMAL;
-    epow->extended_modifier = RTAS_LOG_V6_EPOW_XMODIFIER_PARTITION_SPECIFIC;
-
-    qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->epow_irq));
-}
-
-static void check_exception(sPAPREnvironment *spapr,
-                            uint32_t token, uint32_t nargs,
-                            target_ulong args,
-                            uint32_t nret, target_ulong rets)
-{
-    uint32_t mask, buf, len;
-    uint64_t xinfo;
-
-    if ((nargs < 6) || (nargs > 7) || nret != 1) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    xinfo = rtas_ld(args, 1);
-    mask = rtas_ld(args, 2);
-    buf = rtas_ld(args, 4);
-    len = rtas_ld(args, 5);
-    if (nargs == 7) {
-        xinfo |= (uint64_t)rtas_ld(args, 6) << 32;
-    }
-
-    if ((mask & EVENT_MASK_EPOW) && pending_epow) {
-        if (sizeof(*pending_epow) < len) {
-            len = sizeof(*pending_epow);
-        }
-
-        cpu_physical_memory_write(buf, pending_epow, len);
-        g_free(pending_epow);
-        pending_epow = NULL;
-        rtas_st(rets, 0, 0);
-    } else {
-        rtas_st(rets, 0, 1);
-    }
-}
-
-void spapr_events_init(sPAPREnvironment *spapr)
-{
-    spapr->epow_irq = spapr_allocate_msi(0);
-    spapr->epow_notifier.notify = spapr_powerdown_req;
-    qemu_register_powerdown_notifier(&spapr->epow_notifier);
-    spapr_rtas_register("check-exception", check_exception);
-}
diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
deleted file mode 100644
index 7b89594..0000000
--- a/hw/spapr_hcall.c
+++ /dev/null
@@ -1,741 +0,0 @@
-#include "sysemu/sysemu.h"
-#include "cpu.h"
-#include "sysemu/sysemu.h"
-#include "helper_regs.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
-
-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(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                            target_ulong opcode, target_ulong *args)
-{
-    CPUPPCState *env = &cpu->env;
-    target_ulong flags = args[0];
-    target_ulong pte_index = args[1];
-    target_ulong pteh = args[2];
-    target_ulong ptel = args[3];
-    target_ulong page_shift = 12;
-    target_ulong raddr;
-    target_ulong i;
-    uint8_t *hpte;
-
-    /* only handle 4k and 16M pages for now */
-    if (pteh & HPTE_V_LARGE) {
-#if 0 /* We don't support 64k pages yet */
-        if ((ptel & 0xf000) == 0x1000) {
-            /* 64k page */
-        } else
-#endif
-        if ((ptel & 0xff000) == 0) {
-            /* 16M page */
-            page_shift = 24;
-            /* lowest AVA bit must be 0 for 16M pages */
-            if (pteh & 0x80) {
-                return H_PARAMETER;
-            }
-        } else {
-            return H_PARAMETER;
-        }
-    }
-
-    raddr = (ptel & HPTE_R_RPN) & ~((1ULL << page_shift) - 1);
-
-    if (raddr < spapr->ram_limit) {
-        /* Regular RAM - should have WIMG=0010 */
-        if ((ptel & HPTE_R_WIMG) != HPTE_R_M) {
-            return H_PARAMETER;
-        }
-    } else {
-        /* Looks like an IO address */
-        /* FIXME: What WIMG combinations could be sensible for IO?
-         * For now we allow WIMG=010x, but are there others? */
-        /* FIXME: Should we check against registered IO addresses? */
-        if ((ptel & (HPTE_R_W | HPTE_R_I | HPTE_R_M)) != HPTE_R_I) {
-            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) {
-                break;
-            }
-            hpte += HASH_PTE_SIZE_64;
-        }
-    } else {
-        i = 0;
-        hpte = env->external_htab + (pte_index * HASH_PTE_SIZE_64);
-        if (ldq_p(hpte) & 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);
-
-    args[0] = pte_index + i;
-    return H_SUCCESS;
-}
-
-enum {
-    REMOVE_SUCCESS = 0,
-    REMOVE_NOT_FOUND = 1,
-    REMOVE_PARM = 2,
-    REMOVE_HW = 3,
-};
-
-static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex,
-                                target_ulong avpn,
-                                target_ulong flags,
-                                target_ulong *vp, target_ulong *rp)
-{
-    uint8_t *hpte;
-    target_ulong v, r, rb;
-
-    if ((ptex * HASH_PTE_SIZE_64) & ~env->htab_mask) {
-        return REMOVE_PARM;
-    }
-
-    hpte = env->external_htab + (ptex * HASH_PTE_SIZE_64);
-
-    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)) {
-        return REMOVE_NOT_FOUND;
-    }
-    *vp = v;
-    *rp = r;
-    stq_p(hpte, 0);
-    rb = compute_tlbie_rb(v, r, ptex);
-    ppc_tlb_invalidate_one(env, rb);
-    return REMOVE_SUCCESS;
-}
-
-static target_ulong h_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                             target_ulong opcode, target_ulong *args)
-{
-    CPUPPCState *env = &cpu->env;
-    target_ulong flags = args[0];
-    target_ulong pte_index = args[1];
-    target_ulong avpn = args[2];
-    int ret;
-
-    ret = remove_hpte(env, pte_index, avpn, flags,
-                      &args[0], &args[1]);
-
-    switch (ret) {
-    case REMOVE_SUCCESS:
-        return H_SUCCESS;
-
-    case REMOVE_NOT_FOUND:
-        return H_NOT_FOUND;
-
-    case REMOVE_PARM:
-        return H_PARAMETER;
-
-    case REMOVE_HW:
-        return H_HARDWARE;
-    }
-
-    assert(0);
-}
-
-#define H_BULK_REMOVE_TYPE             0xc000000000000000ULL
-#define   H_BULK_REMOVE_REQUEST        0x4000000000000000ULL
-#define   H_BULK_REMOVE_RESPONSE       0x8000000000000000ULL
-#define   H_BULK_REMOVE_END            0xc000000000000000ULL
-#define H_BULK_REMOVE_CODE             0x3000000000000000ULL
-#define   H_BULK_REMOVE_SUCCESS        0x0000000000000000ULL
-#define   H_BULK_REMOVE_NOT_FOUND      0x1000000000000000ULL
-#define   H_BULK_REMOVE_PARM           0x2000000000000000ULL
-#define   H_BULK_REMOVE_HW             0x3000000000000000ULL
-#define H_BULK_REMOVE_RC               0x0c00000000000000ULL
-#define H_BULK_REMOVE_FLAGS            0x0300000000000000ULL
-#define   H_BULK_REMOVE_ABSOLUTE       0x0000000000000000ULL
-#define   H_BULK_REMOVE_ANDCOND        0x0100000000000000ULL
-#define   H_BULK_REMOVE_AVPN           0x0200000000000000ULL
-#define H_BULK_REMOVE_PTEX             0x00ffffffffffffffULL
-
-#define H_BULK_REMOVE_MAX_BATCH        4
-
-static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                                  target_ulong opcode, target_ulong *args)
-{
-    CPUPPCState *env = &cpu->env;
-    int i;
-
-    for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) {
-        target_ulong *tsh = &args[i*2];
-        target_ulong tsl = args[i*2 + 1];
-        target_ulong v, r, ret;
-
-        if ((*tsh & H_BULK_REMOVE_TYPE) == H_BULK_REMOVE_END) {
-            break;
-        } else if ((*tsh & H_BULK_REMOVE_TYPE) != H_BULK_REMOVE_REQUEST) {
-            return H_PARAMETER;
-        }
-
-        *tsh &= H_BULK_REMOVE_PTEX | H_BULK_REMOVE_FLAGS;
-        *tsh |= H_BULK_REMOVE_RESPONSE;
-
-        if ((*tsh & H_BULK_REMOVE_ANDCOND) && (*tsh & H_BULK_REMOVE_AVPN)) {
-            *tsh |= H_BULK_REMOVE_PARM;
-            return H_PARAMETER;
-        }
-
-        ret = remove_hpte(env, *tsh & H_BULK_REMOVE_PTEX, tsl,
-                          (*tsh & H_BULK_REMOVE_FLAGS) >> 26,
-                          &v, &r);
-
-        *tsh |= ret << 60;
-
-        switch (ret) {
-        case REMOVE_SUCCESS:
-            *tsh |= (r & (HPTE_R_C | HPTE_R_R)) << 43;
-            break;
-
-        case REMOVE_PARM:
-            return H_PARAMETER;
-
-        case REMOVE_HW:
-            return H_HARDWARE;
-        }
-    }
-
-    return H_SUCCESS;
-}
-
-static target_ulong h_protect(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                              target_ulong opcode, target_ulong *args)
-{
-    CPUPPCState *env = &cpu->env;
-    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);
-
-    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)) {
-        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);
-    return H_SUCCESS;
-}
-
-static target_ulong h_set_dabr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                               target_ulong opcode, target_ulong *args)
-{
-    /* FIXME: actually implement this */
-    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(CPUPPCState *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_be_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_addr = vpa;
-
-    tmp = ldub_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET);
-    tmp |= VPA_SHARED_PROC_VAL;
-    stb_phys(env->vpa_addr + VPA_SHARED_PROC_OFFSET, tmp);
-
-    return H_SUCCESS;
-}
-
-static target_ulong deregister_vpa(CPUPPCState *env, target_ulong vpa)
-{
-    if (env->slb_shadow_addr) {
-        return H_RESOURCE;
-    }
-
-    if (env->dtl_addr) {
-        return H_RESOURCE;
-    }
-
-    env->vpa_addr = 0;
-    return H_SUCCESS;
-}
-
-static target_ulong register_slb_shadow(CPUPPCState *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_be_phys(addr + 0x4);
-    if (size < 0x8) {
-        return H_PARAMETER;
-    }
-
-    if ((addr / 4096) != ((addr + size - 1) / 4096)) {
-        return H_PARAMETER;
-    }
-
-    if (!env->vpa_addr) {
-        return H_RESOURCE;
-    }
-
-    env->slb_shadow_addr = addr;
-    env->slb_shadow_size = size;
-
-    return H_SUCCESS;
-}
-
-static target_ulong deregister_slb_shadow(CPUPPCState *env, target_ulong addr)
-{
-    env->slb_shadow_addr = 0;
-    env->slb_shadow_size = 0;
-    return H_SUCCESS;
-}
-
-static target_ulong register_dtl(CPUPPCState *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_be_phys(addr + 0x4);
-
-    if (size < 48) {
-        return H_PARAMETER;
-    }
-
-    if (!env->vpa_addr) {
-        return H_RESOURCE;
-    }
-
-    env->dtl_addr = addr;
-    env->dtl_size = size;
-
-    return H_SUCCESS;
-}
-
-static target_ulong deregister_dtl(CPUPPCState *env, target_ulong addr)
-{
-    env->dtl_addr = 0;
-    env->dtl_size = 0;
-
-    return H_SUCCESS;
-}
-
-static target_ulong h_register_vpa(PowerPCCPU *cpu, 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;
-    CPUPPCState *tenv;
-    CPUState *tcpu;
-
-    tcpu = qemu_get_cpu(procno);
-    if (!tcpu) {
-        return H_PARAMETER;
-    }
-    tenv = tcpu->env_ptr;
-
-    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(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                           target_ulong opcode, target_ulong *args)
-{
-    CPUPPCState *env = &cpu->env;
-    CPUState *cs = CPU(cpu);
-
-    env->msr |= (1ULL << MSR_EE);
-    hreg_compute_hflags(env);
-    if (!cpu_has_work(cs)) {
-        env->halted = 1;
-        env->exception_index = EXCP_HLT;
-        cs->exit_request = 1;
-    }
-    return H_SUCCESS;
-}
-
-static target_ulong h_rtas(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                           target_ulong opcode, target_ulong *args)
-{
-    target_ulong rtas_r3 = args[0];
-    uint32_t token = ldl_be_phys(rtas_r3);
-    uint32_t nargs = ldl_be_phys(rtas_r3 + 4);
-    uint32_t nret = ldl_be_phys(rtas_r3 + 8);
-
-    return spapr_rtas_call(spapr, token, nargs, rtas_r3 + 12,
-                           nret, rtas_r3 + 12 + 4*nargs);
-}
-
-static target_ulong h_logical_load(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                                   target_ulong opcode, target_ulong *args)
-{
-    target_ulong size = args[0];
-    target_ulong addr = args[1];
-
-    switch (size) {
-    case 1:
-        args[0] = ldub_phys(addr);
-        return H_SUCCESS;
-    case 2:
-        args[0] = lduw_phys(addr);
-        return H_SUCCESS;
-    case 4:
-        args[0] = ldl_phys(addr);
-        return H_SUCCESS;
-    case 8:
-        args[0] = ldq_phys(addr);
-        return H_SUCCESS;
-    }
-    return H_PARAMETER;
-}
-
-static target_ulong h_logical_store(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                                    target_ulong opcode, target_ulong *args)
-{
-    target_ulong size = args[0];
-    target_ulong addr = args[1];
-    target_ulong val  = args[2];
-
-    switch (size) {
-    case 1:
-        stb_phys(addr, val);
-        return H_SUCCESS;
-    case 2:
-        stw_phys(addr, val);
-        return H_SUCCESS;
-    case 4:
-        stl_phys(addr, val);
-        return H_SUCCESS;
-    case 8:
-        stq_phys(addr, val);
-        return H_SUCCESS;
-    }
-    return H_PARAMETER;
-}
-
-static target_ulong h_logical_memop(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                                    target_ulong opcode, target_ulong *args)
-{
-    target_ulong dst   = args[0]; /* Destination address */
-    target_ulong src   = args[1]; /* Source address */
-    target_ulong esize = args[2]; /* Element size (0=1,1=2,2=4,3=8) */
-    target_ulong count = args[3]; /* Element count */
-    target_ulong op    = args[4]; /* 0 = copy, 1 = invert */
-    uint64_t tmp;
-    unsigned int mask = (1 << esize) - 1;
-    int step = 1 << esize;
-
-    if (count > 0x80000000) {
-        return H_PARAMETER;
-    }
-
-    if ((dst & mask) || (src & mask) || (op > 1)) {
-        return H_PARAMETER;
-    }
-
-    if (dst >= src && dst < (src + (count << esize))) {
-            dst = dst + ((count - 1) << esize);
-            src = src + ((count - 1) << esize);
-            step = -step;
-    }
-
-    while (count--) {
-        switch (esize) {
-        case 0:
-            tmp = ldub_phys(src);
-            break;
-        case 1:
-            tmp = lduw_phys(src);
-            break;
-        case 2:
-            tmp = ldl_phys(src);
-            break;
-        case 3:
-            tmp = ldq_phys(src);
-            break;
-        default:
-            return H_PARAMETER;
-        }
-        if (op == 1) {
-            tmp = ~tmp;
-        }
-        switch (esize) {
-        case 0:
-            stb_phys(dst, tmp);
-            break;
-        case 1:
-            stw_phys(dst, tmp);
-            break;
-        case 2:
-            stl_phys(dst, tmp);
-            break;
-        case 3:
-            stq_phys(dst, tmp);
-            break;
-        }
-        dst = dst + step;
-        src = src + step;
-    }
-
-    return H_SUCCESS;
-}
-
-static target_ulong h_logical_icbi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                                   target_ulong opcode, target_ulong *args)
-{
-    /* Nothing to do on emulation, KVM will trap this in the kernel */
-    return H_SUCCESS;
-}
-
-static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                                   target_ulong opcode, target_ulong *args)
-{
-    /* Nothing to do on emulation, KVM will trap this in the kernel */
-    return H_SUCCESS;
-}
-
-static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
-static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1];
-
-void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
-{
-    spapr_hcall_fn *slot;
-
-    if (opcode <= MAX_HCALL_OPCODE) {
-        assert((opcode & 0x3) == 0);
-
-        slot = &papr_hypercall_table[opcode / 4];
-    } else {
-        assert((opcode >= KVMPPC_HCALL_BASE) && (opcode <= KVMPPC_HCALL_MAX));
-
-        slot = &kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
-    }
-
-    assert(!(*slot));
-    *slot = fn;
-}
-
-target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode,
-                             target_ulong *args)
-{
-    if ((opcode <= MAX_HCALL_OPCODE)
-        && ((opcode & 0x3) == 0)) {
-        spapr_hcall_fn fn = papr_hypercall_table[opcode / 4];
-
-        if (fn) {
-            return fn(cpu, 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(cpu, spapr, opcode, args);
-        }
-    }
-
-    hcall_dprintf("Unimplemented hcall 0x" TARGET_FMT_lx "\n", opcode);
-    return H_FUNCTION;
-}
-
-static void hypercall_register_types(void)
-{
-    /* hcall-pft */
-    spapr_register_hypercall(H_ENTER, h_enter);
-    spapr_register_hypercall(H_REMOVE, h_remove);
-    spapr_register_hypercall(H_PROTECT, h_protect);
-
-    /* hcall-bulk */
-    spapr_register_hypercall(H_BULK_REMOVE, h_bulk_remove);
-
-    /* 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);
-
-    /* "debugger" hcalls (also used by SLOF). Note: We do -not- differenciate
-     * here between the "CI" and the "CACHE" variants, they will use whatever
-     * mapping attributes qemu is using. When using KVM, the kernel will
-     * enforce the attributes more strongly
-     */
-    spapr_register_hypercall(H_LOGICAL_CI_LOAD, h_logical_load);
-    spapr_register_hypercall(H_LOGICAL_CI_STORE, h_logical_store);
-    spapr_register_hypercall(H_LOGICAL_CACHE_LOAD, h_logical_load);
-    spapr_register_hypercall(H_LOGICAL_CACHE_STORE, h_logical_store);
-    spapr_register_hypercall(H_LOGICAL_ICBI, h_logical_icbi);
-    spapr_register_hypercall(H_LOGICAL_DCBF, h_logical_dcbf);
-    spapr_register_hypercall(KVMPPC_H_LOGICAL_MEMOP, h_logical_memop);
-
-    /* qemu/KVM-PPC specific hcalls */
-    spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
-}
-
-type_init(hypercall_register_types)
diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c
deleted file mode 100644
index 8d500bf..0000000
--- a/hw/spapr_iommu.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * QEMU sPAPR IOMMU (TCE) code
- *
- * Copyright (c) 2010 David Gibson, IBM Corporation <dwg at au1.ibm.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 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/hw.h"
-#include "sysemu/kvm.h"
-#include "hw/qdev.h"
-#include "kvm_ppc.h"
-#include "sysemu/dma.h"
-#include "exec/address-spaces.h"
-
-#include "hw/spapr.h"
-
-#include <libfdt.h>
-
-/* #define DEBUG_TCE */
-
-enum sPAPRTCEAccess {
-    SPAPR_TCE_FAULT = 0,
-    SPAPR_TCE_RO = 1,
-    SPAPR_TCE_WO = 2,
-    SPAPR_TCE_RW = 3,
-};
-
-typedef struct sPAPRTCETable sPAPRTCETable;
-
-struct sPAPRTCETable {
-    DMAContext dma;
-    uint32_t liobn;
-    uint32_t window_size;
-    sPAPRTCE *table;
-    bool bypass;
-    int fd;
-    QLIST_ENTRY(sPAPRTCETable) list;
-};
-
-
-QLIST_HEAD(spapr_tce_tables, sPAPRTCETable) spapr_tce_tables;
-
-static sPAPRTCETable *spapr_tce_find_by_liobn(uint32_t liobn)
-{
-    sPAPRTCETable *tcet;
-
-    QLIST_FOREACH(tcet, &spapr_tce_tables, list) {
-        if (tcet->liobn == liobn) {
-            return tcet;
-        }
-    }
-
-    return NULL;
-}
-
-static int spapr_tce_translate(DMAContext *dma,
-                               dma_addr_t addr,
-                               hwaddr *paddr,
-                               hwaddr *len,
-                               DMADirection dir)
-{
-    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
-    enum sPAPRTCEAccess access = (dir == DMA_DIRECTION_FROM_DEVICE)
-        ? SPAPR_TCE_WO : SPAPR_TCE_RO;
-    uint64_t tce;
-
-#ifdef DEBUG_TCE
-    fprintf(stderr, "spapr_tce_translate liobn=0x%" PRIx32 " addr=0x"
-            DMA_ADDR_FMT "\n", tcet->liobn, addr);
-#endif
-
-    if (tcet->bypass) {
-        *paddr = addr;
-        *len = (hwaddr)-1;
-        return 0;
-    }
-
-    /* Check if we are in bound */
-    if (addr >= tcet->window_size) {
-#ifdef DEBUG_TCE
-        fprintf(stderr, "spapr_tce_translate out of bounds\n");
-#endif
-        return -EFAULT;
-    }
-
-    tce = tcet->table[addr >> SPAPR_TCE_PAGE_SHIFT].tce;
-
-    /* Check TCE */
-    if (!(tce & access)) {
-        return -EPERM;
-    }
-
-    /* How much til end of page ? */
-    *len = ((~addr) & SPAPR_TCE_PAGE_MASK) + 1;
-
-    /* Translate */
-    *paddr = (tce & ~SPAPR_TCE_PAGE_MASK) |
-        (addr & SPAPR_TCE_PAGE_MASK);
-
-#ifdef DEBUG_TCE
-    fprintf(stderr, " ->  *paddr=0x" TARGET_FMT_plx ", *len=0x"
-            TARGET_FMT_plx "\n", *paddr, *len);
-#endif
-
-    return 0;
-}
-
-DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size)
-{
-    sPAPRTCETable *tcet;
-
-    if (spapr_tce_find_by_liobn(liobn)) {
-        fprintf(stderr, "Attempted to create TCE table with duplicate"
-                " LIOBN 0x%x\n", liobn);
-        return NULL;
-    }
-
-    if (!window_size) {
-        return NULL;
-    }
-
-    tcet = g_malloc0(sizeof(*tcet));
-    dma_context_init(&tcet->dma, &address_space_memory, spapr_tce_translate, NULL, NULL);
-
-    tcet->liobn = liobn;
-    tcet->window_size = window_size;
-
-    if (kvm_enabled()) {
-        tcet->table = kvmppc_create_spapr_tce(liobn,
-                                              window_size,
-                                              &tcet->fd);
-    }
-
-    if (!tcet->table) {
-        size_t table_size = (window_size >> SPAPR_TCE_PAGE_SHIFT)
-            * sizeof(sPAPRTCE);
-        tcet->table = g_malloc0(table_size);
-    }
-
-#ifdef DEBUG_TCE
-    fprintf(stderr, "spapr_iommu: New TCE table, liobn=0x%x, context @ %p, "
-            "table @ %p, fd=%d\n", liobn, &tcet->dma, tcet->table, tcet->fd);
-#endif
-
-    QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
-
-    return &tcet->dma;
-}
-
-void spapr_tce_free(DMAContext *dma)
-{
-
-    if (dma) {
-        sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
-
-        QLIST_REMOVE(tcet, list);
-
-        if (!kvm_enabled() ||
-            (kvmppc_remove_spapr_tce(tcet->table, tcet->fd,
-                                     tcet->window_size) != 0)) {
-            g_free(tcet->table);
-        }
-
-        g_free(tcet);
-    }
-}
-
-void spapr_tce_set_bypass(DMAContext *dma, bool bypass)
-{
-    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
-
-    tcet->bypass = bypass;
-}
-
-void spapr_tce_reset(DMAContext *dma)
-{
-    sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
-    size_t table_size = (tcet->window_size >> SPAPR_TCE_PAGE_SHIFT)
-        * sizeof(sPAPRTCE);
-
-    tcet->bypass = false;
-    memset(tcet->table, 0, table_size);
-}
-
-static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
-                                target_ulong tce)
-{
-    sPAPRTCE *tcep;
-
-    if (ioba >= tcet->window_size) {
-        hcall_dprintf("spapr_vio_put_tce on out-of-boards IOBA 0x"
-                      TARGET_FMT_lx "\n", ioba);
-        return H_PARAMETER;
-    }
-
-    tcep = tcet->table + (ioba >> SPAPR_TCE_PAGE_SHIFT);
-    tcep->tce = tce;
-
-    return H_SUCCESS;
-}
-
-static target_ulong h_put_tce(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                              target_ulong opcode, target_ulong *args)
-{
-    target_ulong liobn = args[0];
-    target_ulong ioba = args[1];
-    target_ulong tce = args[2];
-    sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
-
-    if (liobn & 0xFFFFFFFF00000000ULL) {
-        hcall_dprintf("spapr_vio_put_tce on out-of-boundsw LIOBN "
-                      TARGET_FMT_lx "\n", liobn);
-        return H_PARAMETER;
-    }
-
-    ioba &= ~(SPAPR_TCE_PAGE_SIZE - 1);
-
-    if (tcet) {
-        return put_tce_emu(tcet, ioba, tce);
-    }
-#ifdef DEBUG_TCE
-    fprintf(stderr, "%s on liobn=" TARGET_FMT_lx /*%s*/
-            "  ioba 0x" TARGET_FMT_lx "  TCE 0x" TARGET_FMT_lx "\n",
-            __func__, liobn, /*dev->qdev.id, */ioba, tce);
-#endif
-
-    return H_PARAMETER;
-}
-
-void spapr_iommu_init(void)
-{
-    QLIST_INIT(&spapr_tce_tables);
-
-    /* hcall-tce */
-    spapr_register_hypercall(H_PUT_TCE, h_put_tce);
-}
-
-int spapr_dma_dt(void *fdt, int node_off, const char *propname,
-                 uint32_t liobn, uint64_t window, uint32_t size)
-{
-    uint32_t dma_prop[5];
-    int ret;
-
-    dma_prop[0] = cpu_to_be32(liobn);
-    dma_prop[1] = cpu_to_be32(window >> 32);
-    dma_prop[2] = cpu_to_be32(window & 0xFFFFFFFF);
-    dma_prop[3] = 0; /* window size is 32 bits */
-    dma_prop[4] = cpu_to_be32(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, propname, dma_prop, sizeof(dma_prop));
-    if (ret < 0) {
-        return ret;
-    }
-
-    return 0;
-}
-
-int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
-                      DMAContext *iommu)
-{
-    if (!iommu) {
-        return 0;
-    }
-
-    if (iommu->translate == spapr_tce_translate) {
-        sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, iommu);
-        return spapr_dma_dt(fdt, node_off, propname,
-                tcet->liobn, 0, tcet->window_size);
-    }
-
-    return -1;
-}
diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
deleted file mode 100644
index 5ec787f..0000000
--- a/hw/spapr_rtas.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * 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/sysemu.h"
-#include "char/char.h"
-#include "hw/qdev.h"
-#include "sysemu/device_tree.h"
-
-#include "hw/spapr.h"
-#include "hw/spapr_vio.h"
-
-#include <libfdt.h>
-
-#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 = vty_lookup(spapr, 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, spapr->rtc_offset);
-
-    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_set_time_of_day(sPAPREnvironment *spapr,
-                                 uint32_t token, uint32_t nargs,
-                                 target_ulong args,
-                                 uint32_t nret, target_ulong rets)
-{
-    struct tm tm;
-
-    tm.tm_year = rtas_ld(args, 0) - 1900;
-    tm.tm_mon = rtas_ld(args, 1) - 1;
-    tm.tm_mday = rtas_ld(args, 2);
-    tm.tm_hour = rtas_ld(args, 3);
-    tm.tm_min = rtas_ld(args, 4);
-    tm.tm_sec = rtas_ld(args, 5);
-
-    /* Just generate a monitor event for the change */
-    rtc_change_mon_event(&tm);
-    spapr->rtc_offset = qemu_timedate_diff(&tm);
-
-    rtas_st(rets, 0, 0); /* Success */
-}
-
-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 void rtas_system_reboot(sPAPREnvironment *spapr,
-                               uint32_t token, uint32_t nargs,
-                               target_ulong args,
-                               uint32_t nret, target_ulong rets)
-{
-    if (nargs != 0 || nret != 1) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-    qemu_system_reset_request();
-    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;
-    CPUPPCState *env;
-    CPUState *cpu;
-
-    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) {
-        cpu = CPU(ppc_env_get_cpu(env));
-        if (cpu->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 *cpu;
-    CPUPPCState *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) {
-        cpu = CPU(ppc_env_get_cpu(env));
-
-        if (cpu->cpu_index != id) {
-            continue;
-        }
-
-        if (!env->halted) {
-            rtas_st(rets, 0, -1);
-            return;
-        }
-
-        /* This will make sure qemu state is up to date with kvm, and
-         * mark it dirty so our changes get flushed back before the
-         * new cpu enters */
-        kvm_cpu_synchronize_state(env);
-
-        env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
-        env->nip = start;
-        env->gpr[3] = r3;
-        env->halted = 0;
-
-        qemu_cpu_kick(cpu);
-
-        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;
-} 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;
-        }
-    }
-
-    /* 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;
-}
-
-int spapr_rtas_register(const char *name, spapr_rtas_fn fn)
-{
-    int i;
-
-    for (i = 0; i < (rtas_next - rtas_table); i++) {
-        if (strcmp(name, rtas_table[i].name) == 0) {
-            fprintf(stderr, "RTAS call \"%s\" registered twice\n", name);
-            exit(1);
-        }
-    }
-
-    assert(rtas_next < (rtas_table + TOKEN_MAX));
-
-    rtas_next->name = name;
-    rtas_next->fn = fn;
-
-    return (rtas_next++ - rtas_table) + TOKEN_BASE;
-}
-
-int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
-                                 hwaddr 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->name) {
-            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;
-}
-
-static void core_rtas_register_types(void)
-{
-    spapr_rtas_register("display-character", rtas_display_character);
-    spapr_rtas_register("get-time-of-day", rtas_get_time_of_day);
-    spapr_rtas_register("set-time-of-day", rtas_set_time_of_day);
-    spapr_rtas_register("power-off", rtas_power_off);
-    spapr_rtas_register("system-reboot", rtas_system_reboot);
-    spapr_rtas_register("query-cpu-stopped-state",
-                        rtas_query_cpu_stopped_state);
-    spapr_rtas_register("start-cpu", rtas_start_cpu);
-}
-
-type_init(core_rtas_register_types)
commit c68c4a56e93f54b374c5207f0185f8e9fa2aec3b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Feb 5 15:22:56 2013 +0100

    ppc: move files referencing CPU to hw/ppc/
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/mpc8544_guts.c b/hw/mpc8544_guts.c
deleted file mode 100644
index 193beab..0000000
--- a/hw/mpc8544_guts.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * QEMU PowerPC MPC8544 global util pseudo-device
- *
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: Alexander Graf, <alex at csgraf.de>
- *
- * This 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.
- *
- * *****************************************************************
- *
- * The documentation for this device is noted in the MPC8544 documentation,
- * file name "MPC8544ERM.pdf". You can easily find it on the web.
- *
- */
-
-#include "hw/hw.h"
-#include "sysemu/sysemu.h"
-#include "hw/sysbus.h"
-
-#define MPC8544_GUTS_MMIO_SIZE        0x1000
-#define MPC8544_GUTS_RSTCR_RESET      0x02
-
-#define MPC8544_GUTS_ADDR_PORPLLSR    0x00
-#define MPC8544_GUTS_ADDR_PORBMSR     0x04
-#define MPC8544_GUTS_ADDR_PORIMPSCR   0x08
-#define MPC8544_GUTS_ADDR_PORDEVSR    0x0C
-#define MPC8544_GUTS_ADDR_PORDBGMSR   0x10
-#define MPC8544_GUTS_ADDR_PORDEVSR2   0x14
-#define MPC8544_GUTS_ADDR_GPPORCR     0x20
-#define MPC8544_GUTS_ADDR_GPIOCR      0x30
-#define MPC8544_GUTS_ADDR_GPOUTDR     0x40
-#define MPC8544_GUTS_ADDR_GPINDR      0x50
-#define MPC8544_GUTS_ADDR_PMUXCR      0x60
-#define MPC8544_GUTS_ADDR_DEVDISR     0x70
-#define MPC8544_GUTS_ADDR_POWMGTCSR   0x80
-#define MPC8544_GUTS_ADDR_MCPSUMR     0x90
-#define MPC8544_GUTS_ADDR_RSTRSCR     0x94
-#define MPC8544_GUTS_ADDR_PVR         0xA0
-#define MPC8544_GUTS_ADDR_SVR         0xA4
-#define MPC8544_GUTS_ADDR_RSTCR       0xB0
-#define MPC8544_GUTS_ADDR_IOVSELSR    0xC0
-#define MPC8544_GUTS_ADDR_DDRCSR      0xB20
-#define MPC8544_GUTS_ADDR_DDRCDR      0xB24
-#define MPC8544_GUTS_ADDR_DDRCLKDR    0xB28
-#define MPC8544_GUTS_ADDR_CLKOCR      0xE00
-#define MPC8544_GUTS_ADDR_SRDS1CR1    0xF04
-#define MPC8544_GUTS_ADDR_SRDS2CR1    0xF10
-#define MPC8544_GUTS_ADDR_SRDS2CR3    0xF18
-
-struct GutsState {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-};
-
-typedef struct GutsState GutsState;
-
-static uint64_t mpc8544_guts_read(void *opaque, hwaddr addr,
-                                  unsigned size)
-{
-    uint32_t value = 0;
-    CPUPPCState *env = cpu_single_env;
-
-    addr &= MPC8544_GUTS_MMIO_SIZE - 1;
-    switch (addr) {
-    case MPC8544_GUTS_ADDR_PVR:
-        value = env->spr[SPR_PVR];
-        break;
-    case MPC8544_GUTS_ADDR_SVR:
-        value = env->spr[SPR_E500_SVR];
-        break;
-    default:
-        fprintf(stderr, "guts: Unknown register read: %x\n", (int)addr);
-        break;
-    }
-
-    return value;
-}
-
-static void mpc8544_guts_write(void *opaque, hwaddr addr,
-                               uint64_t value, unsigned size)
-{
-    addr &= MPC8544_GUTS_MMIO_SIZE - 1;
-
-    switch (addr) {
-    case MPC8544_GUTS_ADDR_RSTCR:
-        if (value & MPC8544_GUTS_RSTCR_RESET) {
-            qemu_system_reset_request();
-        }
-        break;
-    default:
-        fprintf(stderr, "guts: Unknown register write: %x = %x\n",
-                (int)addr, (unsigned)value);
-        break;
-    }
-}
-
-static const MemoryRegionOps mpc8544_guts_ops = {
-    .read = mpc8544_guts_read,
-    .write = mpc8544_guts_write,
-    .endianness = DEVICE_BIG_ENDIAN,
-    .valid = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-};
-
-static int mpc8544_guts_initfn(SysBusDevice *dev)
-{
-    GutsState *s;
-
-    s = FROM_SYSBUS(GutsState, SYS_BUS_DEVICE(dev));
-
-    memory_region_init_io(&s->iomem, &mpc8544_guts_ops, s,
-                          "mpc6544.guts", MPC8544_GUTS_MMIO_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    return 0;
-}
-
-static void mpc8544_guts_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = mpc8544_guts_initfn;
-}
-
-static const TypeInfo mpc8544_guts_info = {
-    .name          = "mpc8544-guts",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(GutsState),
-    .class_init    = mpc8544_guts_class_init,
-};
-
-static void mpc8544_guts_register_types(void)
-{
-    type_register_static(&mpc8544_guts_info);
-}
-
-type_init(mpc8544_guts_register_types)
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 294d0de..acc9961 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -1,14 +1,12 @@
 # PREP target
 obj-y += mc146818rtc.o
 # IBM pSeries (sPAPR)
-obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_rtas.o spapr_vio.o
-obj-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
+obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_rtas.o
+obj-$(CONFIG_PSERIES) += spapr_vty.o spapr_llan.o spapr_vscsi.o
 obj-$(CONFIG_PSERIES) += spapr_pci.o pci/pci-hotplug.o spapr_iommu.o
 obj-$(CONFIG_PSERIES) += spapr_events.o spapr_nvram.o
 # PowerPC 4xx boards
-obj-y += ppc4xx_devs.o ppc4xx_pci.o
-# PowerPC E500 boards
-obj-$(CONFIG_E500) += mpc8544_guts.o ppce500_spin.o
+obj-y += ppc4xx_pci.o
 # PowerPC OpenPIC
 obj-y += openpic.o
 
@@ -20,9 +18,9 @@ obj-y := $(addprefix ../,$(obj-y))
 # shared objects
 obj-y += ppc.o ppc_booke.o
 # IBM pSeries (sPAPR)
-obj-$(CONFIG_PSERIES) += spapr.o
+obj-$(CONFIG_PSERIES) += spapr.o xics.o spapr_vio.o
 # PowerPC 4xx boards
-obj-y += ppc405_boards.o ppc405_uc.o ppc440_bamboo.o
+obj-y += ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o
 # PReP
 obj-y += prep.o
 # OldWorld PowerMac
@@ -31,5 +29,6 @@ obj-y += mac_oldworld.o
 obj-y += mac_newworld.o
 # e500
 obj-$(CONFIG_E500) += e500.o mpc8544ds.o e500plat.o
+obj-$(CONFIG_E500) += mpc8544_guts.o ppce500_spin.o
 # PowerPC 440 Xilinx ML507 reference board.
 obj-y += virtex_ml507.o
diff --git a/hw/ppc/mpc8544_guts.c b/hw/ppc/mpc8544_guts.c
new file mode 100644
index 0000000..193beab
--- /dev/null
+++ b/hw/ppc/mpc8544_guts.c
@@ -0,0 +1,143 @@
+/*
+ * QEMU PowerPC MPC8544 global util pseudo-device
+ *
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Alexander Graf, <alex at csgraf.de>
+ *
+ * This 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.
+ *
+ * *****************************************************************
+ *
+ * The documentation for this device is noted in the MPC8544 documentation,
+ * file name "MPC8544ERM.pdf". You can easily find it on the web.
+ *
+ */
+
+#include "hw/hw.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+
+#define MPC8544_GUTS_MMIO_SIZE        0x1000
+#define MPC8544_GUTS_RSTCR_RESET      0x02
+
+#define MPC8544_GUTS_ADDR_PORPLLSR    0x00
+#define MPC8544_GUTS_ADDR_PORBMSR     0x04
+#define MPC8544_GUTS_ADDR_PORIMPSCR   0x08
+#define MPC8544_GUTS_ADDR_PORDEVSR    0x0C
+#define MPC8544_GUTS_ADDR_PORDBGMSR   0x10
+#define MPC8544_GUTS_ADDR_PORDEVSR2   0x14
+#define MPC8544_GUTS_ADDR_GPPORCR     0x20
+#define MPC8544_GUTS_ADDR_GPIOCR      0x30
+#define MPC8544_GUTS_ADDR_GPOUTDR     0x40
+#define MPC8544_GUTS_ADDR_GPINDR      0x50
+#define MPC8544_GUTS_ADDR_PMUXCR      0x60
+#define MPC8544_GUTS_ADDR_DEVDISR     0x70
+#define MPC8544_GUTS_ADDR_POWMGTCSR   0x80
+#define MPC8544_GUTS_ADDR_MCPSUMR     0x90
+#define MPC8544_GUTS_ADDR_RSTRSCR     0x94
+#define MPC8544_GUTS_ADDR_PVR         0xA0
+#define MPC8544_GUTS_ADDR_SVR         0xA4
+#define MPC8544_GUTS_ADDR_RSTCR       0xB0
+#define MPC8544_GUTS_ADDR_IOVSELSR    0xC0
+#define MPC8544_GUTS_ADDR_DDRCSR      0xB20
+#define MPC8544_GUTS_ADDR_DDRCDR      0xB24
+#define MPC8544_GUTS_ADDR_DDRCLKDR    0xB28
+#define MPC8544_GUTS_ADDR_CLKOCR      0xE00
+#define MPC8544_GUTS_ADDR_SRDS1CR1    0xF04
+#define MPC8544_GUTS_ADDR_SRDS2CR1    0xF10
+#define MPC8544_GUTS_ADDR_SRDS2CR3    0xF18
+
+struct GutsState {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+};
+
+typedef struct GutsState GutsState;
+
+static uint64_t mpc8544_guts_read(void *opaque, hwaddr addr,
+                                  unsigned size)
+{
+    uint32_t value = 0;
+    CPUPPCState *env = cpu_single_env;
+
+    addr &= MPC8544_GUTS_MMIO_SIZE - 1;
+    switch (addr) {
+    case MPC8544_GUTS_ADDR_PVR:
+        value = env->spr[SPR_PVR];
+        break;
+    case MPC8544_GUTS_ADDR_SVR:
+        value = env->spr[SPR_E500_SVR];
+        break;
+    default:
+        fprintf(stderr, "guts: Unknown register read: %x\n", (int)addr);
+        break;
+    }
+
+    return value;
+}
+
+static void mpc8544_guts_write(void *opaque, hwaddr addr,
+                               uint64_t value, unsigned size)
+{
+    addr &= MPC8544_GUTS_MMIO_SIZE - 1;
+
+    switch (addr) {
+    case MPC8544_GUTS_ADDR_RSTCR:
+        if (value & MPC8544_GUTS_RSTCR_RESET) {
+            qemu_system_reset_request();
+        }
+        break;
+    default:
+        fprintf(stderr, "guts: Unknown register write: %x = %x\n",
+                (int)addr, (unsigned)value);
+        break;
+    }
+}
+
+static const MemoryRegionOps mpc8544_guts_ops = {
+    .read = mpc8544_guts_read,
+    .write = mpc8544_guts_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static int mpc8544_guts_initfn(SysBusDevice *dev)
+{
+    GutsState *s;
+
+    s = FROM_SYSBUS(GutsState, SYS_BUS_DEVICE(dev));
+
+    memory_region_init_io(&s->iomem, &mpc8544_guts_ops, s,
+                          "mpc6544.guts", MPC8544_GUTS_MMIO_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    return 0;
+}
+
+static void mpc8544_guts_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = mpc8544_guts_initfn;
+}
+
+static const TypeInfo mpc8544_guts_info = {
+    .name          = "mpc8544-guts",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(GutsState),
+    .class_init    = mpc8544_guts_class_init,
+};
+
+static void mpc8544_guts_register_types(void)
+{
+    type_register_static(&mpc8544_guts_info);
+}
+
+type_init(mpc8544_guts_register_types)
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
new file mode 100644
index 0000000..49ec728
--- /dev/null
+++ b/hw/ppc/ppc4xx_devs.c
@@ -0,0 +1,721 @@
+/*
+ * QEMU PowerPC 4xx embedded processors shared devices emulation
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * 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/hw.h"
+#include "hw/ppc.h"
+#include "hw/ppc4xx.h"
+#include "qemu/log.h"
+#include "exec/address-spaces.h"
+
+//#define DEBUG_MMIO
+//#define DEBUG_UNASSIGNED
+#define DEBUG_UIC
+
+
+#ifdef DEBUG_UIC
+#  define LOG_UIC(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
+#else
+#  define LOG_UIC(...) do { } while (0)
+#endif
+
+static void ppc4xx_reset(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+
+    cpu_reset(CPU(cpu));
+}
+
+/*****************************************************************************/
+/* Generic PowerPC 4xx processor instantiation */
+PowerPCCPU *ppc4xx_init(const char *cpu_model,
+                        clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
+                        uint32_t sysclk)
+{
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+
+    /* init CPUs */
+    cpu = cpu_ppc_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to find PowerPC %s CPU definition\n",
+                cpu_model);
+        exit(1);
+    }
+    env = &cpu->env;
+
+    cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
+    cpu_clk->opaque = env;
+    /* Set time-base frequency to sysclk */
+    tb_clk->cb = ppc_40x_timers_init(env, sysclk, PPC_INTERRUPT_PIT);
+    tb_clk->opaque = env;
+    ppc_dcr_init(env, NULL, NULL);
+    /* Register qemu callbacks */
+    qemu_register_reset(ppc4xx_reset, cpu);
+
+    return cpu;
+}
+
+/*****************************************************************************/
+/* "Universal" Interrupt controller */
+enum {
+    DCR_UICSR  = 0x000,
+    DCR_UICSRS = 0x001,
+    DCR_UICER  = 0x002,
+    DCR_UICCR  = 0x003,
+    DCR_UICPR  = 0x004,
+    DCR_UICTR  = 0x005,
+    DCR_UICMSR = 0x006,
+    DCR_UICVR  = 0x007,
+    DCR_UICVCR = 0x008,
+    DCR_UICMAX = 0x009,
+};
+
+#define UIC_MAX_IRQ 32
+typedef struct ppcuic_t ppcuic_t;
+struct ppcuic_t {
+    uint32_t dcr_base;
+    int use_vectors;
+    uint32_t level;  /* Remembers the state of level-triggered interrupts. */
+    uint32_t uicsr;  /* Status register */
+    uint32_t uicer;  /* Enable register */
+    uint32_t uiccr;  /* Critical register */
+    uint32_t uicpr;  /* Polarity register */
+    uint32_t uictr;  /* Triggering register */
+    uint32_t uicvcr; /* Vector configuration register */
+    uint32_t uicvr;
+    qemu_irq *irqs;
+};
+
+static void ppcuic_trigger_irq (ppcuic_t *uic)
+{
+    uint32_t ir, cr;
+    int start, end, inc, i;
+
+    /* Trigger interrupt if any is pending */
+    ir = uic->uicsr & uic->uicer & (~uic->uiccr);
+    cr = uic->uicsr & uic->uicer & uic->uiccr;
+    LOG_UIC("%s: uicsr %08" PRIx32 " uicer %08" PRIx32
+                " uiccr %08" PRIx32 "\n"
+                "   %08" PRIx32 " ir %08" PRIx32 " cr %08" PRIx32 "\n",
+                __func__, uic->uicsr, uic->uicer, uic->uiccr,
+                uic->uicsr & uic->uicer, ir, cr);
+    if (ir != 0x0000000) {
+        LOG_UIC("Raise UIC interrupt\n");
+        qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]);
+    } else {
+        LOG_UIC("Lower UIC interrupt\n");
+        qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]);
+    }
+    /* Trigger critical interrupt if any is pending and update vector */
+    if (cr != 0x0000000) {
+        qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]);
+        if (uic->use_vectors) {
+            /* Compute critical IRQ vector */
+            if (uic->uicvcr & 1) {
+                start = 31;
+                end = 0;
+                inc = -1;
+            } else {
+                start = 0;
+                end = 31;
+                inc = 1;
+            }
+            uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
+            for (i = start; i <= end; i += inc) {
+                if (cr & (1 << i)) {
+                    uic->uicvr += (i - start) * 512 * inc;
+                    break;
+                }
+            }
+        }
+        LOG_UIC("Raise UIC critical interrupt - "
+                    "vector %08" PRIx32 "\n", uic->uicvr);
+    } else {
+        LOG_UIC("Lower UIC critical interrupt\n");
+        qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]);
+        uic->uicvr = 0x00000000;
+    }
+}
+
+static void ppcuic_set_irq (void *opaque, int irq_num, int level)
+{
+    ppcuic_t *uic;
+    uint32_t mask, sr;
+
+    uic = opaque;
+    mask = 1 << (31-irq_num);
+    LOG_UIC("%s: irq %d level %d uicsr %08" PRIx32
+                " mask %08" PRIx32 " => %08" PRIx32 " %08" PRIx32 "\n",
+                __func__, irq_num, level,
+                uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
+    if (irq_num < 0 || irq_num > 31)
+        return;
+    sr = uic->uicsr;
+
+    /* Update status register */
+    if (uic->uictr & mask) {
+        /* Edge sensitive interrupt */
+        if (level == 1)
+            uic->uicsr |= mask;
+    } else {
+        /* Level sensitive interrupt */
+        if (level == 1) {
+            uic->uicsr |= mask;
+            uic->level |= mask;
+        } else {
+            uic->uicsr &= ~mask;
+            uic->level &= ~mask;
+        }
+    }
+    LOG_UIC("%s: irq %d level %d sr %" PRIx32 " => "
+                "%08" PRIx32 "\n", __func__, irq_num, level, uic->uicsr, sr);
+    if (sr != uic->uicsr)
+        ppcuic_trigger_irq(uic);
+}
+
+static uint32_t dcr_read_uic (void *opaque, int dcrn)
+{
+    ppcuic_t *uic;
+    uint32_t ret;
+
+    uic = opaque;
+    dcrn -= uic->dcr_base;
+    switch (dcrn) {
+    case DCR_UICSR:
+    case DCR_UICSRS:
+        ret = uic->uicsr;
+        break;
+    case DCR_UICER:
+        ret = uic->uicer;
+        break;
+    case DCR_UICCR:
+        ret = uic->uiccr;
+        break;
+    case DCR_UICPR:
+        ret = uic->uicpr;
+        break;
+    case DCR_UICTR:
+        ret = uic->uictr;
+        break;
+    case DCR_UICMSR:
+        ret = uic->uicsr & uic->uicer;
+        break;
+    case DCR_UICVR:
+        if (!uic->use_vectors)
+            goto no_read;
+        ret = uic->uicvr;
+        break;
+    case DCR_UICVCR:
+        if (!uic->use_vectors)
+            goto no_read;
+        ret = uic->uicvcr;
+        break;
+    default:
+    no_read:
+        ret = 0x00000000;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_uic (void *opaque, int dcrn, uint32_t val)
+{
+    ppcuic_t *uic;
+
+    uic = opaque;
+    dcrn -= uic->dcr_base;
+    LOG_UIC("%s: dcr %d val 0x%x\n", __func__, dcrn, val);
+    switch (dcrn) {
+    case DCR_UICSR:
+        uic->uicsr &= ~val;
+        uic->uicsr |= uic->level;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICSRS:
+        uic->uicsr |= val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICER:
+        uic->uicer = val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICCR:
+        uic->uiccr = val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICPR:
+        uic->uicpr = val;
+        break;
+    case DCR_UICTR:
+        uic->uictr = val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICMSR:
+        break;
+    case DCR_UICVR:
+        break;
+    case DCR_UICVCR:
+        uic->uicvcr = val & 0xFFFFFFFD;
+        ppcuic_trigger_irq(uic);
+        break;
+    }
+}
+
+static void ppcuic_reset (void *opaque)
+{
+    ppcuic_t *uic;
+
+    uic = opaque;
+    uic->uiccr = 0x00000000;
+    uic->uicer = 0x00000000;
+    uic->uicpr = 0x00000000;
+    uic->uicsr = 0x00000000;
+    uic->uictr = 0x00000000;
+    if (uic->use_vectors) {
+        uic->uicvcr = 0x00000000;
+        uic->uicvr = 0x0000000;
+    }
+}
+
+qemu_irq *ppcuic_init (CPUPPCState *env, qemu_irq *irqs,
+                       uint32_t dcr_base, int has_ssr, int has_vr)
+{
+    ppcuic_t *uic;
+    int i;
+
+    uic = g_malloc0(sizeof(ppcuic_t));
+    uic->dcr_base = dcr_base;
+    uic->irqs = irqs;
+    if (has_vr)
+        uic->use_vectors = 1;
+    for (i = 0; i < DCR_UICMAX; i++) {
+        ppc_dcr_register(env, dcr_base + i, uic,
+                         &dcr_read_uic, &dcr_write_uic);
+    }
+    qemu_register_reset(ppcuic_reset, uic);
+
+    return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
+}
+
+/*****************************************************************************/
+/* SDRAM controller */
+typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
+struct ppc4xx_sdram_t {
+    uint32_t addr;
+    int nbanks;
+    MemoryRegion containers[4]; /* used for clipping */
+    MemoryRegion *ram_memories;
+    hwaddr ram_bases[4];
+    hwaddr ram_sizes[4];
+    uint32_t besr0;
+    uint32_t besr1;
+    uint32_t bear;
+    uint32_t cfg;
+    uint32_t status;
+    uint32_t rtr;
+    uint32_t pmit;
+    uint32_t bcr[4];
+    uint32_t tr;
+    uint32_t ecccfg;
+    uint32_t eccesr;
+    qemu_irq irq;
+};
+
+enum {
+    SDRAM0_CFGADDR = 0x010,
+    SDRAM0_CFGDATA = 0x011,
+};
+
+/* XXX: TOFIX: some patches have made this code become inconsistent:
+ *      there are type inconsistencies, mixing hwaddr, target_ulong
+ *      and uint32_t
+ */
+static uint32_t sdram_bcr (hwaddr ram_base,
+                           hwaddr ram_size)
+{
+    uint32_t bcr;
+
+    switch (ram_size) {
+    case (4 * 1024 * 1024):
+        bcr = 0x00000000;
+        break;
+    case (8 * 1024 * 1024):
+        bcr = 0x00020000;
+        break;
+    case (16 * 1024 * 1024):
+        bcr = 0x00040000;
+        break;
+    case (32 * 1024 * 1024):
+        bcr = 0x00060000;
+        break;
+    case (64 * 1024 * 1024):
+        bcr = 0x00080000;
+        break;
+    case (128 * 1024 * 1024):
+        bcr = 0x000A0000;
+        break;
+    case (256 * 1024 * 1024):
+        bcr = 0x000C0000;
+        break;
+    default:
+        printf("%s: invalid RAM size " TARGET_FMT_plx "\n", __func__,
+               ram_size);
+        return 0x00000000;
+    }
+    bcr |= ram_base & 0xFF800000;
+    bcr |= 1;
+
+    return bcr;
+}
+
+static inline hwaddr sdram_base(uint32_t bcr)
+{
+    return bcr & 0xFF800000;
+}
+
+static target_ulong sdram_size (uint32_t bcr)
+{
+    target_ulong size;
+    int sh;
+
+    sh = (bcr >> 17) & 0x7;
+    if (sh == 7)
+        size = -1;
+    else
+        size = (4 * 1024 * 1024) << sh;
+
+    return size;
+}
+
+static void sdram_set_bcr(ppc4xx_sdram_t *sdram,
+                          uint32_t *bcrp, uint32_t bcr, int enabled)
+{
+    unsigned n = bcrp - sdram->bcr;
+
+    if (*bcrp & 0x00000001) {
+        /* Unmap RAM */
+#ifdef DEBUG_SDRAM
+        printf("%s: unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
+               __func__, sdram_base(*bcrp), sdram_size(*bcrp));
+#endif
+        memory_region_del_subregion(get_system_memory(),
+                                    &sdram->containers[n]);
+        memory_region_del_subregion(&sdram->containers[n],
+                                    &sdram->ram_memories[n]);
+        memory_region_destroy(&sdram->containers[n]);
+    }
+    *bcrp = bcr & 0xFFDEE001;
+    if (enabled && (bcr & 0x00000001)) {
+#ifdef DEBUG_SDRAM
+        printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
+               __func__, sdram_base(bcr), sdram_size(bcr));
+#endif
+        memory_region_init(&sdram->containers[n], "sdram-containers",
+                           sdram_size(bcr));
+        memory_region_add_subregion(&sdram->containers[n], 0,
+                                    &sdram->ram_memories[n]);
+        memory_region_add_subregion(get_system_memory(),
+                                    sdram_base(bcr),
+                                    &sdram->containers[n]);
+    }
+}
+
+static void sdram_map_bcr (ppc4xx_sdram_t *sdram)
+{
+    int i;
+
+    for (i = 0; i < sdram->nbanks; i++) {
+        if (sdram->ram_sizes[i] != 0) {
+            sdram_set_bcr(sdram,
+                          &sdram->bcr[i],
+                          sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
+                          1);
+        } else {
+            sdram_set_bcr(sdram, &sdram->bcr[i], 0x00000000, 0);
+        }
+    }
+}
+
+static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
+{
+    int i;
+
+    for (i = 0; i < sdram->nbanks; i++) {
+#ifdef DEBUG_SDRAM
+        printf("%s: Unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
+               __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
+#endif
+        memory_region_del_subregion(get_system_memory(),
+                                    &sdram->ram_memories[i]);
+    }
+}
+
+static uint32_t dcr_read_sdram (void *opaque, int dcrn)
+{
+    ppc4xx_sdram_t *sdram;
+    uint32_t ret;
+
+    sdram = opaque;
+    switch (dcrn) {
+    case SDRAM0_CFGADDR:
+        ret = sdram->addr;
+        break;
+    case SDRAM0_CFGDATA:
+        switch (sdram->addr) {
+        case 0x00: /* SDRAM_BESR0 */
+            ret = sdram->besr0;
+            break;
+        case 0x08: /* SDRAM_BESR1 */
+            ret = sdram->besr1;
+            break;
+        case 0x10: /* SDRAM_BEAR */
+            ret = sdram->bear;
+            break;
+        case 0x20: /* SDRAM_CFG */
+            ret = sdram->cfg;
+            break;
+        case 0x24: /* SDRAM_STATUS */
+            ret = sdram->status;
+            break;
+        case 0x30: /* SDRAM_RTR */
+            ret = sdram->rtr;
+            break;
+        case 0x34: /* SDRAM_PMIT */
+            ret = sdram->pmit;
+            break;
+        case 0x40: /* SDRAM_B0CR */
+            ret = sdram->bcr[0];
+            break;
+        case 0x44: /* SDRAM_B1CR */
+            ret = sdram->bcr[1];
+            break;
+        case 0x48: /* SDRAM_B2CR */
+            ret = sdram->bcr[2];
+            break;
+        case 0x4C: /* SDRAM_B3CR */
+            ret = sdram->bcr[3];
+            break;
+        case 0x80: /* SDRAM_TR */
+            ret = -1; /* ? */
+            break;
+        case 0x94: /* SDRAM_ECCCFG */
+            ret = sdram->ecccfg;
+            break;
+        case 0x98: /* SDRAM_ECCESR */
+            ret = sdram->eccesr;
+            break;
+        default: /* Error */
+            ret = -1;
+            break;
+        }
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0x00000000;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = opaque;
+    switch (dcrn) {
+    case SDRAM0_CFGADDR:
+        sdram->addr = val;
+        break;
+    case SDRAM0_CFGDATA:
+        switch (sdram->addr) {
+        case 0x00: /* SDRAM_BESR0 */
+            sdram->besr0 &= ~val;
+            break;
+        case 0x08: /* SDRAM_BESR1 */
+            sdram->besr1 &= ~val;
+            break;
+        case 0x10: /* SDRAM_BEAR */
+            sdram->bear = val;
+            break;
+        case 0x20: /* SDRAM_CFG */
+            val &= 0xFFE00000;
+            if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
+#ifdef DEBUG_SDRAM
+                printf("%s: enable SDRAM controller\n", __func__);
+#endif
+                /* validate all RAM mappings */
+                sdram_map_bcr(sdram);
+                sdram->status &= ~0x80000000;
+            } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
+#ifdef DEBUG_SDRAM
+                printf("%s: disable SDRAM controller\n", __func__);
+#endif
+                /* invalidate all RAM mappings */
+                sdram_unmap_bcr(sdram);
+                sdram->status |= 0x80000000;
+            }
+            if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
+                sdram->status |= 0x40000000;
+            else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
+                sdram->status &= ~0x40000000;
+            sdram->cfg = val;
+            break;
+        case 0x24: /* SDRAM_STATUS */
+            /* Read-only register */
+            break;
+        case 0x30: /* SDRAM_RTR */
+            sdram->rtr = val & 0x3FF80000;
+            break;
+        case 0x34: /* SDRAM_PMIT */
+            sdram->pmit = (val & 0xF8000000) | 0x07C00000;
+            break;
+        case 0x40: /* SDRAM_B0CR */
+            sdram_set_bcr(sdram, &sdram->bcr[0], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x44: /* SDRAM_B1CR */
+            sdram_set_bcr(sdram, &sdram->bcr[1], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x48: /* SDRAM_B2CR */
+            sdram_set_bcr(sdram, &sdram->bcr[2], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x4C: /* SDRAM_B3CR */
+            sdram_set_bcr(sdram, &sdram->bcr[3], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x80: /* SDRAM_TR */
+            sdram->tr = val & 0x018FC01F;
+            break;
+        case 0x94: /* SDRAM_ECCCFG */
+            sdram->ecccfg = val & 0x00F00000;
+            break;
+        case 0x98: /* SDRAM_ECCESR */
+            val &= 0xFFF0F000;
+            if (sdram->eccesr == 0 && val != 0)
+                qemu_irq_raise(sdram->irq);
+            else if (sdram->eccesr != 0 && val == 0)
+                qemu_irq_lower(sdram->irq);
+            sdram->eccesr = val;
+            break;
+        default: /* Error */
+            break;
+        }
+        break;
+    }
+}
+
+static void sdram_reset (void *opaque)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = opaque;
+    sdram->addr = 0x00000000;
+    sdram->bear = 0x00000000;
+    sdram->besr0 = 0x00000000; /* No error */
+    sdram->besr1 = 0x00000000; /* No error */
+    sdram->cfg = 0x00000000;
+    sdram->ecccfg = 0x00000000; /* No ECC */
+    sdram->eccesr = 0x00000000; /* No error */
+    sdram->pmit = 0x07C00000;
+    sdram->rtr = 0x05F00000;
+    sdram->tr = 0x00854009;
+    /* We pre-initialize RAM banks */
+    sdram->status = 0x00000000;
+    sdram->cfg = 0x00800000;
+}
+
+void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
+                        MemoryRegion *ram_memories,
+                        hwaddr *ram_bases,
+                        hwaddr *ram_sizes,
+                        int do_init)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = g_malloc0(sizeof(ppc4xx_sdram_t));
+    sdram->irq = irq;
+    sdram->nbanks = nbanks;
+    sdram->ram_memories = ram_memories;
+    memset(sdram->ram_bases, 0, 4 * sizeof(hwaddr));
+    memcpy(sdram->ram_bases, ram_bases,
+           nbanks * sizeof(hwaddr));
+    memset(sdram->ram_sizes, 0, 4 * sizeof(hwaddr));
+    memcpy(sdram->ram_sizes, ram_sizes,
+           nbanks * sizeof(hwaddr));
+    qemu_register_reset(&sdram_reset, sdram);
+    ppc_dcr_register(env, SDRAM0_CFGADDR,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    ppc_dcr_register(env, SDRAM0_CFGDATA,
+                     sdram, &dcr_read_sdram, &dcr_write_sdram);
+    if (do_init)
+        sdram_map_bcr(sdram);
+}
+
+/* Fill in consecutive SDRAM banks with 'ram_size' bytes of memory.
+ *
+ * sdram_bank_sizes[] must be 0-terminated.
+ *
+ * The 4xx SDRAM controller supports a small number of banks, and each bank
+ * must be one of a small set of sizes. The number of banks and the supported
+ * sizes varies by SoC. */
+ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
+                               MemoryRegion ram_memories[],
+                               hwaddr ram_bases[],
+                               hwaddr ram_sizes[],
+                               const unsigned int sdram_bank_sizes[])
+{
+    ram_addr_t size_left = ram_size;
+    ram_addr_t base = 0;
+    int i;
+    int j;
+
+    for (i = 0; i < nr_banks; i++) {
+        for (j = 0; sdram_bank_sizes[j] != 0; j++) {
+            unsigned int bank_size = sdram_bank_sizes[j];
+
+            if (bank_size <= size_left) {
+                char name[32];
+                snprintf(name, sizeof(name), "ppc4xx.sdram%d", i);
+                memory_region_init_ram(&ram_memories[i], name, bank_size);
+                vmstate_register_ram_global(&ram_memories[i]);
+                ram_bases[i] = base;
+                ram_sizes[i] = bank_size;
+                base += bank_size;
+                size_left -= bank_size;
+                break;
+            }
+        }
+
+        if (!size_left) {
+            /* No need to use the remaining banks. */
+            break;
+        }
+    }
+
+    ram_size -= size_left;
+    if (size_left)
+        printf("Truncating memory to %d MiB to fit SDRAM controller limits.\n",
+               (int)(ram_size >> 20));
+
+    return ram_size;
+}
diff --git a/hw/ppc/ppce500_spin.c b/hw/ppc/ppce500_spin.c
new file mode 100644
index 0000000..d904fbe
--- /dev/null
+++ b/hw/ppc/ppce500_spin.c
@@ -0,0 +1,222 @@
+/*
+ * QEMU PowerPC e500v2 ePAPR spinning code
+ *
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: 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/>.
+ *
+ * This code is not really a device, but models an interface that usually
+ * firmware takes care of. It's used when QEMU plays the role of firmware.
+ *
+ * Specification:
+ *
+ * https://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.1.pdf
+ *
+ */
+
+#include "hw/hw.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+#include "sysemu/kvm.h"
+
+#define MAX_CPUS 32
+
+typedef struct spin_info {
+    uint64_t addr;
+    uint64_t r3;
+    uint32_t resv;
+    uint32_t pir;
+    uint64_t reserved;
+} QEMU_PACKED SpinInfo;
+
+typedef struct spin_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    SpinInfo spin[MAX_CPUS];
+} SpinState;
+
+typedef struct spin_kick {
+    PowerPCCPU *cpu;
+    SpinInfo *spin;
+} SpinKick;
+
+static void spin_reset(void *opaque)
+{
+    SpinState *s = opaque;
+    int i;
+
+    for (i = 0; i < MAX_CPUS; i++) {
+        SpinInfo *info = &s->spin[i];
+
+        info->pir = i;
+        info->r3 = i;
+        info->addr = 1;
+    }
+}
+
+/* Create -kernel TLB entries for BookE, linearly spanning 256MB.  */
+static inline hwaddr booke206_page_size_to_tlb(uint64_t size)
+{
+    return (ffs(size >> 10) - 1) >> 1;
+}
+
+static void mmubooke_create_initial_mapping(CPUPPCState *env,
+                                     target_ulong va,
+                                     hwaddr pa,
+                                     hwaddr len)
+{
+    ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 1);
+    hwaddr size;
+
+    size = (booke206_page_size_to_tlb(len) << MAS1_TSIZE_SHIFT);
+    tlb->mas1 = MAS1_VALID | size;
+    tlb->mas2 = (va & TARGET_PAGE_MASK) | MAS2_M;
+    tlb->mas7_3 = pa & TARGET_PAGE_MASK;
+    tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
+    env->tlb_dirty = true;
+}
+
+static void spin_kick(void *data)
+{
+    SpinKick *kick = data;
+    CPUState *cpu = CPU(kick->cpu);
+    CPUPPCState *env = &kick->cpu->env;
+    SpinInfo *curspin = kick->spin;
+    hwaddr map_size = 64 * 1024 * 1024;
+    hwaddr map_start;
+
+    cpu_synchronize_state(env);
+    stl_p(&curspin->pir, env->spr[SPR_PIR]);
+    env->nip = ldq_p(&curspin->addr) & (map_size - 1);
+    env->gpr[3] = ldq_p(&curspin->r3);
+    env->gpr[4] = 0;
+    env->gpr[5] = 0;
+    env->gpr[6] = 0;
+    env->gpr[7] = map_size;
+    env->gpr[8] = 0;
+    env->gpr[9] = 0;
+
+    map_start = ldq_p(&curspin->addr) & ~(map_size - 1);
+    mmubooke_create_initial_mapping(env, 0, map_start, map_size);
+
+    env->halted = 0;
+    env->exception_index = -1;
+    cpu->stopped = false;
+    qemu_cpu_kick(cpu);
+}
+
+static void spin_write(void *opaque, hwaddr addr, uint64_t value,
+                       unsigned len)
+{
+    SpinState *s = opaque;
+    int env_idx = addr / sizeof(SpinInfo);
+    CPUState *cpu;
+    SpinInfo *curspin = &s->spin[env_idx];
+    uint8_t *curspin_p = (uint8_t*)curspin;
+
+    cpu = qemu_get_cpu(env_idx);
+    if (cpu == NULL) {
+        /* Unknown CPU */
+        return;
+    }
+
+    if (cpu->cpu_index == 0) {
+        /* primary CPU doesn't spin */
+        return;
+    }
+
+    curspin_p = &curspin_p[addr % sizeof(SpinInfo)];
+    switch (len) {
+    case 1:
+        stb_p(curspin_p, value);
+        break;
+    case 2:
+        stw_p(curspin_p, value);
+        break;
+    case 4:
+        stl_p(curspin_p, value);
+        break;
+    }
+
+    if (!(ldq_p(&curspin->addr) & 1)) {
+        /* run CPU */
+        SpinKick kick = {
+            .cpu = POWERPC_CPU(cpu),
+            .spin = curspin,
+        };
+
+        run_on_cpu(cpu, spin_kick, &kick);
+    }
+}
+
+static uint64_t spin_read(void *opaque, hwaddr addr, unsigned len)
+{
+    SpinState *s = opaque;
+    uint8_t *spin_p = &((uint8_t*)s->spin)[addr];
+
+    switch (len) {
+    case 1:
+        return ldub_p(spin_p);
+    case 2:
+        return lduw_p(spin_p);
+    case 4:
+        return ldl_p(spin_p);
+    default:
+        hw_error("ppce500: unexpected %s with len = %u", __func__, len);
+    }
+}
+
+static const MemoryRegionOps spin_rw_ops = {
+    .read = spin_read,
+    .write = spin_write,
+    .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static int ppce500_spin_initfn(SysBusDevice *dev)
+{
+    SpinState *s;
+
+    s = FROM_SYSBUS(SpinState, SYS_BUS_DEVICE(dev));
+
+    memory_region_init_io(&s->iomem, &spin_rw_ops, s, "e500 spin pv device",
+                          sizeof(SpinInfo) * MAX_CPUS);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    qemu_register_reset(spin_reset, s);
+
+    return 0;
+}
+
+static void ppce500_spin_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = ppce500_spin_initfn;
+}
+
+static const TypeInfo ppce500_spin_info = {
+    .name          = "e500-spin",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(SpinState),
+    .class_init    = ppce500_spin_class_init,
+};
+
+static void ppce500_spin_register_types(void)
+{
+    type_register_static(&ppce500_spin_info);
+}
+
+type_init(ppce500_spin_register_types)
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
new file mode 100644
index 0000000..6eb3ab5
--- /dev/null
+++ b/hw/ppc/spapr_vio.c
@@ -0,0 +1,649 @@
+/*
+ * 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/hw.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "monitor/monitor.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "hw/sysbus.h"
+#include "sysemu/kvm.h"
+#include "sysemu/device_tree.h"
+#include "kvm_ppc.h"
+
+#include "hw/spapr.h"
+#include "hw/spapr_vio.h"
+#include "hw/xics.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 Property spapr_vio_props[] = {
+    DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, irq, 0), \
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static const TypeInfo spapr_vio_bus_info = {
+    .name = TYPE_SPAPR_VIO_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(VIOsPAPRBus),
+};
+
+VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
+{
+    BusChild *kid;
+    VIOsPAPRDevice *dev = NULL;
+
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        dev = (VIOsPAPRDevice *)kid->child;
+        if (dev->reg == reg) {
+            return dev;
+        }
+    }
+
+    return NULL;
+}
+
+static char *vio_format_dev_name(VIOsPAPRDevice *dev)
+{
+    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+    char *name;
+
+    /* Device tree style name device at reg */
+    name = g_strdup_printf("%s@%x", pc->dt_name, dev->reg);
+
+    return name;
+}
+
+#ifdef CONFIG_FDT
+static int vio_make_devnode(VIOsPAPRDevice *dev,
+                            void *fdt)
+{
+    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+    int vdevice_off, node_off, ret;
+    char *dt_name;
+
+    vdevice_off = fdt_path_offset(fdt, "/vdevice");
+    if (vdevice_off < 0) {
+        return vdevice_off;
+    }
+
+    dt_name = vio_format_dev_name(dev);
+    node_off = fdt_add_subnode(fdt, vdevice_off, dt_name);
+    g_free(dt_name);
+    if (node_off < 0) {
+        return node_off;
+    }
+
+    ret = fdt_setprop_cell(fdt, node_off, "reg", dev->reg);
+    if (ret < 0) {
+        return ret;
+    }
+
+    if (pc->dt_type) {
+        ret = fdt_setprop_string(fdt, node_off, "device_type",
+                                 pc->dt_type);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    if (pc->dt_compatible) {
+        ret = fdt_setprop_string(fdt, node_off, "compatible",
+                                 pc->dt_compatible);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    if (dev->irq) {
+        uint32_t ints_prop[] = {cpu_to_be32(dev->irq), 0};
+
+        ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop,
+                          sizeof(ints_prop));
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    ret = spapr_tcet_dma_dt(fdt, node_off, "ibm,my-dma-window", dev->dma);
+    if (ret < 0) {
+        return ret;
+    }
+
+    if (pc->devnode) {
+        ret = (pc->devnode)(dev, fdt, node_off);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    return node_off;
+}
+#endif /* CONFIG_FDT */
+
+/*
+ * CRQ handling
+ */
+static target_ulong h_reg_crq(PowerPCCPU *cpu, 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("Unit 0x" TARGET_FMT_lx " does not exist\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("Queue size too small or too big (0x" TARGET_FMT_lx
+                      ")\n", queue_len);
+        return H_PARAMETER;
+    }
+
+    /* Check queue alignment */
+    if (queue_addr & 0xfff) {
+        hcall_dprintf("Queue not aligned (0x" TARGET_FMT_lx ")\n", queue_addr);
+        return H_PARAMETER;
+    }
+
+    /* Check if device supports CRQs */
+    if (!dev->crq.SendFunc) {
+        hcall_dprintf("Device does not support CRQ\n");
+        return H_NOT_FOUND;
+    }
+
+    /* Already a queue ? */
+    if (dev->crq.qsize) {
+        hcall_dprintf("CRQ already registered\n");
+        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 free_crq(VIOsPAPRDevice *dev)
+{
+    dev->crq.qladdr = 0;
+    dev->crq.qsize = 0;
+    dev->crq.qnext = 0;
+
+    dprintf("CRQ for dev 0x%" PRIx32 " freed\n", dev->reg);
+
+    return H_SUCCESS;
+}
+
+static target_ulong h_free_crq(PowerPCCPU *cpu, 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("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
+        return H_PARAMETER;
+    }
+
+    return free_crq(dev);
+}
+
+static target_ulong h_send_crq(PowerPCCPU *cpu, 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("Unit 0x" TARGET_FMT_lx " does not exist\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(PowerPCCPU *cpu, 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("Unit 0x" TARGET_FMT_lx " does not exist\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_vio_dma_read(dev, dev->crq.qladdr + dev->crq.qnext, &byte, 1);
+    if (rc) {
+        return rc;
+    }
+    if (byte != 0) {
+        return 1;
+    }
+
+    rc = spapr_vio_dma_write(dev, dev->crq.qladdr + dev->crq.qnext + 8,
+                             &crq[8], 8);
+    if (rc) {
+        return rc;
+    }
+
+    kvmppc_eieio();
+
+    rc = spapr_vio_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(spapr_vio_qirq(dev));
+    }
+
+    return 0;
+}
+
+/* "quiesce" handling */
+
+static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev)
+{
+    if (dev->dma) {
+        spapr_tce_reset(dev->dma);
+    }
+    free_crq(dev);
+}
+
+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 (!dev->dma) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    spapr_tce_set_bypass(dev->dma, !!enable);
+
+    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;
+    BusChild *kid;
+    VIOsPAPRDevice *dev = NULL;
+
+    if (nargs != 0) {
+        rtas_st(rets, 0, -3);
+        return;
+    }
+
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        dev = (VIOsPAPRDevice *)kid->child;
+        spapr_vio_quiesce_one(dev);
+    }
+
+    rtas_st(rets, 0, 0);
+}
+
+static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
+{
+    VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
+    BusChild *kid;
+    VIOsPAPRDevice *other;
+
+    /*
+     * Check for a device other than the given one which is already
+     * using the requested address. We have to open code this because
+     * the given dev might already be in the list.
+     */
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        other = DO_UPCAST(VIOsPAPRDevice, qdev, kid->child);
+
+        if (other != dev && other->reg == dev->reg) {
+            return other;
+        }
+    }
+
+    return 0;
+}
+
+static void spapr_vio_busdev_reset(DeviceState *qdev)
+{
+    VIOsPAPRDevice *dev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
+    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+
+    /* Shut down the request queue and TCEs if necessary */
+    spapr_vio_quiesce_one(dev);
+
+    dev->signal_state = 0;
+
+    if (pc->reset) {
+        pc->reset(dev);
+    }
+}
+
+static int spapr_vio_busdev_init(DeviceState *qdev)
+{
+    VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
+    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+    char *id;
+
+    if (dev->reg != -1) {
+        /*
+         * Explicitly assigned address, just verify that no-one else
+         * is using it.  other mechanism). We have to open code this
+         * rather than using spapr_vio_find_by_reg() because sdev
+         * itself is already in the list.
+         */
+        VIOsPAPRDevice *other = reg_conflict(dev);
+
+        if (other) {
+            fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n",
+                    object_get_typename(OBJECT(qdev)),
+                    object_get_typename(OBJECT(&other->qdev)),
+                    dev->reg);
+            return -1;
+        }
+    } else {
+        /* Need to assign an address */
+        VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
+
+        do {
+            dev->reg = bus->next_reg++;
+        } while (reg_conflict(dev));
+    }
+
+    /* Don't overwrite ids assigned on the command line */
+    if (!dev->qdev.id) {
+        id = vio_format_dev_name(dev);
+        dev->qdev.id = id;
+    }
+
+    dev->irq = spapr_allocate_msi(dev->irq);
+    if (!dev->irq) {
+        return -1;
+    }
+
+    if (pc->rtce_window_size) {
+        uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
+        dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size);
+    }
+
+    return pc->init(dev);
+}
+
+static target_ulong h_vio_signal(PowerPCCPU *cpu, 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);
+    VIOsPAPRDeviceClass *pc;
+
+    if (!dev) {
+        return H_PARAMETER;
+    }
+
+    pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+
+    if (mode & ~pc->signal_mask) {
+        return H_PARAMETER;
+    }
+
+    dev->signal_state = mode;
+
+    return H_SUCCESS;
+}
+
+VIOsPAPRBus *spapr_vio_bus_init(void)
+{
+    VIOsPAPRBus *bus;
+    BusState *qbus;
+    DeviceState *dev;
+
+    /* Create bridge device */
+    dev = qdev_create(NULL, "spapr-vio-bridge");
+    qdev_init_nofail(dev);
+
+    /* Create bus on bridge device */
+
+    qbus = qbus_create(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio");
+    bus = DO_UPCAST(VIOsPAPRBus, bus, qbus);
+    bus->next_reg = 0x71000000;
+
+    /* hcall-vio */
+    spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);
+
+    /* 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);
+
+    /* RTAS calls */
+    spapr_rtas_register("ibm,set-tce-bypass", rtas_set_tce_bypass);
+    spapr_rtas_register("quiesce", rtas_quiesce);
+
+    return bus;
+}
+
+/* Represents sPAPR hcall VIO devices */
+
+static int spapr_vio_bridge_init(SysBusDevice *dev)
+{
+    /* nothing */
+    return 0;
+}
+
+static void spapr_vio_bridge_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = spapr_vio_bridge_init;
+    dc->no_user = 1;
+}
+
+static const TypeInfo spapr_vio_bridge_info = {
+    .name          = "spapr-vio-bridge",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(SysBusDevice),
+    .class_init    = spapr_vio_bridge_class_init,
+};
+
+static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *k = DEVICE_CLASS(klass);
+    k->init = spapr_vio_busdev_init;
+    k->reset = spapr_vio_busdev_reset;
+    k->bus_type = TYPE_SPAPR_VIO_BUS;
+    k->props = spapr_vio_props;
+}
+
+static const TypeInfo spapr_vio_type_info = {
+    .name = TYPE_VIO_SPAPR_DEVICE,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(VIOsPAPRDevice),
+    .abstract = true,
+    .class_size = sizeof(VIOsPAPRDeviceClass),
+    .class_init = vio_spapr_device_class_init,
+};
+
+static void spapr_vio_register_types(void)
+{
+    type_register_static(&spapr_vio_bus_info);
+    type_register_static(&spapr_vio_bridge_info);
+    type_register_static(&spapr_vio_type_info);
+}
+
+type_init(spapr_vio_register_types)
+
+#ifdef CONFIG_FDT
+static int compare_reg(const void *p1, const void *p2)
+{
+    VIOsPAPRDevice const *dev1, *dev2;
+
+    dev1 = (VIOsPAPRDevice *)*(DeviceState **)p1;
+    dev2 = (VIOsPAPRDevice *)*(DeviceState **)p2;
+
+    if (dev1->reg < dev2->reg) {
+        return -1;
+    }
+    if (dev1->reg == dev2->reg) {
+        return 0;
+    }
+
+    /* dev1->reg > dev2->reg */
+    return 1;
+}
+
+int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt)
+{
+    DeviceState *qdev, **qdevs;
+    BusChild *kid;
+    int i, num, ret = 0;
+
+    /* Count qdevs on the bus list */
+    num = 0;
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        num++;
+    }
+
+    /* Copy out into an array of pointers */
+    qdevs = g_malloc(sizeof(qdev) * num);
+    num = 0;
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        qdevs[num++] = kid->child;
+    }
+
+    /* Sort the array */
+    qsort(qdevs, num, sizeof(qdev), compare_reg);
+
+    /* Hack alert. Give the devices to libfdt in reverse order, we happen
+     * to know that will mean they are in forward order in the tree. */
+    for (i = num - 1; i >= 0; i--) {
+        VIOsPAPRDevice *dev = (VIOsPAPRDevice *)(qdevs[i]);
+
+        ret = vio_make_devnode(dev, fdt);
+
+        if (ret < 0) {
+            goto out;
+        }
+    }
+
+    ret = 0;
+out:
+    free(qdevs);
+
+    return ret;
+}
+
+int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus)
+{
+    VIOsPAPRDevice *dev;
+    char *name, *path;
+    int ret, offset;
+
+    dev = spapr_vty_get_default(bus);
+    if (!dev)
+        return 0;
+
+    offset = fdt_path_offset(fdt, "/chosen");
+    if (offset < 0) {
+        return offset;
+    }
+
+    name = vio_format_dev_name(dev);
+    path = g_strdup_printf("/vdevice/%s", name);
+
+    ret = fdt_setprop_string(fdt, offset, "linux,stdout-path", path);
+
+    g_free(name);
+    g_free(path);
+
+    return ret;
+}
+#endif /* CONFIG_FDT */
diff --git a/hw/ppc/xics.c b/hw/ppc/xics.c
new file mode 100644
index 0000000..c3ef12f
--- /dev/null
+++ b/hw/ppc/xics.c
@@ -0,0 +1,588 @@
+/*
+ * 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/hw.h"
+#include "trace.h"
+#include "hw/spapr.h"
+#include "hw/xics.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;
+    }
+
+    trace_xics_icp_check_ipi(server, ss->mfrr);
+
+    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 server, uint8_t mfrr)
+{
+    struct icp_server_state *ss = icp->ss + server;
+
+    ss->mfrr = mfrr;
+    if (mfrr < CPPR(ss)) {
+        icp_check_ipi(icp, server);
+    }
+}
+
+static uint32_t icp_accept(struct icp_server_state *ss)
+{
+    uint32_t xirr = ss->xirr;
+
+    qemu_irq_lower(ss->output);
+    ss->xirr = ss->pending_priority << 24;
+
+    trace_xics_icp_accept(xirr, ss->xirr);
+
+    return xirr;
+}
+
+static void icp_eoi(struct icp_state *icp, int server, uint32_t xirr)
+{
+    struct icp_server_state *ss = icp->ss + server;
+
+    /* Send EOI -> ICS */
+    ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
+    trace_xics_icp_eoi(server, xirr, ss->xirr);
+    ics_eoi(icp->ics, xirr & XISR_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;
+
+    trace_xics_icp_irq(server, nr, priority);
+
+    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;
+        trace_xics_icp_raise(ss->xirr, ss->pending_priority);
+        qemu_irq_raise(ss->output);
+    }
+}
+
+/*
+ * ICS: Source layer
+ */
+
+struct ics_irq_state {
+    int server;
+    uint8_t priority;
+    uint8_t saved_priority;
+#define XICS_STATUS_ASSERTED           0x1
+#define XICS_STATUS_SENT               0x2
+#define XICS_STATUS_REJECTED           0x4
+#define XICS_STATUS_MASKED_PENDING     0x8
+    uint8_t status;
+};
+
+struct ics_state {
+    int nr_irqs;
+    int offset;
+    qemu_irq *qirqs;
+    bool *islsi;
+    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 resend_msi(struct ics_state *ics, int srcno)
+{
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    /* FIXME: filter by server#? */
+    if (irq->status & XICS_STATUS_REJECTED) {
+        irq->status &= ~XICS_STATUS_REJECTED;
+        if (irq->priority != 0xff) {
+            icp_irq(ics->icp, irq->server, srcno + ics->offset,
+                    irq->priority);
+        }
+    }
+}
+
+static void resend_lsi(struct ics_state *ics, int srcno)
+{
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    if ((irq->priority != 0xff)
+        && (irq->status & XICS_STATUS_ASSERTED)
+        && !(irq->status & XICS_STATUS_SENT)) {
+        irq->status |= XICS_STATUS_SENT;
+        icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
+    }
+}
+
+static void set_irq_msi(struct ics_state *ics, int srcno, int val)
+{
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    trace_xics_set_irq_msi(srcno, srcno + ics->offset);
+
+    if (val) {
+        if (irq->priority == 0xff) {
+            irq->status |= XICS_STATUS_MASKED_PENDING;
+            trace_xics_masked_pending();
+        } else  {
+            icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
+        }
+    }
+}
+
+static void set_irq_lsi(struct ics_state *ics, int srcno, int val)
+{
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    trace_xics_set_irq_lsi(srcno, srcno + ics->offset);
+    if (val) {
+        irq->status |= XICS_STATUS_ASSERTED;
+    } else {
+        irq->status &= ~XICS_STATUS_ASSERTED;
+    }
+    resend_lsi(ics, srcno);
+}
+
+static void ics_set_irq(void *opaque, int srcno, int val)
+{
+    struct ics_state *ics = (struct ics_state *)opaque;
+
+    if (ics->islsi[srcno]) {
+        set_irq_lsi(ics, srcno, val);
+    } else {
+        set_irq_msi(ics, srcno, val);
+    }
+}
+
+static void write_xive_msi(struct ics_state *ics, int srcno)
+{
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    if (!(irq->status & XICS_STATUS_MASKED_PENDING)
+        || (irq->priority == 0xff)) {
+        return;
+    }
+
+    irq->status &= ~XICS_STATUS_MASKED_PENDING;
+    icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
+}
+
+static void write_xive_lsi(struct ics_state *ics, int srcno)
+{
+    resend_lsi(ics, srcno);
+}
+
+static void ics_write_xive(struct ics_state *ics, int nr, int server,
+                           uint8_t priority, uint8_t saved_priority)
+{
+    int srcno = nr - ics->offset;
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    irq->server = server;
+    irq->priority = priority;
+    irq->saved_priority = saved_priority;
+
+    trace_xics_ics_write_xive(nr, srcno, server, priority);
+
+    if (ics->islsi[srcno]) {
+        write_xive_lsi(ics, srcno);
+    } else {
+        write_xive_msi(ics, srcno);
+    }
+}
+
+static void ics_reject(struct ics_state *ics, int nr)
+{
+    struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
+
+    trace_xics_ics_reject(nr, nr - ics->offset);
+    irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */
+    irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */
+}
+
+static void ics_resend(struct ics_state *ics)
+{
+    int i;
+
+    for (i = 0; i < ics->nr_irqs; i++) {
+        /* FIXME: filter by server#? */
+        if (ics->islsi[i]) {
+            resend_lsi(ics, i);
+        } else {
+            resend_msi(ics, i);
+        }
+    }
+}
+
+static void ics_eoi(struct ics_state *ics, int nr)
+{
+    int srcno = nr - ics->offset;
+    struct ics_irq_state *irq = ics->irqs + srcno;
+
+    trace_xics_ics_eoi(nr);
+
+    if (ics->islsi[srcno]) {
+        irq->status &= ~XICS_STATUS_SENT;
+    }
+}
+
+/*
+ * Exported functions
+ */
+
+qemu_irq xics_get_qirq(struct icp_state *icp, int irq)
+{
+    if (!ics_valid_irq(icp->ics, irq)) {
+        return NULL;
+    }
+
+    return icp->ics->qirqs[irq - icp->ics->offset];
+}
+
+void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi)
+{
+    assert(ics_valid_irq(icp->ics, irq));
+
+    icp->ics->islsi[irq - icp->ics->offset] = lsi;
+}
+
+static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                           target_ulong opcode, target_ulong *args)
+{
+    CPUState *cs = CPU(cpu);
+    target_ulong cppr = args[0];
+
+    icp_set_cppr(spapr->icp, cs->cpu_index, cppr);
+    return H_SUCCESS;
+}
+
+static target_ulong h_ipi(PowerPCCPU *cpu, 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(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                           target_ulong opcode, target_ulong *args)
+{
+    CPUState *cs = CPU(cpu);
+    uint32_t xirr = icp_accept(spapr->icp->ss + cs->cpu_index);
+
+    args[0] = xirr;
+    return H_SUCCESS;
+}
+
+static target_ulong h_eoi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+                          target_ulong opcode, target_ulong *args)
+{
+    CPUState *cs = CPU(cpu);
+    target_ulong xirr = args[0];
+
+    icp_eoi(spapr->icp, cs->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(ics, nr, server, priority, 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;
+    }
+
+    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
+                   ics->irqs[nr - ics->offset].priority);
+
+    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;
+    }
+
+    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
+                   ics->irqs[nr - ics->offset].saved_priority,
+                   ics->irqs[nr - ics->offset].saved_priority);
+
+    rtas_st(rets, 0, 0); /* Success */
+}
+
+static void xics_reset(void *opaque)
+{
+    struct icp_state *icp = (struct icp_state *)opaque;
+    struct ics_state *ics = icp->ics;
+    int i;
+
+    for (i = 0; i < icp->nr_servers; i++) {
+        icp->ss[i].xirr = 0;
+        icp->ss[i].pending_priority = 0xff;
+        icp->ss[i].mfrr = 0xff;
+        /* Make all outputs are deasserted */
+        qemu_set_irq(icp->ss[i].output, 0);
+    }
+
+    memset(ics->irqs, 0, sizeof(struct ics_irq_state) * ics->nr_irqs);
+    for (i = 0; i < ics->nr_irqs; i++) {
+        ics->irqs[i].priority = 0xff;
+        ics->irqs[i].saved_priority = 0xff;
+    }
+}
+
+struct icp_state *xics_system_init(int nr_irqs)
+{
+    CPUPPCState *env;
+    CPUState *cpu;
+    int max_server_num;
+    struct icp_state *icp;
+    struct ics_state *ics;
+
+    max_server_num = -1;
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        cpu = CPU(ppc_env_get_cpu(env));
+        if (cpu->cpu_index > max_server_num) {
+            max_server_num = cpu->cpu_index;
+        }
+    }
+
+    icp = g_malloc0(sizeof(*icp));
+    icp->nr_servers = max_server_num + 1;
+    icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state));
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        cpu = CPU(ppc_env_get_cpu(env));
+        struct icp_server_state *ss = &icp->ss[cpu->cpu_index];
+
+        switch (PPC_INPUT(env)) {
+        case PPC_FLAGS_INPUT_POWER7:
+            ss->output = env->irq_inputs[POWER7_INPUT_INT];
+            break;
+
+        case PPC_FLAGS_INPUT_970:
+            ss->output = env->irq_inputs[PPC970_INPUT_INT];
+            break;
+
+        default:
+            hw_error("XICS interrupt model does not support this CPU bus "
+                     "model\n");
+            exit(1);
+        }
+    }
+
+    ics = g_malloc0(sizeof(*ics));
+    ics->nr_irqs = nr_irqs;
+    ics->offset = XICS_IRQ_BASE;
+    ics->irqs = g_malloc0(nr_irqs * sizeof(struct ics_irq_state));
+    ics->islsi = g_malloc0(nr_irqs * sizeof(bool));
+
+    icp->ics = ics;
+    ics->icp = icp;
+
+    ics->qirqs = qemu_allocate_irqs(ics_set_irq, 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);
+
+    qemu_register_reset(xics_reset, icp);
+
+    return icp;
+}
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
deleted file mode 100644
index 49ec728..0000000
--- a/hw/ppc4xx_devs.c
+++ /dev/null
@@ -1,721 +0,0 @@
-/*
- * QEMU PowerPC 4xx embedded processors shared devices emulation
- *
- * Copyright (c) 2007 Jocelyn Mayer
- *
- * 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/hw.h"
-#include "hw/ppc.h"
-#include "hw/ppc4xx.h"
-#include "qemu/log.h"
-#include "exec/address-spaces.h"
-
-//#define DEBUG_MMIO
-//#define DEBUG_UNASSIGNED
-#define DEBUG_UIC
-
-
-#ifdef DEBUG_UIC
-#  define LOG_UIC(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
-#else
-#  define LOG_UIC(...) do { } while (0)
-#endif
-
-static void ppc4xx_reset(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-
-    cpu_reset(CPU(cpu));
-}
-
-/*****************************************************************************/
-/* Generic PowerPC 4xx processor instantiation */
-PowerPCCPU *ppc4xx_init(const char *cpu_model,
-                        clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
-                        uint32_t sysclk)
-{
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-
-    /* init CPUs */
-    cpu = cpu_ppc_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to find PowerPC %s CPU definition\n",
-                cpu_model);
-        exit(1);
-    }
-    env = &cpu->env;
-
-    cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
-    cpu_clk->opaque = env;
-    /* Set time-base frequency to sysclk */
-    tb_clk->cb = ppc_40x_timers_init(env, sysclk, PPC_INTERRUPT_PIT);
-    tb_clk->opaque = env;
-    ppc_dcr_init(env, NULL, NULL);
-    /* Register qemu callbacks */
-    qemu_register_reset(ppc4xx_reset, cpu);
-
-    return cpu;
-}
-
-/*****************************************************************************/
-/* "Universal" Interrupt controller */
-enum {
-    DCR_UICSR  = 0x000,
-    DCR_UICSRS = 0x001,
-    DCR_UICER  = 0x002,
-    DCR_UICCR  = 0x003,
-    DCR_UICPR  = 0x004,
-    DCR_UICTR  = 0x005,
-    DCR_UICMSR = 0x006,
-    DCR_UICVR  = 0x007,
-    DCR_UICVCR = 0x008,
-    DCR_UICMAX = 0x009,
-};
-
-#define UIC_MAX_IRQ 32
-typedef struct ppcuic_t ppcuic_t;
-struct ppcuic_t {
-    uint32_t dcr_base;
-    int use_vectors;
-    uint32_t level;  /* Remembers the state of level-triggered interrupts. */
-    uint32_t uicsr;  /* Status register */
-    uint32_t uicer;  /* Enable register */
-    uint32_t uiccr;  /* Critical register */
-    uint32_t uicpr;  /* Polarity register */
-    uint32_t uictr;  /* Triggering register */
-    uint32_t uicvcr; /* Vector configuration register */
-    uint32_t uicvr;
-    qemu_irq *irqs;
-};
-
-static void ppcuic_trigger_irq (ppcuic_t *uic)
-{
-    uint32_t ir, cr;
-    int start, end, inc, i;
-
-    /* Trigger interrupt if any is pending */
-    ir = uic->uicsr & uic->uicer & (~uic->uiccr);
-    cr = uic->uicsr & uic->uicer & uic->uiccr;
-    LOG_UIC("%s: uicsr %08" PRIx32 " uicer %08" PRIx32
-                " uiccr %08" PRIx32 "\n"
-                "   %08" PRIx32 " ir %08" PRIx32 " cr %08" PRIx32 "\n",
-                __func__, uic->uicsr, uic->uicer, uic->uiccr,
-                uic->uicsr & uic->uicer, ir, cr);
-    if (ir != 0x0000000) {
-        LOG_UIC("Raise UIC interrupt\n");
-        qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]);
-    } else {
-        LOG_UIC("Lower UIC interrupt\n");
-        qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]);
-    }
-    /* Trigger critical interrupt if any is pending and update vector */
-    if (cr != 0x0000000) {
-        qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]);
-        if (uic->use_vectors) {
-            /* Compute critical IRQ vector */
-            if (uic->uicvcr & 1) {
-                start = 31;
-                end = 0;
-                inc = -1;
-            } else {
-                start = 0;
-                end = 31;
-                inc = 1;
-            }
-            uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
-            for (i = start; i <= end; i += inc) {
-                if (cr & (1 << i)) {
-                    uic->uicvr += (i - start) * 512 * inc;
-                    break;
-                }
-            }
-        }
-        LOG_UIC("Raise UIC critical interrupt - "
-                    "vector %08" PRIx32 "\n", uic->uicvr);
-    } else {
-        LOG_UIC("Lower UIC critical interrupt\n");
-        qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]);
-        uic->uicvr = 0x00000000;
-    }
-}
-
-static void ppcuic_set_irq (void *opaque, int irq_num, int level)
-{
-    ppcuic_t *uic;
-    uint32_t mask, sr;
-
-    uic = opaque;
-    mask = 1 << (31-irq_num);
-    LOG_UIC("%s: irq %d level %d uicsr %08" PRIx32
-                " mask %08" PRIx32 " => %08" PRIx32 " %08" PRIx32 "\n",
-                __func__, irq_num, level,
-                uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
-    if (irq_num < 0 || irq_num > 31)
-        return;
-    sr = uic->uicsr;
-
-    /* Update status register */
-    if (uic->uictr & mask) {
-        /* Edge sensitive interrupt */
-        if (level == 1)
-            uic->uicsr |= mask;
-    } else {
-        /* Level sensitive interrupt */
-        if (level == 1) {
-            uic->uicsr |= mask;
-            uic->level |= mask;
-        } else {
-            uic->uicsr &= ~mask;
-            uic->level &= ~mask;
-        }
-    }
-    LOG_UIC("%s: irq %d level %d sr %" PRIx32 " => "
-                "%08" PRIx32 "\n", __func__, irq_num, level, uic->uicsr, sr);
-    if (sr != uic->uicsr)
-        ppcuic_trigger_irq(uic);
-}
-
-static uint32_t dcr_read_uic (void *opaque, int dcrn)
-{
-    ppcuic_t *uic;
-    uint32_t ret;
-
-    uic = opaque;
-    dcrn -= uic->dcr_base;
-    switch (dcrn) {
-    case DCR_UICSR:
-    case DCR_UICSRS:
-        ret = uic->uicsr;
-        break;
-    case DCR_UICER:
-        ret = uic->uicer;
-        break;
-    case DCR_UICCR:
-        ret = uic->uiccr;
-        break;
-    case DCR_UICPR:
-        ret = uic->uicpr;
-        break;
-    case DCR_UICTR:
-        ret = uic->uictr;
-        break;
-    case DCR_UICMSR:
-        ret = uic->uicsr & uic->uicer;
-        break;
-    case DCR_UICVR:
-        if (!uic->use_vectors)
-            goto no_read;
-        ret = uic->uicvr;
-        break;
-    case DCR_UICVCR:
-        if (!uic->use_vectors)
-            goto no_read;
-        ret = uic->uicvcr;
-        break;
-    default:
-    no_read:
-        ret = 0x00000000;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_uic (void *opaque, int dcrn, uint32_t val)
-{
-    ppcuic_t *uic;
-
-    uic = opaque;
-    dcrn -= uic->dcr_base;
-    LOG_UIC("%s: dcr %d val 0x%x\n", __func__, dcrn, val);
-    switch (dcrn) {
-    case DCR_UICSR:
-        uic->uicsr &= ~val;
-        uic->uicsr |= uic->level;
-        ppcuic_trigger_irq(uic);
-        break;
-    case DCR_UICSRS:
-        uic->uicsr |= val;
-        ppcuic_trigger_irq(uic);
-        break;
-    case DCR_UICER:
-        uic->uicer = val;
-        ppcuic_trigger_irq(uic);
-        break;
-    case DCR_UICCR:
-        uic->uiccr = val;
-        ppcuic_trigger_irq(uic);
-        break;
-    case DCR_UICPR:
-        uic->uicpr = val;
-        break;
-    case DCR_UICTR:
-        uic->uictr = val;
-        ppcuic_trigger_irq(uic);
-        break;
-    case DCR_UICMSR:
-        break;
-    case DCR_UICVR:
-        break;
-    case DCR_UICVCR:
-        uic->uicvcr = val & 0xFFFFFFFD;
-        ppcuic_trigger_irq(uic);
-        break;
-    }
-}
-
-static void ppcuic_reset (void *opaque)
-{
-    ppcuic_t *uic;
-
-    uic = opaque;
-    uic->uiccr = 0x00000000;
-    uic->uicer = 0x00000000;
-    uic->uicpr = 0x00000000;
-    uic->uicsr = 0x00000000;
-    uic->uictr = 0x00000000;
-    if (uic->use_vectors) {
-        uic->uicvcr = 0x00000000;
-        uic->uicvr = 0x0000000;
-    }
-}
-
-qemu_irq *ppcuic_init (CPUPPCState *env, qemu_irq *irqs,
-                       uint32_t dcr_base, int has_ssr, int has_vr)
-{
-    ppcuic_t *uic;
-    int i;
-
-    uic = g_malloc0(sizeof(ppcuic_t));
-    uic->dcr_base = dcr_base;
-    uic->irqs = irqs;
-    if (has_vr)
-        uic->use_vectors = 1;
-    for (i = 0; i < DCR_UICMAX; i++) {
-        ppc_dcr_register(env, dcr_base + i, uic,
-                         &dcr_read_uic, &dcr_write_uic);
-    }
-    qemu_register_reset(ppcuic_reset, uic);
-
-    return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
-}
-
-/*****************************************************************************/
-/* SDRAM controller */
-typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
-struct ppc4xx_sdram_t {
-    uint32_t addr;
-    int nbanks;
-    MemoryRegion containers[4]; /* used for clipping */
-    MemoryRegion *ram_memories;
-    hwaddr ram_bases[4];
-    hwaddr ram_sizes[4];
-    uint32_t besr0;
-    uint32_t besr1;
-    uint32_t bear;
-    uint32_t cfg;
-    uint32_t status;
-    uint32_t rtr;
-    uint32_t pmit;
-    uint32_t bcr[4];
-    uint32_t tr;
-    uint32_t ecccfg;
-    uint32_t eccesr;
-    qemu_irq irq;
-};
-
-enum {
-    SDRAM0_CFGADDR = 0x010,
-    SDRAM0_CFGDATA = 0x011,
-};
-
-/* XXX: TOFIX: some patches have made this code become inconsistent:
- *      there are type inconsistencies, mixing hwaddr, target_ulong
- *      and uint32_t
- */
-static uint32_t sdram_bcr (hwaddr ram_base,
-                           hwaddr ram_size)
-{
-    uint32_t bcr;
-
-    switch (ram_size) {
-    case (4 * 1024 * 1024):
-        bcr = 0x00000000;
-        break;
-    case (8 * 1024 * 1024):
-        bcr = 0x00020000;
-        break;
-    case (16 * 1024 * 1024):
-        bcr = 0x00040000;
-        break;
-    case (32 * 1024 * 1024):
-        bcr = 0x00060000;
-        break;
-    case (64 * 1024 * 1024):
-        bcr = 0x00080000;
-        break;
-    case (128 * 1024 * 1024):
-        bcr = 0x000A0000;
-        break;
-    case (256 * 1024 * 1024):
-        bcr = 0x000C0000;
-        break;
-    default:
-        printf("%s: invalid RAM size " TARGET_FMT_plx "\n", __func__,
-               ram_size);
-        return 0x00000000;
-    }
-    bcr |= ram_base & 0xFF800000;
-    bcr |= 1;
-
-    return bcr;
-}
-
-static inline hwaddr sdram_base(uint32_t bcr)
-{
-    return bcr & 0xFF800000;
-}
-
-static target_ulong sdram_size (uint32_t bcr)
-{
-    target_ulong size;
-    int sh;
-
-    sh = (bcr >> 17) & 0x7;
-    if (sh == 7)
-        size = -1;
-    else
-        size = (4 * 1024 * 1024) << sh;
-
-    return size;
-}
-
-static void sdram_set_bcr(ppc4xx_sdram_t *sdram,
-                          uint32_t *bcrp, uint32_t bcr, int enabled)
-{
-    unsigned n = bcrp - sdram->bcr;
-
-    if (*bcrp & 0x00000001) {
-        /* Unmap RAM */
-#ifdef DEBUG_SDRAM
-        printf("%s: unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
-               __func__, sdram_base(*bcrp), sdram_size(*bcrp));
-#endif
-        memory_region_del_subregion(get_system_memory(),
-                                    &sdram->containers[n]);
-        memory_region_del_subregion(&sdram->containers[n],
-                                    &sdram->ram_memories[n]);
-        memory_region_destroy(&sdram->containers[n]);
-    }
-    *bcrp = bcr & 0xFFDEE001;
-    if (enabled && (bcr & 0x00000001)) {
-#ifdef DEBUG_SDRAM
-        printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
-               __func__, sdram_base(bcr), sdram_size(bcr));
-#endif
-        memory_region_init(&sdram->containers[n], "sdram-containers",
-                           sdram_size(bcr));
-        memory_region_add_subregion(&sdram->containers[n], 0,
-                                    &sdram->ram_memories[n]);
-        memory_region_add_subregion(get_system_memory(),
-                                    sdram_base(bcr),
-                                    &sdram->containers[n]);
-    }
-}
-
-static void sdram_map_bcr (ppc4xx_sdram_t *sdram)
-{
-    int i;
-
-    for (i = 0; i < sdram->nbanks; i++) {
-        if (sdram->ram_sizes[i] != 0) {
-            sdram_set_bcr(sdram,
-                          &sdram->bcr[i],
-                          sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
-                          1);
-        } else {
-            sdram_set_bcr(sdram, &sdram->bcr[i], 0x00000000, 0);
-        }
-    }
-}
-
-static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
-{
-    int i;
-
-    for (i = 0; i < sdram->nbanks; i++) {
-#ifdef DEBUG_SDRAM
-        printf("%s: Unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
-               __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
-#endif
-        memory_region_del_subregion(get_system_memory(),
-                                    &sdram->ram_memories[i]);
-    }
-}
-
-static uint32_t dcr_read_sdram (void *opaque, int dcrn)
-{
-    ppc4xx_sdram_t *sdram;
-    uint32_t ret;
-
-    sdram = opaque;
-    switch (dcrn) {
-    case SDRAM0_CFGADDR:
-        ret = sdram->addr;
-        break;
-    case SDRAM0_CFGDATA:
-        switch (sdram->addr) {
-        case 0x00: /* SDRAM_BESR0 */
-            ret = sdram->besr0;
-            break;
-        case 0x08: /* SDRAM_BESR1 */
-            ret = sdram->besr1;
-            break;
-        case 0x10: /* SDRAM_BEAR */
-            ret = sdram->bear;
-            break;
-        case 0x20: /* SDRAM_CFG */
-            ret = sdram->cfg;
-            break;
-        case 0x24: /* SDRAM_STATUS */
-            ret = sdram->status;
-            break;
-        case 0x30: /* SDRAM_RTR */
-            ret = sdram->rtr;
-            break;
-        case 0x34: /* SDRAM_PMIT */
-            ret = sdram->pmit;
-            break;
-        case 0x40: /* SDRAM_B0CR */
-            ret = sdram->bcr[0];
-            break;
-        case 0x44: /* SDRAM_B1CR */
-            ret = sdram->bcr[1];
-            break;
-        case 0x48: /* SDRAM_B2CR */
-            ret = sdram->bcr[2];
-            break;
-        case 0x4C: /* SDRAM_B3CR */
-            ret = sdram->bcr[3];
-            break;
-        case 0x80: /* SDRAM_TR */
-            ret = -1; /* ? */
-            break;
-        case 0x94: /* SDRAM_ECCCFG */
-            ret = sdram->ecccfg;
-            break;
-        case 0x98: /* SDRAM_ECCESR */
-            ret = sdram->eccesr;
-            break;
-        default: /* Error */
-            ret = -1;
-            break;
-        }
-        break;
-    default:
-        /* Avoid gcc warning */
-        ret = 0x00000000;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val)
-{
-    ppc4xx_sdram_t *sdram;
-
-    sdram = opaque;
-    switch (dcrn) {
-    case SDRAM0_CFGADDR:
-        sdram->addr = val;
-        break;
-    case SDRAM0_CFGDATA:
-        switch (sdram->addr) {
-        case 0x00: /* SDRAM_BESR0 */
-            sdram->besr0 &= ~val;
-            break;
-        case 0x08: /* SDRAM_BESR1 */
-            sdram->besr1 &= ~val;
-            break;
-        case 0x10: /* SDRAM_BEAR */
-            sdram->bear = val;
-            break;
-        case 0x20: /* SDRAM_CFG */
-            val &= 0xFFE00000;
-            if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
-#ifdef DEBUG_SDRAM
-                printf("%s: enable SDRAM controller\n", __func__);
-#endif
-                /* validate all RAM mappings */
-                sdram_map_bcr(sdram);
-                sdram->status &= ~0x80000000;
-            } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
-#ifdef DEBUG_SDRAM
-                printf("%s: disable SDRAM controller\n", __func__);
-#endif
-                /* invalidate all RAM mappings */
-                sdram_unmap_bcr(sdram);
-                sdram->status |= 0x80000000;
-            }
-            if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
-                sdram->status |= 0x40000000;
-            else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
-                sdram->status &= ~0x40000000;
-            sdram->cfg = val;
-            break;
-        case 0x24: /* SDRAM_STATUS */
-            /* Read-only register */
-            break;
-        case 0x30: /* SDRAM_RTR */
-            sdram->rtr = val & 0x3FF80000;
-            break;
-        case 0x34: /* SDRAM_PMIT */
-            sdram->pmit = (val & 0xF8000000) | 0x07C00000;
-            break;
-        case 0x40: /* SDRAM_B0CR */
-            sdram_set_bcr(sdram, &sdram->bcr[0], val, sdram->cfg & 0x80000000);
-            break;
-        case 0x44: /* SDRAM_B1CR */
-            sdram_set_bcr(sdram, &sdram->bcr[1], val, sdram->cfg & 0x80000000);
-            break;
-        case 0x48: /* SDRAM_B2CR */
-            sdram_set_bcr(sdram, &sdram->bcr[2], val, sdram->cfg & 0x80000000);
-            break;
-        case 0x4C: /* SDRAM_B3CR */
-            sdram_set_bcr(sdram, &sdram->bcr[3], val, sdram->cfg & 0x80000000);
-            break;
-        case 0x80: /* SDRAM_TR */
-            sdram->tr = val & 0x018FC01F;
-            break;
-        case 0x94: /* SDRAM_ECCCFG */
-            sdram->ecccfg = val & 0x00F00000;
-            break;
-        case 0x98: /* SDRAM_ECCESR */
-            val &= 0xFFF0F000;
-            if (sdram->eccesr == 0 && val != 0)
-                qemu_irq_raise(sdram->irq);
-            else if (sdram->eccesr != 0 && val == 0)
-                qemu_irq_lower(sdram->irq);
-            sdram->eccesr = val;
-            break;
-        default: /* Error */
-            break;
-        }
-        break;
-    }
-}
-
-static void sdram_reset (void *opaque)
-{
-    ppc4xx_sdram_t *sdram;
-
-    sdram = opaque;
-    sdram->addr = 0x00000000;
-    sdram->bear = 0x00000000;
-    sdram->besr0 = 0x00000000; /* No error */
-    sdram->besr1 = 0x00000000; /* No error */
-    sdram->cfg = 0x00000000;
-    sdram->ecccfg = 0x00000000; /* No ECC */
-    sdram->eccesr = 0x00000000; /* No error */
-    sdram->pmit = 0x07C00000;
-    sdram->rtr = 0x05F00000;
-    sdram->tr = 0x00854009;
-    /* We pre-initialize RAM banks */
-    sdram->status = 0x00000000;
-    sdram->cfg = 0x00800000;
-}
-
-void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
-                        MemoryRegion *ram_memories,
-                        hwaddr *ram_bases,
-                        hwaddr *ram_sizes,
-                        int do_init)
-{
-    ppc4xx_sdram_t *sdram;
-
-    sdram = g_malloc0(sizeof(ppc4xx_sdram_t));
-    sdram->irq = irq;
-    sdram->nbanks = nbanks;
-    sdram->ram_memories = ram_memories;
-    memset(sdram->ram_bases, 0, 4 * sizeof(hwaddr));
-    memcpy(sdram->ram_bases, ram_bases,
-           nbanks * sizeof(hwaddr));
-    memset(sdram->ram_sizes, 0, 4 * sizeof(hwaddr));
-    memcpy(sdram->ram_sizes, ram_sizes,
-           nbanks * sizeof(hwaddr));
-    qemu_register_reset(&sdram_reset, sdram);
-    ppc_dcr_register(env, SDRAM0_CFGADDR,
-                     sdram, &dcr_read_sdram, &dcr_write_sdram);
-    ppc_dcr_register(env, SDRAM0_CFGDATA,
-                     sdram, &dcr_read_sdram, &dcr_write_sdram);
-    if (do_init)
-        sdram_map_bcr(sdram);
-}
-
-/* Fill in consecutive SDRAM banks with 'ram_size' bytes of memory.
- *
- * sdram_bank_sizes[] must be 0-terminated.
- *
- * The 4xx SDRAM controller supports a small number of banks, and each bank
- * must be one of a small set of sizes. The number of banks and the supported
- * sizes varies by SoC. */
-ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
-                               MemoryRegion ram_memories[],
-                               hwaddr ram_bases[],
-                               hwaddr ram_sizes[],
-                               const unsigned int sdram_bank_sizes[])
-{
-    ram_addr_t size_left = ram_size;
-    ram_addr_t base = 0;
-    int i;
-    int j;
-
-    for (i = 0; i < nr_banks; i++) {
-        for (j = 0; sdram_bank_sizes[j] != 0; j++) {
-            unsigned int bank_size = sdram_bank_sizes[j];
-
-            if (bank_size <= size_left) {
-                char name[32];
-                snprintf(name, sizeof(name), "ppc4xx.sdram%d", i);
-                memory_region_init_ram(&ram_memories[i], name, bank_size);
-                vmstate_register_ram_global(&ram_memories[i]);
-                ram_bases[i] = base;
-                ram_sizes[i] = bank_size;
-                base += bank_size;
-                size_left -= bank_size;
-                break;
-            }
-        }
-
-        if (!size_left) {
-            /* No need to use the remaining banks. */
-            break;
-        }
-    }
-
-    ram_size -= size_left;
-    if (size_left)
-        printf("Truncating memory to %d MiB to fit SDRAM controller limits.\n",
-               (int)(ram_size >> 20));
-
-    return ram_size;
-}
diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c
deleted file mode 100644
index d904fbe..0000000
--- a/hw/ppce500_spin.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * QEMU PowerPC e500v2 ePAPR spinning code
- *
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: 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/>.
- *
- * This code is not really a device, but models an interface that usually
- * firmware takes care of. It's used when QEMU plays the role of firmware.
- *
- * Specification:
- *
- * https://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.1.pdf
- *
- */
-
-#include "hw/hw.h"
-#include "sysemu/sysemu.h"
-#include "hw/sysbus.h"
-#include "sysemu/kvm.h"
-
-#define MAX_CPUS 32
-
-typedef struct spin_info {
-    uint64_t addr;
-    uint64_t r3;
-    uint32_t resv;
-    uint32_t pir;
-    uint64_t reserved;
-} QEMU_PACKED SpinInfo;
-
-typedef struct spin_state {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    SpinInfo spin[MAX_CPUS];
-} SpinState;
-
-typedef struct spin_kick {
-    PowerPCCPU *cpu;
-    SpinInfo *spin;
-} SpinKick;
-
-static void spin_reset(void *opaque)
-{
-    SpinState *s = opaque;
-    int i;
-
-    for (i = 0; i < MAX_CPUS; i++) {
-        SpinInfo *info = &s->spin[i];
-
-        info->pir = i;
-        info->r3 = i;
-        info->addr = 1;
-    }
-}
-
-/* Create -kernel TLB entries for BookE, linearly spanning 256MB.  */
-static inline hwaddr booke206_page_size_to_tlb(uint64_t size)
-{
-    return (ffs(size >> 10) - 1) >> 1;
-}
-
-static void mmubooke_create_initial_mapping(CPUPPCState *env,
-                                     target_ulong va,
-                                     hwaddr pa,
-                                     hwaddr len)
-{
-    ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 1);
-    hwaddr size;
-
-    size = (booke206_page_size_to_tlb(len) << MAS1_TSIZE_SHIFT);
-    tlb->mas1 = MAS1_VALID | size;
-    tlb->mas2 = (va & TARGET_PAGE_MASK) | MAS2_M;
-    tlb->mas7_3 = pa & TARGET_PAGE_MASK;
-    tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
-    env->tlb_dirty = true;
-}
-
-static void spin_kick(void *data)
-{
-    SpinKick *kick = data;
-    CPUState *cpu = CPU(kick->cpu);
-    CPUPPCState *env = &kick->cpu->env;
-    SpinInfo *curspin = kick->spin;
-    hwaddr map_size = 64 * 1024 * 1024;
-    hwaddr map_start;
-
-    cpu_synchronize_state(env);
-    stl_p(&curspin->pir, env->spr[SPR_PIR]);
-    env->nip = ldq_p(&curspin->addr) & (map_size - 1);
-    env->gpr[3] = ldq_p(&curspin->r3);
-    env->gpr[4] = 0;
-    env->gpr[5] = 0;
-    env->gpr[6] = 0;
-    env->gpr[7] = map_size;
-    env->gpr[8] = 0;
-    env->gpr[9] = 0;
-
-    map_start = ldq_p(&curspin->addr) & ~(map_size - 1);
-    mmubooke_create_initial_mapping(env, 0, map_start, map_size);
-
-    env->halted = 0;
-    env->exception_index = -1;
-    cpu->stopped = false;
-    qemu_cpu_kick(cpu);
-}
-
-static void spin_write(void *opaque, hwaddr addr, uint64_t value,
-                       unsigned len)
-{
-    SpinState *s = opaque;
-    int env_idx = addr / sizeof(SpinInfo);
-    CPUState *cpu;
-    SpinInfo *curspin = &s->spin[env_idx];
-    uint8_t *curspin_p = (uint8_t*)curspin;
-
-    cpu = qemu_get_cpu(env_idx);
-    if (cpu == NULL) {
-        /* Unknown CPU */
-        return;
-    }
-
-    if (cpu->cpu_index == 0) {
-        /* primary CPU doesn't spin */
-        return;
-    }
-
-    curspin_p = &curspin_p[addr % sizeof(SpinInfo)];
-    switch (len) {
-    case 1:
-        stb_p(curspin_p, value);
-        break;
-    case 2:
-        stw_p(curspin_p, value);
-        break;
-    case 4:
-        stl_p(curspin_p, value);
-        break;
-    }
-
-    if (!(ldq_p(&curspin->addr) & 1)) {
-        /* run CPU */
-        SpinKick kick = {
-            .cpu = POWERPC_CPU(cpu),
-            .spin = curspin,
-        };
-
-        run_on_cpu(cpu, spin_kick, &kick);
-    }
-}
-
-static uint64_t spin_read(void *opaque, hwaddr addr, unsigned len)
-{
-    SpinState *s = opaque;
-    uint8_t *spin_p = &((uint8_t*)s->spin)[addr];
-
-    switch (len) {
-    case 1:
-        return ldub_p(spin_p);
-    case 2:
-        return lduw_p(spin_p);
-    case 4:
-        return ldl_p(spin_p);
-    default:
-        hw_error("ppce500: unexpected %s with len = %u", __func__, len);
-    }
-}
-
-static const MemoryRegionOps spin_rw_ops = {
-    .read = spin_read,
-    .write = spin_write,
-    .endianness = DEVICE_BIG_ENDIAN,
-};
-
-static int ppce500_spin_initfn(SysBusDevice *dev)
-{
-    SpinState *s;
-
-    s = FROM_SYSBUS(SpinState, SYS_BUS_DEVICE(dev));
-
-    memory_region_init_io(&s->iomem, &spin_rw_ops, s, "e500 spin pv device",
-                          sizeof(SpinInfo) * MAX_CPUS);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    qemu_register_reset(spin_reset, s);
-
-    return 0;
-}
-
-static void ppce500_spin_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = ppce500_spin_initfn;
-}
-
-static const TypeInfo ppce500_spin_info = {
-    .name          = "e500-spin",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(SpinState),
-    .class_init    = ppce500_spin_class_init,
-};
-
-static void ppce500_spin_register_types(void)
-{
-    type_register_static(&ppce500_spin_info);
-}
-
-type_init(ppce500_spin_register_types)
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
deleted file mode 100644
index 6eb3ab5..0000000
--- a/hw/spapr_vio.c
+++ /dev/null
@@ -1,649 +0,0 @@
-/*
- * 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/hw.h"
-#include "sysemu/sysemu.h"
-#include "hw/boards.h"
-#include "monitor/monitor.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "hw/sysbus.h"
-#include "sysemu/kvm.h"
-#include "sysemu/device_tree.h"
-#include "kvm_ppc.h"
-
-#include "hw/spapr.h"
-#include "hw/spapr_vio.h"
-#include "hw/xics.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 Property spapr_vio_props[] = {
-    DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, irq, 0), \
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static const TypeInfo spapr_vio_bus_info = {
-    .name = TYPE_SPAPR_VIO_BUS,
-    .parent = TYPE_BUS,
-    .instance_size = sizeof(VIOsPAPRBus),
-};
-
-VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
-{
-    BusChild *kid;
-    VIOsPAPRDevice *dev = NULL;
-
-    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
-        dev = (VIOsPAPRDevice *)kid->child;
-        if (dev->reg == reg) {
-            return dev;
-        }
-    }
-
-    return NULL;
-}
-
-static char *vio_format_dev_name(VIOsPAPRDevice *dev)
-{
-    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
-    char *name;
-
-    /* Device tree style name device at reg */
-    name = g_strdup_printf("%s@%x", pc->dt_name, dev->reg);
-
-    return name;
-}
-
-#ifdef CONFIG_FDT
-static int vio_make_devnode(VIOsPAPRDevice *dev,
-                            void *fdt)
-{
-    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
-    int vdevice_off, node_off, ret;
-    char *dt_name;
-
-    vdevice_off = fdt_path_offset(fdt, "/vdevice");
-    if (vdevice_off < 0) {
-        return vdevice_off;
-    }
-
-    dt_name = vio_format_dev_name(dev);
-    node_off = fdt_add_subnode(fdt, vdevice_off, dt_name);
-    g_free(dt_name);
-    if (node_off < 0) {
-        return node_off;
-    }
-
-    ret = fdt_setprop_cell(fdt, node_off, "reg", dev->reg);
-    if (ret < 0) {
-        return ret;
-    }
-
-    if (pc->dt_type) {
-        ret = fdt_setprop_string(fdt, node_off, "device_type",
-                                 pc->dt_type);
-        if (ret < 0) {
-            return ret;
-        }
-    }
-
-    if (pc->dt_compatible) {
-        ret = fdt_setprop_string(fdt, node_off, "compatible",
-                                 pc->dt_compatible);
-        if (ret < 0) {
-            return ret;
-        }
-    }
-
-    if (dev->irq) {
-        uint32_t ints_prop[] = {cpu_to_be32(dev->irq), 0};
-
-        ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop,
-                          sizeof(ints_prop));
-        if (ret < 0) {
-            return ret;
-        }
-    }
-
-    ret = spapr_tcet_dma_dt(fdt, node_off, "ibm,my-dma-window", dev->dma);
-    if (ret < 0) {
-        return ret;
-    }
-
-    if (pc->devnode) {
-        ret = (pc->devnode)(dev, fdt, node_off);
-        if (ret < 0) {
-            return ret;
-        }
-    }
-
-    return node_off;
-}
-#endif /* CONFIG_FDT */
-
-/*
- * CRQ handling
- */
-static target_ulong h_reg_crq(PowerPCCPU *cpu, 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("Unit 0x" TARGET_FMT_lx " does not exist\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("Queue size too small or too big (0x" TARGET_FMT_lx
-                      ")\n", queue_len);
-        return H_PARAMETER;
-    }
-
-    /* Check queue alignment */
-    if (queue_addr & 0xfff) {
-        hcall_dprintf("Queue not aligned (0x" TARGET_FMT_lx ")\n", queue_addr);
-        return H_PARAMETER;
-    }
-
-    /* Check if device supports CRQs */
-    if (!dev->crq.SendFunc) {
-        hcall_dprintf("Device does not support CRQ\n");
-        return H_NOT_FOUND;
-    }
-
-    /* Already a queue ? */
-    if (dev->crq.qsize) {
-        hcall_dprintf("CRQ already registered\n");
-        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 free_crq(VIOsPAPRDevice *dev)
-{
-    dev->crq.qladdr = 0;
-    dev->crq.qsize = 0;
-    dev->crq.qnext = 0;
-
-    dprintf("CRQ for dev 0x%" PRIx32 " freed\n", dev->reg);
-
-    return H_SUCCESS;
-}
-
-static target_ulong h_free_crq(PowerPCCPU *cpu, 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("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
-        return H_PARAMETER;
-    }
-
-    return free_crq(dev);
-}
-
-static target_ulong h_send_crq(PowerPCCPU *cpu, 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("Unit 0x" TARGET_FMT_lx " does not exist\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(PowerPCCPU *cpu, 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("Unit 0x" TARGET_FMT_lx " does not exist\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_vio_dma_read(dev, dev->crq.qladdr + dev->crq.qnext, &byte, 1);
-    if (rc) {
-        return rc;
-    }
-    if (byte != 0) {
-        return 1;
-    }
-
-    rc = spapr_vio_dma_write(dev, dev->crq.qladdr + dev->crq.qnext + 8,
-                             &crq[8], 8);
-    if (rc) {
-        return rc;
-    }
-
-    kvmppc_eieio();
-
-    rc = spapr_vio_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(spapr_vio_qirq(dev));
-    }
-
-    return 0;
-}
-
-/* "quiesce" handling */
-
-static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev)
-{
-    if (dev->dma) {
-        spapr_tce_reset(dev->dma);
-    }
-    free_crq(dev);
-}
-
-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 (!dev->dma) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    spapr_tce_set_bypass(dev->dma, !!enable);
-
-    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;
-    BusChild *kid;
-    VIOsPAPRDevice *dev = NULL;
-
-    if (nargs != 0) {
-        rtas_st(rets, 0, -3);
-        return;
-    }
-
-    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
-        dev = (VIOsPAPRDevice *)kid->child;
-        spapr_vio_quiesce_one(dev);
-    }
-
-    rtas_st(rets, 0, 0);
-}
-
-static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
-{
-    VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
-    BusChild *kid;
-    VIOsPAPRDevice *other;
-
-    /*
-     * Check for a device other than the given one which is already
-     * using the requested address. We have to open code this because
-     * the given dev might already be in the list.
-     */
-    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
-        other = DO_UPCAST(VIOsPAPRDevice, qdev, kid->child);
-
-        if (other != dev && other->reg == dev->reg) {
-            return other;
-        }
-    }
-
-    return 0;
-}
-
-static void spapr_vio_busdev_reset(DeviceState *qdev)
-{
-    VIOsPAPRDevice *dev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
-    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
-
-    /* Shut down the request queue and TCEs if necessary */
-    spapr_vio_quiesce_one(dev);
-
-    dev->signal_state = 0;
-
-    if (pc->reset) {
-        pc->reset(dev);
-    }
-}
-
-static int spapr_vio_busdev_init(DeviceState *qdev)
-{
-    VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
-    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
-    char *id;
-
-    if (dev->reg != -1) {
-        /*
-         * Explicitly assigned address, just verify that no-one else
-         * is using it.  other mechanism). We have to open code this
-         * rather than using spapr_vio_find_by_reg() because sdev
-         * itself is already in the list.
-         */
-        VIOsPAPRDevice *other = reg_conflict(dev);
-
-        if (other) {
-            fprintf(stderr, "vio: %s and %s devices conflict at address %#x\n",
-                    object_get_typename(OBJECT(qdev)),
-                    object_get_typename(OBJECT(&other->qdev)),
-                    dev->reg);
-            return -1;
-        }
-    } else {
-        /* Need to assign an address */
-        VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
-
-        do {
-            dev->reg = bus->next_reg++;
-        } while (reg_conflict(dev));
-    }
-
-    /* Don't overwrite ids assigned on the command line */
-    if (!dev->qdev.id) {
-        id = vio_format_dev_name(dev);
-        dev->qdev.id = id;
-    }
-
-    dev->irq = spapr_allocate_msi(dev->irq);
-    if (!dev->irq) {
-        return -1;
-    }
-
-    if (pc->rtce_window_size) {
-        uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
-        dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size);
-    }
-
-    return pc->init(dev);
-}
-
-static target_ulong h_vio_signal(PowerPCCPU *cpu, 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);
-    VIOsPAPRDeviceClass *pc;
-
-    if (!dev) {
-        return H_PARAMETER;
-    }
-
-    pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
-
-    if (mode & ~pc->signal_mask) {
-        return H_PARAMETER;
-    }
-
-    dev->signal_state = mode;
-
-    return H_SUCCESS;
-}
-
-VIOsPAPRBus *spapr_vio_bus_init(void)
-{
-    VIOsPAPRBus *bus;
-    BusState *qbus;
-    DeviceState *dev;
-
-    /* Create bridge device */
-    dev = qdev_create(NULL, "spapr-vio-bridge");
-    qdev_init_nofail(dev);
-
-    /* Create bus on bridge device */
-
-    qbus = qbus_create(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio");
-    bus = DO_UPCAST(VIOsPAPRBus, bus, qbus);
-    bus->next_reg = 0x71000000;
-
-    /* hcall-vio */
-    spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);
-
-    /* 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);
-
-    /* RTAS calls */
-    spapr_rtas_register("ibm,set-tce-bypass", rtas_set_tce_bypass);
-    spapr_rtas_register("quiesce", rtas_quiesce);
-
-    return bus;
-}
-
-/* Represents sPAPR hcall VIO devices */
-
-static int spapr_vio_bridge_init(SysBusDevice *dev)
-{
-    /* nothing */
-    return 0;
-}
-
-static void spapr_vio_bridge_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = spapr_vio_bridge_init;
-    dc->no_user = 1;
-}
-
-static const TypeInfo spapr_vio_bridge_info = {
-    .name          = "spapr-vio-bridge",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(SysBusDevice),
-    .class_init    = spapr_vio_bridge_class_init,
-};
-
-static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *k = DEVICE_CLASS(klass);
-    k->init = spapr_vio_busdev_init;
-    k->reset = spapr_vio_busdev_reset;
-    k->bus_type = TYPE_SPAPR_VIO_BUS;
-    k->props = spapr_vio_props;
-}
-
-static const TypeInfo spapr_vio_type_info = {
-    .name = TYPE_VIO_SPAPR_DEVICE,
-    .parent = TYPE_DEVICE,
-    .instance_size = sizeof(VIOsPAPRDevice),
-    .abstract = true,
-    .class_size = sizeof(VIOsPAPRDeviceClass),
-    .class_init = vio_spapr_device_class_init,
-};
-
-static void spapr_vio_register_types(void)
-{
-    type_register_static(&spapr_vio_bus_info);
-    type_register_static(&spapr_vio_bridge_info);
-    type_register_static(&spapr_vio_type_info);
-}
-
-type_init(spapr_vio_register_types)
-
-#ifdef CONFIG_FDT
-static int compare_reg(const void *p1, const void *p2)
-{
-    VIOsPAPRDevice const *dev1, *dev2;
-
-    dev1 = (VIOsPAPRDevice *)*(DeviceState **)p1;
-    dev2 = (VIOsPAPRDevice *)*(DeviceState **)p2;
-
-    if (dev1->reg < dev2->reg) {
-        return -1;
-    }
-    if (dev1->reg == dev2->reg) {
-        return 0;
-    }
-
-    /* dev1->reg > dev2->reg */
-    return 1;
-}
-
-int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt)
-{
-    DeviceState *qdev, **qdevs;
-    BusChild *kid;
-    int i, num, ret = 0;
-
-    /* Count qdevs on the bus list */
-    num = 0;
-    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
-        num++;
-    }
-
-    /* Copy out into an array of pointers */
-    qdevs = g_malloc(sizeof(qdev) * num);
-    num = 0;
-    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
-        qdevs[num++] = kid->child;
-    }
-
-    /* Sort the array */
-    qsort(qdevs, num, sizeof(qdev), compare_reg);
-
-    /* Hack alert. Give the devices to libfdt in reverse order, we happen
-     * to know that will mean they are in forward order in the tree. */
-    for (i = num - 1; i >= 0; i--) {
-        VIOsPAPRDevice *dev = (VIOsPAPRDevice *)(qdevs[i]);
-
-        ret = vio_make_devnode(dev, fdt);
-
-        if (ret < 0) {
-            goto out;
-        }
-    }
-
-    ret = 0;
-out:
-    free(qdevs);
-
-    return ret;
-}
-
-int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus)
-{
-    VIOsPAPRDevice *dev;
-    char *name, *path;
-    int ret, offset;
-
-    dev = spapr_vty_get_default(bus);
-    if (!dev)
-        return 0;
-
-    offset = fdt_path_offset(fdt, "/chosen");
-    if (offset < 0) {
-        return offset;
-    }
-
-    name = vio_format_dev_name(dev);
-    path = g_strdup_printf("/vdevice/%s", name);
-
-    ret = fdt_setprop_string(fdt, offset, "linux,stdout-path", path);
-
-    g_free(name);
-    g_free(path);
-
-    return ret;
-}
-#endif /* CONFIG_FDT */
diff --git a/hw/xics.c b/hw/xics.c
deleted file mode 100644
index c3ef12f..0000000
--- a/hw/xics.c
+++ /dev/null
@@ -1,588 +0,0 @@
-/*
- * 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/hw.h"
-#include "trace.h"
-#include "hw/spapr.h"
-#include "hw/xics.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;
-    }
-
-    trace_xics_icp_check_ipi(server, ss->mfrr);
-
-    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 server, uint8_t mfrr)
-{
-    struct icp_server_state *ss = icp->ss + server;
-
-    ss->mfrr = mfrr;
-    if (mfrr < CPPR(ss)) {
-        icp_check_ipi(icp, server);
-    }
-}
-
-static uint32_t icp_accept(struct icp_server_state *ss)
-{
-    uint32_t xirr = ss->xirr;
-
-    qemu_irq_lower(ss->output);
-    ss->xirr = ss->pending_priority << 24;
-
-    trace_xics_icp_accept(xirr, ss->xirr);
-
-    return xirr;
-}
-
-static void icp_eoi(struct icp_state *icp, int server, uint32_t xirr)
-{
-    struct icp_server_state *ss = icp->ss + server;
-
-    /* Send EOI -> ICS */
-    ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
-    trace_xics_icp_eoi(server, xirr, ss->xirr);
-    ics_eoi(icp->ics, xirr & XISR_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;
-
-    trace_xics_icp_irq(server, nr, priority);
-
-    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;
-        trace_xics_icp_raise(ss->xirr, ss->pending_priority);
-        qemu_irq_raise(ss->output);
-    }
-}
-
-/*
- * ICS: Source layer
- */
-
-struct ics_irq_state {
-    int server;
-    uint8_t priority;
-    uint8_t saved_priority;
-#define XICS_STATUS_ASSERTED           0x1
-#define XICS_STATUS_SENT               0x2
-#define XICS_STATUS_REJECTED           0x4
-#define XICS_STATUS_MASKED_PENDING     0x8
-    uint8_t status;
-};
-
-struct ics_state {
-    int nr_irqs;
-    int offset;
-    qemu_irq *qirqs;
-    bool *islsi;
-    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 resend_msi(struct ics_state *ics, int srcno)
-{
-    struct ics_irq_state *irq = ics->irqs + srcno;
-
-    /* FIXME: filter by server#? */
-    if (irq->status & XICS_STATUS_REJECTED) {
-        irq->status &= ~XICS_STATUS_REJECTED;
-        if (irq->priority != 0xff) {
-            icp_irq(ics->icp, irq->server, srcno + ics->offset,
-                    irq->priority);
-        }
-    }
-}
-
-static void resend_lsi(struct ics_state *ics, int srcno)
-{
-    struct ics_irq_state *irq = ics->irqs + srcno;
-
-    if ((irq->priority != 0xff)
-        && (irq->status & XICS_STATUS_ASSERTED)
-        && !(irq->status & XICS_STATUS_SENT)) {
-        irq->status |= XICS_STATUS_SENT;
-        icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
-    }
-}
-
-static void set_irq_msi(struct ics_state *ics, int srcno, int val)
-{
-    struct ics_irq_state *irq = ics->irqs + srcno;
-
-    trace_xics_set_irq_msi(srcno, srcno + ics->offset);
-
-    if (val) {
-        if (irq->priority == 0xff) {
-            irq->status |= XICS_STATUS_MASKED_PENDING;
-            trace_xics_masked_pending();
-        } else  {
-            icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
-        }
-    }
-}
-
-static void set_irq_lsi(struct ics_state *ics, int srcno, int val)
-{
-    struct ics_irq_state *irq = ics->irqs + srcno;
-
-    trace_xics_set_irq_lsi(srcno, srcno + ics->offset);
-    if (val) {
-        irq->status |= XICS_STATUS_ASSERTED;
-    } else {
-        irq->status &= ~XICS_STATUS_ASSERTED;
-    }
-    resend_lsi(ics, srcno);
-}
-
-static void ics_set_irq(void *opaque, int srcno, int val)
-{
-    struct ics_state *ics = (struct ics_state *)opaque;
-
-    if (ics->islsi[srcno]) {
-        set_irq_lsi(ics, srcno, val);
-    } else {
-        set_irq_msi(ics, srcno, val);
-    }
-}
-
-static void write_xive_msi(struct ics_state *ics, int srcno)
-{
-    struct ics_irq_state *irq = ics->irqs + srcno;
-
-    if (!(irq->status & XICS_STATUS_MASKED_PENDING)
-        || (irq->priority == 0xff)) {
-        return;
-    }
-
-    irq->status &= ~XICS_STATUS_MASKED_PENDING;
-    icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
-}
-
-static void write_xive_lsi(struct ics_state *ics, int srcno)
-{
-    resend_lsi(ics, srcno);
-}
-
-static void ics_write_xive(struct ics_state *ics, int nr, int server,
-                           uint8_t priority, uint8_t saved_priority)
-{
-    int srcno = nr - ics->offset;
-    struct ics_irq_state *irq = ics->irqs + srcno;
-
-    irq->server = server;
-    irq->priority = priority;
-    irq->saved_priority = saved_priority;
-
-    trace_xics_ics_write_xive(nr, srcno, server, priority);
-
-    if (ics->islsi[srcno]) {
-        write_xive_lsi(ics, srcno);
-    } else {
-        write_xive_msi(ics, srcno);
-    }
-}
-
-static void ics_reject(struct ics_state *ics, int nr)
-{
-    struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
-
-    trace_xics_ics_reject(nr, nr - ics->offset);
-    irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */
-    irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */
-}
-
-static void ics_resend(struct ics_state *ics)
-{
-    int i;
-
-    for (i = 0; i < ics->nr_irqs; i++) {
-        /* FIXME: filter by server#? */
-        if (ics->islsi[i]) {
-            resend_lsi(ics, i);
-        } else {
-            resend_msi(ics, i);
-        }
-    }
-}
-
-static void ics_eoi(struct ics_state *ics, int nr)
-{
-    int srcno = nr - ics->offset;
-    struct ics_irq_state *irq = ics->irqs + srcno;
-
-    trace_xics_ics_eoi(nr);
-
-    if (ics->islsi[srcno]) {
-        irq->status &= ~XICS_STATUS_SENT;
-    }
-}
-
-/*
- * Exported functions
- */
-
-qemu_irq xics_get_qirq(struct icp_state *icp, int irq)
-{
-    if (!ics_valid_irq(icp->ics, irq)) {
-        return NULL;
-    }
-
-    return icp->ics->qirqs[irq - icp->ics->offset];
-}
-
-void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi)
-{
-    assert(ics_valid_irq(icp->ics, irq));
-
-    icp->ics->islsi[irq - icp->ics->offset] = lsi;
-}
-
-static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                           target_ulong opcode, target_ulong *args)
-{
-    CPUState *cs = CPU(cpu);
-    target_ulong cppr = args[0];
-
-    icp_set_cppr(spapr->icp, cs->cpu_index, cppr);
-    return H_SUCCESS;
-}
-
-static target_ulong h_ipi(PowerPCCPU *cpu, 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(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                           target_ulong opcode, target_ulong *args)
-{
-    CPUState *cs = CPU(cpu);
-    uint32_t xirr = icp_accept(spapr->icp->ss + cs->cpu_index);
-
-    args[0] = xirr;
-    return H_SUCCESS;
-}
-
-static target_ulong h_eoi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
-                          target_ulong opcode, target_ulong *args)
-{
-    CPUState *cs = CPU(cpu);
-    target_ulong xirr = args[0];
-
-    icp_eoi(spapr->icp, cs->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(ics, nr, server, priority, 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;
-    }
-
-    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
-                   ics->irqs[nr - ics->offset].priority);
-
-    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;
-    }
-
-    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
-                   ics->irqs[nr - ics->offset].saved_priority,
-                   ics->irqs[nr - ics->offset].saved_priority);
-
-    rtas_st(rets, 0, 0); /* Success */
-}
-
-static void xics_reset(void *opaque)
-{
-    struct icp_state *icp = (struct icp_state *)opaque;
-    struct ics_state *ics = icp->ics;
-    int i;
-
-    for (i = 0; i < icp->nr_servers; i++) {
-        icp->ss[i].xirr = 0;
-        icp->ss[i].pending_priority = 0xff;
-        icp->ss[i].mfrr = 0xff;
-        /* Make all outputs are deasserted */
-        qemu_set_irq(icp->ss[i].output, 0);
-    }
-
-    memset(ics->irqs, 0, sizeof(struct ics_irq_state) * ics->nr_irqs);
-    for (i = 0; i < ics->nr_irqs; i++) {
-        ics->irqs[i].priority = 0xff;
-        ics->irqs[i].saved_priority = 0xff;
-    }
-}
-
-struct icp_state *xics_system_init(int nr_irqs)
-{
-    CPUPPCState *env;
-    CPUState *cpu;
-    int max_server_num;
-    struct icp_state *icp;
-    struct ics_state *ics;
-
-    max_server_num = -1;
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu = CPU(ppc_env_get_cpu(env));
-        if (cpu->cpu_index > max_server_num) {
-            max_server_num = cpu->cpu_index;
-        }
-    }
-
-    icp = g_malloc0(sizeof(*icp));
-    icp->nr_servers = max_server_num + 1;
-    icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state));
-
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu = CPU(ppc_env_get_cpu(env));
-        struct icp_server_state *ss = &icp->ss[cpu->cpu_index];
-
-        switch (PPC_INPUT(env)) {
-        case PPC_FLAGS_INPUT_POWER7:
-            ss->output = env->irq_inputs[POWER7_INPUT_INT];
-            break;
-
-        case PPC_FLAGS_INPUT_970:
-            ss->output = env->irq_inputs[PPC970_INPUT_INT];
-            break;
-
-        default:
-            hw_error("XICS interrupt model does not support this CPU bus "
-                     "model\n");
-            exit(1);
-        }
-    }
-
-    ics = g_malloc0(sizeof(*ics));
-    ics->nr_irqs = nr_irqs;
-    ics->offset = XICS_IRQ_BASE;
-    ics->irqs = g_malloc0(nr_irqs * sizeof(struct ics_irq_state));
-    ics->islsi = g_malloc0(nr_irqs * sizeof(bool));
-
-    icp->ics = ics;
-    ics->icp = icp;
-
-    ics->qirqs = qemu_allocate_irqs(ics_set_irq, 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);
-
-    qemu_register_reset(xics_reset, icp);
-
-    return icp;
-}
commit 9743b581a819a05668e6a1f60e3ee6486d25f141
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Feb 5 15:22:56 2013 +0100

    m68k: move files referencing CPU to hw/m68k/
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/m68k/Makefile.objs b/hw/m68k/Makefile.objs
index 7c033a8..ede32a7 100644
--- a/hw/m68k/Makefile.objs
+++ b/hw/m68k/Makefile.objs
@@ -1,7 +1,8 @@
-obj-y = mcf5206.o mcf_uart.o mcf_intc.o mcf_fec.o
+obj-y = mcf_uart.o mcf_fec.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
 obj-y += an5206.o mcf5208.o
 obj-y += dummy_m68k.o
 
+obj-y += mcf5206.o mcf_intc.o
diff --git a/hw/m68k/mcf5206.c b/hw/m68k/mcf5206.c
new file mode 100644
index 0000000..58cd8d4
--- /dev/null
+++ b/hw/m68k/mcf5206.c
@@ -0,0 +1,548 @@
+/*
+ * Motorola ColdFire MCF5206 SoC embedded peripheral emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licensed under the GPL
+ */
+#include "hw/hw.h"
+#include "hw/mcf.h"
+#include "qemu/timer.h"
+#include "hw/ptimer.h"
+#include "sysemu/sysemu.h"
+#include "exec/address-spaces.h"
+
+/* General purpose timer module.  */
+typedef struct {
+    uint16_t tmr;
+    uint16_t trr;
+    uint16_t tcr;
+    uint16_t ter;
+    ptimer_state *timer;
+    qemu_irq irq;
+    int irq_state;
+} m5206_timer_state;
+
+#define TMR_RST 0x01
+#define TMR_CLK 0x06
+#define TMR_FRR 0x08
+#define TMR_ORI 0x10
+#define TMR_OM  0x20
+#define TMR_CE  0xc0
+
+#define TER_CAP 0x01
+#define TER_REF 0x02
+
+static void m5206_timer_update(m5206_timer_state *s)
+{
+    if ((s->tmr & TMR_ORI) != 0 && (s->ter & TER_REF))
+        qemu_irq_raise(s->irq);
+    else
+        qemu_irq_lower(s->irq);
+}
+
+static void m5206_timer_reset(m5206_timer_state *s)
+{
+    s->tmr = 0;
+    s->trr = 0;
+}
+
+static void m5206_timer_recalibrate(m5206_timer_state *s)
+{
+    int prescale;
+    int mode;
+
+    ptimer_stop(s->timer);
+
+    if ((s->tmr & TMR_RST) == 0)
+        return;
+
+    prescale = (s->tmr >> 8) + 1;
+    mode = (s->tmr >> 1) & 3;
+    if (mode == 2)
+        prescale *= 16;
+
+    if (mode == 3 || mode == 0)
+        hw_error("m5206_timer: mode %d not implemented\n", mode);
+    if ((s->tmr & TMR_FRR) == 0)
+        hw_error("m5206_timer: free running mode not implemented\n");
+
+    /* Assume 66MHz system clock.  */
+    ptimer_set_freq(s->timer, 66000000 / prescale);
+
+    ptimer_set_limit(s->timer, s->trr, 0);
+
+    ptimer_run(s->timer, 0);
+}
+
+static void m5206_timer_trigger(void *opaque)
+{
+    m5206_timer_state *s = (m5206_timer_state *)opaque;
+    s->ter |= TER_REF;
+    m5206_timer_update(s);
+}
+
+static uint32_t m5206_timer_read(m5206_timer_state *s, uint32_t addr)
+{
+    switch (addr) {
+    case 0:
+        return s->tmr;
+    case 4:
+        return s->trr;
+    case 8:
+        return s->tcr;
+    case 0xc:
+        return s->trr - ptimer_get_count(s->timer);
+    case 0x11:
+        return s->ter;
+    default:
+        return 0;
+    }
+}
+
+static void m5206_timer_write(m5206_timer_state *s, uint32_t addr, uint32_t val)
+{
+    switch (addr) {
+    case 0:
+        if ((s->tmr & TMR_RST) != 0 && (val & TMR_RST) == 0) {
+            m5206_timer_reset(s);
+        }
+        s->tmr = val;
+        m5206_timer_recalibrate(s);
+        break;
+    case 4:
+        s->trr = val;
+        m5206_timer_recalibrate(s);
+        break;
+    case 8:
+        s->tcr = val;
+        break;
+    case 0xc:
+        ptimer_set_count(s->timer, val);
+        break;
+    case 0x11:
+        s->ter &= ~val;
+        break;
+    default:
+        break;
+    }
+    m5206_timer_update(s);
+}
+
+static m5206_timer_state *m5206_timer_init(qemu_irq irq)
+{
+    m5206_timer_state *s;
+    QEMUBH *bh;
+
+    s = (m5206_timer_state *)g_malloc0(sizeof(m5206_timer_state));
+    bh = qemu_bh_new(m5206_timer_trigger, s);
+    s->timer = ptimer_init(bh);
+    s->irq = irq;
+    m5206_timer_reset(s);
+    return s;
+}
+
+/* System Integration Module.  */
+
+typedef struct {
+    M68kCPU *cpu;
+    MemoryRegion iomem;
+    m5206_timer_state *timer[2];
+    void *uart[2];
+    uint8_t scr;
+    uint8_t icr[14];
+    uint16_t imr; /* 1 == interrupt is masked.  */
+    uint16_t ipr;
+    uint8_t rsr;
+    uint8_t swivr;
+    uint8_t par;
+    /* Include the UART vector registers here.  */
+    uint8_t uivr[2];
+} m5206_mbar_state;
+
+/* Interrupt controller.  */
+
+static int m5206_find_pending_irq(m5206_mbar_state *s)
+{
+    int level;
+    int vector;
+    uint16_t active;
+    int i;
+
+    level = 0;
+    vector = 0;
+    active = s->ipr & ~s->imr;
+    if (!active)
+        return 0;
+
+    for (i = 1; i < 14; i++) {
+        if (active & (1 << i)) {
+            if ((s->icr[i] & 0x1f) > level) {
+                level = s->icr[i] & 0x1f;
+                vector = i;
+            }
+        }
+    }
+
+    if (level < 4)
+        vector = 0;
+
+    return vector;
+}
+
+static void m5206_mbar_update(m5206_mbar_state *s)
+{
+    int irq;
+    int vector;
+    int level;
+
+    irq = m5206_find_pending_irq(s);
+    if (irq) {
+        int tmp;
+        tmp = s->icr[irq];
+        level = (tmp >> 2) & 7;
+        if (tmp & 0x80) {
+            /* Autovector.  */
+            vector = 24 + level;
+        } else {
+            switch (irq) {
+            case 8: /* SWT */
+                vector = s->swivr;
+                break;
+            case 12: /* UART1 */
+                vector = s->uivr[0];
+                break;
+            case 13: /* UART2 */
+                vector = s->uivr[1];
+                break;
+            default:
+                /* Unknown vector.  */
+                fprintf(stderr, "Unhandled vector for IRQ %d\n", irq);
+                vector = 0xf;
+                break;
+            }
+        }
+    } else {
+        level = 0;
+        vector = 0;
+    }
+    m68k_set_irq_level(s->cpu, level, vector);
+}
+
+static void m5206_mbar_set_irq(void *opaque, int irq, int level)
+{
+    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
+    if (level) {
+        s->ipr |= 1 << irq;
+    } else {
+        s->ipr &= ~(1 << irq);
+    }
+    m5206_mbar_update(s);
+}
+
+/* System Integration Module.  */
+
+static void m5206_mbar_reset(m5206_mbar_state *s)
+{
+    s->scr = 0xc0;
+    s->icr[1] = 0x04;
+    s->icr[2] = 0x08;
+    s->icr[3] = 0x0c;
+    s->icr[4] = 0x10;
+    s->icr[5] = 0x14;
+    s->icr[6] = 0x18;
+    s->icr[7] = 0x1c;
+    s->icr[8] = 0x1c;
+    s->icr[9] = 0x80;
+    s->icr[10] = 0x80;
+    s->icr[11] = 0x80;
+    s->icr[12] = 0x00;
+    s->icr[13] = 0x00;
+    s->imr = 0x3ffe;
+    s->rsr = 0x80;
+    s->swivr = 0x0f;
+    s->par = 0;
+}
+
+static uint64_t m5206_mbar_read(m5206_mbar_state *s,
+                                uint64_t offset, unsigned size)
+{
+    if (offset >= 0x100 && offset < 0x120) {
+        return m5206_timer_read(s->timer[0], offset - 0x100);
+    } else if (offset >= 0x120 && offset < 0x140) {
+        return m5206_timer_read(s->timer[1], offset - 0x120);
+    } else if (offset >= 0x140 && offset < 0x160) {
+        return mcf_uart_read(s->uart[0], offset - 0x140, size);
+    } else if (offset >= 0x180 && offset < 0x1a0) {
+        return mcf_uart_read(s->uart[1], offset - 0x180, size);
+    }
+    switch (offset) {
+    case 0x03: return s->scr;
+    case 0x14 ... 0x20: return s->icr[offset - 0x13];
+    case 0x36: return s->imr;
+    case 0x3a: return s->ipr;
+    case 0x40: return s->rsr;
+    case 0x41: return 0;
+    case 0x42: return s->swivr;
+    case 0x50:
+        /* DRAM mask register.  */
+        /* FIXME: currently hardcoded to 128Mb.  */
+        {
+            uint32_t mask = ~0;
+            while (mask > ram_size)
+                mask >>= 1;
+            return mask & 0x0ffe0000;
+        }
+    case 0x5c: return 1; /* DRAM bank 1 empty.  */
+    case 0xcb: return s->par;
+    case 0x170: return s->uivr[0];
+    case 0x1b0: return s->uivr[1];
+    }
+    hw_error("Bad MBAR read offset 0x%x", (int)offset);
+    return 0;
+}
+
+static void m5206_mbar_write(m5206_mbar_state *s, uint32_t offset,
+                             uint64_t value, unsigned size)
+{
+    if (offset >= 0x100 && offset < 0x120) {
+        m5206_timer_write(s->timer[0], offset - 0x100, value);
+        return;
+    } else if (offset >= 0x120 && offset < 0x140) {
+        m5206_timer_write(s->timer[1], offset - 0x120, value);
+        return;
+    } else if (offset >= 0x140 && offset < 0x160) {
+        mcf_uart_write(s->uart[0], offset - 0x140, value, size);
+        return;
+    } else if (offset >= 0x180 && offset < 0x1a0) {
+        mcf_uart_write(s->uart[1], offset - 0x180, value, size);
+        return;
+    }
+    switch (offset) {
+    case 0x03:
+        s->scr = value;
+        break;
+    case 0x14 ... 0x20:
+        s->icr[offset - 0x13] = value;
+        m5206_mbar_update(s);
+        break;
+    case 0x36:
+        s->imr = value;
+        m5206_mbar_update(s);
+        break;
+    case 0x40:
+        s->rsr &= ~value;
+        break;
+    case 0x41:
+        /* TODO: implement watchdog.  */
+        break;
+    case 0x42:
+        s->swivr = value;
+        break;
+    case 0xcb:
+        s->par = value;
+        break;
+    case 0x170:
+        s->uivr[0] = value;
+        break;
+    case 0x178: case 0x17c: case 0x1c8: case 0x1bc:
+        /* Not implemented: UART Output port bits.  */
+        break;
+    case 0x1b0:
+        s->uivr[1] = value;
+        break;
+    default:
+        hw_error("Bad MBAR write offset 0x%x", (int)offset);
+        break;
+    }
+}
+
+/* Internal peripherals use a variety of register widths.
+   This lookup table allows a single routine to handle all of them.  */
+static const uint8_t m5206_mbar_width[] =
+{
+  /* 000-040 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  2, 2, 2, 2,
+  /* 040-080 */ 1, 2, 2, 2,  4, 1, 2, 4,  1, 2, 4, 2,  2, 4, 2, 2,
+  /* 080-0c0 */ 4, 2, 2, 4,  2, 2, 4, 2,  2, 4, 2, 2,  4, 2, 2, 4,
+  /* 0c0-100 */ 2, 2, 1, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,
+  /* 100-140 */ 2, 2, 2, 2,  1, 0, 0, 0,  2, 2, 2, 2,  1, 0, 0, 0,
+  /* 140-180 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+  /* 180-1c0 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+  /* 1c0-200 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+};
+
+static uint32_t m5206_mbar_readw(void *opaque, hwaddr offset);
+static uint32_t m5206_mbar_readl(void *opaque, hwaddr offset);
+
+static uint32_t m5206_mbar_readb(void *opaque, hwaddr offset)
+{
+    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
+    offset &= 0x3ff;
+    if (offset >= 0x200) {
+        hw_error("Bad MBAR read offset 0x%x", (int)offset);
+    }
+    if (m5206_mbar_width[offset >> 2] > 1) {
+        uint16_t val;
+        val = m5206_mbar_readw(opaque, offset & ~1);
+        if ((offset & 1) == 0) {
+            val >>= 8;
+        }
+        return val & 0xff;
+    }
+    return m5206_mbar_read(s, offset, 1);
+}
+
+static uint32_t m5206_mbar_readw(void *opaque, hwaddr offset)
+{
+    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
+    int width;
+    offset &= 0x3ff;
+    if (offset >= 0x200) {
+        hw_error("Bad MBAR read offset 0x%x", (int)offset);
+    }
+    width = m5206_mbar_width[offset >> 2];
+    if (width > 2) {
+        uint32_t val;
+        val = m5206_mbar_readl(opaque, offset & ~3);
+        if ((offset & 3) == 0)
+            val >>= 16;
+        return val & 0xffff;
+    } else if (width < 2) {
+        uint16_t val;
+        val = m5206_mbar_readb(opaque, offset) << 8;
+        val |= m5206_mbar_readb(opaque, offset + 1);
+        return val;
+    }
+    return m5206_mbar_read(s, offset, 2);
+}
+
+static uint32_t m5206_mbar_readl(void *opaque, hwaddr offset)
+{
+    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
+    int width;
+    offset &= 0x3ff;
+    if (offset >= 0x200) {
+        hw_error("Bad MBAR read offset 0x%x", (int)offset);
+    }
+    width = m5206_mbar_width[offset >> 2];
+    if (width < 4) {
+        uint32_t val;
+        val = m5206_mbar_readw(opaque, offset) << 16;
+        val |= m5206_mbar_readw(opaque, offset + 2);
+        return val;
+    }
+    return m5206_mbar_read(s, offset, 4);
+}
+
+static void m5206_mbar_writew(void *opaque, hwaddr offset,
+                              uint32_t value);
+static void m5206_mbar_writel(void *opaque, hwaddr offset,
+                              uint32_t value);
+
+static void m5206_mbar_writeb(void *opaque, hwaddr offset,
+                              uint32_t value)
+{
+    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
+    int width;
+    offset &= 0x3ff;
+    if (offset >= 0x200) {
+        hw_error("Bad MBAR write offset 0x%x", (int)offset);
+    }
+    width = m5206_mbar_width[offset >> 2];
+    if (width > 1) {
+        uint32_t tmp;
+        tmp = m5206_mbar_readw(opaque, offset & ~1);
+        if (offset & 1) {
+            tmp = (tmp & 0xff00) | value;
+        } else {
+            tmp = (tmp & 0x00ff) | (value << 8);
+        }
+        m5206_mbar_writew(opaque, offset & ~1, tmp);
+        return;
+    }
+    m5206_mbar_write(s, offset, value, 1);
+}
+
+static void m5206_mbar_writew(void *opaque, hwaddr offset,
+                              uint32_t value)
+{
+    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
+    int width;
+    offset &= 0x3ff;
+    if (offset >= 0x200) {
+        hw_error("Bad MBAR write offset 0x%x", (int)offset);
+    }
+    width = m5206_mbar_width[offset >> 2];
+    if (width > 2) {
+        uint32_t tmp;
+        tmp = m5206_mbar_readl(opaque, offset & ~3);
+        if (offset & 3) {
+            tmp = (tmp & 0xffff0000) | value;
+        } else {
+            tmp = (tmp & 0x0000ffff) | (value << 16);
+        }
+        m5206_mbar_writel(opaque, offset & ~3, tmp);
+        return;
+    } else if (width < 2) {
+        m5206_mbar_writeb(opaque, offset, value >> 8);
+        m5206_mbar_writeb(opaque, offset + 1, value & 0xff);
+        return;
+    }
+    m5206_mbar_write(s, offset, value, 2);
+}
+
+static void m5206_mbar_writel(void *opaque, hwaddr offset,
+                              uint32_t value)
+{
+    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
+    int width;
+    offset &= 0x3ff;
+    if (offset >= 0x200) {
+        hw_error("Bad MBAR write offset 0x%x", (int)offset);
+    }
+    width = m5206_mbar_width[offset >> 2];
+    if (width < 4) {
+        m5206_mbar_writew(opaque, offset, value >> 16);
+        m5206_mbar_writew(opaque, offset + 2, value & 0xffff);
+        return;
+    }
+    m5206_mbar_write(s, offset, value, 4);
+}
+
+static const MemoryRegionOps m5206_mbar_ops = {
+    .old_mmio = {
+        .read = {
+            m5206_mbar_readb,
+            m5206_mbar_readw,
+            m5206_mbar_readl,
+        },
+        .write = {
+            m5206_mbar_writeb,
+            m5206_mbar_writew,
+            m5206_mbar_writel,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+qemu_irq *mcf5206_init(MemoryRegion *sysmem, uint32_t base, M68kCPU *cpu)
+{
+    m5206_mbar_state *s;
+    qemu_irq *pic;
+
+    s = (m5206_mbar_state *)g_malloc0(sizeof(m5206_mbar_state));
+
+    memory_region_init_io(&s->iomem, &m5206_mbar_ops, s,
+                          "mbar", 0x00001000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
+
+    pic = qemu_allocate_irqs(m5206_mbar_set_irq, s, 14);
+    s->timer[0] = m5206_timer_init(pic[9]);
+    s->timer[1] = m5206_timer_init(pic[10]);
+    s->uart[0] = mcf_uart_init(pic[12], serial_hds[0]);
+    s->uart[1] = mcf_uart_init(pic[13], serial_hds[1]);
+    s->cpu = cpu;
+
+    m5206_mbar_reset(s);
+    return pic;
+}
diff --git a/hw/m68k/mcf_intc.c b/hw/m68k/mcf_intc.c
new file mode 100644
index 0000000..fff27b3
--- /dev/null
+++ b/hw/m68k/mcf_intc.c
@@ -0,0 +1,154 @@
+/*
+ * ColdFire Interrupt Controller emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licensed under the GPL
+ */
+#include "hw/hw.h"
+#include "hw/mcf.h"
+#include "exec/address-spaces.h"
+
+typedef struct {
+    MemoryRegion iomem;
+    uint64_t ipr;
+    uint64_t imr;
+    uint64_t ifr;
+    uint64_t enabled;
+    uint8_t icr[64];
+    M68kCPU *cpu;
+    int active_vector;
+} mcf_intc_state;
+
+static void mcf_intc_update(mcf_intc_state *s)
+{
+    uint64_t active;
+    int i;
+    int best;
+    int best_level;
+
+    active = (s->ipr | s->ifr) & s->enabled & ~s->imr;
+    best_level = 0;
+    best = 64;
+    if (active) {
+        for (i = 0; i < 64; i++) {
+            if ((active & 1) != 0 && s->icr[i] >= best_level) {
+                best_level = s->icr[i];
+                best = i;
+            }
+            active >>= 1;
+        }
+    }
+    s->active_vector = ((best == 64) ? 24 : (best + 64));
+    m68k_set_irq_level(s->cpu, best_level, s->active_vector);
+}
+
+static uint64_t mcf_intc_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    int offset;
+    mcf_intc_state *s = (mcf_intc_state *)opaque;
+    offset = addr & 0xff;
+    if (offset >= 0x40 && offset < 0x80) {
+        return s->icr[offset - 0x40];
+    }
+    switch (offset) {
+    case 0x00:
+        return (uint32_t)(s->ipr >> 32);
+    case 0x04:
+        return (uint32_t)s->ipr;
+    case 0x08:
+        return (uint32_t)(s->imr >> 32);
+    case 0x0c:
+        return (uint32_t)s->imr;
+    case 0x10:
+        return (uint32_t)(s->ifr >> 32);
+    case 0x14:
+        return (uint32_t)s->ifr;
+    case 0xe0: /* SWIACK.  */
+        return s->active_vector;
+    case 0xe1: case 0xe2: case 0xe3: case 0xe4:
+    case 0xe5: case 0xe6: case 0xe7:
+        /* LnIACK */
+        hw_error("mcf_intc_read: LnIACK not implemented\n");
+    default:
+        return 0;
+    }
+}
+
+static void mcf_intc_write(void *opaque, hwaddr addr,
+                           uint64_t val, unsigned size)
+{
+    int offset;
+    mcf_intc_state *s = (mcf_intc_state *)opaque;
+    offset = addr & 0xff;
+    if (offset >= 0x40 && offset < 0x80) {
+        int n = offset - 0x40;
+        s->icr[n] = val;
+        if (val == 0)
+            s->enabled &= ~(1ull << n);
+        else
+            s->enabled |= (1ull << n);
+        mcf_intc_update(s);
+        return;
+    }
+    switch (offset) {
+    case 0x00: case 0x04:
+        /* Ignore IPR writes.  */
+        return;
+    case 0x08:
+        s->imr = (s->imr & 0xffffffff) | ((uint64_t)val << 32);
+        break;
+    case 0x0c:
+        s->imr = (s->imr & 0xffffffff00000000ull) | (uint32_t)val;
+        break;
+    default:
+        hw_error("mcf_intc_write: Bad write offset %d\n", offset);
+        break;
+    }
+    mcf_intc_update(s);
+}
+
+static void mcf_intc_set_irq(void *opaque, int irq, int level)
+{
+    mcf_intc_state *s = (mcf_intc_state *)opaque;
+    if (irq >= 64)
+        return;
+    if (level)
+        s->ipr |= 1ull << irq;
+    else
+        s->ipr &= ~(1ull << irq);
+    mcf_intc_update(s);
+}
+
+static void mcf_intc_reset(mcf_intc_state *s)
+{
+    s->imr = ~0ull;
+    s->ipr = 0;
+    s->ifr = 0;
+    s->enabled = 0;
+    memset(s->icr, 0, 64);
+    s->active_vector = 24;
+}
+
+static const MemoryRegionOps mcf_intc_ops = {
+    .read = mcf_intc_read,
+    .write = mcf_intc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+qemu_irq *mcf_intc_init(MemoryRegion *sysmem,
+                        hwaddr base,
+                        M68kCPU *cpu)
+{
+    mcf_intc_state *s;
+
+    s = g_malloc0(sizeof(mcf_intc_state));
+    s->cpu = cpu;
+    mcf_intc_reset(s);
+
+    memory_region_init_io(&s->iomem, &mcf_intc_ops, s, "mcf", 0x100);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
+
+    return qemu_allocate_irqs(mcf_intc_set_irq, s, 64);
+}
diff --git a/hw/mcf5206.c b/hw/mcf5206.c
deleted file mode 100644
index 58cd8d4..0000000
--- a/hw/mcf5206.c
+++ /dev/null
@@ -1,548 +0,0 @@
-/*
- * Motorola ColdFire MCF5206 SoC embedded peripheral emulation.
- *
- * Copyright (c) 2007 CodeSourcery.
- *
- * This code is licensed under the GPL
- */
-#include "hw/hw.h"
-#include "hw/mcf.h"
-#include "qemu/timer.h"
-#include "hw/ptimer.h"
-#include "sysemu/sysemu.h"
-#include "exec/address-spaces.h"
-
-/* General purpose timer module.  */
-typedef struct {
-    uint16_t tmr;
-    uint16_t trr;
-    uint16_t tcr;
-    uint16_t ter;
-    ptimer_state *timer;
-    qemu_irq irq;
-    int irq_state;
-} m5206_timer_state;
-
-#define TMR_RST 0x01
-#define TMR_CLK 0x06
-#define TMR_FRR 0x08
-#define TMR_ORI 0x10
-#define TMR_OM  0x20
-#define TMR_CE  0xc0
-
-#define TER_CAP 0x01
-#define TER_REF 0x02
-
-static void m5206_timer_update(m5206_timer_state *s)
-{
-    if ((s->tmr & TMR_ORI) != 0 && (s->ter & TER_REF))
-        qemu_irq_raise(s->irq);
-    else
-        qemu_irq_lower(s->irq);
-}
-
-static void m5206_timer_reset(m5206_timer_state *s)
-{
-    s->tmr = 0;
-    s->trr = 0;
-}
-
-static void m5206_timer_recalibrate(m5206_timer_state *s)
-{
-    int prescale;
-    int mode;
-
-    ptimer_stop(s->timer);
-
-    if ((s->tmr & TMR_RST) == 0)
-        return;
-
-    prescale = (s->tmr >> 8) + 1;
-    mode = (s->tmr >> 1) & 3;
-    if (mode == 2)
-        prescale *= 16;
-
-    if (mode == 3 || mode == 0)
-        hw_error("m5206_timer: mode %d not implemented\n", mode);
-    if ((s->tmr & TMR_FRR) == 0)
-        hw_error("m5206_timer: free running mode not implemented\n");
-
-    /* Assume 66MHz system clock.  */
-    ptimer_set_freq(s->timer, 66000000 / prescale);
-
-    ptimer_set_limit(s->timer, s->trr, 0);
-
-    ptimer_run(s->timer, 0);
-}
-
-static void m5206_timer_trigger(void *opaque)
-{
-    m5206_timer_state *s = (m5206_timer_state *)opaque;
-    s->ter |= TER_REF;
-    m5206_timer_update(s);
-}
-
-static uint32_t m5206_timer_read(m5206_timer_state *s, uint32_t addr)
-{
-    switch (addr) {
-    case 0:
-        return s->tmr;
-    case 4:
-        return s->trr;
-    case 8:
-        return s->tcr;
-    case 0xc:
-        return s->trr - ptimer_get_count(s->timer);
-    case 0x11:
-        return s->ter;
-    default:
-        return 0;
-    }
-}
-
-static void m5206_timer_write(m5206_timer_state *s, uint32_t addr, uint32_t val)
-{
-    switch (addr) {
-    case 0:
-        if ((s->tmr & TMR_RST) != 0 && (val & TMR_RST) == 0) {
-            m5206_timer_reset(s);
-        }
-        s->tmr = val;
-        m5206_timer_recalibrate(s);
-        break;
-    case 4:
-        s->trr = val;
-        m5206_timer_recalibrate(s);
-        break;
-    case 8:
-        s->tcr = val;
-        break;
-    case 0xc:
-        ptimer_set_count(s->timer, val);
-        break;
-    case 0x11:
-        s->ter &= ~val;
-        break;
-    default:
-        break;
-    }
-    m5206_timer_update(s);
-}
-
-static m5206_timer_state *m5206_timer_init(qemu_irq irq)
-{
-    m5206_timer_state *s;
-    QEMUBH *bh;
-
-    s = (m5206_timer_state *)g_malloc0(sizeof(m5206_timer_state));
-    bh = qemu_bh_new(m5206_timer_trigger, s);
-    s->timer = ptimer_init(bh);
-    s->irq = irq;
-    m5206_timer_reset(s);
-    return s;
-}
-
-/* System Integration Module.  */
-
-typedef struct {
-    M68kCPU *cpu;
-    MemoryRegion iomem;
-    m5206_timer_state *timer[2];
-    void *uart[2];
-    uint8_t scr;
-    uint8_t icr[14];
-    uint16_t imr; /* 1 == interrupt is masked.  */
-    uint16_t ipr;
-    uint8_t rsr;
-    uint8_t swivr;
-    uint8_t par;
-    /* Include the UART vector registers here.  */
-    uint8_t uivr[2];
-} m5206_mbar_state;
-
-/* Interrupt controller.  */
-
-static int m5206_find_pending_irq(m5206_mbar_state *s)
-{
-    int level;
-    int vector;
-    uint16_t active;
-    int i;
-
-    level = 0;
-    vector = 0;
-    active = s->ipr & ~s->imr;
-    if (!active)
-        return 0;
-
-    for (i = 1; i < 14; i++) {
-        if (active & (1 << i)) {
-            if ((s->icr[i] & 0x1f) > level) {
-                level = s->icr[i] & 0x1f;
-                vector = i;
-            }
-        }
-    }
-
-    if (level < 4)
-        vector = 0;
-
-    return vector;
-}
-
-static void m5206_mbar_update(m5206_mbar_state *s)
-{
-    int irq;
-    int vector;
-    int level;
-
-    irq = m5206_find_pending_irq(s);
-    if (irq) {
-        int tmp;
-        tmp = s->icr[irq];
-        level = (tmp >> 2) & 7;
-        if (tmp & 0x80) {
-            /* Autovector.  */
-            vector = 24 + level;
-        } else {
-            switch (irq) {
-            case 8: /* SWT */
-                vector = s->swivr;
-                break;
-            case 12: /* UART1 */
-                vector = s->uivr[0];
-                break;
-            case 13: /* UART2 */
-                vector = s->uivr[1];
-                break;
-            default:
-                /* Unknown vector.  */
-                fprintf(stderr, "Unhandled vector for IRQ %d\n", irq);
-                vector = 0xf;
-                break;
-            }
-        }
-    } else {
-        level = 0;
-        vector = 0;
-    }
-    m68k_set_irq_level(s->cpu, level, vector);
-}
-
-static void m5206_mbar_set_irq(void *opaque, int irq, int level)
-{
-    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
-    if (level) {
-        s->ipr |= 1 << irq;
-    } else {
-        s->ipr &= ~(1 << irq);
-    }
-    m5206_mbar_update(s);
-}
-
-/* System Integration Module.  */
-
-static void m5206_mbar_reset(m5206_mbar_state *s)
-{
-    s->scr = 0xc0;
-    s->icr[1] = 0x04;
-    s->icr[2] = 0x08;
-    s->icr[3] = 0x0c;
-    s->icr[4] = 0x10;
-    s->icr[5] = 0x14;
-    s->icr[6] = 0x18;
-    s->icr[7] = 0x1c;
-    s->icr[8] = 0x1c;
-    s->icr[9] = 0x80;
-    s->icr[10] = 0x80;
-    s->icr[11] = 0x80;
-    s->icr[12] = 0x00;
-    s->icr[13] = 0x00;
-    s->imr = 0x3ffe;
-    s->rsr = 0x80;
-    s->swivr = 0x0f;
-    s->par = 0;
-}
-
-static uint64_t m5206_mbar_read(m5206_mbar_state *s,
-                                uint64_t offset, unsigned size)
-{
-    if (offset >= 0x100 && offset < 0x120) {
-        return m5206_timer_read(s->timer[0], offset - 0x100);
-    } else if (offset >= 0x120 && offset < 0x140) {
-        return m5206_timer_read(s->timer[1], offset - 0x120);
-    } else if (offset >= 0x140 && offset < 0x160) {
-        return mcf_uart_read(s->uart[0], offset - 0x140, size);
-    } else if (offset >= 0x180 && offset < 0x1a0) {
-        return mcf_uart_read(s->uart[1], offset - 0x180, size);
-    }
-    switch (offset) {
-    case 0x03: return s->scr;
-    case 0x14 ... 0x20: return s->icr[offset - 0x13];
-    case 0x36: return s->imr;
-    case 0x3a: return s->ipr;
-    case 0x40: return s->rsr;
-    case 0x41: return 0;
-    case 0x42: return s->swivr;
-    case 0x50:
-        /* DRAM mask register.  */
-        /* FIXME: currently hardcoded to 128Mb.  */
-        {
-            uint32_t mask = ~0;
-            while (mask > ram_size)
-                mask >>= 1;
-            return mask & 0x0ffe0000;
-        }
-    case 0x5c: return 1; /* DRAM bank 1 empty.  */
-    case 0xcb: return s->par;
-    case 0x170: return s->uivr[0];
-    case 0x1b0: return s->uivr[1];
-    }
-    hw_error("Bad MBAR read offset 0x%x", (int)offset);
-    return 0;
-}
-
-static void m5206_mbar_write(m5206_mbar_state *s, uint32_t offset,
-                             uint64_t value, unsigned size)
-{
-    if (offset >= 0x100 && offset < 0x120) {
-        m5206_timer_write(s->timer[0], offset - 0x100, value);
-        return;
-    } else if (offset >= 0x120 && offset < 0x140) {
-        m5206_timer_write(s->timer[1], offset - 0x120, value);
-        return;
-    } else if (offset >= 0x140 && offset < 0x160) {
-        mcf_uart_write(s->uart[0], offset - 0x140, value, size);
-        return;
-    } else if (offset >= 0x180 && offset < 0x1a0) {
-        mcf_uart_write(s->uart[1], offset - 0x180, value, size);
-        return;
-    }
-    switch (offset) {
-    case 0x03:
-        s->scr = value;
-        break;
-    case 0x14 ... 0x20:
-        s->icr[offset - 0x13] = value;
-        m5206_mbar_update(s);
-        break;
-    case 0x36:
-        s->imr = value;
-        m5206_mbar_update(s);
-        break;
-    case 0x40:
-        s->rsr &= ~value;
-        break;
-    case 0x41:
-        /* TODO: implement watchdog.  */
-        break;
-    case 0x42:
-        s->swivr = value;
-        break;
-    case 0xcb:
-        s->par = value;
-        break;
-    case 0x170:
-        s->uivr[0] = value;
-        break;
-    case 0x178: case 0x17c: case 0x1c8: case 0x1bc:
-        /* Not implemented: UART Output port bits.  */
-        break;
-    case 0x1b0:
-        s->uivr[1] = value;
-        break;
-    default:
-        hw_error("Bad MBAR write offset 0x%x", (int)offset);
-        break;
-    }
-}
-
-/* Internal peripherals use a variety of register widths.
-   This lookup table allows a single routine to handle all of them.  */
-static const uint8_t m5206_mbar_width[] =
-{
-  /* 000-040 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  2, 2, 2, 2,
-  /* 040-080 */ 1, 2, 2, 2,  4, 1, 2, 4,  1, 2, 4, 2,  2, 4, 2, 2,
-  /* 080-0c0 */ 4, 2, 2, 4,  2, 2, 4, 2,  2, 4, 2, 2,  4, 2, 2, 4,
-  /* 0c0-100 */ 2, 2, 1, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,
-  /* 100-140 */ 2, 2, 2, 2,  1, 0, 0, 0,  2, 2, 2, 2,  1, 0, 0, 0,
-  /* 140-180 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-  /* 180-1c0 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-  /* 1c0-200 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
-};
-
-static uint32_t m5206_mbar_readw(void *opaque, hwaddr offset);
-static uint32_t m5206_mbar_readl(void *opaque, hwaddr offset);
-
-static uint32_t m5206_mbar_readb(void *opaque, hwaddr offset)
-{
-    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
-    offset &= 0x3ff;
-    if (offset >= 0x200) {
-        hw_error("Bad MBAR read offset 0x%x", (int)offset);
-    }
-    if (m5206_mbar_width[offset >> 2] > 1) {
-        uint16_t val;
-        val = m5206_mbar_readw(opaque, offset & ~1);
-        if ((offset & 1) == 0) {
-            val >>= 8;
-        }
-        return val & 0xff;
-    }
-    return m5206_mbar_read(s, offset, 1);
-}
-
-static uint32_t m5206_mbar_readw(void *opaque, hwaddr offset)
-{
-    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
-    int width;
-    offset &= 0x3ff;
-    if (offset >= 0x200) {
-        hw_error("Bad MBAR read offset 0x%x", (int)offset);
-    }
-    width = m5206_mbar_width[offset >> 2];
-    if (width > 2) {
-        uint32_t val;
-        val = m5206_mbar_readl(opaque, offset & ~3);
-        if ((offset & 3) == 0)
-            val >>= 16;
-        return val & 0xffff;
-    } else if (width < 2) {
-        uint16_t val;
-        val = m5206_mbar_readb(opaque, offset) << 8;
-        val |= m5206_mbar_readb(opaque, offset + 1);
-        return val;
-    }
-    return m5206_mbar_read(s, offset, 2);
-}
-
-static uint32_t m5206_mbar_readl(void *opaque, hwaddr offset)
-{
-    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
-    int width;
-    offset &= 0x3ff;
-    if (offset >= 0x200) {
-        hw_error("Bad MBAR read offset 0x%x", (int)offset);
-    }
-    width = m5206_mbar_width[offset >> 2];
-    if (width < 4) {
-        uint32_t val;
-        val = m5206_mbar_readw(opaque, offset) << 16;
-        val |= m5206_mbar_readw(opaque, offset + 2);
-        return val;
-    }
-    return m5206_mbar_read(s, offset, 4);
-}
-
-static void m5206_mbar_writew(void *opaque, hwaddr offset,
-                              uint32_t value);
-static void m5206_mbar_writel(void *opaque, hwaddr offset,
-                              uint32_t value);
-
-static void m5206_mbar_writeb(void *opaque, hwaddr offset,
-                              uint32_t value)
-{
-    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
-    int width;
-    offset &= 0x3ff;
-    if (offset >= 0x200) {
-        hw_error("Bad MBAR write offset 0x%x", (int)offset);
-    }
-    width = m5206_mbar_width[offset >> 2];
-    if (width > 1) {
-        uint32_t tmp;
-        tmp = m5206_mbar_readw(opaque, offset & ~1);
-        if (offset & 1) {
-            tmp = (tmp & 0xff00) | value;
-        } else {
-            tmp = (tmp & 0x00ff) | (value << 8);
-        }
-        m5206_mbar_writew(opaque, offset & ~1, tmp);
-        return;
-    }
-    m5206_mbar_write(s, offset, value, 1);
-}
-
-static void m5206_mbar_writew(void *opaque, hwaddr offset,
-                              uint32_t value)
-{
-    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
-    int width;
-    offset &= 0x3ff;
-    if (offset >= 0x200) {
-        hw_error("Bad MBAR write offset 0x%x", (int)offset);
-    }
-    width = m5206_mbar_width[offset >> 2];
-    if (width > 2) {
-        uint32_t tmp;
-        tmp = m5206_mbar_readl(opaque, offset & ~3);
-        if (offset & 3) {
-            tmp = (tmp & 0xffff0000) | value;
-        } else {
-            tmp = (tmp & 0x0000ffff) | (value << 16);
-        }
-        m5206_mbar_writel(opaque, offset & ~3, tmp);
-        return;
-    } else if (width < 2) {
-        m5206_mbar_writeb(opaque, offset, value >> 8);
-        m5206_mbar_writeb(opaque, offset + 1, value & 0xff);
-        return;
-    }
-    m5206_mbar_write(s, offset, value, 2);
-}
-
-static void m5206_mbar_writel(void *opaque, hwaddr offset,
-                              uint32_t value)
-{
-    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
-    int width;
-    offset &= 0x3ff;
-    if (offset >= 0x200) {
-        hw_error("Bad MBAR write offset 0x%x", (int)offset);
-    }
-    width = m5206_mbar_width[offset >> 2];
-    if (width < 4) {
-        m5206_mbar_writew(opaque, offset, value >> 16);
-        m5206_mbar_writew(opaque, offset + 2, value & 0xffff);
-        return;
-    }
-    m5206_mbar_write(s, offset, value, 4);
-}
-
-static const MemoryRegionOps m5206_mbar_ops = {
-    .old_mmio = {
-        .read = {
-            m5206_mbar_readb,
-            m5206_mbar_readw,
-            m5206_mbar_readl,
-        },
-        .write = {
-            m5206_mbar_writeb,
-            m5206_mbar_writew,
-            m5206_mbar_writel,
-        },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-qemu_irq *mcf5206_init(MemoryRegion *sysmem, uint32_t base, M68kCPU *cpu)
-{
-    m5206_mbar_state *s;
-    qemu_irq *pic;
-
-    s = (m5206_mbar_state *)g_malloc0(sizeof(m5206_mbar_state));
-
-    memory_region_init_io(&s->iomem, &m5206_mbar_ops, s,
-                          "mbar", 0x00001000);
-    memory_region_add_subregion(sysmem, base, &s->iomem);
-
-    pic = qemu_allocate_irqs(m5206_mbar_set_irq, s, 14);
-    s->timer[0] = m5206_timer_init(pic[9]);
-    s->timer[1] = m5206_timer_init(pic[10]);
-    s->uart[0] = mcf_uart_init(pic[12], serial_hds[0]);
-    s->uart[1] = mcf_uart_init(pic[13], serial_hds[1]);
-    s->cpu = cpu;
-
-    m5206_mbar_reset(s);
-    return pic;
-}
diff --git a/hw/mcf_intc.c b/hw/mcf_intc.c
deleted file mode 100644
index fff27b3..0000000
--- a/hw/mcf_intc.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * ColdFire Interrupt Controller emulation.
- *
- * Copyright (c) 2007 CodeSourcery.
- *
- * This code is licensed under the GPL
- */
-#include "hw/hw.h"
-#include "hw/mcf.h"
-#include "exec/address-spaces.h"
-
-typedef struct {
-    MemoryRegion iomem;
-    uint64_t ipr;
-    uint64_t imr;
-    uint64_t ifr;
-    uint64_t enabled;
-    uint8_t icr[64];
-    M68kCPU *cpu;
-    int active_vector;
-} mcf_intc_state;
-
-static void mcf_intc_update(mcf_intc_state *s)
-{
-    uint64_t active;
-    int i;
-    int best;
-    int best_level;
-
-    active = (s->ipr | s->ifr) & s->enabled & ~s->imr;
-    best_level = 0;
-    best = 64;
-    if (active) {
-        for (i = 0; i < 64; i++) {
-            if ((active & 1) != 0 && s->icr[i] >= best_level) {
-                best_level = s->icr[i];
-                best = i;
-            }
-            active >>= 1;
-        }
-    }
-    s->active_vector = ((best == 64) ? 24 : (best + 64));
-    m68k_set_irq_level(s->cpu, best_level, s->active_vector);
-}
-
-static uint64_t mcf_intc_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    int offset;
-    mcf_intc_state *s = (mcf_intc_state *)opaque;
-    offset = addr & 0xff;
-    if (offset >= 0x40 && offset < 0x80) {
-        return s->icr[offset - 0x40];
-    }
-    switch (offset) {
-    case 0x00:
-        return (uint32_t)(s->ipr >> 32);
-    case 0x04:
-        return (uint32_t)s->ipr;
-    case 0x08:
-        return (uint32_t)(s->imr >> 32);
-    case 0x0c:
-        return (uint32_t)s->imr;
-    case 0x10:
-        return (uint32_t)(s->ifr >> 32);
-    case 0x14:
-        return (uint32_t)s->ifr;
-    case 0xe0: /* SWIACK.  */
-        return s->active_vector;
-    case 0xe1: case 0xe2: case 0xe3: case 0xe4:
-    case 0xe5: case 0xe6: case 0xe7:
-        /* LnIACK */
-        hw_error("mcf_intc_read: LnIACK not implemented\n");
-    default:
-        return 0;
-    }
-}
-
-static void mcf_intc_write(void *opaque, hwaddr addr,
-                           uint64_t val, unsigned size)
-{
-    int offset;
-    mcf_intc_state *s = (mcf_intc_state *)opaque;
-    offset = addr & 0xff;
-    if (offset >= 0x40 && offset < 0x80) {
-        int n = offset - 0x40;
-        s->icr[n] = val;
-        if (val == 0)
-            s->enabled &= ~(1ull << n);
-        else
-            s->enabled |= (1ull << n);
-        mcf_intc_update(s);
-        return;
-    }
-    switch (offset) {
-    case 0x00: case 0x04:
-        /* Ignore IPR writes.  */
-        return;
-    case 0x08:
-        s->imr = (s->imr & 0xffffffff) | ((uint64_t)val << 32);
-        break;
-    case 0x0c:
-        s->imr = (s->imr & 0xffffffff00000000ull) | (uint32_t)val;
-        break;
-    default:
-        hw_error("mcf_intc_write: Bad write offset %d\n", offset);
-        break;
-    }
-    mcf_intc_update(s);
-}
-
-static void mcf_intc_set_irq(void *opaque, int irq, int level)
-{
-    mcf_intc_state *s = (mcf_intc_state *)opaque;
-    if (irq >= 64)
-        return;
-    if (level)
-        s->ipr |= 1ull << irq;
-    else
-        s->ipr &= ~(1ull << irq);
-    mcf_intc_update(s);
-}
-
-static void mcf_intc_reset(mcf_intc_state *s)
-{
-    s->imr = ~0ull;
-    s->ipr = 0;
-    s->ifr = 0;
-    s->enabled = 0;
-    memset(s->icr, 0, 64);
-    s->active_vector = 24;
-}
-
-static const MemoryRegionOps mcf_intc_ops = {
-    .read = mcf_intc_read,
-    .write = mcf_intc_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-qemu_irq *mcf_intc_init(MemoryRegion *sysmem,
-                        hwaddr base,
-                        M68kCPU *cpu)
-{
-    mcf_intc_state *s;
-
-    s = g_malloc0(sizeof(mcf_intc_state));
-    s->cpu = cpu;
-    mcf_intc_reset(s);
-
-    memory_region_init_io(&s->iomem, &mcf_intc_ops, s, "mcf", 0x100);
-    memory_region_add_subregion(sysmem, base, &s->iomem);
-
-    return qemu_allocate_irqs(mcf_intc_set_irq, s, 64);
-}
commit 8786b05e7bf3c4fc7a25fa14f1736a716cd8a8c4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Feb 5 15:22:56 2013 +0100

    i386: move files referencing CPU to hw/i386/
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 5d071f4..a78c0b2 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -1,5 +1,5 @@
 obj-y += mc146818rtc.o
-obj-y += apic_common.o apic.o kvmvapic.o
+obj-y += apic_common.o apic.o
 obj-y += sga.o ioapic_common.o ioapic.o piix_pci.o
 obj-y += vmport.o
 obj-y += pci/pci-hotplug.o wdt_ib700.o
@@ -18,3 +18,5 @@ obj-y := $(addprefix ../,$(obj-y))
 obj-y += multiboot.o smbios.o
 obj-y += pc.o pc_piix.o pc_q35.o
 obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
+
+obj-y += kvmvapic.o
diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
new file mode 100644
index 0000000..c151c95
--- /dev/null
+++ b/hw/i386/kvmvapic.c
@@ -0,0 +1,822 @@
+/*
+ * TPR optimization for 32-bit Windows guests (XP and Server 2003)
+ *
+ * Copyright (C) 2007-2008 Qumranet Technologies
+ * Copyright (C) 2012      Jan Kiszka, Siemens AG
+ *
+ * This work is licensed under the terms of the GNU GPL version 2, or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ */
+#include "sysemu/sysemu.h"
+#include "sysemu/cpus.h"
+#include "sysemu/kvm.h"
+#include "hw/apic_internal.h"
+
+#define APIC_DEFAULT_ADDRESS    0xfee00000
+
+#define VAPIC_IO_PORT           0x7e
+
+#define VAPIC_CPU_SHIFT         7
+
+#define ROM_BLOCK_SIZE          512
+#define ROM_BLOCK_MASK          (~(ROM_BLOCK_SIZE - 1))
+
+typedef enum VAPICMode {
+    VAPIC_INACTIVE = 0,
+    VAPIC_ACTIVE   = 1,
+    VAPIC_STANDBY  = 2,
+} VAPICMode;
+
+typedef struct VAPICHandlers {
+    uint32_t set_tpr;
+    uint32_t set_tpr_eax;
+    uint32_t get_tpr[8];
+    uint32_t get_tpr_stack;
+} QEMU_PACKED VAPICHandlers;
+
+typedef struct GuestROMState {
+    char signature[8];
+    uint32_t vaddr;
+    uint32_t fixup_start;
+    uint32_t fixup_end;
+    uint32_t vapic_vaddr;
+    uint32_t vapic_size;
+    uint32_t vcpu_shift;
+    uint32_t real_tpr_addr;
+    VAPICHandlers up;
+    VAPICHandlers mp;
+} QEMU_PACKED GuestROMState;
+
+typedef struct VAPICROMState {
+    SysBusDevice busdev;
+    MemoryRegion io;
+    MemoryRegion rom;
+    uint32_t state;
+    uint32_t rom_state_paddr;
+    uint32_t rom_state_vaddr;
+    uint32_t vapic_paddr;
+    uint32_t real_tpr_addr;
+    GuestROMState rom_state;
+    size_t rom_size;
+    bool rom_mapped_writable;
+} VAPICROMState;
+
+#define TPR_INSTR_ABS_MODRM             0x1
+#define TPR_INSTR_MATCH_MODRM_REG       0x2
+
+typedef struct TPRInstruction {
+    uint8_t opcode;
+    uint8_t modrm_reg;
+    unsigned int flags;
+    TPRAccess access;
+    size_t length;
+    off_t addr_offset;
+} TPRInstruction;
+
+/* must be sorted by length, shortest first */
+static const TPRInstruction tpr_instr[] = {
+    { /* mov abs to eax */
+        .opcode = 0xa1,
+        .access = TPR_ACCESS_READ,
+        .length = 5,
+        .addr_offset = 1,
+    },
+    { /* mov eax to abs */
+        .opcode = 0xa3,
+        .access = TPR_ACCESS_WRITE,
+        .length = 5,
+        .addr_offset = 1,
+    },
+    { /* mov r32 to r/m32 */
+        .opcode = 0x89,
+        .flags = TPR_INSTR_ABS_MODRM,
+        .access = TPR_ACCESS_WRITE,
+        .length = 6,
+        .addr_offset = 2,
+    },
+    { /* mov r/m32 to r32 */
+        .opcode = 0x8b,
+        .flags = TPR_INSTR_ABS_MODRM,
+        .access = TPR_ACCESS_READ,
+        .length = 6,
+        .addr_offset = 2,
+    },
+    { /* push r/m32 */
+        .opcode = 0xff,
+        .modrm_reg = 6,
+        .flags = TPR_INSTR_ABS_MODRM | TPR_INSTR_MATCH_MODRM_REG,
+        .access = TPR_ACCESS_READ,
+        .length = 6,
+        .addr_offset = 2,
+    },
+    { /* mov imm32, r/m32 (c7/0) */
+        .opcode = 0xc7,
+        .modrm_reg = 0,
+        .flags = TPR_INSTR_ABS_MODRM | TPR_INSTR_MATCH_MODRM_REG,
+        .access = TPR_ACCESS_WRITE,
+        .length = 10,
+        .addr_offset = 2,
+    },
+};
+
+static void read_guest_rom_state(VAPICROMState *s)
+{
+    cpu_physical_memory_rw(s->rom_state_paddr, (void *)&s->rom_state,
+                           sizeof(GuestROMState), 0);
+}
+
+static void write_guest_rom_state(VAPICROMState *s)
+{
+    cpu_physical_memory_rw(s->rom_state_paddr, (void *)&s->rom_state,
+                           sizeof(GuestROMState), 1);
+}
+
+static void update_guest_rom_state(VAPICROMState *s)
+{
+    read_guest_rom_state(s);
+
+    s->rom_state.real_tpr_addr = cpu_to_le32(s->real_tpr_addr);
+    s->rom_state.vcpu_shift = cpu_to_le32(VAPIC_CPU_SHIFT);
+
+    write_guest_rom_state(s);
+}
+
+static int find_real_tpr_addr(VAPICROMState *s, CPUX86State *env)
+{
+    hwaddr paddr;
+    target_ulong addr;
+
+    if (s->state == VAPIC_ACTIVE) {
+        return 0;
+    }
+    /*
+     * If there is no prior TPR access instruction we could analyze (which is
+     * the case after resume from hibernation), we need to scan the possible
+     * virtual address space for the APIC mapping.
+     */
+    for (addr = 0xfffff000; addr >= 0x80000000; addr -= TARGET_PAGE_SIZE) {
+        paddr = cpu_get_phys_page_debug(env, addr);
+        if (paddr != APIC_DEFAULT_ADDRESS) {
+            continue;
+        }
+        s->real_tpr_addr = addr + 0x80;
+        update_guest_rom_state(s);
+        return 0;
+    }
+    return -1;
+}
+
+static uint8_t modrm_reg(uint8_t modrm)
+{
+    return (modrm >> 3) & 7;
+}
+
+static bool is_abs_modrm(uint8_t modrm)
+{
+    return (modrm & 0xc7) == 0x05;
+}
+
+static bool opcode_matches(uint8_t *opcode, const TPRInstruction *instr)
+{
+    return opcode[0] == instr->opcode &&
+        (!(instr->flags & TPR_INSTR_ABS_MODRM) || is_abs_modrm(opcode[1])) &&
+        (!(instr->flags & TPR_INSTR_MATCH_MODRM_REG) ||
+         modrm_reg(opcode[1]) == instr->modrm_reg);
+}
+
+static int evaluate_tpr_instruction(VAPICROMState *s, CPUX86State *env,
+                                    target_ulong *pip, TPRAccess access)
+{
+    const TPRInstruction *instr;
+    target_ulong ip = *pip;
+    uint8_t opcode[2];
+    uint32_t real_tpr_addr;
+    int i;
+
+    if ((ip & 0xf0000000ULL) != 0x80000000ULL &&
+        (ip & 0xf0000000ULL) != 0xe0000000ULL) {
+        return -1;
+    }
+
+    /*
+     * Early Windows 2003 SMP initialization contains a
+     *
+     *   mov imm32, r/m32
+     *
+     * instruction that is patched by TPR optimization. The problem is that
+     * RSP, used by the patched instruction, is zero, so the guest gets a
+     * double fault and dies.
+     */
+    if (env->regs[R_ESP] == 0) {
+        return -1;
+    }
+
+    if (kvm_enabled() && !kvm_irqchip_in_kernel()) {
+        /*
+         * KVM without kernel-based TPR access reporting will pass an IP that
+         * points after the accessing instruction. So we need to look backward
+         * to find the reason.
+         */
+        for (i = 0; i < ARRAY_SIZE(tpr_instr); i++) {
+            instr = &tpr_instr[i];
+            if (instr->access != access) {
+                continue;
+            }
+            if (cpu_memory_rw_debug(env, ip - instr->length, opcode,
+                                    sizeof(opcode), 0) < 0) {
+                return -1;
+            }
+            if (opcode_matches(opcode, instr)) {
+                ip -= instr->length;
+                goto instruction_ok;
+            }
+        }
+        return -1;
+    } else {
+        if (cpu_memory_rw_debug(env, ip, opcode, sizeof(opcode), 0) < 0) {
+            return -1;
+        }
+        for (i = 0; i < ARRAY_SIZE(tpr_instr); i++) {
+            instr = &tpr_instr[i];
+            if (opcode_matches(opcode, instr)) {
+                goto instruction_ok;
+            }
+        }
+        return -1;
+    }
+
+instruction_ok:
+    /*
+     * Grab the virtual TPR address from the instruction
+     * and update the cached values.
+     */
+    if (cpu_memory_rw_debug(env, ip + instr->addr_offset,
+                            (void *)&real_tpr_addr,
+                            sizeof(real_tpr_addr), 0) < 0) {
+        return -1;
+    }
+    real_tpr_addr = le32_to_cpu(real_tpr_addr);
+    if ((real_tpr_addr & 0xfff) != 0x80) {
+        return -1;
+    }
+    s->real_tpr_addr = real_tpr_addr;
+    update_guest_rom_state(s);
+
+    *pip = ip;
+    return 0;
+}
+
+static int update_rom_mapping(VAPICROMState *s, CPUX86State *env, target_ulong ip)
+{
+    hwaddr paddr;
+    uint32_t rom_state_vaddr;
+    uint32_t pos, patch, offset;
+
+    /* nothing to do if already activated */
+    if (s->state == VAPIC_ACTIVE) {
+        return 0;
+    }
+
+    /* bail out if ROM init code was not executed (missing ROM?) */
+    if (s->state == VAPIC_INACTIVE) {
+        return -1;
+    }
+
+    /* find out virtual address of the ROM */
+    rom_state_vaddr = s->rom_state_paddr + (ip & 0xf0000000);
+    paddr = cpu_get_phys_page_debug(env, rom_state_vaddr);
+    if (paddr == -1) {
+        return -1;
+    }
+    paddr += rom_state_vaddr & ~TARGET_PAGE_MASK;
+    if (paddr != s->rom_state_paddr) {
+        return -1;
+    }
+    read_guest_rom_state(s);
+    if (memcmp(s->rom_state.signature, "kvm aPiC", 8) != 0) {
+        return -1;
+    }
+    s->rom_state_vaddr = rom_state_vaddr;
+
+    /* fixup addresses in ROM if needed */
+    if (rom_state_vaddr == le32_to_cpu(s->rom_state.vaddr)) {
+        return 0;
+    }
+    for (pos = le32_to_cpu(s->rom_state.fixup_start);
+         pos < le32_to_cpu(s->rom_state.fixup_end);
+         pos += 4) {
+        cpu_physical_memory_rw(paddr + pos - s->rom_state.vaddr,
+                               (void *)&offset, sizeof(offset), 0);
+        offset = le32_to_cpu(offset);
+        cpu_physical_memory_rw(paddr + offset, (void *)&patch,
+                               sizeof(patch), 0);
+        patch = le32_to_cpu(patch);
+        patch += rom_state_vaddr - le32_to_cpu(s->rom_state.vaddr);
+        patch = cpu_to_le32(patch);
+        cpu_physical_memory_rw(paddr + offset, (void *)&patch,
+                               sizeof(patch), 1);
+    }
+    read_guest_rom_state(s);
+    s->vapic_paddr = paddr + le32_to_cpu(s->rom_state.vapic_vaddr) -
+        le32_to_cpu(s->rom_state.vaddr);
+
+    return 0;
+}
+
+/*
+ * Tries to read the unique processor number from the Kernel Processor Control
+ * Region (KPCR) of 32-bit Windows XP and Server 2003. Returns -1 if the KPCR
+ * cannot be accessed or is considered invalid. This also ensures that we are
+ * not patching the wrong guest.
+ */
+static int get_kpcr_number(CPUX86State *env)
+{
+    struct kpcr {
+        uint8_t  fill1[0x1c];
+        uint32_t self;
+        uint8_t  fill2[0x31];
+        uint8_t  number;
+    } QEMU_PACKED kpcr;
+
+    if (cpu_memory_rw_debug(env, env->segs[R_FS].base,
+                            (void *)&kpcr, sizeof(kpcr), 0) < 0 ||
+        kpcr.self != env->segs[R_FS].base) {
+        return -1;
+    }
+    return kpcr.number;
+}
+
+static int vapic_enable(VAPICROMState *s, CPUX86State *env)
+{
+    int cpu_number = get_kpcr_number(env);
+    hwaddr vapic_paddr;
+    static const uint8_t enabled = 1;
+
+    if (cpu_number < 0) {
+        return -1;
+    }
+    vapic_paddr = s->vapic_paddr +
+        (((hwaddr)cpu_number) << VAPIC_CPU_SHIFT);
+    cpu_physical_memory_rw(vapic_paddr + offsetof(VAPICState, enabled),
+                           (void *)&enabled, sizeof(enabled), 1);
+    apic_enable_vapic(env->apic_state, vapic_paddr);
+
+    s->state = VAPIC_ACTIVE;
+
+    return 0;
+}
+
+static void patch_byte(CPUX86State *env, target_ulong addr, uint8_t byte)
+{
+    cpu_memory_rw_debug(env, addr, &byte, 1, 1);
+}
+
+static void patch_call(VAPICROMState *s, CPUX86State *env, target_ulong ip,
+                       uint32_t target)
+{
+    uint32_t offset;
+
+    offset = cpu_to_le32(target - ip - 5);
+    patch_byte(env, ip, 0xe8); /* call near */
+    cpu_memory_rw_debug(env, ip + 1, (void *)&offset, sizeof(offset), 1);
+}
+
+static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
+{
+    CPUState *cs = CPU(cpu);
+    CPUX86State *env = &cpu->env;
+    VAPICHandlers *handlers;
+    uint8_t opcode[2];
+    uint32_t imm32;
+    target_ulong current_pc = 0;
+    target_ulong current_cs_base = 0;
+    int current_flags = 0;
+
+    if (smp_cpus == 1) {
+        handlers = &s->rom_state.up;
+    } else {
+        handlers = &s->rom_state.mp;
+    }
+
+    if (!kvm_enabled()) {
+        cpu_restore_state(env, env->mem_io_pc);
+        cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
+                             &current_flags);
+    }
+
+    pause_all_vcpus();
+
+    cpu_memory_rw_debug(env, ip, opcode, sizeof(opcode), 0);
+
+    switch (opcode[0]) {
+    case 0x89: /* mov r32 to r/m32 */
+        patch_byte(env, ip, 0x50 + modrm_reg(opcode[1]));  /* push reg */
+        patch_call(s, env, ip + 1, handlers->set_tpr);
+        break;
+    case 0x8b: /* mov r/m32 to r32 */
+        patch_byte(env, ip, 0x90);
+        patch_call(s, env, ip + 1, handlers->get_tpr[modrm_reg(opcode[1])]);
+        break;
+    case 0xa1: /* mov abs to eax */
+        patch_call(s, env, ip, handlers->get_tpr[0]);
+        break;
+    case 0xa3: /* mov eax to abs */
+        patch_call(s, env, ip, handlers->set_tpr_eax);
+        break;
+    case 0xc7: /* mov imm32, r/m32 (c7/0) */
+        patch_byte(env, ip, 0x68);  /* push imm32 */
+        cpu_memory_rw_debug(env, ip + 6, (void *)&imm32, sizeof(imm32), 0);
+        cpu_memory_rw_debug(env, ip + 1, (void *)&imm32, sizeof(imm32), 1);
+        patch_call(s, env, ip + 5, handlers->set_tpr);
+        break;
+    case 0xff: /* push r/m32 */
+        patch_byte(env, ip, 0x50); /* push eax */
+        patch_call(s, env, ip + 1, handlers->get_tpr_stack);
+        break;
+    default:
+        abort();
+    }
+
+    resume_all_vcpus();
+
+    if (!kvm_enabled()) {
+        cs->current_tb = NULL;
+        tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
+        cpu_resume_from_signal(env, NULL);
+    }
+}
+
+void vapic_report_tpr_access(DeviceState *dev, CPUState *cs, target_ulong ip,
+                             TPRAccess access)
+{
+    VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev);
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
+
+    cpu_synchronize_state(env);
+
+    if (evaluate_tpr_instruction(s, env, &ip, access) < 0) {
+        if (s->state == VAPIC_ACTIVE) {
+            vapic_enable(s, env);
+        }
+        return;
+    }
+    if (update_rom_mapping(s, env, ip) < 0) {
+        return;
+    }
+    if (vapic_enable(s, env) < 0) {
+        return;
+    }
+    patch_instruction(s, cpu, ip);
+}
+
+typedef struct VAPICEnableTPRReporting {
+    DeviceState *apic;
+    bool enable;
+} VAPICEnableTPRReporting;
+
+static void vapic_do_enable_tpr_reporting(void *data)
+{
+    VAPICEnableTPRReporting *info = data;
+
+    apic_enable_tpr_access_reporting(info->apic, info->enable);
+}
+
+static void vapic_enable_tpr_reporting(bool enable)
+{
+    VAPICEnableTPRReporting info = {
+        .enable = enable,
+    };
+    X86CPU *cpu;
+    CPUX86State *env;
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        cpu = x86_env_get_cpu(env);
+        info.apic = env->apic_state;
+        run_on_cpu(CPU(cpu), vapic_do_enable_tpr_reporting, &info);
+    }
+}
+
+static void vapic_reset(DeviceState *dev)
+{
+    VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev);
+
+    if (s->state == VAPIC_ACTIVE) {
+        s->state = VAPIC_STANDBY;
+    }
+    vapic_enable_tpr_reporting(false);
+}
+
+/*
+ * Set the IRQ polling hypercalls to the supported variant:
+ *  - vmcall if using KVM in-kernel irqchip
+ *  - 32-bit VAPIC port write otherwise
+ */
+static int patch_hypercalls(VAPICROMState *s)
+{
+    hwaddr rom_paddr = s->rom_state_paddr & ROM_BLOCK_MASK;
+    static const uint8_t vmcall_pattern[] = { /* vmcall */
+        0xb8, 0x1, 0, 0, 0, 0xf, 0x1, 0xc1
+    };
+    static const uint8_t outl_pattern[] = { /* nop; outl %eax,0x7e */
+        0xb8, 0x1, 0, 0, 0, 0x90, 0xe7, 0x7e
+    };
+    uint8_t alternates[2];
+    const uint8_t *pattern;
+    const uint8_t *patch;
+    int patches = 0;
+    off_t pos;
+    uint8_t *rom;
+
+    rom = g_malloc(s->rom_size);
+    cpu_physical_memory_rw(rom_paddr, rom, s->rom_size, 0);
+
+    for (pos = 0; pos < s->rom_size - sizeof(vmcall_pattern); pos++) {
+        if (kvm_irqchip_in_kernel()) {
+            pattern = outl_pattern;
+            alternates[0] = outl_pattern[7];
+            alternates[1] = outl_pattern[7];
+            patch = &vmcall_pattern[5];
+        } else {
+            pattern = vmcall_pattern;
+            alternates[0] = vmcall_pattern[7];
+            alternates[1] = 0xd9; /* AMD's VMMCALL */
+            patch = &outl_pattern[5];
+        }
+        if (memcmp(rom + pos, pattern, 7) == 0 &&
+            (rom[pos + 7] == alternates[0] || rom[pos + 7] == alternates[1])) {
+            cpu_physical_memory_rw(rom_paddr + pos + 5, (uint8_t *)patch,
+                                   3, 1);
+            /*
+             * Don't flush the tb here. Under ordinary conditions, the patched
+             * calls are miles away from the current IP. Under malicious
+             * conditions, the guest could trick us to crash.
+             */
+        }
+    }
+
+    g_free(rom);
+
+    if (patches != 0 && patches != 2) {
+        return -1;
+    }
+
+    return 0;
+}
+
+/*
+ * For TCG mode or the time KVM honors read-only memory regions, we need to
+ * enable write access to the option ROM so that variables can be updated by
+ * the guest.
+ */
+static void vapic_map_rom_writable(VAPICROMState *s)
+{
+    hwaddr rom_paddr = s->rom_state_paddr & ROM_BLOCK_MASK;
+    MemoryRegionSection section;
+    MemoryRegion *as;
+    size_t rom_size;
+    uint8_t *ram;
+
+    as = sysbus_address_space(&s->busdev);
+
+    if (s->rom_mapped_writable) {
+        memory_region_del_subregion(as, &s->rom);
+        memory_region_destroy(&s->rom);
+    }
+
+    /* grab RAM memory region (region @rom_paddr may still be pc.rom) */
+    section = memory_region_find(as, 0, 1);
+
+    /* read ROM size from RAM region */
+    ram = memory_region_get_ram_ptr(section.mr);
+    rom_size = ram[rom_paddr + 2] * ROM_BLOCK_SIZE;
+    s->rom_size = rom_size;
+
+    /* We need to round to avoid creating subpages
+     * from which we cannot run code. */
+    rom_size += rom_paddr & ~TARGET_PAGE_MASK;
+    rom_paddr &= TARGET_PAGE_MASK;
+    rom_size = TARGET_PAGE_ALIGN(rom_size);
+
+    memory_region_init_alias(&s->rom, "kvmvapic-rom", section.mr, rom_paddr,
+                             rom_size);
+    memory_region_add_subregion_overlap(as, rom_paddr, &s->rom, 1000);
+    s->rom_mapped_writable = true;
+}
+
+static int vapic_prepare(VAPICROMState *s)
+{
+    vapic_map_rom_writable(s);
+
+    if (patch_hypercalls(s) < 0) {
+        return -1;
+    }
+
+    vapic_enable_tpr_reporting(true);
+
+    return 0;
+}
+
+static void vapic_write(void *opaque, hwaddr addr, uint64_t data,
+                        unsigned int size)
+{
+    CPUX86State *env = cpu_single_env;
+    hwaddr rom_paddr;
+    VAPICROMState *s = opaque;
+
+    cpu_synchronize_state(env);
+
+    /*
+     * The VAPIC supports two PIO-based hypercalls, both via port 0x7E.
+     *  o 16-bit write access:
+     *    Reports the option ROM initialization to the hypervisor. Written
+     *    value is the offset of the state structure in the ROM.
+     *  o 8-bit write access:
+     *    Reactivates the VAPIC after a guest hibernation, i.e. after the
+     *    option ROM content has been re-initialized by a guest power cycle.
+     *  o 32-bit write access:
+     *    Poll for pending IRQs, considering the current VAPIC state.
+     */
+    switch (size) {
+    case 2:
+        if (s->state == VAPIC_INACTIVE) {
+            rom_paddr = (env->segs[R_CS].base + env->eip) & ROM_BLOCK_MASK;
+            s->rom_state_paddr = rom_paddr + data;
+
+            s->state = VAPIC_STANDBY;
+        }
+        if (vapic_prepare(s) < 0) {
+            s->state = VAPIC_INACTIVE;
+            break;
+        }
+        break;
+    case 1:
+        if (kvm_enabled()) {
+            /*
+             * Disable triggering instruction in ROM by writing a NOP.
+             *
+             * We cannot do this in TCG mode as the reported IP is not
+             * accurate.
+             */
+            pause_all_vcpus();
+            patch_byte(env, env->eip - 2, 0x66);
+            patch_byte(env, env->eip - 1, 0x90);
+            resume_all_vcpus();
+        }
+
+        if (s->state == VAPIC_ACTIVE) {
+            break;
+        }
+        if (update_rom_mapping(s, env, env->eip) < 0) {
+            break;
+        }
+        if (find_real_tpr_addr(s, env) < 0) {
+            break;
+        }
+        vapic_enable(s, env);
+        break;
+    default:
+    case 4:
+        if (!kvm_irqchip_in_kernel()) {
+            apic_poll_irq(env->apic_state);
+        }
+        break;
+    }
+}
+
+static const MemoryRegionOps vapic_ops = {
+    .write = vapic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int vapic_init(SysBusDevice *dev)
+{
+    VAPICROMState *s = FROM_SYSBUS(VAPICROMState, dev);
+
+    memory_region_init_io(&s->io, &vapic_ops, s, "kvmvapic", 2);
+    sysbus_add_io(dev, VAPIC_IO_PORT, &s->io);
+    sysbus_init_ioports(dev, VAPIC_IO_PORT, 2);
+
+    option_rom[nb_option_roms].name = "kvmvapic.bin";
+    option_rom[nb_option_roms].bootindex = -1;
+    nb_option_roms++;
+
+    return 0;
+}
+
+static void do_vapic_enable(void *data)
+{
+    VAPICROMState *s = data;
+
+    vapic_enable(s, first_cpu);
+}
+
+static int vapic_post_load(void *opaque, int version_id)
+{
+    VAPICROMState *s = opaque;
+    uint8_t *zero;
+
+    /*
+     * The old implementation of qemu-kvm did not provide the state
+     * VAPIC_STANDBY. Reconstruct it.
+     */
+    if (s->state == VAPIC_INACTIVE && s->rom_state_paddr != 0) {
+        s->state = VAPIC_STANDBY;
+    }
+
+    if (s->state != VAPIC_INACTIVE) {
+        if (vapic_prepare(s) < 0) {
+            return -1;
+        }
+    }
+    if (s->state == VAPIC_ACTIVE) {
+        if (smp_cpus == 1) {
+            run_on_cpu(ENV_GET_CPU(first_cpu), do_vapic_enable, s);
+        } else {
+            zero = g_malloc0(s->rom_state.vapic_size);
+            cpu_physical_memory_rw(s->vapic_paddr, zero,
+                                   s->rom_state.vapic_size, 1);
+            g_free(zero);
+        }
+    }
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_handlers = {
+    .name = "kvmvapic-handlers",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(set_tpr, VAPICHandlers),
+        VMSTATE_UINT32(set_tpr_eax, VAPICHandlers),
+        VMSTATE_UINT32_ARRAY(get_tpr, VAPICHandlers, 8),
+        VMSTATE_UINT32(get_tpr_stack, VAPICHandlers),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_guest_rom = {
+    .name = "kvmvapic-guest-rom",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UNUSED(8),     /* signature */
+        VMSTATE_UINT32(vaddr, GuestROMState),
+        VMSTATE_UINT32(fixup_start, GuestROMState),
+        VMSTATE_UINT32(fixup_end, GuestROMState),
+        VMSTATE_UINT32(vapic_vaddr, GuestROMState),
+        VMSTATE_UINT32(vapic_size, GuestROMState),
+        VMSTATE_UINT32(vcpu_shift, GuestROMState),
+        VMSTATE_UINT32(real_tpr_addr, GuestROMState),
+        VMSTATE_STRUCT(up, GuestROMState, 0, vmstate_handlers, VAPICHandlers),
+        VMSTATE_STRUCT(mp, GuestROMState, 0, vmstate_handlers, VAPICHandlers),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_vapic = {
+    .name = "kvm-tpr-opt",      /* compatible with qemu-kvm VAPIC */
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = vapic_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT(rom_state, VAPICROMState, 0, vmstate_guest_rom,
+                       GuestROMState),
+        VMSTATE_UINT32(state, VAPICROMState),
+        VMSTATE_UINT32(real_tpr_addr, VAPICROMState),
+        VMSTATE_UINT32(rom_state_vaddr, VAPICROMState),
+        VMSTATE_UINT32(vapic_paddr, VAPICROMState),
+        VMSTATE_UINT32(rom_state_paddr, VAPICROMState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void vapic_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->no_user = 1;
+    dc->reset   = vapic_reset;
+    dc->vmsd    = &vmstate_vapic;
+    sc->init    = vapic_init;
+}
+
+static const TypeInfo vapic_type = {
+    .name          = "kvmvapic",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(VAPICROMState),
+    .class_init    = vapic_class_init,
+};
+
+static void vapic_register(void)
+{
+    type_register_static(&vapic_type);
+}
+
+type_init(vapic_register);
diff --git a/hw/kvmvapic.c b/hw/kvmvapic.c
deleted file mode 100644
index c151c95..0000000
--- a/hw/kvmvapic.c
+++ /dev/null
@@ -1,822 +0,0 @@
-/*
- * TPR optimization for 32-bit Windows guests (XP and Server 2003)
- *
- * Copyright (C) 2007-2008 Qumranet Technologies
- * Copyright (C) 2012      Jan Kiszka, Siemens AG
- *
- * This work is licensed under the terms of the GNU GPL version 2, or
- * (at your option) any later version. See the COPYING file in the
- * top-level directory.
- */
-#include "sysemu/sysemu.h"
-#include "sysemu/cpus.h"
-#include "sysemu/kvm.h"
-#include "hw/apic_internal.h"
-
-#define APIC_DEFAULT_ADDRESS    0xfee00000
-
-#define VAPIC_IO_PORT           0x7e
-
-#define VAPIC_CPU_SHIFT         7
-
-#define ROM_BLOCK_SIZE          512
-#define ROM_BLOCK_MASK          (~(ROM_BLOCK_SIZE - 1))
-
-typedef enum VAPICMode {
-    VAPIC_INACTIVE = 0,
-    VAPIC_ACTIVE   = 1,
-    VAPIC_STANDBY  = 2,
-} VAPICMode;
-
-typedef struct VAPICHandlers {
-    uint32_t set_tpr;
-    uint32_t set_tpr_eax;
-    uint32_t get_tpr[8];
-    uint32_t get_tpr_stack;
-} QEMU_PACKED VAPICHandlers;
-
-typedef struct GuestROMState {
-    char signature[8];
-    uint32_t vaddr;
-    uint32_t fixup_start;
-    uint32_t fixup_end;
-    uint32_t vapic_vaddr;
-    uint32_t vapic_size;
-    uint32_t vcpu_shift;
-    uint32_t real_tpr_addr;
-    VAPICHandlers up;
-    VAPICHandlers mp;
-} QEMU_PACKED GuestROMState;
-
-typedef struct VAPICROMState {
-    SysBusDevice busdev;
-    MemoryRegion io;
-    MemoryRegion rom;
-    uint32_t state;
-    uint32_t rom_state_paddr;
-    uint32_t rom_state_vaddr;
-    uint32_t vapic_paddr;
-    uint32_t real_tpr_addr;
-    GuestROMState rom_state;
-    size_t rom_size;
-    bool rom_mapped_writable;
-} VAPICROMState;
-
-#define TPR_INSTR_ABS_MODRM             0x1
-#define TPR_INSTR_MATCH_MODRM_REG       0x2
-
-typedef struct TPRInstruction {
-    uint8_t opcode;
-    uint8_t modrm_reg;
-    unsigned int flags;
-    TPRAccess access;
-    size_t length;
-    off_t addr_offset;
-} TPRInstruction;
-
-/* must be sorted by length, shortest first */
-static const TPRInstruction tpr_instr[] = {
-    { /* mov abs to eax */
-        .opcode = 0xa1,
-        .access = TPR_ACCESS_READ,
-        .length = 5,
-        .addr_offset = 1,
-    },
-    { /* mov eax to abs */
-        .opcode = 0xa3,
-        .access = TPR_ACCESS_WRITE,
-        .length = 5,
-        .addr_offset = 1,
-    },
-    { /* mov r32 to r/m32 */
-        .opcode = 0x89,
-        .flags = TPR_INSTR_ABS_MODRM,
-        .access = TPR_ACCESS_WRITE,
-        .length = 6,
-        .addr_offset = 2,
-    },
-    { /* mov r/m32 to r32 */
-        .opcode = 0x8b,
-        .flags = TPR_INSTR_ABS_MODRM,
-        .access = TPR_ACCESS_READ,
-        .length = 6,
-        .addr_offset = 2,
-    },
-    { /* push r/m32 */
-        .opcode = 0xff,
-        .modrm_reg = 6,
-        .flags = TPR_INSTR_ABS_MODRM | TPR_INSTR_MATCH_MODRM_REG,
-        .access = TPR_ACCESS_READ,
-        .length = 6,
-        .addr_offset = 2,
-    },
-    { /* mov imm32, r/m32 (c7/0) */
-        .opcode = 0xc7,
-        .modrm_reg = 0,
-        .flags = TPR_INSTR_ABS_MODRM | TPR_INSTR_MATCH_MODRM_REG,
-        .access = TPR_ACCESS_WRITE,
-        .length = 10,
-        .addr_offset = 2,
-    },
-};
-
-static void read_guest_rom_state(VAPICROMState *s)
-{
-    cpu_physical_memory_rw(s->rom_state_paddr, (void *)&s->rom_state,
-                           sizeof(GuestROMState), 0);
-}
-
-static void write_guest_rom_state(VAPICROMState *s)
-{
-    cpu_physical_memory_rw(s->rom_state_paddr, (void *)&s->rom_state,
-                           sizeof(GuestROMState), 1);
-}
-
-static void update_guest_rom_state(VAPICROMState *s)
-{
-    read_guest_rom_state(s);
-
-    s->rom_state.real_tpr_addr = cpu_to_le32(s->real_tpr_addr);
-    s->rom_state.vcpu_shift = cpu_to_le32(VAPIC_CPU_SHIFT);
-
-    write_guest_rom_state(s);
-}
-
-static int find_real_tpr_addr(VAPICROMState *s, CPUX86State *env)
-{
-    hwaddr paddr;
-    target_ulong addr;
-
-    if (s->state == VAPIC_ACTIVE) {
-        return 0;
-    }
-    /*
-     * If there is no prior TPR access instruction we could analyze (which is
-     * the case after resume from hibernation), we need to scan the possible
-     * virtual address space for the APIC mapping.
-     */
-    for (addr = 0xfffff000; addr >= 0x80000000; addr -= TARGET_PAGE_SIZE) {
-        paddr = cpu_get_phys_page_debug(env, addr);
-        if (paddr != APIC_DEFAULT_ADDRESS) {
-            continue;
-        }
-        s->real_tpr_addr = addr + 0x80;
-        update_guest_rom_state(s);
-        return 0;
-    }
-    return -1;
-}
-
-static uint8_t modrm_reg(uint8_t modrm)
-{
-    return (modrm >> 3) & 7;
-}
-
-static bool is_abs_modrm(uint8_t modrm)
-{
-    return (modrm & 0xc7) == 0x05;
-}
-
-static bool opcode_matches(uint8_t *opcode, const TPRInstruction *instr)
-{
-    return opcode[0] == instr->opcode &&
-        (!(instr->flags & TPR_INSTR_ABS_MODRM) || is_abs_modrm(opcode[1])) &&
-        (!(instr->flags & TPR_INSTR_MATCH_MODRM_REG) ||
-         modrm_reg(opcode[1]) == instr->modrm_reg);
-}
-
-static int evaluate_tpr_instruction(VAPICROMState *s, CPUX86State *env,
-                                    target_ulong *pip, TPRAccess access)
-{
-    const TPRInstruction *instr;
-    target_ulong ip = *pip;
-    uint8_t opcode[2];
-    uint32_t real_tpr_addr;
-    int i;
-
-    if ((ip & 0xf0000000ULL) != 0x80000000ULL &&
-        (ip & 0xf0000000ULL) != 0xe0000000ULL) {
-        return -1;
-    }
-
-    /*
-     * Early Windows 2003 SMP initialization contains a
-     *
-     *   mov imm32, r/m32
-     *
-     * instruction that is patched by TPR optimization. The problem is that
-     * RSP, used by the patched instruction, is zero, so the guest gets a
-     * double fault and dies.
-     */
-    if (env->regs[R_ESP] == 0) {
-        return -1;
-    }
-
-    if (kvm_enabled() && !kvm_irqchip_in_kernel()) {
-        /*
-         * KVM without kernel-based TPR access reporting will pass an IP that
-         * points after the accessing instruction. So we need to look backward
-         * to find the reason.
-         */
-        for (i = 0; i < ARRAY_SIZE(tpr_instr); i++) {
-            instr = &tpr_instr[i];
-            if (instr->access != access) {
-                continue;
-            }
-            if (cpu_memory_rw_debug(env, ip - instr->length, opcode,
-                                    sizeof(opcode), 0) < 0) {
-                return -1;
-            }
-            if (opcode_matches(opcode, instr)) {
-                ip -= instr->length;
-                goto instruction_ok;
-            }
-        }
-        return -1;
-    } else {
-        if (cpu_memory_rw_debug(env, ip, opcode, sizeof(opcode), 0) < 0) {
-            return -1;
-        }
-        for (i = 0; i < ARRAY_SIZE(tpr_instr); i++) {
-            instr = &tpr_instr[i];
-            if (opcode_matches(opcode, instr)) {
-                goto instruction_ok;
-            }
-        }
-        return -1;
-    }
-
-instruction_ok:
-    /*
-     * Grab the virtual TPR address from the instruction
-     * and update the cached values.
-     */
-    if (cpu_memory_rw_debug(env, ip + instr->addr_offset,
-                            (void *)&real_tpr_addr,
-                            sizeof(real_tpr_addr), 0) < 0) {
-        return -1;
-    }
-    real_tpr_addr = le32_to_cpu(real_tpr_addr);
-    if ((real_tpr_addr & 0xfff) != 0x80) {
-        return -1;
-    }
-    s->real_tpr_addr = real_tpr_addr;
-    update_guest_rom_state(s);
-
-    *pip = ip;
-    return 0;
-}
-
-static int update_rom_mapping(VAPICROMState *s, CPUX86State *env, target_ulong ip)
-{
-    hwaddr paddr;
-    uint32_t rom_state_vaddr;
-    uint32_t pos, patch, offset;
-
-    /* nothing to do if already activated */
-    if (s->state == VAPIC_ACTIVE) {
-        return 0;
-    }
-
-    /* bail out if ROM init code was not executed (missing ROM?) */
-    if (s->state == VAPIC_INACTIVE) {
-        return -1;
-    }
-
-    /* find out virtual address of the ROM */
-    rom_state_vaddr = s->rom_state_paddr + (ip & 0xf0000000);
-    paddr = cpu_get_phys_page_debug(env, rom_state_vaddr);
-    if (paddr == -1) {
-        return -1;
-    }
-    paddr += rom_state_vaddr & ~TARGET_PAGE_MASK;
-    if (paddr != s->rom_state_paddr) {
-        return -1;
-    }
-    read_guest_rom_state(s);
-    if (memcmp(s->rom_state.signature, "kvm aPiC", 8) != 0) {
-        return -1;
-    }
-    s->rom_state_vaddr = rom_state_vaddr;
-
-    /* fixup addresses in ROM if needed */
-    if (rom_state_vaddr == le32_to_cpu(s->rom_state.vaddr)) {
-        return 0;
-    }
-    for (pos = le32_to_cpu(s->rom_state.fixup_start);
-         pos < le32_to_cpu(s->rom_state.fixup_end);
-         pos += 4) {
-        cpu_physical_memory_rw(paddr + pos - s->rom_state.vaddr,
-                               (void *)&offset, sizeof(offset), 0);
-        offset = le32_to_cpu(offset);
-        cpu_physical_memory_rw(paddr + offset, (void *)&patch,
-                               sizeof(patch), 0);
-        patch = le32_to_cpu(patch);
-        patch += rom_state_vaddr - le32_to_cpu(s->rom_state.vaddr);
-        patch = cpu_to_le32(patch);
-        cpu_physical_memory_rw(paddr + offset, (void *)&patch,
-                               sizeof(patch), 1);
-    }
-    read_guest_rom_state(s);
-    s->vapic_paddr = paddr + le32_to_cpu(s->rom_state.vapic_vaddr) -
-        le32_to_cpu(s->rom_state.vaddr);
-
-    return 0;
-}
-
-/*
- * Tries to read the unique processor number from the Kernel Processor Control
- * Region (KPCR) of 32-bit Windows XP and Server 2003. Returns -1 if the KPCR
- * cannot be accessed or is considered invalid. This also ensures that we are
- * not patching the wrong guest.
- */
-static int get_kpcr_number(CPUX86State *env)
-{
-    struct kpcr {
-        uint8_t  fill1[0x1c];
-        uint32_t self;
-        uint8_t  fill2[0x31];
-        uint8_t  number;
-    } QEMU_PACKED kpcr;
-
-    if (cpu_memory_rw_debug(env, env->segs[R_FS].base,
-                            (void *)&kpcr, sizeof(kpcr), 0) < 0 ||
-        kpcr.self != env->segs[R_FS].base) {
-        return -1;
-    }
-    return kpcr.number;
-}
-
-static int vapic_enable(VAPICROMState *s, CPUX86State *env)
-{
-    int cpu_number = get_kpcr_number(env);
-    hwaddr vapic_paddr;
-    static const uint8_t enabled = 1;
-
-    if (cpu_number < 0) {
-        return -1;
-    }
-    vapic_paddr = s->vapic_paddr +
-        (((hwaddr)cpu_number) << VAPIC_CPU_SHIFT);
-    cpu_physical_memory_rw(vapic_paddr + offsetof(VAPICState, enabled),
-                           (void *)&enabled, sizeof(enabled), 1);
-    apic_enable_vapic(env->apic_state, vapic_paddr);
-
-    s->state = VAPIC_ACTIVE;
-
-    return 0;
-}
-
-static void patch_byte(CPUX86State *env, target_ulong addr, uint8_t byte)
-{
-    cpu_memory_rw_debug(env, addr, &byte, 1, 1);
-}
-
-static void patch_call(VAPICROMState *s, CPUX86State *env, target_ulong ip,
-                       uint32_t target)
-{
-    uint32_t offset;
-
-    offset = cpu_to_le32(target - ip - 5);
-    patch_byte(env, ip, 0xe8); /* call near */
-    cpu_memory_rw_debug(env, ip + 1, (void *)&offset, sizeof(offset), 1);
-}
-
-static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
-{
-    CPUState *cs = CPU(cpu);
-    CPUX86State *env = &cpu->env;
-    VAPICHandlers *handlers;
-    uint8_t opcode[2];
-    uint32_t imm32;
-    target_ulong current_pc = 0;
-    target_ulong current_cs_base = 0;
-    int current_flags = 0;
-
-    if (smp_cpus == 1) {
-        handlers = &s->rom_state.up;
-    } else {
-        handlers = &s->rom_state.mp;
-    }
-
-    if (!kvm_enabled()) {
-        cpu_restore_state(env, env->mem_io_pc);
-        cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
-                             &current_flags);
-    }
-
-    pause_all_vcpus();
-
-    cpu_memory_rw_debug(env, ip, opcode, sizeof(opcode), 0);
-
-    switch (opcode[0]) {
-    case 0x89: /* mov r32 to r/m32 */
-        patch_byte(env, ip, 0x50 + modrm_reg(opcode[1]));  /* push reg */
-        patch_call(s, env, ip + 1, handlers->set_tpr);
-        break;
-    case 0x8b: /* mov r/m32 to r32 */
-        patch_byte(env, ip, 0x90);
-        patch_call(s, env, ip + 1, handlers->get_tpr[modrm_reg(opcode[1])]);
-        break;
-    case 0xa1: /* mov abs to eax */
-        patch_call(s, env, ip, handlers->get_tpr[0]);
-        break;
-    case 0xa3: /* mov eax to abs */
-        patch_call(s, env, ip, handlers->set_tpr_eax);
-        break;
-    case 0xc7: /* mov imm32, r/m32 (c7/0) */
-        patch_byte(env, ip, 0x68);  /* push imm32 */
-        cpu_memory_rw_debug(env, ip + 6, (void *)&imm32, sizeof(imm32), 0);
-        cpu_memory_rw_debug(env, ip + 1, (void *)&imm32, sizeof(imm32), 1);
-        patch_call(s, env, ip + 5, handlers->set_tpr);
-        break;
-    case 0xff: /* push r/m32 */
-        patch_byte(env, ip, 0x50); /* push eax */
-        patch_call(s, env, ip + 1, handlers->get_tpr_stack);
-        break;
-    default:
-        abort();
-    }
-
-    resume_all_vcpus();
-
-    if (!kvm_enabled()) {
-        cs->current_tb = NULL;
-        tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
-        cpu_resume_from_signal(env, NULL);
-    }
-}
-
-void vapic_report_tpr_access(DeviceState *dev, CPUState *cs, target_ulong ip,
-                             TPRAccess access)
-{
-    VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev);
-    X86CPU *cpu = X86_CPU(cs);
-    CPUX86State *env = &cpu->env;
-
-    cpu_synchronize_state(env);
-
-    if (evaluate_tpr_instruction(s, env, &ip, access) < 0) {
-        if (s->state == VAPIC_ACTIVE) {
-            vapic_enable(s, env);
-        }
-        return;
-    }
-    if (update_rom_mapping(s, env, ip) < 0) {
-        return;
-    }
-    if (vapic_enable(s, env) < 0) {
-        return;
-    }
-    patch_instruction(s, cpu, ip);
-}
-
-typedef struct VAPICEnableTPRReporting {
-    DeviceState *apic;
-    bool enable;
-} VAPICEnableTPRReporting;
-
-static void vapic_do_enable_tpr_reporting(void *data)
-{
-    VAPICEnableTPRReporting *info = data;
-
-    apic_enable_tpr_access_reporting(info->apic, info->enable);
-}
-
-static void vapic_enable_tpr_reporting(bool enable)
-{
-    VAPICEnableTPRReporting info = {
-        .enable = enable,
-    };
-    X86CPU *cpu;
-    CPUX86State *env;
-
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu = x86_env_get_cpu(env);
-        info.apic = env->apic_state;
-        run_on_cpu(CPU(cpu), vapic_do_enable_tpr_reporting, &info);
-    }
-}
-
-static void vapic_reset(DeviceState *dev)
-{
-    VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev);
-
-    if (s->state == VAPIC_ACTIVE) {
-        s->state = VAPIC_STANDBY;
-    }
-    vapic_enable_tpr_reporting(false);
-}
-
-/*
- * Set the IRQ polling hypercalls to the supported variant:
- *  - vmcall if using KVM in-kernel irqchip
- *  - 32-bit VAPIC port write otherwise
- */
-static int patch_hypercalls(VAPICROMState *s)
-{
-    hwaddr rom_paddr = s->rom_state_paddr & ROM_BLOCK_MASK;
-    static const uint8_t vmcall_pattern[] = { /* vmcall */
-        0xb8, 0x1, 0, 0, 0, 0xf, 0x1, 0xc1
-    };
-    static const uint8_t outl_pattern[] = { /* nop; outl %eax,0x7e */
-        0xb8, 0x1, 0, 0, 0, 0x90, 0xe7, 0x7e
-    };
-    uint8_t alternates[2];
-    const uint8_t *pattern;
-    const uint8_t *patch;
-    int patches = 0;
-    off_t pos;
-    uint8_t *rom;
-
-    rom = g_malloc(s->rom_size);
-    cpu_physical_memory_rw(rom_paddr, rom, s->rom_size, 0);
-
-    for (pos = 0; pos < s->rom_size - sizeof(vmcall_pattern); pos++) {
-        if (kvm_irqchip_in_kernel()) {
-            pattern = outl_pattern;
-            alternates[0] = outl_pattern[7];
-            alternates[1] = outl_pattern[7];
-            patch = &vmcall_pattern[5];
-        } else {
-            pattern = vmcall_pattern;
-            alternates[0] = vmcall_pattern[7];
-            alternates[1] = 0xd9; /* AMD's VMMCALL */
-            patch = &outl_pattern[5];
-        }
-        if (memcmp(rom + pos, pattern, 7) == 0 &&
-            (rom[pos + 7] == alternates[0] || rom[pos + 7] == alternates[1])) {
-            cpu_physical_memory_rw(rom_paddr + pos + 5, (uint8_t *)patch,
-                                   3, 1);
-            /*
-             * Don't flush the tb here. Under ordinary conditions, the patched
-             * calls are miles away from the current IP. Under malicious
-             * conditions, the guest could trick us to crash.
-             */
-        }
-    }
-
-    g_free(rom);
-
-    if (patches != 0 && patches != 2) {
-        return -1;
-    }
-
-    return 0;
-}
-
-/*
- * For TCG mode or the time KVM honors read-only memory regions, we need to
- * enable write access to the option ROM so that variables can be updated by
- * the guest.
- */
-static void vapic_map_rom_writable(VAPICROMState *s)
-{
-    hwaddr rom_paddr = s->rom_state_paddr & ROM_BLOCK_MASK;
-    MemoryRegionSection section;
-    MemoryRegion *as;
-    size_t rom_size;
-    uint8_t *ram;
-
-    as = sysbus_address_space(&s->busdev);
-
-    if (s->rom_mapped_writable) {
-        memory_region_del_subregion(as, &s->rom);
-        memory_region_destroy(&s->rom);
-    }
-
-    /* grab RAM memory region (region @rom_paddr may still be pc.rom) */
-    section = memory_region_find(as, 0, 1);
-
-    /* read ROM size from RAM region */
-    ram = memory_region_get_ram_ptr(section.mr);
-    rom_size = ram[rom_paddr + 2] * ROM_BLOCK_SIZE;
-    s->rom_size = rom_size;
-
-    /* We need to round to avoid creating subpages
-     * from which we cannot run code. */
-    rom_size += rom_paddr & ~TARGET_PAGE_MASK;
-    rom_paddr &= TARGET_PAGE_MASK;
-    rom_size = TARGET_PAGE_ALIGN(rom_size);
-
-    memory_region_init_alias(&s->rom, "kvmvapic-rom", section.mr, rom_paddr,
-                             rom_size);
-    memory_region_add_subregion_overlap(as, rom_paddr, &s->rom, 1000);
-    s->rom_mapped_writable = true;
-}
-
-static int vapic_prepare(VAPICROMState *s)
-{
-    vapic_map_rom_writable(s);
-
-    if (patch_hypercalls(s) < 0) {
-        return -1;
-    }
-
-    vapic_enable_tpr_reporting(true);
-
-    return 0;
-}
-
-static void vapic_write(void *opaque, hwaddr addr, uint64_t data,
-                        unsigned int size)
-{
-    CPUX86State *env = cpu_single_env;
-    hwaddr rom_paddr;
-    VAPICROMState *s = opaque;
-
-    cpu_synchronize_state(env);
-
-    /*
-     * The VAPIC supports two PIO-based hypercalls, both via port 0x7E.
-     *  o 16-bit write access:
-     *    Reports the option ROM initialization to the hypervisor. Written
-     *    value is the offset of the state structure in the ROM.
-     *  o 8-bit write access:
-     *    Reactivates the VAPIC after a guest hibernation, i.e. after the
-     *    option ROM content has been re-initialized by a guest power cycle.
-     *  o 32-bit write access:
-     *    Poll for pending IRQs, considering the current VAPIC state.
-     */
-    switch (size) {
-    case 2:
-        if (s->state == VAPIC_INACTIVE) {
-            rom_paddr = (env->segs[R_CS].base + env->eip) & ROM_BLOCK_MASK;
-            s->rom_state_paddr = rom_paddr + data;
-
-            s->state = VAPIC_STANDBY;
-        }
-        if (vapic_prepare(s) < 0) {
-            s->state = VAPIC_INACTIVE;
-            break;
-        }
-        break;
-    case 1:
-        if (kvm_enabled()) {
-            /*
-             * Disable triggering instruction in ROM by writing a NOP.
-             *
-             * We cannot do this in TCG mode as the reported IP is not
-             * accurate.
-             */
-            pause_all_vcpus();
-            patch_byte(env, env->eip - 2, 0x66);
-            patch_byte(env, env->eip - 1, 0x90);
-            resume_all_vcpus();
-        }
-
-        if (s->state == VAPIC_ACTIVE) {
-            break;
-        }
-        if (update_rom_mapping(s, env, env->eip) < 0) {
-            break;
-        }
-        if (find_real_tpr_addr(s, env) < 0) {
-            break;
-        }
-        vapic_enable(s, env);
-        break;
-    default:
-    case 4:
-        if (!kvm_irqchip_in_kernel()) {
-            apic_poll_irq(env->apic_state);
-        }
-        break;
-    }
-}
-
-static const MemoryRegionOps vapic_ops = {
-    .write = vapic_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int vapic_init(SysBusDevice *dev)
-{
-    VAPICROMState *s = FROM_SYSBUS(VAPICROMState, dev);
-
-    memory_region_init_io(&s->io, &vapic_ops, s, "kvmvapic", 2);
-    sysbus_add_io(dev, VAPIC_IO_PORT, &s->io);
-    sysbus_init_ioports(dev, VAPIC_IO_PORT, 2);
-
-    option_rom[nb_option_roms].name = "kvmvapic.bin";
-    option_rom[nb_option_roms].bootindex = -1;
-    nb_option_roms++;
-
-    return 0;
-}
-
-static void do_vapic_enable(void *data)
-{
-    VAPICROMState *s = data;
-
-    vapic_enable(s, first_cpu);
-}
-
-static int vapic_post_load(void *opaque, int version_id)
-{
-    VAPICROMState *s = opaque;
-    uint8_t *zero;
-
-    /*
-     * The old implementation of qemu-kvm did not provide the state
-     * VAPIC_STANDBY. Reconstruct it.
-     */
-    if (s->state == VAPIC_INACTIVE && s->rom_state_paddr != 0) {
-        s->state = VAPIC_STANDBY;
-    }
-
-    if (s->state != VAPIC_INACTIVE) {
-        if (vapic_prepare(s) < 0) {
-            return -1;
-        }
-    }
-    if (s->state == VAPIC_ACTIVE) {
-        if (smp_cpus == 1) {
-            run_on_cpu(ENV_GET_CPU(first_cpu), do_vapic_enable, s);
-        } else {
-            zero = g_malloc0(s->rom_state.vapic_size);
-            cpu_physical_memory_rw(s->vapic_paddr, zero,
-                                   s->rom_state.vapic_size, 1);
-            g_free(zero);
-        }
-    }
-
-    return 0;
-}
-
-static const VMStateDescription vmstate_handlers = {
-    .name = "kvmvapic-handlers",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(set_tpr, VAPICHandlers),
-        VMSTATE_UINT32(set_tpr_eax, VAPICHandlers),
-        VMSTATE_UINT32_ARRAY(get_tpr, VAPICHandlers, 8),
-        VMSTATE_UINT32(get_tpr_stack, VAPICHandlers),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription vmstate_guest_rom = {
-    .name = "kvmvapic-guest-rom",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UNUSED(8),     /* signature */
-        VMSTATE_UINT32(vaddr, GuestROMState),
-        VMSTATE_UINT32(fixup_start, GuestROMState),
-        VMSTATE_UINT32(fixup_end, GuestROMState),
-        VMSTATE_UINT32(vapic_vaddr, GuestROMState),
-        VMSTATE_UINT32(vapic_size, GuestROMState),
-        VMSTATE_UINT32(vcpu_shift, GuestROMState),
-        VMSTATE_UINT32(real_tpr_addr, GuestROMState),
-        VMSTATE_STRUCT(up, GuestROMState, 0, vmstate_handlers, VAPICHandlers),
-        VMSTATE_STRUCT(mp, GuestROMState, 0, vmstate_handlers, VAPICHandlers),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription vmstate_vapic = {
-    .name = "kvm-tpr-opt",      /* compatible with qemu-kvm VAPIC */
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .post_load = vapic_post_load,
-    .fields = (VMStateField[]) {
-        VMSTATE_STRUCT(rom_state, VAPICROMState, 0, vmstate_guest_rom,
-                       GuestROMState),
-        VMSTATE_UINT32(state, VAPICROMState),
-        VMSTATE_UINT32(real_tpr_addr, VAPICROMState),
-        VMSTATE_UINT32(rom_state_vaddr, VAPICROMState),
-        VMSTATE_UINT32(vapic_paddr, VAPICROMState),
-        VMSTATE_UINT32(rom_state_paddr, VAPICROMState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void vapic_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sc = SYS_BUS_DEVICE_CLASS(klass);
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    dc->no_user = 1;
-    dc->reset   = vapic_reset;
-    dc->vmsd    = &vmstate_vapic;
-    sc->init    = vapic_init;
-}
-
-static const TypeInfo vapic_type = {
-    .name          = "kvmvapic",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(VAPICROMState),
-    .class_init    = vapic_class_init,
-};
-
-static void vapic_register(void)
-{
-    type_register_static(&vapic_type);
-}
-
-type_init(vapic_register);
commit dd285b06490d7ef5f7b2f5e6c87b85ddf4345078
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Feb 5 15:22:56 2013 +0100

    arm: move files referencing CPU to hw/arm/
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index c09cc3a..aebbc86 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -3,18 +3,18 @@ obj-y += xilinx_spips.o
 obj-y += arm_gic.o arm_gic_common.o
 obj-y += a9scu.o
 obj-y += realview_gic.o arm_sysctl.o arm11mpcore.o a9mpcore.o
-obj-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
+obj-y += exynos4210_gic.o exynos4210_combiner.o
 obj-y += exynos4210_uart.o exynos4210_pwm.o
 obj-y += exynos4210_pmu.o exynos4210_mct.o exynos4210_fimd.o
 obj-y += exynos4210_rtc.o exynos4210_i2c.o
 obj-y += arm_mptimer.o a15mpcore.o
-obj-y += armv7m.o armv7m_nvic.o stellaris_enet.o
-obj-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
+obj-y += armv7m_nvic.o stellaris_enet.o
+obj-y += pxa2xx_timer.o pxa2xx_dma.o
 obj-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
 obj-y += zaurus.o ide/microdrive.o tc6393xb.o
-obj-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o \
+obj-y += omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o \
                 omap_gpio.o omap_intc.o omap_uart.o
-obj-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
+obj-y += omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
                 omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o omap_l4.o
 obj-y += tsc210x.o
 obj-y += blizzard.o onenand.o cbus.o tusb6010.o usb/hcd-musb.o
@@ -30,3 +30,6 @@ obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
 obj-y += integratorcp.o kzm.o mainstone.o musicpal.o nseries.o
 obj-y += omap_sx1.o palm.o pic_cpu.o realview.o spitz.o stellaris.o
 obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
+
+obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
+obj-y += omap1.o omap2.o
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
new file mode 100644
index 0000000..1d5bb59
--- /dev/null
+++ b/hw/arm/armv7m.c
@@ -0,0 +1,284 @@
+/*
+ * ARMV7M System emulation.
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/loader.h"
+#include "elf.h"
+
+/* Bitbanded IO.  Each word corresponds to a single bit.  */
+
+/* Get the byte address of the real memory for a bitband access.  */
+static inline uint32_t bitband_addr(void * opaque, uint32_t addr)
+{
+    uint32_t res;
+
+    res = *(uint32_t *)opaque;
+    res |= (addr & 0x1ffffff) >> 5;
+    return res;
+
+}
+
+static uint32_t bitband_readb(void *opaque, hwaddr offset)
+{
+    uint8_t v;
+    cpu_physical_memory_read(bitband_addr(opaque, offset), &v, 1);
+    return (v & (1 << ((offset >> 2) & 7))) != 0;
+}
+
+static void bitband_writeb(void *opaque, hwaddr offset,
+                           uint32_t value)
+{
+    uint32_t addr;
+    uint8_t mask;
+    uint8_t v;
+    addr = bitband_addr(opaque, offset);
+    mask = (1 << ((offset >> 2) & 7));
+    cpu_physical_memory_read(addr, &v, 1);
+    if (value & 1)
+        v |= mask;
+    else
+        v &= ~mask;
+    cpu_physical_memory_write(addr, &v, 1);
+}
+
+static uint32_t bitband_readw(void *opaque, hwaddr offset)
+{
+    uint32_t addr;
+    uint16_t mask;
+    uint16_t v;
+    addr = bitband_addr(opaque, offset) & ~1;
+    mask = (1 << ((offset >> 2) & 15));
+    mask = tswap16(mask);
+    cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
+    return (v & mask) != 0;
+}
+
+static void bitband_writew(void *opaque, hwaddr offset,
+                           uint32_t value)
+{
+    uint32_t addr;
+    uint16_t mask;
+    uint16_t v;
+    addr = bitband_addr(opaque, offset) & ~1;
+    mask = (1 << ((offset >> 2) & 15));
+    mask = tswap16(mask);
+    cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
+    if (value & 1)
+        v |= mask;
+    else
+        v &= ~mask;
+    cpu_physical_memory_write(addr, (uint8_t *)&v, 2);
+}
+
+static uint32_t bitband_readl(void *opaque, hwaddr offset)
+{
+    uint32_t addr;
+    uint32_t mask;
+    uint32_t v;
+    addr = bitband_addr(opaque, offset) & ~3;
+    mask = (1 << ((offset >> 2) & 31));
+    mask = tswap32(mask);
+    cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
+    return (v & mask) != 0;
+}
+
+static void bitband_writel(void *opaque, hwaddr offset,
+                           uint32_t value)
+{
+    uint32_t addr;
+    uint32_t mask;
+    uint32_t v;
+    addr = bitband_addr(opaque, offset) & ~3;
+    mask = (1 << ((offset >> 2) & 31));
+    mask = tswap32(mask);
+    cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
+    if (value & 1)
+        v |= mask;
+    else
+        v &= ~mask;
+    cpu_physical_memory_write(addr, (uint8_t *)&v, 4);
+}
+
+static const MemoryRegionOps bitband_ops = {
+    .old_mmio = {
+        .read = { bitband_readb, bitband_readw, bitband_readl, },
+        .write = { bitband_writeb, bitband_writew, bitband_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t base;
+} BitBandState;
+
+static int bitband_init(SysBusDevice *dev)
+{
+    BitBandState *s = FROM_SYSBUS(BitBandState, dev);
+
+    memory_region_init_io(&s->iomem, &bitband_ops, &s->base, "bitband",
+                          0x02000000);
+    sysbus_init_mmio(dev, &s->iomem);
+    return 0;
+}
+
+static void armv7m_bitband_init(void)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "ARM,bitband-memory");
+    qdev_prop_set_uint32(dev, "base", 0x20000000);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x22000000);
+
+    dev = qdev_create(NULL, "ARM,bitband-memory");
+    qdev_prop_set_uint32(dev, "base", 0x40000000);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x42000000);
+}
+
+/* Board init.  */
+
+static void armv7m_reset(void *opaque)
+{
+    ARMCPU *cpu = opaque;
+
+    cpu_reset(CPU(cpu));
+}
+
+/* Init CPU and memory for a v7-M based board.
+   flash_size and sram_size are in kb.
+   Returns the NVIC array.  */
+
+qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
+                      int flash_size, int sram_size,
+                      const char *kernel_filename, const char *cpu_model)
+{
+    ARMCPU *cpu;
+    CPUARMState *env;
+    DeviceState *nvic;
+    /* FIXME: make this local state.  */
+    static qemu_irq pic[64];
+    qemu_irq *cpu_pic;
+    int image_size;
+    uint64_t entry;
+    uint64_t lowaddr;
+    int i;
+    int big_endian;
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
+    MemoryRegion *hack = g_new(MemoryRegion, 1);
+
+    flash_size *= 1024;
+    sram_size *= 1024;
+
+    if (cpu_model == NULL) {
+	cpu_model = "cortex-m3";
+    }
+    cpu = cpu_arm_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+#if 0
+    /* > 32Mb SRAM gets complicated because it overlaps the bitband area.
+       We don't have proper commandline options, so allocate half of memory
+       as SRAM, up to a maximum of 32Mb, and the rest as code.  */
+    if (ram_size > (512 + 32) * 1024 * 1024)
+        ram_size = (512 + 32) * 1024 * 1024;
+    sram_size = (ram_size / 2) & TARGET_PAGE_MASK;
+    if (sram_size > 32 * 1024 * 1024)
+        sram_size = 32 * 1024 * 1024;
+    code_size = ram_size - sram_size;
+#endif
+
+    /* Flash programming is done via the SCU, so pretend it is ROM.  */
+    memory_region_init_ram(flash, "armv7m.flash", flash_size);
+    vmstate_register_ram_global(flash);
+    memory_region_set_readonly(flash, true);
+    memory_region_add_subregion(address_space_mem, 0, flash);
+    memory_region_init_ram(sram, "armv7m.sram", sram_size);
+    vmstate_register_ram_global(sram);
+    memory_region_add_subregion(address_space_mem, 0x20000000, sram);
+    armv7m_bitband_init();
+
+    nvic = qdev_create(NULL, "armv7m_nvic");
+    env->nvic = nvic;
+    qdev_init_nofail(nvic);
+    cpu_pic = arm_pic_init_cpu(cpu);
+    sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]);
+    for (i = 0; i < 64; i++) {
+        pic[i] = qdev_get_gpio_in(nvic, i);
+    }
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    big_endian = 1;
+#else
+    big_endian = 0;
+#endif
+
+    if (!kernel_filename) {
+        fprintf(stderr, "Guest image must be specified (using -kernel)\n");
+        exit(1);
+    }
+
+    image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
+                          NULL, big_endian, ELF_MACHINE, 1);
+    if (image_size < 0) {
+        image_size = load_image_targphys(kernel_filename, 0, flash_size);
+	lowaddr = 0;
+    }
+    if (image_size < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                kernel_filename);
+        exit(1);
+    }
+
+    /* Hack to map an additional page of ram at the top of the address
+       space.  This stops qemu complaining about executing code outside RAM
+       when returning from an exception.  */
+    memory_region_init_ram(hack, "armv7m.hack", 0x1000);
+    vmstate_register_ram_global(hack);
+    memory_region_add_subregion(address_space_mem, 0xfffff000, hack);
+
+    qemu_register_reset(armv7m_reset, cpu);
+    return pic;
+}
+
+static Property bitband_properties[] = {
+    DEFINE_PROP_UINT32("base", BitBandState, base, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void bitband_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = bitband_init;
+    dc->props = bitband_properties;
+}
+
+static const TypeInfo bitband_info = {
+    .name          = "ARM,bitband-memory",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(BitBandState),
+    .class_init    = bitband_class_init,
+};
+
+static void armv7m_register_types(void)
+{
+    type_register_static(&bitband_info);
+}
+
+type_init(armv7m_register_types)
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
new file mode 100644
index 0000000..4592514
--- /dev/null
+++ b/hw/arm/exynos4210.c
@@ -0,0 +1,349 @@
+/*
+ *  Samsung exynos4210 SoC emulation
+ *
+ *  Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *    Maksim Kozlov <m.kozlov at samsung.com>
+ *    Evgeny Voevodin <e.voevodin at samsung.com>
+ *    Igor Mitsyanko  <i.mitsyanko at samsung.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "hw/boards.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/loader.h"
+#include "hw/exynos4210.h"
+#include "hw/usb/hcd-ehci.h"
+
+#define EXYNOS4210_CHIPID_ADDR         0x10000000
+
+/* PWM */
+#define EXYNOS4210_PWM_BASE_ADDR       0x139D0000
+
+/* RTC */
+#define EXYNOS4210_RTC_BASE_ADDR       0x10070000
+
+/* MCT */
+#define EXYNOS4210_MCT_BASE_ADDR       0x10050000
+
+/* I2C */
+#define EXYNOS4210_I2C_SHIFT           0x00010000
+#define EXYNOS4210_I2C_BASE_ADDR       0x13860000
+/* Interrupt Group of External Interrupt Combiner for I2C */
+#define EXYNOS4210_I2C_INTG            27
+#define EXYNOS4210_HDMI_INTG           16
+
+/* UART's definitions */
+#define EXYNOS4210_UART0_BASE_ADDR     0x13800000
+#define EXYNOS4210_UART1_BASE_ADDR     0x13810000
+#define EXYNOS4210_UART2_BASE_ADDR     0x13820000
+#define EXYNOS4210_UART3_BASE_ADDR     0x13830000
+#define EXYNOS4210_UART0_FIFO_SIZE     256
+#define EXYNOS4210_UART1_FIFO_SIZE     64
+#define EXYNOS4210_UART2_FIFO_SIZE     16
+#define EXYNOS4210_UART3_FIFO_SIZE     16
+/* Interrupt Group of External Interrupt Combiner for UART */
+#define EXYNOS4210_UART_INT_GRP        26
+
+/* External GIC */
+#define EXYNOS4210_EXT_GIC_CPU_BASE_ADDR    0x10480000
+#define EXYNOS4210_EXT_GIC_DIST_BASE_ADDR   0x10490000
+
+/* Combiner */
+#define EXYNOS4210_EXT_COMBINER_BASE_ADDR   0x10440000
+#define EXYNOS4210_INT_COMBINER_BASE_ADDR   0x10448000
+
+/* PMU SFR base address */
+#define EXYNOS4210_PMU_BASE_ADDR            0x10020000
+
+/* Display controllers (FIMD) */
+#define EXYNOS4210_FIMD0_BASE_ADDR          0x11C00000
+
+/* EHCI */
+#define EXYNOS4210_EHCI_BASE_ADDR           0x12580000
+
+static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
+                                    0x09, 0x00, 0x00, 0x00 };
+
+void exynos4210_write_secondary(ARMCPU *cpu,
+        const struct arm_boot_info *info)
+{
+    int n;
+    uint32_t smpboot[] = {
+        0xe59f3034, /* ldr r3, External gic_cpu_if */
+        0xe59f2034, /* ldr r2, Internal gic_cpu_if */
+        0xe59f0034, /* ldr r0, startaddr */
+        0xe3a01001, /* mov r1, #1 */
+        0xe5821000, /* str r1, [r2] */
+        0xe5831000, /* str r1, [r3] */
+        0xe3a010ff, /* mov r1, #0xff */
+        0xe5821004, /* str r1, [r2, #4] */
+        0xe5831004, /* str r1, [r3, #4] */
+        0xf57ff04f, /* dsb */
+        0xe320f003, /* wfi */
+        0xe5901000, /* ldr     r1, [r0] */
+        0xe1110001, /* tst     r1, r1 */
+        0x0afffffb, /* beq     <wfi> */
+        0xe12fff11, /* bx      r1 */
+        EXYNOS4210_EXT_GIC_CPU_BASE_ADDR,
+        0,          /* gic_cpu_if: base address of Internal GIC CPU interface */
+        0           /* bootreg: Boot register address is held here */
+    };
+    smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
+    smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr;
+    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
+        smpboot[n] = tswap32(smpboot[n]);
+    }
+    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
+                       info->smp_loader_start);
+}
+
+Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
+        unsigned long ram_size)
+{
+    qemu_irq cpu_irq[EXYNOS4210_NCPUS];
+    int i, n;
+    Exynos4210State *s = g_new(Exynos4210State, 1);
+    qemu_irq *irqp;
+    qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
+    unsigned long mem_size;
+    DeviceState *dev;
+    SysBusDevice *busdev;
+
+    for (n = 0; n < EXYNOS4210_NCPUS; n++) {
+        s->cpu[n] = cpu_arm_init("cortex-a9");
+        if (!s->cpu[n]) {
+            fprintf(stderr, "Unable to find CPU %d definition\n", n);
+            exit(1);
+        }
+
+        /* Create PIC controller for each processor instance */
+        irqp = arm_pic_init_cpu(s->cpu[n]);
+
+        /*
+         * Get GICs gpio_in cpu_irq to connect a combiner to them later.
+         * Use only IRQ for a while.
+         */
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+    }
+
+    /*** IRQs ***/
+
+    s->irq_table = exynos4210_init_irq(&s->irqs);
+
+    /* IRQ Gate */
+    for (i = 0; i < EXYNOS4210_NCPUS; i++) {
+        dev = qdev_create(NULL, "exynos4210.irq_gate");
+        qdev_prop_set_uint32(dev, "n_in", EXYNOS4210_IRQ_GATE_NINPUTS);
+        qdev_init_nofail(dev);
+        /* Get IRQ Gate input in gate_irq */
+        for (n = 0; n < EXYNOS4210_IRQ_GATE_NINPUTS; n++) {
+            gate_irq[i][n] = qdev_get_gpio_in(dev, n);
+        }
+        busdev = SYS_BUS_DEVICE(dev);
+
+        /* Connect IRQ Gate output to cpu_irq */
+        sysbus_connect_irq(busdev, 0, cpu_irq[i]);
+    }
+
+    /* Private memory region and Internal GIC */
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
+    for (n = 0; n < EXYNOS4210_NCPUS; n++) {
+        sysbus_connect_irq(busdev, n, gate_irq[n][0]);
+    }
+    for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
+        s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    /* Cache controller */
+    sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
+
+    /* External GIC */
+    dev = qdev_create(NULL, "exynos4210.gic");
+    qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    /* Map CPU interface */
+    sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_GIC_CPU_BASE_ADDR);
+    /* Map Distributer interface */
+    sysbus_mmio_map(busdev, 1, EXYNOS4210_EXT_GIC_DIST_BASE_ADDR);
+    for (n = 0; n < EXYNOS4210_NCPUS; n++) {
+        sysbus_connect_irq(busdev, n, gate_irq[n][1]);
+    }
+    for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
+        s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    /* Internal Interrupt Combiner */
+    dev = qdev_create(NULL, "exynos4210.combiner");
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
+        sysbus_connect_irq(busdev, n, s->irqs.int_gic_irq[n]);
+    }
+    exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
+    sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
+
+    /* External Interrupt Combiner */
+    dev = qdev_create(NULL, "exynos4210.combiner");
+    qdev_prop_set_uint32(dev, "external", 1);
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
+        sysbus_connect_irq(busdev, n, s->irqs.ext_gic_irq[n]);
+    }
+    exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
+    sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
+
+    /* Initialize board IRQs. */
+    exynos4210_init_board_irqs(&s->irqs);
+
+    /*** Memory ***/
+
+    /* Chip-ID and OMR */
+    memory_region_init_ram_ptr(&s->chipid_mem, "exynos4210.chipid",
+            sizeof(chipid_and_omr), chipid_and_omr);
+    memory_region_set_readonly(&s->chipid_mem, true);
+    memory_region_add_subregion(system_mem, EXYNOS4210_CHIPID_ADDR,
+                                &s->chipid_mem);
+
+    /* Internal ROM */
+    memory_region_init_ram(&s->irom_mem, "exynos4210.irom",
+                           EXYNOS4210_IROM_SIZE);
+    memory_region_set_readonly(&s->irom_mem, true);
+    memory_region_add_subregion(system_mem, EXYNOS4210_IROM_BASE_ADDR,
+                                &s->irom_mem);
+    /* mirror of iROM */
+    memory_region_init_alias(&s->irom_alias_mem, "exynos4210.irom_alias",
+                             &s->irom_mem,
+                             0,
+                             EXYNOS4210_IROM_SIZE);
+    memory_region_set_readonly(&s->irom_alias_mem, true);
+    memory_region_add_subregion(system_mem, EXYNOS4210_IROM_MIRROR_BASE_ADDR,
+                                &s->irom_alias_mem);
+
+    /* Internal RAM */
+    memory_region_init_ram(&s->iram_mem, "exynos4210.iram",
+                           EXYNOS4210_IRAM_SIZE);
+    vmstate_register_ram_global(&s->iram_mem);
+    memory_region_add_subregion(system_mem, EXYNOS4210_IRAM_BASE_ADDR,
+                                &s->iram_mem);
+
+    /* DRAM */
+    mem_size = ram_size;
+    if (mem_size > EXYNOS4210_DRAM_MAX_SIZE) {
+        memory_region_init_ram(&s->dram1_mem, "exynos4210.dram1",
+                mem_size - EXYNOS4210_DRAM_MAX_SIZE);
+        vmstate_register_ram_global(&s->dram1_mem);
+        memory_region_add_subregion(system_mem, EXYNOS4210_DRAM1_BASE_ADDR,
+                &s->dram1_mem);
+        mem_size = EXYNOS4210_DRAM_MAX_SIZE;
+    }
+    memory_region_init_ram(&s->dram0_mem, "exynos4210.dram0", mem_size);
+    vmstate_register_ram_global(&s->dram0_mem);
+    memory_region_add_subregion(system_mem, EXYNOS4210_DRAM0_BASE_ADDR,
+            &s->dram0_mem);
+
+   /* PMU.
+    * The only reason of existence at the moment is that secondary CPU boot
+    * loader uses PMU INFORM5 register as a holding pen.
+    */
+    sysbus_create_simple("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL);
+
+    /* PWM */
+    sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR,
+                          s->irq_table[exynos4210_get_irq(22, 0)],
+                          s->irq_table[exynos4210_get_irq(22, 1)],
+                          s->irq_table[exynos4210_get_irq(22, 2)],
+                          s->irq_table[exynos4210_get_irq(22, 3)],
+                          s->irq_table[exynos4210_get_irq(22, 4)],
+                          NULL);
+    /* RTC */
+    sysbus_create_varargs("exynos4210.rtc", EXYNOS4210_RTC_BASE_ADDR,
+                          s->irq_table[exynos4210_get_irq(23, 0)],
+                          s->irq_table[exynos4210_get_irq(23, 1)],
+                          NULL);
+
+    /* Multi Core Timer */
+    dev = qdev_create(NULL, "exynos4210.mct");
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    for (n = 0; n < 4; n++) {
+        /* Connect global timer interrupts to Combiner gpio_in */
+        sysbus_connect_irq(busdev, n,
+                s->irq_table[exynos4210_get_irq(1, 4 + n)]);
+    }
+    /* Connect local timer interrupts to Combiner gpio_in */
+    sysbus_connect_irq(busdev, 4,
+            s->irq_table[exynos4210_get_irq(51, 0)]);
+    sysbus_connect_irq(busdev, 5,
+            s->irq_table[exynos4210_get_irq(35, 3)]);
+    sysbus_mmio_map(busdev, 0, EXYNOS4210_MCT_BASE_ADDR);
+
+    /*** I2C ***/
+    for (n = 0; n < EXYNOS4210_I2C_NUMBER; n++) {
+        uint32_t addr = EXYNOS4210_I2C_BASE_ADDR + EXYNOS4210_I2C_SHIFT * n;
+        qemu_irq i2c_irq;
+
+        if (n < 8) {
+            i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_I2C_INTG, n)];
+        } else {
+            i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_HDMI_INTG, 1)];
+        }
+
+        dev = qdev_create(NULL, "exynos4210.i2c");
+        qdev_init_nofail(dev);
+        busdev = SYS_BUS_DEVICE(dev);
+        sysbus_connect_irq(busdev, 0, i2c_irq);
+        sysbus_mmio_map(busdev, 0, addr);
+        s->i2c_if[n] = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
+    }
+
+
+    /*** UARTs ***/
+    exynos4210_uart_create(EXYNOS4210_UART0_BASE_ADDR,
+                           EXYNOS4210_UART0_FIFO_SIZE, 0, NULL,
+                  s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 0)]);
+
+    exynos4210_uart_create(EXYNOS4210_UART1_BASE_ADDR,
+                           EXYNOS4210_UART1_FIFO_SIZE, 1, NULL,
+                  s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 1)]);
+
+    exynos4210_uart_create(EXYNOS4210_UART2_BASE_ADDR,
+                           EXYNOS4210_UART2_FIFO_SIZE, 2, NULL,
+                  s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 2)]);
+
+    exynos4210_uart_create(EXYNOS4210_UART3_BASE_ADDR,
+                           EXYNOS4210_UART3_FIFO_SIZE, 3, NULL,
+                  s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 3)]);
+
+    /*** Display controller (FIMD) ***/
+    sysbus_create_varargs("exynos4210.fimd", EXYNOS4210_FIMD0_BASE_ADDR,
+            s->irq_table[exynos4210_get_irq(11, 0)],
+            s->irq_table[exynos4210_get_irq(11, 1)],
+            s->irq_table[exynos4210_get_irq(11, 2)],
+            NULL);
+
+    sysbus_create_simple(TYPE_EXYNOS4210_EHCI, EXYNOS4210_EHCI_BASE_ADDR,
+            s->irq_table[exynos4210_get_irq(28, 3)]);
+
+    return s;
+}
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
new file mode 100644
index 0000000..6f0a8ca
--- /dev/null
+++ b/hw/arm/omap1.c
@@ -0,0 +1,4056 @@
+/*
+ * TI OMAP processors emulation.
+ *
+ * Copyright (C) 2006-2008 Andrzej Zaborowski  <balrog at zabor.org>
+ *
+ * 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 or
+ * (at your option) version 3 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 "hw/arm-misc.h"
+#include "hw/omap.h"
+#include "sysemu/sysemu.h"
+#include "hw/soc_dma.h"
+#include "sysemu/blockdev.h"
+#include "qemu/range.h"
+#include "hw/sysbus.h"
+
+/* Should signal the TCMI/GPMC */
+uint32_t omap_badwidth_read8(void *opaque, hwaddr addr)
+{
+    uint8_t ret;
+
+    OMAP_8B_REG(addr);
+    cpu_physical_memory_read(addr, (void *) &ret, 1);
+    return ret;
+}
+
+void omap_badwidth_write8(void *opaque, hwaddr addr,
+                uint32_t value)
+{
+    uint8_t val8 = value;
+
+    OMAP_8B_REG(addr);
+    cpu_physical_memory_write(addr, (void *) &val8, 1);
+}
+
+uint32_t omap_badwidth_read16(void *opaque, hwaddr addr)
+{
+    uint16_t ret;
+
+    OMAP_16B_REG(addr);
+    cpu_physical_memory_read(addr, (void *) &ret, 2);
+    return ret;
+}
+
+void omap_badwidth_write16(void *opaque, hwaddr addr,
+                uint32_t value)
+{
+    uint16_t val16 = value;
+
+    OMAP_16B_REG(addr);
+    cpu_physical_memory_write(addr, (void *) &val16, 2);
+}
+
+uint32_t omap_badwidth_read32(void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+    OMAP_32B_REG(addr);
+    cpu_physical_memory_read(addr, (void *) &ret, 4);
+    return ret;
+}
+
+void omap_badwidth_write32(void *opaque, hwaddr addr,
+                uint32_t value)
+{
+    OMAP_32B_REG(addr);
+    cpu_physical_memory_write(addr, (void *) &value, 4);
+}
+
+/* MPU OS timers */
+struct omap_mpu_timer_s {
+    MemoryRegion iomem;
+    qemu_irq irq;
+    omap_clk clk;
+    uint32_t val;
+    int64_t time;
+    QEMUTimer *timer;
+    QEMUBH *tick;
+    int64_t rate;
+    int it_ena;
+
+    int enable;
+    int ptv;
+    int ar;
+    int st;
+    uint32_t reset_val;
+};
+
+static inline uint32_t omap_timer_read(struct omap_mpu_timer_s *timer)
+{
+    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),
+                                     timer->rate, get_ticks_per_sec());
+    else
+        return timer->val;
+}
+
+static inline void omap_timer_sync(struct omap_mpu_timer_s *timer)
+{
+    timer->val = omap_timer_read(timer);
+    timer->time = qemu_get_clock_ns(vm_clock);
+}
+
+static inline void omap_timer_update(struct omap_mpu_timer_s *timer)
+{
+    int64_t expires;
+
+    if (timer->enable && timer->st && timer->rate) {
+        timer->val = timer->reset_val;	/* Should skip this on clk enable */
+        expires = muldiv64((uint64_t) timer->val << (timer->ptv + 1),
+                           get_ticks_per_sec(), timer->rate);
+
+        /* If timer expiry would be sooner than in about 1 ms and
+         * auto-reload isn't set, then fire immediately.  This is a hack
+         * to make systems like PalmOS run in acceptable time.  PalmOS
+         * sets the interval to a very low value and polls the status bit
+         * in a busy loop when it wants to sleep just a couple of CPU
+         * ticks.  */
+        if (expires > (get_ticks_per_sec() >> 10) || timer->ar)
+            qemu_mod_timer(timer->timer, timer->time + expires);
+        else
+            qemu_bh_schedule(timer->tick);
+    } else
+        qemu_del_timer(timer->timer);
+}
+
+static void omap_timer_fire(void *opaque)
+{
+    struct omap_mpu_timer_s *timer = opaque;
+
+    if (!timer->ar) {
+        timer->val = 0;
+        timer->st = 0;
+    }
+
+    if (timer->it_ena)
+        /* Edge-triggered irq */
+        qemu_irq_pulse(timer->irq);
+}
+
+static void omap_timer_tick(void *opaque)
+{
+    struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
+
+    omap_timer_sync(timer);
+    omap_timer_fire(timer);
+    omap_timer_update(timer);
+}
+
+static void omap_timer_clk_update(void *opaque, int line, int on)
+{
+    struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
+
+    omap_timer_sync(timer);
+    timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
+    omap_timer_update(timer);
+}
+
+static void omap_timer_clk_setup(struct omap_mpu_timer_s *timer)
+{
+    omap_clk_adduser(timer->clk,
+                    qemu_allocate_irqs(omap_timer_clk_update, timer, 1)[0]);
+    timer->rate = omap_clk_getrate(timer->clk);
+}
+
+static uint64_t omap_mpu_timer_read(void *opaque, hwaddr addr,
+                                    unsigned size)
+{
+    struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x00:	/* CNTL_TIMER */
+        return (s->enable << 5) | (s->ptv << 2) | (s->ar << 1) | s->st;
+
+    case 0x04:	/* LOAD_TIM */
+        break;
+
+    case 0x08:	/* READ_TIM */
+        return omap_timer_read(s);
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_mpu_timer_write(void *opaque, hwaddr addr,
+                                 uint64_t value, unsigned size)
+{
+    struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00:	/* CNTL_TIMER */
+        omap_timer_sync(s);
+        s->enable = (value >> 5) & 1;
+        s->ptv = (value >> 2) & 7;
+        s->ar = (value >> 1) & 1;
+        s->st = value & 1;
+        omap_timer_update(s);
+        return;
+
+    case 0x04:	/* LOAD_TIM */
+        s->reset_val = value;
+        return;
+
+    case 0x08:	/* READ_TIM */
+        OMAP_RO_REG(addr);
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_mpu_timer_ops = {
+    .read = omap_mpu_timer_read,
+    .write = omap_mpu_timer_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void omap_mpu_timer_reset(struct omap_mpu_timer_s *s)
+{
+    qemu_del_timer(s->timer);
+    s->enable = 0;
+    s->reset_val = 31337;
+    s->val = 0;
+    s->ptv = 0;
+    s->ar = 0;
+    s->st = 0;
+    s->it_ena = 1;
+}
+
+static struct omap_mpu_timer_s *omap_mpu_timer_init(MemoryRegion *system_memory,
+                hwaddr base,
+                qemu_irq irq, omap_clk clk)
+{
+    struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *)
+            g_malloc0(sizeof(struct omap_mpu_timer_s));
+
+    s->irq = irq;
+    s->clk = clk;
+    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);
+
+    memory_region_init_io(&s->iomem, &omap_mpu_timer_ops, s,
+                          "omap-mpu-timer", 0x100);
+
+    memory_region_add_subregion(system_memory, base, &s->iomem);
+
+    return s;
+}
+
+/* Watchdog timer */
+struct omap_watchdog_timer_s {
+    struct omap_mpu_timer_s timer;
+    MemoryRegion iomem;
+    uint8_t last_wr;
+    int mode;
+    int free;
+    int reset;
+};
+
+static uint64_t omap_wd_timer_read(void *opaque, hwaddr addr,
+                                   unsigned size)
+{
+    struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x00:	/* CNTL_TIMER */
+        return (s->timer.ptv << 9) | (s->timer.ar << 8) |
+                (s->timer.st << 7) | (s->free << 1);
+
+    case 0x04:	/* READ_TIMER */
+        return omap_timer_read(&s->timer);
+
+    case 0x08:	/* TIMER_MODE */
+        return s->mode << 15;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_wd_timer_write(void *opaque, hwaddr addr,
+                                uint64_t value, unsigned size)
+{
+    struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00:	/* CNTL_TIMER */
+        omap_timer_sync(&s->timer);
+        s->timer.ptv = (value >> 9) & 7;
+        s->timer.ar = (value >> 8) & 1;
+        s->timer.st = (value >> 7) & 1;
+        s->free = (value >> 1) & 1;
+        omap_timer_update(&s->timer);
+        break;
+
+    case 0x04:	/* LOAD_TIMER */
+        s->timer.reset_val = value & 0xffff;
+        break;
+
+    case 0x08:	/* TIMER_MODE */
+        if (!s->mode && ((value >> 15) & 1))
+            omap_clk_get(s->timer.clk);
+        s->mode |= (value >> 15) & 1;
+        if (s->last_wr == 0xf5) {
+            if ((value & 0xff) == 0xa0) {
+                if (s->mode) {
+                    s->mode = 0;
+                    omap_clk_put(s->timer.clk);
+                }
+            } else {
+                /* XXX: on T|E hardware somehow this has no effect,
+                 * on Zire 71 it works as specified.  */
+                s->reset = 1;
+                qemu_system_reset_request();
+            }
+        }
+        s->last_wr = value & 0xff;
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_wd_timer_ops = {
+    .read = omap_wd_timer_read,
+    .write = omap_wd_timer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_wd_timer_reset(struct omap_watchdog_timer_s *s)
+{
+    qemu_del_timer(s->timer.timer);
+    if (!s->mode)
+        omap_clk_get(s->timer.clk);
+    s->mode = 1;
+    s->free = 1;
+    s->reset = 0;
+    s->timer.enable = 1;
+    s->timer.it_ena = 1;
+    s->timer.reset_val = 0xffff;
+    s->timer.val = 0;
+    s->timer.st = 0;
+    s->timer.ptv = 0;
+    s->timer.ar = 0;
+    omap_timer_update(&s->timer);
+}
+
+static struct omap_watchdog_timer_s *omap_wd_timer_init(MemoryRegion *memory,
+                hwaddr base,
+                qemu_irq irq, omap_clk clk)
+{
+    struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *)
+            g_malloc0(sizeof(struct omap_watchdog_timer_s));
+
+    s->timer.irq = irq;
+    s->timer.clk = clk;
+    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);
+
+    memory_region_init_io(&s->iomem, &omap_wd_timer_ops, s,
+                          "omap-wd-timer", 0x100);
+    memory_region_add_subregion(memory, base, &s->iomem);
+
+    return s;
+}
+
+/* 32-kHz timer */
+struct omap_32khz_timer_s {
+    struct omap_mpu_timer_s timer;
+    MemoryRegion iomem;
+};
+
+static uint64_t omap_os_timer_read(void *opaque, hwaddr addr,
+                                   unsigned size)
+{
+    struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
+    switch (offset) {
+    case 0x00:	/* TVR */
+        return s->timer.reset_val;
+
+    case 0x04:	/* TCR */
+        return omap_timer_read(&s->timer);
+
+    case 0x08:	/* CR */
+        return (s->timer.ar << 3) | (s->timer.it_ena << 2) | s->timer.st;
+
+    default:
+        break;
+    }
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_os_timer_write(void *opaque, hwaddr addr,
+                                uint64_t value, unsigned size)
+{
+    struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
+    switch (offset) {
+    case 0x00:	/* TVR */
+        s->timer.reset_val = value & 0x00ffffff;
+        break;
+
+    case 0x04:	/* TCR */
+        OMAP_RO_REG(addr);
+        break;
+
+    case 0x08:	/* CR */
+        s->timer.ar = (value >> 3) & 1;
+        s->timer.it_ena = (value >> 2) & 1;
+        if (s->timer.st != (value & 1) || (value & 2)) {
+            omap_timer_sync(&s->timer);
+            s->timer.enable = value & 1;
+            s->timer.st = value & 1;
+            omap_timer_update(&s->timer);
+        }
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_os_timer_ops = {
+    .read = omap_os_timer_read,
+    .write = omap_os_timer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_os_timer_reset(struct omap_32khz_timer_s *s)
+{
+    qemu_del_timer(s->timer.timer);
+    s->timer.enable = 0;
+    s->timer.it_ena = 0;
+    s->timer.reset_val = 0x00ffffff;
+    s->timer.val = 0;
+    s->timer.st = 0;
+    s->timer.ptv = 0;
+    s->timer.ar = 1;
+}
+
+static struct omap_32khz_timer_s *omap_os_timer_init(MemoryRegion *memory,
+                hwaddr base,
+                qemu_irq irq, omap_clk clk)
+{
+    struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *)
+            g_malloc0(sizeof(struct omap_32khz_timer_s));
+
+    s->timer.irq = irq;
+    s->timer.clk = clk;
+    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);
+
+    memory_region_init_io(&s->iomem, &omap_os_timer_ops, s,
+                          "omap-os-timer", 0x800);
+    memory_region_add_subregion(memory, base, &s->iomem);
+
+    return s;
+}
+
+/* Ultra Low-Power Device Module */
+static uint64_t omap_ulpd_pm_read(void *opaque, hwaddr addr,
+                                  unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    uint16_t ret;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x14:	/* IT_STATUS */
+        ret = s->ulpd_pm_regs[addr >> 2];
+        s->ulpd_pm_regs[addr >> 2] = 0;
+        qemu_irq_lower(qdev_get_gpio_in(s->ih[1], OMAP_INT_GAUGE_32K));
+        return ret;
+
+    case 0x18:	/* Reserved */
+    case 0x1c:	/* Reserved */
+    case 0x20:	/* Reserved */
+    case 0x28:	/* Reserved */
+    case 0x2c:	/* Reserved */
+        OMAP_BAD_REG(addr);
+        /* fall through */
+    case 0x00:	/* COUNTER_32_LSB */
+    case 0x04:	/* COUNTER_32_MSB */
+    case 0x08:	/* COUNTER_HIGH_FREQ_LSB */
+    case 0x0c:	/* COUNTER_HIGH_FREQ_MSB */
+    case 0x10:	/* GAUGING_CTRL */
+    case 0x24:	/* SETUP_ANALOG_CELL3_ULPD1 */
+    case 0x30:	/* CLOCK_CTRL */
+    case 0x34:	/* SOFT_REQ */
+    case 0x38:	/* COUNTER_32_FIQ */
+    case 0x3c:	/* DPLL_CTRL */
+    case 0x40:	/* STATUS_REQ */
+        /* XXX: check clk::usecount state for every clock */
+    case 0x48:	/* LOCL_TIME */
+    case 0x4c:	/* APLL_CTRL */
+    case 0x50:	/* POWER_CTRL */
+        return s->ulpd_pm_regs[addr >> 2];
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static inline void omap_ulpd_clk_update(struct omap_mpu_state_s *s,
+                uint16_t diff, uint16_t value)
+{
+    if (diff & (1 << 4))				/* USB_MCLK_EN */
+        omap_clk_onoff(omap_findclk(s, "usb_clk0"), (value >> 4) & 1);
+    if (diff & (1 << 5))				/* DIS_USB_PVCI_CLK */
+        omap_clk_onoff(omap_findclk(s, "usb_w2fc_ck"), (~value >> 5) & 1);
+}
+
+static inline void omap_ulpd_req_update(struct omap_mpu_state_s *s,
+                uint16_t diff, uint16_t value)
+{
+    if (diff & (1 << 0))				/* SOFT_DPLL_REQ */
+        omap_clk_canidle(omap_findclk(s, "dpll4"), (~value >> 0) & 1);
+    if (diff & (1 << 1))				/* SOFT_COM_REQ */
+        omap_clk_canidle(omap_findclk(s, "com_mclk_out"), (~value >> 1) & 1);
+    if (diff & (1 << 2))				/* SOFT_SDW_REQ */
+        omap_clk_canidle(omap_findclk(s, "bt_mclk_out"), (~value >> 2) & 1);
+    if (diff & (1 << 3))				/* SOFT_USB_REQ */
+        omap_clk_canidle(omap_findclk(s, "usb_clk0"), (~value >> 3) & 1);
+}
+
+static void omap_ulpd_pm_write(void *opaque, hwaddr addr,
+                               uint64_t value, unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    int64_t now, ticks;
+    int div, mult;
+    static const int bypass_div[4] = { 1, 2, 4, 4 };
+    uint16_t diff;
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00:	/* COUNTER_32_LSB */
+    case 0x04:	/* COUNTER_32_MSB */
+    case 0x08:	/* COUNTER_HIGH_FREQ_LSB */
+    case 0x0c:	/* COUNTER_HIGH_FREQ_MSB */
+    case 0x14:	/* IT_STATUS */
+    case 0x40:	/* STATUS_REQ */
+        OMAP_RO_REG(addr);
+        break;
+
+    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_ns(vm_clock);
+
+            if (value & 1)
+                s->ulpd_gauge_start = now;
+            else {
+                now -= s->ulpd_gauge_start;
+
+                /* 32-kHz ticks */
+                ticks = muldiv64(now, 32768, get_ticks_per_sec());
+                s->ulpd_pm_regs[0x00 >> 2] = (ticks >>  0) & 0xffff;
+                s->ulpd_pm_regs[0x04 >> 2] = (ticks >> 16) & 0xffff;
+                if (ticks >> 32)	/* OVERFLOW_32K */
+                    s->ulpd_pm_regs[0x14 >> 2] |= 1 << 2;
+
+                /* High frequency ticks */
+                ticks = muldiv64(now, 12000000, get_ticks_per_sec());
+                s->ulpd_pm_regs[0x08 >> 2] = (ticks >>  0) & 0xffff;
+                s->ulpd_pm_regs[0x0c >> 2] = (ticks >> 16) & 0xffff;
+                if (ticks >> 32)	/* OVERFLOW_HI_FREQ */
+                    s->ulpd_pm_regs[0x14 >> 2] |= 1 << 1;
+
+                s->ulpd_pm_regs[0x14 >> 2] |= 1 << 0;	/* IT_GAUGING */
+                qemu_irq_raise(qdev_get_gpio_in(s->ih[1], OMAP_INT_GAUGE_32K));
+            }
+        }
+        s->ulpd_pm_regs[addr >> 2] = value;
+        break;
+
+    case 0x18:	/* Reserved */
+    case 0x1c:	/* Reserved */
+    case 0x20:	/* Reserved */
+    case 0x28:	/* Reserved */
+    case 0x2c:	/* Reserved */
+        OMAP_BAD_REG(addr);
+        /* fall through */
+    case 0x24:	/* SETUP_ANALOG_CELL3_ULPD1 */
+    case 0x38:	/* COUNTER_32_FIQ */
+    case 0x48:	/* LOCL_TIME */
+    case 0x50:	/* POWER_CTRL */
+        s->ulpd_pm_regs[addr >> 2] = value;
+        break;
+
+    case 0x30:	/* CLOCK_CTRL */
+        diff = s->ulpd_pm_regs[addr >> 2] ^ value;
+        s->ulpd_pm_regs[addr >> 2] = value & 0x3f;
+        omap_ulpd_clk_update(s, diff, value);
+        break;
+
+    case 0x34:	/* SOFT_REQ */
+        diff = s->ulpd_pm_regs[addr >> 2] ^ value;
+        s->ulpd_pm_regs[addr >> 2] = value & 0x1f;
+        omap_ulpd_req_update(s, diff, value);
+        break;
+
+    case 0x3c:	/* DPLL_CTRL */
+        /* XXX: OMAP310 TRM claims bit 3 is PLL_ENABLE, and bit 4 is
+         * omitted altogether, probably a typo.  */
+        /* This register has identical semantics with DPLL(1:3) control
+         * registers, see omap_dpll_write() */
+        diff = s->ulpd_pm_regs[addr >> 2] & value;
+        s->ulpd_pm_regs[addr >> 2] = value & 0x2fff;
+        if (diff & (0x3ff << 2)) {
+            if (value & (1 << 4)) {			/* PLL_ENABLE */
+                div = ((value >> 5) & 3) + 1;		/* PLL_DIV */
+                mult = MIN((value >> 7) & 0x1f, 1);	/* PLL_MULT */
+            } else {
+                div = bypass_div[((value >> 2) & 3)];	/* BYPASS_DIV */
+                mult = 1;
+            }
+            omap_clk_setrate(omap_findclk(s, "dpll4"), div, mult);
+        }
+
+        /* Enter the desired mode.  */
+        s->ulpd_pm_regs[addr >> 2] =
+                (s->ulpd_pm_regs[addr >> 2] & 0xfffe) |
+                ((s->ulpd_pm_regs[addr >> 2] >> 4) & 1);
+
+        /* Act as if the lock is restored.  */
+        s->ulpd_pm_regs[addr >> 2] |= 2;
+        break;
+
+    case 0x4c:	/* APLL_CTRL */
+        diff = s->ulpd_pm_regs[addr >> 2] & value;
+        s->ulpd_pm_regs[addr >> 2] = value & 0xf;
+        if (diff & (1 << 0))				/* APLL_NDPLL_SWITCH */
+            omap_clk_reparent(omap_findclk(s, "ck_48m"), omap_findclk(s,
+                                    (value & (1 << 0)) ? "apll" : "dpll4"));
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_ulpd_pm_ops = {
+    .read = omap_ulpd_pm_read,
+    .write = omap_ulpd_pm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_ulpd_pm_reset(struct omap_mpu_state_s *mpu)
+{
+    mpu->ulpd_pm_regs[0x00 >> 2] = 0x0001;
+    mpu->ulpd_pm_regs[0x04 >> 2] = 0x0000;
+    mpu->ulpd_pm_regs[0x08 >> 2] = 0x0001;
+    mpu->ulpd_pm_regs[0x0c >> 2] = 0x0000;
+    mpu->ulpd_pm_regs[0x10 >> 2] = 0x0000;
+    mpu->ulpd_pm_regs[0x18 >> 2] = 0x01;
+    mpu->ulpd_pm_regs[0x1c >> 2] = 0x01;
+    mpu->ulpd_pm_regs[0x20 >> 2] = 0x01;
+    mpu->ulpd_pm_regs[0x24 >> 2] = 0x03ff;
+    mpu->ulpd_pm_regs[0x28 >> 2] = 0x01;
+    mpu->ulpd_pm_regs[0x2c >> 2] = 0x01;
+    omap_ulpd_clk_update(mpu, mpu->ulpd_pm_regs[0x30 >> 2], 0x0000);
+    mpu->ulpd_pm_regs[0x30 >> 2] = 0x0000;
+    omap_ulpd_req_update(mpu, mpu->ulpd_pm_regs[0x34 >> 2], 0x0000);
+    mpu->ulpd_pm_regs[0x34 >> 2] = 0x0000;
+    mpu->ulpd_pm_regs[0x38 >> 2] = 0x0001;
+    mpu->ulpd_pm_regs[0x3c >> 2] = 0x2211;
+    mpu->ulpd_pm_regs[0x40 >> 2] = 0x0000; /* FIXME: dump a real STATUS_REQ */
+    mpu->ulpd_pm_regs[0x48 >> 2] = 0x960;
+    mpu->ulpd_pm_regs[0x4c >> 2] = 0x08;
+    mpu->ulpd_pm_regs[0x50 >> 2] = 0x08;
+    omap_clk_setrate(omap_findclk(mpu, "dpll4"), 1, 4);
+    omap_clk_reparent(omap_findclk(mpu, "ck_48m"), omap_findclk(mpu, "dpll4"));
+}
+
+static void omap_ulpd_pm_init(MemoryRegion *system_memory,
+                hwaddr base,
+                struct omap_mpu_state_s *mpu)
+{
+    memory_region_init_io(&mpu->ulpd_pm_iomem, &omap_ulpd_pm_ops, mpu,
+                          "omap-ulpd-pm", 0x800);
+    memory_region_add_subregion(system_memory, base, &mpu->ulpd_pm_iomem);
+    omap_ulpd_pm_reset(mpu);
+}
+
+/* OMAP Pin Configuration */
+static uint64_t omap_pin_cfg_read(void *opaque, hwaddr addr,
+                                  unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x00:	/* FUNC_MUX_CTRL_0 */
+    case 0x04:	/* FUNC_MUX_CTRL_1 */
+    case 0x08:	/* FUNC_MUX_CTRL_2 */
+        return s->func_mux_ctrl[addr >> 2];
+
+    case 0x0c:	/* COMP_MODE_CTRL_0 */
+        return s->comp_mode_ctrl[0];
+
+    case 0x10:	/* FUNC_MUX_CTRL_3 */
+    case 0x14:	/* FUNC_MUX_CTRL_4 */
+    case 0x18:	/* FUNC_MUX_CTRL_5 */
+    case 0x1c:	/* FUNC_MUX_CTRL_6 */
+    case 0x20:	/* FUNC_MUX_CTRL_7 */
+    case 0x24:	/* FUNC_MUX_CTRL_8 */
+    case 0x28:	/* FUNC_MUX_CTRL_9 */
+    case 0x2c:	/* FUNC_MUX_CTRL_A */
+    case 0x30:	/* FUNC_MUX_CTRL_B */
+    case 0x34:	/* FUNC_MUX_CTRL_C */
+    case 0x38:	/* FUNC_MUX_CTRL_D */
+        return s->func_mux_ctrl[(addr >> 2) - 1];
+
+    case 0x40:	/* PULL_DWN_CTRL_0 */
+    case 0x44:	/* PULL_DWN_CTRL_1 */
+    case 0x48:	/* PULL_DWN_CTRL_2 */
+    case 0x4c:	/* PULL_DWN_CTRL_3 */
+        return s->pull_dwn_ctrl[(addr & 0xf) >> 2];
+
+    case 0x50:	/* GATE_INH_CTRL_0 */
+        return s->gate_inh_ctrl[0];
+
+    case 0x60:	/* VOLTAGE_CTRL_0 */
+        return s->voltage_ctrl[0];
+
+    case 0x70:	/* TEST_DBG_CTRL_0 */
+        return s->test_dbg_ctrl[0];
+
+    case 0x80:	/* MOD_CONF_CTRL_0 */
+        return s->mod_conf_ctrl[0];
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static inline void omap_pin_funcmux0_update(struct omap_mpu_state_s *s,
+                uint32_t diff, uint32_t value)
+{
+    if (s->compat1509) {
+        if (diff & (1 << 9))			/* BLUETOOTH */
+            omap_clk_onoff(omap_findclk(s, "bt_mclk_out"),
+                            (~value >> 9) & 1);
+        if (diff & (1 << 7))			/* USB.CLKO */
+            omap_clk_onoff(omap_findclk(s, "usb.clko"),
+                            (value >> 7) & 1);
+    }
+}
+
+static inline void omap_pin_funcmux1_update(struct omap_mpu_state_s *s,
+                uint32_t diff, uint32_t value)
+{
+    if (s->compat1509) {
+        if (diff & (1 << 31))			/* MCBSP3_CLK_HIZ_DI */
+            omap_clk_onoff(omap_findclk(s, "mcbsp3.clkx"),
+                            (value >> 31) & 1);
+        if (diff & (1 << 1))			/* CLK32K */
+            omap_clk_onoff(omap_findclk(s, "clk32k_out"),
+                            (~value >> 1) & 1);
+    }
+}
+
+static inline void omap_pin_modconf1_update(struct omap_mpu_state_s *s,
+                uint32_t diff, uint32_t value)
+{
+    if (diff & (1 << 31))			/* CONF_MOD_UART3_CLK_MODE_R */
+         omap_clk_reparent(omap_findclk(s, "uart3_ck"),
+                         omap_findclk(s, ((value >> 31) & 1) ?
+                                 "ck_48m" : "armper_ck"));
+    if (diff & (1 << 30))			/* CONF_MOD_UART2_CLK_MODE_R */
+         omap_clk_reparent(omap_findclk(s, "uart2_ck"),
+                         omap_findclk(s, ((value >> 30) & 1) ?
+                                 "ck_48m" : "armper_ck"));
+    if (diff & (1 << 29))			/* CONF_MOD_UART1_CLK_MODE_R */
+         omap_clk_reparent(omap_findclk(s, "uart1_ck"),
+                         omap_findclk(s, ((value >> 29) & 1) ?
+                                 "ck_48m" : "armper_ck"));
+    if (diff & (1 << 23))			/* CONF_MOD_MMC_SD_CLK_REQ_R */
+         omap_clk_reparent(omap_findclk(s, "mmc_ck"),
+                         omap_findclk(s, ((value >> 23) & 1) ?
+                                 "ck_48m" : "armper_ck"));
+    if (diff & (1 << 12))			/* CONF_MOD_COM_MCLK_12_48_S */
+         omap_clk_reparent(omap_findclk(s, "com_mclk_out"),
+                         omap_findclk(s, ((value >> 12) & 1) ?
+                                 "ck_48m" : "armper_ck"));
+    if (diff & (1 << 9))			/* CONF_MOD_USB_HOST_HHC_UHO */
+         omap_clk_onoff(omap_findclk(s, "usb_hhc_ck"), (value >> 9) & 1);
+}
+
+static void omap_pin_cfg_write(void *opaque, hwaddr addr,
+                               uint64_t value, unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    uint32_t diff;
+
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00:	/* FUNC_MUX_CTRL_0 */
+        diff = s->func_mux_ctrl[addr >> 2] ^ value;
+        s->func_mux_ctrl[addr >> 2] = value;
+        omap_pin_funcmux0_update(s, diff, value);
+        return;
+
+    case 0x04:	/* FUNC_MUX_CTRL_1 */
+        diff = s->func_mux_ctrl[addr >> 2] ^ value;
+        s->func_mux_ctrl[addr >> 2] = value;
+        omap_pin_funcmux1_update(s, diff, value);
+        return;
+
+    case 0x08:	/* FUNC_MUX_CTRL_2 */
+        s->func_mux_ctrl[addr >> 2] = value;
+        return;
+
+    case 0x0c:	/* COMP_MODE_CTRL_0 */
+        s->comp_mode_ctrl[0] = value;
+        s->compat1509 = (value != 0x0000eaef);
+        omap_pin_funcmux0_update(s, ~0, s->func_mux_ctrl[0]);
+        omap_pin_funcmux1_update(s, ~0, s->func_mux_ctrl[1]);
+        return;
+
+    case 0x10:	/* FUNC_MUX_CTRL_3 */
+    case 0x14:	/* FUNC_MUX_CTRL_4 */
+    case 0x18:	/* FUNC_MUX_CTRL_5 */
+    case 0x1c:	/* FUNC_MUX_CTRL_6 */
+    case 0x20:	/* FUNC_MUX_CTRL_7 */
+    case 0x24:	/* FUNC_MUX_CTRL_8 */
+    case 0x28:	/* FUNC_MUX_CTRL_9 */
+    case 0x2c:	/* FUNC_MUX_CTRL_A */
+    case 0x30:	/* FUNC_MUX_CTRL_B */
+    case 0x34:	/* FUNC_MUX_CTRL_C */
+    case 0x38:	/* FUNC_MUX_CTRL_D */
+        s->func_mux_ctrl[(addr >> 2) - 1] = value;
+        return;
+
+    case 0x40:	/* PULL_DWN_CTRL_0 */
+    case 0x44:	/* PULL_DWN_CTRL_1 */
+    case 0x48:	/* PULL_DWN_CTRL_2 */
+    case 0x4c:	/* PULL_DWN_CTRL_3 */
+        s->pull_dwn_ctrl[(addr & 0xf) >> 2] = value;
+        return;
+
+    case 0x50:	/* GATE_INH_CTRL_0 */
+        s->gate_inh_ctrl[0] = value;
+        return;
+
+    case 0x60:	/* VOLTAGE_CTRL_0 */
+        s->voltage_ctrl[0] = value;
+        return;
+
+    case 0x70:	/* TEST_DBG_CTRL_0 */
+        s->test_dbg_ctrl[0] = value;
+        return;
+
+    case 0x80:	/* MOD_CONF_CTRL_0 */
+        diff = s->mod_conf_ctrl[0] ^ value;
+        s->mod_conf_ctrl[0] = value;
+        omap_pin_modconf1_update(s, diff, value);
+        return;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_pin_cfg_ops = {
+    .read = omap_pin_cfg_read,
+    .write = omap_pin_cfg_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_pin_cfg_reset(struct omap_mpu_state_s *mpu)
+{
+    /* Start in Compatibility Mode.  */
+    mpu->compat1509 = 1;
+    omap_pin_funcmux0_update(mpu, mpu->func_mux_ctrl[0], 0);
+    omap_pin_funcmux1_update(mpu, mpu->func_mux_ctrl[1], 0);
+    omap_pin_modconf1_update(mpu, mpu->mod_conf_ctrl[0], 0);
+    memset(mpu->func_mux_ctrl, 0, sizeof(mpu->func_mux_ctrl));
+    memset(mpu->comp_mode_ctrl, 0, sizeof(mpu->comp_mode_ctrl));
+    memset(mpu->pull_dwn_ctrl, 0, sizeof(mpu->pull_dwn_ctrl));
+    memset(mpu->gate_inh_ctrl, 0, sizeof(mpu->gate_inh_ctrl));
+    memset(mpu->voltage_ctrl, 0, sizeof(mpu->voltage_ctrl));
+    memset(mpu->test_dbg_ctrl, 0, sizeof(mpu->test_dbg_ctrl));
+    memset(mpu->mod_conf_ctrl, 0, sizeof(mpu->mod_conf_ctrl));
+}
+
+static void omap_pin_cfg_init(MemoryRegion *system_memory,
+                hwaddr base,
+                struct omap_mpu_state_s *mpu)
+{
+    memory_region_init_io(&mpu->pin_cfg_iomem, &omap_pin_cfg_ops, mpu,
+                          "omap-pin-cfg", 0x800);
+    memory_region_add_subregion(system_memory, base, &mpu->pin_cfg_iomem);
+    omap_pin_cfg_reset(mpu);
+}
+
+/* Device Identification, Die Identification */
+static uint64_t omap_id_read(void *opaque, hwaddr addr,
+                             unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0xfffe1800:	/* DIE_ID_LSB */
+        return 0xc9581f0e;
+    case 0xfffe1804:	/* DIE_ID_MSB */
+        return 0xa8858bfa;
+
+    case 0xfffe2000:	/* PRODUCT_ID_LSB */
+        return 0x00aaaafc;
+    case 0xfffe2004:	/* PRODUCT_ID_MSB */
+        return 0xcafeb574;
+
+    case 0xfffed400:	/* JTAG_ID_LSB */
+        switch (s->mpu_model) {
+        case omap310:
+            return 0x03310315;
+        case omap1510:
+            return 0x03310115;
+        default:
+            hw_error("%s: bad mpu model\n", __FUNCTION__);
+        }
+        break;
+
+    case 0xfffed404:	/* JTAG_ID_MSB */
+        switch (s->mpu_model) {
+        case omap310:
+            return 0xfb57402f;
+        case omap1510:
+            return 0xfb47002f;
+        default:
+            hw_error("%s: bad mpu model\n", __FUNCTION__);
+        }
+        break;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_id_write(void *opaque, hwaddr addr,
+                          uint64_t value, unsigned size)
+{
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
+    OMAP_BAD_REG(addr);
+}
+
+static const MemoryRegionOps omap_id_ops = {
+    .read = omap_id_read,
+    .write = omap_id_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_id_init(MemoryRegion *memory, struct omap_mpu_state_s *mpu)
+{
+    memory_region_init_io(&mpu->id_iomem, &omap_id_ops, mpu,
+                          "omap-id", 0x100000000ULL);
+    memory_region_init_alias(&mpu->id_iomem_e18, "omap-id-e18", &mpu->id_iomem,
+                             0xfffe1800, 0x800);
+    memory_region_add_subregion(memory, 0xfffe1800, &mpu->id_iomem_e18);
+    memory_region_init_alias(&mpu->id_iomem_ed4, "omap-id-ed4", &mpu->id_iomem,
+                             0xfffed400, 0x100);
+    memory_region_add_subregion(memory, 0xfffed400, &mpu->id_iomem_ed4);
+    if (!cpu_is_omap15xx(mpu)) {
+        memory_region_init_alias(&mpu->id_iomem_ed4, "omap-id-e20",
+                                 &mpu->id_iomem, 0xfffe2000, 0x800);
+        memory_region_add_subregion(memory, 0xfffe2000, &mpu->id_iomem_e20);
+    }
+}
+
+/* MPUI Control (Dummy) */
+static uint64_t omap_mpui_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x00:	/* CTRL */
+        return s->mpui_ctrl;
+    case 0x04:	/* DEBUG_ADDR */
+        return 0x01ffffff;
+    case 0x08:	/* DEBUG_DATA */
+        return 0xffffffff;
+    case 0x0c:	/* DEBUG_FLAG */
+        return 0x00000800;
+    case 0x10:	/* STATUS */
+        return 0x00000000;
+
+    /* Not in OMAP310 */
+    case 0x14:	/* DSP_STATUS */
+    case 0x18:	/* DSP_BOOT_CONFIG */
+        return 0x00000000;
+    case 0x1c:	/* DSP_MPUI_CONFIG */
+        return 0x0000ffff;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_mpui_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00:	/* CTRL */
+        s->mpui_ctrl = value & 0x007fffff;
+        break;
+
+    case 0x04:	/* DEBUG_ADDR */
+    case 0x08:	/* DEBUG_DATA */
+    case 0x0c:	/* DEBUG_FLAG */
+    case 0x10:	/* STATUS */
+    /* Not in OMAP310 */
+    case 0x14:	/* DSP_STATUS */
+        OMAP_RO_REG(addr);
+        break;
+    case 0x18:	/* DSP_BOOT_CONFIG */
+    case 0x1c:	/* DSP_MPUI_CONFIG */
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_mpui_ops = {
+    .read = omap_mpui_read,
+    .write = omap_mpui_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_mpui_reset(struct omap_mpu_state_s *s)
+{
+    s->mpui_ctrl = 0x0003ff1b;
+}
+
+static void omap_mpui_init(MemoryRegion *memory, hwaddr base,
+                struct omap_mpu_state_s *mpu)
+{
+    memory_region_init_io(&mpu->mpui_iomem, &omap_mpui_ops, mpu,
+                          "omap-mpui", 0x100);
+    memory_region_add_subregion(memory, base, &mpu->mpui_iomem);
+
+    omap_mpui_reset(mpu);
+}
+
+/* TIPB Bridges */
+struct omap_tipb_bridge_s {
+    qemu_irq abort;
+    MemoryRegion iomem;
+
+    int width_intr;
+    uint16_t control;
+    uint16_t alloc;
+    uint16_t buffer;
+    uint16_t enh_control;
+};
+
+static uint64_t omap_tipb_bridge_read(void *opaque, hwaddr addr,
+                                      unsigned size)
+{
+    struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
+
+    if (size < 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x00:	/* TIPB_CNTL */
+        return s->control;
+    case 0x04:	/* TIPB_BUS_ALLOC */
+        return s->alloc;
+    case 0x08:	/* MPU_TIPB_CNTL */
+        return s->buffer;
+    case 0x0c:	/* ENHANCED_TIPB_CNTL */
+        return s->enh_control;
+    case 0x10:	/* ADDRESS_DBG */
+    case 0x14:	/* DATA_DEBUG_LOW */
+    case 0x18:	/* DATA_DEBUG_HIGH */
+        return 0xffff;
+    case 0x1c:	/* DEBUG_CNTR_SIG */
+        return 0x00f8;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_tipb_bridge_write(void *opaque, hwaddr addr,
+                                   uint64_t value, unsigned size)
+{
+    struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
+
+    if (size < 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00:	/* TIPB_CNTL */
+        s->control = value & 0xffff;
+        break;
+
+    case 0x04:	/* TIPB_BUS_ALLOC */
+        s->alloc = value & 0x003f;
+        break;
+
+    case 0x08:	/* MPU_TIPB_CNTL */
+        s->buffer = value & 0x0003;
+        break;
+
+    case 0x0c:	/* ENHANCED_TIPB_CNTL */
+        s->width_intr = !(value & 2);
+        s->enh_control = value & 0x000f;
+        break;
+
+    case 0x10:	/* ADDRESS_DBG */
+    case 0x14:	/* DATA_DEBUG_LOW */
+    case 0x18:	/* DATA_DEBUG_HIGH */
+    case 0x1c:	/* DEBUG_CNTR_SIG */
+        OMAP_RO_REG(addr);
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_tipb_bridge_ops = {
+    .read = omap_tipb_bridge_read,
+    .write = omap_tipb_bridge_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_tipb_bridge_reset(struct omap_tipb_bridge_s *s)
+{
+    s->control = 0xffff;
+    s->alloc = 0x0009;
+    s->buffer = 0x0000;
+    s->enh_control = 0x000f;
+}
+
+static struct omap_tipb_bridge_s *omap_tipb_bridge_init(
+    MemoryRegion *memory, hwaddr base,
+    qemu_irq abort_irq, omap_clk clk)
+{
+    struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *)
+            g_malloc0(sizeof(struct omap_tipb_bridge_s));
+
+    s->abort = abort_irq;
+    omap_tipb_bridge_reset(s);
+
+    memory_region_init_io(&s->iomem, &omap_tipb_bridge_ops, s,
+                          "omap-tipb-bridge", 0x100);
+    memory_region_add_subregion(memory, base, &s->iomem);
+
+    return s;
+}
+
+/* Dummy Traffic Controller's Memory Interface */
+static uint64_t omap_tcmi_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    uint32_t ret;
+
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x00:	/* IMIF_PRIO */
+    case 0x04:	/* EMIFS_PRIO */
+    case 0x08:	/* EMIFF_PRIO */
+    case 0x0c:	/* EMIFS_CONFIG */
+    case 0x10:	/* EMIFS_CS0_CONFIG */
+    case 0x14:	/* EMIFS_CS1_CONFIG */
+    case 0x18:	/* EMIFS_CS2_CONFIG */
+    case 0x1c:	/* EMIFS_CS3_CONFIG */
+    case 0x24:	/* EMIFF_MRS */
+    case 0x28:	/* TIMEOUT1 */
+    case 0x2c:	/* TIMEOUT2 */
+    case 0x30:	/* TIMEOUT3 */
+    case 0x3c:	/* EMIFF_SDRAM_CONFIG_2 */
+    case 0x40:	/* EMIFS_CFG_DYN_WAIT */
+        return s->tcmi_regs[addr >> 2];
+
+    case 0x20:	/* EMIFF_SDRAM_CONFIG */
+        ret = s->tcmi_regs[addr >> 2];
+        s->tcmi_regs[addr >> 2] &= ~1; /* XXX: Clear SLRF on SDRAM access */
+        /* XXX: We can try using the VGA_DIRTY flag for this */
+        return ret;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_tcmi_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00:	/* IMIF_PRIO */
+    case 0x04:	/* EMIFS_PRIO */
+    case 0x08:	/* EMIFF_PRIO */
+    case 0x10:	/* EMIFS_CS0_CONFIG */
+    case 0x14:	/* EMIFS_CS1_CONFIG */
+    case 0x18:	/* EMIFS_CS2_CONFIG */
+    case 0x1c:	/* EMIFS_CS3_CONFIG */
+    case 0x20:	/* EMIFF_SDRAM_CONFIG */
+    case 0x24:	/* EMIFF_MRS */
+    case 0x28:	/* TIMEOUT1 */
+    case 0x2c:	/* TIMEOUT2 */
+    case 0x30:	/* TIMEOUT3 */
+    case 0x3c:	/* EMIFF_SDRAM_CONFIG_2 */
+    case 0x40:	/* EMIFS_CFG_DYN_WAIT */
+        s->tcmi_regs[addr >> 2] = value;
+        break;
+    case 0x0c:	/* EMIFS_CONFIG */
+        s->tcmi_regs[addr >> 2] = (value & 0xf) | (1 << 4);
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_tcmi_ops = {
+    .read = omap_tcmi_read,
+    .write = omap_tcmi_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_tcmi_reset(struct omap_mpu_state_s *mpu)
+{
+    mpu->tcmi_regs[0x00 >> 2] = 0x00000000;
+    mpu->tcmi_regs[0x04 >> 2] = 0x00000000;
+    mpu->tcmi_regs[0x08 >> 2] = 0x00000000;
+    mpu->tcmi_regs[0x0c >> 2] = 0x00000010;
+    mpu->tcmi_regs[0x10 >> 2] = 0x0010fffb;
+    mpu->tcmi_regs[0x14 >> 2] = 0x0010fffb;
+    mpu->tcmi_regs[0x18 >> 2] = 0x0010fffb;
+    mpu->tcmi_regs[0x1c >> 2] = 0x0010fffb;
+    mpu->tcmi_regs[0x20 >> 2] = 0x00618800;
+    mpu->tcmi_regs[0x24 >> 2] = 0x00000037;
+    mpu->tcmi_regs[0x28 >> 2] = 0x00000000;
+    mpu->tcmi_regs[0x2c >> 2] = 0x00000000;
+    mpu->tcmi_regs[0x30 >> 2] = 0x00000000;
+    mpu->tcmi_regs[0x3c >> 2] = 0x00000003;
+    mpu->tcmi_regs[0x40 >> 2] = 0x00000000;
+}
+
+static void omap_tcmi_init(MemoryRegion *memory, hwaddr base,
+                struct omap_mpu_state_s *mpu)
+{
+    memory_region_init_io(&mpu->tcmi_iomem, &omap_tcmi_ops, mpu,
+                          "omap-tcmi", 0x100);
+    memory_region_add_subregion(memory, base, &mpu->tcmi_iomem);
+    omap_tcmi_reset(mpu);
+}
+
+/* Digital phase-locked loops control */
+struct dpll_ctl_s {
+    MemoryRegion iomem;
+    uint16_t mode;
+    omap_clk dpll;
+};
+
+static uint64_t omap_dpll_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    if (addr == 0x00)	/* CTL_REG */
+        return s->mode;
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_dpll_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
+    uint16_t diff;
+    static const int bypass_div[4] = { 1, 2, 4, 4 };
+    int div, mult;
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    if (addr == 0x00) {	/* CTL_REG */
+        /* See omap_ulpd_pm_write() too */
+        diff = s->mode & value;
+        s->mode = value & 0x2fff;
+        if (diff & (0x3ff << 2)) {
+            if (value & (1 << 4)) {			/* PLL_ENABLE */
+                div = ((value >> 5) & 3) + 1;		/* PLL_DIV */
+                mult = MIN((value >> 7) & 0x1f, 1);	/* PLL_MULT */
+            } else {
+                div = bypass_div[((value >> 2) & 3)];	/* BYPASS_DIV */
+                mult = 1;
+            }
+            omap_clk_setrate(s->dpll, div, mult);
+        }
+
+        /* Enter the desired mode.  */
+        s->mode = (s->mode & 0xfffe) | ((s->mode >> 4) & 1);
+
+        /* Act as if the lock is restored.  */
+        s->mode |= 2;
+    } else {
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_dpll_ops = {
+    .read = omap_dpll_read,
+    .write = omap_dpll_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_dpll_reset(struct dpll_ctl_s *s)
+{
+    s->mode = 0x2002;
+    omap_clk_setrate(s->dpll, 1, 1);
+}
+
+static struct dpll_ctl_s  *omap_dpll_init(MemoryRegion *memory,
+                           hwaddr base, omap_clk clk)
+{
+    struct dpll_ctl_s *s = g_malloc0(sizeof(*s));
+    memory_region_init_io(&s->iomem, &omap_dpll_ops, s, "omap-dpll", 0x100);
+
+    s->dpll = clk;
+    omap_dpll_reset(s);
+
+    memory_region_add_subregion(memory, base, &s->iomem);
+    return s;
+}
+
+/* MPU Clock/Reset/Power Mode Control */
+static uint64_t omap_clkm_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x00:	/* ARM_CKCTL */
+        return s->clkm.arm_ckctl;
+
+    case 0x04:	/* ARM_IDLECT1 */
+        return s->clkm.arm_idlect1;
+
+    case 0x08:	/* ARM_IDLECT2 */
+        return s->clkm.arm_idlect2;
+
+    case 0x0c:	/* ARM_EWUPCT */
+        return s->clkm.arm_ewupct;
+
+    case 0x10:	/* ARM_RSTCT1 */
+        return s->clkm.arm_rstct1;
+
+    case 0x14:	/* ARM_RSTCT2 */
+        return s->clkm.arm_rstct2;
+
+    case 0x18:	/* ARM_SYSST */
+        return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start;
+
+    case 0x1c:	/* ARM_CKOUT1 */
+        return s->clkm.arm_ckout1;
+
+    case 0x20:	/* ARM_CKOUT2 */
+        break;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static inline void omap_clkm_ckctl_update(struct omap_mpu_state_s *s,
+                uint16_t diff, uint16_t value)
+{
+    omap_clk clk;
+
+    if (diff & (1 << 14)) {				/* ARM_INTHCK_SEL */
+        if (value & (1 << 14))
+            /* Reserved */;
+        else {
+            clk = omap_findclk(s, "arminth_ck");
+            omap_clk_reparent(clk, omap_findclk(s, "tc_ck"));
+        }
+    }
+    if (diff & (1 << 12)) {				/* ARM_TIMXO */
+        clk = omap_findclk(s, "armtim_ck");
+        if (value & (1 << 12))
+            omap_clk_reparent(clk, omap_findclk(s, "clkin"));
+        else
+            omap_clk_reparent(clk, omap_findclk(s, "ck_gen1"));
+    }
+    /* XXX: en_dspck */
+    if (diff & (3 << 10)) {				/* DSPMMUDIV */
+        clk = omap_findclk(s, "dspmmu_ck");
+        omap_clk_setrate(clk, 1 << ((value >> 10) & 3), 1);
+    }
+    if (diff & (3 << 8)) {				/* TCDIV */
+        clk = omap_findclk(s, "tc_ck");
+        omap_clk_setrate(clk, 1 << ((value >> 8) & 3), 1);
+    }
+    if (diff & (3 << 6)) {				/* DSPDIV */
+        clk = omap_findclk(s, "dsp_ck");
+        omap_clk_setrate(clk, 1 << ((value >> 6) & 3), 1);
+    }
+    if (diff & (3 << 4)) {				/* ARMDIV */
+        clk = omap_findclk(s, "arm_ck");
+        omap_clk_setrate(clk, 1 << ((value >> 4) & 3), 1);
+    }
+    if (diff & (3 << 2)) {				/* LCDDIV */
+        clk = omap_findclk(s, "lcd_ck");
+        omap_clk_setrate(clk, 1 << ((value >> 2) & 3), 1);
+    }
+    if (diff & (3 << 0)) {				/* PERDIV */
+        clk = omap_findclk(s, "armper_ck");
+        omap_clk_setrate(clk, 1 << ((value >> 0) & 3), 1);
+    }
+}
+
+static inline void omap_clkm_idlect1_update(struct omap_mpu_state_s *s,
+                uint16_t diff, uint16_t value)
+{
+    omap_clk clk;
+
+    if (value & (1 << 11)) {                            /* SETARM_IDLE */
+        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
+    }
+    if (!(value & (1 << 10)))				/* WKUP_MODE */
+        qemu_system_shutdown_request();	/* XXX: disable wakeup from IRQ */
+
+#define SET_CANIDLE(clock, bit)				\
+    if (diff & (1 << bit)) {				\
+        clk = omap_findclk(s, clock);			\
+        omap_clk_canidle(clk, (value >> bit) & 1);	\
+    }
+    SET_CANIDLE("mpuwd_ck", 0)				/* IDLWDT_ARM */
+    SET_CANIDLE("armxor_ck", 1)				/* IDLXORP_ARM */
+    SET_CANIDLE("mpuper_ck", 2)				/* IDLPER_ARM */
+    SET_CANIDLE("lcd_ck", 3)				/* IDLLCD_ARM */
+    SET_CANIDLE("lb_ck", 4)				/* IDLLB_ARM */
+    SET_CANIDLE("hsab_ck", 5)				/* IDLHSAB_ARM */
+    SET_CANIDLE("tipb_ck", 6)				/* IDLIF_ARM */
+    SET_CANIDLE("dma_ck", 6)				/* IDLIF_ARM */
+    SET_CANIDLE("tc_ck", 6)				/* IDLIF_ARM */
+    SET_CANIDLE("dpll1", 7)				/* IDLDPLL_ARM */
+    SET_CANIDLE("dpll2", 7)				/* IDLDPLL_ARM */
+    SET_CANIDLE("dpll3", 7)				/* IDLDPLL_ARM */
+    SET_CANIDLE("mpui_ck", 8)				/* IDLAPI_ARM */
+    SET_CANIDLE("armtim_ck", 9)				/* IDLTIM_ARM */
+}
+
+static inline void omap_clkm_idlect2_update(struct omap_mpu_state_s *s,
+                uint16_t diff, uint16_t value)
+{
+    omap_clk clk;
+
+#define SET_ONOFF(clock, bit)				\
+    if (diff & (1 << bit)) {				\
+        clk = omap_findclk(s, clock);			\
+        omap_clk_onoff(clk, (value >> bit) & 1);	\
+    }
+    SET_ONOFF("mpuwd_ck", 0)				/* EN_WDTCK */
+    SET_ONOFF("armxor_ck", 1)				/* EN_XORPCK */
+    SET_ONOFF("mpuper_ck", 2)				/* EN_PERCK */
+    SET_ONOFF("lcd_ck", 3)				/* EN_LCDCK */
+    SET_ONOFF("lb_ck", 4)				/* EN_LBCK */
+    SET_ONOFF("hsab_ck", 5)				/* EN_HSABCK */
+    SET_ONOFF("mpui_ck", 6)				/* EN_APICK */
+    SET_ONOFF("armtim_ck", 7)				/* EN_TIMCK */
+    SET_CANIDLE("dma_ck", 8)				/* DMACK_REQ */
+    SET_ONOFF("arm_gpio_ck", 9)				/* EN_GPIOCK */
+    SET_ONOFF("lbfree_ck", 10)				/* EN_LBFREECK */
+}
+
+static inline void omap_clkm_ckout1_update(struct omap_mpu_state_s *s,
+                uint16_t diff, uint16_t value)
+{
+    omap_clk clk;
+
+    if (diff & (3 << 4)) {				/* TCLKOUT */
+        clk = omap_findclk(s, "tclk_out");
+        switch ((value >> 4) & 3) {
+        case 1:
+            omap_clk_reparent(clk, omap_findclk(s, "ck_gen3"));
+            omap_clk_onoff(clk, 1);
+            break;
+        case 2:
+            omap_clk_reparent(clk, omap_findclk(s, "tc_ck"));
+            omap_clk_onoff(clk, 1);
+            break;
+        default:
+            omap_clk_onoff(clk, 0);
+        }
+    }
+    if (diff & (3 << 2)) {				/* DCLKOUT */
+        clk = omap_findclk(s, "dclk_out");
+        switch ((value >> 2) & 3) {
+        case 0:
+            omap_clk_reparent(clk, omap_findclk(s, "dspmmu_ck"));
+            break;
+        case 1:
+            omap_clk_reparent(clk, omap_findclk(s, "ck_gen2"));
+            break;
+        case 2:
+            omap_clk_reparent(clk, omap_findclk(s, "dsp_ck"));
+            break;
+        case 3:
+            omap_clk_reparent(clk, omap_findclk(s, "ck_ref14"));
+            break;
+        }
+    }
+    if (diff & (3 << 0)) {				/* ACLKOUT */
+        clk = omap_findclk(s, "aclk_out");
+        switch ((value >> 0) & 3) {
+        case 1:
+            omap_clk_reparent(clk, omap_findclk(s, "ck_gen1"));
+            omap_clk_onoff(clk, 1);
+            break;
+        case 2:
+            omap_clk_reparent(clk, omap_findclk(s, "arm_ck"));
+            omap_clk_onoff(clk, 1);
+            break;
+        case 3:
+            omap_clk_reparent(clk, omap_findclk(s, "ck_ref14"));
+            omap_clk_onoff(clk, 1);
+            break;
+        default:
+            omap_clk_onoff(clk, 0);
+        }
+    }
+}
+
+static void omap_clkm_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    uint16_t diff;
+    omap_clk clk;
+    static const char *clkschemename[8] = {
+        "fully synchronous", "fully asynchronous", "synchronous scalable",
+        "mix mode 1", "mix mode 2", "bypass mode", "mix mode 3", "mix mode 4",
+    };
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00:	/* ARM_CKCTL */
+        diff = s->clkm.arm_ckctl ^ value;
+        s->clkm.arm_ckctl = value & 0x7fff;
+        omap_clkm_ckctl_update(s, diff, value);
+        return;
+
+    case 0x04:	/* ARM_IDLECT1 */
+        diff = s->clkm.arm_idlect1 ^ value;
+        s->clkm.arm_idlect1 = value & 0x0fff;
+        omap_clkm_idlect1_update(s, diff, value);
+        return;
+
+    case 0x08:	/* ARM_IDLECT2 */
+        diff = s->clkm.arm_idlect2 ^ value;
+        s->clkm.arm_idlect2 = value & 0x07ff;
+        omap_clkm_idlect2_update(s, diff, value);
+        return;
+
+    case 0x0c:	/* ARM_EWUPCT */
+        s->clkm.arm_ewupct = value & 0x003f;
+        return;
+
+    case 0x10:	/* ARM_RSTCT1 */
+        diff = s->clkm.arm_rstct1 ^ value;
+        s->clkm.arm_rstct1 = value & 0x0007;
+        if (value & 9) {
+            qemu_system_reset_request();
+            s->clkm.cold_start = 0xa;
+        }
+        if (diff & ~value & 4) {				/* DSP_RST */
+            omap_mpui_reset(s);
+            omap_tipb_bridge_reset(s->private_tipb);
+            omap_tipb_bridge_reset(s->public_tipb);
+        }
+        if (diff & 2) {						/* DSP_EN */
+            clk = omap_findclk(s, "dsp_ck");
+            omap_clk_canidle(clk, (~value >> 1) & 1);
+        }
+        return;
+
+    case 0x14:	/* ARM_RSTCT2 */
+        s->clkm.arm_rstct2 = value & 0x0001;
+        return;
+
+    case 0x18:	/* ARM_SYSST */
+        if ((s->clkm.clocking_scheme ^ (value >> 11)) & 7) {
+            s->clkm.clocking_scheme = (value >> 11) & 7;
+            printf("%s: clocking scheme set to %s\n", __FUNCTION__,
+                            clkschemename[s->clkm.clocking_scheme]);
+        }
+        s->clkm.cold_start &= value & 0x3f;
+        return;
+
+    case 0x1c:	/* ARM_CKOUT1 */
+        diff = s->clkm.arm_ckout1 ^ value;
+        s->clkm.arm_ckout1 = value & 0x003f;
+        omap_clkm_ckout1_update(s, diff, value);
+        return;
+
+    case 0x20:	/* ARM_CKOUT2 */
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_clkm_ops = {
+    .read = omap_clkm_read,
+    .write = omap_clkm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static uint64_t omap_clkdsp_read(void *opaque, hwaddr addr,
+                                 unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x04:	/* DSP_IDLECT1 */
+        return s->clkm.dsp_idlect1;
+
+    case 0x08:	/* DSP_IDLECT2 */
+        return s->clkm.dsp_idlect2;
+
+    case 0x14:	/* DSP_RSTCT2 */
+        return s->clkm.dsp_rstct2;
+
+    case 0x18:	/* DSP_SYSST */
+        return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start |
+                (s->cpu->env.halted << 6);      /* Quite useless... */
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static inline void omap_clkdsp_idlect1_update(struct omap_mpu_state_s *s,
+                uint16_t diff, uint16_t value)
+{
+    omap_clk clk;
+
+    SET_CANIDLE("dspxor_ck", 1);			/* IDLXORP_DSP */
+}
+
+static inline void omap_clkdsp_idlect2_update(struct omap_mpu_state_s *s,
+                uint16_t diff, uint16_t value)
+{
+    omap_clk clk;
+
+    SET_ONOFF("dspxor_ck", 1);				/* EN_XORPCK */
+}
+
+static void omap_clkdsp_write(void *opaque, hwaddr addr,
+                              uint64_t value, unsigned size)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
+    uint16_t diff;
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x04:	/* DSP_IDLECT1 */
+        diff = s->clkm.dsp_idlect1 ^ value;
+        s->clkm.dsp_idlect1 = value & 0x01f7;
+        omap_clkdsp_idlect1_update(s, diff, value);
+        break;
+
+    case 0x08:	/* DSP_IDLECT2 */
+        s->clkm.dsp_idlect2 = value & 0x0037;
+        diff = s->clkm.dsp_idlect1 ^ value;
+        omap_clkdsp_idlect2_update(s, diff, value);
+        break;
+
+    case 0x14:	/* DSP_RSTCT2 */
+        s->clkm.dsp_rstct2 = value & 0x0001;
+        break;
+
+    case 0x18:	/* DSP_SYSST */
+        s->clkm.cold_start &= value & 0x3f;
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+    }
+}
+
+static const MemoryRegionOps omap_clkdsp_ops = {
+    .read = omap_clkdsp_read,
+    .write = omap_clkdsp_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_clkm_reset(struct omap_mpu_state_s *s)
+{
+    if (s->wdt && s->wdt->reset)
+        s->clkm.cold_start = 0x6;
+    s->clkm.clocking_scheme = 0;
+    omap_clkm_ckctl_update(s, ~0, 0x3000);
+    s->clkm.arm_ckctl = 0x3000;
+    omap_clkm_idlect1_update(s, s->clkm.arm_idlect1 ^ 0x0400, 0x0400);
+    s->clkm.arm_idlect1 = 0x0400;
+    omap_clkm_idlect2_update(s, s->clkm.arm_idlect2 ^ 0x0100, 0x0100);
+    s->clkm.arm_idlect2 = 0x0100;
+    s->clkm.arm_ewupct = 0x003f;
+    s->clkm.arm_rstct1 = 0x0000;
+    s->clkm.arm_rstct2 = 0x0000;
+    s->clkm.arm_ckout1 = 0x0015;
+    s->clkm.dpll1_mode = 0x2002;
+    omap_clkdsp_idlect1_update(s, s->clkm.dsp_idlect1 ^ 0x0040, 0x0040);
+    s->clkm.dsp_idlect1 = 0x0040;
+    omap_clkdsp_idlect2_update(s, ~0, 0x0000);
+    s->clkm.dsp_idlect2 = 0x0000;
+    s->clkm.dsp_rstct2 = 0x0000;
+}
+
+static void omap_clkm_init(MemoryRegion *memory, hwaddr mpu_base,
+                hwaddr dsp_base, struct omap_mpu_state_s *s)
+{
+    memory_region_init_io(&s->clkm_iomem, &omap_clkm_ops, s,
+                          "omap-clkm", 0x100);
+    memory_region_init_io(&s->clkdsp_iomem, &omap_clkdsp_ops, s,
+                          "omap-clkdsp", 0x1000);
+
+    s->clkm.arm_idlect1 = 0x03ff;
+    s->clkm.arm_idlect2 = 0x0100;
+    s->clkm.dsp_idlect1 = 0x0002;
+    omap_clkm_reset(s);
+    s->clkm.cold_start = 0x3a;
+
+    memory_region_add_subregion(memory, mpu_base, &s->clkm_iomem);
+    memory_region_add_subregion(memory, dsp_base, &s->clkdsp_iomem);
+}
+
+/* MPU I/O */
+struct omap_mpuio_s {
+    qemu_irq irq;
+    qemu_irq kbd_irq;
+    qemu_irq *in;
+    qemu_irq handler[16];
+    qemu_irq wakeup;
+    MemoryRegion iomem;
+
+    uint16_t inputs;
+    uint16_t outputs;
+    uint16_t dir;
+    uint16_t edge;
+    uint16_t mask;
+    uint16_t ints;
+
+    uint16_t debounce;
+    uint16_t latch;
+    uint8_t event;
+
+    uint8_t buttons[5];
+    uint8_t row_latch;
+    uint8_t cols;
+    int kbd_mask;
+    int clk;
+};
+
+static void omap_mpuio_set(void *opaque, int line, int level)
+{
+    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
+    uint16_t prev = s->inputs;
+
+    if (level)
+        s->inputs |= 1 << line;
+    else
+        s->inputs &= ~(1 << line);
+
+    if (((1 << line) & s->dir & ~s->mask) && s->clk) {
+        if ((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) {
+            s->ints |= 1 << line;
+            qemu_irq_raise(s->irq);
+            /* TODO: wakeup */
+        }
+        if ((s->event & (1 << 0)) &&		/* SET_GPIO_EVENT_MODE */
+                (s->event >> 1) == line)	/* PIN_SELECT */
+            s->latch = s->inputs;
+    }
+}
+
+static void omap_mpuio_kbd_update(struct omap_mpuio_s *s)
+{
+    int i;
+    uint8_t *row, rows = 0, cols = ~s->cols;
+
+    for (row = s->buttons + 4, i = 1 << 4; i; row --, i >>= 1)
+        if (*row & cols)
+            rows |= i;
+
+    qemu_set_irq(s->kbd_irq, rows && !s->kbd_mask && s->clk);
+    s->row_latch = ~rows;
+}
+
+static uint64_t omap_mpuio_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+    uint16_t ret;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (offset) {
+    case 0x00:	/* INPUT_LATCH */
+        return s->inputs;
+
+    case 0x04:	/* OUTPUT_REG */
+        return s->outputs;
+
+    case 0x08:	/* IO_CNTL */
+        return s->dir;
+
+    case 0x10:	/* KBR_LATCH */
+        return s->row_latch;
+
+    case 0x14:	/* KBC_REG */
+        return s->cols;
+
+    case 0x18:	/* GPIO_EVENT_MODE_REG */
+        return s->event;
+
+    case 0x1c:	/* GPIO_INT_EDGE_REG */
+        return s->edge;
+
+    case 0x20:	/* KBD_INT */
+        return (~s->row_latch & 0x1f) && !s->kbd_mask;
+
+    case 0x24:	/* GPIO_INT */
+        ret = s->ints;
+        s->ints &= s->mask;
+        if (ret)
+            qemu_irq_lower(s->irq);
+        return ret;
+
+    case 0x28:	/* KBD_MASKIT */
+        return s->kbd_mask;
+
+    case 0x2c:	/* GPIO_MASKIT */
+        return s->mask;
+
+    case 0x30:	/* GPIO_DEBOUNCING_REG */
+        return s->debounce;
+
+    case 0x34:	/* GPIO_LATCH_REG */
+        return s->latch;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_mpuio_write(void *opaque, hwaddr addr,
+                             uint64_t value, unsigned size)
+{
+    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+    uint16_t diff;
+    int ln;
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    switch (offset) {
+    case 0x04:	/* OUTPUT_REG */
+        diff = (s->outputs ^ value) & ~s->dir;
+        s->outputs = value;
+        while ((ln = ffs(diff))) {
+            ln --;
+            if (s->handler[ln])
+                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
+            diff &= ~(1 << ln);
+        }
+        break;
+
+    case 0x08:	/* IO_CNTL */
+        diff = s->outputs & (s->dir ^ value);
+        s->dir = value;
+
+        value = s->outputs & ~s->dir;
+        while ((ln = ffs(diff))) {
+            ln --;
+            if (s->handler[ln])
+                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
+            diff &= ~(1 << ln);
+        }
+        break;
+
+    case 0x14:	/* KBC_REG */
+        s->cols = value;
+        omap_mpuio_kbd_update(s);
+        break;
+
+    case 0x18:	/* GPIO_EVENT_MODE_REG */
+        s->event = value & 0x1f;
+        break;
+
+    case 0x1c:	/* GPIO_INT_EDGE_REG */
+        s->edge = value;
+        break;
+
+    case 0x28:	/* KBD_MASKIT */
+        s->kbd_mask = value & 1;
+        omap_mpuio_kbd_update(s);
+        break;
+
+    case 0x2c:	/* GPIO_MASKIT */
+        s->mask = value;
+        break;
+
+    case 0x30:	/* GPIO_DEBOUNCING_REG */
+        s->debounce = value & 0x1ff;
+        break;
+
+    case 0x00:	/* INPUT_LATCH */
+    case 0x10:	/* KBR_LATCH */
+    case 0x20:	/* KBD_INT */
+    case 0x24:	/* GPIO_INT */
+    case 0x34:	/* GPIO_LATCH_REG */
+        OMAP_RO_REG(addr);
+        return;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_mpuio_ops  = {
+    .read = omap_mpuio_read,
+    .write = omap_mpuio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_mpuio_reset(struct omap_mpuio_s *s)
+{
+    s->inputs = 0;
+    s->outputs = 0;
+    s->dir = ~0;
+    s->event = 0;
+    s->edge = 0;
+    s->kbd_mask = 0;
+    s->mask = 0;
+    s->debounce = 0;
+    s->latch = 0;
+    s->ints = 0;
+    s->row_latch = 0x1f;
+    s->clk = 1;
+}
+
+static void omap_mpuio_onoff(void *opaque, int line, int on)
+{
+    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
+
+    s->clk = on;
+    if (on)
+        omap_mpuio_kbd_update(s);
+}
+
+static struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *memory,
+                hwaddr base,
+                qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup,
+                omap_clk clk)
+{
+    struct omap_mpuio_s *s = (struct omap_mpuio_s *)
+            g_malloc0(sizeof(struct omap_mpuio_s));
+
+    s->irq = gpio_int;
+    s->kbd_irq = kbd_int;
+    s->wakeup = wakeup;
+    s->in = qemu_allocate_irqs(omap_mpuio_set, s, 16);
+    omap_mpuio_reset(s);
+
+    memory_region_init_io(&s->iomem, &omap_mpuio_ops, s,
+                          "omap-mpuio", 0x800);
+    memory_region_add_subregion(memory, base, &s->iomem);
+
+    omap_clk_adduser(clk, qemu_allocate_irqs(omap_mpuio_onoff, s, 1)[0]);
+
+    return s;
+}
+
+qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s)
+{
+    return s->in;
+}
+
+void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler)
+{
+    if (line >= 16 || line < 0)
+        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
+    s->handler[line] = handler;
+}
+
+void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down)
+{
+    if (row >= 5 || row < 0)
+        hw_error("%s: No key %i-%i\n", __FUNCTION__, col, row);
+
+    if (down)
+        s->buttons[row] |= 1 << col;
+    else
+        s->buttons[row] &= ~(1 << col);
+
+    omap_mpuio_kbd_update(s);
+}
+
+/* MicroWire Interface */
+struct omap_uwire_s {
+    MemoryRegion iomem;
+    qemu_irq txirq;
+    qemu_irq rxirq;
+    qemu_irq txdrq;
+
+    uint16_t txbuf;
+    uint16_t rxbuf;
+    uint16_t control;
+    uint16_t setup[5];
+
+    uWireSlave *chip[4];
+};
+
+static void omap_uwire_transfer_start(struct omap_uwire_s *s)
+{
+    int chipselect = (s->control >> 10) & 3;		/* INDEX */
+    uWireSlave *slave = s->chip[chipselect];
+
+    if ((s->control >> 5) & 0x1f) {			/* NB_BITS_WR */
+        if (s->control & (1 << 12))			/* CS_CMD */
+            if (slave && slave->send)
+                slave->send(slave->opaque,
+                                s->txbuf >> (16 - ((s->control >> 5) & 0x1f)));
+        s->control &= ~(1 << 14);			/* CSRB */
+        /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
+         * a DRQ.  When is the level IRQ supposed to be reset?  */
+    }
+
+    if ((s->control >> 0) & 0x1f) {			/* NB_BITS_RD */
+        if (s->control & (1 << 12))			/* CS_CMD */
+            if (slave && slave->receive)
+                s->rxbuf = slave->receive(slave->opaque);
+        s->control |= 1 << 15;				/* RDRB */
+        /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
+         * a DRQ.  When is the level IRQ supposed to be reset?  */
+    }
+}
+
+static uint64_t omap_uwire_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (offset) {
+    case 0x00:	/* RDR */
+        s->control &= ~(1 << 15);			/* RDRB */
+        return s->rxbuf;
+
+    case 0x04:	/* CSR */
+        return s->control;
+
+    case 0x08:	/* SR1 */
+        return s->setup[0];
+    case 0x0c:	/* SR2 */
+        return s->setup[1];
+    case 0x10:	/* SR3 */
+        return s->setup[2];
+    case 0x14:	/* SR4 */
+        return s->setup[3];
+    case 0x18:	/* SR5 */
+        return s->setup[4];
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_uwire_write(void *opaque, hwaddr addr,
+                             uint64_t value, unsigned size)
+{
+    struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    switch (offset) {
+    case 0x00:	/* TDR */
+        s->txbuf = value;				/* TD */
+        if ((s->setup[4] & (1 << 2)) &&			/* AUTO_TX_EN */
+                        ((s->setup[4] & (1 << 3)) ||	/* CS_TOGGLE_TX_EN */
+                         (s->control & (1 << 12)))) {	/* CS_CMD */
+            s->control |= 1 << 14;			/* CSRB */
+            omap_uwire_transfer_start(s);
+        }
+        break;
+
+    case 0x04:	/* CSR */
+        s->control = value & 0x1fff;
+        if (value & (1 << 13))				/* START */
+            omap_uwire_transfer_start(s);
+        break;
+
+    case 0x08:	/* SR1 */
+        s->setup[0] = value & 0x003f;
+        break;
+
+    case 0x0c:	/* SR2 */
+        s->setup[1] = value & 0x0fc0;
+        break;
+
+    case 0x10:	/* SR3 */
+        s->setup[2] = value & 0x0003;
+        break;
+
+    case 0x14:	/* SR4 */
+        s->setup[3] = value & 0x0001;
+        break;
+
+    case 0x18:	/* SR5 */
+        s->setup[4] = value & 0x000f;
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_uwire_ops = {
+    .read = omap_uwire_read,
+    .write = omap_uwire_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_uwire_reset(struct omap_uwire_s *s)
+{
+    s->control = 0;
+    s->setup[0] = 0;
+    s->setup[1] = 0;
+    s->setup[2] = 0;
+    s->setup[3] = 0;
+    s->setup[4] = 0;
+}
+
+static struct omap_uwire_s *omap_uwire_init(MemoryRegion *system_memory,
+                                            hwaddr base,
+                                            qemu_irq txirq, qemu_irq rxirq,
+                                            qemu_irq dma,
+                                            omap_clk clk)
+{
+    struct omap_uwire_s *s = (struct omap_uwire_s *)
+            g_malloc0(sizeof(struct omap_uwire_s));
+
+    s->txirq = txirq;
+    s->rxirq = rxirq;
+    s->txdrq = dma;
+    omap_uwire_reset(s);
+
+    memory_region_init_io(&s->iomem, &omap_uwire_ops, s, "omap-uwire", 0x800);
+    memory_region_add_subregion(system_memory, base, &s->iomem);
+
+    return s;
+}
+
+void omap_uwire_attach(struct omap_uwire_s *s,
+                uWireSlave *slave, int chipselect)
+{
+    if (chipselect < 0 || chipselect > 3) {
+        fprintf(stderr, "%s: Bad chipselect %i\n", __FUNCTION__, chipselect);
+        exit(-1);
+    }
+
+    s->chip[chipselect] = slave;
+}
+
+/* Pseudonoise Pulse-Width Light Modulator */
+struct omap_pwl_s {
+    MemoryRegion iomem;
+    uint8_t output;
+    uint8_t level;
+    uint8_t enable;
+    int clk;
+};
+
+static void omap_pwl_update(struct omap_pwl_s *s)
+{
+    int output = (s->clk && s->enable) ? s->level : 0;
+
+    if (output != s->output) {
+        s->output = output;
+        printf("%s: Backlight now at %i/256\n", __FUNCTION__, output);
+    }
+}
+
+static uint64_t omap_pwl_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 1) {
+        return omap_badwidth_read8(opaque, addr);
+    }
+
+    switch (offset) {
+    case 0x00:	/* PWL_LEVEL */
+        return s->level;
+    case 0x04:	/* PWL_CTRL */
+        return s->enable;
+    }
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_pwl_write(void *opaque, hwaddr addr,
+                           uint64_t value, unsigned size)
+{
+    struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 1) {
+        return omap_badwidth_write8(opaque, addr, value);
+    }
+
+    switch (offset) {
+    case 0x00:	/* PWL_LEVEL */
+        s->level = value;
+        omap_pwl_update(s);
+        break;
+    case 0x04:	/* PWL_CTRL */
+        s->enable = value & 1;
+        omap_pwl_update(s);
+        break;
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_pwl_ops = {
+    .read = omap_pwl_read,
+    .write = omap_pwl_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_pwl_reset(struct omap_pwl_s *s)
+{
+    s->output = 0;
+    s->level = 0;
+    s->enable = 0;
+    s->clk = 1;
+    omap_pwl_update(s);
+}
+
+static void omap_pwl_clk_update(void *opaque, int line, int on)
+{
+    struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
+
+    s->clk = on;
+    omap_pwl_update(s);
+}
+
+static struct omap_pwl_s *omap_pwl_init(MemoryRegion *system_memory,
+                                        hwaddr base,
+                                        omap_clk clk)
+{
+    struct omap_pwl_s *s = g_malloc0(sizeof(*s));
+
+    omap_pwl_reset(s);
+
+    memory_region_init_io(&s->iomem, &omap_pwl_ops, s,
+                          "omap-pwl", 0x800);
+    memory_region_add_subregion(system_memory, base, &s->iomem);
+
+    omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]);
+    return s;
+}
+
+/* Pulse-Width Tone module */
+struct omap_pwt_s {
+    MemoryRegion iomem;
+    uint8_t frc;
+    uint8_t vrc;
+    uint8_t gcr;
+    omap_clk clk;
+};
+
+static uint64_t omap_pwt_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    struct omap_pwt_s *s = (struct omap_pwt_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 1) {
+        return omap_badwidth_read8(opaque, addr);
+    }
+
+    switch (offset) {
+    case 0x00:	/* FRC */
+        return s->frc;
+    case 0x04:	/* VCR */
+        return s->vrc;
+    case 0x08:	/* GCR */
+        return s->gcr;
+    }
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_pwt_write(void *opaque, hwaddr addr,
+                           uint64_t value, unsigned size)
+{
+    struct omap_pwt_s *s = (struct omap_pwt_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 1) {
+        return omap_badwidth_write8(opaque, addr, value);
+    }
+
+    switch (offset) {
+    case 0x00:	/* FRC */
+        s->frc = value & 0x3f;
+        break;
+    case 0x04:	/* VRC */
+        if ((value ^ s->vrc) & 1) {
+            if (value & 1)
+                printf("%s: %iHz buzz on\n", __FUNCTION__, (int)
+                                /* 1.5 MHz from a 12-MHz or 13-MHz PWT_CLK */
+                                ((omap_clk_getrate(s->clk) >> 3) /
+                                 /* Pre-multiplexer divider */
+                                 ((s->gcr & 2) ? 1 : 154) /
+                                 /* Octave multiplexer */
+                                 (2 << (value & 3)) *
+                                 /* 101/107 divider */
+                                 ((value & (1 << 2)) ? 101 : 107) *
+                                 /*  49/55 divider */
+                                 ((value & (1 << 3)) ?  49 : 55) *
+                                 /*  50/63 divider */
+                                 ((value & (1 << 4)) ?  50 : 63) *
+                                 /*  80/127 divider */
+                                 ((value & (1 << 5)) ?  80 : 127) /
+                                 (107 * 55 * 63 * 127)));
+            else
+                printf("%s: silence!\n", __FUNCTION__);
+        }
+        s->vrc = value & 0x7f;
+        break;
+    case 0x08:	/* GCR */
+        s->gcr = value & 3;
+        break;
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_pwt_ops = {
+    .read =omap_pwt_read,
+    .write = omap_pwt_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_pwt_reset(struct omap_pwt_s *s)
+{
+    s->frc = 0;
+    s->vrc = 0;
+    s->gcr = 0;
+}
+
+static struct omap_pwt_s *omap_pwt_init(MemoryRegion *system_memory,
+                                        hwaddr base,
+                                        omap_clk clk)
+{
+    struct omap_pwt_s *s = g_malloc0(sizeof(*s));
+    s->clk = clk;
+    omap_pwt_reset(s);
+
+    memory_region_init_io(&s->iomem, &omap_pwt_ops, s,
+                          "omap-pwt", 0x800);
+    memory_region_add_subregion(system_memory, base, &s->iomem);
+    return s;
+}
+
+/* Real-time Clock module */
+struct omap_rtc_s {
+    MemoryRegion iomem;
+    qemu_irq irq;
+    qemu_irq alarm;
+    QEMUTimer *clk;
+
+    uint8_t interrupts;
+    uint8_t status;
+    int16_t comp_reg;
+    int running;
+    int pm_am;
+    int auto_comp;
+    int round;
+    struct tm alarm_tm;
+    time_t alarm_ti;
+
+    struct tm current_tm;
+    time_t ti;
+    uint64_t tick;
+};
+
+static void omap_rtc_interrupts_update(struct omap_rtc_s *s)
+{
+    /* s->alarm is level-triggered */
+    qemu_set_irq(s->alarm, (s->status >> 6) & 1);
+}
+
+static void omap_rtc_alarm_update(struct omap_rtc_s *s)
+{
+    s->alarm_ti = mktimegm(&s->alarm_tm);
+    if (s->alarm_ti == -1)
+        printf("%s: conversion failed\n", __FUNCTION__);
+}
+
+static uint64_t omap_rtc_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+    uint8_t i;
+
+    if (size != 1) {
+        return omap_badwidth_read8(opaque, addr);
+    }
+
+    switch (offset) {
+    case 0x00:	/* SECONDS_REG */
+        return to_bcd(s->current_tm.tm_sec);
+
+    case 0x04:	/* MINUTES_REG */
+        return to_bcd(s->current_tm.tm_min);
+
+    case 0x08:	/* HOURS_REG */
+        if (s->pm_am)
+            return ((s->current_tm.tm_hour > 11) << 7) |
+                    to_bcd(((s->current_tm.tm_hour - 1) % 12) + 1);
+        else
+            return to_bcd(s->current_tm.tm_hour);
+
+    case 0x0c:	/* DAYS_REG */
+        return to_bcd(s->current_tm.tm_mday);
+
+    case 0x10:	/* MONTHS_REG */
+        return to_bcd(s->current_tm.tm_mon + 1);
+
+    case 0x14:	/* YEARS_REG */
+        return to_bcd(s->current_tm.tm_year % 100);
+
+    case 0x18:	/* WEEK_REG */
+        return s->current_tm.tm_wday;
+
+    case 0x20:	/* ALARM_SECONDS_REG */
+        return to_bcd(s->alarm_tm.tm_sec);
+
+    case 0x24:	/* ALARM_MINUTES_REG */
+        return to_bcd(s->alarm_tm.tm_min);
+
+    case 0x28:	/* ALARM_HOURS_REG */
+        if (s->pm_am)
+            return ((s->alarm_tm.tm_hour > 11) << 7) |
+                    to_bcd(((s->alarm_tm.tm_hour - 1) % 12) + 1);
+        else
+            return to_bcd(s->alarm_tm.tm_hour);
+
+    case 0x2c:	/* ALARM_DAYS_REG */
+        return to_bcd(s->alarm_tm.tm_mday);
+
+    case 0x30:	/* ALARM_MONTHS_REG */
+        return to_bcd(s->alarm_tm.tm_mon + 1);
+
+    case 0x34:	/* ALARM_YEARS_REG */
+        return to_bcd(s->alarm_tm.tm_year % 100);
+
+    case 0x40:	/* RTC_CTRL_REG */
+        return (s->pm_am << 3) | (s->auto_comp << 2) |
+                (s->round << 1) | s->running;
+
+    case 0x44:	/* RTC_STATUS_REG */
+        i = s->status;
+        s->status &= ~0x3d;
+        return i;
+
+    case 0x48:	/* RTC_INTERRUPTS_REG */
+        return s->interrupts;
+
+    case 0x4c:	/* RTC_COMP_LSB_REG */
+        return ((uint16_t) s->comp_reg) & 0xff;
+
+    case 0x50:	/* RTC_COMP_MSB_REG */
+        return ((uint16_t) s->comp_reg) >> 8;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_rtc_write(void *opaque, hwaddr addr,
+                           uint64_t value, unsigned size)
+{
+    struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+    struct tm new_tm;
+    time_t ti[2];
+
+    if (size != 1) {
+        return omap_badwidth_write8(opaque, addr, value);
+    }
+
+    switch (offset) {
+    case 0x00:	/* SECONDS_REG */
+#ifdef ALMDEBUG
+        printf("RTC SEC_REG <-- %02x\n", value);
+#endif
+        s->ti -= s->current_tm.tm_sec;
+        s->ti += from_bcd(value);
+        return;
+
+    case 0x04:	/* MINUTES_REG */
+#ifdef ALMDEBUG
+        printf("RTC MIN_REG <-- %02x\n", value);
+#endif
+        s->ti -= s->current_tm.tm_min * 60;
+        s->ti += from_bcd(value) * 60;
+        return;
+
+    case 0x08:	/* HOURS_REG */
+#ifdef ALMDEBUG
+        printf("RTC HRS_REG <-- %02x\n", value);
+#endif
+        s->ti -= s->current_tm.tm_hour * 3600;
+        if (s->pm_am) {
+            s->ti += (from_bcd(value & 0x3f) & 12) * 3600;
+            s->ti += ((value >> 7) & 1) * 43200;
+        } else
+            s->ti += from_bcd(value & 0x3f) * 3600;
+        return;
+
+    case 0x0c:	/* DAYS_REG */
+#ifdef ALMDEBUG
+        printf("RTC DAY_REG <-- %02x\n", value);
+#endif
+        s->ti -= s->current_tm.tm_mday * 86400;
+        s->ti += from_bcd(value) * 86400;
+        return;
+
+    case 0x10:	/* MONTHS_REG */
+#ifdef ALMDEBUG
+        printf("RTC MTH_REG <-- %02x\n", value);
+#endif
+        memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
+        new_tm.tm_mon = from_bcd(value);
+        ti[0] = mktimegm(&s->current_tm);
+        ti[1] = mktimegm(&new_tm);
+
+        if (ti[0] != -1 && ti[1] != -1) {
+            s->ti -= ti[0];
+            s->ti += ti[1];
+        } else {
+            /* A less accurate version */
+            s->ti -= s->current_tm.tm_mon * 2592000;
+            s->ti += from_bcd(value) * 2592000;
+        }
+        return;
+
+    case 0x14:	/* YEARS_REG */
+#ifdef ALMDEBUG
+        printf("RTC YRS_REG <-- %02x\n", value);
+#endif
+        memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
+        new_tm.tm_year += from_bcd(value) - (new_tm.tm_year % 100);
+        ti[0] = mktimegm(&s->current_tm);
+        ti[1] = mktimegm(&new_tm);
+
+        if (ti[0] != -1 && ti[1] != -1) {
+            s->ti -= ti[0];
+            s->ti += ti[1];
+        } else {
+            /* A less accurate version */
+            s->ti -= (s->current_tm.tm_year % 100) * 31536000;
+            s->ti += from_bcd(value) * 31536000;
+        }
+        return;
+
+    case 0x18:	/* WEEK_REG */
+        return;	/* Ignored */
+
+    case 0x20:	/* ALARM_SECONDS_REG */
+#ifdef ALMDEBUG
+        printf("ALM SEC_REG <-- %02x\n", value);
+#endif
+        s->alarm_tm.tm_sec = from_bcd(value);
+        omap_rtc_alarm_update(s);
+        return;
+
+    case 0x24:	/* ALARM_MINUTES_REG */
+#ifdef ALMDEBUG
+        printf("ALM MIN_REG <-- %02x\n", value);
+#endif
+        s->alarm_tm.tm_min = from_bcd(value);
+        omap_rtc_alarm_update(s);
+        return;
+
+    case 0x28:	/* ALARM_HOURS_REG */
+#ifdef ALMDEBUG
+        printf("ALM HRS_REG <-- %02x\n", value);
+#endif
+        if (s->pm_am)
+            s->alarm_tm.tm_hour =
+                    ((from_bcd(value & 0x3f)) % 12) +
+                    ((value >> 7) & 1) * 12;
+        else
+            s->alarm_tm.tm_hour = from_bcd(value);
+        omap_rtc_alarm_update(s);
+        return;
+
+    case 0x2c:	/* ALARM_DAYS_REG */
+#ifdef ALMDEBUG
+        printf("ALM DAY_REG <-- %02x\n", value);
+#endif
+        s->alarm_tm.tm_mday = from_bcd(value);
+        omap_rtc_alarm_update(s);
+        return;
+
+    case 0x30:	/* ALARM_MONTHS_REG */
+#ifdef ALMDEBUG
+        printf("ALM MON_REG <-- %02x\n", value);
+#endif
+        s->alarm_tm.tm_mon = from_bcd(value);
+        omap_rtc_alarm_update(s);
+        return;
+
+    case 0x34:	/* ALARM_YEARS_REG */
+#ifdef ALMDEBUG
+        printf("ALM YRS_REG <-- %02x\n", value);
+#endif
+        s->alarm_tm.tm_year = from_bcd(value);
+        omap_rtc_alarm_update(s);
+        return;
+
+    case 0x40:	/* RTC_CTRL_REG */
+#ifdef ALMDEBUG
+        printf("RTC CONTROL <-- %02x\n", value);
+#endif
+        s->pm_am = (value >> 3) & 1;
+        s->auto_comp = (value >> 2) & 1;
+        s->round = (value >> 1) & 1;
+        s->running = value & 1;
+        s->status &= 0xfd;
+        s->status |= s->running << 1;
+        return;
+
+    case 0x44:	/* RTC_STATUS_REG */
+#ifdef ALMDEBUG
+        printf("RTC STATUSL <-- %02x\n", value);
+#endif
+        s->status &= ~((value & 0xc0) ^ 0x80);
+        omap_rtc_interrupts_update(s);
+        return;
+
+    case 0x48:	/* RTC_INTERRUPTS_REG */
+#ifdef ALMDEBUG
+        printf("RTC INTRS <-- %02x\n", value);
+#endif
+        s->interrupts = value;
+        return;
+
+    case 0x4c:	/* RTC_COMP_LSB_REG */
+#ifdef ALMDEBUG
+        printf("RTC COMPLSB <-- %02x\n", value);
+#endif
+        s->comp_reg &= 0xff00;
+        s->comp_reg |= 0x00ff & value;
+        return;
+
+    case 0x50:	/* RTC_COMP_MSB_REG */
+#ifdef ALMDEBUG
+        printf("RTC COMPMSB <-- %02x\n", value);
+#endif
+        s->comp_reg &= 0x00ff;
+        s->comp_reg |= 0xff00 & (value << 8);
+        return;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_rtc_ops = {
+    .read = omap_rtc_read,
+    .write = omap_rtc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_rtc_tick(void *opaque)
+{
+    struct omap_rtc_s *s = opaque;
+
+    if (s->round) {
+        /* Round to nearest full minute.  */
+        if (s->current_tm.tm_sec < 30)
+            s->ti -= s->current_tm.tm_sec;
+        else
+            s->ti += 60 - s->current_tm.tm_sec;
+
+        s->round = 0;
+    }
+
+    localtime_r(&s->ti, &s->current_tm);
+
+    if ((s->interrupts & 0x08) && s->ti == s->alarm_ti) {
+        s->status |= 0x40;
+        omap_rtc_interrupts_update(s);
+    }
+
+    if (s->interrupts & 0x04)
+        switch (s->interrupts & 3) {
+        case 0:
+            s->status |= 0x04;
+            qemu_irq_pulse(s->irq);
+            break;
+        case 1:
+            if (s->current_tm.tm_sec)
+                break;
+            s->status |= 0x08;
+            qemu_irq_pulse(s->irq);
+            break;
+        case 2:
+            if (s->current_tm.tm_sec || s->current_tm.tm_min)
+                break;
+            s->status |= 0x10;
+            qemu_irq_pulse(s->irq);
+            break;
+        case 3:
+            if (s->current_tm.tm_sec ||
+                            s->current_tm.tm_min || s->current_tm.tm_hour)
+                break;
+            s->status |= 0x20;
+            qemu_irq_pulse(s->irq);
+            break;
+        }
+
+    /* Move on */
+    if (s->running)
+        s->ti ++;
+    s->tick += 1000;
+
+    /*
+     * Every full hour add a rough approximation of the compensation
+     * register to the 32kHz Timer (which drives the RTC) value. 
+     */
+    if (s->auto_comp && !s->current_tm.tm_sec && !s->current_tm.tm_min)
+        s->tick += s->comp_reg * 1000 / 32768;
+
+    qemu_mod_timer(s->clk, s->tick);
+}
+
+static void omap_rtc_reset(struct omap_rtc_s *s)
+{
+    struct tm tm;
+
+    s->interrupts = 0;
+    s->comp_reg = 0;
+    s->running = 0;
+    s->pm_am = 0;
+    s->auto_comp = 0;
+    s->round = 0;
+    s->tick = qemu_get_clock_ms(rtc_clock);
+    memset(&s->alarm_tm, 0, sizeof(s->alarm_tm));
+    s->alarm_tm.tm_mday = 0x01;
+    s->status = 1 << 7;
+    qemu_get_timedate(&tm, 0);
+    s->ti = mktimegm(&tm);
+
+    omap_rtc_alarm_update(s);
+    omap_rtc_tick(s);
+}
+
+static struct omap_rtc_s *omap_rtc_init(MemoryRegion *system_memory,
+                                        hwaddr base,
+                                        qemu_irq timerirq, qemu_irq alarmirq,
+                                        omap_clk clk)
+{
+    struct omap_rtc_s *s = (struct omap_rtc_s *)
+            g_malloc0(sizeof(struct omap_rtc_s));
+
+    s->irq = timerirq;
+    s->alarm = alarmirq;
+    s->clk = qemu_new_timer_ms(rtc_clock, omap_rtc_tick, s);
+
+    omap_rtc_reset(s);
+
+    memory_region_init_io(&s->iomem, &omap_rtc_ops, s,
+                          "omap-rtc", 0x800);
+    memory_region_add_subregion(system_memory, base, &s->iomem);
+
+    return s;
+}
+
+/* Multi-channel Buffered Serial Port interfaces */
+struct omap_mcbsp_s {
+    MemoryRegion iomem;
+    qemu_irq txirq;
+    qemu_irq rxirq;
+    qemu_irq txdrq;
+    qemu_irq rxdrq;
+
+    uint16_t spcr[2];
+    uint16_t rcr[2];
+    uint16_t xcr[2];
+    uint16_t srgr[2];
+    uint16_t mcr[2];
+    uint16_t pcr;
+    uint16_t rcer[8];
+    uint16_t xcer[8];
+    int tx_rate;
+    int rx_rate;
+    int tx_req;
+    int rx_req;
+
+    I2SCodec *codec;
+    QEMUTimer *source_timer;
+    QEMUTimer *sink_timer;
+};
+
+static void omap_mcbsp_intr_update(struct omap_mcbsp_s *s)
+{
+    int irq;
+
+    switch ((s->spcr[0] >> 4) & 3) {			/* RINTM */
+    case 0:
+        irq = (s->spcr[0] >> 1) & 1;			/* RRDY */
+        break;
+    case 3:
+        irq = (s->spcr[0] >> 3) & 1;			/* RSYNCERR */
+        break;
+    default:
+        irq = 0;
+        break;
+    }
+
+    if (irq)
+        qemu_irq_pulse(s->rxirq);
+
+    switch ((s->spcr[1] >> 4) & 3) {			/* XINTM */
+    case 0:
+        irq = (s->spcr[1] >> 1) & 1;			/* XRDY */
+        break;
+    case 3:
+        irq = (s->spcr[1] >> 3) & 1;			/* XSYNCERR */
+        break;
+    default:
+        irq = 0;
+        break;
+    }
+
+    if (irq)
+        qemu_irq_pulse(s->txirq);
+}
+
+static void omap_mcbsp_rx_newdata(struct omap_mcbsp_s *s)
+{
+    if ((s->spcr[0] >> 1) & 1)				/* RRDY */
+        s->spcr[0] |= 1 << 2;				/* RFULL */
+    s->spcr[0] |= 1 << 1;				/* RRDY */
+    qemu_irq_raise(s->rxdrq);
+    omap_mcbsp_intr_update(s);
+}
+
+static void omap_mcbsp_source_tick(void *opaque)
+{
+    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+    static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
+
+    if (!s->rx_rate)
+        return;
+    if (s->rx_req)
+        printf("%s: Rx FIFO overrun\n", __FUNCTION__);
+
+    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_ns(vm_clock) +
+                   get_ticks_per_sec());
+}
+
+static void omap_mcbsp_rx_start(struct omap_mcbsp_s *s)
+{
+    if (!s->codec || !s->codec->rts)
+        omap_mcbsp_source_tick(s);
+    else if (s->codec->in.len) {
+        s->rx_req = s->codec->in.len;
+        omap_mcbsp_rx_newdata(s);
+    }
+}
+
+static void omap_mcbsp_rx_stop(struct omap_mcbsp_s *s)
+{
+    qemu_del_timer(s->source_timer);
+}
+
+static void omap_mcbsp_rx_done(struct omap_mcbsp_s *s)
+{
+    s->spcr[0] &= ~(1 << 1);				/* RRDY */
+    qemu_irq_lower(s->rxdrq);
+    omap_mcbsp_intr_update(s);
+}
+
+static void omap_mcbsp_tx_newdata(struct omap_mcbsp_s *s)
+{
+    s->spcr[1] |= 1 << 1;				/* XRDY */
+    qemu_irq_raise(s->txdrq);
+    omap_mcbsp_intr_update(s);
+}
+
+static void omap_mcbsp_sink_tick(void *opaque)
+{
+    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+    static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
+
+    if (!s->tx_rate)
+        return;
+    if (s->tx_req)
+        printf("%s: Tx FIFO underrun\n", __FUNCTION__);
+
+    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_ns(vm_clock) +
+                   get_ticks_per_sec());
+}
+
+static void omap_mcbsp_tx_start(struct omap_mcbsp_s *s)
+{
+    if (!s->codec || !s->codec->cts)
+        omap_mcbsp_sink_tick(s);
+    else if (s->codec->out.size) {
+        s->tx_req = s->codec->out.size;
+        omap_mcbsp_tx_newdata(s);
+    }
+}
+
+static void omap_mcbsp_tx_done(struct omap_mcbsp_s *s)
+{
+    s->spcr[1] &= ~(1 << 1);				/* XRDY */
+    qemu_irq_lower(s->txdrq);
+    omap_mcbsp_intr_update(s);
+    if (s->codec && s->codec->cts)
+        s->codec->tx_swallow(s->codec->opaque);
+}
+
+static void omap_mcbsp_tx_stop(struct omap_mcbsp_s *s)
+{
+    s->tx_req = 0;
+    omap_mcbsp_tx_done(s);
+    qemu_del_timer(s->sink_timer);
+}
+
+static void omap_mcbsp_req_update(struct omap_mcbsp_s *s)
+{
+    int prev_rx_rate, prev_tx_rate;
+    int rx_rate = 0, tx_rate = 0;
+    int cpu_rate = 1500000;	/* XXX */
+
+    /* TODO: check CLKSTP bit */
+    if (s->spcr[1] & (1 << 6)) {			/* GRST */
+        if (s->spcr[0] & (1 << 0)) {			/* RRST */
+            if ((s->srgr[1] & (1 << 13)) &&		/* CLKSM */
+                            (s->pcr & (1 << 8))) {	/* CLKRM */
+                if (~s->pcr & (1 << 7))			/* SCLKME */
+                    rx_rate = cpu_rate /
+                            ((s->srgr[0] & 0xff) + 1);	/* CLKGDV */
+            } else
+                if (s->codec)
+                    rx_rate = s->codec->rx_rate;
+        }
+
+        if (s->spcr[1] & (1 << 0)) {			/* XRST */
+            if ((s->srgr[1] & (1 << 13)) &&		/* CLKSM */
+                            (s->pcr & (1 << 9))) {	/* CLKXM */
+                if (~s->pcr & (1 << 7))			/* SCLKME */
+                    tx_rate = cpu_rate /
+                            ((s->srgr[0] & 0xff) + 1);	/* CLKGDV */
+            } else
+                if (s->codec)
+                    tx_rate = s->codec->tx_rate;
+        }
+    }
+    prev_tx_rate = s->tx_rate;
+    prev_rx_rate = s->rx_rate;
+    s->tx_rate = tx_rate;
+    s->rx_rate = rx_rate;
+
+    if (s->codec)
+        s->codec->set_rate(s->codec->opaque, rx_rate, tx_rate);
+
+    if (!prev_tx_rate && tx_rate)
+        omap_mcbsp_tx_start(s);
+    else if (s->tx_rate && !tx_rate)
+        omap_mcbsp_tx_stop(s);
+
+    if (!prev_rx_rate && rx_rate)
+        omap_mcbsp_rx_start(s);
+    else if (prev_tx_rate && !tx_rate)
+        omap_mcbsp_rx_stop(s);
+}
+
+static uint64_t omap_mcbsp_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+    uint16_t ret;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (offset) {
+    case 0x00:	/* DRR2 */
+        if (((s->rcr[0] >> 5) & 7) < 3)			/* RWDLEN1 */
+            return 0x0000;
+        /* Fall through.  */
+    case 0x02:	/* DRR1 */
+        if (s->rx_req < 2) {
+            printf("%s: Rx FIFO underrun\n", __FUNCTION__);
+            omap_mcbsp_rx_done(s);
+        } else {
+            s->tx_req -= 2;
+            if (s->codec && s->codec->in.len >= 2) {
+                ret = s->codec->in.fifo[s->codec->in.start ++] << 8;
+                ret |= s->codec->in.fifo[s->codec->in.start ++];
+                s->codec->in.len -= 2;
+            } else
+                ret = 0x0000;
+            if (!s->tx_req)
+                omap_mcbsp_rx_done(s);
+            return ret;
+        }
+        return 0x0000;
+
+    case 0x04:	/* DXR2 */
+    case 0x06:	/* DXR1 */
+        return 0x0000;
+
+    case 0x08:	/* SPCR2 */
+        return s->spcr[1];
+    case 0x0a:	/* SPCR1 */
+        return s->spcr[0];
+    case 0x0c:	/* RCR2 */
+        return s->rcr[1];
+    case 0x0e:	/* RCR1 */
+        return s->rcr[0];
+    case 0x10:	/* XCR2 */
+        return s->xcr[1];
+    case 0x12:	/* XCR1 */
+        return s->xcr[0];
+    case 0x14:	/* SRGR2 */
+        return s->srgr[1];
+    case 0x16:	/* SRGR1 */
+        return s->srgr[0];
+    case 0x18:	/* MCR2 */
+        return s->mcr[1];
+    case 0x1a:	/* MCR1 */
+        return s->mcr[0];
+    case 0x1c:	/* RCERA */
+        return s->rcer[0];
+    case 0x1e:	/* RCERB */
+        return s->rcer[1];
+    case 0x20:	/* XCERA */
+        return s->xcer[0];
+    case 0x22:	/* XCERB */
+        return s->xcer[1];
+    case 0x24:	/* PCR0 */
+        return s->pcr;
+    case 0x26:	/* RCERC */
+        return s->rcer[2];
+    case 0x28:	/* RCERD */
+        return s->rcer[3];
+    case 0x2a:	/* XCERC */
+        return s->xcer[2];
+    case 0x2c:	/* XCERD */
+        return s->xcer[3];
+    case 0x2e:	/* RCERE */
+        return s->rcer[4];
+    case 0x30:	/* RCERF */
+        return s->rcer[5];
+    case 0x32:	/* XCERE */
+        return s->xcer[4];
+    case 0x34:	/* XCERF */
+        return s->xcer[5];
+    case 0x36:	/* RCERG */
+        return s->rcer[6];
+    case 0x38:	/* RCERH */
+        return s->rcer[7];
+    case 0x3a:	/* XCERG */
+        return s->xcer[6];
+    case 0x3c:	/* XCERH */
+        return s->xcer[7];
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_mcbsp_writeh(void *opaque, hwaddr addr,
+                uint32_t value)
+{
+    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    switch (offset) {
+    case 0x00:	/* DRR2 */
+    case 0x02:	/* DRR1 */
+        OMAP_RO_REG(addr);
+        return;
+
+    case 0x04:	/* DXR2 */
+        if (((s->xcr[0] >> 5) & 7) < 3)			/* XWDLEN1 */
+            return;
+        /* Fall through.  */
+    case 0x06:	/* DXR1 */
+        if (s->tx_req > 1) {
+            s->tx_req -= 2;
+            if (s->codec && s->codec->cts) {
+                s->codec->out.fifo[s->codec->out.len ++] = (value >> 8) & 0xff;
+                s->codec->out.fifo[s->codec->out.len ++] = (value >> 0) & 0xff;
+            }
+            if (s->tx_req < 2)
+                omap_mcbsp_tx_done(s);
+        } else
+            printf("%s: Tx FIFO overrun\n", __FUNCTION__);
+        return;
+
+    case 0x08:	/* SPCR2 */
+        s->spcr[1] &= 0x0002;
+        s->spcr[1] |= 0x03f9 & value;
+        s->spcr[1] |= 0x0004 & (value << 2);		/* XEMPTY := XRST */
+        if (~value & 1)					/* XRST */
+            s->spcr[1] &= ~6;
+        omap_mcbsp_req_update(s);
+        return;
+    case 0x0a:	/* SPCR1 */
+        s->spcr[0] &= 0x0006;
+        s->spcr[0] |= 0xf8f9 & value;
+        if (value & (1 << 15))				/* DLB */
+            printf("%s: Digital Loopback mode enable attempt\n", __FUNCTION__);
+        if (~value & 1) {				/* RRST */
+            s->spcr[0] &= ~6;
+            s->rx_req = 0;
+            omap_mcbsp_rx_done(s);
+        }
+        omap_mcbsp_req_update(s);
+        return;
+
+    case 0x0c:	/* RCR2 */
+        s->rcr[1] = value & 0xffff;
+        return;
+    case 0x0e:	/* RCR1 */
+        s->rcr[0] = value & 0x7fe0;
+        return;
+    case 0x10:	/* XCR2 */
+        s->xcr[1] = value & 0xffff;
+        return;
+    case 0x12:	/* XCR1 */
+        s->xcr[0] = value & 0x7fe0;
+        return;
+    case 0x14:	/* SRGR2 */
+        s->srgr[1] = value & 0xffff;
+        omap_mcbsp_req_update(s);
+        return;
+    case 0x16:	/* SRGR1 */
+        s->srgr[0] = value & 0xffff;
+        omap_mcbsp_req_update(s);
+        return;
+    case 0x18:	/* MCR2 */
+        s->mcr[1] = value & 0x03e3;
+        if (value & 3)					/* XMCM */
+            printf("%s: Tx channel selection mode enable attempt\n",
+                            __FUNCTION__);
+        return;
+    case 0x1a:	/* MCR1 */
+        s->mcr[0] = value & 0x03e1;
+        if (value & 1)					/* RMCM */
+            printf("%s: Rx channel selection mode enable attempt\n",
+                            __FUNCTION__);
+        return;
+    case 0x1c:	/* RCERA */
+        s->rcer[0] = value & 0xffff;
+        return;
+    case 0x1e:	/* RCERB */
+        s->rcer[1] = value & 0xffff;
+        return;
+    case 0x20:	/* XCERA */
+        s->xcer[0] = value & 0xffff;
+        return;
+    case 0x22:	/* XCERB */
+        s->xcer[1] = value & 0xffff;
+        return;
+    case 0x24:	/* PCR0 */
+        s->pcr = value & 0x7faf;
+        return;
+    case 0x26:	/* RCERC */
+        s->rcer[2] = value & 0xffff;
+        return;
+    case 0x28:	/* RCERD */
+        s->rcer[3] = value & 0xffff;
+        return;
+    case 0x2a:	/* XCERC */
+        s->xcer[2] = value & 0xffff;
+        return;
+    case 0x2c:	/* XCERD */
+        s->xcer[3] = value & 0xffff;
+        return;
+    case 0x2e:	/* RCERE */
+        s->rcer[4] = value & 0xffff;
+        return;
+    case 0x30:	/* RCERF */
+        s->rcer[5] = value & 0xffff;
+        return;
+    case 0x32:	/* XCERE */
+        s->xcer[4] = value & 0xffff;
+        return;
+    case 0x34:	/* XCERF */
+        s->xcer[5] = value & 0xffff;
+        return;
+    case 0x36:	/* RCERG */
+        s->rcer[6] = value & 0xffff;
+        return;
+    case 0x38:	/* RCERH */
+        s->rcer[7] = value & 0xffff;
+        return;
+    case 0x3a:	/* XCERG */
+        s->xcer[6] = value & 0xffff;
+        return;
+    case 0x3c:	/* XCERH */
+        s->xcer[7] = value & 0xffff;
+        return;
+    }
+
+    OMAP_BAD_REG(addr);
+}
+
+static void omap_mcbsp_writew(void *opaque, hwaddr addr,
+                uint32_t value)
+{
+    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (offset == 0x04) {				/* DXR */
+        if (((s->xcr[0] >> 5) & 7) < 3)			/* XWDLEN1 */
+            return;
+        if (s->tx_req > 3) {
+            s->tx_req -= 4;
+            if (s->codec && s->codec->cts) {
+                s->codec->out.fifo[s->codec->out.len ++] =
+                        (value >> 24) & 0xff;
+                s->codec->out.fifo[s->codec->out.len ++] =
+                        (value >> 16) & 0xff;
+                s->codec->out.fifo[s->codec->out.len ++] =
+                        (value >> 8) & 0xff;
+                s->codec->out.fifo[s->codec->out.len ++] =
+                        (value >> 0) & 0xff;
+            }
+            if (s->tx_req < 4)
+                omap_mcbsp_tx_done(s);
+        } else
+            printf("%s: Tx FIFO overrun\n", __FUNCTION__);
+        return;
+    }
+
+    omap_badwidth_write16(opaque, addr, value);
+}
+
+static void omap_mcbsp_write(void *opaque, hwaddr addr,
+                             uint64_t value, unsigned size)
+{
+    switch (size) {
+    case 2: return omap_mcbsp_writeh(opaque, addr, value);
+    case 4: return omap_mcbsp_writew(opaque, addr, value);
+    default: return omap_badwidth_write16(opaque, addr, value);
+    }
+}
+
+static const MemoryRegionOps omap_mcbsp_ops = {
+    .read = omap_mcbsp_read,
+    .write = omap_mcbsp_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_mcbsp_reset(struct omap_mcbsp_s *s)
+{
+    memset(&s->spcr, 0, sizeof(s->spcr));
+    memset(&s->rcr, 0, sizeof(s->rcr));
+    memset(&s->xcr, 0, sizeof(s->xcr));
+    s->srgr[0] = 0x0001;
+    s->srgr[1] = 0x2000;
+    memset(&s->mcr, 0, sizeof(s->mcr));
+    memset(&s->pcr, 0, sizeof(s->pcr));
+    memset(&s->rcer, 0, sizeof(s->rcer));
+    memset(&s->xcer, 0, sizeof(s->xcer));
+    s->tx_req = 0;
+    s->rx_req = 0;
+    s->tx_rate = 0;
+    s->rx_rate = 0;
+    qemu_del_timer(s->source_timer);
+    qemu_del_timer(s->sink_timer);
+}
+
+static struct omap_mcbsp_s *omap_mcbsp_init(MemoryRegion *system_memory,
+                                            hwaddr base,
+                                            qemu_irq txirq, qemu_irq rxirq,
+                                            qemu_irq *dma, omap_clk clk)
+{
+    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *)
+            g_malloc0(sizeof(struct omap_mcbsp_s));
+
+    s->txirq = txirq;
+    s->rxirq = rxirq;
+    s->txdrq = dma[0];
+    s->rxdrq = dma[1];
+    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);
+
+    memory_region_init_io(&s->iomem, &omap_mcbsp_ops, s, "omap-mcbsp", 0x800);
+    memory_region_add_subregion(system_memory, base, &s->iomem);
+
+    return s;
+}
+
+static void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
+{
+    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+
+    if (s->rx_rate) {
+        s->rx_req = s->codec->in.len;
+        omap_mcbsp_rx_newdata(s);
+    }
+}
+
+static void omap_mcbsp_i2s_start(void *opaque, int line, int level)
+{
+    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
+
+    if (s->tx_rate) {
+        s->tx_req = s->codec->out.size;
+        omap_mcbsp_tx_newdata(s);
+    }
+}
+
+void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, I2SCodec *slave)
+{
+    s->codec = slave;
+    slave->rx_swallow = qemu_allocate_irqs(omap_mcbsp_i2s_swallow, s, 1)[0];
+    slave->tx_start = qemu_allocate_irqs(omap_mcbsp_i2s_start, s, 1)[0];
+}
+
+/* LED Pulse Generators */
+struct omap_lpg_s {
+    MemoryRegion iomem;
+    QEMUTimer *tm;
+
+    uint8_t control;
+    uint8_t power;
+    int64_t on;
+    int64_t period;
+    int clk;
+    int cycle;
+};
+
+static void omap_lpg_tick(void *opaque)
+{
+    struct omap_lpg_s *s = opaque;
+
+    if (s->cycle)
+        qemu_mod_timer(s->tm, qemu_get_clock_ms(vm_clock) + s->period - s->on);
+    else
+        qemu_mod_timer(s->tm, qemu_get_clock_ms(vm_clock) + s->on);
+
+    s->cycle = !s->cycle;
+    printf("%s: LED is %s\n", __FUNCTION__, s->cycle ? "on" : "off");
+}
+
+static void omap_lpg_update(struct omap_lpg_s *s)
+{
+    int64_t on, period = 1, ticks = 1000;
+    static const int per[8] = { 1, 2, 4, 8, 12, 16, 20, 24 };
+
+    if (~s->control & (1 << 6))					/* LPGRES */
+        on = 0;
+    else if (s->control & (1 << 7))				/* PERM_ON */
+        on = period;
+    else {
+        period = muldiv64(ticks, per[s->control & 7],		/* PERCTRL */
+                        256 / 32);
+        on = (s->clk && s->power) ? muldiv64(ticks,
+                        per[(s->control >> 3) & 7], 256) : 0;	/* ONCTRL */
+    }
+
+    qemu_del_timer(s->tm);
+    if (on == period && s->on < s->period)
+        printf("%s: LED is on\n", __FUNCTION__);
+    else if (on == 0 && s->on)
+        printf("%s: LED is off\n", __FUNCTION__);
+    else if (on && (on != s->on || period != s->period)) {
+        s->cycle = 0;
+        s->on = on;
+        s->period = period;
+        omap_lpg_tick(s);
+        return;
+    }
+
+    s->on = on;
+    s->period = period;
+}
+
+static void omap_lpg_reset(struct omap_lpg_s *s)
+{
+    s->control = 0x00;
+    s->power = 0x00;
+    s->clk = 1;
+    omap_lpg_update(s);
+}
+
+static uint64_t omap_lpg_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 1) {
+        return omap_badwidth_read8(opaque, addr);
+    }
+
+    switch (offset) {
+    case 0x00:	/* LCR */
+        return s->control;
+
+    case 0x04:	/* PMR */
+        return s->power;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_lpg_write(void *opaque, hwaddr addr,
+                           uint64_t value, unsigned size)
+{
+    struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
+    int offset = addr & OMAP_MPUI_REG_MASK;
+
+    if (size != 1) {
+        return omap_badwidth_write8(opaque, addr, value);
+    }
+
+    switch (offset) {
+    case 0x00:	/* LCR */
+        if (~value & (1 << 6))					/* LPGRES */
+            omap_lpg_reset(s);
+        s->control = value & 0xff;
+        omap_lpg_update(s);
+        return;
+
+    case 0x04:	/* PMR */
+        s->power = value & 0x01;
+        omap_lpg_update(s);
+        return;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_lpg_ops = {
+    .read = omap_lpg_read,
+    .write = omap_lpg_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_lpg_clk_update(void *opaque, int line, int on)
+{
+    struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
+
+    s->clk = on;
+    omap_lpg_update(s);
+}
+
+static struct omap_lpg_s *omap_lpg_init(MemoryRegion *system_memory,
+                                        hwaddr base, omap_clk clk)
+{
+    struct omap_lpg_s *s = (struct omap_lpg_s *)
+            g_malloc0(sizeof(struct omap_lpg_s));
+
+    s->tm = qemu_new_timer_ms(vm_clock, omap_lpg_tick, s);
+
+    omap_lpg_reset(s);
+
+    memory_region_init_io(&s->iomem, &omap_lpg_ops, s, "omap-lpg", 0x800);
+    memory_region_add_subregion(system_memory, base, &s->iomem);
+
+    omap_clk_adduser(clk, qemu_allocate_irqs(omap_lpg_clk_update, s, 1)[0]);
+
+    return s;
+}
+
+/* MPUI Peripheral Bridge configuration */
+static uint64_t omap_mpui_io_read(void *opaque, hwaddr addr,
+                                  unsigned size)
+{
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    if (addr == OMAP_MPUI_BASE)	/* CMR */
+        return 0xfe4d;
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_mpui_io_write(void *opaque, hwaddr addr,
+                               uint64_t value, unsigned size)
+{
+    /* FIXME: infinite loop */
+    omap_badwidth_write16(opaque, addr, value);
+}
+
+static const MemoryRegionOps omap_mpui_io_ops = {
+    .read = omap_mpui_io_read,
+    .write = omap_mpui_io_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_setup_mpui_io(MemoryRegion *system_memory,
+                               struct omap_mpu_state_s *mpu)
+{
+    memory_region_init_io(&mpu->mpui_io_iomem, &omap_mpui_io_ops, mpu,
+                          "omap-mpui-io", 0x7fff);
+    memory_region_add_subregion(system_memory, OMAP_MPUI_BASE,
+                                &mpu->mpui_io_iomem);
+}
+
+/* General chip reset */
+static void omap1_mpu_reset(void *opaque)
+{
+    struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
+
+    omap_dma_reset(mpu->dma);
+    omap_mpu_timer_reset(mpu->timer[0]);
+    omap_mpu_timer_reset(mpu->timer[1]);
+    omap_mpu_timer_reset(mpu->timer[2]);
+    omap_wd_timer_reset(mpu->wdt);
+    omap_os_timer_reset(mpu->os_timer);
+    omap_lcdc_reset(mpu->lcd);
+    omap_ulpd_pm_reset(mpu);
+    omap_pin_cfg_reset(mpu);
+    omap_mpui_reset(mpu);
+    omap_tipb_bridge_reset(mpu->private_tipb);
+    omap_tipb_bridge_reset(mpu->public_tipb);
+    omap_dpll_reset(mpu->dpll[0]);
+    omap_dpll_reset(mpu->dpll[1]);
+    omap_dpll_reset(mpu->dpll[2]);
+    omap_uart_reset(mpu->uart[0]);
+    omap_uart_reset(mpu->uart[1]);
+    omap_uart_reset(mpu->uart[2]);
+    omap_mmc_reset(mpu->mmc);
+    omap_mpuio_reset(mpu->mpuio);
+    omap_uwire_reset(mpu->microwire);
+    omap_pwl_reset(mpu->pwl);
+    omap_pwt_reset(mpu->pwt);
+    omap_rtc_reset(mpu->rtc);
+    omap_mcbsp_reset(mpu->mcbsp1);
+    omap_mcbsp_reset(mpu->mcbsp2);
+    omap_mcbsp_reset(mpu->mcbsp3);
+    omap_lpg_reset(mpu->led[0]);
+    omap_lpg_reset(mpu->led[1]);
+    omap_clkm_reset(mpu);
+    cpu_reset(CPU(mpu->cpu));
+}
+
+static const struct omap_map_s {
+    hwaddr phys_dsp;
+    hwaddr phys_mpu;
+    uint32_t size;
+    const char *name;
+} omap15xx_dsp_mm[] = {
+    /* Strobe 0 */
+    { 0xe1010000, 0xfffb0000, 0x800, "UART1 BT" },		/* CS0 */
+    { 0xe1010800, 0xfffb0800, 0x800, "UART2 COM" },		/* CS1 */
+    { 0xe1011800, 0xfffb1800, 0x800, "McBSP1 audio" },		/* CS3 */
+    { 0xe1012000, 0xfffb2000, 0x800, "MCSI2 communication" },	/* CS4 */
+    { 0xe1012800, 0xfffb2800, 0x800, "MCSI1 BT u-Law" },	/* CS5 */
+    { 0xe1013000, 0xfffb3000, 0x800, "uWire" },			/* CS6 */
+    { 0xe1013800, 0xfffb3800, 0x800, "I^2C" },			/* CS7 */
+    { 0xe1014000, 0xfffb4000, 0x800, "USB W2FC" },		/* CS8 */
+    { 0xe1014800, 0xfffb4800, 0x800, "RTC" },			/* CS9 */
+    { 0xe1015000, 0xfffb5000, 0x800, "MPUIO" },			/* CS10 */
+    { 0xe1015800, 0xfffb5800, 0x800, "PWL" },			/* CS11 */
+    { 0xe1016000, 0xfffb6000, 0x800, "PWT" },			/* CS12 */
+    { 0xe1017000, 0xfffb7000, 0x800, "McBSP3" },		/* CS14 */
+    { 0xe1017800, 0xfffb7800, 0x800, "MMC" },			/* CS15 */
+    { 0xe1019000, 0xfffb9000, 0x800, "32-kHz timer" },		/* CS18 */
+    { 0xe1019800, 0xfffb9800, 0x800, "UART3" },			/* CS19 */
+    { 0xe101c800, 0xfffbc800, 0x800, "TIPB switches" },		/* CS25 */
+    /* Strobe 1 */
+    { 0xe101e000, 0xfffce000, 0x800, "GPIOs" },			/* CS28 */
+
+    { 0 }
+};
+
+static void omap_setup_dsp_mapping(MemoryRegion *system_memory,
+                                   const struct omap_map_s *map)
+{
+    MemoryRegion *io;
+
+    for (; map->phys_dsp; map ++) {
+        io = g_new(MemoryRegion, 1);
+        memory_region_init_alias(io, map->name,
+                                 system_memory, map->phys_mpu, map->size);
+        memory_region_add_subregion(system_memory, map->phys_dsp, io);
+    }
+}
+
+void omap_mpu_wakeup(void *opaque, int irq, int req)
+{
+    struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
+
+    if (mpu->cpu->env.halted) {
+        cpu_interrupt(&mpu->cpu->env, CPU_INTERRUPT_EXITTB);
+    }
+}
+
+static const struct dma_irq_map omap1_dma_irq_map[] = {
+    { 0, OMAP_INT_DMA_CH0_6 },
+    { 0, OMAP_INT_DMA_CH1_7 },
+    { 0, OMAP_INT_DMA_CH2_8 },
+    { 0, OMAP_INT_DMA_CH3 },
+    { 0, OMAP_INT_DMA_CH4 },
+    { 0, OMAP_INT_DMA_CH5 },
+    { 1, OMAP_INT_1610_DMA_CH6 },
+    { 1, OMAP_INT_1610_DMA_CH7 },
+    { 1, OMAP_INT_1610_DMA_CH8 },
+    { 1, OMAP_INT_1610_DMA_CH9 },
+    { 1, OMAP_INT_1610_DMA_CH10 },
+    { 1, OMAP_INT_1610_DMA_CH11 },
+    { 1, OMAP_INT_1610_DMA_CH12 },
+    { 1, OMAP_INT_1610_DMA_CH13 },
+    { 1, OMAP_INT_1610_DMA_CH14 },
+    { 1, OMAP_INT_1610_DMA_CH15 }
+};
+
+/* DMA ports for OMAP1 */
+static int omap_validate_emiff_addr(struct omap_mpu_state_s *s,
+                hwaddr addr)
+{
+    return range_covers_byte(OMAP_EMIFF_BASE, s->sdram_size, addr);
+}
+
+static int omap_validate_emifs_addr(struct omap_mpu_state_s *s,
+                hwaddr addr)
+{
+    return range_covers_byte(OMAP_EMIFS_BASE, OMAP_EMIFF_BASE - OMAP_EMIFS_BASE,
+                             addr);
+}
+
+static int omap_validate_imif_addr(struct omap_mpu_state_s *s,
+                hwaddr addr)
+{
+    return range_covers_byte(OMAP_IMIF_BASE, s->sram_size, addr);
+}
+
+static int omap_validate_tipb_addr(struct omap_mpu_state_s *s,
+                hwaddr addr)
+{
+    return range_covers_byte(0xfffb0000, 0xffff0000 - 0xfffb0000, addr);
+}
+
+static int omap_validate_local_addr(struct omap_mpu_state_s *s,
+                hwaddr addr)
+{
+    return range_covers_byte(OMAP_LOCALBUS_BASE, 0x1000000, addr);
+}
+
+static int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s,
+                hwaddr addr)
+{
+    return range_covers_byte(0xe1010000, 0xe1020004 - 0xe1010000, addr);
+}
+
+struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
+                unsigned long sdram_size,
+                const char *core)
+{
+    int i;
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
+            g_malloc0(sizeof(struct omap_mpu_state_s));
+    qemu_irq *cpu_irq;
+    qemu_irq dma_irqs[6];
+    DriveInfo *dinfo;
+    SysBusDevice *busdev;
+
+    if (!core)
+        core = "ti925t";
+
+    /* Core */
+    s->mpu_model = omap310;
+    s->cpu = cpu_arm_init(core);
+    if (s->cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    s->sdram_size = sdram_size;
+    s->sram_size = OMAP15XX_SRAM_SIZE;
+
+    s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
+
+    /* Clocks */
+    omap_clk_init(s);
+
+    /* Memory-mapped stuff */
+    memory_region_init_ram(&s->emiff_ram, "omap1.dram", s->sdram_size);
+    vmstate_register_ram_global(&s->emiff_ram);
+    memory_region_add_subregion(system_memory, OMAP_EMIFF_BASE, &s->emiff_ram);
+    memory_region_init_ram(&s->imif_ram, "omap1.sram", s->sram_size);
+    vmstate_register_ram_global(&s->imif_ram);
+    memory_region_add_subregion(system_memory, OMAP_IMIF_BASE, &s->imif_ram);
+
+    omap_clkm_init(system_memory, 0xfffece00, 0xe1008000, s);
+
+    cpu_irq = arm_pic_init_cpu(s->cpu);
+    s->ih[0] = qdev_create(NULL, "omap-intc");
+    qdev_prop_set_uint32(s->ih[0], "size", 0x100);
+    qdev_prop_set_ptr(s->ih[0], "clk", omap_findclk(s, "arminth_ck"));
+    qdev_init_nofail(s->ih[0]);
+    busdev = SYS_BUS_DEVICE(s->ih[0]);
+    sysbus_connect_irq(busdev, 0, cpu_irq[ARM_PIC_CPU_IRQ]);
+    sysbus_connect_irq(busdev, 1, cpu_irq[ARM_PIC_CPU_FIQ]);
+    sysbus_mmio_map(busdev, 0, 0xfffecb00);
+    s->ih[1] = qdev_create(NULL, "omap-intc");
+    qdev_prop_set_uint32(s->ih[1], "size", 0x800);
+    qdev_prop_set_ptr(s->ih[1], "clk", omap_findclk(s, "arminth_ck"));
+    qdev_init_nofail(s->ih[1]);
+    busdev = SYS_BUS_DEVICE(s->ih[1]);
+    sysbus_connect_irq(busdev, 0,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_15XX_IH2_IRQ));
+    /* The second interrupt controller's FIQ output is not wired up */
+    sysbus_mmio_map(busdev, 0, 0xfffe0000);
+
+    for (i = 0; i < 6; i++) {
+        dma_irqs[i] = qdev_get_gpio_in(s->ih[omap1_dma_irq_map[i].ih],
+                                       omap1_dma_irq_map[i].intr);
+    }
+    s->dma = omap_dma_init(0xfffed800, dma_irqs, system_memory,
+                           qdev_get_gpio_in(s->ih[0], OMAP_INT_DMA_LCD),
+                           s, omap_findclk(s, "dma_ck"), omap_dma_3_1);
+
+    s->port[emiff    ].addr_valid = omap_validate_emiff_addr;
+    s->port[emifs    ].addr_valid = omap_validate_emifs_addr;
+    s->port[imif     ].addr_valid = omap_validate_imif_addr;
+    s->port[tipb     ].addr_valid = omap_validate_tipb_addr;
+    s->port[local    ].addr_valid = omap_validate_local_addr;
+    s->port[tipb_mpui].addr_valid = omap_validate_tipb_mpui_addr;
+
+    /* Register SDRAM and SRAM DMA ports for fast transfers.  */
+    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->emiff_ram),
+                         OMAP_EMIFF_BASE, s->sdram_size);
+    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->imif_ram),
+                         OMAP_IMIF_BASE, s->sram_size);
+
+    s->timer[0] = omap_mpu_timer_init(system_memory, 0xfffec500,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_TIMER1),
+                    omap_findclk(s, "mputim_ck"));
+    s->timer[1] = omap_mpu_timer_init(system_memory, 0xfffec600,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_TIMER2),
+                    omap_findclk(s, "mputim_ck"));
+    s->timer[2] = omap_mpu_timer_init(system_memory, 0xfffec700,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_TIMER3),
+                    omap_findclk(s, "mputim_ck"));
+
+    s->wdt = omap_wd_timer_init(system_memory, 0xfffec800,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_WD_TIMER),
+                    omap_findclk(s, "armwdt_ck"));
+
+    s->os_timer = omap_os_timer_init(system_memory, 0xfffb9000,
+                    qdev_get_gpio_in(s->ih[1], OMAP_INT_OS_TIMER),
+                    omap_findclk(s, "clk32-kHz"));
+
+    s->lcd = omap_lcdc_init(system_memory, 0xfffec000,
+                            qdev_get_gpio_in(s->ih[0], OMAP_INT_LCD_CTRL),
+                            omap_dma_get_lcdch(s->dma),
+                            omap_findclk(s, "lcd_ck"));
+
+    omap_ulpd_pm_init(system_memory, 0xfffe0800, s);
+    omap_pin_cfg_init(system_memory, 0xfffe1000, s);
+    omap_id_init(system_memory, s);
+
+    omap_mpui_init(system_memory, 0xfffec900, s);
+
+    s->private_tipb = omap_tipb_bridge_init(system_memory, 0xfffeca00,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_BRIDGE_PRIV),
+                    omap_findclk(s, "tipb_ck"));
+    s->public_tipb = omap_tipb_bridge_init(system_memory, 0xfffed300,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_BRIDGE_PUB),
+                    omap_findclk(s, "tipb_ck"));
+
+    omap_tcmi_init(system_memory, 0xfffecc00, s);
+
+    s->uart[0] = omap_uart_init(0xfffb0000,
+                                qdev_get_gpio_in(s->ih[1], OMAP_INT_UART1),
+                    omap_findclk(s, "uart1_ck"),
+                    omap_findclk(s, "uart1_ck"),
+                    s->drq[OMAP_DMA_UART1_TX], s->drq[OMAP_DMA_UART1_RX],
+                    "uart1",
+                    serial_hds[0]);
+    s->uart[1] = omap_uart_init(0xfffb0800,
+                                qdev_get_gpio_in(s->ih[1], OMAP_INT_UART2),
+                    omap_findclk(s, "uart2_ck"),
+                    omap_findclk(s, "uart2_ck"),
+                    s->drq[OMAP_DMA_UART2_TX], s->drq[OMAP_DMA_UART2_RX],
+                    "uart2",
+                    serial_hds[0] ? serial_hds[1] : NULL);
+    s->uart[2] = omap_uart_init(0xfffb9800,
+                                qdev_get_gpio_in(s->ih[0], OMAP_INT_UART3),
+                    omap_findclk(s, "uart3_ck"),
+                    omap_findclk(s, "uart3_ck"),
+                    s->drq[OMAP_DMA_UART3_TX], s->drq[OMAP_DMA_UART3_RX],
+                    "uart3",
+                    serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
+
+    s->dpll[0] = omap_dpll_init(system_memory, 0xfffecf00,
+                                omap_findclk(s, "dpll1"));
+    s->dpll[1] = omap_dpll_init(system_memory, 0xfffed000,
+                                omap_findclk(s, "dpll2"));
+    s->dpll[2] = omap_dpll_init(system_memory, 0xfffed100,
+                                omap_findclk(s, "dpll3"));
+
+    dinfo = drive_get(IF_SD, 0, 0);
+    if (!dinfo) {
+        fprintf(stderr, "qemu: missing SecureDigital device\n");
+        exit(1);
+    }
+    s->mmc = omap_mmc_init(0xfffb7800, system_memory, dinfo->bdrv,
+                           qdev_get_gpio_in(s->ih[1], OMAP_INT_OQN),
+                           &s->drq[OMAP_DMA_MMC_TX],
+                    omap_findclk(s, "mmc_ck"));
+
+    s->mpuio = omap_mpuio_init(system_memory, 0xfffb5000,
+                               qdev_get_gpio_in(s->ih[1], OMAP_INT_KEYBOARD),
+                               qdev_get_gpio_in(s->ih[1], OMAP_INT_MPUIO),
+                               s->wakeup, omap_findclk(s, "clk32-kHz"));
+
+    s->gpio = qdev_create(NULL, "omap-gpio");
+    qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
+    qdev_prop_set_ptr(s->gpio, "clk", omap_findclk(s, "arm_gpio_ck"));
+    qdev_init_nofail(s->gpio);
+    sysbus_connect_irq(SYS_BUS_DEVICE(s->gpio), 0,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_GPIO_BANK1));
+    sysbus_mmio_map(SYS_BUS_DEVICE(s->gpio), 0, 0xfffce000);
+
+    s->microwire = omap_uwire_init(system_memory, 0xfffb3000,
+                                   qdev_get_gpio_in(s->ih[1], OMAP_INT_uWireTX),
+                                   qdev_get_gpio_in(s->ih[1], OMAP_INT_uWireRX),
+                    s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
+
+    s->pwl = omap_pwl_init(system_memory, 0xfffb5800,
+                           omap_findclk(s, "armxor_ck"));
+    s->pwt = omap_pwt_init(system_memory, 0xfffb6000,
+                           omap_findclk(s, "armxor_ck"));
+
+    s->i2c[0] = qdev_create(NULL, "omap_i2c");
+    qdev_prop_set_uint8(s->i2c[0], "revision", 0x11);
+    qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "mpuper_ck"));
+    qdev_init_nofail(s->i2c[0]);
+    busdev = SYS_BUS_DEVICE(s->i2c[0]);
+    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C));
+    sysbus_connect_irq(busdev, 1, s->drq[OMAP_DMA_I2C_TX]);
+    sysbus_connect_irq(busdev, 2, s->drq[OMAP_DMA_I2C_RX]);
+    sysbus_mmio_map(busdev, 0, 0xfffb3800);
+
+    s->rtc = omap_rtc_init(system_memory, 0xfffb4800,
+                           qdev_get_gpio_in(s->ih[1], OMAP_INT_RTC_TIMER),
+                           qdev_get_gpio_in(s->ih[1], OMAP_INT_RTC_ALARM),
+                    omap_findclk(s, "clk32-kHz"));
+
+    s->mcbsp1 = omap_mcbsp_init(system_memory, 0xfffb1800,
+                                qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP1TX),
+                                qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP1RX),
+                    &s->drq[OMAP_DMA_MCBSP1_TX], omap_findclk(s, "dspxor_ck"));
+    s->mcbsp2 = omap_mcbsp_init(system_memory, 0xfffb1000,
+                                qdev_get_gpio_in(s->ih[0],
+                                                 OMAP_INT_310_McBSP2_TX),
+                                qdev_get_gpio_in(s->ih[0],
+                                                 OMAP_INT_310_McBSP2_RX),
+                    &s->drq[OMAP_DMA_MCBSP2_TX], omap_findclk(s, "mpuper_ck"));
+    s->mcbsp3 = omap_mcbsp_init(system_memory, 0xfffb7000,
+                                qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP3TX),
+                                qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP3RX),
+                    &s->drq[OMAP_DMA_MCBSP3_TX], omap_findclk(s, "dspxor_ck"));
+
+    s->led[0] = omap_lpg_init(system_memory,
+                              0xfffbd000, omap_findclk(s, "clk32-kHz"));
+    s->led[1] = omap_lpg_init(system_memory,
+                              0xfffbd800, omap_findclk(s, "clk32-kHz"));
+
+    /* Register mappings not currenlty implemented:
+     * MCSI2 Comm	fffb2000 - fffb27ff (not mapped on OMAP310)
+     * MCSI1 Bluetooth	fffb2800 - fffb2fff (not mapped on OMAP310)
+     * USB W2FC		fffb4000 - fffb47ff
+     * Camera Interface	fffb6800 - fffb6fff
+     * USB Host		fffba000 - fffba7ff
+     * FAC		fffba800 - fffbafff
+     * HDQ/1-Wire	fffbc000 - fffbc7ff
+     * TIPB switches	fffbc800 - fffbcfff
+     * Mailbox		fffcf000 - fffcf7ff
+     * Local bus IF	fffec100 - fffec1ff
+     * Local bus MMU	fffec200 - fffec2ff
+     * DSP MMU		fffed200 - fffed2ff
+     */
+
+    omap_setup_dsp_mapping(system_memory, omap15xx_dsp_mm);
+    omap_setup_mpui_io(system_memory, s);
+
+    qemu_register_reset(omap1_mpu_reset, s);
+
+    return s;
+}
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
new file mode 100644
index 0000000..0a2cd7b
--- /dev/null
+++ b/hw/arm/omap2.c
@@ -0,0 +1,2684 @@
+/*
+ * TI OMAP processors emulation.
+ *
+ * Copyright (C) 2007-2008 Nokia Corporation
+ * Written by Andrzej Zaborowski <andrew at openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 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 "sysemu/blockdev.h"
+#include "hw/hw.h"
+#include "hw/arm-misc.h"
+#include "hw/omap.h"
+#include "sysemu/sysemu.h"
+#include "qemu/timer.h"
+#include "char/char.h"
+#include "hw/flash.h"
+#include "hw/soc_dma.h"
+#include "hw/sysbus.h"
+#include "audio/audio.h"
+
+/* Enhanced Audio Controller (CODEC only) */
+struct omap_eac_s {
+    qemu_irq irq;
+    MemoryRegion iomem;
+
+    uint16_t sysconfig;
+    uint8_t config[4];
+    uint8_t control;
+    uint8_t address;
+    uint16_t data;
+    uint8_t vtol;
+    uint8_t vtsl;
+    uint16_t mixer;
+    uint16_t gain[4];
+    uint8_t att;
+    uint16_t max[7];
+
+    struct {
+        qemu_irq txdrq;
+        qemu_irq rxdrq;
+        uint32_t (*txrx)(void *opaque, uint32_t, int);
+        void *opaque;
+
+#define EAC_BUF_LEN 1024
+        uint32_t rxbuf[EAC_BUF_LEN];
+        int rxoff;
+        int rxlen;
+        int rxavail;
+        uint32_t txbuf[EAC_BUF_LEN];
+        int txlen;
+        int txavail;
+
+        int enable;
+        int rate;
+
+        uint16_t config[4];
+
+        /* These need to be moved to the actual codec */
+        QEMUSoundCard card;
+        SWVoiceIn *in_voice;
+        SWVoiceOut *out_voice;
+        int hw_enable;
+    } codec;
+
+    struct {
+        uint8_t control;
+        uint16_t config;
+    } modem, bt;
+};
+
+static inline void omap_eac_interrupt_update(struct omap_eac_s *s)
+{
+    qemu_set_irq(s->irq, (s->codec.config[1] >> 14) & 1);	/* AURDI */
+}
+
+static inline void omap_eac_in_dmarequest_update(struct omap_eac_s *s)
+{
+    qemu_set_irq(s->codec.rxdrq, (s->codec.rxavail || s->codec.rxlen) &&
+                    ((s->codec.config[1] >> 12) & 1));		/* DMAREN */
+}
+
+static inline void omap_eac_out_dmarequest_update(struct omap_eac_s *s)
+{
+    qemu_set_irq(s->codec.txdrq, s->codec.txlen < s->codec.txavail &&
+                    ((s->codec.config[1] >> 11) & 1));		/* DMAWEN */
+}
+
+static inline void omap_eac_in_refill(struct omap_eac_s *s)
+{
+    int left = MIN(EAC_BUF_LEN - s->codec.rxlen, s->codec.rxavail) << 2;
+    int start = ((s->codec.rxoff + s->codec.rxlen) & (EAC_BUF_LEN - 1)) << 2;
+    int leftwrap = MIN(left, (EAC_BUF_LEN << 2) - start);
+    int recv = 1;
+    uint8_t *buf = (uint8_t *) s->codec.rxbuf + start;
+
+    left -= leftwrap;
+    start = 0;
+    while (leftwrap && (recv = AUD_read(s->codec.in_voice, buf + start,
+                                    leftwrap)) > 0) {	/* Be defensive */
+        start += recv;
+        leftwrap -= recv;
+    }
+    if (recv <= 0)
+        s->codec.rxavail = 0;
+    else
+        s->codec.rxavail -= start >> 2;
+    s->codec.rxlen += start >> 2;
+
+    if (recv > 0 && left > 0) {
+        start = 0;
+        while (left && (recv = AUD_read(s->codec.in_voice,
+                                        (uint8_t *) s->codec.rxbuf + start,
+                                        left)) > 0) {	/* Be defensive */
+            start += recv;
+            left -= recv;
+        }
+        if (recv <= 0)
+            s->codec.rxavail = 0;
+        else
+            s->codec.rxavail -= start >> 2;
+        s->codec.rxlen += start >> 2;
+    }
+}
+
+static inline void omap_eac_out_empty(struct omap_eac_s *s)
+{
+    int left = s->codec.txlen << 2;
+    int start = 0;
+    int sent = 1;
+
+    while (left && (sent = AUD_write(s->codec.out_voice,
+                                    (uint8_t *) s->codec.txbuf + start,
+                                    left)) > 0) {	/* Be defensive */
+        start += sent;
+        left -= sent;
+    }
+
+    if (!sent) {
+        s->codec.txavail = 0;
+        omap_eac_out_dmarequest_update(s);
+    }
+
+    if (start)
+        s->codec.txlen = 0;
+}
+
+static void omap_eac_in_cb(void *opaque, int avail_b)
+{
+    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
+
+    s->codec.rxavail = avail_b >> 2;
+    omap_eac_in_refill(s);
+    /* TODO: possibly discard current buffer if overrun */
+    omap_eac_in_dmarequest_update(s);
+}
+
+static void omap_eac_out_cb(void *opaque, int free_b)
+{
+    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
+
+    s->codec.txavail = free_b >> 2;
+    if (s->codec.txlen)
+        omap_eac_out_empty(s);
+    else
+        omap_eac_out_dmarequest_update(s);
+}
+
+static void omap_eac_enable_update(struct omap_eac_s *s)
+{
+    s->codec.enable = !(s->codec.config[1] & 1) &&		/* EACPWD */
+            (s->codec.config[1] & 2) &&				/* AUDEN */
+            s->codec.hw_enable;
+}
+
+static const int omap_eac_fsint[4] = {
+    8000,
+    11025,
+    22050,
+    44100,
+};
+
+static const int omap_eac_fsint2[8] = {
+    8000,
+    11025,
+    22050,
+    44100,
+    48000,
+    0, 0, 0,
+};
+
+static const int omap_eac_fsint3[16] = {
+    8000,
+    11025,
+    16000,
+    22050,
+    24000,
+    32000,
+    44100,
+    48000,
+    0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static void omap_eac_rate_update(struct omap_eac_s *s)
+{
+    int fsint[3];
+
+    fsint[2] = (s->codec.config[3] >> 9) & 0xf;
+    fsint[1] = (s->codec.config[2] >> 0) & 0x7;
+    fsint[0] = (s->codec.config[0] >> 6) & 0x3;
+    if (fsint[2] < 0xf)
+        s->codec.rate = omap_eac_fsint3[fsint[2]];
+    else if (fsint[1] < 0x7)
+        s->codec.rate = omap_eac_fsint2[fsint[1]];
+    else
+        s->codec.rate = omap_eac_fsint[fsint[0]];
+}
+
+static void omap_eac_volume_update(struct omap_eac_s *s)
+{
+    /* TODO */
+}
+
+static void omap_eac_format_update(struct omap_eac_s *s)
+{
+    struct audsettings fmt;
+
+    /* The hardware buffers at most one sample */
+    if (s->codec.rxlen)
+        s->codec.rxlen = 1;
+
+    if (s->codec.in_voice) {
+        AUD_set_active_in(s->codec.in_voice, 0);
+        AUD_close_in(&s->codec.card, s->codec.in_voice);
+        s->codec.in_voice = NULL;
+    }
+    if (s->codec.out_voice) {
+        omap_eac_out_empty(s);
+        AUD_set_active_out(s->codec.out_voice, 0);
+        AUD_close_out(&s->codec.card, s->codec.out_voice);
+        s->codec.out_voice = NULL;
+        s->codec.txavail = 0;
+    }
+    /* Discard what couldn't be written */
+    s->codec.txlen = 0;
+
+    omap_eac_enable_update(s);
+    if (!s->codec.enable)
+        return;
+
+    omap_eac_rate_update(s);
+    fmt.endianness = ((s->codec.config[0] >> 8) & 1);		/* LI_BI */
+    fmt.nchannels = ((s->codec.config[0] >> 10) & 1) ? 2 : 1;	/* MN_ST */
+    fmt.freq = s->codec.rate;
+    /* TODO: signedness possibly depends on the CODEC hardware - or
+     * does I2S specify it?  */
+    /* All register writes are 16 bits so we we store 16-bit samples
+     * in the buffers regardless of AGCFR[B8_16] value.  */
+    fmt.fmt = AUD_FMT_U16;
+
+    s->codec.in_voice = AUD_open_in(&s->codec.card, s->codec.in_voice,
+                    "eac.codec.in", s, omap_eac_in_cb, &fmt);
+    s->codec.out_voice = AUD_open_out(&s->codec.card, s->codec.out_voice,
+                    "eac.codec.out", s, omap_eac_out_cb, &fmt);
+
+    omap_eac_volume_update(s);
+
+    AUD_set_active_in(s->codec.in_voice, 1);
+    AUD_set_active_out(s->codec.out_voice, 1);
+}
+
+static void omap_eac_reset(struct omap_eac_s *s)
+{
+    s->sysconfig = 0;
+    s->config[0] = 0x0c;
+    s->config[1] = 0x09;
+    s->config[2] = 0xab;
+    s->config[3] = 0x03;
+    s->control = 0x00;
+    s->address = 0x00;
+    s->data = 0x0000;
+    s->vtol = 0x00;
+    s->vtsl = 0x00;
+    s->mixer = 0x0000;
+    s->gain[0] = 0xe7e7;
+    s->gain[1] = 0x6767;
+    s->gain[2] = 0x6767;
+    s->gain[3] = 0x6767;
+    s->att = 0xce;
+    s->max[0] = 0;
+    s->max[1] = 0;
+    s->max[2] = 0;
+    s->max[3] = 0;
+    s->max[4] = 0;
+    s->max[5] = 0;
+    s->max[6] = 0;
+
+    s->modem.control = 0x00;
+    s->modem.config = 0x0000;
+    s->bt.control = 0x00;
+    s->bt.config = 0x0000;
+    s->codec.config[0] = 0x0649;
+    s->codec.config[1] = 0x0000;
+    s->codec.config[2] = 0x0007;
+    s->codec.config[3] = 0x1ffc;
+    s->codec.rxoff = 0;
+    s->codec.rxlen = 0;
+    s->codec.txlen = 0;
+    s->codec.rxavail = 0;
+    s->codec.txavail = 0;
+
+    omap_eac_format_update(s);
+    omap_eac_interrupt_update(s);
+}
+
+static uint64_t omap_eac_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
+    uint32_t ret;
+
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x000:	/* CPCFR1 */
+        return s->config[0];
+    case 0x004:	/* CPCFR2 */
+        return s->config[1];
+    case 0x008:	/* CPCFR3 */
+        return s->config[2];
+    case 0x00c:	/* CPCFR4 */
+        return s->config[3];
+
+    case 0x010:	/* CPTCTL */
+        return s->control | ((s->codec.rxavail + s->codec.rxlen > 0) << 7) |
+                ((s->codec.txlen < s->codec.txavail) << 5);
+
+    case 0x014:	/* CPTTADR */
+        return s->address;
+    case 0x018:	/* CPTDATL */
+        return s->data & 0xff;
+    case 0x01c:	/* CPTDATH */
+        return s->data >> 8;
+    case 0x020:	/* CPTVSLL */
+        return s->vtol;
+    case 0x024:	/* CPTVSLH */
+        return s->vtsl | (3 << 5);	/* CRDY1 | CRDY2 */
+    case 0x040:	/* MPCTR */
+        return s->modem.control;
+    case 0x044:	/* MPMCCFR */
+        return s->modem.config;
+    case 0x060:	/* BPCTR */
+        return s->bt.control;
+    case 0x064:	/* BPMCCFR */
+        return s->bt.config;
+    case 0x080:	/* AMSCFR */
+        return s->mixer;
+    case 0x084:	/* AMVCTR */
+        return s->gain[0];
+    case 0x088:	/* AM1VCTR */
+        return s->gain[1];
+    case 0x08c:	/* AM2VCTR */
+        return s->gain[2];
+    case 0x090:	/* AM3VCTR */
+        return s->gain[3];
+    case 0x094:	/* ASTCTR */
+        return s->att;
+    case 0x098:	/* APD1LCR */
+        return s->max[0];
+    case 0x09c:	/* APD1RCR */
+        return s->max[1];
+    case 0x0a0:	/* APD2LCR */
+        return s->max[2];
+    case 0x0a4:	/* APD2RCR */
+        return s->max[3];
+    case 0x0a8:	/* APD3LCR */
+        return s->max[4];
+    case 0x0ac:	/* APD3RCR */
+        return s->max[5];
+    case 0x0b0:	/* APD4R */
+        return s->max[6];
+    case 0x0b4:	/* ADWR */
+        /* This should be write-only?  Docs list it as read-only.  */
+        return 0x0000;
+    case 0x0b8:	/* ADRDR */
+        if (likely(s->codec.rxlen > 1)) {
+            ret = s->codec.rxbuf[s->codec.rxoff ++];
+            s->codec.rxlen --;
+            s->codec.rxoff &= EAC_BUF_LEN - 1;
+            return ret;
+        } else if (s->codec.rxlen) {
+            ret = s->codec.rxbuf[s->codec.rxoff ++];
+            s->codec.rxlen --;
+            s->codec.rxoff &= EAC_BUF_LEN - 1;
+            if (s->codec.rxavail)
+                omap_eac_in_refill(s);
+            omap_eac_in_dmarequest_update(s);
+            return ret;
+        }
+        return 0x0000;
+    case 0x0bc:	/* AGCFR */
+        return s->codec.config[0];
+    case 0x0c0:	/* AGCTR */
+        return s->codec.config[1] | ((s->codec.config[1] & 2) << 14);
+    case 0x0c4:	/* AGCFR2 */
+        return s->codec.config[2];
+    case 0x0c8:	/* AGCFR3 */
+        return s->codec.config[3];
+    case 0x0cc:	/* MBPDMACTR */
+    case 0x0d0:	/* MPDDMARR */
+    case 0x0d8:	/* MPUDMARR */
+    case 0x0e4:	/* BPDDMARR */
+    case 0x0ec:	/* BPUDMARR */
+        return 0x0000;
+
+    case 0x100:	/* VERSION_NUMBER */
+        return 0x0010;
+
+    case 0x104:	/* SYSCONFIG */
+        return s->sysconfig;
+
+    case 0x108:	/* SYSSTATUS */
+        return 1 | 0xe;					/* RESETDONE | stuff */
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_eac_write(void *opaque, hwaddr addr,
+                           uint64_t value, unsigned size)
+{
+    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
+
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x098:	/* APD1LCR */
+    case 0x09c:	/* APD1RCR */
+    case 0x0a0:	/* APD2LCR */
+    case 0x0a4:	/* APD2RCR */
+    case 0x0a8:	/* APD3LCR */
+    case 0x0ac:	/* APD3RCR */
+    case 0x0b0:	/* APD4R */
+    case 0x0b8:	/* ADRDR */
+    case 0x0d0:	/* MPDDMARR */
+    case 0x0d8:	/* MPUDMARR */
+    case 0x0e4:	/* BPDDMARR */
+    case 0x0ec:	/* BPUDMARR */
+    case 0x100:	/* VERSION_NUMBER */
+    case 0x108:	/* SYSSTATUS */
+        OMAP_RO_REG(addr);
+        return;
+
+    case 0x000:	/* CPCFR1 */
+        s->config[0] = value & 0xff;
+        omap_eac_format_update(s);
+        break;
+    case 0x004:	/* CPCFR2 */
+        s->config[1] = value & 0xff;
+        omap_eac_format_update(s);
+        break;
+    case 0x008:	/* CPCFR3 */
+        s->config[2] = value & 0xff;
+        omap_eac_format_update(s);
+        break;
+    case 0x00c:	/* CPCFR4 */
+        s->config[3] = value & 0xff;
+        omap_eac_format_update(s);
+        break;
+
+    case 0x010:	/* CPTCTL */
+        /* Assuming TXF and TXE bits are read-only... */
+        s->control = value & 0x5f;
+        omap_eac_interrupt_update(s);
+        break;
+
+    case 0x014:	/* CPTTADR */
+        s->address = value & 0xff;
+        break;
+    case 0x018:	/* CPTDATL */
+        s->data &= 0xff00;
+        s->data |= value & 0xff;
+        break;
+    case 0x01c:	/* CPTDATH */
+        s->data &= 0x00ff;
+        s->data |= value << 8;
+        break;
+    case 0x020:	/* CPTVSLL */
+        s->vtol = value & 0xf8;
+        break;
+    case 0x024:	/* CPTVSLH */
+        s->vtsl = value & 0x9f;
+        break;
+    case 0x040:	/* MPCTR */
+        s->modem.control = value & 0x8f;
+        break;
+    case 0x044:	/* MPMCCFR */
+        s->modem.config = value & 0x7fff;
+        break;
+    case 0x060:	/* BPCTR */
+        s->bt.control = value & 0x8f;
+        break;
+    case 0x064:	/* BPMCCFR */
+        s->bt.config = value & 0x7fff;
+        break;
+    case 0x080:	/* AMSCFR */
+        s->mixer = value & 0x0fff;
+        break;
+    case 0x084:	/* AMVCTR */
+        s->gain[0] = value & 0xffff;
+        break;
+    case 0x088:	/* AM1VCTR */
+        s->gain[1] = value & 0xff7f;
+        break;
+    case 0x08c:	/* AM2VCTR */
+        s->gain[2] = value & 0xff7f;
+        break;
+    case 0x090:	/* AM3VCTR */
+        s->gain[3] = value & 0xff7f;
+        break;
+    case 0x094:	/* ASTCTR */
+        s->att = value & 0xff;
+        break;
+
+    case 0x0b4:	/* ADWR */
+        s->codec.txbuf[s->codec.txlen ++] = value;
+        if (unlikely(s->codec.txlen == EAC_BUF_LEN ||
+                                s->codec.txlen == s->codec.txavail)) {
+            if (s->codec.txavail)
+                omap_eac_out_empty(s);
+            /* Discard what couldn't be written */
+            s->codec.txlen = 0;
+        }
+        break;
+
+    case 0x0bc:	/* AGCFR */
+        s->codec.config[0] = value & 0x07ff;
+        omap_eac_format_update(s);
+        break;
+    case 0x0c0:	/* AGCTR */
+        s->codec.config[1] = value & 0x780f;
+        omap_eac_format_update(s);
+        break;
+    case 0x0c4:	/* AGCFR2 */
+        s->codec.config[2] = value & 0x003f;
+        omap_eac_format_update(s);
+        break;
+    case 0x0c8:	/* AGCFR3 */
+        s->codec.config[3] = value & 0xffff;
+        omap_eac_format_update(s);
+        break;
+    case 0x0cc:	/* MBPDMACTR */
+    case 0x0d4:	/* MPDDMAWR */
+    case 0x0e0:	/* MPUDMAWR */
+    case 0x0e8:	/* BPDDMAWR */
+    case 0x0f0:	/* BPUDMAWR */
+        break;
+
+    case 0x104:	/* SYSCONFIG */
+        if (value & (1 << 1))				/* SOFTRESET */
+            omap_eac_reset(s);
+        s->sysconfig = value & 0x31d;
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_eac_ops = {
+    .read = omap_eac_read,
+    .write = omap_eac_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
+                qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
+{
+    struct omap_eac_s *s = (struct omap_eac_s *)
+            g_malloc0(sizeof(struct omap_eac_s));
+
+    s->irq = irq;
+    s->codec.rxdrq = *drq ++;
+    s->codec.txdrq = *drq;
+    omap_eac_reset(s);
+
+    AUD_register_card("OMAP EAC", &s->codec.card);
+
+    memory_region_init_io(&s->iomem, &omap_eac_ops, s, "omap.eac",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &s->iomem);
+
+    return s;
+}
+
+/* STI/XTI (emulation interface) console - reverse engineered only */
+struct omap_sti_s {
+    qemu_irq irq;
+    MemoryRegion iomem;
+    MemoryRegion iomem_fifo;
+    CharDriverState *chr;
+
+    uint32_t sysconfig;
+    uint32_t systest;
+    uint32_t irqst;
+    uint32_t irqen;
+    uint32_t clkcontrol;
+    uint32_t serial_config;
+};
+
+#define STI_TRACE_CONSOLE_CHANNEL	239
+#define STI_TRACE_CONTROL_CHANNEL	253
+
+static inline void omap_sti_interrupt_update(struct omap_sti_s *s)
+{
+    qemu_set_irq(s->irq, s->irqst & s->irqen);
+}
+
+static void omap_sti_reset(struct omap_sti_s *s)
+{
+    s->sysconfig = 0;
+    s->irqst = 0;
+    s->irqen = 0;
+    s->clkcontrol = 0;
+    s->serial_config = 0;
+
+    omap_sti_interrupt_update(s);
+}
+
+static uint64_t omap_sti_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    struct omap_sti_s *s = (struct omap_sti_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x00:	/* STI_REVISION */
+        return 0x10;
+
+    case 0x10:	/* STI_SYSCONFIG */
+        return s->sysconfig;
+
+    case 0x14:	/* STI_SYSSTATUS / STI_RX_STATUS / XTI_SYSSTATUS */
+        return 0x00;
+
+    case 0x18:	/* STI_IRQSTATUS */
+        return s->irqst;
+
+    case 0x1c:	/* STI_IRQSETEN / STI_IRQCLREN */
+        return s->irqen;
+
+    case 0x24:	/* STI_ER / STI_DR / XTI_TRACESELECT */
+    case 0x28:	/* STI_RX_DR / XTI_RXDATA */
+        /* TODO */
+        return 0;
+
+    case 0x2c:	/* STI_CLK_CTRL / XTI_SCLKCRTL */
+        return s->clkcontrol;
+
+    case 0x30:	/* STI_SERIAL_CFG / XTI_SCONFIG */
+        return s->serial_config;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_sti_write(void *opaque, hwaddr addr,
+                           uint64_t value, unsigned size)
+{
+    struct omap_sti_s *s = (struct omap_sti_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x00:	/* STI_REVISION */
+    case 0x14:	/* STI_SYSSTATUS / STI_RX_STATUS / XTI_SYSSTATUS */
+        OMAP_RO_REG(addr);
+        return;
+
+    case 0x10:	/* STI_SYSCONFIG */
+        if (value & (1 << 1))				/* SOFTRESET */
+            omap_sti_reset(s);
+        s->sysconfig = value & 0xfe;
+        break;
+
+    case 0x18:	/* STI_IRQSTATUS */
+        s->irqst &= ~value;
+        omap_sti_interrupt_update(s);
+        break;
+
+    case 0x1c:	/* STI_IRQSETEN / STI_IRQCLREN */
+        s->irqen = value & 0xffff;
+        omap_sti_interrupt_update(s);
+        break;
+
+    case 0x2c:	/* STI_CLK_CTRL / XTI_SCLKCRTL */
+        s->clkcontrol = value & 0xff;
+        break;
+
+    case 0x30:	/* STI_SERIAL_CFG / XTI_SCONFIG */
+        s->serial_config = value & 0xff;
+        break;
+
+    case 0x24:	/* STI_ER / STI_DR / XTI_TRACESELECT */
+    case 0x28:	/* STI_RX_DR / XTI_RXDATA */
+        /* TODO */
+        return;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_sti_ops = {
+    .read = omap_sti_read,
+    .write = omap_sti_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static uint64_t omap_sti_fifo_read(void *opaque, hwaddr addr,
+                                   unsigned size)
+{
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_sti_fifo_write(void *opaque, hwaddr addr,
+                                uint64_t value, unsigned size)
+{
+    struct omap_sti_s *s = (struct omap_sti_s *) opaque;
+    int ch = addr >> 6;
+    uint8_t byte = value;
+
+    if (size != 1) {
+        return omap_badwidth_write8(opaque, addr, size);
+    }
+
+    if (ch == STI_TRACE_CONTROL_CHANNEL) {
+        /* Flush channel <i>value</i>.  */
+        qemu_chr_fe_write(s->chr, (const uint8_t *) "\r", 1);
+    } else if (ch == STI_TRACE_CONSOLE_CHANNEL || 1) {
+        if (value == 0xc0 || value == 0xc3) {
+            /* Open channel <i>ch</i>.  */
+        } else if (value == 0x00)
+            qemu_chr_fe_write(s->chr, (const uint8_t *) "\n", 1);
+        else
+            qemu_chr_fe_write(s->chr, &byte, 1);
+    }
+}
+
+static const MemoryRegionOps omap_sti_fifo_ops = {
+    .read = omap_sti_fifo_read,
+    .write = omap_sti_fifo_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
+                MemoryRegion *sysmem,
+                hwaddr channel_base, qemu_irq irq, omap_clk clk,
+                CharDriverState *chr)
+{
+    struct omap_sti_s *s = (struct omap_sti_s *)
+            g_malloc0(sizeof(struct omap_sti_s));
+
+    s->irq = irq;
+    omap_sti_reset(s);
+
+    s->chr = chr ?: qemu_chr_new("null", "null", NULL);
+
+    memory_region_init_io(&s->iomem, &omap_sti_ops, s, "omap.sti",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &s->iomem);
+
+    memory_region_init_io(&s->iomem_fifo, &omap_sti_fifo_ops, s,
+                          "omap.sti.fifo", 0x10000);
+    memory_region_add_subregion(sysmem, channel_base, &s->iomem_fifo);
+
+    return s;
+}
+
+/* L4 Interconnect */
+#define L4TA(n)		(n)
+#define L4TAO(n)	((n) + 39)
+
+static const struct omap_l4_region_s omap_l4_region[125] = {
+    [  1] = { 0x40800,  0x800, 32          }, /* Initiator agent */
+    [  2] = { 0x41000, 0x1000, 32          }, /* Link agent */
+    [  0] = { 0x40000,  0x800, 32          }, /* Address and protection */
+    [  3] = { 0x00000, 0x1000, 32 | 16 | 8 }, /* System Control and Pinout */
+    [  4] = { 0x01000, 0x1000, 32 | 16 | 8 }, /* L4TAO1 */
+    [  5] = { 0x04000, 0x1000, 32 | 16     }, /* 32K Timer */
+    [  6] = { 0x05000, 0x1000, 32 | 16 | 8 }, /* L4TAO2 */
+    [  7] = { 0x08000,  0x800, 32          }, /* PRCM Region A */
+    [  8] = { 0x08800,  0x800, 32          }, /* PRCM Region B */
+    [  9] = { 0x09000, 0x1000, 32 | 16 | 8 }, /* L4TAO */
+    [ 10] = { 0x12000, 0x1000, 32 | 16 | 8 }, /* Test (BCM) */
+    [ 11] = { 0x13000, 0x1000, 32 | 16 | 8 }, /* L4TA1 */
+    [ 12] = { 0x14000, 0x1000, 32          }, /* Test/emulation (TAP) */
+    [ 13] = { 0x15000, 0x1000, 32 | 16 | 8 }, /* L4TA2 */
+    [ 14] = { 0x18000, 0x1000, 32 | 16 | 8 }, /* GPIO1 */
+    [ 16] = { 0x1a000, 0x1000, 32 | 16 | 8 }, /* GPIO2 */
+    [ 18] = { 0x1c000, 0x1000, 32 | 16 | 8 }, /* GPIO3 */
+    [ 19] = { 0x1e000, 0x1000, 32 | 16 | 8 }, /* GPIO4 */
+    [ 15] = { 0x19000, 0x1000, 32 | 16 | 8 }, /* Quad GPIO TOP */
+    [ 17] = { 0x1b000, 0x1000, 32 | 16 | 8 }, /* L4TA3 */
+    [ 20] = { 0x20000, 0x1000, 32 | 16 | 8 }, /* WD Timer 1 (Secure) */
+    [ 22] = { 0x22000, 0x1000, 32 | 16 | 8 }, /* WD Timer 2 (OMAP) */
+    [ 21] = { 0x21000, 0x1000, 32 | 16 | 8 }, /* Dual WD timer TOP */
+    [ 23] = { 0x23000, 0x1000, 32 | 16 | 8 }, /* L4TA4 */
+    [ 24] = { 0x28000, 0x1000, 32 | 16 | 8 }, /* GP Timer 1 */
+    [ 25] = { 0x29000, 0x1000, 32 | 16 | 8 }, /* L4TA7 */
+    [ 26] = { 0x48000, 0x2000, 32 | 16 | 8 }, /* Emulation (ARM11ETB) */
+    [ 27] = { 0x4a000, 0x1000, 32 | 16 | 8 }, /* L4TA9 */
+    [ 28] = { 0x50000,  0x400, 32 | 16 | 8 }, /* Display top */
+    [ 29] = { 0x50400,  0x400, 32 | 16 | 8 }, /* Display control */
+    [ 30] = { 0x50800,  0x400, 32 | 16 | 8 }, /* Display RFBI */
+    [ 31] = { 0x50c00,  0x400, 32 | 16 | 8 }, /* Display encoder */
+    [ 32] = { 0x51000, 0x1000, 32 | 16 | 8 }, /* L4TA10 */
+    [ 33] = { 0x52000,  0x400, 32 | 16 | 8 }, /* Camera top */
+    [ 34] = { 0x52400,  0x400, 32 | 16 | 8 }, /* Camera core */
+    [ 35] = { 0x52800,  0x400, 32 | 16 | 8 }, /* Camera DMA */
+    [ 36] = { 0x52c00,  0x400, 32 | 16 | 8 }, /* Camera MMU */
+    [ 37] = { 0x53000, 0x1000, 32 | 16 | 8 }, /* L4TA11 */
+    [ 38] = { 0x56000, 0x1000, 32 | 16 | 8 }, /* sDMA */
+    [ 39] = { 0x57000, 0x1000, 32 | 16 | 8 }, /* L4TA12 */
+    [ 40] = { 0x58000, 0x1000, 32 | 16 | 8 }, /* SSI top */
+    [ 41] = { 0x59000, 0x1000, 32 | 16 | 8 }, /* SSI GDD */
+    [ 42] = { 0x5a000, 0x1000, 32 | 16 | 8 }, /* SSI Port1 */
+    [ 43] = { 0x5b000, 0x1000, 32 | 16 | 8 }, /* SSI Port2 */
+    [ 44] = { 0x5c000, 0x1000, 32 | 16 | 8 }, /* L4TA13 */
+    [ 45] = { 0x5e000, 0x1000, 32 | 16 | 8 }, /* USB OTG */
+    [ 46] = { 0x5f000, 0x1000, 32 | 16 | 8 }, /* L4TAO4 */
+    [ 47] = { 0x60000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER1SDRC) */
+    [ 48] = { 0x61000, 0x1000, 32 | 16 | 8 }, /* L4TA14 */
+    [ 49] = { 0x62000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER2GPMC) */
+    [ 50] = { 0x63000, 0x1000, 32 | 16 | 8 }, /* L4TA15 */
+    [ 51] = { 0x64000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER3OCM) */
+    [ 52] = { 0x65000, 0x1000, 32 | 16 | 8 }, /* L4TA16 */
+    [ 53] = { 0x66000,  0x300, 32 | 16 | 8 }, /* Emulation (WIN_TRACER4L4) */
+    [ 54] = { 0x67000, 0x1000, 32 | 16 | 8 }, /* L4TA17 */
+    [ 55] = { 0x68000, 0x1000, 32 | 16 | 8 }, /* Emulation (XTI) */
+    [ 56] = { 0x69000, 0x1000, 32 | 16 | 8 }, /* L4TA18 */
+    [ 57] = { 0x6a000, 0x1000,      16 | 8 }, /* UART1 */
+    [ 58] = { 0x6b000, 0x1000, 32 | 16 | 8 }, /* L4TA19 */
+    [ 59] = { 0x6c000, 0x1000,      16 | 8 }, /* UART2 */
+    [ 60] = { 0x6d000, 0x1000, 32 | 16 | 8 }, /* L4TA20 */
+    [ 61] = { 0x6e000, 0x1000,      16 | 8 }, /* UART3 */
+    [ 62] = { 0x6f000, 0x1000, 32 | 16 | 8 }, /* L4TA21 */
+    [ 63] = { 0x70000, 0x1000,      16     }, /* I2C1 */
+    [ 64] = { 0x71000, 0x1000, 32 | 16 | 8 }, /* L4TAO5 */
+    [ 65] = { 0x72000, 0x1000,      16     }, /* I2C2 */
+    [ 66] = { 0x73000, 0x1000, 32 | 16 | 8 }, /* L4TAO6 */
+    [ 67] = { 0x74000, 0x1000,      16     }, /* McBSP1 */
+    [ 68] = { 0x75000, 0x1000, 32 | 16 | 8 }, /* L4TAO7 */
+    [ 69] = { 0x76000, 0x1000,      16     }, /* McBSP2 */
+    [ 70] = { 0x77000, 0x1000, 32 | 16 | 8 }, /* L4TAO8 */
+    [ 71] = { 0x24000, 0x1000, 32 | 16 | 8 }, /* WD Timer 3 (DSP) */
+    [ 72] = { 0x25000, 0x1000, 32 | 16 | 8 }, /* L4TA5 */
+    [ 73] = { 0x26000, 0x1000, 32 | 16 | 8 }, /* WD Timer 4 (IVA) */
+    [ 74] = { 0x27000, 0x1000, 32 | 16 | 8 }, /* L4TA6 */
+    [ 75] = { 0x2a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 2 */
+    [ 76] = { 0x2b000, 0x1000, 32 | 16 | 8 }, /* L4TA8 */
+    [ 77] = { 0x78000, 0x1000, 32 | 16 | 8 }, /* GP Timer 3 */
+    [ 78] = { 0x79000, 0x1000, 32 | 16 | 8 }, /* L4TA22 */
+    [ 79] = { 0x7a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 4 */
+    [ 80] = { 0x7b000, 0x1000, 32 | 16 | 8 }, /* L4TA23 */
+    [ 81] = { 0x7c000, 0x1000, 32 | 16 | 8 }, /* GP Timer 5 */
+    [ 82] = { 0x7d000, 0x1000, 32 | 16 | 8 }, /* L4TA24 */
+    [ 83] = { 0x7e000, 0x1000, 32 | 16 | 8 }, /* GP Timer 6 */
+    [ 84] = { 0x7f000, 0x1000, 32 | 16 | 8 }, /* L4TA25 */
+    [ 85] = { 0x80000, 0x1000, 32 | 16 | 8 }, /* GP Timer 7 */
+    [ 86] = { 0x81000, 0x1000, 32 | 16 | 8 }, /* L4TA26 */
+    [ 87] = { 0x82000, 0x1000, 32 | 16 | 8 }, /* GP Timer 8 */
+    [ 88] = { 0x83000, 0x1000, 32 | 16 | 8 }, /* L4TA27 */
+    [ 89] = { 0x84000, 0x1000, 32 | 16 | 8 }, /* GP Timer 9 */
+    [ 90] = { 0x85000, 0x1000, 32 | 16 | 8 }, /* L4TA28 */
+    [ 91] = { 0x86000, 0x1000, 32 | 16 | 8 }, /* GP Timer 10 */
+    [ 92] = { 0x87000, 0x1000, 32 | 16 | 8 }, /* L4TA29 */
+    [ 93] = { 0x88000, 0x1000, 32 | 16 | 8 }, /* GP Timer 11 */
+    [ 94] = { 0x89000, 0x1000, 32 | 16 | 8 }, /* L4TA30 */
+    [ 95] = { 0x8a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 12 */
+    [ 96] = { 0x8b000, 0x1000, 32 | 16 | 8 }, /* L4TA31 */
+    [ 97] = { 0x90000, 0x1000,      16     }, /* EAC */
+    [ 98] = { 0x91000, 0x1000, 32 | 16 | 8 }, /* L4TA32 */
+    [ 99] = { 0x92000, 0x1000,      16     }, /* FAC */
+    [100] = { 0x93000, 0x1000, 32 | 16 | 8 }, /* L4TA33 */
+    [101] = { 0x94000, 0x1000, 32 | 16 | 8 }, /* IPC (MAILBOX) */
+    [102] = { 0x95000, 0x1000, 32 | 16 | 8 }, /* L4TA34 */
+    [103] = { 0x98000, 0x1000, 32 | 16 | 8 }, /* SPI1 */
+    [104] = { 0x99000, 0x1000, 32 | 16 | 8 }, /* L4TA35 */
+    [105] = { 0x9a000, 0x1000, 32 | 16 | 8 }, /* SPI2 */
+    [106] = { 0x9b000, 0x1000, 32 | 16 | 8 }, /* L4TA36 */
+    [107] = { 0x9c000, 0x1000,      16 | 8 }, /* MMC SDIO */
+    [108] = { 0x9d000, 0x1000, 32 | 16 | 8 }, /* L4TAO9 */
+    [109] = { 0x9e000, 0x1000, 32 | 16 | 8 }, /* MS_PRO */
+    [110] = { 0x9f000, 0x1000, 32 | 16 | 8 }, /* L4TAO10 */
+    [111] = { 0xa0000, 0x1000, 32          }, /* RNG */
+    [112] = { 0xa1000, 0x1000, 32 | 16 | 8 }, /* L4TAO11 */
+    [113] = { 0xa2000, 0x1000, 32          }, /* DES3DES */
+    [114] = { 0xa3000, 0x1000, 32 | 16 | 8 }, /* L4TAO12 */
+    [115] = { 0xa4000, 0x1000, 32          }, /* SHA1MD5 */
+    [116] = { 0xa5000, 0x1000, 32 | 16 | 8 }, /* L4TAO13 */
+    [117] = { 0xa6000, 0x1000, 32          }, /* AES */
+    [118] = { 0xa7000, 0x1000, 32 | 16 | 8 }, /* L4TA37 */
+    [119] = { 0xa8000, 0x2000, 32          }, /* PKA */
+    [120] = { 0xaa000, 0x1000, 32 | 16 | 8 }, /* L4TA38 */
+    [121] = { 0xb0000, 0x1000, 32          }, /* MG */
+    [122] = { 0xb1000, 0x1000, 32 | 16 | 8 },
+    [123] = { 0xb2000, 0x1000, 32          }, /* HDQ/1-Wire */
+    [124] = { 0xb3000, 0x1000, 32 | 16 | 8 }, /* L4TA39 */
+};
+
+static const struct omap_l4_agent_info_s omap_l4_agent_info[54] = {
+    { 0,           0, 3, 2 }, /* L4IA initiatior agent */
+    { L4TAO(1),    3, 2, 1 }, /* Control and pinout module */
+    { L4TAO(2),    5, 2, 1 }, /* 32K timer */
+    { L4TAO(3),    7, 3, 2 }, /* PRCM */
+    { L4TA(1),    10, 2, 1 }, /* BCM */
+    { L4TA(2),    12, 2, 1 }, /* Test JTAG */
+    { L4TA(3),    14, 6, 3 }, /* Quad GPIO */
+    { L4TA(4),    20, 4, 3 }, /* WD timer 1/2 */
+    { L4TA(7),    24, 2, 1 }, /* GP timer 1 */
+    { L4TA(9),    26, 2, 1 }, /* ATM11 ETB */
+    { L4TA(10),   28, 5, 4 }, /* Display subsystem */
+    { L4TA(11),   33, 5, 4 }, /* Camera subsystem */
+    { L4TA(12),   38, 2, 1 }, /* sDMA */
+    { L4TA(13),   40, 5, 4 }, /* SSI */
+    { L4TAO(4),   45, 2, 1 }, /* USB */
+    { L4TA(14),   47, 2, 1 }, /* Win Tracer1 */
+    { L4TA(15),   49, 2, 1 }, /* Win Tracer2 */
+    { L4TA(16),   51, 2, 1 }, /* Win Tracer3 */
+    { L4TA(17),   53, 2, 1 }, /* Win Tracer4 */
+    { L4TA(18),   55, 2, 1 }, /* XTI */
+    { L4TA(19),   57, 2, 1 }, /* UART1 */
+    { L4TA(20),   59, 2, 1 }, /* UART2 */
+    { L4TA(21),   61, 2, 1 }, /* UART3 */
+    { L4TAO(5),   63, 2, 1 }, /* I2C1 */
+    { L4TAO(6),   65, 2, 1 }, /* I2C2 */
+    { L4TAO(7),   67, 2, 1 }, /* McBSP1 */
+    { L4TAO(8),   69, 2, 1 }, /* McBSP2 */
+    { L4TA(5),    71, 2, 1 }, /* WD Timer 3 (DSP) */
+    { L4TA(6),    73, 2, 1 }, /* WD Timer 4 (IVA) */
+    { L4TA(8),    75, 2, 1 }, /* GP Timer 2 */
+    { L4TA(22),   77, 2, 1 }, /* GP Timer 3 */
+    { L4TA(23),   79, 2, 1 }, /* GP Timer 4 */
+    { L4TA(24),   81, 2, 1 }, /* GP Timer 5 */
+    { L4TA(25),   83, 2, 1 }, /* GP Timer 6 */
+    { L4TA(26),   85, 2, 1 }, /* GP Timer 7 */
+    { L4TA(27),   87, 2, 1 }, /* GP Timer 8 */
+    { L4TA(28),   89, 2, 1 }, /* GP Timer 9 */
+    { L4TA(29),   91, 2, 1 }, /* GP Timer 10 */
+    { L4TA(30),   93, 2, 1 }, /* GP Timer 11 */
+    { L4TA(31),   95, 2, 1 }, /* GP Timer 12 */
+    { L4TA(32),   97, 2, 1 }, /* EAC */
+    { L4TA(33),   99, 2, 1 }, /* FAC */
+    { L4TA(34),  101, 2, 1 }, /* IPC */
+    { L4TA(35),  103, 2, 1 }, /* SPI1 */
+    { L4TA(36),  105, 2, 1 }, /* SPI2 */
+    { L4TAO(9),  107, 2, 1 }, /* MMC SDIO */
+    { L4TAO(10), 109, 2, 1 },
+    { L4TAO(11), 111, 2, 1 }, /* RNG */
+    { L4TAO(12), 113, 2, 1 }, /* DES3DES */
+    { L4TAO(13), 115, 2, 1 }, /* SHA1MD5 */
+    { L4TA(37),  117, 2, 1 }, /* AES */
+    { L4TA(38),  119, 2, 1 }, /* PKA */
+    { -1,        121, 2, 1 },
+    { L4TA(39),  123, 2, 1 }, /* HDQ/1-Wire */
+};
+
+#define omap_l4ta(bus, cs)	\
+    omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TA(cs))
+#define omap_l4tao(bus, cs)	\
+    omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TAO(cs))
+
+/* Power, Reset, and Clock Management */
+struct omap_prcm_s {
+    qemu_irq irq[3];
+    struct omap_mpu_state_s *mpu;
+    MemoryRegion iomem0;
+    MemoryRegion iomem1;
+
+    uint32_t irqst[3];
+    uint32_t irqen[3];
+
+    uint32_t sysconfig;
+    uint32_t voltctrl;
+    uint32_t scratch[20];
+
+    uint32_t clksrc[1];
+    uint32_t clkout[1];
+    uint32_t clkemul[1];
+    uint32_t clkpol[1];
+    uint32_t clksel[8];
+    uint32_t clken[12];
+    uint32_t clkctrl[4];
+    uint32_t clkidle[7];
+    uint32_t setuptime[2];
+
+    uint32_t wkup[3];
+    uint32_t wken[3];
+    uint32_t wkst[3];
+    uint32_t rst[4];
+    uint32_t rstctrl[1];
+    uint32_t power[4];
+    uint32_t rsttime_wkup;
+
+    uint32_t ev;
+    uint32_t evtime[2];
+
+    int dpll_lock, apll_lock[2];
+};
+
+static void omap_prcm_int_update(struct omap_prcm_s *s, int dom)
+{
+    qemu_set_irq(s->irq[dom], s->irqst[dom] & s->irqen[dom]);
+    /* XXX or is the mask applied before PRCM_IRQSTATUS_* ? */
+}
+
+static uint64_t omap_prcm_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
+    uint32_t ret;
+
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
+    switch (addr) {
+    case 0x000:	/* PRCM_REVISION */
+        return 0x10;
+
+    case 0x010:	/* PRCM_SYSCONFIG */
+        return s->sysconfig;
+
+    case 0x018:	/* PRCM_IRQSTATUS_MPU */
+        return s->irqst[0];
+
+    case 0x01c:	/* PRCM_IRQENABLE_MPU */
+        return s->irqen[0];
+
+    case 0x050:	/* PRCM_VOLTCTRL */
+        return s->voltctrl;
+    case 0x054:	/* PRCM_VOLTST */
+        return s->voltctrl & 3;
+
+    case 0x060:	/* PRCM_CLKSRC_CTRL */
+        return s->clksrc[0];
+    case 0x070:	/* PRCM_CLKOUT_CTRL */
+        return s->clkout[0];
+    case 0x078:	/* PRCM_CLKEMUL_CTRL */
+        return s->clkemul[0];
+    case 0x080:	/* PRCM_CLKCFG_CTRL */
+    case 0x084:	/* PRCM_CLKCFG_STATUS */
+        return 0;
+
+    case 0x090:	/* PRCM_VOLTSETUP */
+        return s->setuptime[0];
+
+    case 0x094:	/* PRCM_CLKSSETUP */
+        return s->setuptime[1];
+
+    case 0x098:	/* PRCM_POLCTRL */
+        return s->clkpol[0];
+
+    case 0x0b0:	/* GENERAL_PURPOSE1 */
+    case 0x0b4:	/* GENERAL_PURPOSE2 */
+    case 0x0b8:	/* GENERAL_PURPOSE3 */
+    case 0x0bc:	/* GENERAL_PURPOSE4 */
+    case 0x0c0:	/* GENERAL_PURPOSE5 */
+    case 0x0c4:	/* GENERAL_PURPOSE6 */
+    case 0x0c8:	/* GENERAL_PURPOSE7 */
+    case 0x0cc:	/* GENERAL_PURPOSE8 */
+    case 0x0d0:	/* GENERAL_PURPOSE9 */
+    case 0x0d4:	/* GENERAL_PURPOSE10 */
+    case 0x0d8:	/* GENERAL_PURPOSE11 */
+    case 0x0dc:	/* GENERAL_PURPOSE12 */
+    case 0x0e0:	/* GENERAL_PURPOSE13 */
+    case 0x0e4:	/* GENERAL_PURPOSE14 */
+    case 0x0e8:	/* GENERAL_PURPOSE15 */
+    case 0x0ec:	/* GENERAL_PURPOSE16 */
+    case 0x0f0:	/* GENERAL_PURPOSE17 */
+    case 0x0f4:	/* GENERAL_PURPOSE18 */
+    case 0x0f8:	/* GENERAL_PURPOSE19 */
+    case 0x0fc:	/* GENERAL_PURPOSE20 */
+        return s->scratch[(addr - 0xb0) >> 2];
+
+    case 0x140:	/* CM_CLKSEL_MPU */
+        return s->clksel[0];
+    case 0x148:	/* CM_CLKSTCTRL_MPU */
+        return s->clkctrl[0];
+
+    case 0x158:	/* RM_RSTST_MPU */
+        return s->rst[0];
+    case 0x1c8:	/* PM_WKDEP_MPU */
+        return s->wkup[0];
+    case 0x1d4:	/* PM_EVGENCTRL_MPU */
+        return s->ev;
+    case 0x1d8:	/* PM_EVEGENONTIM_MPU */
+        return s->evtime[0];
+    case 0x1dc:	/* PM_EVEGENOFFTIM_MPU */
+        return s->evtime[1];
+    case 0x1e0:	/* PM_PWSTCTRL_MPU */
+        return s->power[0];
+    case 0x1e4:	/* PM_PWSTST_MPU */
+        return 0;
+
+    case 0x200:	/* CM_FCLKEN1_CORE */
+        return s->clken[0];
+    case 0x204:	/* CM_FCLKEN2_CORE */
+        return s->clken[1];
+    case 0x210:	/* CM_ICLKEN1_CORE */
+        return s->clken[2];
+    case 0x214:	/* CM_ICLKEN2_CORE */
+        return s->clken[3];
+    case 0x21c:	/* CM_ICLKEN4_CORE */
+        return s->clken[4];
+
+    case 0x220:	/* CM_IDLEST1_CORE */
+        /* TODO: check the actual iclk status */
+        return 0x7ffffff9;
+    case 0x224:	/* CM_IDLEST2_CORE */
+        /* TODO: check the actual iclk status */
+        return 0x00000007;
+    case 0x22c:	/* CM_IDLEST4_CORE */
+        /* TODO: check the actual iclk status */
+        return 0x0000001f;
+
+    case 0x230:	/* CM_AUTOIDLE1_CORE */
+        return s->clkidle[0];
+    case 0x234:	/* CM_AUTOIDLE2_CORE */
+        return s->clkidle[1];
+    case 0x238:	/* CM_AUTOIDLE3_CORE */
+        return s->clkidle[2];
+    case 0x23c:	/* CM_AUTOIDLE4_CORE */
+        return s->clkidle[3];
+
+    case 0x240:	/* CM_CLKSEL1_CORE */
+        return s->clksel[1];
+    case 0x244:	/* CM_CLKSEL2_CORE */
+        return s->clksel[2];
+
+    case 0x248:	/* CM_CLKSTCTRL_CORE */
+        return s->clkctrl[1];
+
+    case 0x2a0:	/* PM_WKEN1_CORE */
+        return s->wken[0];
+    case 0x2a4:	/* PM_WKEN2_CORE */
+        return s->wken[1];
+
+    case 0x2b0:	/* PM_WKST1_CORE */
+        return s->wkst[0];
+    case 0x2b4:	/* PM_WKST2_CORE */
+        return s->wkst[1];
+    case 0x2c8:	/* PM_WKDEP_CORE */
+        return 0x1e;
+
+    case 0x2e0:	/* PM_PWSTCTRL_CORE */
+        return s->power[1];
+    case 0x2e4:	/* PM_PWSTST_CORE */
+        return 0x000030 | (s->power[1] & 0xfc00);
+
+    case 0x300:	/* CM_FCLKEN_GFX */
+        return s->clken[5];
+    case 0x310:	/* CM_ICLKEN_GFX */
+        return s->clken[6];
+    case 0x320:	/* CM_IDLEST_GFX */
+        /* TODO: check the actual iclk status */
+        return 0x00000001;
+    case 0x340:	/* CM_CLKSEL_GFX */
+        return s->clksel[3];
+    case 0x348:	/* CM_CLKSTCTRL_GFX */
+        return s->clkctrl[2];
+    case 0x350:	/* RM_RSTCTRL_GFX */
+        return s->rstctrl[0];
+    case 0x358:	/* RM_RSTST_GFX */
+        return s->rst[1];
+    case 0x3c8:	/* PM_WKDEP_GFX */
+        return s->wkup[1];
+
+    case 0x3e0:	/* PM_PWSTCTRL_GFX */
+        return s->power[2];
+    case 0x3e4:	/* PM_PWSTST_GFX */
+        return s->power[2] & 3;
+
+    case 0x400:	/* CM_FCLKEN_WKUP */
+        return s->clken[7];
+    case 0x410:	/* CM_ICLKEN_WKUP */
+        return s->clken[8];
+    case 0x420:	/* CM_IDLEST_WKUP */
+        /* TODO: check the actual iclk status */
+        return 0x0000003f;
+    case 0x430:	/* CM_AUTOIDLE_WKUP */
+        return s->clkidle[4];
+    case 0x440:	/* CM_CLKSEL_WKUP */
+        return s->clksel[4];
+    case 0x450:	/* RM_RSTCTRL_WKUP */
+        return 0;
+    case 0x454:	/* RM_RSTTIME_WKUP */
+        return s->rsttime_wkup;
+    case 0x458:	/* RM_RSTST_WKUP */
+        return s->rst[2];
+    case 0x4a0:	/* PM_WKEN_WKUP */
+        return s->wken[2];
+    case 0x4b0:	/* PM_WKST_WKUP */
+        return s->wkst[2];
+
+    case 0x500:	/* CM_CLKEN_PLL */
+        return s->clken[9];
+    case 0x520:	/* CM_IDLEST_CKGEN */
+        ret = 0x0000070 | (s->apll_lock[0] << 9) | (s->apll_lock[1] << 8);
+        if (!(s->clksel[6] & 3))
+            /* Core uses 32-kHz clock */
+            ret |= 3 << 0;
+        else if (!s->dpll_lock)
+            /* DPLL not locked, core uses ref_clk */
+            ret |= 1 << 0;
+        else
+            /* Core uses DPLL */
+            ret |= 2 << 0;
+        return ret;
+    case 0x530:	/* CM_AUTOIDLE_PLL */
+        return s->clkidle[5];
+    case 0x540:	/* CM_CLKSEL1_PLL */
+        return s->clksel[5];
+    case 0x544:	/* CM_CLKSEL2_PLL */
+        return s->clksel[6];
+
+    case 0x800:	/* CM_FCLKEN_DSP */
+        return s->clken[10];
+    case 0x810:	/* CM_ICLKEN_DSP */
+        return s->clken[11];
+    case 0x820:	/* CM_IDLEST_DSP */
+        /* TODO: check the actual iclk status */
+        return 0x00000103;
+    case 0x830:	/* CM_AUTOIDLE_DSP */
+        return s->clkidle[6];
+    case 0x840:	/* CM_CLKSEL_DSP */
+        return s->clksel[7];
+    case 0x848:	/* CM_CLKSTCTRL_DSP */
+        return s->clkctrl[3];
+    case 0x850:	/* RM_RSTCTRL_DSP */
+        return 0;
+    case 0x858:	/* RM_RSTST_DSP */
+        return s->rst[3];
+    case 0x8c8:	/* PM_WKDEP_DSP */
+        return s->wkup[2];
+    case 0x8e0:	/* PM_PWSTCTRL_DSP */
+        return s->power[3];
+    case 0x8e4:	/* PM_PWSTST_DSP */
+        return 0x008030 | (s->power[3] & 0x3003);
+
+    case 0x8f0:	/* PRCM_IRQSTATUS_DSP */
+        return s->irqst[1];
+    case 0x8f4:	/* PRCM_IRQENABLE_DSP */
+        return s->irqen[1];
+
+    case 0x8f8:	/* PRCM_IRQSTATUS_IVA */
+        return s->irqst[2];
+    case 0x8fc:	/* PRCM_IRQENABLE_IVA */
+        return s->irqen[2];
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_prcm_apll_update(struct omap_prcm_s *s)
+{
+    int mode[2];
+
+    mode[0] = (s->clken[9] >> 6) & 3;
+    s->apll_lock[0] = (mode[0] == 3);
+    mode[1] = (s->clken[9] >> 2) & 3;
+    s->apll_lock[1] = (mode[1] == 3);
+    /* TODO: update clocks */
+
+    if (mode[0] == 1 || mode[0] == 2 || mode[1] == 1 || mode[1] == 2)
+        fprintf(stderr, "%s: bad EN_54M_PLL or bad EN_96M_PLL\n",
+                        __FUNCTION__);
+}
+
+static void omap_prcm_dpll_update(struct omap_prcm_s *s)
+{
+    omap_clk dpll = omap_findclk(s->mpu, "dpll");
+    omap_clk dpll_x2 = omap_findclk(s->mpu, "dpll");
+    omap_clk core = omap_findclk(s->mpu, "core_clk");
+    int mode = (s->clken[9] >> 0) & 3;
+    int mult, div;
+
+    mult = (s->clksel[5] >> 12) & 0x3ff;
+    div = (s->clksel[5] >> 8) & 0xf;
+    if (mult == 0 || mult == 1)
+        mode = 1;	/* Bypass */
+
+    s->dpll_lock = 0;
+    switch (mode) {
+    case 0:
+        fprintf(stderr, "%s: bad EN_DPLL\n", __FUNCTION__);
+        break;
+    case 1:	/* Low-power bypass mode (Default) */
+    case 2:	/* Fast-relock bypass mode */
+        omap_clk_setrate(dpll, 1, 1);
+        omap_clk_setrate(dpll_x2, 1, 1);
+        break;
+    case 3:	/* Lock mode */
+        s->dpll_lock = 1; /* After 20 FINT cycles (ref_clk / (div + 1)).  */
+
+        omap_clk_setrate(dpll, div + 1, mult);
+        omap_clk_setrate(dpll_x2, div + 1, mult * 2);
+        break;
+    }
+
+    switch ((s->clksel[6] >> 0) & 3) {
+    case 0:
+        omap_clk_reparent(core, omap_findclk(s->mpu, "clk32-kHz"));
+        break;
+    case 1:
+        omap_clk_reparent(core, dpll);
+        break;
+    case 2:
+        /* Default */
+        omap_clk_reparent(core, dpll_x2);
+        break;
+    case 3:
+        fprintf(stderr, "%s: bad CORE_CLK_SRC\n", __FUNCTION__);
+        break;
+    }
+}
+
+static void omap_prcm_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
+
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
+    switch (addr) {
+    case 0x000:	/* PRCM_REVISION */
+    case 0x054:	/* PRCM_VOLTST */
+    case 0x084:	/* PRCM_CLKCFG_STATUS */
+    case 0x1e4:	/* PM_PWSTST_MPU */
+    case 0x220:	/* CM_IDLEST1_CORE */
+    case 0x224:	/* CM_IDLEST2_CORE */
+    case 0x22c:	/* CM_IDLEST4_CORE */
+    case 0x2c8:	/* PM_WKDEP_CORE */
+    case 0x2e4:	/* PM_PWSTST_CORE */
+    case 0x320:	/* CM_IDLEST_GFX */
+    case 0x3e4:	/* PM_PWSTST_GFX */
+    case 0x420:	/* CM_IDLEST_WKUP */
+    case 0x520:	/* CM_IDLEST_CKGEN */
+    case 0x820:	/* CM_IDLEST_DSP */
+    case 0x8e4:	/* PM_PWSTST_DSP */
+        OMAP_RO_REG(addr);
+        return;
+
+    case 0x010:	/* PRCM_SYSCONFIG */
+        s->sysconfig = value & 1;
+        break;
+
+    case 0x018:	/* PRCM_IRQSTATUS_MPU */
+        s->irqst[0] &= ~value;
+        omap_prcm_int_update(s, 0);
+        break;
+    case 0x01c:	/* PRCM_IRQENABLE_MPU */
+        s->irqen[0] = value & 0x3f;
+        omap_prcm_int_update(s, 0);
+        break;
+
+    case 0x050:	/* PRCM_VOLTCTRL */
+        s->voltctrl = value & 0xf1c3;
+        break;
+
+    case 0x060:	/* PRCM_CLKSRC_CTRL */
+        s->clksrc[0] = value & 0xdb;
+        /* TODO update clocks */
+        break;
+
+    case 0x070:	/* PRCM_CLKOUT_CTRL */
+        s->clkout[0] = value & 0xbbbb;
+        /* TODO update clocks */
+        break;
+
+    case 0x078:	/* PRCM_CLKEMUL_CTRL */
+        s->clkemul[0] = value & 1;
+        /* TODO update clocks */
+        break;
+
+    case 0x080:	/* PRCM_CLKCFG_CTRL */
+        break;
+
+    case 0x090:	/* PRCM_VOLTSETUP */
+        s->setuptime[0] = value & 0xffff;
+        break;
+    case 0x094:	/* PRCM_CLKSSETUP */
+        s->setuptime[1] = value & 0xffff;
+        break;
+
+    case 0x098:	/* PRCM_POLCTRL */
+        s->clkpol[0] = value & 0x701;
+        break;
+
+    case 0x0b0:	/* GENERAL_PURPOSE1 */
+    case 0x0b4:	/* GENERAL_PURPOSE2 */
+    case 0x0b8:	/* GENERAL_PURPOSE3 */
+    case 0x0bc:	/* GENERAL_PURPOSE4 */
+    case 0x0c0:	/* GENERAL_PURPOSE5 */
+    case 0x0c4:	/* GENERAL_PURPOSE6 */
+    case 0x0c8:	/* GENERAL_PURPOSE7 */
+    case 0x0cc:	/* GENERAL_PURPOSE8 */
+    case 0x0d0:	/* GENERAL_PURPOSE9 */
+    case 0x0d4:	/* GENERAL_PURPOSE10 */
+    case 0x0d8:	/* GENERAL_PURPOSE11 */
+    case 0x0dc:	/* GENERAL_PURPOSE12 */
+    case 0x0e0:	/* GENERAL_PURPOSE13 */
+    case 0x0e4:	/* GENERAL_PURPOSE14 */
+    case 0x0e8:	/* GENERAL_PURPOSE15 */
+    case 0x0ec:	/* GENERAL_PURPOSE16 */
+    case 0x0f0:	/* GENERAL_PURPOSE17 */
+    case 0x0f4:	/* GENERAL_PURPOSE18 */
+    case 0x0f8:	/* GENERAL_PURPOSE19 */
+    case 0x0fc:	/* GENERAL_PURPOSE20 */
+        s->scratch[(addr - 0xb0) >> 2] = value;
+        break;
+
+    case 0x140:	/* CM_CLKSEL_MPU */
+        s->clksel[0] = value & 0x1f;
+        /* TODO update clocks */
+        break;
+    case 0x148:	/* CM_CLKSTCTRL_MPU */
+        s->clkctrl[0] = value & 0x1f;
+        break;
+
+    case 0x158:	/* RM_RSTST_MPU */
+        s->rst[0] &= ~value;
+        break;
+    case 0x1c8:	/* PM_WKDEP_MPU */
+        s->wkup[0] = value & 0x15;
+        break;
+
+    case 0x1d4:	/* PM_EVGENCTRL_MPU */
+        s->ev = value & 0x1f;
+        break;
+    case 0x1d8:	/* PM_EVEGENONTIM_MPU */
+        s->evtime[0] = value;
+        break;
+    case 0x1dc:	/* PM_EVEGENOFFTIM_MPU */
+        s->evtime[1] = value;
+        break;
+
+    case 0x1e0:	/* PM_PWSTCTRL_MPU */
+        s->power[0] = value & 0xc0f;
+        break;
+
+    case 0x200:	/* CM_FCLKEN1_CORE */
+        s->clken[0] = value & 0xbfffffff;
+        /* TODO update clocks */
+        /* The EN_EAC bit only gets/puts func_96m_clk.  */
+        break;
+    case 0x204:	/* CM_FCLKEN2_CORE */
+        s->clken[1] = value & 0x00000007;
+        /* TODO update clocks */
+        break;
+    case 0x210:	/* CM_ICLKEN1_CORE */
+        s->clken[2] = value & 0xfffffff9;
+        /* TODO update clocks */
+        /* The EN_EAC bit only gets/puts core_l4_iclk.  */
+        break;
+    case 0x214:	/* CM_ICLKEN2_CORE */
+        s->clken[3] = value & 0x00000007;
+        /* TODO update clocks */
+        break;
+    case 0x21c:	/* CM_ICLKEN4_CORE */
+        s->clken[4] = value & 0x0000001f;
+        /* TODO update clocks */
+        break;
+
+    case 0x230:	/* CM_AUTOIDLE1_CORE */
+        s->clkidle[0] = value & 0xfffffff9;
+        /* TODO update clocks */
+        break;
+    case 0x234:	/* CM_AUTOIDLE2_CORE */
+        s->clkidle[1] = value & 0x00000007;
+        /* TODO update clocks */
+        break;
+    case 0x238:	/* CM_AUTOIDLE3_CORE */
+        s->clkidle[2] = value & 0x00000007;
+        /* TODO update clocks */
+        break;
+    case 0x23c:	/* CM_AUTOIDLE4_CORE */
+        s->clkidle[3] = value & 0x0000001f;
+        /* TODO update clocks */
+        break;
+
+    case 0x240:	/* CM_CLKSEL1_CORE */
+        s->clksel[1] = value & 0x0fffbf7f;
+        /* TODO update clocks */
+        break;
+
+    case 0x244:	/* CM_CLKSEL2_CORE */
+        s->clksel[2] = value & 0x00fffffc;
+        /* TODO update clocks */
+        break;
+
+    case 0x248:	/* CM_CLKSTCTRL_CORE */
+        s->clkctrl[1] = value & 0x7;
+        break;
+
+    case 0x2a0:	/* PM_WKEN1_CORE */
+        s->wken[0] = value & 0x04667ff8;
+        break;
+    case 0x2a4:	/* PM_WKEN2_CORE */
+        s->wken[1] = value & 0x00000005;
+        break;
+
+    case 0x2b0:	/* PM_WKST1_CORE */
+        s->wkst[0] &= ~value;
+        break;
+    case 0x2b4:	/* PM_WKST2_CORE */
+        s->wkst[1] &= ~value;
+        break;
+
+    case 0x2e0:	/* PM_PWSTCTRL_CORE */
+        s->power[1] = (value & 0x00fc3f) | (1 << 2);
+        break;
+
+    case 0x300:	/* CM_FCLKEN_GFX */
+        s->clken[5] = value & 6;
+        /* TODO update clocks */
+        break;
+    case 0x310:	/* CM_ICLKEN_GFX */
+        s->clken[6] = value & 1;
+        /* TODO update clocks */
+        break;
+    case 0x340:	/* CM_CLKSEL_GFX */
+        s->clksel[3] = value & 7;
+        /* TODO update clocks */
+        break;
+    case 0x348:	/* CM_CLKSTCTRL_GFX */
+        s->clkctrl[2] = value & 1;
+        break;
+    case 0x350:	/* RM_RSTCTRL_GFX */
+        s->rstctrl[0] = value & 1;
+        /* TODO: reset */
+        break;
+    case 0x358:	/* RM_RSTST_GFX */
+        s->rst[1] &= ~value;
+        break;
+    case 0x3c8:	/* PM_WKDEP_GFX */
+        s->wkup[1] = value & 0x13;
+        break;
+    case 0x3e0:	/* PM_PWSTCTRL_GFX */
+        s->power[2] = (value & 0x00c0f) | (3 << 2);
+        break;
+
+    case 0x400:	/* CM_FCLKEN_WKUP */
+        s->clken[7] = value & 0xd;
+        /* TODO update clocks */
+        break;
+    case 0x410:	/* CM_ICLKEN_WKUP */
+        s->clken[8] = value & 0x3f;
+        /* TODO update clocks */
+        break;
+    case 0x430:	/* CM_AUTOIDLE_WKUP */
+        s->clkidle[4] = value & 0x0000003f;
+        /* TODO update clocks */
+        break;
+    case 0x440:	/* CM_CLKSEL_WKUP */
+        s->clksel[4] = value & 3;
+        /* TODO update clocks */
+        break;
+    case 0x450:	/* RM_RSTCTRL_WKUP */
+        /* TODO: reset */
+        if (value & 2)
+            qemu_system_reset_request();
+        break;
+    case 0x454:	/* RM_RSTTIME_WKUP */
+        s->rsttime_wkup = value & 0x1fff;
+        break;
+    case 0x458:	/* RM_RSTST_WKUP */
+        s->rst[2] &= ~value;
+        break;
+    case 0x4a0:	/* PM_WKEN_WKUP */
+        s->wken[2] = value & 0x00000005;
+        break;
+    case 0x4b0:	/* PM_WKST_WKUP */
+        s->wkst[2] &= ~value;
+        break;
+
+    case 0x500:	/* CM_CLKEN_PLL */
+        if (value & 0xffffff30)
+            fprintf(stderr, "%s: write 0s in CM_CLKEN_PLL for "
+                            "future compatibility\n", __FUNCTION__);
+        if ((s->clken[9] ^ value) & 0xcc) {
+            s->clken[9] &= ~0xcc;
+            s->clken[9] |= value & 0xcc;
+            omap_prcm_apll_update(s);
+        }
+        if ((s->clken[9] ^ value) & 3) {
+            s->clken[9] &= ~3;
+            s->clken[9] |= value & 3;
+            omap_prcm_dpll_update(s);
+        }
+        break;
+    case 0x530:	/* CM_AUTOIDLE_PLL */
+        s->clkidle[5] = value & 0x000000cf;
+        /* TODO update clocks */
+        break;
+    case 0x540:	/* CM_CLKSEL1_PLL */
+        if (value & 0xfc4000d7)
+            fprintf(stderr, "%s: write 0s in CM_CLKSEL1_PLL for "
+                            "future compatibility\n", __FUNCTION__);
+        if ((s->clksel[5] ^ value) & 0x003fff00) {
+            s->clksel[5] = value & 0x03bfff28;
+            omap_prcm_dpll_update(s);
+        }
+        /* TODO update the other clocks */
+
+        s->clksel[5] = value & 0x03bfff28;
+        break;
+    case 0x544:	/* CM_CLKSEL2_PLL */
+        if (value & ~3)
+            fprintf(stderr, "%s: write 0s in CM_CLKSEL2_PLL[31:2] for "
+                            "future compatibility\n", __FUNCTION__);
+        if (s->clksel[6] != (value & 3)) {
+            s->clksel[6] = value & 3;
+            omap_prcm_dpll_update(s);
+        }
+        break;
+
+    case 0x800:	/* CM_FCLKEN_DSP */
+        s->clken[10] = value & 0x501;
+        /* TODO update clocks */
+        break;
+    case 0x810:	/* CM_ICLKEN_DSP */
+        s->clken[11] = value & 0x2;
+        /* TODO update clocks */
+        break;
+    case 0x830:	/* CM_AUTOIDLE_DSP */
+        s->clkidle[6] = value & 0x2;
+        /* TODO update clocks */
+        break;
+    case 0x840:	/* CM_CLKSEL_DSP */
+        s->clksel[7] = value & 0x3fff;
+        /* TODO update clocks */
+        break;
+    case 0x848:	/* CM_CLKSTCTRL_DSP */
+        s->clkctrl[3] = value & 0x101;
+        break;
+    case 0x850:	/* RM_RSTCTRL_DSP */
+        /* TODO: reset */
+        break;
+    case 0x858:	/* RM_RSTST_DSP */
+        s->rst[3] &= ~value;
+        break;
+    case 0x8c8:	/* PM_WKDEP_DSP */
+        s->wkup[2] = value & 0x13;
+        break;
+    case 0x8e0:	/* PM_PWSTCTRL_DSP */
+        s->power[3] = (value & 0x03017) | (3 << 2);
+        break;
+
+    case 0x8f0:	/* PRCM_IRQSTATUS_DSP */
+        s->irqst[1] &= ~value;
+        omap_prcm_int_update(s, 1);
+        break;
+    case 0x8f4:	/* PRCM_IRQENABLE_DSP */
+        s->irqen[1] = value & 0x7;
+        omap_prcm_int_update(s, 1);
+        break;
+
+    case 0x8f8:	/* PRCM_IRQSTATUS_IVA */
+        s->irqst[2] &= ~value;
+        omap_prcm_int_update(s, 2);
+        break;
+    case 0x8fc:	/* PRCM_IRQENABLE_IVA */
+        s->irqen[2] = value & 0x7;
+        omap_prcm_int_update(s, 2);
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_prcm_ops = {
+    .read = omap_prcm_read,
+    .write = omap_prcm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_prcm_reset(struct omap_prcm_s *s)
+{
+    s->sysconfig = 0;
+    s->irqst[0] = 0;
+    s->irqst[1] = 0;
+    s->irqst[2] = 0;
+    s->irqen[0] = 0;
+    s->irqen[1] = 0;
+    s->irqen[2] = 0;
+    s->voltctrl = 0x1040;
+    s->ev = 0x14;
+    s->evtime[0] = 0;
+    s->evtime[1] = 0;
+    s->clkctrl[0] = 0;
+    s->clkctrl[1] = 0;
+    s->clkctrl[2] = 0;
+    s->clkctrl[3] = 0;
+    s->clken[1] = 7;
+    s->clken[3] = 7;
+    s->clken[4] = 0;
+    s->clken[5] = 0;
+    s->clken[6] = 0;
+    s->clken[7] = 0xc;
+    s->clken[8] = 0x3e;
+    s->clken[9] = 0x0d;
+    s->clken[10] = 0;
+    s->clken[11] = 0;
+    s->clkidle[0] = 0;
+    s->clkidle[2] = 7;
+    s->clkidle[3] = 0;
+    s->clkidle[4] = 0;
+    s->clkidle[5] = 0x0c;
+    s->clkidle[6] = 0;
+    s->clksel[0] = 0x01;
+    s->clksel[1] = 0x02100121;
+    s->clksel[2] = 0x00000000;
+    s->clksel[3] = 0x01;
+    s->clksel[4] = 0;
+    s->clksel[7] = 0x0121;
+    s->wkup[0] = 0x15;
+    s->wkup[1] = 0x13;
+    s->wkup[2] = 0x13;
+    s->wken[0] = 0x04667ff8;
+    s->wken[1] = 0x00000005;
+    s->wken[2] = 5;
+    s->wkst[0] = 0;
+    s->wkst[1] = 0;
+    s->wkst[2] = 0;
+    s->power[0] = 0x00c;
+    s->power[1] = 4;
+    s->power[2] = 0x0000c;
+    s->power[3] = 0x14;
+    s->rstctrl[0] = 1;
+    s->rst[3] = 1;
+    omap_prcm_apll_update(s);
+    omap_prcm_dpll_update(s);
+}
+
+static void omap_prcm_coldreset(struct omap_prcm_s *s)
+{
+    s->setuptime[0] = 0;
+    s->setuptime[1] = 0;
+    memset(&s->scratch, 0, sizeof(s->scratch));
+    s->rst[0] = 0x01;
+    s->rst[1] = 0x00;
+    s->rst[2] = 0x01;
+    s->clken[0] = 0;
+    s->clken[2] = 0;
+    s->clkidle[1] = 0;
+    s->clksel[5] = 0;
+    s->clksel[6] = 2;
+    s->clksrc[0] = 0x43;
+    s->clkout[0] = 0x0303;
+    s->clkemul[0] = 0;
+    s->clkpol[0] = 0x100;
+    s->rsttime_wkup = 0x1002;
+
+    omap_prcm_reset(s);
+}
+
+static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
+                qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
+                struct omap_mpu_state_s *mpu)
+{
+    struct omap_prcm_s *s = (struct omap_prcm_s *)
+            g_malloc0(sizeof(struct omap_prcm_s));
+
+    s->irq[0] = mpu_int;
+    s->irq[1] = dsp_int;
+    s->irq[2] = iva_int;
+    s->mpu = mpu;
+    omap_prcm_coldreset(s);
+
+    memory_region_init_io(&s->iomem0, &omap_prcm_ops, s, "omap.pcrm0",
+                          omap_l4_region_size(ta, 0));
+    memory_region_init_io(&s->iomem1, &omap_prcm_ops, s, "omap.pcrm1",
+                          omap_l4_region_size(ta, 1));
+    omap_l4_attach(ta, 0, &s->iomem0);
+    omap_l4_attach(ta, 1, &s->iomem1);
+
+    return s;
+}
+
+/* System and Pinout control */
+struct omap_sysctl_s {
+    struct omap_mpu_state_s *mpu;
+    MemoryRegion iomem;
+
+    uint32_t sysconfig;
+    uint32_t devconfig;
+    uint32_t psaconfig;
+    uint32_t padconf[0x45];
+    uint8_t obs;
+    uint32_t msuspendmux[5];
+};
+
+static uint32_t omap_sysctl_read8(void *opaque, hwaddr addr)
+{
+
+    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
+    int pad_offset, byte_offset;
+    int value;
+
+    switch (addr) {
+    case 0x030 ... 0x140:	/* CONTROL_PADCONF - only used in the POP */
+        pad_offset = (addr - 0x30) >> 2;
+        byte_offset = (addr - 0x30) & (4 - 1);
+
+        value = s->padconf[pad_offset];
+        value = (value >> (byte_offset * 8)) & 0xff;
+
+        return value;
+
+    default:
+        break;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static uint32_t omap_sysctl_read(void *opaque, hwaddr addr)
+{
+    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
+
+    switch (addr) {
+    case 0x000:	/* CONTROL_REVISION */
+        return 0x20;
+
+    case 0x010:	/* CONTROL_SYSCONFIG */
+        return s->sysconfig;
+
+    case 0x030 ... 0x140:	/* CONTROL_PADCONF - only used in the POP */
+        return s->padconf[(addr - 0x30) >> 2];
+
+    case 0x270:	/* CONTROL_DEBOBS */
+        return s->obs;
+
+    case 0x274:	/* CONTROL_DEVCONF */
+        return s->devconfig;
+
+    case 0x28c:	/* CONTROL_EMU_SUPPORT */
+        return 0;
+
+    case 0x290:	/* CONTROL_MSUSPENDMUX_0 */
+        return s->msuspendmux[0];
+    case 0x294:	/* CONTROL_MSUSPENDMUX_1 */
+        return s->msuspendmux[1];
+    case 0x298:	/* CONTROL_MSUSPENDMUX_2 */
+        return s->msuspendmux[2];
+    case 0x29c:	/* CONTROL_MSUSPENDMUX_3 */
+        return s->msuspendmux[3];
+    case 0x2a0:	/* CONTROL_MSUSPENDMUX_4 */
+        return s->msuspendmux[4];
+    case 0x2a4:	/* CONTROL_MSUSPENDMUX_5 */
+        return 0;
+
+    case 0x2b8:	/* CONTROL_PSA_CTRL */
+        return s->psaconfig;
+    case 0x2bc:	/* CONTROL_PSA_CMD */
+    case 0x2c0:	/* CONTROL_PSA_VALUE */
+        return 0;
+
+    case 0x2b0:	/* CONTROL_SEC_CTRL */
+        return 0x800000f1;
+    case 0x2d0:	/* CONTROL_SEC_EMU */
+        return 0x80000015;
+    case 0x2d4:	/* CONTROL_SEC_TAP */
+        return 0x8000007f;
+    case 0x2b4:	/* CONTROL_SEC_TEST */
+    case 0x2f0:	/* CONTROL_SEC_STATUS */
+    case 0x2f4:	/* CONTROL_SEC_ERR_STATUS */
+        /* Secure mode is not present on general-pusrpose device.  Outside
+         * secure mode these values cannot be read or written.  */
+        return 0;
+
+    case 0x2d8:	/* CONTROL_OCM_RAM_PERM */
+        return 0xff;
+    case 0x2dc:	/* CONTROL_OCM_PUB_RAM_ADD */
+    case 0x2e0:	/* CONTROL_EXT_SEC_RAM_START_ADD */
+    case 0x2e4:	/* CONTROL_EXT_SEC_RAM_STOP_ADD */
+        /* No secure mode so no Extended Secure RAM present.  */
+        return 0;
+
+    case 0x2f8:	/* CONTROL_STATUS */
+        /* Device Type => General-purpose */
+        return 0x0300;
+    case 0x2fc:	/* CONTROL_GENERAL_PURPOSE_STATUS */
+
+    case 0x300:	/* CONTROL_RPUB_KEY_H_0 */
+    case 0x304:	/* CONTROL_RPUB_KEY_H_1 */
+    case 0x308:	/* CONTROL_RPUB_KEY_H_2 */
+    case 0x30c:	/* CONTROL_RPUB_KEY_H_3 */
+        return 0xdecafbad;
+
+    case 0x310:	/* CONTROL_RAND_KEY_0 */
+    case 0x314:	/* CONTROL_RAND_KEY_1 */
+    case 0x318:	/* CONTROL_RAND_KEY_2 */
+    case 0x31c:	/* CONTROL_RAND_KEY_3 */
+    case 0x320:	/* CONTROL_CUST_KEY_0 */
+    case 0x324:	/* CONTROL_CUST_KEY_1 */
+    case 0x330:	/* CONTROL_TEST_KEY_0 */
+    case 0x334:	/* CONTROL_TEST_KEY_1 */
+    case 0x338:	/* CONTROL_TEST_KEY_2 */
+    case 0x33c:	/* CONTROL_TEST_KEY_3 */
+    case 0x340:	/* CONTROL_TEST_KEY_4 */
+    case 0x344:	/* CONTROL_TEST_KEY_5 */
+    case 0x348:	/* CONTROL_TEST_KEY_6 */
+    case 0x34c:	/* CONTROL_TEST_KEY_7 */
+    case 0x350:	/* CONTROL_TEST_KEY_8 */
+    case 0x354:	/* CONTROL_TEST_KEY_9 */
+        /* Can only be accessed in secure mode and when C_FieldAccEnable
+         * bit is set in CONTROL_SEC_CTRL.
+         * TODO: otherwise an interconnect access error is generated.  */
+        return 0;
+    }
+
+    OMAP_BAD_REG(addr);
+    return 0;
+}
+
+static void omap_sysctl_write8(void *opaque, hwaddr addr,
+                uint32_t value)
+{
+    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
+    int pad_offset, byte_offset;
+    int prev_value;
+
+    switch (addr) {
+    case 0x030 ... 0x140:	/* CONTROL_PADCONF - only used in the POP */
+        pad_offset = (addr - 0x30) >> 2;
+        byte_offset = (addr - 0x30) & (4 - 1);
+
+        prev_value = s->padconf[pad_offset];
+        prev_value &= ~(0xff << (byte_offset * 8));
+        prev_value |= ((value & 0x1f1f1f1f) << (byte_offset * 8)) & 0x1f1f1f1f;
+        s->padconf[pad_offset] = prev_value;
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        break;
+    }
+}
+
+static void omap_sysctl_write(void *opaque, hwaddr addr,
+                uint32_t value)
+{
+    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
+
+    switch (addr) {
+    case 0x000:	/* CONTROL_REVISION */
+    case 0x2a4:	/* CONTROL_MSUSPENDMUX_5 */
+    case 0x2c0:	/* CONTROL_PSA_VALUE */
+    case 0x2f8:	/* CONTROL_STATUS */
+    case 0x2fc:	/* CONTROL_GENERAL_PURPOSE_STATUS */
+    case 0x300:	/* CONTROL_RPUB_KEY_H_0 */
+    case 0x304:	/* CONTROL_RPUB_KEY_H_1 */
+    case 0x308:	/* CONTROL_RPUB_KEY_H_2 */
+    case 0x30c:	/* CONTROL_RPUB_KEY_H_3 */
+    case 0x310:	/* CONTROL_RAND_KEY_0 */
+    case 0x314:	/* CONTROL_RAND_KEY_1 */
+    case 0x318:	/* CONTROL_RAND_KEY_2 */
+    case 0x31c:	/* CONTROL_RAND_KEY_3 */
+    case 0x320:	/* CONTROL_CUST_KEY_0 */
+    case 0x324:	/* CONTROL_CUST_KEY_1 */
+    case 0x330:	/* CONTROL_TEST_KEY_0 */
+    case 0x334:	/* CONTROL_TEST_KEY_1 */
+    case 0x338:	/* CONTROL_TEST_KEY_2 */
+    case 0x33c:	/* CONTROL_TEST_KEY_3 */
+    case 0x340:	/* CONTROL_TEST_KEY_4 */
+    case 0x344:	/* CONTROL_TEST_KEY_5 */
+    case 0x348:	/* CONTROL_TEST_KEY_6 */
+    case 0x34c:	/* CONTROL_TEST_KEY_7 */
+    case 0x350:	/* CONTROL_TEST_KEY_8 */
+    case 0x354:	/* CONTROL_TEST_KEY_9 */
+        OMAP_RO_REG(addr);
+        return;
+
+    case 0x010:	/* CONTROL_SYSCONFIG */
+        s->sysconfig = value & 0x1e;
+        break;
+
+    case 0x030 ... 0x140:	/* CONTROL_PADCONF - only used in the POP */
+        /* XXX: should check constant bits */
+        s->padconf[(addr - 0x30) >> 2] = value & 0x1f1f1f1f;
+        break;
+
+    case 0x270:	/* CONTROL_DEBOBS */
+        s->obs = value & 0xff;
+        break;
+
+    case 0x274:	/* CONTROL_DEVCONF */
+        s->devconfig = value & 0xffffc7ff;
+        break;
+
+    case 0x28c:	/* CONTROL_EMU_SUPPORT */
+        break;
+
+    case 0x290:	/* CONTROL_MSUSPENDMUX_0 */
+        s->msuspendmux[0] = value & 0x3fffffff;
+        break;
+    case 0x294:	/* CONTROL_MSUSPENDMUX_1 */
+        s->msuspendmux[1] = value & 0x3fffffff;
+        break;
+    case 0x298:	/* CONTROL_MSUSPENDMUX_2 */
+        s->msuspendmux[2] = value & 0x3fffffff;
+        break;
+    case 0x29c:	/* CONTROL_MSUSPENDMUX_3 */
+        s->msuspendmux[3] = value & 0x3fffffff;
+        break;
+    case 0x2a0:	/* CONTROL_MSUSPENDMUX_4 */
+        s->msuspendmux[4] = value & 0x3fffffff;
+        break;
+
+    case 0x2b8:	/* CONTROL_PSA_CTRL */
+        s->psaconfig = value & 0x1c;
+        s->psaconfig |= (value & 0x20) ? 2 : 1;
+        break;
+    case 0x2bc:	/* CONTROL_PSA_CMD */
+        break;
+
+    case 0x2b0:	/* CONTROL_SEC_CTRL */
+    case 0x2b4:	/* CONTROL_SEC_TEST */
+    case 0x2d0:	/* CONTROL_SEC_EMU */
+    case 0x2d4:	/* CONTROL_SEC_TAP */
+    case 0x2d8:	/* CONTROL_OCM_RAM_PERM */
+    case 0x2dc:	/* CONTROL_OCM_PUB_RAM_ADD */
+    case 0x2e0:	/* CONTROL_EXT_SEC_RAM_START_ADD */
+    case 0x2e4:	/* CONTROL_EXT_SEC_RAM_STOP_ADD */
+    case 0x2f0:	/* CONTROL_SEC_STATUS */
+    case 0x2f4:	/* CONTROL_SEC_ERR_STATUS */
+        break;
+
+    default:
+        OMAP_BAD_REG(addr);
+        return;
+    }
+}
+
+static const MemoryRegionOps omap_sysctl_ops = {
+    .old_mmio = {
+        .read = {
+            omap_sysctl_read8,
+            omap_badwidth_read32,	/* TODO */
+            omap_sysctl_read,
+        },
+        .write = {
+            omap_sysctl_write8,
+            omap_badwidth_write32,	/* TODO */
+            omap_sysctl_write,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void omap_sysctl_reset(struct omap_sysctl_s *s)
+{
+    /* (power-on reset) */
+    s->sysconfig = 0;
+    s->obs = 0;
+    s->devconfig = 0x0c000000;
+    s->msuspendmux[0] = 0x00000000;
+    s->msuspendmux[1] = 0x00000000;
+    s->msuspendmux[2] = 0x00000000;
+    s->msuspendmux[3] = 0x00000000;
+    s->msuspendmux[4] = 0x00000000;
+    s->psaconfig = 1;
+
+    s->padconf[0x00] = 0x000f0f0f;
+    s->padconf[0x01] = 0x00000000;
+    s->padconf[0x02] = 0x00000000;
+    s->padconf[0x03] = 0x00000000;
+    s->padconf[0x04] = 0x00000000;
+    s->padconf[0x05] = 0x00000000;
+    s->padconf[0x06] = 0x00000000;
+    s->padconf[0x07] = 0x00000000;
+    s->padconf[0x08] = 0x08080800;
+    s->padconf[0x09] = 0x08080808;
+    s->padconf[0x0a] = 0x08080808;
+    s->padconf[0x0b] = 0x08080808;
+    s->padconf[0x0c] = 0x08080808;
+    s->padconf[0x0d] = 0x08080800;
+    s->padconf[0x0e] = 0x08080808;
+    s->padconf[0x0f] = 0x08080808;
+    s->padconf[0x10] = 0x18181808;	/* | 0x07070700 if SBoot3 */
+    s->padconf[0x11] = 0x18181818;	/* | 0x07070707 if SBoot3 */
+    s->padconf[0x12] = 0x18181818;	/* | 0x07070707 if SBoot3 */
+    s->padconf[0x13] = 0x18181818;	/* | 0x07070707 if SBoot3 */
+    s->padconf[0x14] = 0x18181818;	/* | 0x00070707 if SBoot3 */
+    s->padconf[0x15] = 0x18181818;
+    s->padconf[0x16] = 0x18181818;	/* | 0x07000000 if SBoot3 */
+    s->padconf[0x17] = 0x1f001f00;
+    s->padconf[0x18] = 0x1f1f1f1f;
+    s->padconf[0x19] = 0x00000000;
+    s->padconf[0x1a] = 0x1f180000;
+    s->padconf[0x1b] = 0x00001f1f;
+    s->padconf[0x1c] = 0x1f001f00;
+    s->padconf[0x1d] = 0x00000000;
+    s->padconf[0x1e] = 0x00000000;
+    s->padconf[0x1f] = 0x08000000;
+    s->padconf[0x20] = 0x08080808;
+    s->padconf[0x21] = 0x08080808;
+    s->padconf[0x22] = 0x0f080808;
+    s->padconf[0x23] = 0x0f0f0f0f;
+    s->padconf[0x24] = 0x000f0f0f;
+    s->padconf[0x25] = 0x1f1f1f0f;
+    s->padconf[0x26] = 0x080f0f1f;
+    s->padconf[0x27] = 0x070f1808;
+    s->padconf[0x28] = 0x0f070707;
+    s->padconf[0x29] = 0x000f0f1f;
+    s->padconf[0x2a] = 0x0f0f0f1f;
+    s->padconf[0x2b] = 0x08000000;
+    s->padconf[0x2c] = 0x0000001f;
+    s->padconf[0x2d] = 0x0f0f1f00;
+    s->padconf[0x2e] = 0x1f1f0f0f;
+    s->padconf[0x2f] = 0x0f1f1f1f;
+    s->padconf[0x30] = 0x0f0f0f0f;
+    s->padconf[0x31] = 0x0f1f0f1f;
+    s->padconf[0x32] = 0x0f0f0f0f;
+    s->padconf[0x33] = 0x0f1f0f1f;
+    s->padconf[0x34] = 0x1f1f0f0f;
+    s->padconf[0x35] = 0x0f0f1f1f;
+    s->padconf[0x36] = 0x0f0f1f0f;
+    s->padconf[0x37] = 0x0f0f0f0f;
+    s->padconf[0x38] = 0x1f18180f;
+    s->padconf[0x39] = 0x1f1f1f1f;
+    s->padconf[0x3a] = 0x00001f1f;
+    s->padconf[0x3b] = 0x00000000;
+    s->padconf[0x3c] = 0x00000000;
+    s->padconf[0x3d] = 0x0f0f0f0f;
+    s->padconf[0x3e] = 0x18000f0f;
+    s->padconf[0x3f] = 0x00070000;
+    s->padconf[0x40] = 0x00000707;
+    s->padconf[0x41] = 0x0f1f0700;
+    s->padconf[0x42] = 0x1f1f070f;
+    s->padconf[0x43] = 0x0008081f;
+    s->padconf[0x44] = 0x00000800;
+}
+
+static struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
+                omap_clk iclk, struct omap_mpu_state_s *mpu)
+{
+    struct omap_sysctl_s *s = (struct omap_sysctl_s *)
+            g_malloc0(sizeof(struct omap_sysctl_s));
+
+    s->mpu = mpu;
+    omap_sysctl_reset(s);
+
+    memory_region_init_io(&s->iomem, &omap_sysctl_ops, s, "omap.sysctl",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &s->iomem);
+
+    return s;
+}
+
+/* General chip reset */
+static void omap2_mpu_reset(void *opaque)
+{
+    struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
+
+    omap_dma_reset(mpu->dma);
+    omap_prcm_reset(mpu->prcm);
+    omap_sysctl_reset(mpu->sysc);
+    omap_gp_timer_reset(mpu->gptimer[0]);
+    omap_gp_timer_reset(mpu->gptimer[1]);
+    omap_gp_timer_reset(mpu->gptimer[2]);
+    omap_gp_timer_reset(mpu->gptimer[3]);
+    omap_gp_timer_reset(mpu->gptimer[4]);
+    omap_gp_timer_reset(mpu->gptimer[5]);
+    omap_gp_timer_reset(mpu->gptimer[6]);
+    omap_gp_timer_reset(mpu->gptimer[7]);
+    omap_gp_timer_reset(mpu->gptimer[8]);
+    omap_gp_timer_reset(mpu->gptimer[9]);
+    omap_gp_timer_reset(mpu->gptimer[10]);
+    omap_gp_timer_reset(mpu->gptimer[11]);
+    omap_synctimer_reset(mpu->synctimer);
+    omap_sdrc_reset(mpu->sdrc);
+    omap_gpmc_reset(mpu->gpmc);
+    omap_dss_reset(mpu->dss);
+    omap_uart_reset(mpu->uart[0]);
+    omap_uart_reset(mpu->uart[1]);
+    omap_uart_reset(mpu->uart[2]);
+    omap_mmc_reset(mpu->mmc);
+    omap_mcspi_reset(mpu->mcspi[0]);
+    omap_mcspi_reset(mpu->mcspi[1]);
+    cpu_reset(CPU(mpu->cpu));
+}
+
+static int omap2_validate_addr(struct omap_mpu_state_s *s,
+                hwaddr addr)
+{
+    return 1;
+}
+
+static const struct dma_irq_map omap2_dma_irq_map[] = {
+    { 0, OMAP_INT_24XX_SDMA_IRQ0 },
+    { 0, OMAP_INT_24XX_SDMA_IRQ1 },
+    { 0, OMAP_INT_24XX_SDMA_IRQ2 },
+    { 0, OMAP_INT_24XX_SDMA_IRQ3 },
+};
+
+struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
+                unsigned long sdram_size,
+                const char *core)
+{
+    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
+            g_malloc0(sizeof(struct omap_mpu_state_s));
+    qemu_irq *cpu_irq;
+    qemu_irq dma_irqs[4];
+    DriveInfo *dinfo;
+    int i;
+    SysBusDevice *busdev;
+    struct omap_target_agent_s *ta;
+
+    /* Core */
+    s->mpu_model = omap2420;
+    s->cpu = cpu_arm_init(core ?: "arm1136-r2");
+    if (s->cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    s->sdram_size = sdram_size;
+    s->sram_size = OMAP242X_SRAM_SIZE;
+
+    s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
+
+    /* Clocks */
+    omap_clk_init(s);
+
+    /* Memory-mapped stuff */
+    memory_region_init_ram(&s->sdram, "omap2.dram", s->sdram_size);
+    vmstate_register_ram_global(&s->sdram);
+    memory_region_add_subregion(sysmem, OMAP2_Q2_BASE, &s->sdram);
+    memory_region_init_ram(&s->sram, "omap2.sram", s->sram_size);
+    vmstate_register_ram_global(&s->sram);
+    memory_region_add_subregion(sysmem, OMAP2_SRAM_BASE, &s->sram);
+
+    s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54);
+
+    /* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */
+    cpu_irq = arm_pic_init_cpu(s->cpu);
+    s->ih[0] = qdev_create(NULL, "omap2-intc");
+    qdev_prop_set_uint8(s->ih[0], "revision", 0x21);
+    qdev_prop_set_ptr(s->ih[0], "fclk", omap_findclk(s, "mpu_intc_fclk"));
+    qdev_prop_set_ptr(s->ih[0], "iclk", omap_findclk(s, "mpu_intc_iclk"));
+    qdev_init_nofail(s->ih[0]);
+    busdev = SYS_BUS_DEVICE(s->ih[0]);
+    sysbus_connect_irq(busdev, 0, cpu_irq[ARM_PIC_CPU_IRQ]);
+    sysbus_connect_irq(busdev, 1, cpu_irq[ARM_PIC_CPU_FIQ]);
+    sysbus_mmio_map(busdev, 0, 0x480fe000);
+    s->prcm = omap_prcm_init(omap_l4tao(s->l4, 3),
+                             qdev_get_gpio_in(s->ih[0],
+                                              OMAP_INT_24XX_PRCM_MPU_IRQ),
+                             NULL, NULL, s);
+
+    s->sysc = omap_sysctl_init(omap_l4tao(s->l4, 1),
+                    omap_findclk(s, "omapctrl_iclk"), s);
+
+    for (i = 0; i < 4; i++) {
+        dma_irqs[i] = qdev_get_gpio_in(s->ih[omap2_dma_irq_map[i].ih],
+                                       omap2_dma_irq_map[i].intr);
+    }
+    s->dma = omap_dma4_init(0x48056000, dma_irqs, sysmem, s, 256, 32,
+                    omap_findclk(s, "sdma_iclk"),
+                    omap_findclk(s, "sdma_fclk"));
+    s->port->addr_valid = omap2_validate_addr;
+
+    /* Register SDRAM and SRAM ports for fast DMA transfers.  */
+    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sdram),
+                         OMAP2_Q2_BASE, s->sdram_size);
+    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sram),
+                         OMAP2_SRAM_BASE, s->sram_size);
+
+    s->uart[0] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 19),
+                                 qdev_get_gpio_in(s->ih[0],
+                                                  OMAP_INT_24XX_UART1_IRQ),
+                    omap_findclk(s, "uart1_fclk"),
+                    omap_findclk(s, "uart1_iclk"),
+                    s->drq[OMAP24XX_DMA_UART1_TX],
+                    s->drq[OMAP24XX_DMA_UART1_RX],
+                    "uart1",
+                    serial_hds[0]);
+    s->uart[1] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 20),
+                                 qdev_get_gpio_in(s->ih[0],
+                                                  OMAP_INT_24XX_UART2_IRQ),
+                    omap_findclk(s, "uart2_fclk"),
+                    omap_findclk(s, "uart2_iclk"),
+                    s->drq[OMAP24XX_DMA_UART2_TX],
+                    s->drq[OMAP24XX_DMA_UART2_RX],
+                    "uart2",
+                    serial_hds[0] ? serial_hds[1] : NULL);
+    s->uart[2] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 21),
+                                 qdev_get_gpio_in(s->ih[0],
+                                                  OMAP_INT_24XX_UART3_IRQ),
+                    omap_findclk(s, "uart3_fclk"),
+                    omap_findclk(s, "uart3_iclk"),
+                    s->drq[OMAP24XX_DMA_UART3_TX],
+                    s->drq[OMAP24XX_DMA_UART3_RX],
+                    "uart3",
+                    serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
+
+    s->gptimer[0] = omap_gp_timer_init(omap_l4ta(s->l4, 7),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER1),
+                    omap_findclk(s, "wu_gpt1_clk"),
+                    omap_findclk(s, "wu_l4_iclk"));
+    s->gptimer[1] = omap_gp_timer_init(omap_l4ta(s->l4, 8),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER2),
+                    omap_findclk(s, "core_gpt2_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[2] = omap_gp_timer_init(omap_l4ta(s->l4, 22),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER3),
+                    omap_findclk(s, "core_gpt3_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[3] = omap_gp_timer_init(omap_l4ta(s->l4, 23),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER4),
+                    omap_findclk(s, "core_gpt4_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[4] = omap_gp_timer_init(omap_l4ta(s->l4, 24),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER5),
+                    omap_findclk(s, "core_gpt5_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[5] = omap_gp_timer_init(omap_l4ta(s->l4, 25),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER6),
+                    omap_findclk(s, "core_gpt6_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[6] = omap_gp_timer_init(omap_l4ta(s->l4, 26),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER7),
+                    omap_findclk(s, "core_gpt7_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[7] = omap_gp_timer_init(omap_l4ta(s->l4, 27),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER8),
+                    omap_findclk(s, "core_gpt8_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[8] = omap_gp_timer_init(omap_l4ta(s->l4, 28),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER9),
+                    omap_findclk(s, "core_gpt9_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[9] = omap_gp_timer_init(omap_l4ta(s->l4, 29),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER10),
+                    omap_findclk(s, "core_gpt10_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[10] = omap_gp_timer_init(omap_l4ta(s->l4, 30),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER11),
+                    omap_findclk(s, "core_gpt11_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+    s->gptimer[11] = omap_gp_timer_init(omap_l4ta(s->l4, 31),
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER12),
+                    omap_findclk(s, "core_gpt12_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+
+    omap_tap_init(omap_l4ta(s->l4, 2), s);
+
+    s->synctimer = omap_synctimer_init(omap_l4tao(s->l4, 2), s,
+                    omap_findclk(s, "clk32-kHz"),
+                    omap_findclk(s, "core_l4_iclk"));
+
+    s->i2c[0] = qdev_create(NULL, "omap_i2c");
+    qdev_prop_set_uint8(s->i2c[0], "revision", 0x34);
+    qdev_prop_set_ptr(s->i2c[0], "iclk", omap_findclk(s, "i2c1.iclk"));
+    qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "i2c1.fclk"));
+    qdev_init_nofail(s->i2c[0]);
+    busdev = SYS_BUS_DEVICE(s->i2c[0]);
+    sysbus_connect_irq(busdev, 0,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C1_IRQ));
+    sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C1_TX]);
+    sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C1_RX]);
+    sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 5), 0));
+
+    s->i2c[1] = qdev_create(NULL, "omap_i2c");
+    qdev_prop_set_uint8(s->i2c[1], "revision", 0x34);
+    qdev_prop_set_ptr(s->i2c[1], "iclk", omap_findclk(s, "i2c2.iclk"));
+    qdev_prop_set_ptr(s->i2c[1], "fclk", omap_findclk(s, "i2c2.fclk"));
+    qdev_init_nofail(s->i2c[1]);
+    busdev = SYS_BUS_DEVICE(s->i2c[1]);
+    sysbus_connect_irq(busdev, 0,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C2_IRQ));
+    sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C2_TX]);
+    sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C2_RX]);
+    sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 6), 0));
+
+    s->gpio = qdev_create(NULL, "omap2-gpio");
+    qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
+    qdev_prop_set_ptr(s->gpio, "iclk", omap_findclk(s, "gpio_iclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk0", omap_findclk(s, "gpio1_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk1", omap_findclk(s, "gpio2_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk2", omap_findclk(s, "gpio3_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk3", omap_findclk(s, "gpio4_dbclk"));
+    if (s->mpu_model == omap2430) {
+        qdev_prop_set_ptr(s->gpio, "fclk4", omap_findclk(s, "gpio5_dbclk"));
+    }
+    qdev_init_nofail(s->gpio);
+    busdev = SYS_BUS_DEVICE(s->gpio);
+    sysbus_connect_irq(busdev, 0,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK1));
+    sysbus_connect_irq(busdev, 3,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK2));
+    sysbus_connect_irq(busdev, 6,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK3));
+    sysbus_connect_irq(busdev, 9,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK4));
+    if (s->mpu_model == omap2430) {
+        sysbus_connect_irq(busdev, 12,
+                           qdev_get_gpio_in(s->ih[0],
+                                            OMAP_INT_243X_GPIO_BANK5));
+    }
+    ta = omap_l4ta(s->l4, 3);
+    sysbus_mmio_map(busdev, 0, omap_l4_region_base(ta, 1));
+    sysbus_mmio_map(busdev, 1, omap_l4_region_base(ta, 0));
+    sysbus_mmio_map(busdev, 2, omap_l4_region_base(ta, 2));
+    sysbus_mmio_map(busdev, 3, omap_l4_region_base(ta, 4));
+    sysbus_mmio_map(busdev, 4, omap_l4_region_base(ta, 5));
+
+    s->sdrc = omap_sdrc_init(sysmem, 0x68009000);
+    s->gpmc = omap_gpmc_init(s, 0x6800a000,
+                             qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPMC_IRQ),
+                             s->drq[OMAP24XX_DMA_GPMC]);
+
+    dinfo = drive_get(IF_SD, 0, 0);
+    if (!dinfo) {
+        fprintf(stderr, "qemu: missing SecureDigital device\n");
+        exit(1);
+    }
+    s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9), dinfo->bdrv,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MMC_IRQ),
+                    &s->drq[OMAP24XX_DMA_MMC1_TX],
+                    omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
+
+    s->mcspi[0] = omap_mcspi_init(omap_l4ta(s->l4, 35), 4,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI1_IRQ),
+                    &s->drq[OMAP24XX_DMA_SPI1_TX0],
+                    omap_findclk(s, "spi1_fclk"),
+                    omap_findclk(s, "spi1_iclk"));
+    s->mcspi[1] = omap_mcspi_init(omap_l4ta(s->l4, 36), 2,
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI2_IRQ),
+                    &s->drq[OMAP24XX_DMA_SPI2_TX0],
+                    omap_findclk(s, "spi2_fclk"),
+                    omap_findclk(s, "spi2_iclk"));
+
+    s->dss = omap_dss_init(omap_l4ta(s->l4, 10), sysmem, 0x68000800,
+                    /* XXX wire M_IRQ_25, D_L2_IRQ_30 and I_IRQ_13 together */
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_DSS_IRQ),
+                           s->drq[OMAP24XX_DMA_DSS],
+                    omap_findclk(s, "dss_clk1"), omap_findclk(s, "dss_clk2"),
+                    omap_findclk(s, "dss_54m_clk"),
+                    omap_findclk(s, "dss_l3_iclk"),
+                    omap_findclk(s, "dss_l4_iclk"));
+
+    omap_sti_init(omap_l4ta(s->l4, 18), sysmem, 0x54000000,
+                  qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_STI),
+                  omap_findclk(s, "emul_ck"),
+                    serial_hds[0] && serial_hds[1] && serial_hds[2] ?
+                    serial_hds[3] : NULL);
+
+    s->eac = omap_eac_init(omap_l4ta(s->l4, 32),
+                           qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_EAC_IRQ),
+                    /* Ten consecutive lines */
+                    &s->drq[OMAP24XX_DMA_EAC_AC_RD],
+                    omap_findclk(s, "func_96m_clk"),
+                    omap_findclk(s, "core_l4_iclk"));
+
+    /* All register mappings (includin those not currenlty implemented):
+     * SystemControlMod	48000000 - 48000fff
+     * SystemControlL4	48001000 - 48001fff
+     * 32kHz Timer Mod	48004000 - 48004fff
+     * 32kHz Timer L4	48005000 - 48005fff
+     * PRCM ModA	48008000 - 480087ff
+     * PRCM ModB	48008800 - 48008fff
+     * PRCM L4		48009000 - 48009fff
+     * TEST-BCM Mod	48012000 - 48012fff
+     * TEST-BCM L4	48013000 - 48013fff
+     * TEST-TAP Mod	48014000 - 48014fff
+     * TEST-TAP L4	48015000 - 48015fff
+     * GPIO1 Mod	48018000 - 48018fff
+     * GPIO Top		48019000 - 48019fff
+     * GPIO2 Mod	4801a000 - 4801afff
+     * GPIO L4		4801b000 - 4801bfff
+     * GPIO3 Mod	4801c000 - 4801cfff
+     * GPIO4 Mod	4801e000 - 4801efff
+     * WDTIMER1 Mod	48020000 - 48010fff
+     * WDTIMER Top	48021000 - 48011fff
+     * WDTIMER2 Mod	48022000 - 48012fff
+     * WDTIMER L4	48023000 - 48013fff
+     * WDTIMER3 Mod	48024000 - 48014fff
+     * WDTIMER3 L4	48025000 - 48015fff
+     * WDTIMER4 Mod	48026000 - 48016fff
+     * WDTIMER4 L4	48027000 - 48017fff
+     * GPTIMER1 Mod	48028000 - 48018fff
+     * GPTIMER1 L4	48029000 - 48019fff
+     * GPTIMER2 Mod	4802a000 - 4801afff
+     * GPTIMER2 L4	4802b000 - 4801bfff
+     * L4-Config AP	48040000 - 480407ff
+     * L4-Config IP	48040800 - 48040fff
+     * L4-Config LA	48041000 - 48041fff
+     * ARM11ETB Mod	48048000 - 48049fff
+     * ARM11ETB L4	4804a000 - 4804afff
+     * DISPLAY Top	48050000 - 480503ff
+     * DISPLAY DISPC	48050400 - 480507ff
+     * DISPLAY RFBI	48050800 - 48050bff
+     * DISPLAY VENC	48050c00 - 48050fff
+     * DISPLAY L4	48051000 - 48051fff
+     * CAMERA Top	48052000 - 480523ff
+     * CAMERA core	48052400 - 480527ff
+     * CAMERA DMA	48052800 - 48052bff
+     * CAMERA MMU	48052c00 - 48052fff
+     * CAMERA L4	48053000 - 48053fff
+     * SDMA Mod		48056000 - 48056fff
+     * SDMA L4		48057000 - 48057fff
+     * SSI Top		48058000 - 48058fff
+     * SSI GDD		48059000 - 48059fff
+     * SSI Port1	4805a000 - 4805afff
+     * SSI Port2	4805b000 - 4805bfff
+     * SSI L4		4805c000 - 4805cfff
+     * USB Mod		4805e000 - 480fefff
+     * USB L4		4805f000 - 480fffff
+     * WIN_TRACER1 Mod	48060000 - 48060fff
+     * WIN_TRACER1 L4	48061000 - 48061fff
+     * WIN_TRACER2 Mod	48062000 - 48062fff
+     * WIN_TRACER2 L4	48063000 - 48063fff
+     * WIN_TRACER3 Mod	48064000 - 48064fff
+     * WIN_TRACER3 L4	48065000 - 48065fff
+     * WIN_TRACER4 Top	48066000 - 480660ff
+     * WIN_TRACER4 ETT	48066100 - 480661ff
+     * WIN_TRACER4 WT	48066200 - 480662ff
+     * WIN_TRACER4 L4	48067000 - 48067fff
+     * XTI Mod		48068000 - 48068fff
+     * XTI L4		48069000 - 48069fff
+     * UART1 Mod	4806a000 - 4806afff
+     * UART1 L4		4806b000 - 4806bfff
+     * UART2 Mod	4806c000 - 4806cfff
+     * UART2 L4		4806d000 - 4806dfff
+     * UART3 Mod	4806e000 - 4806efff
+     * UART3 L4		4806f000 - 4806ffff
+     * I2C1 Mod		48070000 - 48070fff
+     * I2C1 L4		48071000 - 48071fff
+     * I2C2 Mod		48072000 - 48072fff
+     * I2C2 L4		48073000 - 48073fff
+     * McBSP1 Mod	48074000 - 48074fff
+     * McBSP1 L4	48075000 - 48075fff
+     * McBSP2 Mod	48076000 - 48076fff
+     * McBSP2 L4	48077000 - 48077fff
+     * GPTIMER3 Mod	48078000 - 48078fff
+     * GPTIMER3 L4	48079000 - 48079fff
+     * GPTIMER4 Mod	4807a000 - 4807afff
+     * GPTIMER4 L4	4807b000 - 4807bfff
+     * GPTIMER5 Mod	4807c000 - 4807cfff
+     * GPTIMER5 L4	4807d000 - 4807dfff
+     * GPTIMER6 Mod	4807e000 - 4807efff
+     * GPTIMER6 L4	4807f000 - 4807ffff
+     * GPTIMER7 Mod	48080000 - 48080fff
+     * GPTIMER7 L4	48081000 - 48081fff
+     * GPTIMER8 Mod	48082000 - 48082fff
+     * GPTIMER8 L4	48083000 - 48083fff
+     * GPTIMER9 Mod	48084000 - 48084fff
+     * GPTIMER9 L4	48085000 - 48085fff
+     * GPTIMER10 Mod	48086000 - 48086fff
+     * GPTIMER10 L4	48087000 - 48087fff
+     * GPTIMER11 Mod	48088000 - 48088fff
+     * GPTIMER11 L4	48089000 - 48089fff
+     * GPTIMER12 Mod	4808a000 - 4808afff
+     * GPTIMER12 L4	4808b000 - 4808bfff
+     * EAC Mod		48090000 - 48090fff
+     * EAC L4		48091000 - 48091fff
+     * FAC Mod		48092000 - 48092fff
+     * FAC L4		48093000 - 48093fff
+     * MAILBOX Mod	48094000 - 48094fff
+     * MAILBOX L4	48095000 - 48095fff
+     * SPI1 Mod		48098000 - 48098fff
+     * SPI1 L4		48099000 - 48099fff
+     * SPI2 Mod		4809a000 - 4809afff
+     * SPI2 L4		4809b000 - 4809bfff
+     * MMC/SDIO Mod	4809c000 - 4809cfff
+     * MMC/SDIO L4	4809d000 - 4809dfff
+     * MS_PRO Mod	4809e000 - 4809efff
+     * MS_PRO L4	4809f000 - 4809ffff
+     * RNG Mod		480a0000 - 480a0fff
+     * RNG L4		480a1000 - 480a1fff
+     * DES3DES Mod	480a2000 - 480a2fff
+     * DES3DES L4	480a3000 - 480a3fff
+     * SHA1MD5 Mod	480a4000 - 480a4fff
+     * SHA1MD5 L4	480a5000 - 480a5fff
+     * AES Mod		480a6000 - 480a6fff
+     * AES L4		480a7000 - 480a7fff
+     * PKA Mod		480a8000 - 480a9fff
+     * PKA L4		480aa000 - 480aafff
+     * MG Mod		480b0000 - 480b0fff
+     * MG L4		480b1000 - 480b1fff
+     * HDQ/1-wire Mod	480b2000 - 480b2fff
+     * HDQ/1-wire L4	480b3000 - 480b3fff
+     * MPU interrupt	480fe000 - 480fefff
+     * STI channel base	54000000 - 5400ffff
+     * IVA RAM		5c000000 - 5c01ffff
+     * IVA ROM		5c020000 - 5c027fff
+     * IMG_BUF_A	5c040000 - 5c040fff
+     * IMG_BUF_B	5c042000 - 5c042fff
+     * VLCDS		5c048000 - 5c0487ff
+     * IMX_COEF		5c049000 - 5c04afff
+     * IMX_CMD		5c051000 - 5c051fff
+     * VLCDQ		5c053000 - 5c0533ff
+     * VLCDH		5c054000 - 5c054fff
+     * SEQ_CMD		5c055000 - 5c055fff
+     * IMX_REG		5c056000 - 5c0560ff
+     * VLCD_REG		5c056100 - 5c0561ff
+     * SEQ_REG		5c056200 - 5c0562ff
+     * IMG_BUF_REG	5c056300 - 5c0563ff
+     * SEQIRQ_REG	5c056400 - 5c0564ff
+     * OCP_REG		5c060000 - 5c060fff
+     * SYSC_REG		5c070000 - 5c070fff
+     * MMU_REG		5d000000 - 5d000fff
+     * sDMA R		68000400 - 680005ff
+     * sDMA W		68000600 - 680007ff
+     * Display Control	68000800 - 680009ff
+     * DSP subsystem	68000a00 - 68000bff
+     * MPU subsystem	68000c00 - 68000dff
+     * IVA subsystem	68001000 - 680011ff
+     * USB		68001200 - 680013ff
+     * Camera		68001400 - 680015ff
+     * VLYNQ (firewall)	68001800 - 68001bff
+     * VLYNQ		68001e00 - 68001fff
+     * SSI		68002000 - 680021ff
+     * L4		68002400 - 680025ff
+     * DSP (firewall)	68002800 - 68002bff
+     * DSP subsystem	68002e00 - 68002fff
+     * IVA (firewall)	68003000 - 680033ff
+     * IVA		68003600 - 680037ff
+     * GFX		68003a00 - 68003bff
+     * CMDWR emulation	68003c00 - 68003dff
+     * SMS		68004000 - 680041ff
+     * OCM		68004200 - 680043ff
+     * GPMC		68004400 - 680045ff
+     * RAM (firewall)	68005000 - 680053ff
+     * RAM (err login)	68005400 - 680057ff
+     * ROM (firewall)	68005800 - 68005bff
+     * ROM (err login)	68005c00 - 68005fff
+     * GPMC (firewall)	68006000 - 680063ff
+     * GPMC (err login)	68006400 - 680067ff
+     * SMS (err login)	68006c00 - 68006fff
+     * SMS registers	68008000 - 68008fff
+     * SDRC registers	68009000 - 68009fff
+     * GPMC registers	6800a000   6800afff
+     */
+
+    qemu_register_reset(omap2_mpu_reset, s);
+
+    return s;
+}
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
new file mode 100644
index 0000000..c0f50c9
--- /dev/null
+++ b/hw/arm/pxa2xx.c
@@ -0,0 +1,2291 @@
+/*
+ * Intel XScale PXA255/270 processor support.
+ *
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Written by Andrzej Zaborowski <balrog at zabor.org>
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/pxa.h"
+#include "sysemu/sysemu.h"
+#include "hw/serial.h"
+#include "hw/i2c.h"
+#include "hw/ssi.h"
+#include "char/char.h"
+#include "sysemu/blockdev.h"
+
+static struct {
+    hwaddr io_base;
+    int irqn;
+} pxa255_serial[] = {
+    { 0x40100000, PXA2XX_PIC_FFUART },
+    { 0x40200000, PXA2XX_PIC_BTUART },
+    { 0x40700000, PXA2XX_PIC_STUART },
+    { 0x41600000, PXA25X_PIC_HWUART },
+    { 0, 0 }
+}, pxa270_serial[] = {
+    { 0x40100000, PXA2XX_PIC_FFUART },
+    { 0x40200000, PXA2XX_PIC_BTUART },
+    { 0x40700000, PXA2XX_PIC_STUART },
+    { 0, 0 }
+};
+
+typedef struct PXASSPDef {
+    hwaddr io_base;
+    int irqn;
+} PXASSPDef;
+
+#if 0
+static PXASSPDef pxa250_ssp[] = {
+    { 0x41000000, PXA2XX_PIC_SSP },
+    { 0, 0 }
+};
+#endif
+
+static PXASSPDef pxa255_ssp[] = {
+    { 0x41000000, PXA2XX_PIC_SSP },
+    { 0x41400000, PXA25X_PIC_NSSP },
+    { 0, 0 }
+};
+
+#if 0
+static PXASSPDef pxa26x_ssp[] = {
+    { 0x41000000, PXA2XX_PIC_SSP },
+    { 0x41400000, PXA25X_PIC_NSSP },
+    { 0x41500000, PXA26X_PIC_ASSP },
+    { 0, 0 }
+};
+#endif
+
+static PXASSPDef pxa27x_ssp[] = {
+    { 0x41000000, PXA2XX_PIC_SSP },
+    { 0x41700000, PXA27X_PIC_SSP2 },
+    { 0x41900000, PXA2XX_PIC_SSP3 },
+    { 0, 0 }
+};
+
+#define PMCR	0x00	/* Power Manager Control register */
+#define PSSR	0x04	/* Power Manager Sleep Status register */
+#define PSPR	0x08	/* Power Manager Scratch-Pad register */
+#define PWER	0x0c	/* Power Manager Wake-Up Enable register */
+#define PRER	0x10	/* Power Manager Rising-Edge Detect Enable register */
+#define PFER	0x14	/* Power Manager Falling-Edge Detect Enable register */
+#define PEDR	0x18	/* Power Manager Edge-Detect Status register */
+#define PCFR	0x1c	/* Power Manager General Configuration register */
+#define PGSR0	0x20	/* Power Manager GPIO Sleep-State register 0 */
+#define PGSR1	0x24	/* Power Manager GPIO Sleep-State register 1 */
+#define PGSR2	0x28	/* Power Manager GPIO Sleep-State register 2 */
+#define PGSR3	0x2c	/* Power Manager GPIO Sleep-State register 3 */
+#define RCSR	0x30	/* Reset Controller Status register */
+#define PSLR	0x34	/* Power Manager Sleep Configuration register */
+#define PTSR	0x38	/* Power Manager Standby Configuration register */
+#define PVCR	0x40	/* Power Manager Voltage Change Control register */
+#define PUCR	0x4c	/* Power Manager USIM Card Control/Status register */
+#define PKWR	0x50	/* Power Manager Keyboard Wake-Up Enable register */
+#define PKSR	0x54	/* Power Manager Keyboard Level-Detect Status */
+#define PCMD0	0x80	/* Power Manager I2C Command register File 0 */
+#define PCMD31	0xfc	/* Power Manager I2C Command register File 31 */
+
+static uint64_t pxa2xx_pm_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    PXA2xxState *s = (PXA2xxState *) opaque;
+
+    switch (addr) {
+    case PMCR ... PCMD31:
+        if (addr & 3)
+            goto fail;
+
+        return s->pm_regs[addr >> 2];
+    default:
+    fail:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_pm_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    PXA2xxState *s = (PXA2xxState *) opaque;
+
+    switch (addr) {
+    case PMCR:
+        /* Clear the write-one-to-clear bits... */
+        s->pm_regs[addr >> 2] &= ~(value & 0x2a);
+        /* ...and set the plain r/w bits */
+        s->pm_regs[addr >> 2] &= ~0x15;
+        s->pm_regs[addr >> 2] |= value & 0x15;
+        break;
+
+    case PSSR:	/* Read-clean registers */
+    case RCSR:
+    case PKSR:
+        s->pm_regs[addr >> 2] &= ~value;
+        break;
+
+    default:	/* Read-write registers */
+        if (!(addr & 3)) {
+            s->pm_regs[addr >> 2] = value;
+            break;
+        }
+
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+}
+
+static const MemoryRegionOps pxa2xx_pm_ops = {
+    .read = pxa2xx_pm_read,
+    .write = pxa2xx_pm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+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 */
+#define OSCC	0x08	/* Oscillator Configuration register */
+#define CCSR	0x0c	/* Core Clock Status register */
+
+static uint64_t pxa2xx_cm_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    PXA2xxState *s = (PXA2xxState *) opaque;
+
+    switch (addr) {
+    case CCCR:
+    case CKEN:
+    case OSCC:
+        return s->cm_regs[addr >> 2];
+
+    case CCSR:
+        return s->cm_regs[CCCR >> 2] | (3 << 28);
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_cm_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    PXA2xxState *s = (PXA2xxState *) opaque;
+
+    switch (addr) {
+    case CCCR:
+    case CKEN:
+        s->cm_regs[addr >> 2] = value;
+        break;
+
+    case OSCC:
+        s->cm_regs[addr >> 2] &= ~0x6c;
+        s->cm_regs[addr >> 2] |= value & 0x6e;
+        if ((value >> 1) & 1)			/* OON */
+            s->cm_regs[addr >> 2] |= 1 << 0;	/* Oscillator is now stable */
+        break;
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+}
+
+static const MemoryRegionOps pxa2xx_cm_ops = {
+    .read = pxa2xx_cm_read,
+    .write = pxa2xx_cm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+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 int pxa2xx_clkcfg_read(CPUARMState *env, const ARMCPRegInfo *ri,
+                              uint64_t *value)
+{
+    PXA2xxState *s = (PXA2xxState *)ri->opaque;
+    *value = s->clkcfg;
+    return 0;
+}
+
+static int pxa2xx_clkcfg_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                               uint64_t value)
+{
+    PXA2xxState *s = (PXA2xxState *)ri->opaque;
+    s->clkcfg = value & 0xf;
+    if (value & 2) {
+        printf("%s: CPU frequency change attempt\n", __func__);
+    }
+    return 0;
+}
+
+static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                                uint64_t value)
+{
+    PXA2xxState *s = (PXA2xxState *)ri->opaque;
+    static const char *pwrmode[8] = {
+        "Normal", "Idle", "Deep-idle", "Standby",
+        "Sleep", "reserved (!)", "reserved (!)", "Deep-sleep",
+    };
+
+    if (value & 8) {
+        printf("%s: CPU voltage change attempt\n", __func__);
+    }
+    switch (value & 7) {
+    case 0:
+        /* Do nothing */
+        break;
+
+    case 1:
+        /* Idle */
+        if (!(s->cm_regs[CCCR >> 2] & (1 << 31))) { /* CPDIS */
+            cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
+            break;
+        }
+        /* Fall through.  */
+
+    case 2:
+        /* Deep-Idle */
+        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
+        s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
+        goto message;
+
+    case 3:
+        s->cpu->env.uncached_cpsr =
+            ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
+        s->cpu->env.cp15.c1_sys = 0;
+        s->cpu->env.cp15.c1_coproc = 0;
+        s->cpu->env.cp15.c2_base0 = 0;
+        s->cpu->env.cp15.c3 = 0;
+        s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */
+        s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
+
+        /*
+         * The scratch-pad register is almost universally used
+         * for storing the return address on suspend.  For the
+         * lack of a resuming bootloader, perform a jump
+         * directly to that address.
+         */
+        memset(s->cpu->env.regs, 0, 4 * 15);
+        s->cpu->env.regs[15] = s->pm_regs[PSPR >> 2];
+
+#if 0
+        buffer = 0xe59ff000; /* ldr     pc, [pc, #0] */
+        cpu_physical_memory_write(0, &buffer, 4);
+        buffer = s->pm_regs[PSPR >> 2];
+        cpu_physical_memory_write(8, &buffer, 4);
+#endif
+
+        /* Suspend */
+        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
+
+        goto message;
+
+    default:
+    message:
+        printf("%s: machine entered %s mode\n", __func__,
+               pwrmode[value & 7]);
+    }
+
+    return 0;
+}
+
+static int pxa2xx_cppmnc_read(CPUARMState *env, const ARMCPRegInfo *ri,
+                              uint64_t *value)
+{
+    PXA2xxState *s = (PXA2xxState *)ri->opaque;
+    *value = s->pmnc;
+    return 0;
+}
+
+static int pxa2xx_cppmnc_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                               uint64_t value)
+{
+    PXA2xxState *s = (PXA2xxState *)ri->opaque;
+    s->pmnc = value;
+    return 0;
+}
+
+static int pxa2xx_cpccnt_read(CPUARMState *env, const ARMCPRegInfo *ri,
+                              uint64_t *value)
+{
+    PXA2xxState *s = (PXA2xxState *)ri->opaque;
+    if (s->pmnc & 1) {
+        *value = qemu_get_clock_ns(vm_clock);
+    } else {
+        *value = 0;
+    }
+    return 0;
+}
+
+static const ARMCPRegInfo pxa_cp_reginfo[] = {
+    /* cp14 crm==1: perf registers */
+    { .name = "CPPMNC", .cp = 14, .crn = 0, .crm = 1, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW,
+      .readfn = pxa2xx_cppmnc_read, .writefn = pxa2xx_cppmnc_write },
+    { .name = "CPCCNT", .cp = 14, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW,
+      .readfn = pxa2xx_cpccnt_read, .writefn = arm_cp_write_ignore },
+    { .name = "CPINTEN", .cp = 14, .crn = 4, .crm = 1, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "CPFLAG", .cp = 14, .crn = 5, .crm = 1, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "CPEVTSEL", .cp = 14, .crn = 8, .crm = 1, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    /* cp14 crm==2: performance count registers */
+    { .name = "CPPMN0", .cp = 14, .crn = 0, .crm = 2, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "CPPMN1", .cp = 14, .crn = 1, .crm = 2, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "CPPMN2", .cp = 14, .crn = 2, .crm = 2, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "CPPMN3", .cp = 14, .crn = 2, .crm = 3, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    /* cp14 crn==6: CLKCFG */
+    { .name = "CLKCFG", .cp = 14, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW,
+      .readfn = pxa2xx_clkcfg_read, .writefn = pxa2xx_clkcfg_write },
+    /* cp14 crn==7: PWRMODE */
+    { .name = "PWRMODE", .cp = 14, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW,
+      .readfn = arm_cp_read_zero, .writefn = pxa2xx_pwrmode_write },
+    REGINFO_SENTINEL
+};
+
+static void pxa2xx_setup_cp14(PXA2xxState *s)
+{
+    define_arm_cp_regs_with_opaque(s->cpu, pxa_cp_reginfo, s);
+}
+
+#define MDCNFG		0x00	/* SDRAM Configuration register */
+#define MDREFR		0x04	/* SDRAM Refresh Control register */
+#define MSC0		0x08	/* Static Memory Control register 0 */
+#define MSC1		0x0c	/* Static Memory Control register 1 */
+#define MSC2		0x10	/* Static Memory Control register 2 */
+#define MECR		0x14	/* Expansion Memory Bus Config register */
+#define SXCNFG		0x1c	/* Synchronous Static Memory Config register */
+#define MCMEM0		0x28	/* PC Card Memory Socket 0 Timing register */
+#define MCMEM1		0x2c	/* PC Card Memory Socket 1 Timing register */
+#define MCATT0		0x30	/* PC Card Attribute Socket 0 register */
+#define MCATT1		0x34	/* PC Card Attribute Socket 1 register */
+#define MCIO0		0x38	/* PC Card I/O Socket 0 Timing register */
+#define MCIO1		0x3c	/* PC Card I/O Socket 1 Timing register */
+#define MDMRS		0x40	/* SDRAM Mode Register Set Config register */
+#define BOOT_DEF	0x44	/* Boot-time Default Configuration register */
+#define ARB_CNTL	0x48	/* Arbiter Control register */
+#define BSCNTR0		0x4c	/* Memory Buffer Strength Control register 0 */
+#define BSCNTR1		0x50	/* Memory Buffer Strength Control register 1 */
+#define LCDBSCNTR	0x54	/* LCD Buffer Strength Control register */
+#define MDMRSLP		0x58	/* Low Power SDRAM Mode Set Config register */
+#define BSCNTR2		0x5c	/* Memory Buffer Strength Control register 2 */
+#define BSCNTR3		0x60	/* Memory Buffer Strength Control register 3 */
+#define SA1110		0x64	/* SA-1110 Memory Compatibility register */
+
+static uint64_t pxa2xx_mm_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    PXA2xxState *s = (PXA2xxState *) opaque;
+
+    switch (addr) {
+    case MDCNFG ... SA1110:
+        if ((addr & 3) == 0)
+            return s->mm_regs[addr >> 2];
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_mm_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    PXA2xxState *s = (PXA2xxState *) opaque;
+
+    switch (addr) {
+    case MDCNFG ... SA1110:
+        if ((addr & 3) == 0) {
+            s->mm_regs[addr >> 2] = value;
+            break;
+        }
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+}
+
+static const MemoryRegionOps pxa2xx_mm_ops = {
+    .read = pxa2xx_mm_read,
+    .write = pxa2xx_mm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+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 {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq irq;
+    int enable;
+    SSIBus *bus;
+
+    uint32_t sscr[2];
+    uint32_t sspsp;
+    uint32_t ssto;
+    uint32_t ssitr;
+    uint32_t sssr;
+    uint8_t sstsa;
+    uint8_t ssrsa;
+    uint8_t ssacd;
+
+    uint32_t rx_fifo[16];
+    int rx_level;
+    int rx_start;
+} PXA2xxSSPState;
+
+#define SSCR0	0x00	/* SSP Control register 0 */
+#define SSCR1	0x04	/* SSP Control register 1 */
+#define SSSR	0x08	/* SSP Status register */
+#define SSITR	0x0c	/* SSP Interrupt Test register */
+#define SSDR	0x10	/* SSP Data register */
+#define SSTO	0x28	/* SSP Time-Out register */
+#define SSPSP	0x2c	/* SSP Programmable Serial Protocol register */
+#define SSTSA	0x30	/* SSP TX Time Slot Active register */
+#define SSRSA	0x34	/* SSP RX Time Slot Active register */
+#define SSTSS	0x38	/* SSP Time Slot Status register */
+#define SSACD	0x3c	/* SSP Audio Clock Divider 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_RIM	(1 << 22)
+#define SSCR0_TIM	(1 << 23)
+#define SSCR0_MOD	(1 << 31)
+#define SSCR0_DSS(x)	(((((x) >> 16) & 0x10) | ((x) & 0xf)) + 1)
+#define SSCR1_RIE	(1 << 0)
+#define SSCR1_TIE	(1 << 1)
+#define SSCR1_LBM	(1 << 2)
+#define SSCR1_MWDS	(1 << 5)
+#define SSCR1_TFT(x)	((((x) >> 6) & 0xf) + 1)
+#define SSCR1_RFT(x)	((((x) >> 10) & 0xf) + 1)
+#define SSCR1_EFWR	(1 << 14)
+#define SSCR1_PINTE	(1 << 18)
+#define SSCR1_TINTE	(1 << 19)
+#define SSCR1_RSRE	(1 << 20)
+#define SSCR1_TSRE	(1 << 21)
+#define SSCR1_EBCEI	(1 << 29)
+#define SSITR_INT	(7 << 5)
+#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_PINT	(1 << 18)
+#define SSSR_TINT	(1 << 19)
+#define SSSR_EOC	(1 << 20)
+#define SSSR_TUR	(1 << 21)
+#define SSSR_BCE	(1 << 23)
+#define SSSR_RW		0x00bc0080
+
+static void pxa2xx_ssp_int_update(PXA2xxSSPState *s)
+{
+    int level = 0;
+
+    level |= s->ssitr & SSITR_INT;
+    level |= (s->sssr & SSSR_BCE)  &&  (s->sscr[1] & SSCR1_EBCEI);
+    level |= (s->sssr & SSSR_TUR)  && !(s->sscr[0] & SSCR0_TIM);
+    level |= (s->sssr & SSSR_EOC)  &&  (s->sssr & (SSSR_TINT | SSSR_PINT));
+    level |= (s->sssr & SSSR_TINT) &&  (s->sscr[1] & SSCR1_TINTE);
+    level |= (s->sssr & SSSR_PINT) &&  (s->sscr[1] & SSCR1_PINTE);
+    level |= (s->sssr & SSSR_ROR)  && !(s->sscr[0] & SSCR0_RIM);
+    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 pxa2xx_ssp_fifo_update(PXA2xxSSPState *s)
+{
+    s->sssr &= ~(0xf << 12);	/* Clear RFL */
+    s->sssr &= ~(0xf << 8);	/* Clear TFL */
+    s->sssr &= ~SSSR_TFS;
+    s->sssr &= ~SSSR_TNF;
+    if (s->enable) {
+        s->sssr |= ((s->rx_level - 1) & 0xf) << 12;
+        if (s->rx_level >= SSCR1_RFT(s->sscr[1]))
+            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;
+    }
+
+    pxa2xx_ssp_int_update(s);
+}
+
+static uint64_t pxa2xx_ssp_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
+    uint32_t retval;
+
+    switch (addr) {
+    case SSCR0:
+        return s->sscr[0];
+    case SSCR1:
+        return s->sscr[1];
+    case SSPSP:
+        return s->sspsp;
+    case SSTO:
+        return s->ssto;
+    case SSITR:
+        return s->ssitr;
+    case SSSR:
+        return s->sssr | s->ssitr;
+    case SSDR:
+        if (!s->enable)
+            return 0xffffffff;
+        if (s->rx_level < 1) {
+            printf("%s: SSP Rx Underrun\n", __FUNCTION__);
+            return 0xffffffff;
+        }
+        s->rx_level --;
+        retval = s->rx_fifo[s->rx_start ++];
+        s->rx_start &= 0xf;
+        pxa2xx_ssp_fifo_update(s);
+        return retval;
+    case SSTSA:
+        return s->sstsa;
+    case SSRSA:
+        return s->ssrsa;
+    case SSTSS:
+        return 0;
+    case SSACD:
+        return s->ssacd;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_ssp_write(void *opaque, hwaddr addr,
+                             uint64_t value64, unsigned size)
+{
+    PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
+    uint32_t value = value64;
+
+    switch (addr) {
+    case SSCR0:
+        s->sscr[0] = value & 0xc7ffffff;
+        s->enable = value & SSCR0_SSE;
+        if (value & SSCR0_MOD)
+            printf("%s: Attempt to use network mode\n", __FUNCTION__);
+        if (s->enable && SSCR0_DSS(value) < 4)
+            printf("%s: Wrong data size: %i bits\n", __FUNCTION__,
+                            SSCR0_DSS(value));
+        if (!(value & SSCR0_SSE)) {
+            s->sssr = 0;
+            s->ssitr = 0;
+            s->rx_level = 0;
+        }
+        pxa2xx_ssp_fifo_update(s);
+        break;
+
+    case SSCR1:
+        s->sscr[1] = value;
+        if (value & (SSCR1_LBM | SSCR1_EFWR))
+            printf("%s: Attempt to use SSP test mode\n", __FUNCTION__);
+        pxa2xx_ssp_fifo_update(s);
+        break;
+
+    case SSPSP:
+        s->sspsp = value;
+        break;
+
+    case SSTO:
+        s->ssto = value;
+        break;
+
+    case SSITR:
+        s->ssitr = value & SSITR_INT;
+        pxa2xx_ssp_int_update(s);
+        break;
+
+    case SSSR:
+        s->sssr &= ~(value & SSSR_RW);
+        pxa2xx_ssp_int_update(s);
+        break;
+
+    case SSDR:
+        if (SSCR0_UWIRE(s->sscr[0])) {
+            if (s->sscr[1] & SSCR1_MWDS)
+                value &= 0xffff;
+            else
+                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->enable) {
+            uint32_t readval;
+            readval = ssi_transfer(s->bus, value);
+            if (s->rx_level < 0x10) {
+                s->rx_fifo[(s->rx_start + s->rx_level ++) & 0xf] = readval;
+            } else {
+                s->sssr |= SSSR_ROR;
+            }
+        }
+        pxa2xx_ssp_fifo_update(s);
+        break;
+
+    case SSTSA:
+        s->sstsa = value;
+        break;
+
+    case SSRSA:
+        s->ssrsa = value;
+        break;
+
+    case SSACD:
+        s->ssacd = value;
+        break;
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+}
+
+static const MemoryRegionOps pxa2xx_ssp_ops = {
+    .read = pxa2xx_ssp_read,
+    .write = pxa2xx_ssp_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void pxa2xx_ssp_save(QEMUFile *f, void *opaque)
+{
+    PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
+    int i;
+
+    qemu_put_be32(f, s->enable);
+
+    qemu_put_be32s(f, &s->sscr[0]);
+    qemu_put_be32s(f, &s->sscr[1]);
+    qemu_put_be32s(f, &s->sspsp);
+    qemu_put_be32s(f, &s->ssto);
+    qemu_put_be32s(f, &s->ssitr);
+    qemu_put_be32s(f, &s->sssr);
+    qemu_put_8s(f, &s->sstsa);
+    qemu_put_8s(f, &s->ssrsa);
+    qemu_put_8s(f, &s->ssacd);
+
+    qemu_put_byte(f, s->rx_level);
+    for (i = 0; i < s->rx_level; i ++)
+        qemu_put_byte(f, s->rx_fifo[(s->rx_start + i) & 0xf]);
+}
+
+static int pxa2xx_ssp_load(QEMUFile *f, void *opaque, int version_id)
+{
+    PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
+    int i;
+
+    s->enable = qemu_get_be32(f);
+
+    qemu_get_be32s(f, &s->sscr[0]);
+    qemu_get_be32s(f, &s->sscr[1]);
+    qemu_get_be32s(f, &s->sspsp);
+    qemu_get_be32s(f, &s->ssto);
+    qemu_get_be32s(f, &s->ssitr);
+    qemu_get_be32s(f, &s->sssr);
+    qemu_get_8s(f, &s->sstsa);
+    qemu_get_8s(f, &s->ssrsa);
+    qemu_get_8s(f, &s->ssacd);
+
+    s->rx_level = qemu_get_byte(f);
+    s->rx_start = 0;
+    for (i = 0; i < s->rx_level; i ++)
+        s->rx_fifo[i] = qemu_get_byte(f);
+
+    return 0;
+}
+
+static int pxa2xx_ssp_init(SysBusDevice *dev)
+{
+    PXA2xxSSPState *s = FROM_SYSBUS(PXA2xxSSPState, dev);
+
+    sysbus_init_irq(dev, &s->irq);
+
+    memory_region_init_io(&s->iomem, &pxa2xx_ssp_ops, s, "pxa2xx-ssp", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    register_savevm(&dev->qdev, "pxa2xx_ssp", -1, 0,
+                    pxa2xx_ssp_save, pxa2xx_ssp_load, s);
+
+    s->bus = ssi_create_bus(&dev->qdev, "ssi");
+    return 0;
+}
+
+/* Real-Time Clock */
+#define RCNR		0x00	/* RTC Counter register */
+#define RTAR		0x04	/* RTC Alarm register */
+#define RTSR		0x08	/* RTC Status register */
+#define RTTR		0x0c	/* RTC Timer Trim register */
+#define RDCR		0x10	/* RTC Day Counter register */
+#define RYCR		0x14	/* RTC Year Counter register */
+#define RDAR1		0x18	/* RTC Wristwatch Day Alarm register 1 */
+#define RYAR1		0x1c	/* RTC Wristwatch Year Alarm register 1 */
+#define RDAR2		0x20	/* RTC Wristwatch Day Alarm register 2 */
+#define RYAR2		0x24	/* RTC Wristwatch Year Alarm register 2 */
+#define SWCR		0x28	/* RTC Stopwatch Counter register */
+#define SWAR1		0x2c	/* RTC Stopwatch Alarm register 1 */
+#define SWAR2		0x30	/* RTC Stopwatch Alarm register 2 */
+#define RTCPICR		0x34	/* RTC Periodic Interrupt Counter register */
+#define PIAR		0x38	/* RTC Periodic Interrupt Alarm register */
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    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(PXA2xxRTCState *s)
+{
+    int64_t rt = qemu_get_clock_ms(rtc_clock);
+    s->last_rcnr += ((rt - s->last_hz) << 15) /
+            (1000 * ((s->rttr & 0xffff) + 1));
+    s->last_rdcr += ((rt - s->last_hz) << 15) /
+            (1000 * ((s->rttr & 0xffff) + 1));
+    s->last_hz = rt;
+}
+
+static void pxa2xx_rtc_swupdate(PXA2xxRTCState *s)
+{
+    int64_t rt = qemu_get_clock_ms(rtc_clock);
+    if (s->rtsr & (1 << 12))
+        s->last_swcr += (rt - s->last_sw) / 10;
+    s->last_sw = rt;
+}
+
+static void pxa2xx_rtc_piupdate(PXA2xxRTCState *s)
+{
+    int64_t rt = qemu_get_clock_ms(rtc_clock);
+    if (s->rtsr & (1 << 15))
+        s->last_swcr += rt - s->last_pi;
+    s->last_pi = rt;
+}
+
+static inline void pxa2xx_rtc_alarm_update(PXA2xxRTCState *s,
+                uint32_t rtsr)
+{
+    if ((rtsr & (1 << 2)) && !(rtsr & (1 << 0)))
+        qemu_mod_timer(s->rtc_hz, s->last_hz +
+                (((s->rtar - s->last_rcnr) * 1000 *
+                  ((s->rttr & 0xffff) + 1)) >> 15));
+    else
+        qemu_del_timer(s->rtc_hz);
+
+    if ((rtsr & (1 << 5)) && !(rtsr & (1 << 4)))
+        qemu_mod_timer(s->rtc_rdal1, s->last_hz +
+                (((s->rdar1 - s->last_rdcr) * 1000 *
+                  ((s->rttr & 0xffff) + 1)) >> 15)); /* TODO: fixup */
+    else
+        qemu_del_timer(s->rtc_rdal1);
+
+    if ((rtsr & (1 << 7)) && !(rtsr & (1 << 6)))
+        qemu_mod_timer(s->rtc_rdal2, s->last_hz +
+                (((s->rdar2 - s->last_rdcr) * 1000 *
+                  ((s->rttr & 0xffff) + 1)) >> 15)); /* TODO: fixup */
+    else
+        qemu_del_timer(s->rtc_rdal2);
+
+    if ((rtsr & 0x1200) == 0x1200 && !(rtsr & (1 << 8)))
+        qemu_mod_timer(s->rtc_swal1, s->last_sw +
+                        (s->swar1 - s->last_swcr) * 10); /* TODO: fixup */
+    else
+        qemu_del_timer(s->rtc_swal1);
+
+    if ((rtsr & 0x1800) == 0x1800 && !(rtsr & (1 << 10)))
+        qemu_mod_timer(s->rtc_swal2, s->last_sw +
+                        (s->swar2 - s->last_swcr) * 10); /* TODO: fixup */
+    else
+        qemu_del_timer(s->rtc_swal2);
+
+    if ((rtsr & 0xc000) == 0xc000 && !(rtsr & (1 << 13)))
+        qemu_mod_timer(s->rtc_pi, s->last_pi +
+                        (s->piar & 0xffff) - s->last_rtcpicr);
+    else
+        qemu_del_timer(s->rtc_pi);
+}
+
+static inline void pxa2xx_rtc_hz_tick(void *opaque)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+    s->rtsr |= (1 << 0);
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static inline void pxa2xx_rtc_rdal1_tick(void *opaque)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+    s->rtsr |= (1 << 4);
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static inline void pxa2xx_rtc_rdal2_tick(void *opaque)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+    s->rtsr |= (1 << 6);
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static inline void pxa2xx_rtc_swal1_tick(void *opaque)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+    s->rtsr |= (1 << 8);
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static inline void pxa2xx_rtc_swal2_tick(void *opaque)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+    s->rtsr |= (1 << 10);
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static inline void pxa2xx_rtc_pi_tick(void *opaque)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+    s->rtsr |= (1 << 13);
+    pxa2xx_rtc_piupdate(s);
+    s->last_rtcpicr = 0;
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static uint64_t pxa2xx_rtc_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+
+    switch (addr) {
+    case RTTR:
+        return s->rttr;
+    case RTSR:
+        return s->rtsr;
+    case RTAR:
+        return s->rtar;
+    case RDAR1:
+        return s->rdar1;
+    case RDAR2:
+        return s->rdar2;
+    case RYAR1:
+        return s->ryar1;
+    case RYAR2:
+        return s->ryar2;
+    case SWAR1:
+        return s->swar1;
+    case SWAR2:
+        return s->swar2;
+    case PIAR:
+        return s->piar;
+    case RCNR:
+        return s->last_rcnr + ((qemu_get_clock_ms(rtc_clock) - s->last_hz) << 15) /
+                (1000 * ((s->rttr & 0xffff) + 1));
+    case RDCR:
+        return s->last_rdcr + ((qemu_get_clock_ms(rtc_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_ms(rtc_clock) - s->last_sw) / 10;
+        else
+            return s->last_swcr;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_rtc_write(void *opaque, hwaddr addr,
+                             uint64_t value64, unsigned size)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+    uint32_t value = value64;
+
+    switch (addr) {
+    case RTTR:
+        if (!(s->rttr & (1 << 31))) {
+            pxa2xx_rtc_hzupdate(s);
+            s->rttr = value;
+            pxa2xx_rtc_alarm_update(s, s->rtsr);
+        }
+        break;
+
+    case RTSR:
+        if ((s->rtsr ^ value) & (1 << 15))
+            pxa2xx_rtc_piupdate(s);
+
+        if ((s->rtsr ^ value) & (1 << 12))
+            pxa2xx_rtc_swupdate(s);
+
+        if (((s->rtsr ^ value) & 0x4aac) | (value & ~0xdaac))
+            pxa2xx_rtc_alarm_update(s, value);
+
+        s->rtsr = (value & 0xdaac) | (s->rtsr & ~(value & ~0xdaac));
+        pxa2xx_rtc_int_update(s);
+        break;
+
+    case RTAR:
+        s->rtar = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RDAR1:
+        s->rdar1 = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RDAR2:
+        s->rdar2 = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RYAR1:
+        s->ryar1 = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RYAR2:
+        s->ryar2 = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case SWAR1:
+        pxa2xx_rtc_swupdate(s);
+        s->swar1 = value;
+        s->last_swcr = 0;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case SWAR2:
+        s->swar2 = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case PIAR:
+        s->piar = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RCNR:
+        pxa2xx_rtc_hzupdate(s);
+        s->last_rcnr = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RDCR:
+        pxa2xx_rtc_hzupdate(s);
+        s->last_rdcr = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RYCR:
+        s->last_rycr = value;
+        break;
+
+    case SWCR:
+        pxa2xx_rtc_swupdate(s);
+        s->last_swcr = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RTCPICR:
+        pxa2xx_rtc_piupdate(s);
+        s->last_rtcpicr = value & 0xffff;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+    }
+}
+
+static const MemoryRegionOps pxa2xx_rtc_ops = {
+    .read = pxa2xx_rtc_read,
+    .write = pxa2xx_rtc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int pxa2xx_rtc_init(SysBusDevice *dev)
+{
+    PXA2xxRTCState *s = FROM_SYSBUS(PXA2xxRTCState, dev);
+    struct tm tm;
+    int wom;
+
+    s->rttr = 0x7fff;
+    s->rtsr = 0;
+
+    qemu_get_timedate(&tm, 0);
+    wom = ((tm.tm_mday - 1) / 7) + 1;
+
+    s->last_rcnr = (uint32_t) mktimegm(&tm);
+    s->last_rdcr = (wom << 20) | ((tm.tm_wday + 1) << 17) |
+            (tm.tm_hour << 12) | (tm.tm_min << 6) | tm.tm_sec;
+    s->last_rycr = ((tm.tm_year + 1900) << 9) |
+            ((tm.tm_mon + 1) << 5) | tm.tm_mday;
+    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_ms(rtc_clock);
+
+    s->rtc_hz    = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_hz_tick,    s);
+    s->rtc_rdal1 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_rdal1_tick, s);
+    s->rtc_rdal2 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_rdal2_tick, s);
+    s->rtc_swal1 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_swal1_tick, s);
+    s->rtc_swal2 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_swal2_tick, s);
+    s->rtc_pi    = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_pi_tick,    s);
+
+    sysbus_init_irq(dev, &s->rtc_irq);
+
+    memory_region_init_io(&s->iomem, &pxa2xx_rtc_ops, s, "pxa2xx-rtc", 0x10000);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    return 0;
+}
+
+static void pxa2xx_rtc_pre_save(void *opaque)
+{
+    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
+
+    pxa2xx_rtc_hzupdate(s);
+    pxa2xx_rtc_piupdate(s);
+    pxa2xx_rtc_swupdate(s);
+}
+
+static int pxa2xx_rtc_post_load(void *opaque, int version_id)
+{
+    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 void pxa2xx_rtc_sysbus_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = pxa2xx_rtc_init;
+    dc->desc = "PXA2xx RTC Controller";
+    dc->vmsd = &vmstate_pxa2xx_rtc_regs;
+}
+
+static const TypeInfo pxa2xx_rtc_sysbus_info = {
+    .name          = "pxa2xx_rtc",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PXA2xxRTCState),
+    .class_init    = pxa2xx_rtc_sysbus_class_init,
+};
+
+/* I2C Interface */
+typedef struct {
+    I2CSlave i2c;
+    PXA2xxI2CState *host;
+} PXA2xxI2CSlaveState;
+
+struct PXA2xxI2CState {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    PXA2xxI2CSlaveState *slave;
+    i2c_bus *bus;
+    qemu_irq irq;
+    uint32_t offset;
+    uint32_t region_size;
+
+    uint16_t control;
+    uint16_t status;
+    uint8_t ibmr;
+    uint8_t data;
+};
+
+#define IBMR	0x80	/* I2C Bus Monitor register */
+#define IDBR	0x88	/* I2C Data Buffer register */
+#define ICR	0x90	/* I2C Control register */
+#define ISR	0x98	/* I2C Status register */
+#define ISAR	0xa0	/* I2C Slave Address register */
+
+static void pxa2xx_i2c_update(PXA2xxI2CState *s)
+{
+    uint16_t level = 0;
+    level |= s->status & s->control & (1 << 10);		/* BED */
+    level |= (s->status & (1 << 7)) && (s->control & (1 << 9));	/* IRF */
+    level |= (s->status & (1 << 6)) && (s->control & (1 << 8));	/* ITE */
+    level |= s->status & (1 << 9);				/* SAD */
+    qemu_set_irq(s->irq, !!level);
+}
+
+/* These are only stubs now.  */
+static void pxa2xx_i2c_event(I2CSlave *i2c, enum i2c_event event)
+{
+    PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
+    PXA2xxI2CState *s = slave->host;
+
+    switch (event) {
+    case I2C_START_SEND:
+        s->status |= (1 << 9);				/* set SAD */
+        s->status &= ~(1 << 0);				/* clear RWM */
+        break;
+    case I2C_START_RECV:
+        s->status |= (1 << 9);				/* set SAD */
+        s->status |= 1 << 0;				/* set RWM */
+        break;
+    case I2C_FINISH:
+        s->status |= (1 << 4);				/* set SSD */
+        break;
+    case I2C_NACK:
+        s->status |= 1 << 1;				/* set ACKNAK */
+        break;
+    }
+    pxa2xx_i2c_update(s);
+}
+
+static int pxa2xx_i2c_rx(I2CSlave *i2c)
+{
+    PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
+    PXA2xxI2CState *s = slave->host;
+    if ((s->control & (1 << 14)) || !(s->control & (1 << 6)))
+        return 0;
+
+    if (s->status & (1 << 0)) {			/* RWM */
+        s->status |= 1 << 6;			/* set ITE */
+    }
+    pxa2xx_i2c_update(s);
+
+    return s->data;
+}
+
+static int pxa2xx_i2c_tx(I2CSlave *i2c, uint8_t data)
+{
+    PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
+    PXA2xxI2CState *s = slave->host;
+    if ((s->control & (1 << 14)) || !(s->control & (1 << 6)))
+        return 1;
+
+    if (!(s->status & (1 << 0))) {		/* RWM */
+        s->status |= 1 << 7;			/* set IRF */
+        s->data = data;
+    }
+    pxa2xx_i2c_update(s);
+
+    return 1;
+}
+
+static uint64_t pxa2xx_i2c_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    PXA2xxI2CState *s = (PXA2xxI2CState *) opaque;
+
+    addr -= s->offset;
+    switch (addr) {
+    case ICR:
+        return s->control;
+    case ISR:
+        return s->status | (i2c_bus_busy(s->bus) << 2);
+    case ISAR:
+        return s->slave->i2c.address;
+    case IDBR:
+        return s->data;
+    case IBMR:
+        if (s->status & (1 << 2))
+            s->ibmr ^= 3;	/* Fake SCL and SDA pin changes */
+        else
+            s->ibmr = 0;
+        return s->ibmr;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_i2c_write(void *opaque, hwaddr addr,
+                             uint64_t value64, unsigned size)
+{
+    PXA2xxI2CState *s = (PXA2xxI2CState *) opaque;
+    uint32_t value = value64;
+    int ack;
+
+    addr -= s->offset;
+    switch (addr) {
+    case ICR:
+        s->control = value & 0xfff7;
+        if ((value & (1 << 3)) && (value & (1 << 6))) {	/* TB and IUE */
+            /* TODO: slave mode */
+            if (value & (1 << 0)) {			/* START condition */
+                if (s->data & 1)
+                    s->status |= 1 << 0;		/* set RWM */
+                else
+                    s->status &= ~(1 << 0);		/* clear RWM */
+                ack = !i2c_start_transfer(s->bus, s->data >> 1, s->data & 1);
+            } else {
+                if (s->status & (1 << 0)) {		/* RWM */
+                    s->data = i2c_recv(s->bus);
+                    if (value & (1 << 2))		/* ACKNAK */
+                        i2c_nack(s->bus);
+                    ack = 1;
+                } else
+                    ack = !i2c_send(s->bus, s->data);
+            }
+
+            if (value & (1 << 1))			/* STOP condition */
+                i2c_end_transfer(s->bus);
+
+            if (ack) {
+                if (value & (1 << 0))			/* START condition */
+                    s->status |= 1 << 6;		/* set ITE */
+                else
+                    if (s->status & (1 << 0))		/* RWM */
+                        s->status |= 1 << 7;		/* set IRF */
+                    else
+                        s->status |= 1 << 6;		/* set ITE */
+                s->status &= ~(1 << 1);			/* clear ACKNAK */
+            } else {
+                s->status |= 1 << 6;			/* set ITE */
+                s->status |= 1 << 10;			/* set BED */
+                s->status |= 1 << 1;			/* set ACKNAK */
+            }
+        }
+        if (!(value & (1 << 3)) && (value & (1 << 6)))	/* !TB and IUE */
+            if (value & (1 << 4))			/* MA */
+                i2c_end_transfer(s->bus);
+        pxa2xx_i2c_update(s);
+        break;
+
+    case ISR:
+        s->status &= ~(value & 0x07f0);
+        pxa2xx_i2c_update(s);
+        break;
+
+    case ISAR:
+        i2c_set_slave_address(&s->slave->i2c, value & 0x7f);
+        break;
+
+    case IDBR:
+        s->data = value & 0xff;
+        break;
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+    }
+}
+
+static const MemoryRegionOps pxa2xx_i2c_ops = {
+    .read = pxa2xx_i2c_read,
+    .write = pxa2xx_i2c_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_pxa2xx_i2c_slave = {
+    .name = "pxa2xx_i2c_slave",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_I2C_SLAVE(i2c, PXA2xxI2CSlaveState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_pxa2xx_i2c = {
+    .name = "pxa2xx_i2c",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_UINT16(control, PXA2xxI2CState),
+        VMSTATE_UINT16(status, PXA2xxI2CState),
+        VMSTATE_UINT8(ibmr, PXA2xxI2CState),
+        VMSTATE_UINT8(data, PXA2xxI2CState),
+        VMSTATE_STRUCT_POINTER(slave, PXA2xxI2CState,
+                               vmstate_pxa2xx_i2c_slave, PXA2xxI2CSlaveState *),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static int pxa2xx_i2c_slave_init(I2CSlave *i2c)
+{
+    /* Nothing to do.  */
+    return 0;
+}
+
+static void pxa2xx_i2c_slave_class_init(ObjectClass *klass, void *data)
+{
+    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+    k->init = pxa2xx_i2c_slave_init;
+    k->event = pxa2xx_i2c_event;
+    k->recv = pxa2xx_i2c_rx;
+    k->send = pxa2xx_i2c_tx;
+}
+
+static const TypeInfo pxa2xx_i2c_slave_info = {
+    .name          = "pxa2xx-i2c-slave",
+    .parent        = TYPE_I2C_SLAVE,
+    .instance_size = sizeof(PXA2xxI2CSlaveState),
+    .class_init    = pxa2xx_i2c_slave_class_init,
+};
+
+PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base,
+                qemu_irq irq, uint32_t region_size)
+{
+    DeviceState *dev;
+    SysBusDevice *i2c_dev;
+    PXA2xxI2CState *s;
+
+    i2c_dev = SYS_BUS_DEVICE(qdev_create(NULL, "pxa2xx_i2c"));
+    qdev_prop_set_uint32(&i2c_dev->qdev, "size", region_size + 1);
+    qdev_prop_set_uint32(&i2c_dev->qdev, "offset", base & region_size);
+
+    qdev_init_nofail(&i2c_dev->qdev);
+
+    sysbus_mmio_map(i2c_dev, 0, base & ~region_size);
+    sysbus_connect_irq(i2c_dev, 0, irq);
+
+    s = FROM_SYSBUS(PXA2xxI2CState, i2c_dev);
+    /* FIXME: Should the slave device really be on a separate bus?  */
+    dev = i2c_create_slave(i2c_init_bus(NULL, "dummy"), "pxa2xx-i2c-slave", 0);
+    s->slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, I2C_SLAVE(dev));
+    s->slave->host = s;
+
+    return s;
+}
+
+static int pxa2xx_i2c_initfn(SysBusDevice *dev)
+{
+    PXA2xxI2CState *s = FROM_SYSBUS(PXA2xxI2CState, dev);
+
+    s->bus = i2c_init_bus(&dev->qdev, "i2c");
+
+    memory_region_init_io(&s->iomem, &pxa2xx_i2c_ops, s,
+                          "pxa2xx-i2x", s->region_size);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->irq);
+
+    return 0;
+}
+
+i2c_bus *pxa2xx_i2c_bus(PXA2xxI2CState *s)
+{
+    return s->bus;
+}
+
+static Property pxa2xx_i2c_properties[] = {
+    DEFINE_PROP_UINT32("size", PXA2xxI2CState, region_size, 0x10000),
+    DEFINE_PROP_UINT32("offset", PXA2xxI2CState, offset, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pxa2xx_i2c_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = pxa2xx_i2c_initfn;
+    dc->desc = "PXA2xx I2C Bus Controller";
+    dc->vmsd = &vmstate_pxa2xx_i2c;
+    dc->props = pxa2xx_i2c_properties;
+}
+
+static const TypeInfo pxa2xx_i2c_info = {
+    .name          = "pxa2xx_i2c",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PXA2xxI2CState),
+    .class_init    = pxa2xx_i2c_class_init,
+};
+
+/* PXA Inter-IC Sound Controller */
+static void pxa2xx_i2s_reset(PXA2xxI2SState *i2s)
+{
+    i2s->rx_len = 0;
+    i2s->tx_len = 0;
+    i2s->fifo_len = 0;
+    i2s->clk = 0x1a;
+    i2s->control[0] = 0x00;
+    i2s->control[1] = 0x00;
+    i2s->status = 0x00;
+    i2s->mask = 0x00;
+}
+
+#define SACR_TFTH(val)	((val >> 8) & 0xf)
+#define SACR_RFTH(val)	((val >> 12) & 0xf)
+#define SACR_DREC(val)	(val & (1 << 3))
+#define SACR_DPRL(val)	(val & (1 << 4))
+
+static inline void pxa2xx_i2s_update(PXA2xxI2SState *i2s)
+{
+    int rfs, tfs;
+    rfs = SACR_RFTH(i2s->control[0]) < i2s->rx_len &&
+            !SACR_DREC(i2s->control[1]);
+    tfs = (i2s->tx_len || i2s->fifo_len < SACR_TFTH(i2s->control[0])) &&
+            i2s->enable && !SACR_DPRL(i2s->control[1]);
+
+    qemu_set_irq(i2s->rx_dma, rfs);
+    qemu_set_irq(i2s->tx_dma, tfs);
+
+    i2s->status &= 0xe0;
+    if (i2s->fifo_len < 16 || !i2s->enable)
+        i2s->status |= 1 << 0;			/* TNF */
+    if (i2s->rx_len)
+        i2s->status |= 1 << 1;			/* RNE */
+    if (i2s->enable)
+        i2s->status |= 1 << 2;			/* BSY */
+    if (tfs)
+        i2s->status |= 1 << 3;			/* TFS */
+    if (rfs)
+        i2s->status |= 1 << 4;			/* RFS */
+    if (!(i2s->tx_len && i2s->enable))
+        i2s->status |= i2s->fifo_len << 8;	/* TFL */
+    i2s->status |= MAX(i2s->rx_len, 0xf) << 12;	/* RFL */
+
+    qemu_set_irq(i2s->irq, i2s->status & i2s->mask);
+}
+
+#define SACR0	0x00	/* Serial Audio Global Control register */
+#define SACR1	0x04	/* Serial Audio I2S/MSB-Justified Control register */
+#define SASR0	0x0c	/* Serial Audio Interface and FIFO Status register */
+#define SAIMR	0x14	/* Serial Audio Interrupt Mask register */
+#define SAICR	0x18	/* Serial Audio Interrupt Clear register */
+#define SADIV	0x60	/* Serial Audio Clock Divider register */
+#define SADR	0x80	/* Serial Audio Data register */
+
+static uint64_t pxa2xx_i2s_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
+
+    switch (addr) {
+    case SACR0:
+        return s->control[0];
+    case SACR1:
+        return s->control[1];
+    case SASR0:
+        return s->status;
+    case SAIMR:
+        return s->mask;
+    case SAICR:
+        return 0;
+    case SADIV:
+        return s->clk;
+    case SADR:
+        if (s->rx_len > 0) {
+            s->rx_len --;
+            pxa2xx_i2s_update(s);
+            return s->codec_in(s->opaque);
+        }
+        return 0;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_i2s_write(void *opaque, hwaddr addr,
+                             uint64_t value, unsigned size)
+{
+    PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
+    uint32_t *sample;
+
+    switch (addr) {
+    case SACR0:
+        if (value & (1 << 3))				/* RST */
+            pxa2xx_i2s_reset(s);
+        s->control[0] = value & 0xff3d;
+        if (!s->enable && (value & 1) && s->tx_len) {	/* ENB */
+            for (sample = s->fifo; s->fifo_len > 0; s->fifo_len --, sample ++)
+                s->codec_out(s->opaque, *sample);
+            s->status &= ~(1 << 7);			/* I2SOFF */
+        }
+        if (value & (1 << 4))				/* EFWR */
+            printf("%s: Attempt to use special function\n", __FUNCTION__);
+        s->enable = (value & 9) == 1;			/* ENB && !RST*/
+        pxa2xx_i2s_update(s);
+        break;
+    case SACR1:
+        s->control[1] = value & 0x0039;
+        if (value & (1 << 5))				/* ENLBF */
+            printf("%s: Attempt to use loopback function\n", __FUNCTION__);
+        if (value & (1 << 4))				/* DPRL */
+            s->fifo_len = 0;
+        pxa2xx_i2s_update(s);
+        break;
+    case SAIMR:
+        s->mask = value & 0x0078;
+        pxa2xx_i2s_update(s);
+        break;
+    case SAICR:
+        s->status &= ~(value & (3 << 5));
+        pxa2xx_i2s_update(s);
+        break;
+    case SADIV:
+        s->clk = value & 0x007f;
+        break;
+    case SADR:
+        if (s->tx_len && s->enable) {
+            s->tx_len --;
+            pxa2xx_i2s_update(s);
+            s->codec_out(s->opaque, value);
+        } else if (s->fifo_len < 16) {
+            s->fifo[s->fifo_len ++] = value;
+            pxa2xx_i2s_update(s);
+        }
+        break;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+    }
+}
+
+static const MemoryRegionOps pxa2xx_i2s_ops = {
+    .read = pxa2xx_i2s_read,
+    .write = pxa2xx_i2s_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+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)
+{
+    PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
+    uint32_t *sample;
+
+    /* Signal FIFO errors */
+    if (s->enable && s->tx_len)
+        s->status |= 1 << 5;		/* TUR */
+    if (s->enable && s->rx_len)
+        s->status |= 1 << 6;		/* ROR */
+
+    /* Should be tx - MIN(tx, s->fifo_len) but we don't really need to
+     * handle the cases where it makes a difference.  */
+    s->tx_len = tx - s->fifo_len;
+    s->rx_len = rx;
+    /* Note that is s->codec_out wasn't set, we wouldn't get called.  */
+    if (s->enable)
+        for (sample = s->fifo; s->fifo_len; s->fifo_len --, sample ++)
+            s->codec_out(s->opaque, *sample);
+    pxa2xx_i2s_update(s);
+}
+
+static PXA2xxI2SState *pxa2xx_i2s_init(MemoryRegion *sysmem,
+                hwaddr base,
+                qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma)
+{
+    PXA2xxI2SState *s = (PXA2xxI2SState *)
+            g_malloc0(sizeof(PXA2xxI2SState));
+
+    s->irq = irq;
+    s->rx_dma = rx_dma;
+    s->tx_dma = tx_dma;
+    s->data_req = pxa2xx_i2s_data_req;
+
+    pxa2xx_i2s_reset(s);
+
+    memory_region_init_io(&s->iomem, &pxa2xx_i2s_ops, s,
+                          "pxa2xx-i2s", 0x100000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
+
+    vmstate_register(NULL, base, &vmstate_pxa2xx_i2s, s);
+
+    return s;
+}
+
+/* PXA Fast Infra-red Communications Port */
+struct PXA2xxFIrState {
+    MemoryRegion iomem;
+    qemu_irq irq;
+    qemu_irq rx_dma;
+    qemu_irq tx_dma;
+    int enable;
+    CharDriverState *chr;
+
+    uint8_t control[3];
+    uint8_t status[2];
+
+    int rx_len;
+    int rx_start;
+    uint8_t rx_fifo[64];
+};
+
+static void pxa2xx_fir_reset(PXA2xxFIrState *s)
+{
+    s->control[0] = 0x00;
+    s->control[1] = 0x00;
+    s->control[2] = 0x00;
+    s->status[0] = 0x00;
+    s->status[1] = 0x00;
+    s->enable = 0;
+}
+
+static inline void pxa2xx_fir_update(PXA2xxFIrState *s)
+{
+    static const int tresh[4] = { 8, 16, 32, 0 };
+    int intr = 0;
+    if ((s->control[0] & (1 << 4)) &&			/* RXE */
+                    s->rx_len >= tresh[s->control[2] & 3])	/* TRIG */
+        s->status[0] |= 1 << 4;				/* RFS */
+    else
+        s->status[0] &= ~(1 << 4);			/* RFS */
+    if (s->control[0] & (1 << 3))			/* TXE */
+        s->status[0] |= 1 << 3;				/* TFS */
+    else
+        s->status[0] &= ~(1 << 3);			/* TFS */
+    if (s->rx_len)
+        s->status[1] |= 1 << 2;				/* RNE */
+    else
+        s->status[1] &= ~(1 << 2);			/* RNE */
+    if (s->control[0] & (1 << 4))			/* RXE */
+        s->status[1] |= 1 << 0;				/* RSY */
+    else
+        s->status[1] &= ~(1 << 0);			/* RSY */
+
+    intr |= (s->control[0] & (1 << 5)) &&		/* RIE */
+            (s->status[0] & (1 << 4));			/* RFS */
+    intr |= (s->control[0] & (1 << 6)) &&		/* TIE */
+            (s->status[0] & (1 << 3));			/* TFS */
+    intr |= (s->control[2] & (1 << 4)) &&		/* TRAIL */
+            (s->status[0] & (1 << 6));			/* EOC */
+    intr |= (s->control[0] & (1 << 2)) &&		/* TUS */
+            (s->status[0] & (1 << 1));			/* TUR */
+    intr |= s->status[0] & 0x25;			/* FRE, RAB, EIF */
+
+    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);
+}
+
+#define ICCR0	0x00	/* FICP Control register 0 */
+#define ICCR1	0x04	/* FICP Control register 1 */
+#define ICCR2	0x08	/* FICP Control register 2 */
+#define ICDR	0x0c	/* FICP Data register */
+#define ICSR0	0x14	/* FICP Status register 0 */
+#define ICSR1	0x18	/* FICP Status register 1 */
+#define ICFOR	0x1c	/* FICP FIFO Occupancy Status register */
+
+static uint64_t pxa2xx_fir_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
+    uint8_t ret;
+
+    switch (addr) {
+    case ICCR0:
+        return s->control[0];
+    case ICCR1:
+        return s->control[1];
+    case ICCR2:
+        return s->control[2];
+    case ICDR:
+        s->status[0] &= ~0x01;
+        s->status[1] &= ~0x72;
+        if (s->rx_len) {
+            s->rx_len --;
+            ret = s->rx_fifo[s->rx_start ++];
+            s->rx_start &= 63;
+            pxa2xx_fir_update(s);
+            return ret;
+        }
+        printf("%s: Rx FIFO underrun.\n", __FUNCTION__);
+        break;
+    case ICSR0:
+        return s->status[0];
+    case ICSR1:
+        return s->status[1] | (1 << 3);			/* TNF */
+    case ICFOR:
+        return s->rx_len;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_fir_write(void *opaque, hwaddr addr,
+                             uint64_t value64, unsigned size)
+{
+    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
+    uint32_t value = value64;
+    uint8_t ch;
+
+    switch (addr) {
+    case ICCR0:
+        s->control[0] = value;
+        if (!(value & (1 << 4)))			/* RXE */
+            s->rx_len = s->rx_start = 0;
+        if (!(value & (1 << 3))) {                      /* TXE */
+            /* Nop */
+        }
+        s->enable = value & 1;				/* ITR */
+        if (!s->enable)
+            s->status[0] = 0;
+        pxa2xx_fir_update(s);
+        break;
+    case ICCR1:
+        s->control[1] = value;
+        break;
+    case ICCR2:
+        s->control[2] = value & 0x3f;
+        pxa2xx_fir_update(s);
+        break;
+    case ICDR:
+        if (s->control[2] & (1 << 2))			/* TXP */
+            ch = value;
+        else
+            ch = ~value;
+        if (s->chr && s->enable && (s->control[0] & (1 << 3)))	/* TXE */
+            qemu_chr_fe_write(s->chr, &ch, 1);
+        break;
+    case ICSR0:
+        s->status[0] &= ~(value & 0x66);
+        pxa2xx_fir_update(s);
+        break;
+    case ICFOR:
+        break;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+    }
+}
+
+static const MemoryRegionOps pxa2xx_fir_ops = {
+    .read = pxa2xx_fir_read,
+    .write = pxa2xx_fir_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int pxa2xx_fir_is_empty(void *opaque)
+{
+    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
+    return (s->rx_len < 64);
+}
+
+static void pxa2xx_fir_rx(void *opaque, const uint8_t *buf, int size)
+{
+    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
+    if (!(s->control[0] & (1 << 4)))			/* RXE */
+        return;
+
+    while (size --) {
+        s->status[1] |= 1 << 4;				/* EOF */
+        if (s->rx_len >= 64) {
+            s->status[1] |= 1 << 6;			/* ROR */
+            break;
+        }
+
+        if (s->control[2] & (1 << 3))			/* RXP */
+            s->rx_fifo[(s->rx_start + s->rx_len ++) & 63] = *(buf ++);
+        else
+            s->rx_fifo[(s->rx_start + s->rx_len ++) & 63] = ~*(buf ++);
+    }
+
+    pxa2xx_fir_update(s);
+}
+
+static void pxa2xx_fir_event(void *opaque, int event)
+{
+}
+
+static void pxa2xx_fir_save(QEMUFile *f, void *opaque)
+{
+    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
+    int i;
+
+    qemu_put_be32(f, s->enable);
+
+    qemu_put_8s(f, &s->control[0]);
+    qemu_put_8s(f, &s->control[1]);
+    qemu_put_8s(f, &s->control[2]);
+    qemu_put_8s(f, &s->status[0]);
+    qemu_put_8s(f, &s->status[1]);
+
+    qemu_put_byte(f, s->rx_len);
+    for (i = 0; i < s->rx_len; i ++)
+        qemu_put_byte(f, s->rx_fifo[(s->rx_start + i) & 63]);
+}
+
+static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
+{
+    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
+    int i;
+
+    s->enable = qemu_get_be32(f);
+
+    qemu_get_8s(f, &s->control[0]);
+    qemu_get_8s(f, &s->control[1]);
+    qemu_get_8s(f, &s->control[2]);
+    qemu_get_8s(f, &s->status[0]);
+    qemu_get_8s(f, &s->status[1]);
+
+    s->rx_len = qemu_get_byte(f);
+    s->rx_start = 0;
+    for (i = 0; i < s->rx_len; i ++)
+        s->rx_fifo[i] = qemu_get_byte(f);
+
+    return 0;
+}
+
+static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
+                hwaddr base,
+                qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma,
+                CharDriverState *chr)
+{
+    PXA2xxFIrState *s = (PXA2xxFIrState *)
+            g_malloc0(sizeof(PXA2xxFIrState));
+
+    s->irq = irq;
+    s->rx_dma = rx_dma;
+    s->tx_dma = tx_dma;
+    s->chr = chr;
+
+    pxa2xx_fir_reset(s);
+
+    memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
+
+    if (chr)
+        qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
+                        pxa2xx_fir_rx, pxa2xx_fir_event, s);
+
+    register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
+                    pxa2xx_fir_load, s);
+
+    return s;
+}
+
+static void pxa2xx_reset(void *opaque, int line, int level)
+{
+    PXA2xxState *s = (PXA2xxState *) opaque;
+
+    if (level && (s->pm_regs[PCFR >> 2] & 0x10)) {	/* GPR_EN */
+        cpu_reset(CPU(s->cpu));
+        /* TODO: reset peripherals */
+    }
+}
+
+/* Initialise a PXA270 integrated chip (ARM based core).  */
+PXA2xxState *pxa270_init(MemoryRegion *address_space,
+                         unsigned int sdram_size, const char *revision)
+{
+    PXA2xxState *s;
+    int i;
+    DriveInfo *dinfo;
+    s = (PXA2xxState *) g_malloc0(sizeof(PXA2xxState));
+
+    if (revision && strncmp(revision, "pxa27", 5)) {
+        fprintf(stderr, "Machine requires a PXA27x processor.\n");
+        exit(1);
+    }
+    if (!revision)
+        revision = "pxa270";
+    
+    s->cpu = cpu_arm_init(revision);
+    if (s->cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
+
+    /* SDRAM & Internal Memory Storage */
+    memory_region_init_ram(&s->sdram, "pxa270.sdram", sdram_size);
+    vmstate_register_ram_global(&s->sdram);
+    memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram);
+    memory_region_init_ram(&s->internal, "pxa270.internal", 0x40000);
+    vmstate_register_ram_global(&s->internal);
+    memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
+                                &s->internal);
+
+    s->pic = pxa2xx_pic_init(0x40d00000, s->cpu);
+
+    s->dma = pxa27x_dma_init(0x40000000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
+
+    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->cpu, s->pic, 121);
+
+    dinfo = drive_get(IF_SD, 0, 0);
+    if (!dinfo) {
+        fprintf(stderr, "qemu: missing SecureDigital device\n");
+        exit(1);
+    }
+    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv,
+                    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]) {
+            serial_mm_init(address_space, pxa270_serial[i].io_base, 2,
+                           qdev_get_gpio_in(s->pic, pxa270_serial[i].irqn),
+                           14857000 / 16, serial_hds[i],
+                           DEVICE_NATIVE_ENDIAN);
+        } else {
+            break;
+        }
+    }
+    if (serial_hds[i])
+        s->fir = pxa2xx_fir_init(address_space, 0x40800000,
+                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_ICP),
+                        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(address_space, 0x44000000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_LCD));
+
+    s->cm_base = 0x41300000;
+    s->cm_regs[CCCR >> 2] = 0x02000210;	/* 416.0 MHz */
+    s->clkcfg = 0x00000009;		/* Turbo mode active */
+    memory_region_init_io(&s->cm_iomem, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000);
+    memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
+
+    pxa2xx_setup_cp14(s);
+
+    s->mm_base = 0x48000000;
+    s->mm_regs[MDMRS >> 2] = 0x00020002;
+    s->mm_regs[MDREFR >> 2] = 0x03ca4000;
+    s->mm_regs[MECR >> 2] = 0x00000001;	/* Two PC Card sockets */
+    memory_region_init_io(&s->mm_iomem, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000);
+    memory_region_add_subregion(address_space, s->mm_base, &s->mm_iomem);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
+
+    s->pm_base = 0x40f00000;
+    memory_region_init_io(&s->pm_iomem, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100);
+    memory_region_add_subregion(address_space, s->pm_base, &s->pm_iomem);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
+
+    for (i = 0; pxa27x_ssp[i].io_base; i ++);
+    s->ssp = (SSIBus **)g_malloc0(sizeof(SSIBus *) * i);
+    for (i = 0; pxa27x_ssp[i].io_base; i ++) {
+        DeviceState *dev;
+        dev = sysbus_create_simple("pxa2xx-ssp", pxa27x_ssp[i].io_base,
+                        qdev_get_gpio_in(s->pic, pxa27x_ssp[i].irqn));
+        s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
+    }
+
+    if (usb_enabled(false)) {
+        sysbus_create_simple("sysbus-ohci", 0x4c000000,
+                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
+    }
+
+    s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
+    s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
+
+    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);
+    s->i2c[1] = pxa2xx_i2c_init(0x40f00100,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_PWRI2C), 0xff);
+
+    s->i2s = pxa2xx_i2s_init(address_space, 0x40400000,
+                    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(address_space, 0x41500000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_KEYPAD));
+
+    /* GPIO1 resets the processor */
+    /* The handler can be overridden by board-specific code */
+    qdev_connect_gpio_out(s->gpio, 1, s->reset);
+    return s;
+}
+
+/* Initialise a PXA255 integrated chip (ARM based core).  */
+PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
+{
+    PXA2xxState *s;
+    int i;
+    DriveInfo *dinfo;
+
+    s = (PXA2xxState *) g_malloc0(sizeof(PXA2xxState));
+
+    s->cpu = cpu_arm_init("pxa255");
+    if (s->cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
+
+    /* SDRAM & Internal Memory Storage */
+    memory_region_init_ram(&s->sdram, "pxa255.sdram", sdram_size);
+    vmstate_register_ram_global(&s->sdram);
+    memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram);
+    memory_region_init_ram(&s->internal, "pxa255.internal",
+                           PXA2XX_INTERNAL_SIZE);
+    vmstate_register_ram_global(&s->internal);
+    memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
+                                &s->internal);
+
+    s->pic = pxa2xx_pic_init(0x40d00000, s->cpu);
+
+    s->dma = pxa255_dma_init(0x40000000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
+
+    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->cpu, s->pic, 85);
+
+    dinfo = drive_get(IF_SD, 0, 0);
+    if (!dinfo) {
+        fprintf(stderr, "qemu: missing SecureDigital device\n");
+        exit(1);
+    }
+    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv,
+                    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]) {
+            serial_mm_init(address_space, pxa255_serial[i].io_base, 2,
+                           qdev_get_gpio_in(s->pic, pxa255_serial[i].irqn),
+                           14745600 / 16, serial_hds[i],
+                           DEVICE_NATIVE_ENDIAN);
+        } else {
+            break;
+        }
+    }
+    if (serial_hds[i])
+        s->fir = pxa2xx_fir_init(address_space, 0x40800000,
+                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_ICP),
+                        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(address_space, 0x44000000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_LCD));
+
+    s->cm_base = 0x41300000;
+    s->cm_regs[CCCR >> 2] = 0x02000210;	/* 416.0 MHz */
+    s->clkcfg = 0x00000009;		/* Turbo mode active */
+    memory_region_init_io(&s->cm_iomem, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000);
+    memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
+
+    pxa2xx_setup_cp14(s);
+
+    s->mm_base = 0x48000000;
+    s->mm_regs[MDMRS >> 2] = 0x00020002;
+    s->mm_regs[MDREFR >> 2] = 0x03ca4000;
+    s->mm_regs[MECR >> 2] = 0x00000001;	/* Two PC Card sockets */
+    memory_region_init_io(&s->mm_iomem, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000);
+    memory_region_add_subregion(address_space, s->mm_base, &s->mm_iomem);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
+
+    s->pm_base = 0x40f00000;
+    memory_region_init_io(&s->pm_iomem, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100);
+    memory_region_add_subregion(address_space, s->pm_base, &s->pm_iomem);
+    vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
+
+    for (i = 0; pxa255_ssp[i].io_base; i ++);
+    s->ssp = (SSIBus **)g_malloc0(sizeof(SSIBus *) * i);
+    for (i = 0; pxa255_ssp[i].io_base; i ++) {
+        DeviceState *dev;
+        dev = sysbus_create_simple("pxa2xx-ssp", pxa255_ssp[i].io_base,
+                        qdev_get_gpio_in(s->pic, pxa255_ssp[i].irqn));
+        s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
+    }
+
+    if (usb_enabled(false)) {
+        sysbus_create_simple("sysbus-ohci", 0x4c000000,
+                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
+    }
+
+    s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
+    s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
+
+    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);
+    s->i2c[1] = pxa2xx_i2c_init(0x40f00100,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_PWRI2C), 0xff);
+
+    s->i2s = pxa2xx_i2s_init(address_space, 0x40400000,
+                    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 */
+    qdev_connect_gpio_out(s->gpio, 1, s->reset);
+    return s;
+}
+
+static void pxa2xx_ssp_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = pxa2xx_ssp_init;
+}
+
+static const TypeInfo pxa2xx_ssp_info = {
+    .name          = "pxa2xx-ssp",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PXA2xxSSPState),
+    .class_init    = pxa2xx_ssp_class_init,
+};
+
+static void pxa2xx_register_types(void)
+{
+    type_register_static(&pxa2xx_i2c_slave_info);
+    type_register_static(&pxa2xx_ssp_info);
+    type_register_static(&pxa2xx_i2c_info);
+    type_register_static(&pxa2xx_rtc_sysbus_info);
+}
+
+type_init(pxa2xx_register_types)
diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c
new file mode 100644
index 0000000..eef8411
--- /dev/null
+++ b/hw/arm/pxa2xx_gpio.c
@@ -0,0 +1,350 @@
+/*
+ * Intel XScale PXA255/270 GPIO controller emulation.
+ *
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Written by Andrzej Zaborowski <balrog at zabor.org>
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/hw.h"
+#include "hw/sysbus.h"
+#include "hw/pxa.h"
+
+#define PXA2XX_GPIO_BANKS	4
+
+typedef struct PXA2xxGPIOInfo PXA2xxGPIOInfo;
+struct PXA2xxGPIOInfo {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq irq0, irq1, irqX;
+    int lines;
+    int ncpu;
+    ARMCPU *cpu;
+
+    /* XXX: GNU C vectors are more suitable */
+    uint32_t ilevel[PXA2XX_GPIO_BANKS];
+    uint32_t olevel[PXA2XX_GPIO_BANKS];
+    uint32_t dir[PXA2XX_GPIO_BANKS];
+    uint32_t rising[PXA2XX_GPIO_BANKS];
+    uint32_t falling[PXA2XX_GPIO_BANKS];
+    uint32_t status[PXA2XX_GPIO_BANKS];
+    uint32_t gpsr[PXA2XX_GPIO_BANKS];
+    uint32_t gafr[PXA2XX_GPIO_BANKS * 2];
+
+    uint32_t prev_level[PXA2XX_GPIO_BANKS];
+    qemu_irq handler[PXA2XX_GPIO_BANKS * 32];
+    qemu_irq read_notify;
+};
+
+static struct {
+    enum {
+        GPIO_NONE,
+        GPLR,
+        GPSR,
+        GPCR,
+        GPDR,
+        GRER,
+        GFER,
+        GEDR,
+        GAFR_L,
+        GAFR_U,
+    } reg;
+    int bank;
+} pxa2xx_gpio_regs[0x200] = {
+    [0 ... 0x1ff] = { GPIO_NONE, 0 },
+#define PXA2XX_REG(reg, a0, a1, a2, a3)	\
+    [a0] = { reg, 0 }, [a1] = { reg, 1 }, [a2] = { reg, 2 }, [a3] = { reg, 3 },
+
+    PXA2XX_REG(GPLR, 0x000, 0x004, 0x008, 0x100)
+    PXA2XX_REG(GPSR, 0x018, 0x01c, 0x020, 0x118)
+    PXA2XX_REG(GPCR, 0x024, 0x028, 0x02c, 0x124)
+    PXA2XX_REG(GPDR, 0x00c, 0x010, 0x014, 0x10c)
+    PXA2XX_REG(GRER, 0x030, 0x034, 0x038, 0x130)
+    PXA2XX_REG(GFER, 0x03c, 0x040, 0x044, 0x13c)
+    PXA2XX_REG(GEDR, 0x048, 0x04c, 0x050, 0x148)
+    PXA2XX_REG(GAFR_L, 0x054, 0x05c, 0x064, 0x06c)
+    PXA2XX_REG(GAFR_U, 0x058, 0x060, 0x068, 0x070)
+};
+
+static void pxa2xx_gpio_irq_update(PXA2xxGPIOInfo *s)
+{
+    if (s->status[0] & (1 << 0))
+        qemu_irq_raise(s->irq0);
+    else
+        qemu_irq_lower(s->irq0);
+
+    if (s->status[0] & (1 << 1))
+        qemu_irq_raise(s->irq1);
+    else
+        qemu_irq_lower(s->irq1);
+
+    if ((s->status[0] & ~3) | s->status[1] | s->status[2] | s->status[3])
+        qemu_irq_raise(s->irqX);
+    else
+        qemu_irq_lower(s->irqX);
+}
+
+/* Bitmap of pins used as standby and sleep wake-up sources.  */
+static const int pxa2xx_gpio_wake[PXA2XX_GPIO_BANKS] = {
+    0x8003fe1b, 0x002001fc, 0xec080000, 0x0012007f,
+};
+
+static void pxa2xx_gpio_set(void *opaque, int line, int level)
+{
+    PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
+    int bank;
+    uint32_t mask;
+
+    if (line >= s->lines) {
+        printf("%s: No GPIO pin %i\n", __FUNCTION__, line);
+        return;
+    }
+
+    bank = line >> 5;
+    mask = 1 << (line & 31);
+
+    if (level) {
+        s->status[bank] |= s->rising[bank] & mask &
+                ~s->ilevel[bank] & ~s->dir[bank];
+        s->ilevel[bank] |= mask;
+    } else {
+        s->status[bank] |= s->falling[bank] & mask &
+                s->ilevel[bank] & ~s->dir[bank];
+        s->ilevel[bank] &= ~mask;
+    }
+
+    if (s->status[bank] & mask)
+        pxa2xx_gpio_irq_update(s);
+
+    /* Wake-up GPIOs */
+    if (s->cpu->env.halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
+        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
+    }
+}
+
+static void pxa2xx_gpio_handler_update(PXA2xxGPIOInfo *s) {
+    uint32_t level, diff;
+    int i, bit, line;
+    for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) {
+        level = s->olevel[i] & s->dir[i];
+
+        for (diff = s->prev_level[i] ^ level; diff; diff ^= 1 << bit) {
+            bit = ffs(diff) - 1;
+            line = bit + 32 * i;
+            qemu_set_irq(s->handler[line], (level >> bit) & 1);
+        }
+
+        s->prev_level[i] = level;
+    }
+}
+
+static uint64_t pxa2xx_gpio_read(void *opaque, hwaddr offset,
+                                 unsigned size)
+{
+    PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
+    uint32_t ret;
+    int bank;
+    if (offset >= 0x200)
+        return 0;
+
+    bank = pxa2xx_gpio_regs[offset].bank;
+    switch (pxa2xx_gpio_regs[offset].reg) {
+    case GPDR:		/* GPIO Pin-Direction registers */
+        return s->dir[bank];
+
+    case GPSR:		/* GPIO Pin-Output Set registers */
+        printf("%s: Read from a write-only register " REG_FMT "\n",
+                        __FUNCTION__, offset);
+        return s->gpsr[bank];	/* Return last written value.  */
+
+    case GPCR:		/* GPIO Pin-Output Clear registers */
+        printf("%s: Read from a write-only register " REG_FMT "\n",
+                        __FUNCTION__, offset);
+        return 31337;		/* Specified as unpredictable in the docs.  */
+
+    case GRER:		/* GPIO Rising-Edge Detect Enable registers */
+        return s->rising[bank];
+
+    case GFER:		/* GPIO Falling-Edge Detect Enable registers */
+        return s->falling[bank];
+
+    case GAFR_L:	/* GPIO Alternate Function registers */
+        return s->gafr[bank * 2];
+
+    case GAFR_U:	/* GPIO Alternate Function registers */
+        return s->gafr[bank * 2 + 1];
+
+    case GPLR:		/* GPIO Pin-Level registers */
+        ret = (s->olevel[bank] & s->dir[bank]) |
+                (s->ilevel[bank] & ~s->dir[bank]);
+        qemu_irq_raise(s->read_notify);
+        return ret;
+
+    case GEDR:		/* GPIO Edge Detect Status registers */
+        return s->status[bank];
+
+    default:
+        hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
+    }
+
+    return 0;
+}
+
+static void pxa2xx_gpio_write(void *opaque, hwaddr offset,
+                              uint64_t value, unsigned size)
+{
+    PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
+    int bank;
+    if (offset >= 0x200)
+        return;
+
+    bank = pxa2xx_gpio_regs[offset].bank;
+    switch (pxa2xx_gpio_regs[offset].reg) {
+    case GPDR:		/* GPIO Pin-Direction registers */
+        s->dir[bank] = value;
+        pxa2xx_gpio_handler_update(s);
+        break;
+
+    case GPSR:		/* GPIO Pin-Output Set registers */
+        s->olevel[bank] |= value;
+        pxa2xx_gpio_handler_update(s);
+        s->gpsr[bank] = value;
+        break;
+
+    case GPCR:		/* GPIO Pin-Output Clear registers */
+        s->olevel[bank] &= ~value;
+        pxa2xx_gpio_handler_update(s);
+        break;
+
+    case GRER:		/* GPIO Rising-Edge Detect Enable registers */
+        s->rising[bank] = value;
+        break;
+
+    case GFER:		/* GPIO Falling-Edge Detect Enable registers */
+        s->falling[bank] = value;
+        break;
+
+    case GAFR_L:	/* GPIO Alternate Function registers */
+        s->gafr[bank * 2] = value;
+        break;
+
+    case GAFR_U:	/* GPIO Alternate Function registers */
+        s->gafr[bank * 2 + 1] = value;
+        break;
+
+    case GEDR:		/* GPIO Edge Detect Status registers */
+        s->status[bank] &= ~value;
+        pxa2xx_gpio_irq_update(s);
+        break;
+
+    default:
+        hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
+    }
+}
+
+static const MemoryRegionOps pxa_gpio_ops = {
+    .read = pxa2xx_gpio_read,
+    .write = pxa2xx_gpio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+DeviceState *pxa2xx_gpio_init(hwaddr base,
+                              ARMCPU *cpu, DeviceState *pic, int lines)
+{
+    CPUState *cs = CPU(cpu);
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "pxa2xx-gpio");
+    qdev_prop_set_int32(dev, "lines", lines);
+    qdev_prop_set_int32(dev, "ncpu", cs->cpu_index);
+    qdev_init_nofail(dev);
+
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
+                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_0));
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1,
+                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_1));
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2,
+                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_X));
+
+    return dev;
+}
+
+static int pxa2xx_gpio_initfn(SysBusDevice *dev)
+{
+    PXA2xxGPIOInfo *s;
+
+    s = FROM_SYSBUS(PXA2xxGPIOInfo, dev);
+
+    s->cpu = ARM_CPU(qemu_get_cpu(s->ncpu));
+
+    qdev_init_gpio_in(&dev->qdev, pxa2xx_gpio_set, s->lines);
+    qdev_init_gpio_out(&dev->qdev, s->handler, s->lines);
+
+    memory_region_init_io(&s->iomem, &pxa_gpio_ops, s, "pxa2xx-gpio", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->irq0);
+    sysbus_init_irq(dev, &s->irq1);
+    sysbus_init_irq(dev, &s->irqX);
+
+    return 0;
+}
+
+/*
+ * Registers a callback to notify on GPLR reads.  This normally
+ * shouldn't be needed but it is used for the hack on Spitz machines.
+ */
+void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler)
+{
+    PXA2xxGPIOInfo *s = FROM_SYSBUS(PXA2xxGPIOInfo, SYS_BUS_DEVICE(dev));
+    s->read_notify = handler;
+}
+
+static const VMStateDescription vmstate_pxa2xx_gpio_regs = {
+    .name = "pxa2xx-gpio",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_INT32(lines, PXA2xxGPIOInfo),
+        VMSTATE_UINT32_ARRAY(ilevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(olevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(dir, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(rising, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(falling, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(status, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(gafr, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS * 2),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static Property pxa2xx_gpio_properties[] = {
+    DEFINE_PROP_INT32("lines", PXA2xxGPIOInfo, lines, 0),
+    DEFINE_PROP_INT32("ncpu", PXA2xxGPIOInfo, ncpu, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pxa2xx_gpio_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = pxa2xx_gpio_initfn;
+    dc->desc = "PXA2xx GPIO controller";
+    dc->props = pxa2xx_gpio_properties;
+}
+
+static const TypeInfo pxa2xx_gpio_info = {
+    .name          = "pxa2xx-gpio",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PXA2xxGPIOInfo),
+    .class_init    = pxa2xx_gpio_class_init,
+};
+
+static void pxa2xx_gpio_register_types(void)
+{
+    type_register_static(&pxa2xx_gpio_info);
+}
+
+type_init(pxa2xx_gpio_register_types)
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
new file mode 100644
index 0000000..145fc78
--- /dev/null
+++ b/hw/arm/pxa2xx_pic.c
@@ -0,0 +1,334 @@
+/*
+ * Intel XScale PXA Programmable Interrupt Controller.
+ *
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Copyright (c) 2006 Thorsten Zitterell
+ * Written by Andrzej Zaborowski <balrog at zabor.org>
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/sysbus.h"
+
+#define ICIP	0x00	/* Interrupt Controller IRQ Pending register */
+#define ICMR	0x04	/* Interrupt Controller Mask register */
+#define ICLR	0x08	/* Interrupt Controller Level register */
+#define ICFP	0x0c	/* Interrupt Controller FIQ Pending register */
+#define ICPR	0x10	/* Interrupt Controller Pending register */
+#define ICCR	0x14	/* Interrupt Controller Control register */
+#define ICHP	0x18	/* Interrupt Controller Highest Priority register */
+#define IPR0	0x1c	/* Interrupt Controller Priority register 0 */
+#define IPR31	0x98	/* Interrupt Controller Priority register 31 */
+#define ICIP2	0x9c	/* Interrupt Controller IRQ Pending register 2 */
+#define ICMR2	0xa0	/* Interrupt Controller Mask register 2 */
+#define ICLR2	0xa4	/* Interrupt Controller Level register 2 */
+#define ICFP2	0xa8	/* Interrupt Controller FIQ Pending register 2 */
+#define ICPR2	0xac	/* Interrupt Controller Pending register 2 */
+#define IPR32	0xb0	/* Interrupt Controller Priority register 32 */
+#define IPR39	0xcc	/* Interrupt Controller Priority register 39 */
+
+#define PXA2XX_PIC_SRCS	40
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    ARMCPU *cpu;
+    uint32_t int_enabled[2];
+    uint32_t int_pending[2];
+    uint32_t is_fiq[2];
+    uint32_t int_idle;
+    uint32_t priority[PXA2XX_PIC_SRCS];
+} PXA2xxPICState;
+
+static void pxa2xx_pic_update(void *opaque)
+{
+    uint32_t mask[2];
+    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
+
+    if (s->cpu->env.halted) {
+        mask[0] = s->int_pending[0] & (s->int_enabled[0] | s->int_idle);
+        mask[1] = s->int_pending[1] & (s->int_enabled[1] | s->int_idle);
+        if (mask[0] || mask[1]) {
+            cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
+        }
+    }
+
+    mask[0] = s->int_pending[0] & s->int_enabled[0];
+    mask[1] = s->int_pending[1] & s->int_enabled[1];
+
+    if ((mask[0] & s->is_fiq[0]) || (mask[1] & s->is_fiq[1])) {
+        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
+    } else {
+        cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
+    }
+
+    if ((mask[0] & ~s->is_fiq[0]) || (mask[1] & ~s->is_fiq[1])) {
+        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
+    }
+}
+
+/* Note: Here level means state of the signal on a pin, not
+ * IRQ/FIQ distinction as in PXA Developer Manual.  */
+static void pxa2xx_pic_set_irq(void *opaque, int irq, int level)
+{
+    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
+    int int_set = (irq >= 32);
+    irq &= 31;
+
+    if (level)
+        s->int_pending[int_set] |= 1 << irq;
+    else
+        s->int_pending[int_set] &= ~(1 << irq);
+
+    pxa2xx_pic_update(opaque);
+}
+
+static inline uint32_t pxa2xx_pic_highest(PXA2xxPICState *s) {
+    int i, int_set, irq;
+    uint32_t bit, mask[2];
+    uint32_t ichp = 0x003f003f;	/* Both IDs invalid */
+
+    mask[0] = s->int_pending[0] & s->int_enabled[0];
+    mask[1] = s->int_pending[1] & s->int_enabled[1];
+
+    for (i = PXA2XX_PIC_SRCS - 1; i >= 0; i --) {
+        irq = s->priority[i] & 0x3f;
+        if ((s->priority[i] & (1 << 31)) && irq < PXA2XX_PIC_SRCS) {
+            /* Source peripheral ID is valid.  */
+            bit = 1 << (irq & 31);
+            int_set = (irq >= 32);
+
+            if (mask[int_set] & bit & s->is_fiq[int_set]) {
+                /* FIQ asserted */
+                ichp &= 0xffff0000;
+                ichp |= (1 << 15) | irq;
+            }
+
+            if (mask[int_set] & bit & ~s->is_fiq[int_set]) {
+                /* IRQ asserted */
+                ichp &= 0x0000ffff;
+                ichp |= (1 << 31) | (irq << 16);
+            }
+        }
+    }
+
+    return ichp;
+}
+
+static uint64_t pxa2xx_pic_mem_read(void *opaque, hwaddr offset,
+                                    unsigned size)
+{
+    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
+
+    switch (offset) {
+    case ICIP:	/* IRQ Pending register */
+        return s->int_pending[0] & ~s->is_fiq[0] & s->int_enabled[0];
+    case ICIP2:	/* IRQ Pending register 2 */
+        return s->int_pending[1] & ~s->is_fiq[1] & s->int_enabled[1];
+    case ICMR:	/* Mask register */
+        return s->int_enabled[0];
+    case ICMR2:	/* Mask register 2 */
+        return s->int_enabled[1];
+    case ICLR:	/* Level register */
+        return s->is_fiq[0];
+    case ICLR2:	/* Level register 2 */
+        return s->is_fiq[1];
+    case ICCR:	/* Idle mask */
+        return (s->int_idle == 0);
+    case ICFP:	/* FIQ Pending register */
+        return s->int_pending[0] & s->is_fiq[0] & s->int_enabled[0];
+    case ICFP2:	/* FIQ Pending register 2 */
+        return s->int_pending[1] & s->is_fiq[1] & s->int_enabled[1];
+    case ICPR:	/* Pending register */
+        return s->int_pending[0];
+    case ICPR2:	/* Pending register 2 */
+        return s->int_pending[1];
+    case IPR0  ... IPR31:
+        return s->priority[0  + ((offset - IPR0 ) >> 2)];
+    case IPR32 ... IPR39:
+        return s->priority[32 + ((offset - IPR32) >> 2)];
+    case ICHP:	/* Highest Priority register */
+        return pxa2xx_pic_highest(s);
+    default:
+        printf("%s: Bad register offset " REG_FMT "\n", __FUNCTION__, offset);
+        return 0;
+    }
+}
+
+static void pxa2xx_pic_mem_write(void *opaque, hwaddr offset,
+                                 uint64_t value, unsigned size)
+{
+    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
+
+    switch (offset) {
+    case ICMR:	/* Mask register */
+        s->int_enabled[0] = value;
+        break;
+    case ICMR2:	/* Mask register 2 */
+        s->int_enabled[1] = value;
+        break;
+    case ICLR:	/* Level register */
+        s->is_fiq[0] = value;
+        break;
+    case ICLR2:	/* Level register 2 */
+        s->is_fiq[1] = value;
+        break;
+    case ICCR:	/* Idle mask */
+        s->int_idle = (value & 1) ? 0 : ~0;
+        break;
+    case IPR0  ... IPR31:
+        s->priority[0  + ((offset - IPR0 ) >> 2)] = value & 0x8000003f;
+        break;
+    case IPR32 ... IPR39:
+        s->priority[32 + ((offset - IPR32) >> 2)] = value & 0x8000003f;
+        break;
+    default:
+        printf("%s: Bad register offset " REG_FMT "\n", __FUNCTION__, offset);
+        return;
+    }
+    pxa2xx_pic_update(opaque);
+}
+
+/* Interrupt Controller Coprocessor Space Register Mapping */
+static const int pxa2xx_cp_reg_map[0x10] = {
+    [0x0 ... 0xf] = -1,
+    [0x0] = ICIP,
+    [0x1] = ICMR,
+    [0x2] = ICLR,
+    [0x3] = ICFP,
+    [0x4] = ICPR,
+    [0x5] = ICHP,
+    [0x6] = ICIP2,
+    [0x7] = ICMR2,
+    [0x8] = ICLR2,
+    [0x9] = ICFP2,
+    [0xa] = ICPR2,
+};
+
+static int pxa2xx_pic_cp_read(CPUARMState *env, const ARMCPRegInfo *ri,
+                              uint64_t *value)
+{
+    int offset = pxa2xx_cp_reg_map[ri->crn];
+    *value = pxa2xx_pic_mem_read(ri->opaque, offset, 4);
+    return 0;
+}
+
+static int pxa2xx_pic_cp_write(CPUARMState *env, const ARMCPRegInfo *ri,
+                               uint64_t value)
+{
+    int offset = pxa2xx_cp_reg_map[ri->crn];
+    pxa2xx_pic_mem_write(ri->opaque, offset, value, 4);
+    return 0;
+}
+
+#define REGINFO_FOR_PIC_CP(NAME, CRN) \
+    { .name = NAME, .cp = 6, .crn = CRN, .crm = 0, .opc1 = 0, .opc2 = 0, \
+      .access = PL1_RW, \
+      .readfn = pxa2xx_pic_cp_read, .writefn = pxa2xx_pic_cp_write }
+
+static const ARMCPRegInfo pxa_pic_cp_reginfo[] = {
+    REGINFO_FOR_PIC_CP("ICIP", 0),
+    REGINFO_FOR_PIC_CP("ICMR", 1),
+    REGINFO_FOR_PIC_CP("ICLR", 2),
+    REGINFO_FOR_PIC_CP("ICFP", 3),
+    REGINFO_FOR_PIC_CP("ICPR", 4),
+    REGINFO_FOR_PIC_CP("ICHP", 5),
+    REGINFO_FOR_PIC_CP("ICIP2", 6),
+    REGINFO_FOR_PIC_CP("ICMR2", 7),
+    REGINFO_FOR_PIC_CP("ICLR2", 8),
+    REGINFO_FOR_PIC_CP("ICFP2", 9),
+    REGINFO_FOR_PIC_CP("ICPR2", 0xa),
+    REGINFO_SENTINEL
+};
+
+static const MemoryRegionOps pxa2xx_pic_ops = {
+    .read = pxa2xx_pic_mem_read,
+    .write = pxa2xx_pic_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int pxa2xx_pic_post_load(void *opaque, int version_id)
+{
+    pxa2xx_pic_update(opaque);
+    return 0;
+}
+
+DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu)
+{
+    CPUARMState *env = &cpu->env;
+    DeviceState *dev = qdev_create(NULL, "pxa2xx_pic");
+    PXA2xxPICState *s = FROM_SYSBUS(PXA2xxPICState, SYS_BUS_DEVICE(dev));
+
+    s->cpu = cpu;
+
+    s->int_pending[0] = 0;
+    s->int_pending[1] = 0;
+    s->int_enabled[0] = 0;
+    s->int_enabled[1] = 0;
+    s->is_fiq[0] = 0;
+    s->is_fiq[1] = 0;
+
+    qdev_init_nofail(dev);
+
+    qdev_init_gpio_in(dev, pxa2xx_pic_set_irq, PXA2XX_PIC_SRCS);
+
+    /* Enable IC memory-mapped registers access.  */
+    memory_region_init_io(&s->iomem, &pxa2xx_pic_ops, s,
+                          "pxa2xx-pic", 0x00100000);
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+
+    /* Enable IC coprocessor access.  */
+    define_arm_cp_regs_with_opaque(arm_env_get_cpu(env), pxa_pic_cp_reginfo, 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(),
+    },
+};
+
+static int pxa2xx_pic_initfn(SysBusDevice *dev)
+{
+    return 0;
+}
+
+static void pxa2xx_pic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = pxa2xx_pic_initfn;
+    dc->desc = "PXA2xx PIC";
+    dc->vmsd = &vmstate_pxa2xx_pic_regs;
+}
+
+static const TypeInfo pxa2xx_pic_info = {
+    .name          = "pxa2xx_pic",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PXA2xxPICState),
+    .class_init    = pxa2xx_pic_class_init,
+};
+
+static void pxa2xx_pic_register_types(void)
+{
+    type_register_static(&pxa2xx_pic_info);
+}
+
+type_init(pxa2xx_pic_register_types)
diff --git a/hw/armv7m.c b/hw/armv7m.c
deleted file mode 100644
index 1d5bb59..0000000
--- a/hw/armv7m.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * ARMV7M System emulation.
- *
- * Copyright (c) 2006-2007 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GPL.
- */
-
-#include "hw/sysbus.h"
-#include "hw/arm-misc.h"
-#include "hw/loader.h"
-#include "elf.h"
-
-/* Bitbanded IO.  Each word corresponds to a single bit.  */
-
-/* Get the byte address of the real memory for a bitband access.  */
-static inline uint32_t bitband_addr(void * opaque, uint32_t addr)
-{
-    uint32_t res;
-
-    res = *(uint32_t *)opaque;
-    res |= (addr & 0x1ffffff) >> 5;
-    return res;
-
-}
-
-static uint32_t bitband_readb(void *opaque, hwaddr offset)
-{
-    uint8_t v;
-    cpu_physical_memory_read(bitband_addr(opaque, offset), &v, 1);
-    return (v & (1 << ((offset >> 2) & 7))) != 0;
-}
-
-static void bitband_writeb(void *opaque, hwaddr offset,
-                           uint32_t value)
-{
-    uint32_t addr;
-    uint8_t mask;
-    uint8_t v;
-    addr = bitband_addr(opaque, offset);
-    mask = (1 << ((offset >> 2) & 7));
-    cpu_physical_memory_read(addr, &v, 1);
-    if (value & 1)
-        v |= mask;
-    else
-        v &= ~mask;
-    cpu_physical_memory_write(addr, &v, 1);
-}
-
-static uint32_t bitband_readw(void *opaque, hwaddr offset)
-{
-    uint32_t addr;
-    uint16_t mask;
-    uint16_t v;
-    addr = bitband_addr(opaque, offset) & ~1;
-    mask = (1 << ((offset >> 2) & 15));
-    mask = tswap16(mask);
-    cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
-    return (v & mask) != 0;
-}
-
-static void bitband_writew(void *opaque, hwaddr offset,
-                           uint32_t value)
-{
-    uint32_t addr;
-    uint16_t mask;
-    uint16_t v;
-    addr = bitband_addr(opaque, offset) & ~1;
-    mask = (1 << ((offset >> 2) & 15));
-    mask = tswap16(mask);
-    cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
-    if (value & 1)
-        v |= mask;
-    else
-        v &= ~mask;
-    cpu_physical_memory_write(addr, (uint8_t *)&v, 2);
-}
-
-static uint32_t bitband_readl(void *opaque, hwaddr offset)
-{
-    uint32_t addr;
-    uint32_t mask;
-    uint32_t v;
-    addr = bitband_addr(opaque, offset) & ~3;
-    mask = (1 << ((offset >> 2) & 31));
-    mask = tswap32(mask);
-    cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
-    return (v & mask) != 0;
-}
-
-static void bitband_writel(void *opaque, hwaddr offset,
-                           uint32_t value)
-{
-    uint32_t addr;
-    uint32_t mask;
-    uint32_t v;
-    addr = bitband_addr(opaque, offset) & ~3;
-    mask = (1 << ((offset >> 2) & 31));
-    mask = tswap32(mask);
-    cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
-    if (value & 1)
-        v |= mask;
-    else
-        v &= ~mask;
-    cpu_physical_memory_write(addr, (uint8_t *)&v, 4);
-}
-
-static const MemoryRegionOps bitband_ops = {
-    .old_mmio = {
-        .read = { bitband_readb, bitband_readw, bitband_readl, },
-        .write = { bitband_writeb, bitband_writew, bitband_writel, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t base;
-} BitBandState;
-
-static int bitband_init(SysBusDevice *dev)
-{
-    BitBandState *s = FROM_SYSBUS(BitBandState, dev);
-
-    memory_region_init_io(&s->iomem, &bitband_ops, &s->base, "bitband",
-                          0x02000000);
-    sysbus_init_mmio(dev, &s->iomem);
-    return 0;
-}
-
-static void armv7m_bitband_init(void)
-{
-    DeviceState *dev;
-
-    dev = qdev_create(NULL, "ARM,bitband-memory");
-    qdev_prop_set_uint32(dev, "base", 0x20000000);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x22000000);
-
-    dev = qdev_create(NULL, "ARM,bitband-memory");
-    qdev_prop_set_uint32(dev, "base", 0x40000000);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x42000000);
-}
-
-/* Board init.  */
-
-static void armv7m_reset(void *opaque)
-{
-    ARMCPU *cpu = opaque;
-
-    cpu_reset(CPU(cpu));
-}
-
-/* Init CPU and memory for a v7-M based board.
-   flash_size and sram_size are in kb.
-   Returns the NVIC array.  */
-
-qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
-                      int flash_size, int sram_size,
-                      const char *kernel_filename, const char *cpu_model)
-{
-    ARMCPU *cpu;
-    CPUARMState *env;
-    DeviceState *nvic;
-    /* FIXME: make this local state.  */
-    static qemu_irq pic[64];
-    qemu_irq *cpu_pic;
-    int image_size;
-    uint64_t entry;
-    uint64_t lowaddr;
-    int i;
-    int big_endian;
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-    MemoryRegion *flash = g_new(MemoryRegion, 1);
-    MemoryRegion *hack = g_new(MemoryRegion, 1);
-
-    flash_size *= 1024;
-    sram_size *= 1024;
-
-    if (cpu_model == NULL) {
-	cpu_model = "cortex-m3";
-    }
-    cpu = cpu_arm_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-#if 0
-    /* > 32Mb SRAM gets complicated because it overlaps the bitband area.
-       We don't have proper commandline options, so allocate half of memory
-       as SRAM, up to a maximum of 32Mb, and the rest as code.  */
-    if (ram_size > (512 + 32) * 1024 * 1024)
-        ram_size = (512 + 32) * 1024 * 1024;
-    sram_size = (ram_size / 2) & TARGET_PAGE_MASK;
-    if (sram_size > 32 * 1024 * 1024)
-        sram_size = 32 * 1024 * 1024;
-    code_size = ram_size - sram_size;
-#endif
-
-    /* Flash programming is done via the SCU, so pretend it is ROM.  */
-    memory_region_init_ram(flash, "armv7m.flash", flash_size);
-    vmstate_register_ram_global(flash);
-    memory_region_set_readonly(flash, true);
-    memory_region_add_subregion(address_space_mem, 0, flash);
-    memory_region_init_ram(sram, "armv7m.sram", sram_size);
-    vmstate_register_ram_global(sram);
-    memory_region_add_subregion(address_space_mem, 0x20000000, sram);
-    armv7m_bitband_init();
-
-    nvic = qdev_create(NULL, "armv7m_nvic");
-    env->nvic = nvic;
-    qdev_init_nofail(nvic);
-    cpu_pic = arm_pic_init_cpu(cpu);
-    sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]);
-    for (i = 0; i < 64; i++) {
-        pic[i] = qdev_get_gpio_in(nvic, i);
-    }
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    big_endian = 1;
-#else
-    big_endian = 0;
-#endif
-
-    if (!kernel_filename) {
-        fprintf(stderr, "Guest image must be specified (using -kernel)\n");
-        exit(1);
-    }
-
-    image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
-                          NULL, big_endian, ELF_MACHINE, 1);
-    if (image_size < 0) {
-        image_size = load_image_targphys(kernel_filename, 0, flash_size);
-	lowaddr = 0;
-    }
-    if (image_size < 0) {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                kernel_filename);
-        exit(1);
-    }
-
-    /* Hack to map an additional page of ram at the top of the address
-       space.  This stops qemu complaining about executing code outside RAM
-       when returning from an exception.  */
-    memory_region_init_ram(hack, "armv7m.hack", 0x1000);
-    vmstate_register_ram_global(hack);
-    memory_region_add_subregion(address_space_mem, 0xfffff000, hack);
-
-    qemu_register_reset(armv7m_reset, cpu);
-    return pic;
-}
-
-static Property bitband_properties[] = {
-    DEFINE_PROP_UINT32("base", BitBandState, base, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void bitband_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = bitband_init;
-    dc->props = bitband_properties;
-}
-
-static const TypeInfo bitband_info = {
-    .name          = "ARM,bitband-memory",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(BitBandState),
-    .class_init    = bitband_class_init,
-};
-
-static void armv7m_register_types(void)
-{
-    type_register_static(&bitband_info);
-}
-
-type_init(armv7m_register_types)
diff --git a/hw/exynos4210.c b/hw/exynos4210.c
deleted file mode 100644
index 4592514..0000000
--- a/hw/exynos4210.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- *  Samsung exynos4210 SoC emulation
- *
- *  Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *    Maksim Kozlov <m.kozlov at samsung.com>
- *    Evgeny Voevodin <e.voevodin at samsung.com>
- *    Igor Mitsyanko  <i.mitsyanko at samsung.com>
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "hw/boards.h"
-#include "sysemu/sysemu.h"
-#include "hw/sysbus.h"
-#include "hw/arm-misc.h"
-#include "hw/loader.h"
-#include "hw/exynos4210.h"
-#include "hw/usb/hcd-ehci.h"
-
-#define EXYNOS4210_CHIPID_ADDR         0x10000000
-
-/* PWM */
-#define EXYNOS4210_PWM_BASE_ADDR       0x139D0000
-
-/* RTC */
-#define EXYNOS4210_RTC_BASE_ADDR       0x10070000
-
-/* MCT */
-#define EXYNOS4210_MCT_BASE_ADDR       0x10050000
-
-/* I2C */
-#define EXYNOS4210_I2C_SHIFT           0x00010000
-#define EXYNOS4210_I2C_BASE_ADDR       0x13860000
-/* Interrupt Group of External Interrupt Combiner for I2C */
-#define EXYNOS4210_I2C_INTG            27
-#define EXYNOS4210_HDMI_INTG           16
-
-/* UART's definitions */
-#define EXYNOS4210_UART0_BASE_ADDR     0x13800000
-#define EXYNOS4210_UART1_BASE_ADDR     0x13810000
-#define EXYNOS4210_UART2_BASE_ADDR     0x13820000
-#define EXYNOS4210_UART3_BASE_ADDR     0x13830000
-#define EXYNOS4210_UART0_FIFO_SIZE     256
-#define EXYNOS4210_UART1_FIFO_SIZE     64
-#define EXYNOS4210_UART2_FIFO_SIZE     16
-#define EXYNOS4210_UART3_FIFO_SIZE     16
-/* Interrupt Group of External Interrupt Combiner for UART */
-#define EXYNOS4210_UART_INT_GRP        26
-
-/* External GIC */
-#define EXYNOS4210_EXT_GIC_CPU_BASE_ADDR    0x10480000
-#define EXYNOS4210_EXT_GIC_DIST_BASE_ADDR   0x10490000
-
-/* Combiner */
-#define EXYNOS4210_EXT_COMBINER_BASE_ADDR   0x10440000
-#define EXYNOS4210_INT_COMBINER_BASE_ADDR   0x10448000
-
-/* PMU SFR base address */
-#define EXYNOS4210_PMU_BASE_ADDR            0x10020000
-
-/* Display controllers (FIMD) */
-#define EXYNOS4210_FIMD0_BASE_ADDR          0x11C00000
-
-/* EHCI */
-#define EXYNOS4210_EHCI_BASE_ADDR           0x12580000
-
-static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
-                                    0x09, 0x00, 0x00, 0x00 };
-
-void exynos4210_write_secondary(ARMCPU *cpu,
-        const struct arm_boot_info *info)
-{
-    int n;
-    uint32_t smpboot[] = {
-        0xe59f3034, /* ldr r3, External gic_cpu_if */
-        0xe59f2034, /* ldr r2, Internal gic_cpu_if */
-        0xe59f0034, /* ldr r0, startaddr */
-        0xe3a01001, /* mov r1, #1 */
-        0xe5821000, /* str r1, [r2] */
-        0xe5831000, /* str r1, [r3] */
-        0xe3a010ff, /* mov r1, #0xff */
-        0xe5821004, /* str r1, [r2, #4] */
-        0xe5831004, /* str r1, [r3, #4] */
-        0xf57ff04f, /* dsb */
-        0xe320f003, /* wfi */
-        0xe5901000, /* ldr     r1, [r0] */
-        0xe1110001, /* tst     r1, r1 */
-        0x0afffffb, /* beq     <wfi> */
-        0xe12fff11, /* bx      r1 */
-        EXYNOS4210_EXT_GIC_CPU_BASE_ADDR,
-        0,          /* gic_cpu_if: base address of Internal GIC CPU interface */
-        0           /* bootreg: Boot register address is held here */
-    };
-    smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
-    smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr;
-    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
-        smpboot[n] = tswap32(smpboot[n]);
-    }
-    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
-                       info->smp_loader_start);
-}
-
-Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
-        unsigned long ram_size)
-{
-    qemu_irq cpu_irq[EXYNOS4210_NCPUS];
-    int i, n;
-    Exynos4210State *s = g_new(Exynos4210State, 1);
-    qemu_irq *irqp;
-    qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
-    unsigned long mem_size;
-    DeviceState *dev;
-    SysBusDevice *busdev;
-
-    for (n = 0; n < EXYNOS4210_NCPUS; n++) {
-        s->cpu[n] = cpu_arm_init("cortex-a9");
-        if (!s->cpu[n]) {
-            fprintf(stderr, "Unable to find CPU %d definition\n", n);
-            exit(1);
-        }
-
-        /* Create PIC controller for each processor instance */
-        irqp = arm_pic_init_cpu(s->cpu[n]);
-
-        /*
-         * Get GICs gpio_in cpu_irq to connect a combiner to them later.
-         * Use only IRQ for a while.
-         */
-        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
-    }
-
-    /*** IRQs ***/
-
-    s->irq_table = exynos4210_init_irq(&s->irqs);
-
-    /* IRQ Gate */
-    for (i = 0; i < EXYNOS4210_NCPUS; i++) {
-        dev = qdev_create(NULL, "exynos4210.irq_gate");
-        qdev_prop_set_uint32(dev, "n_in", EXYNOS4210_IRQ_GATE_NINPUTS);
-        qdev_init_nofail(dev);
-        /* Get IRQ Gate input in gate_irq */
-        for (n = 0; n < EXYNOS4210_IRQ_GATE_NINPUTS; n++) {
-            gate_irq[i][n] = qdev_get_gpio_in(dev, n);
-        }
-        busdev = SYS_BUS_DEVICE(dev);
-
-        /* Connect IRQ Gate output to cpu_irq */
-        sysbus_connect_irq(busdev, 0, cpu_irq[i]);
-    }
-
-    /* Private memory region and Internal GIC */
-    dev = qdev_create(NULL, "a9mpcore_priv");
-    qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
-    for (n = 0; n < EXYNOS4210_NCPUS; n++) {
-        sysbus_connect_irq(busdev, n, gate_irq[n][0]);
-    }
-    for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
-        s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
-    }
-
-    /* Cache controller */
-    sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
-
-    /* External GIC */
-    dev = qdev_create(NULL, "exynos4210.gic");
-    qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    /* Map CPU interface */
-    sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_GIC_CPU_BASE_ADDR);
-    /* Map Distributer interface */
-    sysbus_mmio_map(busdev, 1, EXYNOS4210_EXT_GIC_DIST_BASE_ADDR);
-    for (n = 0; n < EXYNOS4210_NCPUS; n++) {
-        sysbus_connect_irq(busdev, n, gate_irq[n][1]);
-    }
-    for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
-        s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
-    }
-
-    /* Internal Interrupt Combiner */
-    dev = qdev_create(NULL, "exynos4210.combiner");
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
-        sysbus_connect_irq(busdev, n, s->irqs.int_gic_irq[n]);
-    }
-    exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
-    sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
-
-    /* External Interrupt Combiner */
-    dev = qdev_create(NULL, "exynos4210.combiner");
-    qdev_prop_set_uint32(dev, "external", 1);
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
-        sysbus_connect_irq(busdev, n, s->irqs.ext_gic_irq[n]);
-    }
-    exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
-    sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
-
-    /* Initialize board IRQs. */
-    exynos4210_init_board_irqs(&s->irqs);
-
-    /*** Memory ***/
-
-    /* Chip-ID and OMR */
-    memory_region_init_ram_ptr(&s->chipid_mem, "exynos4210.chipid",
-            sizeof(chipid_and_omr), chipid_and_omr);
-    memory_region_set_readonly(&s->chipid_mem, true);
-    memory_region_add_subregion(system_mem, EXYNOS4210_CHIPID_ADDR,
-                                &s->chipid_mem);
-
-    /* Internal ROM */
-    memory_region_init_ram(&s->irom_mem, "exynos4210.irom",
-                           EXYNOS4210_IROM_SIZE);
-    memory_region_set_readonly(&s->irom_mem, true);
-    memory_region_add_subregion(system_mem, EXYNOS4210_IROM_BASE_ADDR,
-                                &s->irom_mem);
-    /* mirror of iROM */
-    memory_region_init_alias(&s->irom_alias_mem, "exynos4210.irom_alias",
-                             &s->irom_mem,
-                             0,
-                             EXYNOS4210_IROM_SIZE);
-    memory_region_set_readonly(&s->irom_alias_mem, true);
-    memory_region_add_subregion(system_mem, EXYNOS4210_IROM_MIRROR_BASE_ADDR,
-                                &s->irom_alias_mem);
-
-    /* Internal RAM */
-    memory_region_init_ram(&s->iram_mem, "exynos4210.iram",
-                           EXYNOS4210_IRAM_SIZE);
-    vmstate_register_ram_global(&s->iram_mem);
-    memory_region_add_subregion(system_mem, EXYNOS4210_IRAM_BASE_ADDR,
-                                &s->iram_mem);
-
-    /* DRAM */
-    mem_size = ram_size;
-    if (mem_size > EXYNOS4210_DRAM_MAX_SIZE) {
-        memory_region_init_ram(&s->dram1_mem, "exynos4210.dram1",
-                mem_size - EXYNOS4210_DRAM_MAX_SIZE);
-        vmstate_register_ram_global(&s->dram1_mem);
-        memory_region_add_subregion(system_mem, EXYNOS4210_DRAM1_BASE_ADDR,
-                &s->dram1_mem);
-        mem_size = EXYNOS4210_DRAM_MAX_SIZE;
-    }
-    memory_region_init_ram(&s->dram0_mem, "exynos4210.dram0", mem_size);
-    vmstate_register_ram_global(&s->dram0_mem);
-    memory_region_add_subregion(system_mem, EXYNOS4210_DRAM0_BASE_ADDR,
-            &s->dram0_mem);
-
-   /* PMU.
-    * The only reason of existence at the moment is that secondary CPU boot
-    * loader uses PMU INFORM5 register as a holding pen.
-    */
-    sysbus_create_simple("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL);
-
-    /* PWM */
-    sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR,
-                          s->irq_table[exynos4210_get_irq(22, 0)],
-                          s->irq_table[exynos4210_get_irq(22, 1)],
-                          s->irq_table[exynos4210_get_irq(22, 2)],
-                          s->irq_table[exynos4210_get_irq(22, 3)],
-                          s->irq_table[exynos4210_get_irq(22, 4)],
-                          NULL);
-    /* RTC */
-    sysbus_create_varargs("exynos4210.rtc", EXYNOS4210_RTC_BASE_ADDR,
-                          s->irq_table[exynos4210_get_irq(23, 0)],
-                          s->irq_table[exynos4210_get_irq(23, 1)],
-                          NULL);
-
-    /* Multi Core Timer */
-    dev = qdev_create(NULL, "exynos4210.mct");
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    for (n = 0; n < 4; n++) {
-        /* Connect global timer interrupts to Combiner gpio_in */
-        sysbus_connect_irq(busdev, n,
-                s->irq_table[exynos4210_get_irq(1, 4 + n)]);
-    }
-    /* Connect local timer interrupts to Combiner gpio_in */
-    sysbus_connect_irq(busdev, 4,
-            s->irq_table[exynos4210_get_irq(51, 0)]);
-    sysbus_connect_irq(busdev, 5,
-            s->irq_table[exynos4210_get_irq(35, 3)]);
-    sysbus_mmio_map(busdev, 0, EXYNOS4210_MCT_BASE_ADDR);
-
-    /*** I2C ***/
-    for (n = 0; n < EXYNOS4210_I2C_NUMBER; n++) {
-        uint32_t addr = EXYNOS4210_I2C_BASE_ADDR + EXYNOS4210_I2C_SHIFT * n;
-        qemu_irq i2c_irq;
-
-        if (n < 8) {
-            i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_I2C_INTG, n)];
-        } else {
-            i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_HDMI_INTG, 1)];
-        }
-
-        dev = qdev_create(NULL, "exynos4210.i2c");
-        qdev_init_nofail(dev);
-        busdev = SYS_BUS_DEVICE(dev);
-        sysbus_connect_irq(busdev, 0, i2c_irq);
-        sysbus_mmio_map(busdev, 0, addr);
-        s->i2c_if[n] = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
-    }
-
-
-    /*** UARTs ***/
-    exynos4210_uart_create(EXYNOS4210_UART0_BASE_ADDR,
-                           EXYNOS4210_UART0_FIFO_SIZE, 0, NULL,
-                  s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 0)]);
-
-    exynos4210_uart_create(EXYNOS4210_UART1_BASE_ADDR,
-                           EXYNOS4210_UART1_FIFO_SIZE, 1, NULL,
-                  s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 1)]);
-
-    exynos4210_uart_create(EXYNOS4210_UART2_BASE_ADDR,
-                           EXYNOS4210_UART2_FIFO_SIZE, 2, NULL,
-                  s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 2)]);
-
-    exynos4210_uart_create(EXYNOS4210_UART3_BASE_ADDR,
-                           EXYNOS4210_UART3_FIFO_SIZE, 3, NULL,
-                  s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 3)]);
-
-    /*** Display controller (FIMD) ***/
-    sysbus_create_varargs("exynos4210.fimd", EXYNOS4210_FIMD0_BASE_ADDR,
-            s->irq_table[exynos4210_get_irq(11, 0)],
-            s->irq_table[exynos4210_get_irq(11, 1)],
-            s->irq_table[exynos4210_get_irq(11, 2)],
-            NULL);
-
-    sysbus_create_simple(TYPE_EXYNOS4210_EHCI, EXYNOS4210_EHCI_BASE_ADDR,
-            s->irq_table[exynos4210_get_irq(28, 3)]);
-
-    return s;
-}
diff --git a/hw/omap1.c b/hw/omap1.c
deleted file mode 100644
index 6f0a8ca..0000000
--- a/hw/omap1.c
+++ /dev/null
@@ -1,4056 +0,0 @@
-/*
- * TI OMAP processors emulation.
- *
- * Copyright (C) 2006-2008 Andrzej Zaborowski  <balrog at zabor.org>
- *
- * 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 or
- * (at your option) version 3 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 "hw/arm-misc.h"
-#include "hw/omap.h"
-#include "sysemu/sysemu.h"
-#include "hw/soc_dma.h"
-#include "sysemu/blockdev.h"
-#include "qemu/range.h"
-#include "hw/sysbus.h"
-
-/* Should signal the TCMI/GPMC */
-uint32_t omap_badwidth_read8(void *opaque, hwaddr addr)
-{
-    uint8_t ret;
-
-    OMAP_8B_REG(addr);
-    cpu_physical_memory_read(addr, (void *) &ret, 1);
-    return ret;
-}
-
-void omap_badwidth_write8(void *opaque, hwaddr addr,
-                uint32_t value)
-{
-    uint8_t val8 = value;
-
-    OMAP_8B_REG(addr);
-    cpu_physical_memory_write(addr, (void *) &val8, 1);
-}
-
-uint32_t omap_badwidth_read16(void *opaque, hwaddr addr)
-{
-    uint16_t ret;
-
-    OMAP_16B_REG(addr);
-    cpu_physical_memory_read(addr, (void *) &ret, 2);
-    return ret;
-}
-
-void omap_badwidth_write16(void *opaque, hwaddr addr,
-                uint32_t value)
-{
-    uint16_t val16 = value;
-
-    OMAP_16B_REG(addr);
-    cpu_physical_memory_write(addr, (void *) &val16, 2);
-}
-
-uint32_t omap_badwidth_read32(void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-    OMAP_32B_REG(addr);
-    cpu_physical_memory_read(addr, (void *) &ret, 4);
-    return ret;
-}
-
-void omap_badwidth_write32(void *opaque, hwaddr addr,
-                uint32_t value)
-{
-    OMAP_32B_REG(addr);
-    cpu_physical_memory_write(addr, (void *) &value, 4);
-}
-
-/* MPU OS timers */
-struct omap_mpu_timer_s {
-    MemoryRegion iomem;
-    qemu_irq irq;
-    omap_clk clk;
-    uint32_t val;
-    int64_t time;
-    QEMUTimer *timer;
-    QEMUBH *tick;
-    int64_t rate;
-    int it_ena;
-
-    int enable;
-    int ptv;
-    int ar;
-    int st;
-    uint32_t reset_val;
-};
-
-static inline uint32_t omap_timer_read(struct omap_mpu_timer_s *timer)
-{
-    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),
-                                     timer->rate, get_ticks_per_sec());
-    else
-        return timer->val;
-}
-
-static inline void omap_timer_sync(struct omap_mpu_timer_s *timer)
-{
-    timer->val = omap_timer_read(timer);
-    timer->time = qemu_get_clock_ns(vm_clock);
-}
-
-static inline void omap_timer_update(struct omap_mpu_timer_s *timer)
-{
-    int64_t expires;
-
-    if (timer->enable && timer->st && timer->rate) {
-        timer->val = timer->reset_val;	/* Should skip this on clk enable */
-        expires = muldiv64((uint64_t) timer->val << (timer->ptv + 1),
-                           get_ticks_per_sec(), timer->rate);
-
-        /* If timer expiry would be sooner than in about 1 ms and
-         * auto-reload isn't set, then fire immediately.  This is a hack
-         * to make systems like PalmOS run in acceptable time.  PalmOS
-         * sets the interval to a very low value and polls the status bit
-         * in a busy loop when it wants to sleep just a couple of CPU
-         * ticks.  */
-        if (expires > (get_ticks_per_sec() >> 10) || timer->ar)
-            qemu_mod_timer(timer->timer, timer->time + expires);
-        else
-            qemu_bh_schedule(timer->tick);
-    } else
-        qemu_del_timer(timer->timer);
-}
-
-static void omap_timer_fire(void *opaque)
-{
-    struct omap_mpu_timer_s *timer = opaque;
-
-    if (!timer->ar) {
-        timer->val = 0;
-        timer->st = 0;
-    }
-
-    if (timer->it_ena)
-        /* Edge-triggered irq */
-        qemu_irq_pulse(timer->irq);
-}
-
-static void omap_timer_tick(void *opaque)
-{
-    struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
-
-    omap_timer_sync(timer);
-    omap_timer_fire(timer);
-    omap_timer_update(timer);
-}
-
-static void omap_timer_clk_update(void *opaque, int line, int on)
-{
-    struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
-
-    omap_timer_sync(timer);
-    timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
-    omap_timer_update(timer);
-}
-
-static void omap_timer_clk_setup(struct omap_mpu_timer_s *timer)
-{
-    omap_clk_adduser(timer->clk,
-                    qemu_allocate_irqs(omap_timer_clk_update, timer, 1)[0]);
-    timer->rate = omap_clk_getrate(timer->clk);
-}
-
-static uint64_t omap_mpu_timer_read(void *opaque, hwaddr addr,
-                                    unsigned size)
-{
-    struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_read32(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x00:	/* CNTL_TIMER */
-        return (s->enable << 5) | (s->ptv << 2) | (s->ar << 1) | s->st;
-
-    case 0x04:	/* LOAD_TIM */
-        break;
-
-    case 0x08:	/* READ_TIM */
-        return omap_timer_read(s);
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_mpu_timer_write(void *opaque, hwaddr addr,
-                                 uint64_t value, unsigned size)
-{
-    struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_write32(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00:	/* CNTL_TIMER */
-        omap_timer_sync(s);
-        s->enable = (value >> 5) & 1;
-        s->ptv = (value >> 2) & 7;
-        s->ar = (value >> 1) & 1;
-        s->st = value & 1;
-        omap_timer_update(s);
-        return;
-
-    case 0x04:	/* LOAD_TIM */
-        s->reset_val = value;
-        return;
-
-    case 0x08:	/* READ_TIM */
-        OMAP_RO_REG(addr);
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_mpu_timer_ops = {
-    .read = omap_mpu_timer_read,
-    .write = omap_mpu_timer_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static void omap_mpu_timer_reset(struct omap_mpu_timer_s *s)
-{
-    qemu_del_timer(s->timer);
-    s->enable = 0;
-    s->reset_val = 31337;
-    s->val = 0;
-    s->ptv = 0;
-    s->ar = 0;
-    s->st = 0;
-    s->it_ena = 1;
-}
-
-static struct omap_mpu_timer_s *omap_mpu_timer_init(MemoryRegion *system_memory,
-                hwaddr base,
-                qemu_irq irq, omap_clk clk)
-{
-    struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *)
-            g_malloc0(sizeof(struct omap_mpu_timer_s));
-
-    s->irq = irq;
-    s->clk = clk;
-    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);
-
-    memory_region_init_io(&s->iomem, &omap_mpu_timer_ops, s,
-                          "omap-mpu-timer", 0x100);
-
-    memory_region_add_subregion(system_memory, base, &s->iomem);
-
-    return s;
-}
-
-/* Watchdog timer */
-struct omap_watchdog_timer_s {
-    struct omap_mpu_timer_s timer;
-    MemoryRegion iomem;
-    uint8_t last_wr;
-    int mode;
-    int free;
-    int reset;
-};
-
-static uint64_t omap_wd_timer_read(void *opaque, hwaddr addr,
-                                   unsigned size)
-{
-    struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x00:	/* CNTL_TIMER */
-        return (s->timer.ptv << 9) | (s->timer.ar << 8) |
-                (s->timer.st << 7) | (s->free << 1);
-
-    case 0x04:	/* READ_TIMER */
-        return omap_timer_read(&s->timer);
-
-    case 0x08:	/* TIMER_MODE */
-        return s->mode << 15;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_wd_timer_write(void *opaque, hwaddr addr,
-                                uint64_t value, unsigned size)
-{
-    struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
-
-    if (size != 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00:	/* CNTL_TIMER */
-        omap_timer_sync(&s->timer);
-        s->timer.ptv = (value >> 9) & 7;
-        s->timer.ar = (value >> 8) & 1;
-        s->timer.st = (value >> 7) & 1;
-        s->free = (value >> 1) & 1;
-        omap_timer_update(&s->timer);
-        break;
-
-    case 0x04:	/* LOAD_TIMER */
-        s->timer.reset_val = value & 0xffff;
-        break;
-
-    case 0x08:	/* TIMER_MODE */
-        if (!s->mode && ((value >> 15) & 1))
-            omap_clk_get(s->timer.clk);
-        s->mode |= (value >> 15) & 1;
-        if (s->last_wr == 0xf5) {
-            if ((value & 0xff) == 0xa0) {
-                if (s->mode) {
-                    s->mode = 0;
-                    omap_clk_put(s->timer.clk);
-                }
-            } else {
-                /* XXX: on T|E hardware somehow this has no effect,
-                 * on Zire 71 it works as specified.  */
-                s->reset = 1;
-                qemu_system_reset_request();
-            }
-        }
-        s->last_wr = value & 0xff;
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_wd_timer_ops = {
-    .read = omap_wd_timer_read,
-    .write = omap_wd_timer_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_wd_timer_reset(struct omap_watchdog_timer_s *s)
-{
-    qemu_del_timer(s->timer.timer);
-    if (!s->mode)
-        omap_clk_get(s->timer.clk);
-    s->mode = 1;
-    s->free = 1;
-    s->reset = 0;
-    s->timer.enable = 1;
-    s->timer.it_ena = 1;
-    s->timer.reset_val = 0xffff;
-    s->timer.val = 0;
-    s->timer.st = 0;
-    s->timer.ptv = 0;
-    s->timer.ar = 0;
-    omap_timer_update(&s->timer);
-}
-
-static struct omap_watchdog_timer_s *omap_wd_timer_init(MemoryRegion *memory,
-                hwaddr base,
-                qemu_irq irq, omap_clk clk)
-{
-    struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *)
-            g_malloc0(sizeof(struct omap_watchdog_timer_s));
-
-    s->timer.irq = irq;
-    s->timer.clk = clk;
-    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);
-
-    memory_region_init_io(&s->iomem, &omap_wd_timer_ops, s,
-                          "omap-wd-timer", 0x100);
-    memory_region_add_subregion(memory, base, &s->iomem);
-
-    return s;
-}
-
-/* 32-kHz timer */
-struct omap_32khz_timer_s {
-    struct omap_mpu_timer_s timer;
-    MemoryRegion iomem;
-};
-
-static uint64_t omap_os_timer_read(void *opaque, hwaddr addr,
-                                   unsigned size)
-{
-    struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 4) {
-        return omap_badwidth_read32(opaque, addr);
-    }
-
-    switch (offset) {
-    case 0x00:	/* TVR */
-        return s->timer.reset_val;
-
-    case 0x04:	/* TCR */
-        return omap_timer_read(&s->timer);
-
-    case 0x08:	/* CR */
-        return (s->timer.ar << 3) | (s->timer.it_ena << 2) | s->timer.st;
-
-    default:
-        break;
-    }
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_os_timer_write(void *opaque, hwaddr addr,
-                                uint64_t value, unsigned size)
-{
-    struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 4) {
-        return omap_badwidth_write32(opaque, addr, value);
-    }
-
-    switch (offset) {
-    case 0x00:	/* TVR */
-        s->timer.reset_val = value & 0x00ffffff;
-        break;
-
-    case 0x04:	/* TCR */
-        OMAP_RO_REG(addr);
-        break;
-
-    case 0x08:	/* CR */
-        s->timer.ar = (value >> 3) & 1;
-        s->timer.it_ena = (value >> 2) & 1;
-        if (s->timer.st != (value & 1) || (value & 2)) {
-            omap_timer_sync(&s->timer);
-            s->timer.enable = value & 1;
-            s->timer.st = value & 1;
-            omap_timer_update(&s->timer);
-        }
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_os_timer_ops = {
-    .read = omap_os_timer_read,
-    .write = omap_os_timer_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_os_timer_reset(struct omap_32khz_timer_s *s)
-{
-    qemu_del_timer(s->timer.timer);
-    s->timer.enable = 0;
-    s->timer.it_ena = 0;
-    s->timer.reset_val = 0x00ffffff;
-    s->timer.val = 0;
-    s->timer.st = 0;
-    s->timer.ptv = 0;
-    s->timer.ar = 1;
-}
-
-static struct omap_32khz_timer_s *omap_os_timer_init(MemoryRegion *memory,
-                hwaddr base,
-                qemu_irq irq, omap_clk clk)
-{
-    struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *)
-            g_malloc0(sizeof(struct omap_32khz_timer_s));
-
-    s->timer.irq = irq;
-    s->timer.clk = clk;
-    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);
-
-    memory_region_init_io(&s->iomem, &omap_os_timer_ops, s,
-                          "omap-os-timer", 0x800);
-    memory_region_add_subregion(memory, base, &s->iomem);
-
-    return s;
-}
-
-/* Ultra Low-Power Device Module */
-static uint64_t omap_ulpd_pm_read(void *opaque, hwaddr addr,
-                                  unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    uint16_t ret;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x14:	/* IT_STATUS */
-        ret = s->ulpd_pm_regs[addr >> 2];
-        s->ulpd_pm_regs[addr >> 2] = 0;
-        qemu_irq_lower(qdev_get_gpio_in(s->ih[1], OMAP_INT_GAUGE_32K));
-        return ret;
-
-    case 0x18:	/* Reserved */
-    case 0x1c:	/* Reserved */
-    case 0x20:	/* Reserved */
-    case 0x28:	/* Reserved */
-    case 0x2c:	/* Reserved */
-        OMAP_BAD_REG(addr);
-        /* fall through */
-    case 0x00:	/* COUNTER_32_LSB */
-    case 0x04:	/* COUNTER_32_MSB */
-    case 0x08:	/* COUNTER_HIGH_FREQ_LSB */
-    case 0x0c:	/* COUNTER_HIGH_FREQ_MSB */
-    case 0x10:	/* GAUGING_CTRL */
-    case 0x24:	/* SETUP_ANALOG_CELL3_ULPD1 */
-    case 0x30:	/* CLOCK_CTRL */
-    case 0x34:	/* SOFT_REQ */
-    case 0x38:	/* COUNTER_32_FIQ */
-    case 0x3c:	/* DPLL_CTRL */
-    case 0x40:	/* STATUS_REQ */
-        /* XXX: check clk::usecount state for every clock */
-    case 0x48:	/* LOCL_TIME */
-    case 0x4c:	/* APLL_CTRL */
-    case 0x50:	/* POWER_CTRL */
-        return s->ulpd_pm_regs[addr >> 2];
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static inline void omap_ulpd_clk_update(struct omap_mpu_state_s *s,
-                uint16_t diff, uint16_t value)
-{
-    if (diff & (1 << 4))				/* USB_MCLK_EN */
-        omap_clk_onoff(omap_findclk(s, "usb_clk0"), (value >> 4) & 1);
-    if (diff & (1 << 5))				/* DIS_USB_PVCI_CLK */
-        omap_clk_onoff(omap_findclk(s, "usb_w2fc_ck"), (~value >> 5) & 1);
-}
-
-static inline void omap_ulpd_req_update(struct omap_mpu_state_s *s,
-                uint16_t diff, uint16_t value)
-{
-    if (diff & (1 << 0))				/* SOFT_DPLL_REQ */
-        omap_clk_canidle(omap_findclk(s, "dpll4"), (~value >> 0) & 1);
-    if (diff & (1 << 1))				/* SOFT_COM_REQ */
-        omap_clk_canidle(omap_findclk(s, "com_mclk_out"), (~value >> 1) & 1);
-    if (diff & (1 << 2))				/* SOFT_SDW_REQ */
-        omap_clk_canidle(omap_findclk(s, "bt_mclk_out"), (~value >> 2) & 1);
-    if (diff & (1 << 3))				/* SOFT_USB_REQ */
-        omap_clk_canidle(omap_findclk(s, "usb_clk0"), (~value >> 3) & 1);
-}
-
-static void omap_ulpd_pm_write(void *opaque, hwaddr addr,
-                               uint64_t value, unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    int64_t now, ticks;
-    int div, mult;
-    static const int bypass_div[4] = { 1, 2, 4, 4 };
-    uint16_t diff;
-
-    if (size != 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00:	/* COUNTER_32_LSB */
-    case 0x04:	/* COUNTER_32_MSB */
-    case 0x08:	/* COUNTER_HIGH_FREQ_LSB */
-    case 0x0c:	/* COUNTER_HIGH_FREQ_MSB */
-    case 0x14:	/* IT_STATUS */
-    case 0x40:	/* STATUS_REQ */
-        OMAP_RO_REG(addr);
-        break;
-
-    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_ns(vm_clock);
-
-            if (value & 1)
-                s->ulpd_gauge_start = now;
-            else {
-                now -= s->ulpd_gauge_start;
-
-                /* 32-kHz ticks */
-                ticks = muldiv64(now, 32768, get_ticks_per_sec());
-                s->ulpd_pm_regs[0x00 >> 2] = (ticks >>  0) & 0xffff;
-                s->ulpd_pm_regs[0x04 >> 2] = (ticks >> 16) & 0xffff;
-                if (ticks >> 32)	/* OVERFLOW_32K */
-                    s->ulpd_pm_regs[0x14 >> 2] |= 1 << 2;
-
-                /* High frequency ticks */
-                ticks = muldiv64(now, 12000000, get_ticks_per_sec());
-                s->ulpd_pm_regs[0x08 >> 2] = (ticks >>  0) & 0xffff;
-                s->ulpd_pm_regs[0x0c >> 2] = (ticks >> 16) & 0xffff;
-                if (ticks >> 32)	/* OVERFLOW_HI_FREQ */
-                    s->ulpd_pm_regs[0x14 >> 2] |= 1 << 1;
-
-                s->ulpd_pm_regs[0x14 >> 2] |= 1 << 0;	/* IT_GAUGING */
-                qemu_irq_raise(qdev_get_gpio_in(s->ih[1], OMAP_INT_GAUGE_32K));
-            }
-        }
-        s->ulpd_pm_regs[addr >> 2] = value;
-        break;
-
-    case 0x18:	/* Reserved */
-    case 0x1c:	/* Reserved */
-    case 0x20:	/* Reserved */
-    case 0x28:	/* Reserved */
-    case 0x2c:	/* Reserved */
-        OMAP_BAD_REG(addr);
-        /* fall through */
-    case 0x24:	/* SETUP_ANALOG_CELL3_ULPD1 */
-    case 0x38:	/* COUNTER_32_FIQ */
-    case 0x48:	/* LOCL_TIME */
-    case 0x50:	/* POWER_CTRL */
-        s->ulpd_pm_regs[addr >> 2] = value;
-        break;
-
-    case 0x30:	/* CLOCK_CTRL */
-        diff = s->ulpd_pm_regs[addr >> 2] ^ value;
-        s->ulpd_pm_regs[addr >> 2] = value & 0x3f;
-        omap_ulpd_clk_update(s, diff, value);
-        break;
-
-    case 0x34:	/* SOFT_REQ */
-        diff = s->ulpd_pm_regs[addr >> 2] ^ value;
-        s->ulpd_pm_regs[addr >> 2] = value & 0x1f;
-        omap_ulpd_req_update(s, diff, value);
-        break;
-
-    case 0x3c:	/* DPLL_CTRL */
-        /* XXX: OMAP310 TRM claims bit 3 is PLL_ENABLE, and bit 4 is
-         * omitted altogether, probably a typo.  */
-        /* This register has identical semantics with DPLL(1:3) control
-         * registers, see omap_dpll_write() */
-        diff = s->ulpd_pm_regs[addr >> 2] & value;
-        s->ulpd_pm_regs[addr >> 2] = value & 0x2fff;
-        if (diff & (0x3ff << 2)) {
-            if (value & (1 << 4)) {			/* PLL_ENABLE */
-                div = ((value >> 5) & 3) + 1;		/* PLL_DIV */
-                mult = MIN((value >> 7) & 0x1f, 1);	/* PLL_MULT */
-            } else {
-                div = bypass_div[((value >> 2) & 3)];	/* BYPASS_DIV */
-                mult = 1;
-            }
-            omap_clk_setrate(omap_findclk(s, "dpll4"), div, mult);
-        }
-
-        /* Enter the desired mode.  */
-        s->ulpd_pm_regs[addr >> 2] =
-                (s->ulpd_pm_regs[addr >> 2] & 0xfffe) |
-                ((s->ulpd_pm_regs[addr >> 2] >> 4) & 1);
-
-        /* Act as if the lock is restored.  */
-        s->ulpd_pm_regs[addr >> 2] |= 2;
-        break;
-
-    case 0x4c:	/* APLL_CTRL */
-        diff = s->ulpd_pm_regs[addr >> 2] & value;
-        s->ulpd_pm_regs[addr >> 2] = value & 0xf;
-        if (diff & (1 << 0))				/* APLL_NDPLL_SWITCH */
-            omap_clk_reparent(omap_findclk(s, "ck_48m"), omap_findclk(s,
-                                    (value & (1 << 0)) ? "apll" : "dpll4"));
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_ulpd_pm_ops = {
-    .read = omap_ulpd_pm_read,
-    .write = omap_ulpd_pm_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_ulpd_pm_reset(struct omap_mpu_state_s *mpu)
-{
-    mpu->ulpd_pm_regs[0x00 >> 2] = 0x0001;
-    mpu->ulpd_pm_regs[0x04 >> 2] = 0x0000;
-    mpu->ulpd_pm_regs[0x08 >> 2] = 0x0001;
-    mpu->ulpd_pm_regs[0x0c >> 2] = 0x0000;
-    mpu->ulpd_pm_regs[0x10 >> 2] = 0x0000;
-    mpu->ulpd_pm_regs[0x18 >> 2] = 0x01;
-    mpu->ulpd_pm_regs[0x1c >> 2] = 0x01;
-    mpu->ulpd_pm_regs[0x20 >> 2] = 0x01;
-    mpu->ulpd_pm_regs[0x24 >> 2] = 0x03ff;
-    mpu->ulpd_pm_regs[0x28 >> 2] = 0x01;
-    mpu->ulpd_pm_regs[0x2c >> 2] = 0x01;
-    omap_ulpd_clk_update(mpu, mpu->ulpd_pm_regs[0x30 >> 2], 0x0000);
-    mpu->ulpd_pm_regs[0x30 >> 2] = 0x0000;
-    omap_ulpd_req_update(mpu, mpu->ulpd_pm_regs[0x34 >> 2], 0x0000);
-    mpu->ulpd_pm_regs[0x34 >> 2] = 0x0000;
-    mpu->ulpd_pm_regs[0x38 >> 2] = 0x0001;
-    mpu->ulpd_pm_regs[0x3c >> 2] = 0x2211;
-    mpu->ulpd_pm_regs[0x40 >> 2] = 0x0000; /* FIXME: dump a real STATUS_REQ */
-    mpu->ulpd_pm_regs[0x48 >> 2] = 0x960;
-    mpu->ulpd_pm_regs[0x4c >> 2] = 0x08;
-    mpu->ulpd_pm_regs[0x50 >> 2] = 0x08;
-    omap_clk_setrate(omap_findclk(mpu, "dpll4"), 1, 4);
-    omap_clk_reparent(omap_findclk(mpu, "ck_48m"), omap_findclk(mpu, "dpll4"));
-}
-
-static void omap_ulpd_pm_init(MemoryRegion *system_memory,
-                hwaddr base,
-                struct omap_mpu_state_s *mpu)
-{
-    memory_region_init_io(&mpu->ulpd_pm_iomem, &omap_ulpd_pm_ops, mpu,
-                          "omap-ulpd-pm", 0x800);
-    memory_region_add_subregion(system_memory, base, &mpu->ulpd_pm_iomem);
-    omap_ulpd_pm_reset(mpu);
-}
-
-/* OMAP Pin Configuration */
-static uint64_t omap_pin_cfg_read(void *opaque, hwaddr addr,
-                                  unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_read32(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x00:	/* FUNC_MUX_CTRL_0 */
-    case 0x04:	/* FUNC_MUX_CTRL_1 */
-    case 0x08:	/* FUNC_MUX_CTRL_2 */
-        return s->func_mux_ctrl[addr >> 2];
-
-    case 0x0c:	/* COMP_MODE_CTRL_0 */
-        return s->comp_mode_ctrl[0];
-
-    case 0x10:	/* FUNC_MUX_CTRL_3 */
-    case 0x14:	/* FUNC_MUX_CTRL_4 */
-    case 0x18:	/* FUNC_MUX_CTRL_5 */
-    case 0x1c:	/* FUNC_MUX_CTRL_6 */
-    case 0x20:	/* FUNC_MUX_CTRL_7 */
-    case 0x24:	/* FUNC_MUX_CTRL_8 */
-    case 0x28:	/* FUNC_MUX_CTRL_9 */
-    case 0x2c:	/* FUNC_MUX_CTRL_A */
-    case 0x30:	/* FUNC_MUX_CTRL_B */
-    case 0x34:	/* FUNC_MUX_CTRL_C */
-    case 0x38:	/* FUNC_MUX_CTRL_D */
-        return s->func_mux_ctrl[(addr >> 2) - 1];
-
-    case 0x40:	/* PULL_DWN_CTRL_0 */
-    case 0x44:	/* PULL_DWN_CTRL_1 */
-    case 0x48:	/* PULL_DWN_CTRL_2 */
-    case 0x4c:	/* PULL_DWN_CTRL_3 */
-        return s->pull_dwn_ctrl[(addr & 0xf) >> 2];
-
-    case 0x50:	/* GATE_INH_CTRL_0 */
-        return s->gate_inh_ctrl[0];
-
-    case 0x60:	/* VOLTAGE_CTRL_0 */
-        return s->voltage_ctrl[0];
-
-    case 0x70:	/* TEST_DBG_CTRL_0 */
-        return s->test_dbg_ctrl[0];
-
-    case 0x80:	/* MOD_CONF_CTRL_0 */
-        return s->mod_conf_ctrl[0];
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static inline void omap_pin_funcmux0_update(struct omap_mpu_state_s *s,
-                uint32_t diff, uint32_t value)
-{
-    if (s->compat1509) {
-        if (diff & (1 << 9))			/* BLUETOOTH */
-            omap_clk_onoff(omap_findclk(s, "bt_mclk_out"),
-                            (~value >> 9) & 1);
-        if (diff & (1 << 7))			/* USB.CLKO */
-            omap_clk_onoff(omap_findclk(s, "usb.clko"),
-                            (value >> 7) & 1);
-    }
-}
-
-static inline void omap_pin_funcmux1_update(struct omap_mpu_state_s *s,
-                uint32_t diff, uint32_t value)
-{
-    if (s->compat1509) {
-        if (diff & (1 << 31))			/* MCBSP3_CLK_HIZ_DI */
-            omap_clk_onoff(omap_findclk(s, "mcbsp3.clkx"),
-                            (value >> 31) & 1);
-        if (diff & (1 << 1))			/* CLK32K */
-            omap_clk_onoff(omap_findclk(s, "clk32k_out"),
-                            (~value >> 1) & 1);
-    }
-}
-
-static inline void omap_pin_modconf1_update(struct omap_mpu_state_s *s,
-                uint32_t diff, uint32_t value)
-{
-    if (diff & (1 << 31))			/* CONF_MOD_UART3_CLK_MODE_R */
-         omap_clk_reparent(omap_findclk(s, "uart3_ck"),
-                         omap_findclk(s, ((value >> 31) & 1) ?
-                                 "ck_48m" : "armper_ck"));
-    if (diff & (1 << 30))			/* CONF_MOD_UART2_CLK_MODE_R */
-         omap_clk_reparent(omap_findclk(s, "uart2_ck"),
-                         omap_findclk(s, ((value >> 30) & 1) ?
-                                 "ck_48m" : "armper_ck"));
-    if (diff & (1 << 29))			/* CONF_MOD_UART1_CLK_MODE_R */
-         omap_clk_reparent(omap_findclk(s, "uart1_ck"),
-                         omap_findclk(s, ((value >> 29) & 1) ?
-                                 "ck_48m" : "armper_ck"));
-    if (diff & (1 << 23))			/* CONF_MOD_MMC_SD_CLK_REQ_R */
-         omap_clk_reparent(omap_findclk(s, "mmc_ck"),
-                         omap_findclk(s, ((value >> 23) & 1) ?
-                                 "ck_48m" : "armper_ck"));
-    if (diff & (1 << 12))			/* CONF_MOD_COM_MCLK_12_48_S */
-         omap_clk_reparent(omap_findclk(s, "com_mclk_out"),
-                         omap_findclk(s, ((value >> 12) & 1) ?
-                                 "ck_48m" : "armper_ck"));
-    if (diff & (1 << 9))			/* CONF_MOD_USB_HOST_HHC_UHO */
-         omap_clk_onoff(omap_findclk(s, "usb_hhc_ck"), (value >> 9) & 1);
-}
-
-static void omap_pin_cfg_write(void *opaque, hwaddr addr,
-                               uint64_t value, unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    uint32_t diff;
-
-    if (size != 4) {
-        return omap_badwidth_write32(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00:	/* FUNC_MUX_CTRL_0 */
-        diff = s->func_mux_ctrl[addr >> 2] ^ value;
-        s->func_mux_ctrl[addr >> 2] = value;
-        omap_pin_funcmux0_update(s, diff, value);
-        return;
-
-    case 0x04:	/* FUNC_MUX_CTRL_1 */
-        diff = s->func_mux_ctrl[addr >> 2] ^ value;
-        s->func_mux_ctrl[addr >> 2] = value;
-        omap_pin_funcmux1_update(s, diff, value);
-        return;
-
-    case 0x08:	/* FUNC_MUX_CTRL_2 */
-        s->func_mux_ctrl[addr >> 2] = value;
-        return;
-
-    case 0x0c:	/* COMP_MODE_CTRL_0 */
-        s->comp_mode_ctrl[0] = value;
-        s->compat1509 = (value != 0x0000eaef);
-        omap_pin_funcmux0_update(s, ~0, s->func_mux_ctrl[0]);
-        omap_pin_funcmux1_update(s, ~0, s->func_mux_ctrl[1]);
-        return;
-
-    case 0x10:	/* FUNC_MUX_CTRL_3 */
-    case 0x14:	/* FUNC_MUX_CTRL_4 */
-    case 0x18:	/* FUNC_MUX_CTRL_5 */
-    case 0x1c:	/* FUNC_MUX_CTRL_6 */
-    case 0x20:	/* FUNC_MUX_CTRL_7 */
-    case 0x24:	/* FUNC_MUX_CTRL_8 */
-    case 0x28:	/* FUNC_MUX_CTRL_9 */
-    case 0x2c:	/* FUNC_MUX_CTRL_A */
-    case 0x30:	/* FUNC_MUX_CTRL_B */
-    case 0x34:	/* FUNC_MUX_CTRL_C */
-    case 0x38:	/* FUNC_MUX_CTRL_D */
-        s->func_mux_ctrl[(addr >> 2) - 1] = value;
-        return;
-
-    case 0x40:	/* PULL_DWN_CTRL_0 */
-    case 0x44:	/* PULL_DWN_CTRL_1 */
-    case 0x48:	/* PULL_DWN_CTRL_2 */
-    case 0x4c:	/* PULL_DWN_CTRL_3 */
-        s->pull_dwn_ctrl[(addr & 0xf) >> 2] = value;
-        return;
-
-    case 0x50:	/* GATE_INH_CTRL_0 */
-        s->gate_inh_ctrl[0] = value;
-        return;
-
-    case 0x60:	/* VOLTAGE_CTRL_0 */
-        s->voltage_ctrl[0] = value;
-        return;
-
-    case 0x70:	/* TEST_DBG_CTRL_0 */
-        s->test_dbg_ctrl[0] = value;
-        return;
-
-    case 0x80:	/* MOD_CONF_CTRL_0 */
-        diff = s->mod_conf_ctrl[0] ^ value;
-        s->mod_conf_ctrl[0] = value;
-        omap_pin_modconf1_update(s, diff, value);
-        return;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_pin_cfg_ops = {
-    .read = omap_pin_cfg_read,
-    .write = omap_pin_cfg_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_pin_cfg_reset(struct omap_mpu_state_s *mpu)
-{
-    /* Start in Compatibility Mode.  */
-    mpu->compat1509 = 1;
-    omap_pin_funcmux0_update(mpu, mpu->func_mux_ctrl[0], 0);
-    omap_pin_funcmux1_update(mpu, mpu->func_mux_ctrl[1], 0);
-    omap_pin_modconf1_update(mpu, mpu->mod_conf_ctrl[0], 0);
-    memset(mpu->func_mux_ctrl, 0, sizeof(mpu->func_mux_ctrl));
-    memset(mpu->comp_mode_ctrl, 0, sizeof(mpu->comp_mode_ctrl));
-    memset(mpu->pull_dwn_ctrl, 0, sizeof(mpu->pull_dwn_ctrl));
-    memset(mpu->gate_inh_ctrl, 0, sizeof(mpu->gate_inh_ctrl));
-    memset(mpu->voltage_ctrl, 0, sizeof(mpu->voltage_ctrl));
-    memset(mpu->test_dbg_ctrl, 0, sizeof(mpu->test_dbg_ctrl));
-    memset(mpu->mod_conf_ctrl, 0, sizeof(mpu->mod_conf_ctrl));
-}
-
-static void omap_pin_cfg_init(MemoryRegion *system_memory,
-                hwaddr base,
-                struct omap_mpu_state_s *mpu)
-{
-    memory_region_init_io(&mpu->pin_cfg_iomem, &omap_pin_cfg_ops, mpu,
-                          "omap-pin-cfg", 0x800);
-    memory_region_add_subregion(system_memory, base, &mpu->pin_cfg_iomem);
-    omap_pin_cfg_reset(mpu);
-}
-
-/* Device Identification, Die Identification */
-static uint64_t omap_id_read(void *opaque, hwaddr addr,
-                             unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_read32(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0xfffe1800:	/* DIE_ID_LSB */
-        return 0xc9581f0e;
-    case 0xfffe1804:	/* DIE_ID_MSB */
-        return 0xa8858bfa;
-
-    case 0xfffe2000:	/* PRODUCT_ID_LSB */
-        return 0x00aaaafc;
-    case 0xfffe2004:	/* PRODUCT_ID_MSB */
-        return 0xcafeb574;
-
-    case 0xfffed400:	/* JTAG_ID_LSB */
-        switch (s->mpu_model) {
-        case omap310:
-            return 0x03310315;
-        case omap1510:
-            return 0x03310115;
-        default:
-            hw_error("%s: bad mpu model\n", __FUNCTION__);
-        }
-        break;
-
-    case 0xfffed404:	/* JTAG_ID_MSB */
-        switch (s->mpu_model) {
-        case omap310:
-            return 0xfb57402f;
-        case omap1510:
-            return 0xfb47002f;
-        default:
-            hw_error("%s: bad mpu model\n", __FUNCTION__);
-        }
-        break;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_id_write(void *opaque, hwaddr addr,
-                          uint64_t value, unsigned size)
-{
-    if (size != 4) {
-        return omap_badwidth_write32(opaque, addr, value);
-    }
-
-    OMAP_BAD_REG(addr);
-}
-
-static const MemoryRegionOps omap_id_ops = {
-    .read = omap_id_read,
-    .write = omap_id_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_id_init(MemoryRegion *memory, struct omap_mpu_state_s *mpu)
-{
-    memory_region_init_io(&mpu->id_iomem, &omap_id_ops, mpu,
-                          "omap-id", 0x100000000ULL);
-    memory_region_init_alias(&mpu->id_iomem_e18, "omap-id-e18", &mpu->id_iomem,
-                             0xfffe1800, 0x800);
-    memory_region_add_subregion(memory, 0xfffe1800, &mpu->id_iomem_e18);
-    memory_region_init_alias(&mpu->id_iomem_ed4, "omap-id-ed4", &mpu->id_iomem,
-                             0xfffed400, 0x100);
-    memory_region_add_subregion(memory, 0xfffed400, &mpu->id_iomem_ed4);
-    if (!cpu_is_omap15xx(mpu)) {
-        memory_region_init_alias(&mpu->id_iomem_ed4, "omap-id-e20",
-                                 &mpu->id_iomem, 0xfffe2000, 0x800);
-        memory_region_add_subregion(memory, 0xfffe2000, &mpu->id_iomem_e20);
-    }
-}
-
-/* MPUI Control (Dummy) */
-static uint64_t omap_mpui_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_read32(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x00:	/* CTRL */
-        return s->mpui_ctrl;
-    case 0x04:	/* DEBUG_ADDR */
-        return 0x01ffffff;
-    case 0x08:	/* DEBUG_DATA */
-        return 0xffffffff;
-    case 0x0c:	/* DEBUG_FLAG */
-        return 0x00000800;
-    case 0x10:	/* STATUS */
-        return 0x00000000;
-
-    /* Not in OMAP310 */
-    case 0x14:	/* DSP_STATUS */
-    case 0x18:	/* DSP_BOOT_CONFIG */
-        return 0x00000000;
-    case 0x1c:	/* DSP_MPUI_CONFIG */
-        return 0x0000ffff;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_mpui_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_write32(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00:	/* CTRL */
-        s->mpui_ctrl = value & 0x007fffff;
-        break;
-
-    case 0x04:	/* DEBUG_ADDR */
-    case 0x08:	/* DEBUG_DATA */
-    case 0x0c:	/* DEBUG_FLAG */
-    case 0x10:	/* STATUS */
-    /* Not in OMAP310 */
-    case 0x14:	/* DSP_STATUS */
-        OMAP_RO_REG(addr);
-        break;
-    case 0x18:	/* DSP_BOOT_CONFIG */
-    case 0x1c:	/* DSP_MPUI_CONFIG */
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_mpui_ops = {
-    .read = omap_mpui_read,
-    .write = omap_mpui_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_mpui_reset(struct omap_mpu_state_s *s)
-{
-    s->mpui_ctrl = 0x0003ff1b;
-}
-
-static void omap_mpui_init(MemoryRegion *memory, hwaddr base,
-                struct omap_mpu_state_s *mpu)
-{
-    memory_region_init_io(&mpu->mpui_iomem, &omap_mpui_ops, mpu,
-                          "omap-mpui", 0x100);
-    memory_region_add_subregion(memory, base, &mpu->mpui_iomem);
-
-    omap_mpui_reset(mpu);
-}
-
-/* TIPB Bridges */
-struct omap_tipb_bridge_s {
-    qemu_irq abort;
-    MemoryRegion iomem;
-
-    int width_intr;
-    uint16_t control;
-    uint16_t alloc;
-    uint16_t buffer;
-    uint16_t enh_control;
-};
-
-static uint64_t omap_tipb_bridge_read(void *opaque, hwaddr addr,
-                                      unsigned size)
-{
-    struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
-
-    if (size < 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x00:	/* TIPB_CNTL */
-        return s->control;
-    case 0x04:	/* TIPB_BUS_ALLOC */
-        return s->alloc;
-    case 0x08:	/* MPU_TIPB_CNTL */
-        return s->buffer;
-    case 0x0c:	/* ENHANCED_TIPB_CNTL */
-        return s->enh_control;
-    case 0x10:	/* ADDRESS_DBG */
-    case 0x14:	/* DATA_DEBUG_LOW */
-    case 0x18:	/* DATA_DEBUG_HIGH */
-        return 0xffff;
-    case 0x1c:	/* DEBUG_CNTR_SIG */
-        return 0x00f8;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_tipb_bridge_write(void *opaque, hwaddr addr,
-                                   uint64_t value, unsigned size)
-{
-    struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
-
-    if (size < 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00:	/* TIPB_CNTL */
-        s->control = value & 0xffff;
-        break;
-
-    case 0x04:	/* TIPB_BUS_ALLOC */
-        s->alloc = value & 0x003f;
-        break;
-
-    case 0x08:	/* MPU_TIPB_CNTL */
-        s->buffer = value & 0x0003;
-        break;
-
-    case 0x0c:	/* ENHANCED_TIPB_CNTL */
-        s->width_intr = !(value & 2);
-        s->enh_control = value & 0x000f;
-        break;
-
-    case 0x10:	/* ADDRESS_DBG */
-    case 0x14:	/* DATA_DEBUG_LOW */
-    case 0x18:	/* DATA_DEBUG_HIGH */
-    case 0x1c:	/* DEBUG_CNTR_SIG */
-        OMAP_RO_REG(addr);
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_tipb_bridge_ops = {
-    .read = omap_tipb_bridge_read,
-    .write = omap_tipb_bridge_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_tipb_bridge_reset(struct omap_tipb_bridge_s *s)
-{
-    s->control = 0xffff;
-    s->alloc = 0x0009;
-    s->buffer = 0x0000;
-    s->enh_control = 0x000f;
-}
-
-static struct omap_tipb_bridge_s *omap_tipb_bridge_init(
-    MemoryRegion *memory, hwaddr base,
-    qemu_irq abort_irq, omap_clk clk)
-{
-    struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *)
-            g_malloc0(sizeof(struct omap_tipb_bridge_s));
-
-    s->abort = abort_irq;
-    omap_tipb_bridge_reset(s);
-
-    memory_region_init_io(&s->iomem, &omap_tipb_bridge_ops, s,
-                          "omap-tipb-bridge", 0x100);
-    memory_region_add_subregion(memory, base, &s->iomem);
-
-    return s;
-}
-
-/* Dummy Traffic Controller's Memory Interface */
-static uint64_t omap_tcmi_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    uint32_t ret;
-
-    if (size != 4) {
-        return omap_badwidth_read32(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x00:	/* IMIF_PRIO */
-    case 0x04:	/* EMIFS_PRIO */
-    case 0x08:	/* EMIFF_PRIO */
-    case 0x0c:	/* EMIFS_CONFIG */
-    case 0x10:	/* EMIFS_CS0_CONFIG */
-    case 0x14:	/* EMIFS_CS1_CONFIG */
-    case 0x18:	/* EMIFS_CS2_CONFIG */
-    case 0x1c:	/* EMIFS_CS3_CONFIG */
-    case 0x24:	/* EMIFF_MRS */
-    case 0x28:	/* TIMEOUT1 */
-    case 0x2c:	/* TIMEOUT2 */
-    case 0x30:	/* TIMEOUT3 */
-    case 0x3c:	/* EMIFF_SDRAM_CONFIG_2 */
-    case 0x40:	/* EMIFS_CFG_DYN_WAIT */
-        return s->tcmi_regs[addr >> 2];
-
-    case 0x20:	/* EMIFF_SDRAM_CONFIG */
-        ret = s->tcmi_regs[addr >> 2];
-        s->tcmi_regs[addr >> 2] &= ~1; /* XXX: Clear SLRF on SDRAM access */
-        /* XXX: We can try using the VGA_DIRTY flag for this */
-        return ret;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_tcmi_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_write32(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00:	/* IMIF_PRIO */
-    case 0x04:	/* EMIFS_PRIO */
-    case 0x08:	/* EMIFF_PRIO */
-    case 0x10:	/* EMIFS_CS0_CONFIG */
-    case 0x14:	/* EMIFS_CS1_CONFIG */
-    case 0x18:	/* EMIFS_CS2_CONFIG */
-    case 0x1c:	/* EMIFS_CS3_CONFIG */
-    case 0x20:	/* EMIFF_SDRAM_CONFIG */
-    case 0x24:	/* EMIFF_MRS */
-    case 0x28:	/* TIMEOUT1 */
-    case 0x2c:	/* TIMEOUT2 */
-    case 0x30:	/* TIMEOUT3 */
-    case 0x3c:	/* EMIFF_SDRAM_CONFIG_2 */
-    case 0x40:	/* EMIFS_CFG_DYN_WAIT */
-        s->tcmi_regs[addr >> 2] = value;
-        break;
-    case 0x0c:	/* EMIFS_CONFIG */
-        s->tcmi_regs[addr >> 2] = (value & 0xf) | (1 << 4);
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_tcmi_ops = {
-    .read = omap_tcmi_read,
-    .write = omap_tcmi_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_tcmi_reset(struct omap_mpu_state_s *mpu)
-{
-    mpu->tcmi_regs[0x00 >> 2] = 0x00000000;
-    mpu->tcmi_regs[0x04 >> 2] = 0x00000000;
-    mpu->tcmi_regs[0x08 >> 2] = 0x00000000;
-    mpu->tcmi_regs[0x0c >> 2] = 0x00000010;
-    mpu->tcmi_regs[0x10 >> 2] = 0x0010fffb;
-    mpu->tcmi_regs[0x14 >> 2] = 0x0010fffb;
-    mpu->tcmi_regs[0x18 >> 2] = 0x0010fffb;
-    mpu->tcmi_regs[0x1c >> 2] = 0x0010fffb;
-    mpu->tcmi_regs[0x20 >> 2] = 0x00618800;
-    mpu->tcmi_regs[0x24 >> 2] = 0x00000037;
-    mpu->tcmi_regs[0x28 >> 2] = 0x00000000;
-    mpu->tcmi_regs[0x2c >> 2] = 0x00000000;
-    mpu->tcmi_regs[0x30 >> 2] = 0x00000000;
-    mpu->tcmi_regs[0x3c >> 2] = 0x00000003;
-    mpu->tcmi_regs[0x40 >> 2] = 0x00000000;
-}
-
-static void omap_tcmi_init(MemoryRegion *memory, hwaddr base,
-                struct omap_mpu_state_s *mpu)
-{
-    memory_region_init_io(&mpu->tcmi_iomem, &omap_tcmi_ops, mpu,
-                          "omap-tcmi", 0x100);
-    memory_region_add_subregion(memory, base, &mpu->tcmi_iomem);
-    omap_tcmi_reset(mpu);
-}
-
-/* Digital phase-locked loops control */
-struct dpll_ctl_s {
-    MemoryRegion iomem;
-    uint16_t mode;
-    omap_clk dpll;
-};
-
-static uint64_t omap_dpll_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    if (addr == 0x00)	/* CTL_REG */
-        return s->mode;
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_dpll_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
-    uint16_t diff;
-    static const int bypass_div[4] = { 1, 2, 4, 4 };
-    int div, mult;
-
-    if (size != 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    if (addr == 0x00) {	/* CTL_REG */
-        /* See omap_ulpd_pm_write() too */
-        diff = s->mode & value;
-        s->mode = value & 0x2fff;
-        if (diff & (0x3ff << 2)) {
-            if (value & (1 << 4)) {			/* PLL_ENABLE */
-                div = ((value >> 5) & 3) + 1;		/* PLL_DIV */
-                mult = MIN((value >> 7) & 0x1f, 1);	/* PLL_MULT */
-            } else {
-                div = bypass_div[((value >> 2) & 3)];	/* BYPASS_DIV */
-                mult = 1;
-            }
-            omap_clk_setrate(s->dpll, div, mult);
-        }
-
-        /* Enter the desired mode.  */
-        s->mode = (s->mode & 0xfffe) | ((s->mode >> 4) & 1);
-
-        /* Act as if the lock is restored.  */
-        s->mode |= 2;
-    } else {
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_dpll_ops = {
-    .read = omap_dpll_read,
-    .write = omap_dpll_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_dpll_reset(struct dpll_ctl_s *s)
-{
-    s->mode = 0x2002;
-    omap_clk_setrate(s->dpll, 1, 1);
-}
-
-static struct dpll_ctl_s  *omap_dpll_init(MemoryRegion *memory,
-                           hwaddr base, omap_clk clk)
-{
-    struct dpll_ctl_s *s = g_malloc0(sizeof(*s));
-    memory_region_init_io(&s->iomem, &omap_dpll_ops, s, "omap-dpll", 0x100);
-
-    s->dpll = clk;
-    omap_dpll_reset(s);
-
-    memory_region_add_subregion(memory, base, &s->iomem);
-    return s;
-}
-
-/* MPU Clock/Reset/Power Mode Control */
-static uint64_t omap_clkm_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x00:	/* ARM_CKCTL */
-        return s->clkm.arm_ckctl;
-
-    case 0x04:	/* ARM_IDLECT1 */
-        return s->clkm.arm_idlect1;
-
-    case 0x08:	/* ARM_IDLECT2 */
-        return s->clkm.arm_idlect2;
-
-    case 0x0c:	/* ARM_EWUPCT */
-        return s->clkm.arm_ewupct;
-
-    case 0x10:	/* ARM_RSTCT1 */
-        return s->clkm.arm_rstct1;
-
-    case 0x14:	/* ARM_RSTCT2 */
-        return s->clkm.arm_rstct2;
-
-    case 0x18:	/* ARM_SYSST */
-        return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start;
-
-    case 0x1c:	/* ARM_CKOUT1 */
-        return s->clkm.arm_ckout1;
-
-    case 0x20:	/* ARM_CKOUT2 */
-        break;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static inline void omap_clkm_ckctl_update(struct omap_mpu_state_s *s,
-                uint16_t diff, uint16_t value)
-{
-    omap_clk clk;
-
-    if (diff & (1 << 14)) {				/* ARM_INTHCK_SEL */
-        if (value & (1 << 14))
-            /* Reserved */;
-        else {
-            clk = omap_findclk(s, "arminth_ck");
-            omap_clk_reparent(clk, omap_findclk(s, "tc_ck"));
-        }
-    }
-    if (diff & (1 << 12)) {				/* ARM_TIMXO */
-        clk = omap_findclk(s, "armtim_ck");
-        if (value & (1 << 12))
-            omap_clk_reparent(clk, omap_findclk(s, "clkin"));
-        else
-            omap_clk_reparent(clk, omap_findclk(s, "ck_gen1"));
-    }
-    /* XXX: en_dspck */
-    if (diff & (3 << 10)) {				/* DSPMMUDIV */
-        clk = omap_findclk(s, "dspmmu_ck");
-        omap_clk_setrate(clk, 1 << ((value >> 10) & 3), 1);
-    }
-    if (diff & (3 << 8)) {				/* TCDIV */
-        clk = omap_findclk(s, "tc_ck");
-        omap_clk_setrate(clk, 1 << ((value >> 8) & 3), 1);
-    }
-    if (diff & (3 << 6)) {				/* DSPDIV */
-        clk = omap_findclk(s, "dsp_ck");
-        omap_clk_setrate(clk, 1 << ((value >> 6) & 3), 1);
-    }
-    if (diff & (3 << 4)) {				/* ARMDIV */
-        clk = omap_findclk(s, "arm_ck");
-        omap_clk_setrate(clk, 1 << ((value >> 4) & 3), 1);
-    }
-    if (diff & (3 << 2)) {				/* LCDDIV */
-        clk = omap_findclk(s, "lcd_ck");
-        omap_clk_setrate(clk, 1 << ((value >> 2) & 3), 1);
-    }
-    if (diff & (3 << 0)) {				/* PERDIV */
-        clk = omap_findclk(s, "armper_ck");
-        omap_clk_setrate(clk, 1 << ((value >> 0) & 3), 1);
-    }
-}
-
-static inline void omap_clkm_idlect1_update(struct omap_mpu_state_s *s,
-                uint16_t diff, uint16_t value)
-{
-    omap_clk clk;
-
-    if (value & (1 << 11)) {                            /* SETARM_IDLE */
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
-    }
-    if (!(value & (1 << 10)))				/* WKUP_MODE */
-        qemu_system_shutdown_request();	/* XXX: disable wakeup from IRQ */
-
-#define SET_CANIDLE(clock, bit)				\
-    if (diff & (1 << bit)) {				\
-        clk = omap_findclk(s, clock);			\
-        omap_clk_canidle(clk, (value >> bit) & 1);	\
-    }
-    SET_CANIDLE("mpuwd_ck", 0)				/* IDLWDT_ARM */
-    SET_CANIDLE("armxor_ck", 1)				/* IDLXORP_ARM */
-    SET_CANIDLE("mpuper_ck", 2)				/* IDLPER_ARM */
-    SET_CANIDLE("lcd_ck", 3)				/* IDLLCD_ARM */
-    SET_CANIDLE("lb_ck", 4)				/* IDLLB_ARM */
-    SET_CANIDLE("hsab_ck", 5)				/* IDLHSAB_ARM */
-    SET_CANIDLE("tipb_ck", 6)				/* IDLIF_ARM */
-    SET_CANIDLE("dma_ck", 6)				/* IDLIF_ARM */
-    SET_CANIDLE("tc_ck", 6)				/* IDLIF_ARM */
-    SET_CANIDLE("dpll1", 7)				/* IDLDPLL_ARM */
-    SET_CANIDLE("dpll2", 7)				/* IDLDPLL_ARM */
-    SET_CANIDLE("dpll3", 7)				/* IDLDPLL_ARM */
-    SET_CANIDLE("mpui_ck", 8)				/* IDLAPI_ARM */
-    SET_CANIDLE("armtim_ck", 9)				/* IDLTIM_ARM */
-}
-
-static inline void omap_clkm_idlect2_update(struct omap_mpu_state_s *s,
-                uint16_t diff, uint16_t value)
-{
-    omap_clk clk;
-
-#define SET_ONOFF(clock, bit)				\
-    if (diff & (1 << bit)) {				\
-        clk = omap_findclk(s, clock);			\
-        omap_clk_onoff(clk, (value >> bit) & 1);	\
-    }
-    SET_ONOFF("mpuwd_ck", 0)				/* EN_WDTCK */
-    SET_ONOFF("armxor_ck", 1)				/* EN_XORPCK */
-    SET_ONOFF("mpuper_ck", 2)				/* EN_PERCK */
-    SET_ONOFF("lcd_ck", 3)				/* EN_LCDCK */
-    SET_ONOFF("lb_ck", 4)				/* EN_LBCK */
-    SET_ONOFF("hsab_ck", 5)				/* EN_HSABCK */
-    SET_ONOFF("mpui_ck", 6)				/* EN_APICK */
-    SET_ONOFF("armtim_ck", 7)				/* EN_TIMCK */
-    SET_CANIDLE("dma_ck", 8)				/* DMACK_REQ */
-    SET_ONOFF("arm_gpio_ck", 9)				/* EN_GPIOCK */
-    SET_ONOFF("lbfree_ck", 10)				/* EN_LBFREECK */
-}
-
-static inline void omap_clkm_ckout1_update(struct omap_mpu_state_s *s,
-                uint16_t diff, uint16_t value)
-{
-    omap_clk clk;
-
-    if (diff & (3 << 4)) {				/* TCLKOUT */
-        clk = omap_findclk(s, "tclk_out");
-        switch ((value >> 4) & 3) {
-        case 1:
-            omap_clk_reparent(clk, omap_findclk(s, "ck_gen3"));
-            omap_clk_onoff(clk, 1);
-            break;
-        case 2:
-            omap_clk_reparent(clk, omap_findclk(s, "tc_ck"));
-            omap_clk_onoff(clk, 1);
-            break;
-        default:
-            omap_clk_onoff(clk, 0);
-        }
-    }
-    if (diff & (3 << 2)) {				/* DCLKOUT */
-        clk = omap_findclk(s, "dclk_out");
-        switch ((value >> 2) & 3) {
-        case 0:
-            omap_clk_reparent(clk, omap_findclk(s, "dspmmu_ck"));
-            break;
-        case 1:
-            omap_clk_reparent(clk, omap_findclk(s, "ck_gen2"));
-            break;
-        case 2:
-            omap_clk_reparent(clk, omap_findclk(s, "dsp_ck"));
-            break;
-        case 3:
-            omap_clk_reparent(clk, omap_findclk(s, "ck_ref14"));
-            break;
-        }
-    }
-    if (diff & (3 << 0)) {				/* ACLKOUT */
-        clk = omap_findclk(s, "aclk_out");
-        switch ((value >> 0) & 3) {
-        case 1:
-            omap_clk_reparent(clk, omap_findclk(s, "ck_gen1"));
-            omap_clk_onoff(clk, 1);
-            break;
-        case 2:
-            omap_clk_reparent(clk, omap_findclk(s, "arm_ck"));
-            omap_clk_onoff(clk, 1);
-            break;
-        case 3:
-            omap_clk_reparent(clk, omap_findclk(s, "ck_ref14"));
-            omap_clk_onoff(clk, 1);
-            break;
-        default:
-            omap_clk_onoff(clk, 0);
-        }
-    }
-}
-
-static void omap_clkm_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    uint16_t diff;
-    omap_clk clk;
-    static const char *clkschemename[8] = {
-        "fully synchronous", "fully asynchronous", "synchronous scalable",
-        "mix mode 1", "mix mode 2", "bypass mode", "mix mode 3", "mix mode 4",
-    };
-
-    if (size != 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00:	/* ARM_CKCTL */
-        diff = s->clkm.arm_ckctl ^ value;
-        s->clkm.arm_ckctl = value & 0x7fff;
-        omap_clkm_ckctl_update(s, diff, value);
-        return;
-
-    case 0x04:	/* ARM_IDLECT1 */
-        diff = s->clkm.arm_idlect1 ^ value;
-        s->clkm.arm_idlect1 = value & 0x0fff;
-        omap_clkm_idlect1_update(s, diff, value);
-        return;
-
-    case 0x08:	/* ARM_IDLECT2 */
-        diff = s->clkm.arm_idlect2 ^ value;
-        s->clkm.arm_idlect2 = value & 0x07ff;
-        omap_clkm_idlect2_update(s, diff, value);
-        return;
-
-    case 0x0c:	/* ARM_EWUPCT */
-        s->clkm.arm_ewupct = value & 0x003f;
-        return;
-
-    case 0x10:	/* ARM_RSTCT1 */
-        diff = s->clkm.arm_rstct1 ^ value;
-        s->clkm.arm_rstct1 = value & 0x0007;
-        if (value & 9) {
-            qemu_system_reset_request();
-            s->clkm.cold_start = 0xa;
-        }
-        if (diff & ~value & 4) {				/* DSP_RST */
-            omap_mpui_reset(s);
-            omap_tipb_bridge_reset(s->private_tipb);
-            omap_tipb_bridge_reset(s->public_tipb);
-        }
-        if (diff & 2) {						/* DSP_EN */
-            clk = omap_findclk(s, "dsp_ck");
-            omap_clk_canidle(clk, (~value >> 1) & 1);
-        }
-        return;
-
-    case 0x14:	/* ARM_RSTCT2 */
-        s->clkm.arm_rstct2 = value & 0x0001;
-        return;
-
-    case 0x18:	/* ARM_SYSST */
-        if ((s->clkm.clocking_scheme ^ (value >> 11)) & 7) {
-            s->clkm.clocking_scheme = (value >> 11) & 7;
-            printf("%s: clocking scheme set to %s\n", __FUNCTION__,
-                            clkschemename[s->clkm.clocking_scheme]);
-        }
-        s->clkm.cold_start &= value & 0x3f;
-        return;
-
-    case 0x1c:	/* ARM_CKOUT1 */
-        diff = s->clkm.arm_ckout1 ^ value;
-        s->clkm.arm_ckout1 = value & 0x003f;
-        omap_clkm_ckout1_update(s, diff, value);
-        return;
-
-    case 0x20:	/* ARM_CKOUT2 */
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_clkm_ops = {
-    .read = omap_clkm_read,
-    .write = omap_clkm_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static uint64_t omap_clkdsp_read(void *opaque, hwaddr addr,
-                                 unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x04:	/* DSP_IDLECT1 */
-        return s->clkm.dsp_idlect1;
-
-    case 0x08:	/* DSP_IDLECT2 */
-        return s->clkm.dsp_idlect2;
-
-    case 0x14:	/* DSP_RSTCT2 */
-        return s->clkm.dsp_rstct2;
-
-    case 0x18:	/* DSP_SYSST */
-        return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start |
-                (s->cpu->env.halted << 6);      /* Quite useless... */
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static inline void omap_clkdsp_idlect1_update(struct omap_mpu_state_s *s,
-                uint16_t diff, uint16_t value)
-{
-    omap_clk clk;
-
-    SET_CANIDLE("dspxor_ck", 1);			/* IDLXORP_DSP */
-}
-
-static inline void omap_clkdsp_idlect2_update(struct omap_mpu_state_s *s,
-                uint16_t diff, uint16_t value)
-{
-    omap_clk clk;
-
-    SET_ONOFF("dspxor_ck", 1);				/* EN_XORPCK */
-}
-
-static void omap_clkdsp_write(void *opaque, hwaddr addr,
-                              uint64_t value, unsigned size)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-    uint16_t diff;
-
-    if (size != 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x04:	/* DSP_IDLECT1 */
-        diff = s->clkm.dsp_idlect1 ^ value;
-        s->clkm.dsp_idlect1 = value & 0x01f7;
-        omap_clkdsp_idlect1_update(s, diff, value);
-        break;
-
-    case 0x08:	/* DSP_IDLECT2 */
-        s->clkm.dsp_idlect2 = value & 0x0037;
-        diff = s->clkm.dsp_idlect1 ^ value;
-        omap_clkdsp_idlect2_update(s, diff, value);
-        break;
-
-    case 0x14:	/* DSP_RSTCT2 */
-        s->clkm.dsp_rstct2 = value & 0x0001;
-        break;
-
-    case 0x18:	/* DSP_SYSST */
-        s->clkm.cold_start &= value & 0x3f;
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static const MemoryRegionOps omap_clkdsp_ops = {
-    .read = omap_clkdsp_read,
-    .write = omap_clkdsp_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_clkm_reset(struct omap_mpu_state_s *s)
-{
-    if (s->wdt && s->wdt->reset)
-        s->clkm.cold_start = 0x6;
-    s->clkm.clocking_scheme = 0;
-    omap_clkm_ckctl_update(s, ~0, 0x3000);
-    s->clkm.arm_ckctl = 0x3000;
-    omap_clkm_idlect1_update(s, s->clkm.arm_idlect1 ^ 0x0400, 0x0400);
-    s->clkm.arm_idlect1 = 0x0400;
-    omap_clkm_idlect2_update(s, s->clkm.arm_idlect2 ^ 0x0100, 0x0100);
-    s->clkm.arm_idlect2 = 0x0100;
-    s->clkm.arm_ewupct = 0x003f;
-    s->clkm.arm_rstct1 = 0x0000;
-    s->clkm.arm_rstct2 = 0x0000;
-    s->clkm.arm_ckout1 = 0x0015;
-    s->clkm.dpll1_mode = 0x2002;
-    omap_clkdsp_idlect1_update(s, s->clkm.dsp_idlect1 ^ 0x0040, 0x0040);
-    s->clkm.dsp_idlect1 = 0x0040;
-    omap_clkdsp_idlect2_update(s, ~0, 0x0000);
-    s->clkm.dsp_idlect2 = 0x0000;
-    s->clkm.dsp_rstct2 = 0x0000;
-}
-
-static void omap_clkm_init(MemoryRegion *memory, hwaddr mpu_base,
-                hwaddr dsp_base, struct omap_mpu_state_s *s)
-{
-    memory_region_init_io(&s->clkm_iomem, &omap_clkm_ops, s,
-                          "omap-clkm", 0x100);
-    memory_region_init_io(&s->clkdsp_iomem, &omap_clkdsp_ops, s,
-                          "omap-clkdsp", 0x1000);
-
-    s->clkm.arm_idlect1 = 0x03ff;
-    s->clkm.arm_idlect2 = 0x0100;
-    s->clkm.dsp_idlect1 = 0x0002;
-    omap_clkm_reset(s);
-    s->clkm.cold_start = 0x3a;
-
-    memory_region_add_subregion(memory, mpu_base, &s->clkm_iomem);
-    memory_region_add_subregion(memory, dsp_base, &s->clkdsp_iomem);
-}
-
-/* MPU I/O */
-struct omap_mpuio_s {
-    qemu_irq irq;
-    qemu_irq kbd_irq;
-    qemu_irq *in;
-    qemu_irq handler[16];
-    qemu_irq wakeup;
-    MemoryRegion iomem;
-
-    uint16_t inputs;
-    uint16_t outputs;
-    uint16_t dir;
-    uint16_t edge;
-    uint16_t mask;
-    uint16_t ints;
-
-    uint16_t debounce;
-    uint16_t latch;
-    uint8_t event;
-
-    uint8_t buttons[5];
-    uint8_t row_latch;
-    uint8_t cols;
-    int kbd_mask;
-    int clk;
-};
-
-static void omap_mpuio_set(void *opaque, int line, int level)
-{
-    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
-    uint16_t prev = s->inputs;
-
-    if (level)
-        s->inputs |= 1 << line;
-    else
-        s->inputs &= ~(1 << line);
-
-    if (((1 << line) & s->dir & ~s->mask) && s->clk) {
-        if ((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) {
-            s->ints |= 1 << line;
-            qemu_irq_raise(s->irq);
-            /* TODO: wakeup */
-        }
-        if ((s->event & (1 << 0)) &&		/* SET_GPIO_EVENT_MODE */
-                (s->event >> 1) == line)	/* PIN_SELECT */
-            s->latch = s->inputs;
-    }
-}
-
-static void omap_mpuio_kbd_update(struct omap_mpuio_s *s)
-{
-    int i;
-    uint8_t *row, rows = 0, cols = ~s->cols;
-
-    for (row = s->buttons + 4, i = 1 << 4; i; row --, i >>= 1)
-        if (*row & cols)
-            rows |= i;
-
-    qemu_set_irq(s->kbd_irq, rows && !s->kbd_mask && s->clk);
-    s->row_latch = ~rows;
-}
-
-static uint64_t omap_mpuio_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-    uint16_t ret;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (offset) {
-    case 0x00:	/* INPUT_LATCH */
-        return s->inputs;
-
-    case 0x04:	/* OUTPUT_REG */
-        return s->outputs;
-
-    case 0x08:	/* IO_CNTL */
-        return s->dir;
-
-    case 0x10:	/* KBR_LATCH */
-        return s->row_latch;
-
-    case 0x14:	/* KBC_REG */
-        return s->cols;
-
-    case 0x18:	/* GPIO_EVENT_MODE_REG */
-        return s->event;
-
-    case 0x1c:	/* GPIO_INT_EDGE_REG */
-        return s->edge;
-
-    case 0x20:	/* KBD_INT */
-        return (~s->row_latch & 0x1f) && !s->kbd_mask;
-
-    case 0x24:	/* GPIO_INT */
-        ret = s->ints;
-        s->ints &= s->mask;
-        if (ret)
-            qemu_irq_lower(s->irq);
-        return ret;
-
-    case 0x28:	/* KBD_MASKIT */
-        return s->kbd_mask;
-
-    case 0x2c:	/* GPIO_MASKIT */
-        return s->mask;
-
-    case 0x30:	/* GPIO_DEBOUNCING_REG */
-        return s->debounce;
-
-    case 0x34:	/* GPIO_LATCH_REG */
-        return s->latch;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_mpuio_write(void *opaque, hwaddr addr,
-                             uint64_t value, unsigned size)
-{
-    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-    uint16_t diff;
-    int ln;
-
-    if (size != 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    switch (offset) {
-    case 0x04:	/* OUTPUT_REG */
-        diff = (s->outputs ^ value) & ~s->dir;
-        s->outputs = value;
-        while ((ln = ffs(diff))) {
-            ln --;
-            if (s->handler[ln])
-                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
-            diff &= ~(1 << ln);
-        }
-        break;
-
-    case 0x08:	/* IO_CNTL */
-        diff = s->outputs & (s->dir ^ value);
-        s->dir = value;
-
-        value = s->outputs & ~s->dir;
-        while ((ln = ffs(diff))) {
-            ln --;
-            if (s->handler[ln])
-                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
-            diff &= ~(1 << ln);
-        }
-        break;
-
-    case 0x14:	/* KBC_REG */
-        s->cols = value;
-        omap_mpuio_kbd_update(s);
-        break;
-
-    case 0x18:	/* GPIO_EVENT_MODE_REG */
-        s->event = value & 0x1f;
-        break;
-
-    case 0x1c:	/* GPIO_INT_EDGE_REG */
-        s->edge = value;
-        break;
-
-    case 0x28:	/* KBD_MASKIT */
-        s->kbd_mask = value & 1;
-        omap_mpuio_kbd_update(s);
-        break;
-
-    case 0x2c:	/* GPIO_MASKIT */
-        s->mask = value;
-        break;
-
-    case 0x30:	/* GPIO_DEBOUNCING_REG */
-        s->debounce = value & 0x1ff;
-        break;
-
-    case 0x00:	/* INPUT_LATCH */
-    case 0x10:	/* KBR_LATCH */
-    case 0x20:	/* KBD_INT */
-    case 0x24:	/* GPIO_INT */
-    case 0x34:	/* GPIO_LATCH_REG */
-        OMAP_RO_REG(addr);
-        return;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_mpuio_ops  = {
-    .read = omap_mpuio_read,
-    .write = omap_mpuio_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_mpuio_reset(struct omap_mpuio_s *s)
-{
-    s->inputs = 0;
-    s->outputs = 0;
-    s->dir = ~0;
-    s->event = 0;
-    s->edge = 0;
-    s->kbd_mask = 0;
-    s->mask = 0;
-    s->debounce = 0;
-    s->latch = 0;
-    s->ints = 0;
-    s->row_latch = 0x1f;
-    s->clk = 1;
-}
-
-static void omap_mpuio_onoff(void *opaque, int line, int on)
-{
-    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
-
-    s->clk = on;
-    if (on)
-        omap_mpuio_kbd_update(s);
-}
-
-static struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *memory,
-                hwaddr base,
-                qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup,
-                omap_clk clk)
-{
-    struct omap_mpuio_s *s = (struct omap_mpuio_s *)
-            g_malloc0(sizeof(struct omap_mpuio_s));
-
-    s->irq = gpio_int;
-    s->kbd_irq = kbd_int;
-    s->wakeup = wakeup;
-    s->in = qemu_allocate_irqs(omap_mpuio_set, s, 16);
-    omap_mpuio_reset(s);
-
-    memory_region_init_io(&s->iomem, &omap_mpuio_ops, s,
-                          "omap-mpuio", 0x800);
-    memory_region_add_subregion(memory, base, &s->iomem);
-
-    omap_clk_adduser(clk, qemu_allocate_irqs(omap_mpuio_onoff, s, 1)[0]);
-
-    return s;
-}
-
-qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s)
-{
-    return s->in;
-}
-
-void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler)
-{
-    if (line >= 16 || line < 0)
-        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
-    s->handler[line] = handler;
-}
-
-void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down)
-{
-    if (row >= 5 || row < 0)
-        hw_error("%s: No key %i-%i\n", __FUNCTION__, col, row);
-
-    if (down)
-        s->buttons[row] |= 1 << col;
-    else
-        s->buttons[row] &= ~(1 << col);
-
-    omap_mpuio_kbd_update(s);
-}
-
-/* MicroWire Interface */
-struct omap_uwire_s {
-    MemoryRegion iomem;
-    qemu_irq txirq;
-    qemu_irq rxirq;
-    qemu_irq txdrq;
-
-    uint16_t txbuf;
-    uint16_t rxbuf;
-    uint16_t control;
-    uint16_t setup[5];
-
-    uWireSlave *chip[4];
-};
-
-static void omap_uwire_transfer_start(struct omap_uwire_s *s)
-{
-    int chipselect = (s->control >> 10) & 3;		/* INDEX */
-    uWireSlave *slave = s->chip[chipselect];
-
-    if ((s->control >> 5) & 0x1f) {			/* NB_BITS_WR */
-        if (s->control & (1 << 12))			/* CS_CMD */
-            if (slave && slave->send)
-                slave->send(slave->opaque,
-                                s->txbuf >> (16 - ((s->control >> 5) & 0x1f)));
-        s->control &= ~(1 << 14);			/* CSRB */
-        /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
-         * a DRQ.  When is the level IRQ supposed to be reset?  */
-    }
-
-    if ((s->control >> 0) & 0x1f) {			/* NB_BITS_RD */
-        if (s->control & (1 << 12))			/* CS_CMD */
-            if (slave && slave->receive)
-                s->rxbuf = slave->receive(slave->opaque);
-        s->control |= 1 << 15;				/* RDRB */
-        /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
-         * a DRQ.  When is the level IRQ supposed to be reset?  */
-    }
-}
-
-static uint64_t omap_uwire_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (offset) {
-    case 0x00:	/* RDR */
-        s->control &= ~(1 << 15);			/* RDRB */
-        return s->rxbuf;
-
-    case 0x04:	/* CSR */
-        return s->control;
-
-    case 0x08:	/* SR1 */
-        return s->setup[0];
-    case 0x0c:	/* SR2 */
-        return s->setup[1];
-    case 0x10:	/* SR3 */
-        return s->setup[2];
-    case 0x14:	/* SR4 */
-        return s->setup[3];
-    case 0x18:	/* SR5 */
-        return s->setup[4];
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_uwire_write(void *opaque, hwaddr addr,
-                             uint64_t value, unsigned size)
-{
-    struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    switch (offset) {
-    case 0x00:	/* TDR */
-        s->txbuf = value;				/* TD */
-        if ((s->setup[4] & (1 << 2)) &&			/* AUTO_TX_EN */
-                        ((s->setup[4] & (1 << 3)) ||	/* CS_TOGGLE_TX_EN */
-                         (s->control & (1 << 12)))) {	/* CS_CMD */
-            s->control |= 1 << 14;			/* CSRB */
-            omap_uwire_transfer_start(s);
-        }
-        break;
-
-    case 0x04:	/* CSR */
-        s->control = value & 0x1fff;
-        if (value & (1 << 13))				/* START */
-            omap_uwire_transfer_start(s);
-        break;
-
-    case 0x08:	/* SR1 */
-        s->setup[0] = value & 0x003f;
-        break;
-
-    case 0x0c:	/* SR2 */
-        s->setup[1] = value & 0x0fc0;
-        break;
-
-    case 0x10:	/* SR3 */
-        s->setup[2] = value & 0x0003;
-        break;
-
-    case 0x14:	/* SR4 */
-        s->setup[3] = value & 0x0001;
-        break;
-
-    case 0x18:	/* SR5 */
-        s->setup[4] = value & 0x000f;
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_uwire_ops = {
-    .read = omap_uwire_read,
-    .write = omap_uwire_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_uwire_reset(struct omap_uwire_s *s)
-{
-    s->control = 0;
-    s->setup[0] = 0;
-    s->setup[1] = 0;
-    s->setup[2] = 0;
-    s->setup[3] = 0;
-    s->setup[4] = 0;
-}
-
-static struct omap_uwire_s *omap_uwire_init(MemoryRegion *system_memory,
-                                            hwaddr base,
-                                            qemu_irq txirq, qemu_irq rxirq,
-                                            qemu_irq dma,
-                                            omap_clk clk)
-{
-    struct omap_uwire_s *s = (struct omap_uwire_s *)
-            g_malloc0(sizeof(struct omap_uwire_s));
-
-    s->txirq = txirq;
-    s->rxirq = rxirq;
-    s->txdrq = dma;
-    omap_uwire_reset(s);
-
-    memory_region_init_io(&s->iomem, &omap_uwire_ops, s, "omap-uwire", 0x800);
-    memory_region_add_subregion(system_memory, base, &s->iomem);
-
-    return s;
-}
-
-void omap_uwire_attach(struct omap_uwire_s *s,
-                uWireSlave *slave, int chipselect)
-{
-    if (chipselect < 0 || chipselect > 3) {
-        fprintf(stderr, "%s: Bad chipselect %i\n", __FUNCTION__, chipselect);
-        exit(-1);
-    }
-
-    s->chip[chipselect] = slave;
-}
-
-/* Pseudonoise Pulse-Width Light Modulator */
-struct omap_pwl_s {
-    MemoryRegion iomem;
-    uint8_t output;
-    uint8_t level;
-    uint8_t enable;
-    int clk;
-};
-
-static void omap_pwl_update(struct omap_pwl_s *s)
-{
-    int output = (s->clk && s->enable) ? s->level : 0;
-
-    if (output != s->output) {
-        s->output = output;
-        printf("%s: Backlight now at %i/256\n", __FUNCTION__, output);
-    }
-}
-
-static uint64_t omap_pwl_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 1) {
-        return omap_badwidth_read8(opaque, addr);
-    }
-
-    switch (offset) {
-    case 0x00:	/* PWL_LEVEL */
-        return s->level;
-    case 0x04:	/* PWL_CTRL */
-        return s->enable;
-    }
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_pwl_write(void *opaque, hwaddr addr,
-                           uint64_t value, unsigned size)
-{
-    struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 1) {
-        return omap_badwidth_write8(opaque, addr, value);
-    }
-
-    switch (offset) {
-    case 0x00:	/* PWL_LEVEL */
-        s->level = value;
-        omap_pwl_update(s);
-        break;
-    case 0x04:	/* PWL_CTRL */
-        s->enable = value & 1;
-        omap_pwl_update(s);
-        break;
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_pwl_ops = {
-    .read = omap_pwl_read,
-    .write = omap_pwl_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_pwl_reset(struct omap_pwl_s *s)
-{
-    s->output = 0;
-    s->level = 0;
-    s->enable = 0;
-    s->clk = 1;
-    omap_pwl_update(s);
-}
-
-static void omap_pwl_clk_update(void *opaque, int line, int on)
-{
-    struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
-
-    s->clk = on;
-    omap_pwl_update(s);
-}
-
-static struct omap_pwl_s *omap_pwl_init(MemoryRegion *system_memory,
-                                        hwaddr base,
-                                        omap_clk clk)
-{
-    struct omap_pwl_s *s = g_malloc0(sizeof(*s));
-
-    omap_pwl_reset(s);
-
-    memory_region_init_io(&s->iomem, &omap_pwl_ops, s,
-                          "omap-pwl", 0x800);
-    memory_region_add_subregion(system_memory, base, &s->iomem);
-
-    omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]);
-    return s;
-}
-
-/* Pulse-Width Tone module */
-struct omap_pwt_s {
-    MemoryRegion iomem;
-    uint8_t frc;
-    uint8_t vrc;
-    uint8_t gcr;
-    omap_clk clk;
-};
-
-static uint64_t omap_pwt_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    struct omap_pwt_s *s = (struct omap_pwt_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 1) {
-        return omap_badwidth_read8(opaque, addr);
-    }
-
-    switch (offset) {
-    case 0x00:	/* FRC */
-        return s->frc;
-    case 0x04:	/* VCR */
-        return s->vrc;
-    case 0x08:	/* GCR */
-        return s->gcr;
-    }
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_pwt_write(void *opaque, hwaddr addr,
-                           uint64_t value, unsigned size)
-{
-    struct omap_pwt_s *s = (struct omap_pwt_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 1) {
-        return omap_badwidth_write8(opaque, addr, value);
-    }
-
-    switch (offset) {
-    case 0x00:	/* FRC */
-        s->frc = value & 0x3f;
-        break;
-    case 0x04:	/* VRC */
-        if ((value ^ s->vrc) & 1) {
-            if (value & 1)
-                printf("%s: %iHz buzz on\n", __FUNCTION__, (int)
-                                /* 1.5 MHz from a 12-MHz or 13-MHz PWT_CLK */
-                                ((omap_clk_getrate(s->clk) >> 3) /
-                                 /* Pre-multiplexer divider */
-                                 ((s->gcr & 2) ? 1 : 154) /
-                                 /* Octave multiplexer */
-                                 (2 << (value & 3)) *
-                                 /* 101/107 divider */
-                                 ((value & (1 << 2)) ? 101 : 107) *
-                                 /*  49/55 divider */
-                                 ((value & (1 << 3)) ?  49 : 55) *
-                                 /*  50/63 divider */
-                                 ((value & (1 << 4)) ?  50 : 63) *
-                                 /*  80/127 divider */
-                                 ((value & (1 << 5)) ?  80 : 127) /
-                                 (107 * 55 * 63 * 127)));
-            else
-                printf("%s: silence!\n", __FUNCTION__);
-        }
-        s->vrc = value & 0x7f;
-        break;
-    case 0x08:	/* GCR */
-        s->gcr = value & 3;
-        break;
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_pwt_ops = {
-    .read =omap_pwt_read,
-    .write = omap_pwt_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_pwt_reset(struct omap_pwt_s *s)
-{
-    s->frc = 0;
-    s->vrc = 0;
-    s->gcr = 0;
-}
-
-static struct omap_pwt_s *omap_pwt_init(MemoryRegion *system_memory,
-                                        hwaddr base,
-                                        omap_clk clk)
-{
-    struct omap_pwt_s *s = g_malloc0(sizeof(*s));
-    s->clk = clk;
-    omap_pwt_reset(s);
-
-    memory_region_init_io(&s->iomem, &omap_pwt_ops, s,
-                          "omap-pwt", 0x800);
-    memory_region_add_subregion(system_memory, base, &s->iomem);
-    return s;
-}
-
-/* Real-time Clock module */
-struct omap_rtc_s {
-    MemoryRegion iomem;
-    qemu_irq irq;
-    qemu_irq alarm;
-    QEMUTimer *clk;
-
-    uint8_t interrupts;
-    uint8_t status;
-    int16_t comp_reg;
-    int running;
-    int pm_am;
-    int auto_comp;
-    int round;
-    struct tm alarm_tm;
-    time_t alarm_ti;
-
-    struct tm current_tm;
-    time_t ti;
-    uint64_t tick;
-};
-
-static void omap_rtc_interrupts_update(struct omap_rtc_s *s)
-{
-    /* s->alarm is level-triggered */
-    qemu_set_irq(s->alarm, (s->status >> 6) & 1);
-}
-
-static void omap_rtc_alarm_update(struct omap_rtc_s *s)
-{
-    s->alarm_ti = mktimegm(&s->alarm_tm);
-    if (s->alarm_ti == -1)
-        printf("%s: conversion failed\n", __FUNCTION__);
-}
-
-static uint64_t omap_rtc_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-    uint8_t i;
-
-    if (size != 1) {
-        return omap_badwidth_read8(opaque, addr);
-    }
-
-    switch (offset) {
-    case 0x00:	/* SECONDS_REG */
-        return to_bcd(s->current_tm.tm_sec);
-
-    case 0x04:	/* MINUTES_REG */
-        return to_bcd(s->current_tm.tm_min);
-
-    case 0x08:	/* HOURS_REG */
-        if (s->pm_am)
-            return ((s->current_tm.tm_hour > 11) << 7) |
-                    to_bcd(((s->current_tm.tm_hour - 1) % 12) + 1);
-        else
-            return to_bcd(s->current_tm.tm_hour);
-
-    case 0x0c:	/* DAYS_REG */
-        return to_bcd(s->current_tm.tm_mday);
-
-    case 0x10:	/* MONTHS_REG */
-        return to_bcd(s->current_tm.tm_mon + 1);
-
-    case 0x14:	/* YEARS_REG */
-        return to_bcd(s->current_tm.tm_year % 100);
-
-    case 0x18:	/* WEEK_REG */
-        return s->current_tm.tm_wday;
-
-    case 0x20:	/* ALARM_SECONDS_REG */
-        return to_bcd(s->alarm_tm.tm_sec);
-
-    case 0x24:	/* ALARM_MINUTES_REG */
-        return to_bcd(s->alarm_tm.tm_min);
-
-    case 0x28:	/* ALARM_HOURS_REG */
-        if (s->pm_am)
-            return ((s->alarm_tm.tm_hour > 11) << 7) |
-                    to_bcd(((s->alarm_tm.tm_hour - 1) % 12) + 1);
-        else
-            return to_bcd(s->alarm_tm.tm_hour);
-
-    case 0x2c:	/* ALARM_DAYS_REG */
-        return to_bcd(s->alarm_tm.tm_mday);
-
-    case 0x30:	/* ALARM_MONTHS_REG */
-        return to_bcd(s->alarm_tm.tm_mon + 1);
-
-    case 0x34:	/* ALARM_YEARS_REG */
-        return to_bcd(s->alarm_tm.tm_year % 100);
-
-    case 0x40:	/* RTC_CTRL_REG */
-        return (s->pm_am << 3) | (s->auto_comp << 2) |
-                (s->round << 1) | s->running;
-
-    case 0x44:	/* RTC_STATUS_REG */
-        i = s->status;
-        s->status &= ~0x3d;
-        return i;
-
-    case 0x48:	/* RTC_INTERRUPTS_REG */
-        return s->interrupts;
-
-    case 0x4c:	/* RTC_COMP_LSB_REG */
-        return ((uint16_t) s->comp_reg) & 0xff;
-
-    case 0x50:	/* RTC_COMP_MSB_REG */
-        return ((uint16_t) s->comp_reg) >> 8;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_rtc_write(void *opaque, hwaddr addr,
-                           uint64_t value, unsigned size)
-{
-    struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-    struct tm new_tm;
-    time_t ti[2];
-
-    if (size != 1) {
-        return omap_badwidth_write8(opaque, addr, value);
-    }
-
-    switch (offset) {
-    case 0x00:	/* SECONDS_REG */
-#ifdef ALMDEBUG
-        printf("RTC SEC_REG <-- %02x\n", value);
-#endif
-        s->ti -= s->current_tm.tm_sec;
-        s->ti += from_bcd(value);
-        return;
-
-    case 0x04:	/* MINUTES_REG */
-#ifdef ALMDEBUG
-        printf("RTC MIN_REG <-- %02x\n", value);
-#endif
-        s->ti -= s->current_tm.tm_min * 60;
-        s->ti += from_bcd(value) * 60;
-        return;
-
-    case 0x08:	/* HOURS_REG */
-#ifdef ALMDEBUG
-        printf("RTC HRS_REG <-- %02x\n", value);
-#endif
-        s->ti -= s->current_tm.tm_hour * 3600;
-        if (s->pm_am) {
-            s->ti += (from_bcd(value & 0x3f) & 12) * 3600;
-            s->ti += ((value >> 7) & 1) * 43200;
-        } else
-            s->ti += from_bcd(value & 0x3f) * 3600;
-        return;
-
-    case 0x0c:	/* DAYS_REG */
-#ifdef ALMDEBUG
-        printf("RTC DAY_REG <-- %02x\n", value);
-#endif
-        s->ti -= s->current_tm.tm_mday * 86400;
-        s->ti += from_bcd(value) * 86400;
-        return;
-
-    case 0x10:	/* MONTHS_REG */
-#ifdef ALMDEBUG
-        printf("RTC MTH_REG <-- %02x\n", value);
-#endif
-        memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
-        new_tm.tm_mon = from_bcd(value);
-        ti[0] = mktimegm(&s->current_tm);
-        ti[1] = mktimegm(&new_tm);
-
-        if (ti[0] != -1 && ti[1] != -1) {
-            s->ti -= ti[0];
-            s->ti += ti[1];
-        } else {
-            /* A less accurate version */
-            s->ti -= s->current_tm.tm_mon * 2592000;
-            s->ti += from_bcd(value) * 2592000;
-        }
-        return;
-
-    case 0x14:	/* YEARS_REG */
-#ifdef ALMDEBUG
-        printf("RTC YRS_REG <-- %02x\n", value);
-#endif
-        memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
-        new_tm.tm_year += from_bcd(value) - (new_tm.tm_year % 100);
-        ti[0] = mktimegm(&s->current_tm);
-        ti[1] = mktimegm(&new_tm);
-
-        if (ti[0] != -1 && ti[1] != -1) {
-            s->ti -= ti[0];
-            s->ti += ti[1];
-        } else {
-            /* A less accurate version */
-            s->ti -= (s->current_tm.tm_year % 100) * 31536000;
-            s->ti += from_bcd(value) * 31536000;
-        }
-        return;
-
-    case 0x18:	/* WEEK_REG */
-        return;	/* Ignored */
-
-    case 0x20:	/* ALARM_SECONDS_REG */
-#ifdef ALMDEBUG
-        printf("ALM SEC_REG <-- %02x\n", value);
-#endif
-        s->alarm_tm.tm_sec = from_bcd(value);
-        omap_rtc_alarm_update(s);
-        return;
-
-    case 0x24:	/* ALARM_MINUTES_REG */
-#ifdef ALMDEBUG
-        printf("ALM MIN_REG <-- %02x\n", value);
-#endif
-        s->alarm_tm.tm_min = from_bcd(value);
-        omap_rtc_alarm_update(s);
-        return;
-
-    case 0x28:	/* ALARM_HOURS_REG */
-#ifdef ALMDEBUG
-        printf("ALM HRS_REG <-- %02x\n", value);
-#endif
-        if (s->pm_am)
-            s->alarm_tm.tm_hour =
-                    ((from_bcd(value & 0x3f)) % 12) +
-                    ((value >> 7) & 1) * 12;
-        else
-            s->alarm_tm.tm_hour = from_bcd(value);
-        omap_rtc_alarm_update(s);
-        return;
-
-    case 0x2c:	/* ALARM_DAYS_REG */
-#ifdef ALMDEBUG
-        printf("ALM DAY_REG <-- %02x\n", value);
-#endif
-        s->alarm_tm.tm_mday = from_bcd(value);
-        omap_rtc_alarm_update(s);
-        return;
-
-    case 0x30:	/* ALARM_MONTHS_REG */
-#ifdef ALMDEBUG
-        printf("ALM MON_REG <-- %02x\n", value);
-#endif
-        s->alarm_tm.tm_mon = from_bcd(value);
-        omap_rtc_alarm_update(s);
-        return;
-
-    case 0x34:	/* ALARM_YEARS_REG */
-#ifdef ALMDEBUG
-        printf("ALM YRS_REG <-- %02x\n", value);
-#endif
-        s->alarm_tm.tm_year = from_bcd(value);
-        omap_rtc_alarm_update(s);
-        return;
-
-    case 0x40:	/* RTC_CTRL_REG */
-#ifdef ALMDEBUG
-        printf("RTC CONTROL <-- %02x\n", value);
-#endif
-        s->pm_am = (value >> 3) & 1;
-        s->auto_comp = (value >> 2) & 1;
-        s->round = (value >> 1) & 1;
-        s->running = value & 1;
-        s->status &= 0xfd;
-        s->status |= s->running << 1;
-        return;
-
-    case 0x44:	/* RTC_STATUS_REG */
-#ifdef ALMDEBUG
-        printf("RTC STATUSL <-- %02x\n", value);
-#endif
-        s->status &= ~((value & 0xc0) ^ 0x80);
-        omap_rtc_interrupts_update(s);
-        return;
-
-    case 0x48:	/* RTC_INTERRUPTS_REG */
-#ifdef ALMDEBUG
-        printf("RTC INTRS <-- %02x\n", value);
-#endif
-        s->interrupts = value;
-        return;
-
-    case 0x4c:	/* RTC_COMP_LSB_REG */
-#ifdef ALMDEBUG
-        printf("RTC COMPLSB <-- %02x\n", value);
-#endif
-        s->comp_reg &= 0xff00;
-        s->comp_reg |= 0x00ff & value;
-        return;
-
-    case 0x50:	/* RTC_COMP_MSB_REG */
-#ifdef ALMDEBUG
-        printf("RTC COMPMSB <-- %02x\n", value);
-#endif
-        s->comp_reg &= 0x00ff;
-        s->comp_reg |= 0xff00 & (value << 8);
-        return;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_rtc_ops = {
-    .read = omap_rtc_read,
-    .write = omap_rtc_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_rtc_tick(void *opaque)
-{
-    struct omap_rtc_s *s = opaque;
-
-    if (s->round) {
-        /* Round to nearest full minute.  */
-        if (s->current_tm.tm_sec < 30)
-            s->ti -= s->current_tm.tm_sec;
-        else
-            s->ti += 60 - s->current_tm.tm_sec;
-
-        s->round = 0;
-    }
-
-    localtime_r(&s->ti, &s->current_tm);
-
-    if ((s->interrupts & 0x08) && s->ti == s->alarm_ti) {
-        s->status |= 0x40;
-        omap_rtc_interrupts_update(s);
-    }
-
-    if (s->interrupts & 0x04)
-        switch (s->interrupts & 3) {
-        case 0:
-            s->status |= 0x04;
-            qemu_irq_pulse(s->irq);
-            break;
-        case 1:
-            if (s->current_tm.tm_sec)
-                break;
-            s->status |= 0x08;
-            qemu_irq_pulse(s->irq);
-            break;
-        case 2:
-            if (s->current_tm.tm_sec || s->current_tm.tm_min)
-                break;
-            s->status |= 0x10;
-            qemu_irq_pulse(s->irq);
-            break;
-        case 3:
-            if (s->current_tm.tm_sec ||
-                            s->current_tm.tm_min || s->current_tm.tm_hour)
-                break;
-            s->status |= 0x20;
-            qemu_irq_pulse(s->irq);
-            break;
-        }
-
-    /* Move on */
-    if (s->running)
-        s->ti ++;
-    s->tick += 1000;
-
-    /*
-     * Every full hour add a rough approximation of the compensation
-     * register to the 32kHz Timer (which drives the RTC) value. 
-     */
-    if (s->auto_comp && !s->current_tm.tm_sec && !s->current_tm.tm_min)
-        s->tick += s->comp_reg * 1000 / 32768;
-
-    qemu_mod_timer(s->clk, s->tick);
-}
-
-static void omap_rtc_reset(struct omap_rtc_s *s)
-{
-    struct tm tm;
-
-    s->interrupts = 0;
-    s->comp_reg = 0;
-    s->running = 0;
-    s->pm_am = 0;
-    s->auto_comp = 0;
-    s->round = 0;
-    s->tick = qemu_get_clock_ms(rtc_clock);
-    memset(&s->alarm_tm, 0, sizeof(s->alarm_tm));
-    s->alarm_tm.tm_mday = 0x01;
-    s->status = 1 << 7;
-    qemu_get_timedate(&tm, 0);
-    s->ti = mktimegm(&tm);
-
-    omap_rtc_alarm_update(s);
-    omap_rtc_tick(s);
-}
-
-static struct omap_rtc_s *omap_rtc_init(MemoryRegion *system_memory,
-                                        hwaddr base,
-                                        qemu_irq timerirq, qemu_irq alarmirq,
-                                        omap_clk clk)
-{
-    struct omap_rtc_s *s = (struct omap_rtc_s *)
-            g_malloc0(sizeof(struct omap_rtc_s));
-
-    s->irq = timerirq;
-    s->alarm = alarmirq;
-    s->clk = qemu_new_timer_ms(rtc_clock, omap_rtc_tick, s);
-
-    omap_rtc_reset(s);
-
-    memory_region_init_io(&s->iomem, &omap_rtc_ops, s,
-                          "omap-rtc", 0x800);
-    memory_region_add_subregion(system_memory, base, &s->iomem);
-
-    return s;
-}
-
-/* Multi-channel Buffered Serial Port interfaces */
-struct omap_mcbsp_s {
-    MemoryRegion iomem;
-    qemu_irq txirq;
-    qemu_irq rxirq;
-    qemu_irq txdrq;
-    qemu_irq rxdrq;
-
-    uint16_t spcr[2];
-    uint16_t rcr[2];
-    uint16_t xcr[2];
-    uint16_t srgr[2];
-    uint16_t mcr[2];
-    uint16_t pcr;
-    uint16_t rcer[8];
-    uint16_t xcer[8];
-    int tx_rate;
-    int rx_rate;
-    int tx_req;
-    int rx_req;
-
-    I2SCodec *codec;
-    QEMUTimer *source_timer;
-    QEMUTimer *sink_timer;
-};
-
-static void omap_mcbsp_intr_update(struct omap_mcbsp_s *s)
-{
-    int irq;
-
-    switch ((s->spcr[0] >> 4) & 3) {			/* RINTM */
-    case 0:
-        irq = (s->spcr[0] >> 1) & 1;			/* RRDY */
-        break;
-    case 3:
-        irq = (s->spcr[0] >> 3) & 1;			/* RSYNCERR */
-        break;
-    default:
-        irq = 0;
-        break;
-    }
-
-    if (irq)
-        qemu_irq_pulse(s->rxirq);
-
-    switch ((s->spcr[1] >> 4) & 3) {			/* XINTM */
-    case 0:
-        irq = (s->spcr[1] >> 1) & 1;			/* XRDY */
-        break;
-    case 3:
-        irq = (s->spcr[1] >> 3) & 1;			/* XSYNCERR */
-        break;
-    default:
-        irq = 0;
-        break;
-    }
-
-    if (irq)
-        qemu_irq_pulse(s->txirq);
-}
-
-static void omap_mcbsp_rx_newdata(struct omap_mcbsp_s *s)
-{
-    if ((s->spcr[0] >> 1) & 1)				/* RRDY */
-        s->spcr[0] |= 1 << 2;				/* RFULL */
-    s->spcr[0] |= 1 << 1;				/* RRDY */
-    qemu_irq_raise(s->rxdrq);
-    omap_mcbsp_intr_update(s);
-}
-
-static void omap_mcbsp_source_tick(void *opaque)
-{
-    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
-    static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
-
-    if (!s->rx_rate)
-        return;
-    if (s->rx_req)
-        printf("%s: Rx FIFO overrun\n", __FUNCTION__);
-
-    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_ns(vm_clock) +
-                   get_ticks_per_sec());
-}
-
-static void omap_mcbsp_rx_start(struct omap_mcbsp_s *s)
-{
-    if (!s->codec || !s->codec->rts)
-        omap_mcbsp_source_tick(s);
-    else if (s->codec->in.len) {
-        s->rx_req = s->codec->in.len;
-        omap_mcbsp_rx_newdata(s);
-    }
-}
-
-static void omap_mcbsp_rx_stop(struct omap_mcbsp_s *s)
-{
-    qemu_del_timer(s->source_timer);
-}
-
-static void omap_mcbsp_rx_done(struct omap_mcbsp_s *s)
-{
-    s->spcr[0] &= ~(1 << 1);				/* RRDY */
-    qemu_irq_lower(s->rxdrq);
-    omap_mcbsp_intr_update(s);
-}
-
-static void omap_mcbsp_tx_newdata(struct omap_mcbsp_s *s)
-{
-    s->spcr[1] |= 1 << 1;				/* XRDY */
-    qemu_irq_raise(s->txdrq);
-    omap_mcbsp_intr_update(s);
-}
-
-static void omap_mcbsp_sink_tick(void *opaque)
-{
-    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
-    static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
-
-    if (!s->tx_rate)
-        return;
-    if (s->tx_req)
-        printf("%s: Tx FIFO underrun\n", __FUNCTION__);
-
-    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_ns(vm_clock) +
-                   get_ticks_per_sec());
-}
-
-static void omap_mcbsp_tx_start(struct omap_mcbsp_s *s)
-{
-    if (!s->codec || !s->codec->cts)
-        omap_mcbsp_sink_tick(s);
-    else if (s->codec->out.size) {
-        s->tx_req = s->codec->out.size;
-        omap_mcbsp_tx_newdata(s);
-    }
-}
-
-static void omap_mcbsp_tx_done(struct omap_mcbsp_s *s)
-{
-    s->spcr[1] &= ~(1 << 1);				/* XRDY */
-    qemu_irq_lower(s->txdrq);
-    omap_mcbsp_intr_update(s);
-    if (s->codec && s->codec->cts)
-        s->codec->tx_swallow(s->codec->opaque);
-}
-
-static void omap_mcbsp_tx_stop(struct omap_mcbsp_s *s)
-{
-    s->tx_req = 0;
-    omap_mcbsp_tx_done(s);
-    qemu_del_timer(s->sink_timer);
-}
-
-static void omap_mcbsp_req_update(struct omap_mcbsp_s *s)
-{
-    int prev_rx_rate, prev_tx_rate;
-    int rx_rate = 0, tx_rate = 0;
-    int cpu_rate = 1500000;	/* XXX */
-
-    /* TODO: check CLKSTP bit */
-    if (s->spcr[1] & (1 << 6)) {			/* GRST */
-        if (s->spcr[0] & (1 << 0)) {			/* RRST */
-            if ((s->srgr[1] & (1 << 13)) &&		/* CLKSM */
-                            (s->pcr & (1 << 8))) {	/* CLKRM */
-                if (~s->pcr & (1 << 7))			/* SCLKME */
-                    rx_rate = cpu_rate /
-                            ((s->srgr[0] & 0xff) + 1);	/* CLKGDV */
-            } else
-                if (s->codec)
-                    rx_rate = s->codec->rx_rate;
-        }
-
-        if (s->spcr[1] & (1 << 0)) {			/* XRST */
-            if ((s->srgr[1] & (1 << 13)) &&		/* CLKSM */
-                            (s->pcr & (1 << 9))) {	/* CLKXM */
-                if (~s->pcr & (1 << 7))			/* SCLKME */
-                    tx_rate = cpu_rate /
-                            ((s->srgr[0] & 0xff) + 1);	/* CLKGDV */
-            } else
-                if (s->codec)
-                    tx_rate = s->codec->tx_rate;
-        }
-    }
-    prev_tx_rate = s->tx_rate;
-    prev_rx_rate = s->rx_rate;
-    s->tx_rate = tx_rate;
-    s->rx_rate = rx_rate;
-
-    if (s->codec)
-        s->codec->set_rate(s->codec->opaque, rx_rate, tx_rate);
-
-    if (!prev_tx_rate && tx_rate)
-        omap_mcbsp_tx_start(s);
-    else if (s->tx_rate && !tx_rate)
-        omap_mcbsp_tx_stop(s);
-
-    if (!prev_rx_rate && rx_rate)
-        omap_mcbsp_rx_start(s);
-    else if (prev_tx_rate && !tx_rate)
-        omap_mcbsp_rx_stop(s);
-}
-
-static uint64_t omap_mcbsp_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-    uint16_t ret;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (offset) {
-    case 0x00:	/* DRR2 */
-        if (((s->rcr[0] >> 5) & 7) < 3)			/* RWDLEN1 */
-            return 0x0000;
-        /* Fall through.  */
-    case 0x02:	/* DRR1 */
-        if (s->rx_req < 2) {
-            printf("%s: Rx FIFO underrun\n", __FUNCTION__);
-            omap_mcbsp_rx_done(s);
-        } else {
-            s->tx_req -= 2;
-            if (s->codec && s->codec->in.len >= 2) {
-                ret = s->codec->in.fifo[s->codec->in.start ++] << 8;
-                ret |= s->codec->in.fifo[s->codec->in.start ++];
-                s->codec->in.len -= 2;
-            } else
-                ret = 0x0000;
-            if (!s->tx_req)
-                omap_mcbsp_rx_done(s);
-            return ret;
-        }
-        return 0x0000;
-
-    case 0x04:	/* DXR2 */
-    case 0x06:	/* DXR1 */
-        return 0x0000;
-
-    case 0x08:	/* SPCR2 */
-        return s->spcr[1];
-    case 0x0a:	/* SPCR1 */
-        return s->spcr[0];
-    case 0x0c:	/* RCR2 */
-        return s->rcr[1];
-    case 0x0e:	/* RCR1 */
-        return s->rcr[0];
-    case 0x10:	/* XCR2 */
-        return s->xcr[1];
-    case 0x12:	/* XCR1 */
-        return s->xcr[0];
-    case 0x14:	/* SRGR2 */
-        return s->srgr[1];
-    case 0x16:	/* SRGR1 */
-        return s->srgr[0];
-    case 0x18:	/* MCR2 */
-        return s->mcr[1];
-    case 0x1a:	/* MCR1 */
-        return s->mcr[0];
-    case 0x1c:	/* RCERA */
-        return s->rcer[0];
-    case 0x1e:	/* RCERB */
-        return s->rcer[1];
-    case 0x20:	/* XCERA */
-        return s->xcer[0];
-    case 0x22:	/* XCERB */
-        return s->xcer[1];
-    case 0x24:	/* PCR0 */
-        return s->pcr;
-    case 0x26:	/* RCERC */
-        return s->rcer[2];
-    case 0x28:	/* RCERD */
-        return s->rcer[3];
-    case 0x2a:	/* XCERC */
-        return s->xcer[2];
-    case 0x2c:	/* XCERD */
-        return s->xcer[3];
-    case 0x2e:	/* RCERE */
-        return s->rcer[4];
-    case 0x30:	/* RCERF */
-        return s->rcer[5];
-    case 0x32:	/* XCERE */
-        return s->xcer[4];
-    case 0x34:	/* XCERF */
-        return s->xcer[5];
-    case 0x36:	/* RCERG */
-        return s->rcer[6];
-    case 0x38:	/* RCERH */
-        return s->rcer[7];
-    case 0x3a:	/* XCERG */
-        return s->xcer[6];
-    case 0x3c:	/* XCERH */
-        return s->xcer[7];
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_mcbsp_writeh(void *opaque, hwaddr addr,
-                uint32_t value)
-{
-    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    switch (offset) {
-    case 0x00:	/* DRR2 */
-    case 0x02:	/* DRR1 */
-        OMAP_RO_REG(addr);
-        return;
-
-    case 0x04:	/* DXR2 */
-        if (((s->xcr[0] >> 5) & 7) < 3)			/* XWDLEN1 */
-            return;
-        /* Fall through.  */
-    case 0x06:	/* DXR1 */
-        if (s->tx_req > 1) {
-            s->tx_req -= 2;
-            if (s->codec && s->codec->cts) {
-                s->codec->out.fifo[s->codec->out.len ++] = (value >> 8) & 0xff;
-                s->codec->out.fifo[s->codec->out.len ++] = (value >> 0) & 0xff;
-            }
-            if (s->tx_req < 2)
-                omap_mcbsp_tx_done(s);
-        } else
-            printf("%s: Tx FIFO overrun\n", __FUNCTION__);
-        return;
-
-    case 0x08:	/* SPCR2 */
-        s->spcr[1] &= 0x0002;
-        s->spcr[1] |= 0x03f9 & value;
-        s->spcr[1] |= 0x0004 & (value << 2);		/* XEMPTY := XRST */
-        if (~value & 1)					/* XRST */
-            s->spcr[1] &= ~6;
-        omap_mcbsp_req_update(s);
-        return;
-    case 0x0a:	/* SPCR1 */
-        s->spcr[0] &= 0x0006;
-        s->spcr[0] |= 0xf8f9 & value;
-        if (value & (1 << 15))				/* DLB */
-            printf("%s: Digital Loopback mode enable attempt\n", __FUNCTION__);
-        if (~value & 1) {				/* RRST */
-            s->spcr[0] &= ~6;
-            s->rx_req = 0;
-            omap_mcbsp_rx_done(s);
-        }
-        omap_mcbsp_req_update(s);
-        return;
-
-    case 0x0c:	/* RCR2 */
-        s->rcr[1] = value & 0xffff;
-        return;
-    case 0x0e:	/* RCR1 */
-        s->rcr[0] = value & 0x7fe0;
-        return;
-    case 0x10:	/* XCR2 */
-        s->xcr[1] = value & 0xffff;
-        return;
-    case 0x12:	/* XCR1 */
-        s->xcr[0] = value & 0x7fe0;
-        return;
-    case 0x14:	/* SRGR2 */
-        s->srgr[1] = value & 0xffff;
-        omap_mcbsp_req_update(s);
-        return;
-    case 0x16:	/* SRGR1 */
-        s->srgr[0] = value & 0xffff;
-        omap_mcbsp_req_update(s);
-        return;
-    case 0x18:	/* MCR2 */
-        s->mcr[1] = value & 0x03e3;
-        if (value & 3)					/* XMCM */
-            printf("%s: Tx channel selection mode enable attempt\n",
-                            __FUNCTION__);
-        return;
-    case 0x1a:	/* MCR1 */
-        s->mcr[0] = value & 0x03e1;
-        if (value & 1)					/* RMCM */
-            printf("%s: Rx channel selection mode enable attempt\n",
-                            __FUNCTION__);
-        return;
-    case 0x1c:	/* RCERA */
-        s->rcer[0] = value & 0xffff;
-        return;
-    case 0x1e:	/* RCERB */
-        s->rcer[1] = value & 0xffff;
-        return;
-    case 0x20:	/* XCERA */
-        s->xcer[0] = value & 0xffff;
-        return;
-    case 0x22:	/* XCERB */
-        s->xcer[1] = value & 0xffff;
-        return;
-    case 0x24:	/* PCR0 */
-        s->pcr = value & 0x7faf;
-        return;
-    case 0x26:	/* RCERC */
-        s->rcer[2] = value & 0xffff;
-        return;
-    case 0x28:	/* RCERD */
-        s->rcer[3] = value & 0xffff;
-        return;
-    case 0x2a:	/* XCERC */
-        s->xcer[2] = value & 0xffff;
-        return;
-    case 0x2c:	/* XCERD */
-        s->xcer[3] = value & 0xffff;
-        return;
-    case 0x2e:	/* RCERE */
-        s->rcer[4] = value & 0xffff;
-        return;
-    case 0x30:	/* RCERF */
-        s->rcer[5] = value & 0xffff;
-        return;
-    case 0x32:	/* XCERE */
-        s->xcer[4] = value & 0xffff;
-        return;
-    case 0x34:	/* XCERF */
-        s->xcer[5] = value & 0xffff;
-        return;
-    case 0x36:	/* RCERG */
-        s->rcer[6] = value & 0xffff;
-        return;
-    case 0x38:	/* RCERH */
-        s->rcer[7] = value & 0xffff;
-        return;
-    case 0x3a:	/* XCERG */
-        s->xcer[6] = value & 0xffff;
-        return;
-    case 0x3c:	/* XCERH */
-        s->xcer[7] = value & 0xffff;
-        return;
-    }
-
-    OMAP_BAD_REG(addr);
-}
-
-static void omap_mcbsp_writew(void *opaque, hwaddr addr,
-                uint32_t value)
-{
-    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (offset == 0x04) {				/* DXR */
-        if (((s->xcr[0] >> 5) & 7) < 3)			/* XWDLEN1 */
-            return;
-        if (s->tx_req > 3) {
-            s->tx_req -= 4;
-            if (s->codec && s->codec->cts) {
-                s->codec->out.fifo[s->codec->out.len ++] =
-                        (value >> 24) & 0xff;
-                s->codec->out.fifo[s->codec->out.len ++] =
-                        (value >> 16) & 0xff;
-                s->codec->out.fifo[s->codec->out.len ++] =
-                        (value >> 8) & 0xff;
-                s->codec->out.fifo[s->codec->out.len ++] =
-                        (value >> 0) & 0xff;
-            }
-            if (s->tx_req < 4)
-                omap_mcbsp_tx_done(s);
-        } else
-            printf("%s: Tx FIFO overrun\n", __FUNCTION__);
-        return;
-    }
-
-    omap_badwidth_write16(opaque, addr, value);
-}
-
-static void omap_mcbsp_write(void *opaque, hwaddr addr,
-                             uint64_t value, unsigned size)
-{
-    switch (size) {
-    case 2: return omap_mcbsp_writeh(opaque, addr, value);
-    case 4: return omap_mcbsp_writew(opaque, addr, value);
-    default: return omap_badwidth_write16(opaque, addr, value);
-    }
-}
-
-static const MemoryRegionOps omap_mcbsp_ops = {
-    .read = omap_mcbsp_read,
-    .write = omap_mcbsp_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_mcbsp_reset(struct omap_mcbsp_s *s)
-{
-    memset(&s->spcr, 0, sizeof(s->spcr));
-    memset(&s->rcr, 0, sizeof(s->rcr));
-    memset(&s->xcr, 0, sizeof(s->xcr));
-    s->srgr[0] = 0x0001;
-    s->srgr[1] = 0x2000;
-    memset(&s->mcr, 0, sizeof(s->mcr));
-    memset(&s->pcr, 0, sizeof(s->pcr));
-    memset(&s->rcer, 0, sizeof(s->rcer));
-    memset(&s->xcer, 0, sizeof(s->xcer));
-    s->tx_req = 0;
-    s->rx_req = 0;
-    s->tx_rate = 0;
-    s->rx_rate = 0;
-    qemu_del_timer(s->source_timer);
-    qemu_del_timer(s->sink_timer);
-}
-
-static struct omap_mcbsp_s *omap_mcbsp_init(MemoryRegion *system_memory,
-                                            hwaddr base,
-                                            qemu_irq txirq, qemu_irq rxirq,
-                                            qemu_irq *dma, omap_clk clk)
-{
-    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *)
-            g_malloc0(sizeof(struct omap_mcbsp_s));
-
-    s->txirq = txirq;
-    s->rxirq = rxirq;
-    s->txdrq = dma[0];
-    s->rxdrq = dma[1];
-    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);
-
-    memory_region_init_io(&s->iomem, &omap_mcbsp_ops, s, "omap-mcbsp", 0x800);
-    memory_region_add_subregion(system_memory, base, &s->iomem);
-
-    return s;
-}
-
-static void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
-{
-    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
-
-    if (s->rx_rate) {
-        s->rx_req = s->codec->in.len;
-        omap_mcbsp_rx_newdata(s);
-    }
-}
-
-static void omap_mcbsp_i2s_start(void *opaque, int line, int level)
-{
-    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
-
-    if (s->tx_rate) {
-        s->tx_req = s->codec->out.size;
-        omap_mcbsp_tx_newdata(s);
-    }
-}
-
-void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, I2SCodec *slave)
-{
-    s->codec = slave;
-    slave->rx_swallow = qemu_allocate_irqs(omap_mcbsp_i2s_swallow, s, 1)[0];
-    slave->tx_start = qemu_allocate_irqs(omap_mcbsp_i2s_start, s, 1)[0];
-}
-
-/* LED Pulse Generators */
-struct omap_lpg_s {
-    MemoryRegion iomem;
-    QEMUTimer *tm;
-
-    uint8_t control;
-    uint8_t power;
-    int64_t on;
-    int64_t period;
-    int clk;
-    int cycle;
-};
-
-static void omap_lpg_tick(void *opaque)
-{
-    struct omap_lpg_s *s = opaque;
-
-    if (s->cycle)
-        qemu_mod_timer(s->tm, qemu_get_clock_ms(vm_clock) + s->period - s->on);
-    else
-        qemu_mod_timer(s->tm, qemu_get_clock_ms(vm_clock) + s->on);
-
-    s->cycle = !s->cycle;
-    printf("%s: LED is %s\n", __FUNCTION__, s->cycle ? "on" : "off");
-}
-
-static void omap_lpg_update(struct omap_lpg_s *s)
-{
-    int64_t on, period = 1, ticks = 1000;
-    static const int per[8] = { 1, 2, 4, 8, 12, 16, 20, 24 };
-
-    if (~s->control & (1 << 6))					/* LPGRES */
-        on = 0;
-    else if (s->control & (1 << 7))				/* PERM_ON */
-        on = period;
-    else {
-        period = muldiv64(ticks, per[s->control & 7],		/* PERCTRL */
-                        256 / 32);
-        on = (s->clk && s->power) ? muldiv64(ticks,
-                        per[(s->control >> 3) & 7], 256) : 0;	/* ONCTRL */
-    }
-
-    qemu_del_timer(s->tm);
-    if (on == period && s->on < s->period)
-        printf("%s: LED is on\n", __FUNCTION__);
-    else if (on == 0 && s->on)
-        printf("%s: LED is off\n", __FUNCTION__);
-    else if (on && (on != s->on || period != s->period)) {
-        s->cycle = 0;
-        s->on = on;
-        s->period = period;
-        omap_lpg_tick(s);
-        return;
-    }
-
-    s->on = on;
-    s->period = period;
-}
-
-static void omap_lpg_reset(struct omap_lpg_s *s)
-{
-    s->control = 0x00;
-    s->power = 0x00;
-    s->clk = 1;
-    omap_lpg_update(s);
-}
-
-static uint64_t omap_lpg_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 1) {
-        return omap_badwidth_read8(opaque, addr);
-    }
-
-    switch (offset) {
-    case 0x00:	/* LCR */
-        return s->control;
-
-    case 0x04:	/* PMR */
-        return s->power;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_lpg_write(void *opaque, hwaddr addr,
-                           uint64_t value, unsigned size)
-{
-    struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
-    int offset = addr & OMAP_MPUI_REG_MASK;
-
-    if (size != 1) {
-        return omap_badwidth_write8(opaque, addr, value);
-    }
-
-    switch (offset) {
-    case 0x00:	/* LCR */
-        if (~value & (1 << 6))					/* LPGRES */
-            omap_lpg_reset(s);
-        s->control = value & 0xff;
-        omap_lpg_update(s);
-        return;
-
-    case 0x04:	/* PMR */
-        s->power = value & 0x01;
-        omap_lpg_update(s);
-        return;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_lpg_ops = {
-    .read = omap_lpg_read,
-    .write = omap_lpg_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_lpg_clk_update(void *opaque, int line, int on)
-{
-    struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
-
-    s->clk = on;
-    omap_lpg_update(s);
-}
-
-static struct omap_lpg_s *omap_lpg_init(MemoryRegion *system_memory,
-                                        hwaddr base, omap_clk clk)
-{
-    struct omap_lpg_s *s = (struct omap_lpg_s *)
-            g_malloc0(sizeof(struct omap_lpg_s));
-
-    s->tm = qemu_new_timer_ms(vm_clock, omap_lpg_tick, s);
-
-    omap_lpg_reset(s);
-
-    memory_region_init_io(&s->iomem, &omap_lpg_ops, s, "omap-lpg", 0x800);
-    memory_region_add_subregion(system_memory, base, &s->iomem);
-
-    omap_clk_adduser(clk, qemu_allocate_irqs(omap_lpg_clk_update, s, 1)[0]);
-
-    return s;
-}
-
-/* MPUI Peripheral Bridge configuration */
-static uint64_t omap_mpui_io_read(void *opaque, hwaddr addr,
-                                  unsigned size)
-{
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    if (addr == OMAP_MPUI_BASE)	/* CMR */
-        return 0xfe4d;
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_mpui_io_write(void *opaque, hwaddr addr,
-                               uint64_t value, unsigned size)
-{
-    /* FIXME: infinite loop */
-    omap_badwidth_write16(opaque, addr, value);
-}
-
-static const MemoryRegionOps omap_mpui_io_ops = {
-    .read = omap_mpui_io_read,
-    .write = omap_mpui_io_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_setup_mpui_io(MemoryRegion *system_memory,
-                               struct omap_mpu_state_s *mpu)
-{
-    memory_region_init_io(&mpu->mpui_io_iomem, &omap_mpui_io_ops, mpu,
-                          "omap-mpui-io", 0x7fff);
-    memory_region_add_subregion(system_memory, OMAP_MPUI_BASE,
-                                &mpu->mpui_io_iomem);
-}
-
-/* General chip reset */
-static void omap1_mpu_reset(void *opaque)
-{
-    struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
-
-    omap_dma_reset(mpu->dma);
-    omap_mpu_timer_reset(mpu->timer[0]);
-    omap_mpu_timer_reset(mpu->timer[1]);
-    omap_mpu_timer_reset(mpu->timer[2]);
-    omap_wd_timer_reset(mpu->wdt);
-    omap_os_timer_reset(mpu->os_timer);
-    omap_lcdc_reset(mpu->lcd);
-    omap_ulpd_pm_reset(mpu);
-    omap_pin_cfg_reset(mpu);
-    omap_mpui_reset(mpu);
-    omap_tipb_bridge_reset(mpu->private_tipb);
-    omap_tipb_bridge_reset(mpu->public_tipb);
-    omap_dpll_reset(mpu->dpll[0]);
-    omap_dpll_reset(mpu->dpll[1]);
-    omap_dpll_reset(mpu->dpll[2]);
-    omap_uart_reset(mpu->uart[0]);
-    omap_uart_reset(mpu->uart[1]);
-    omap_uart_reset(mpu->uart[2]);
-    omap_mmc_reset(mpu->mmc);
-    omap_mpuio_reset(mpu->mpuio);
-    omap_uwire_reset(mpu->microwire);
-    omap_pwl_reset(mpu->pwl);
-    omap_pwt_reset(mpu->pwt);
-    omap_rtc_reset(mpu->rtc);
-    omap_mcbsp_reset(mpu->mcbsp1);
-    omap_mcbsp_reset(mpu->mcbsp2);
-    omap_mcbsp_reset(mpu->mcbsp3);
-    omap_lpg_reset(mpu->led[0]);
-    omap_lpg_reset(mpu->led[1]);
-    omap_clkm_reset(mpu);
-    cpu_reset(CPU(mpu->cpu));
-}
-
-static const struct omap_map_s {
-    hwaddr phys_dsp;
-    hwaddr phys_mpu;
-    uint32_t size;
-    const char *name;
-} omap15xx_dsp_mm[] = {
-    /* Strobe 0 */
-    { 0xe1010000, 0xfffb0000, 0x800, "UART1 BT" },		/* CS0 */
-    { 0xe1010800, 0xfffb0800, 0x800, "UART2 COM" },		/* CS1 */
-    { 0xe1011800, 0xfffb1800, 0x800, "McBSP1 audio" },		/* CS3 */
-    { 0xe1012000, 0xfffb2000, 0x800, "MCSI2 communication" },	/* CS4 */
-    { 0xe1012800, 0xfffb2800, 0x800, "MCSI1 BT u-Law" },	/* CS5 */
-    { 0xe1013000, 0xfffb3000, 0x800, "uWire" },			/* CS6 */
-    { 0xe1013800, 0xfffb3800, 0x800, "I^2C" },			/* CS7 */
-    { 0xe1014000, 0xfffb4000, 0x800, "USB W2FC" },		/* CS8 */
-    { 0xe1014800, 0xfffb4800, 0x800, "RTC" },			/* CS9 */
-    { 0xe1015000, 0xfffb5000, 0x800, "MPUIO" },			/* CS10 */
-    { 0xe1015800, 0xfffb5800, 0x800, "PWL" },			/* CS11 */
-    { 0xe1016000, 0xfffb6000, 0x800, "PWT" },			/* CS12 */
-    { 0xe1017000, 0xfffb7000, 0x800, "McBSP3" },		/* CS14 */
-    { 0xe1017800, 0xfffb7800, 0x800, "MMC" },			/* CS15 */
-    { 0xe1019000, 0xfffb9000, 0x800, "32-kHz timer" },		/* CS18 */
-    { 0xe1019800, 0xfffb9800, 0x800, "UART3" },			/* CS19 */
-    { 0xe101c800, 0xfffbc800, 0x800, "TIPB switches" },		/* CS25 */
-    /* Strobe 1 */
-    { 0xe101e000, 0xfffce000, 0x800, "GPIOs" },			/* CS28 */
-
-    { 0 }
-};
-
-static void omap_setup_dsp_mapping(MemoryRegion *system_memory,
-                                   const struct omap_map_s *map)
-{
-    MemoryRegion *io;
-
-    for (; map->phys_dsp; map ++) {
-        io = g_new(MemoryRegion, 1);
-        memory_region_init_alias(io, map->name,
-                                 system_memory, map->phys_mpu, map->size);
-        memory_region_add_subregion(system_memory, map->phys_dsp, io);
-    }
-}
-
-void omap_mpu_wakeup(void *opaque, int irq, int req)
-{
-    struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
-
-    if (mpu->cpu->env.halted) {
-        cpu_interrupt(&mpu->cpu->env, CPU_INTERRUPT_EXITTB);
-    }
-}
-
-static const struct dma_irq_map omap1_dma_irq_map[] = {
-    { 0, OMAP_INT_DMA_CH0_6 },
-    { 0, OMAP_INT_DMA_CH1_7 },
-    { 0, OMAP_INT_DMA_CH2_8 },
-    { 0, OMAP_INT_DMA_CH3 },
-    { 0, OMAP_INT_DMA_CH4 },
-    { 0, OMAP_INT_DMA_CH5 },
-    { 1, OMAP_INT_1610_DMA_CH6 },
-    { 1, OMAP_INT_1610_DMA_CH7 },
-    { 1, OMAP_INT_1610_DMA_CH8 },
-    { 1, OMAP_INT_1610_DMA_CH9 },
-    { 1, OMAP_INT_1610_DMA_CH10 },
-    { 1, OMAP_INT_1610_DMA_CH11 },
-    { 1, OMAP_INT_1610_DMA_CH12 },
-    { 1, OMAP_INT_1610_DMA_CH13 },
-    { 1, OMAP_INT_1610_DMA_CH14 },
-    { 1, OMAP_INT_1610_DMA_CH15 }
-};
-
-/* DMA ports for OMAP1 */
-static int omap_validate_emiff_addr(struct omap_mpu_state_s *s,
-                hwaddr addr)
-{
-    return range_covers_byte(OMAP_EMIFF_BASE, s->sdram_size, addr);
-}
-
-static int omap_validate_emifs_addr(struct omap_mpu_state_s *s,
-                hwaddr addr)
-{
-    return range_covers_byte(OMAP_EMIFS_BASE, OMAP_EMIFF_BASE - OMAP_EMIFS_BASE,
-                             addr);
-}
-
-static int omap_validate_imif_addr(struct omap_mpu_state_s *s,
-                hwaddr addr)
-{
-    return range_covers_byte(OMAP_IMIF_BASE, s->sram_size, addr);
-}
-
-static int omap_validate_tipb_addr(struct omap_mpu_state_s *s,
-                hwaddr addr)
-{
-    return range_covers_byte(0xfffb0000, 0xffff0000 - 0xfffb0000, addr);
-}
-
-static int omap_validate_local_addr(struct omap_mpu_state_s *s,
-                hwaddr addr)
-{
-    return range_covers_byte(OMAP_LOCALBUS_BASE, 0x1000000, addr);
-}
-
-static int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s,
-                hwaddr addr)
-{
-    return range_covers_byte(0xe1010000, 0xe1020004 - 0xe1010000, addr);
-}
-
-struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
-                unsigned long sdram_size,
-                const char *core)
-{
-    int i;
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
-            g_malloc0(sizeof(struct omap_mpu_state_s));
-    qemu_irq *cpu_irq;
-    qemu_irq dma_irqs[6];
-    DriveInfo *dinfo;
-    SysBusDevice *busdev;
-
-    if (!core)
-        core = "ti925t";
-
-    /* Core */
-    s->mpu_model = omap310;
-    s->cpu = cpu_arm_init(core);
-    if (s->cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    s->sdram_size = sdram_size;
-    s->sram_size = OMAP15XX_SRAM_SIZE;
-
-    s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
-
-    /* Clocks */
-    omap_clk_init(s);
-
-    /* Memory-mapped stuff */
-    memory_region_init_ram(&s->emiff_ram, "omap1.dram", s->sdram_size);
-    vmstate_register_ram_global(&s->emiff_ram);
-    memory_region_add_subregion(system_memory, OMAP_EMIFF_BASE, &s->emiff_ram);
-    memory_region_init_ram(&s->imif_ram, "omap1.sram", s->sram_size);
-    vmstate_register_ram_global(&s->imif_ram);
-    memory_region_add_subregion(system_memory, OMAP_IMIF_BASE, &s->imif_ram);
-
-    omap_clkm_init(system_memory, 0xfffece00, 0xe1008000, s);
-
-    cpu_irq = arm_pic_init_cpu(s->cpu);
-    s->ih[0] = qdev_create(NULL, "omap-intc");
-    qdev_prop_set_uint32(s->ih[0], "size", 0x100);
-    qdev_prop_set_ptr(s->ih[0], "clk", omap_findclk(s, "arminth_ck"));
-    qdev_init_nofail(s->ih[0]);
-    busdev = SYS_BUS_DEVICE(s->ih[0]);
-    sysbus_connect_irq(busdev, 0, cpu_irq[ARM_PIC_CPU_IRQ]);
-    sysbus_connect_irq(busdev, 1, cpu_irq[ARM_PIC_CPU_FIQ]);
-    sysbus_mmio_map(busdev, 0, 0xfffecb00);
-    s->ih[1] = qdev_create(NULL, "omap-intc");
-    qdev_prop_set_uint32(s->ih[1], "size", 0x800);
-    qdev_prop_set_ptr(s->ih[1], "clk", omap_findclk(s, "arminth_ck"));
-    qdev_init_nofail(s->ih[1]);
-    busdev = SYS_BUS_DEVICE(s->ih[1]);
-    sysbus_connect_irq(busdev, 0,
-                       qdev_get_gpio_in(s->ih[0], OMAP_INT_15XX_IH2_IRQ));
-    /* The second interrupt controller's FIQ output is not wired up */
-    sysbus_mmio_map(busdev, 0, 0xfffe0000);
-
-    for (i = 0; i < 6; i++) {
-        dma_irqs[i] = qdev_get_gpio_in(s->ih[omap1_dma_irq_map[i].ih],
-                                       omap1_dma_irq_map[i].intr);
-    }
-    s->dma = omap_dma_init(0xfffed800, dma_irqs, system_memory,
-                           qdev_get_gpio_in(s->ih[0], OMAP_INT_DMA_LCD),
-                           s, omap_findclk(s, "dma_ck"), omap_dma_3_1);
-
-    s->port[emiff    ].addr_valid = omap_validate_emiff_addr;
-    s->port[emifs    ].addr_valid = omap_validate_emifs_addr;
-    s->port[imif     ].addr_valid = omap_validate_imif_addr;
-    s->port[tipb     ].addr_valid = omap_validate_tipb_addr;
-    s->port[local    ].addr_valid = omap_validate_local_addr;
-    s->port[tipb_mpui].addr_valid = omap_validate_tipb_mpui_addr;
-
-    /* Register SDRAM and SRAM DMA ports for fast transfers.  */
-    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->emiff_ram),
-                         OMAP_EMIFF_BASE, s->sdram_size);
-    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->imif_ram),
-                         OMAP_IMIF_BASE, s->sram_size);
-
-    s->timer[0] = omap_mpu_timer_init(system_memory, 0xfffec500,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_TIMER1),
-                    omap_findclk(s, "mputim_ck"));
-    s->timer[1] = omap_mpu_timer_init(system_memory, 0xfffec600,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_TIMER2),
-                    omap_findclk(s, "mputim_ck"));
-    s->timer[2] = omap_mpu_timer_init(system_memory, 0xfffec700,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_TIMER3),
-                    omap_findclk(s, "mputim_ck"));
-
-    s->wdt = omap_wd_timer_init(system_memory, 0xfffec800,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_WD_TIMER),
-                    omap_findclk(s, "armwdt_ck"));
-
-    s->os_timer = omap_os_timer_init(system_memory, 0xfffb9000,
-                    qdev_get_gpio_in(s->ih[1], OMAP_INT_OS_TIMER),
-                    omap_findclk(s, "clk32-kHz"));
-
-    s->lcd = omap_lcdc_init(system_memory, 0xfffec000,
-                            qdev_get_gpio_in(s->ih[0], OMAP_INT_LCD_CTRL),
-                            omap_dma_get_lcdch(s->dma),
-                            omap_findclk(s, "lcd_ck"));
-
-    omap_ulpd_pm_init(system_memory, 0xfffe0800, s);
-    omap_pin_cfg_init(system_memory, 0xfffe1000, s);
-    omap_id_init(system_memory, s);
-
-    omap_mpui_init(system_memory, 0xfffec900, s);
-
-    s->private_tipb = omap_tipb_bridge_init(system_memory, 0xfffeca00,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_BRIDGE_PRIV),
-                    omap_findclk(s, "tipb_ck"));
-    s->public_tipb = omap_tipb_bridge_init(system_memory, 0xfffed300,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_BRIDGE_PUB),
-                    omap_findclk(s, "tipb_ck"));
-
-    omap_tcmi_init(system_memory, 0xfffecc00, s);
-
-    s->uart[0] = omap_uart_init(0xfffb0000,
-                                qdev_get_gpio_in(s->ih[1], OMAP_INT_UART1),
-                    omap_findclk(s, "uart1_ck"),
-                    omap_findclk(s, "uart1_ck"),
-                    s->drq[OMAP_DMA_UART1_TX], s->drq[OMAP_DMA_UART1_RX],
-                    "uart1",
-                    serial_hds[0]);
-    s->uart[1] = omap_uart_init(0xfffb0800,
-                                qdev_get_gpio_in(s->ih[1], OMAP_INT_UART2),
-                    omap_findclk(s, "uart2_ck"),
-                    omap_findclk(s, "uart2_ck"),
-                    s->drq[OMAP_DMA_UART2_TX], s->drq[OMAP_DMA_UART2_RX],
-                    "uart2",
-                    serial_hds[0] ? serial_hds[1] : NULL);
-    s->uart[2] = omap_uart_init(0xfffb9800,
-                                qdev_get_gpio_in(s->ih[0], OMAP_INT_UART3),
-                    omap_findclk(s, "uart3_ck"),
-                    omap_findclk(s, "uart3_ck"),
-                    s->drq[OMAP_DMA_UART3_TX], s->drq[OMAP_DMA_UART3_RX],
-                    "uart3",
-                    serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
-
-    s->dpll[0] = omap_dpll_init(system_memory, 0xfffecf00,
-                                omap_findclk(s, "dpll1"));
-    s->dpll[1] = omap_dpll_init(system_memory, 0xfffed000,
-                                omap_findclk(s, "dpll2"));
-    s->dpll[2] = omap_dpll_init(system_memory, 0xfffed100,
-                                omap_findclk(s, "dpll3"));
-
-    dinfo = drive_get(IF_SD, 0, 0);
-    if (!dinfo) {
-        fprintf(stderr, "qemu: missing SecureDigital device\n");
-        exit(1);
-    }
-    s->mmc = omap_mmc_init(0xfffb7800, system_memory, dinfo->bdrv,
-                           qdev_get_gpio_in(s->ih[1], OMAP_INT_OQN),
-                           &s->drq[OMAP_DMA_MMC_TX],
-                    omap_findclk(s, "mmc_ck"));
-
-    s->mpuio = omap_mpuio_init(system_memory, 0xfffb5000,
-                               qdev_get_gpio_in(s->ih[1], OMAP_INT_KEYBOARD),
-                               qdev_get_gpio_in(s->ih[1], OMAP_INT_MPUIO),
-                               s->wakeup, omap_findclk(s, "clk32-kHz"));
-
-    s->gpio = qdev_create(NULL, "omap-gpio");
-    qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
-    qdev_prop_set_ptr(s->gpio, "clk", omap_findclk(s, "arm_gpio_ck"));
-    qdev_init_nofail(s->gpio);
-    sysbus_connect_irq(SYS_BUS_DEVICE(s->gpio), 0,
-                       qdev_get_gpio_in(s->ih[0], OMAP_INT_GPIO_BANK1));
-    sysbus_mmio_map(SYS_BUS_DEVICE(s->gpio), 0, 0xfffce000);
-
-    s->microwire = omap_uwire_init(system_memory, 0xfffb3000,
-                                   qdev_get_gpio_in(s->ih[1], OMAP_INT_uWireTX),
-                                   qdev_get_gpio_in(s->ih[1], OMAP_INT_uWireRX),
-                    s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
-
-    s->pwl = omap_pwl_init(system_memory, 0xfffb5800,
-                           omap_findclk(s, "armxor_ck"));
-    s->pwt = omap_pwt_init(system_memory, 0xfffb6000,
-                           omap_findclk(s, "armxor_ck"));
-
-    s->i2c[0] = qdev_create(NULL, "omap_i2c");
-    qdev_prop_set_uint8(s->i2c[0], "revision", 0x11);
-    qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "mpuper_ck"));
-    qdev_init_nofail(s->i2c[0]);
-    busdev = SYS_BUS_DEVICE(s->i2c[0]);
-    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C));
-    sysbus_connect_irq(busdev, 1, s->drq[OMAP_DMA_I2C_TX]);
-    sysbus_connect_irq(busdev, 2, s->drq[OMAP_DMA_I2C_RX]);
-    sysbus_mmio_map(busdev, 0, 0xfffb3800);
-
-    s->rtc = omap_rtc_init(system_memory, 0xfffb4800,
-                           qdev_get_gpio_in(s->ih[1], OMAP_INT_RTC_TIMER),
-                           qdev_get_gpio_in(s->ih[1], OMAP_INT_RTC_ALARM),
-                    omap_findclk(s, "clk32-kHz"));
-
-    s->mcbsp1 = omap_mcbsp_init(system_memory, 0xfffb1800,
-                                qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP1TX),
-                                qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP1RX),
-                    &s->drq[OMAP_DMA_MCBSP1_TX], omap_findclk(s, "dspxor_ck"));
-    s->mcbsp2 = omap_mcbsp_init(system_memory, 0xfffb1000,
-                                qdev_get_gpio_in(s->ih[0],
-                                                 OMAP_INT_310_McBSP2_TX),
-                                qdev_get_gpio_in(s->ih[0],
-                                                 OMAP_INT_310_McBSP2_RX),
-                    &s->drq[OMAP_DMA_MCBSP2_TX], omap_findclk(s, "mpuper_ck"));
-    s->mcbsp3 = omap_mcbsp_init(system_memory, 0xfffb7000,
-                                qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP3TX),
-                                qdev_get_gpio_in(s->ih[1], OMAP_INT_McBSP3RX),
-                    &s->drq[OMAP_DMA_MCBSP3_TX], omap_findclk(s, "dspxor_ck"));
-
-    s->led[0] = omap_lpg_init(system_memory,
-                              0xfffbd000, omap_findclk(s, "clk32-kHz"));
-    s->led[1] = omap_lpg_init(system_memory,
-                              0xfffbd800, omap_findclk(s, "clk32-kHz"));
-
-    /* Register mappings not currenlty implemented:
-     * MCSI2 Comm	fffb2000 - fffb27ff (not mapped on OMAP310)
-     * MCSI1 Bluetooth	fffb2800 - fffb2fff (not mapped on OMAP310)
-     * USB W2FC		fffb4000 - fffb47ff
-     * Camera Interface	fffb6800 - fffb6fff
-     * USB Host		fffba000 - fffba7ff
-     * FAC		fffba800 - fffbafff
-     * HDQ/1-Wire	fffbc000 - fffbc7ff
-     * TIPB switches	fffbc800 - fffbcfff
-     * Mailbox		fffcf000 - fffcf7ff
-     * Local bus IF	fffec100 - fffec1ff
-     * Local bus MMU	fffec200 - fffec2ff
-     * DSP MMU		fffed200 - fffed2ff
-     */
-
-    omap_setup_dsp_mapping(system_memory, omap15xx_dsp_mm);
-    omap_setup_mpui_io(system_memory, s);
-
-    qemu_register_reset(omap1_mpu_reset, s);
-
-    return s;
-}
diff --git a/hw/omap2.c b/hw/omap2.c
deleted file mode 100644
index 0a2cd7b..0000000
--- a/hw/omap2.c
+++ /dev/null
@@ -1,2684 +0,0 @@
-/*
- * TI OMAP processors emulation.
- *
- * Copyright (C) 2007-2008 Nokia Corporation
- * Written by Andrzej Zaborowski <andrew at openedhand.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 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 "sysemu/blockdev.h"
-#include "hw/hw.h"
-#include "hw/arm-misc.h"
-#include "hw/omap.h"
-#include "sysemu/sysemu.h"
-#include "qemu/timer.h"
-#include "char/char.h"
-#include "hw/flash.h"
-#include "hw/soc_dma.h"
-#include "hw/sysbus.h"
-#include "audio/audio.h"
-
-/* Enhanced Audio Controller (CODEC only) */
-struct omap_eac_s {
-    qemu_irq irq;
-    MemoryRegion iomem;
-
-    uint16_t sysconfig;
-    uint8_t config[4];
-    uint8_t control;
-    uint8_t address;
-    uint16_t data;
-    uint8_t vtol;
-    uint8_t vtsl;
-    uint16_t mixer;
-    uint16_t gain[4];
-    uint8_t att;
-    uint16_t max[7];
-
-    struct {
-        qemu_irq txdrq;
-        qemu_irq rxdrq;
-        uint32_t (*txrx)(void *opaque, uint32_t, int);
-        void *opaque;
-
-#define EAC_BUF_LEN 1024
-        uint32_t rxbuf[EAC_BUF_LEN];
-        int rxoff;
-        int rxlen;
-        int rxavail;
-        uint32_t txbuf[EAC_BUF_LEN];
-        int txlen;
-        int txavail;
-
-        int enable;
-        int rate;
-
-        uint16_t config[4];
-
-        /* These need to be moved to the actual codec */
-        QEMUSoundCard card;
-        SWVoiceIn *in_voice;
-        SWVoiceOut *out_voice;
-        int hw_enable;
-    } codec;
-
-    struct {
-        uint8_t control;
-        uint16_t config;
-    } modem, bt;
-};
-
-static inline void omap_eac_interrupt_update(struct omap_eac_s *s)
-{
-    qemu_set_irq(s->irq, (s->codec.config[1] >> 14) & 1);	/* AURDI */
-}
-
-static inline void omap_eac_in_dmarequest_update(struct omap_eac_s *s)
-{
-    qemu_set_irq(s->codec.rxdrq, (s->codec.rxavail || s->codec.rxlen) &&
-                    ((s->codec.config[1] >> 12) & 1));		/* DMAREN */
-}
-
-static inline void omap_eac_out_dmarequest_update(struct omap_eac_s *s)
-{
-    qemu_set_irq(s->codec.txdrq, s->codec.txlen < s->codec.txavail &&
-                    ((s->codec.config[1] >> 11) & 1));		/* DMAWEN */
-}
-
-static inline void omap_eac_in_refill(struct omap_eac_s *s)
-{
-    int left = MIN(EAC_BUF_LEN - s->codec.rxlen, s->codec.rxavail) << 2;
-    int start = ((s->codec.rxoff + s->codec.rxlen) & (EAC_BUF_LEN - 1)) << 2;
-    int leftwrap = MIN(left, (EAC_BUF_LEN << 2) - start);
-    int recv = 1;
-    uint8_t *buf = (uint8_t *) s->codec.rxbuf + start;
-
-    left -= leftwrap;
-    start = 0;
-    while (leftwrap && (recv = AUD_read(s->codec.in_voice, buf + start,
-                                    leftwrap)) > 0) {	/* Be defensive */
-        start += recv;
-        leftwrap -= recv;
-    }
-    if (recv <= 0)
-        s->codec.rxavail = 0;
-    else
-        s->codec.rxavail -= start >> 2;
-    s->codec.rxlen += start >> 2;
-
-    if (recv > 0 && left > 0) {
-        start = 0;
-        while (left && (recv = AUD_read(s->codec.in_voice,
-                                        (uint8_t *) s->codec.rxbuf + start,
-                                        left)) > 0) {	/* Be defensive */
-            start += recv;
-            left -= recv;
-        }
-        if (recv <= 0)
-            s->codec.rxavail = 0;
-        else
-            s->codec.rxavail -= start >> 2;
-        s->codec.rxlen += start >> 2;
-    }
-}
-
-static inline void omap_eac_out_empty(struct omap_eac_s *s)
-{
-    int left = s->codec.txlen << 2;
-    int start = 0;
-    int sent = 1;
-
-    while (left && (sent = AUD_write(s->codec.out_voice,
-                                    (uint8_t *) s->codec.txbuf + start,
-                                    left)) > 0) {	/* Be defensive */
-        start += sent;
-        left -= sent;
-    }
-
-    if (!sent) {
-        s->codec.txavail = 0;
-        omap_eac_out_dmarequest_update(s);
-    }
-
-    if (start)
-        s->codec.txlen = 0;
-}
-
-static void omap_eac_in_cb(void *opaque, int avail_b)
-{
-    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
-
-    s->codec.rxavail = avail_b >> 2;
-    omap_eac_in_refill(s);
-    /* TODO: possibly discard current buffer if overrun */
-    omap_eac_in_dmarequest_update(s);
-}
-
-static void omap_eac_out_cb(void *opaque, int free_b)
-{
-    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
-
-    s->codec.txavail = free_b >> 2;
-    if (s->codec.txlen)
-        omap_eac_out_empty(s);
-    else
-        omap_eac_out_dmarequest_update(s);
-}
-
-static void omap_eac_enable_update(struct omap_eac_s *s)
-{
-    s->codec.enable = !(s->codec.config[1] & 1) &&		/* EACPWD */
-            (s->codec.config[1] & 2) &&				/* AUDEN */
-            s->codec.hw_enable;
-}
-
-static const int omap_eac_fsint[4] = {
-    8000,
-    11025,
-    22050,
-    44100,
-};
-
-static const int omap_eac_fsint2[8] = {
-    8000,
-    11025,
-    22050,
-    44100,
-    48000,
-    0, 0, 0,
-};
-
-static const int omap_eac_fsint3[16] = {
-    8000,
-    11025,
-    16000,
-    22050,
-    24000,
-    32000,
-    44100,
-    48000,
-    0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-static void omap_eac_rate_update(struct omap_eac_s *s)
-{
-    int fsint[3];
-
-    fsint[2] = (s->codec.config[3] >> 9) & 0xf;
-    fsint[1] = (s->codec.config[2] >> 0) & 0x7;
-    fsint[0] = (s->codec.config[0] >> 6) & 0x3;
-    if (fsint[2] < 0xf)
-        s->codec.rate = omap_eac_fsint3[fsint[2]];
-    else if (fsint[1] < 0x7)
-        s->codec.rate = omap_eac_fsint2[fsint[1]];
-    else
-        s->codec.rate = omap_eac_fsint[fsint[0]];
-}
-
-static void omap_eac_volume_update(struct omap_eac_s *s)
-{
-    /* TODO */
-}
-
-static void omap_eac_format_update(struct omap_eac_s *s)
-{
-    struct audsettings fmt;
-
-    /* The hardware buffers at most one sample */
-    if (s->codec.rxlen)
-        s->codec.rxlen = 1;
-
-    if (s->codec.in_voice) {
-        AUD_set_active_in(s->codec.in_voice, 0);
-        AUD_close_in(&s->codec.card, s->codec.in_voice);
-        s->codec.in_voice = NULL;
-    }
-    if (s->codec.out_voice) {
-        omap_eac_out_empty(s);
-        AUD_set_active_out(s->codec.out_voice, 0);
-        AUD_close_out(&s->codec.card, s->codec.out_voice);
-        s->codec.out_voice = NULL;
-        s->codec.txavail = 0;
-    }
-    /* Discard what couldn't be written */
-    s->codec.txlen = 0;
-
-    omap_eac_enable_update(s);
-    if (!s->codec.enable)
-        return;
-
-    omap_eac_rate_update(s);
-    fmt.endianness = ((s->codec.config[0] >> 8) & 1);		/* LI_BI */
-    fmt.nchannels = ((s->codec.config[0] >> 10) & 1) ? 2 : 1;	/* MN_ST */
-    fmt.freq = s->codec.rate;
-    /* TODO: signedness possibly depends on the CODEC hardware - or
-     * does I2S specify it?  */
-    /* All register writes are 16 bits so we we store 16-bit samples
-     * in the buffers regardless of AGCFR[B8_16] value.  */
-    fmt.fmt = AUD_FMT_U16;
-
-    s->codec.in_voice = AUD_open_in(&s->codec.card, s->codec.in_voice,
-                    "eac.codec.in", s, omap_eac_in_cb, &fmt);
-    s->codec.out_voice = AUD_open_out(&s->codec.card, s->codec.out_voice,
-                    "eac.codec.out", s, omap_eac_out_cb, &fmt);
-
-    omap_eac_volume_update(s);
-
-    AUD_set_active_in(s->codec.in_voice, 1);
-    AUD_set_active_out(s->codec.out_voice, 1);
-}
-
-static void omap_eac_reset(struct omap_eac_s *s)
-{
-    s->sysconfig = 0;
-    s->config[0] = 0x0c;
-    s->config[1] = 0x09;
-    s->config[2] = 0xab;
-    s->config[3] = 0x03;
-    s->control = 0x00;
-    s->address = 0x00;
-    s->data = 0x0000;
-    s->vtol = 0x00;
-    s->vtsl = 0x00;
-    s->mixer = 0x0000;
-    s->gain[0] = 0xe7e7;
-    s->gain[1] = 0x6767;
-    s->gain[2] = 0x6767;
-    s->gain[3] = 0x6767;
-    s->att = 0xce;
-    s->max[0] = 0;
-    s->max[1] = 0;
-    s->max[2] = 0;
-    s->max[3] = 0;
-    s->max[4] = 0;
-    s->max[5] = 0;
-    s->max[6] = 0;
-
-    s->modem.control = 0x00;
-    s->modem.config = 0x0000;
-    s->bt.control = 0x00;
-    s->bt.config = 0x0000;
-    s->codec.config[0] = 0x0649;
-    s->codec.config[1] = 0x0000;
-    s->codec.config[2] = 0x0007;
-    s->codec.config[3] = 0x1ffc;
-    s->codec.rxoff = 0;
-    s->codec.rxlen = 0;
-    s->codec.txlen = 0;
-    s->codec.rxavail = 0;
-    s->codec.txavail = 0;
-
-    omap_eac_format_update(s);
-    omap_eac_interrupt_update(s);
-}
-
-static uint64_t omap_eac_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
-    uint32_t ret;
-
-    if (size != 2) {
-        return omap_badwidth_read16(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x000:	/* CPCFR1 */
-        return s->config[0];
-    case 0x004:	/* CPCFR2 */
-        return s->config[1];
-    case 0x008:	/* CPCFR3 */
-        return s->config[2];
-    case 0x00c:	/* CPCFR4 */
-        return s->config[3];
-
-    case 0x010:	/* CPTCTL */
-        return s->control | ((s->codec.rxavail + s->codec.rxlen > 0) << 7) |
-                ((s->codec.txlen < s->codec.txavail) << 5);
-
-    case 0x014:	/* CPTTADR */
-        return s->address;
-    case 0x018:	/* CPTDATL */
-        return s->data & 0xff;
-    case 0x01c:	/* CPTDATH */
-        return s->data >> 8;
-    case 0x020:	/* CPTVSLL */
-        return s->vtol;
-    case 0x024:	/* CPTVSLH */
-        return s->vtsl | (3 << 5);	/* CRDY1 | CRDY2 */
-    case 0x040:	/* MPCTR */
-        return s->modem.control;
-    case 0x044:	/* MPMCCFR */
-        return s->modem.config;
-    case 0x060:	/* BPCTR */
-        return s->bt.control;
-    case 0x064:	/* BPMCCFR */
-        return s->bt.config;
-    case 0x080:	/* AMSCFR */
-        return s->mixer;
-    case 0x084:	/* AMVCTR */
-        return s->gain[0];
-    case 0x088:	/* AM1VCTR */
-        return s->gain[1];
-    case 0x08c:	/* AM2VCTR */
-        return s->gain[2];
-    case 0x090:	/* AM3VCTR */
-        return s->gain[3];
-    case 0x094:	/* ASTCTR */
-        return s->att;
-    case 0x098:	/* APD1LCR */
-        return s->max[0];
-    case 0x09c:	/* APD1RCR */
-        return s->max[1];
-    case 0x0a0:	/* APD2LCR */
-        return s->max[2];
-    case 0x0a4:	/* APD2RCR */
-        return s->max[3];
-    case 0x0a8:	/* APD3LCR */
-        return s->max[4];
-    case 0x0ac:	/* APD3RCR */
-        return s->max[5];
-    case 0x0b0:	/* APD4R */
-        return s->max[6];
-    case 0x0b4:	/* ADWR */
-        /* This should be write-only?  Docs list it as read-only.  */
-        return 0x0000;
-    case 0x0b8:	/* ADRDR */
-        if (likely(s->codec.rxlen > 1)) {
-            ret = s->codec.rxbuf[s->codec.rxoff ++];
-            s->codec.rxlen --;
-            s->codec.rxoff &= EAC_BUF_LEN - 1;
-            return ret;
-        } else if (s->codec.rxlen) {
-            ret = s->codec.rxbuf[s->codec.rxoff ++];
-            s->codec.rxlen --;
-            s->codec.rxoff &= EAC_BUF_LEN - 1;
-            if (s->codec.rxavail)
-                omap_eac_in_refill(s);
-            omap_eac_in_dmarequest_update(s);
-            return ret;
-        }
-        return 0x0000;
-    case 0x0bc:	/* AGCFR */
-        return s->codec.config[0];
-    case 0x0c0:	/* AGCTR */
-        return s->codec.config[1] | ((s->codec.config[1] & 2) << 14);
-    case 0x0c4:	/* AGCFR2 */
-        return s->codec.config[2];
-    case 0x0c8:	/* AGCFR3 */
-        return s->codec.config[3];
-    case 0x0cc:	/* MBPDMACTR */
-    case 0x0d0:	/* MPDDMARR */
-    case 0x0d8:	/* MPUDMARR */
-    case 0x0e4:	/* BPDDMARR */
-    case 0x0ec:	/* BPUDMARR */
-        return 0x0000;
-
-    case 0x100:	/* VERSION_NUMBER */
-        return 0x0010;
-
-    case 0x104:	/* SYSCONFIG */
-        return s->sysconfig;
-
-    case 0x108:	/* SYSSTATUS */
-        return 1 | 0xe;					/* RESETDONE | stuff */
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_eac_write(void *opaque, hwaddr addr,
-                           uint64_t value, unsigned size)
-{
-    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
-
-    if (size != 2) {
-        return omap_badwidth_write16(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x098:	/* APD1LCR */
-    case 0x09c:	/* APD1RCR */
-    case 0x0a0:	/* APD2LCR */
-    case 0x0a4:	/* APD2RCR */
-    case 0x0a8:	/* APD3LCR */
-    case 0x0ac:	/* APD3RCR */
-    case 0x0b0:	/* APD4R */
-    case 0x0b8:	/* ADRDR */
-    case 0x0d0:	/* MPDDMARR */
-    case 0x0d8:	/* MPUDMARR */
-    case 0x0e4:	/* BPDDMARR */
-    case 0x0ec:	/* BPUDMARR */
-    case 0x100:	/* VERSION_NUMBER */
-    case 0x108:	/* SYSSTATUS */
-        OMAP_RO_REG(addr);
-        return;
-
-    case 0x000:	/* CPCFR1 */
-        s->config[0] = value & 0xff;
-        omap_eac_format_update(s);
-        break;
-    case 0x004:	/* CPCFR2 */
-        s->config[1] = value & 0xff;
-        omap_eac_format_update(s);
-        break;
-    case 0x008:	/* CPCFR3 */
-        s->config[2] = value & 0xff;
-        omap_eac_format_update(s);
-        break;
-    case 0x00c:	/* CPCFR4 */
-        s->config[3] = value & 0xff;
-        omap_eac_format_update(s);
-        break;
-
-    case 0x010:	/* CPTCTL */
-        /* Assuming TXF and TXE bits are read-only... */
-        s->control = value & 0x5f;
-        omap_eac_interrupt_update(s);
-        break;
-
-    case 0x014:	/* CPTTADR */
-        s->address = value & 0xff;
-        break;
-    case 0x018:	/* CPTDATL */
-        s->data &= 0xff00;
-        s->data |= value & 0xff;
-        break;
-    case 0x01c:	/* CPTDATH */
-        s->data &= 0x00ff;
-        s->data |= value << 8;
-        break;
-    case 0x020:	/* CPTVSLL */
-        s->vtol = value & 0xf8;
-        break;
-    case 0x024:	/* CPTVSLH */
-        s->vtsl = value & 0x9f;
-        break;
-    case 0x040:	/* MPCTR */
-        s->modem.control = value & 0x8f;
-        break;
-    case 0x044:	/* MPMCCFR */
-        s->modem.config = value & 0x7fff;
-        break;
-    case 0x060:	/* BPCTR */
-        s->bt.control = value & 0x8f;
-        break;
-    case 0x064:	/* BPMCCFR */
-        s->bt.config = value & 0x7fff;
-        break;
-    case 0x080:	/* AMSCFR */
-        s->mixer = value & 0x0fff;
-        break;
-    case 0x084:	/* AMVCTR */
-        s->gain[0] = value & 0xffff;
-        break;
-    case 0x088:	/* AM1VCTR */
-        s->gain[1] = value & 0xff7f;
-        break;
-    case 0x08c:	/* AM2VCTR */
-        s->gain[2] = value & 0xff7f;
-        break;
-    case 0x090:	/* AM3VCTR */
-        s->gain[3] = value & 0xff7f;
-        break;
-    case 0x094:	/* ASTCTR */
-        s->att = value & 0xff;
-        break;
-
-    case 0x0b4:	/* ADWR */
-        s->codec.txbuf[s->codec.txlen ++] = value;
-        if (unlikely(s->codec.txlen == EAC_BUF_LEN ||
-                                s->codec.txlen == s->codec.txavail)) {
-            if (s->codec.txavail)
-                omap_eac_out_empty(s);
-            /* Discard what couldn't be written */
-            s->codec.txlen = 0;
-        }
-        break;
-
-    case 0x0bc:	/* AGCFR */
-        s->codec.config[0] = value & 0x07ff;
-        omap_eac_format_update(s);
-        break;
-    case 0x0c0:	/* AGCTR */
-        s->codec.config[1] = value & 0x780f;
-        omap_eac_format_update(s);
-        break;
-    case 0x0c4:	/* AGCFR2 */
-        s->codec.config[2] = value & 0x003f;
-        omap_eac_format_update(s);
-        break;
-    case 0x0c8:	/* AGCFR3 */
-        s->codec.config[3] = value & 0xffff;
-        omap_eac_format_update(s);
-        break;
-    case 0x0cc:	/* MBPDMACTR */
-    case 0x0d4:	/* MPDDMAWR */
-    case 0x0e0:	/* MPUDMAWR */
-    case 0x0e8:	/* BPDDMAWR */
-    case 0x0f0:	/* BPUDMAWR */
-        break;
-
-    case 0x104:	/* SYSCONFIG */
-        if (value & (1 << 1))				/* SOFTRESET */
-            omap_eac_reset(s);
-        s->sysconfig = value & 0x31d;
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_eac_ops = {
-    .read = omap_eac_read,
-    .write = omap_eac_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
-                qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
-{
-    struct omap_eac_s *s = (struct omap_eac_s *)
-            g_malloc0(sizeof(struct omap_eac_s));
-
-    s->irq = irq;
-    s->codec.rxdrq = *drq ++;
-    s->codec.txdrq = *drq;
-    omap_eac_reset(s);
-
-    AUD_register_card("OMAP EAC", &s->codec.card);
-
-    memory_region_init_io(&s->iomem, &omap_eac_ops, s, "omap.eac",
-                          omap_l4_region_size(ta, 0));
-    omap_l4_attach(ta, 0, &s->iomem);
-
-    return s;
-}
-
-/* STI/XTI (emulation interface) console - reverse engineered only */
-struct omap_sti_s {
-    qemu_irq irq;
-    MemoryRegion iomem;
-    MemoryRegion iomem_fifo;
-    CharDriverState *chr;
-
-    uint32_t sysconfig;
-    uint32_t systest;
-    uint32_t irqst;
-    uint32_t irqen;
-    uint32_t clkcontrol;
-    uint32_t serial_config;
-};
-
-#define STI_TRACE_CONSOLE_CHANNEL	239
-#define STI_TRACE_CONTROL_CHANNEL	253
-
-static inline void omap_sti_interrupt_update(struct omap_sti_s *s)
-{
-    qemu_set_irq(s->irq, s->irqst & s->irqen);
-}
-
-static void omap_sti_reset(struct omap_sti_s *s)
-{
-    s->sysconfig = 0;
-    s->irqst = 0;
-    s->irqen = 0;
-    s->clkcontrol = 0;
-    s->serial_config = 0;
-
-    omap_sti_interrupt_update(s);
-}
-
-static uint64_t omap_sti_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    struct omap_sti_s *s = (struct omap_sti_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_read32(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x00:	/* STI_REVISION */
-        return 0x10;
-
-    case 0x10:	/* STI_SYSCONFIG */
-        return s->sysconfig;
-
-    case 0x14:	/* STI_SYSSTATUS / STI_RX_STATUS / XTI_SYSSTATUS */
-        return 0x00;
-
-    case 0x18:	/* STI_IRQSTATUS */
-        return s->irqst;
-
-    case 0x1c:	/* STI_IRQSETEN / STI_IRQCLREN */
-        return s->irqen;
-
-    case 0x24:	/* STI_ER / STI_DR / XTI_TRACESELECT */
-    case 0x28:	/* STI_RX_DR / XTI_RXDATA */
-        /* TODO */
-        return 0;
-
-    case 0x2c:	/* STI_CLK_CTRL / XTI_SCLKCRTL */
-        return s->clkcontrol;
-
-    case 0x30:	/* STI_SERIAL_CFG / XTI_SCONFIG */
-        return s->serial_config;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_sti_write(void *opaque, hwaddr addr,
-                           uint64_t value, unsigned size)
-{
-    struct omap_sti_s *s = (struct omap_sti_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_write32(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x00:	/* STI_REVISION */
-    case 0x14:	/* STI_SYSSTATUS / STI_RX_STATUS / XTI_SYSSTATUS */
-        OMAP_RO_REG(addr);
-        return;
-
-    case 0x10:	/* STI_SYSCONFIG */
-        if (value & (1 << 1))				/* SOFTRESET */
-            omap_sti_reset(s);
-        s->sysconfig = value & 0xfe;
-        break;
-
-    case 0x18:	/* STI_IRQSTATUS */
-        s->irqst &= ~value;
-        omap_sti_interrupt_update(s);
-        break;
-
-    case 0x1c:	/* STI_IRQSETEN / STI_IRQCLREN */
-        s->irqen = value & 0xffff;
-        omap_sti_interrupt_update(s);
-        break;
-
-    case 0x2c:	/* STI_CLK_CTRL / XTI_SCLKCRTL */
-        s->clkcontrol = value & 0xff;
-        break;
-
-    case 0x30:	/* STI_SERIAL_CFG / XTI_SCONFIG */
-        s->serial_config = value & 0xff;
-        break;
-
-    case 0x24:	/* STI_ER / STI_DR / XTI_TRACESELECT */
-    case 0x28:	/* STI_RX_DR / XTI_RXDATA */
-        /* TODO */
-        return;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_sti_ops = {
-    .read = omap_sti_read,
-    .write = omap_sti_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static uint64_t omap_sti_fifo_read(void *opaque, hwaddr addr,
-                                   unsigned size)
-{
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_sti_fifo_write(void *opaque, hwaddr addr,
-                                uint64_t value, unsigned size)
-{
-    struct omap_sti_s *s = (struct omap_sti_s *) opaque;
-    int ch = addr >> 6;
-    uint8_t byte = value;
-
-    if (size != 1) {
-        return omap_badwidth_write8(opaque, addr, size);
-    }
-
-    if (ch == STI_TRACE_CONTROL_CHANNEL) {
-        /* Flush channel <i>value</i>.  */
-        qemu_chr_fe_write(s->chr, (const uint8_t *) "\r", 1);
-    } else if (ch == STI_TRACE_CONSOLE_CHANNEL || 1) {
-        if (value == 0xc0 || value == 0xc3) {
-            /* Open channel <i>ch</i>.  */
-        } else if (value == 0x00)
-            qemu_chr_fe_write(s->chr, (const uint8_t *) "\n", 1);
-        else
-            qemu_chr_fe_write(s->chr, &byte, 1);
-    }
-}
-
-static const MemoryRegionOps omap_sti_fifo_ops = {
-    .read = omap_sti_fifo_read,
-    .write = omap_sti_fifo_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
-                MemoryRegion *sysmem,
-                hwaddr channel_base, qemu_irq irq, omap_clk clk,
-                CharDriverState *chr)
-{
-    struct omap_sti_s *s = (struct omap_sti_s *)
-            g_malloc0(sizeof(struct omap_sti_s));
-
-    s->irq = irq;
-    omap_sti_reset(s);
-
-    s->chr = chr ?: qemu_chr_new("null", "null", NULL);
-
-    memory_region_init_io(&s->iomem, &omap_sti_ops, s, "omap.sti",
-                          omap_l4_region_size(ta, 0));
-    omap_l4_attach(ta, 0, &s->iomem);
-
-    memory_region_init_io(&s->iomem_fifo, &omap_sti_fifo_ops, s,
-                          "omap.sti.fifo", 0x10000);
-    memory_region_add_subregion(sysmem, channel_base, &s->iomem_fifo);
-
-    return s;
-}
-
-/* L4 Interconnect */
-#define L4TA(n)		(n)
-#define L4TAO(n)	((n) + 39)
-
-static const struct omap_l4_region_s omap_l4_region[125] = {
-    [  1] = { 0x40800,  0x800, 32          }, /* Initiator agent */
-    [  2] = { 0x41000, 0x1000, 32          }, /* Link agent */
-    [  0] = { 0x40000,  0x800, 32          }, /* Address and protection */
-    [  3] = { 0x00000, 0x1000, 32 | 16 | 8 }, /* System Control and Pinout */
-    [  4] = { 0x01000, 0x1000, 32 | 16 | 8 }, /* L4TAO1 */
-    [  5] = { 0x04000, 0x1000, 32 | 16     }, /* 32K Timer */
-    [  6] = { 0x05000, 0x1000, 32 | 16 | 8 }, /* L4TAO2 */
-    [  7] = { 0x08000,  0x800, 32          }, /* PRCM Region A */
-    [  8] = { 0x08800,  0x800, 32          }, /* PRCM Region B */
-    [  9] = { 0x09000, 0x1000, 32 | 16 | 8 }, /* L4TAO */
-    [ 10] = { 0x12000, 0x1000, 32 | 16 | 8 }, /* Test (BCM) */
-    [ 11] = { 0x13000, 0x1000, 32 | 16 | 8 }, /* L4TA1 */
-    [ 12] = { 0x14000, 0x1000, 32          }, /* Test/emulation (TAP) */
-    [ 13] = { 0x15000, 0x1000, 32 | 16 | 8 }, /* L4TA2 */
-    [ 14] = { 0x18000, 0x1000, 32 | 16 | 8 }, /* GPIO1 */
-    [ 16] = { 0x1a000, 0x1000, 32 | 16 | 8 }, /* GPIO2 */
-    [ 18] = { 0x1c000, 0x1000, 32 | 16 | 8 }, /* GPIO3 */
-    [ 19] = { 0x1e000, 0x1000, 32 | 16 | 8 }, /* GPIO4 */
-    [ 15] = { 0x19000, 0x1000, 32 | 16 | 8 }, /* Quad GPIO TOP */
-    [ 17] = { 0x1b000, 0x1000, 32 | 16 | 8 }, /* L4TA3 */
-    [ 20] = { 0x20000, 0x1000, 32 | 16 | 8 }, /* WD Timer 1 (Secure) */
-    [ 22] = { 0x22000, 0x1000, 32 | 16 | 8 }, /* WD Timer 2 (OMAP) */
-    [ 21] = { 0x21000, 0x1000, 32 | 16 | 8 }, /* Dual WD timer TOP */
-    [ 23] = { 0x23000, 0x1000, 32 | 16 | 8 }, /* L4TA4 */
-    [ 24] = { 0x28000, 0x1000, 32 | 16 | 8 }, /* GP Timer 1 */
-    [ 25] = { 0x29000, 0x1000, 32 | 16 | 8 }, /* L4TA7 */
-    [ 26] = { 0x48000, 0x2000, 32 | 16 | 8 }, /* Emulation (ARM11ETB) */
-    [ 27] = { 0x4a000, 0x1000, 32 | 16 | 8 }, /* L4TA9 */
-    [ 28] = { 0x50000,  0x400, 32 | 16 | 8 }, /* Display top */
-    [ 29] = { 0x50400,  0x400, 32 | 16 | 8 }, /* Display control */
-    [ 30] = { 0x50800,  0x400, 32 | 16 | 8 }, /* Display RFBI */
-    [ 31] = { 0x50c00,  0x400, 32 | 16 | 8 }, /* Display encoder */
-    [ 32] = { 0x51000, 0x1000, 32 | 16 | 8 }, /* L4TA10 */
-    [ 33] = { 0x52000,  0x400, 32 | 16 | 8 }, /* Camera top */
-    [ 34] = { 0x52400,  0x400, 32 | 16 | 8 }, /* Camera core */
-    [ 35] = { 0x52800,  0x400, 32 | 16 | 8 }, /* Camera DMA */
-    [ 36] = { 0x52c00,  0x400, 32 | 16 | 8 }, /* Camera MMU */
-    [ 37] = { 0x53000, 0x1000, 32 | 16 | 8 }, /* L4TA11 */
-    [ 38] = { 0x56000, 0x1000, 32 | 16 | 8 }, /* sDMA */
-    [ 39] = { 0x57000, 0x1000, 32 | 16 | 8 }, /* L4TA12 */
-    [ 40] = { 0x58000, 0x1000, 32 | 16 | 8 }, /* SSI top */
-    [ 41] = { 0x59000, 0x1000, 32 | 16 | 8 }, /* SSI GDD */
-    [ 42] = { 0x5a000, 0x1000, 32 | 16 | 8 }, /* SSI Port1 */
-    [ 43] = { 0x5b000, 0x1000, 32 | 16 | 8 }, /* SSI Port2 */
-    [ 44] = { 0x5c000, 0x1000, 32 | 16 | 8 }, /* L4TA13 */
-    [ 45] = { 0x5e000, 0x1000, 32 | 16 | 8 }, /* USB OTG */
-    [ 46] = { 0x5f000, 0x1000, 32 | 16 | 8 }, /* L4TAO4 */
-    [ 47] = { 0x60000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER1SDRC) */
-    [ 48] = { 0x61000, 0x1000, 32 | 16 | 8 }, /* L4TA14 */
-    [ 49] = { 0x62000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER2GPMC) */
-    [ 50] = { 0x63000, 0x1000, 32 | 16 | 8 }, /* L4TA15 */
-    [ 51] = { 0x64000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER3OCM) */
-    [ 52] = { 0x65000, 0x1000, 32 | 16 | 8 }, /* L4TA16 */
-    [ 53] = { 0x66000,  0x300, 32 | 16 | 8 }, /* Emulation (WIN_TRACER4L4) */
-    [ 54] = { 0x67000, 0x1000, 32 | 16 | 8 }, /* L4TA17 */
-    [ 55] = { 0x68000, 0x1000, 32 | 16 | 8 }, /* Emulation (XTI) */
-    [ 56] = { 0x69000, 0x1000, 32 | 16 | 8 }, /* L4TA18 */
-    [ 57] = { 0x6a000, 0x1000,      16 | 8 }, /* UART1 */
-    [ 58] = { 0x6b000, 0x1000, 32 | 16 | 8 }, /* L4TA19 */
-    [ 59] = { 0x6c000, 0x1000,      16 | 8 }, /* UART2 */
-    [ 60] = { 0x6d000, 0x1000, 32 | 16 | 8 }, /* L4TA20 */
-    [ 61] = { 0x6e000, 0x1000,      16 | 8 }, /* UART3 */
-    [ 62] = { 0x6f000, 0x1000, 32 | 16 | 8 }, /* L4TA21 */
-    [ 63] = { 0x70000, 0x1000,      16     }, /* I2C1 */
-    [ 64] = { 0x71000, 0x1000, 32 | 16 | 8 }, /* L4TAO5 */
-    [ 65] = { 0x72000, 0x1000,      16     }, /* I2C2 */
-    [ 66] = { 0x73000, 0x1000, 32 | 16 | 8 }, /* L4TAO6 */
-    [ 67] = { 0x74000, 0x1000,      16     }, /* McBSP1 */
-    [ 68] = { 0x75000, 0x1000, 32 | 16 | 8 }, /* L4TAO7 */
-    [ 69] = { 0x76000, 0x1000,      16     }, /* McBSP2 */
-    [ 70] = { 0x77000, 0x1000, 32 | 16 | 8 }, /* L4TAO8 */
-    [ 71] = { 0x24000, 0x1000, 32 | 16 | 8 }, /* WD Timer 3 (DSP) */
-    [ 72] = { 0x25000, 0x1000, 32 | 16 | 8 }, /* L4TA5 */
-    [ 73] = { 0x26000, 0x1000, 32 | 16 | 8 }, /* WD Timer 4 (IVA) */
-    [ 74] = { 0x27000, 0x1000, 32 | 16 | 8 }, /* L4TA6 */
-    [ 75] = { 0x2a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 2 */
-    [ 76] = { 0x2b000, 0x1000, 32 | 16 | 8 }, /* L4TA8 */
-    [ 77] = { 0x78000, 0x1000, 32 | 16 | 8 }, /* GP Timer 3 */
-    [ 78] = { 0x79000, 0x1000, 32 | 16 | 8 }, /* L4TA22 */
-    [ 79] = { 0x7a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 4 */
-    [ 80] = { 0x7b000, 0x1000, 32 | 16 | 8 }, /* L4TA23 */
-    [ 81] = { 0x7c000, 0x1000, 32 | 16 | 8 }, /* GP Timer 5 */
-    [ 82] = { 0x7d000, 0x1000, 32 | 16 | 8 }, /* L4TA24 */
-    [ 83] = { 0x7e000, 0x1000, 32 | 16 | 8 }, /* GP Timer 6 */
-    [ 84] = { 0x7f000, 0x1000, 32 | 16 | 8 }, /* L4TA25 */
-    [ 85] = { 0x80000, 0x1000, 32 | 16 | 8 }, /* GP Timer 7 */
-    [ 86] = { 0x81000, 0x1000, 32 | 16 | 8 }, /* L4TA26 */
-    [ 87] = { 0x82000, 0x1000, 32 | 16 | 8 }, /* GP Timer 8 */
-    [ 88] = { 0x83000, 0x1000, 32 | 16 | 8 }, /* L4TA27 */
-    [ 89] = { 0x84000, 0x1000, 32 | 16 | 8 }, /* GP Timer 9 */
-    [ 90] = { 0x85000, 0x1000, 32 | 16 | 8 }, /* L4TA28 */
-    [ 91] = { 0x86000, 0x1000, 32 | 16 | 8 }, /* GP Timer 10 */
-    [ 92] = { 0x87000, 0x1000, 32 | 16 | 8 }, /* L4TA29 */
-    [ 93] = { 0x88000, 0x1000, 32 | 16 | 8 }, /* GP Timer 11 */
-    [ 94] = { 0x89000, 0x1000, 32 | 16 | 8 }, /* L4TA30 */
-    [ 95] = { 0x8a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 12 */
-    [ 96] = { 0x8b000, 0x1000, 32 | 16 | 8 }, /* L4TA31 */
-    [ 97] = { 0x90000, 0x1000,      16     }, /* EAC */
-    [ 98] = { 0x91000, 0x1000, 32 | 16 | 8 }, /* L4TA32 */
-    [ 99] = { 0x92000, 0x1000,      16     }, /* FAC */
-    [100] = { 0x93000, 0x1000, 32 | 16 | 8 }, /* L4TA33 */
-    [101] = { 0x94000, 0x1000, 32 | 16 | 8 }, /* IPC (MAILBOX) */
-    [102] = { 0x95000, 0x1000, 32 | 16 | 8 }, /* L4TA34 */
-    [103] = { 0x98000, 0x1000, 32 | 16 | 8 }, /* SPI1 */
-    [104] = { 0x99000, 0x1000, 32 | 16 | 8 }, /* L4TA35 */
-    [105] = { 0x9a000, 0x1000, 32 | 16 | 8 }, /* SPI2 */
-    [106] = { 0x9b000, 0x1000, 32 | 16 | 8 }, /* L4TA36 */
-    [107] = { 0x9c000, 0x1000,      16 | 8 }, /* MMC SDIO */
-    [108] = { 0x9d000, 0x1000, 32 | 16 | 8 }, /* L4TAO9 */
-    [109] = { 0x9e000, 0x1000, 32 | 16 | 8 }, /* MS_PRO */
-    [110] = { 0x9f000, 0x1000, 32 | 16 | 8 }, /* L4TAO10 */
-    [111] = { 0xa0000, 0x1000, 32          }, /* RNG */
-    [112] = { 0xa1000, 0x1000, 32 | 16 | 8 }, /* L4TAO11 */
-    [113] = { 0xa2000, 0x1000, 32          }, /* DES3DES */
-    [114] = { 0xa3000, 0x1000, 32 | 16 | 8 }, /* L4TAO12 */
-    [115] = { 0xa4000, 0x1000, 32          }, /* SHA1MD5 */
-    [116] = { 0xa5000, 0x1000, 32 | 16 | 8 }, /* L4TAO13 */
-    [117] = { 0xa6000, 0x1000, 32          }, /* AES */
-    [118] = { 0xa7000, 0x1000, 32 | 16 | 8 }, /* L4TA37 */
-    [119] = { 0xa8000, 0x2000, 32          }, /* PKA */
-    [120] = { 0xaa000, 0x1000, 32 | 16 | 8 }, /* L4TA38 */
-    [121] = { 0xb0000, 0x1000, 32          }, /* MG */
-    [122] = { 0xb1000, 0x1000, 32 | 16 | 8 },
-    [123] = { 0xb2000, 0x1000, 32          }, /* HDQ/1-Wire */
-    [124] = { 0xb3000, 0x1000, 32 | 16 | 8 }, /* L4TA39 */
-};
-
-static const struct omap_l4_agent_info_s omap_l4_agent_info[54] = {
-    { 0,           0, 3, 2 }, /* L4IA initiatior agent */
-    { L4TAO(1),    3, 2, 1 }, /* Control and pinout module */
-    { L4TAO(2),    5, 2, 1 }, /* 32K timer */
-    { L4TAO(3),    7, 3, 2 }, /* PRCM */
-    { L4TA(1),    10, 2, 1 }, /* BCM */
-    { L4TA(2),    12, 2, 1 }, /* Test JTAG */
-    { L4TA(3),    14, 6, 3 }, /* Quad GPIO */
-    { L4TA(4),    20, 4, 3 }, /* WD timer 1/2 */
-    { L4TA(7),    24, 2, 1 }, /* GP timer 1 */
-    { L4TA(9),    26, 2, 1 }, /* ATM11 ETB */
-    { L4TA(10),   28, 5, 4 }, /* Display subsystem */
-    { L4TA(11),   33, 5, 4 }, /* Camera subsystem */
-    { L4TA(12),   38, 2, 1 }, /* sDMA */
-    { L4TA(13),   40, 5, 4 }, /* SSI */
-    { L4TAO(4),   45, 2, 1 }, /* USB */
-    { L4TA(14),   47, 2, 1 }, /* Win Tracer1 */
-    { L4TA(15),   49, 2, 1 }, /* Win Tracer2 */
-    { L4TA(16),   51, 2, 1 }, /* Win Tracer3 */
-    { L4TA(17),   53, 2, 1 }, /* Win Tracer4 */
-    { L4TA(18),   55, 2, 1 }, /* XTI */
-    { L4TA(19),   57, 2, 1 }, /* UART1 */
-    { L4TA(20),   59, 2, 1 }, /* UART2 */
-    { L4TA(21),   61, 2, 1 }, /* UART3 */
-    { L4TAO(5),   63, 2, 1 }, /* I2C1 */
-    { L4TAO(6),   65, 2, 1 }, /* I2C2 */
-    { L4TAO(7),   67, 2, 1 }, /* McBSP1 */
-    { L4TAO(8),   69, 2, 1 }, /* McBSP2 */
-    { L4TA(5),    71, 2, 1 }, /* WD Timer 3 (DSP) */
-    { L4TA(6),    73, 2, 1 }, /* WD Timer 4 (IVA) */
-    { L4TA(8),    75, 2, 1 }, /* GP Timer 2 */
-    { L4TA(22),   77, 2, 1 }, /* GP Timer 3 */
-    { L4TA(23),   79, 2, 1 }, /* GP Timer 4 */
-    { L4TA(24),   81, 2, 1 }, /* GP Timer 5 */
-    { L4TA(25),   83, 2, 1 }, /* GP Timer 6 */
-    { L4TA(26),   85, 2, 1 }, /* GP Timer 7 */
-    { L4TA(27),   87, 2, 1 }, /* GP Timer 8 */
-    { L4TA(28),   89, 2, 1 }, /* GP Timer 9 */
-    { L4TA(29),   91, 2, 1 }, /* GP Timer 10 */
-    { L4TA(30),   93, 2, 1 }, /* GP Timer 11 */
-    { L4TA(31),   95, 2, 1 }, /* GP Timer 12 */
-    { L4TA(32),   97, 2, 1 }, /* EAC */
-    { L4TA(33),   99, 2, 1 }, /* FAC */
-    { L4TA(34),  101, 2, 1 }, /* IPC */
-    { L4TA(35),  103, 2, 1 }, /* SPI1 */
-    { L4TA(36),  105, 2, 1 }, /* SPI2 */
-    { L4TAO(9),  107, 2, 1 }, /* MMC SDIO */
-    { L4TAO(10), 109, 2, 1 },
-    { L4TAO(11), 111, 2, 1 }, /* RNG */
-    { L4TAO(12), 113, 2, 1 }, /* DES3DES */
-    { L4TAO(13), 115, 2, 1 }, /* SHA1MD5 */
-    { L4TA(37),  117, 2, 1 }, /* AES */
-    { L4TA(38),  119, 2, 1 }, /* PKA */
-    { -1,        121, 2, 1 },
-    { L4TA(39),  123, 2, 1 }, /* HDQ/1-Wire */
-};
-
-#define omap_l4ta(bus, cs)	\
-    omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TA(cs))
-#define omap_l4tao(bus, cs)	\
-    omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TAO(cs))
-
-/* Power, Reset, and Clock Management */
-struct omap_prcm_s {
-    qemu_irq irq[3];
-    struct omap_mpu_state_s *mpu;
-    MemoryRegion iomem0;
-    MemoryRegion iomem1;
-
-    uint32_t irqst[3];
-    uint32_t irqen[3];
-
-    uint32_t sysconfig;
-    uint32_t voltctrl;
-    uint32_t scratch[20];
-
-    uint32_t clksrc[1];
-    uint32_t clkout[1];
-    uint32_t clkemul[1];
-    uint32_t clkpol[1];
-    uint32_t clksel[8];
-    uint32_t clken[12];
-    uint32_t clkctrl[4];
-    uint32_t clkidle[7];
-    uint32_t setuptime[2];
-
-    uint32_t wkup[3];
-    uint32_t wken[3];
-    uint32_t wkst[3];
-    uint32_t rst[4];
-    uint32_t rstctrl[1];
-    uint32_t power[4];
-    uint32_t rsttime_wkup;
-
-    uint32_t ev;
-    uint32_t evtime[2];
-
-    int dpll_lock, apll_lock[2];
-};
-
-static void omap_prcm_int_update(struct omap_prcm_s *s, int dom)
-{
-    qemu_set_irq(s->irq[dom], s->irqst[dom] & s->irqen[dom]);
-    /* XXX or is the mask applied before PRCM_IRQSTATUS_* ? */
-}
-
-static uint64_t omap_prcm_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
-    uint32_t ret;
-
-    if (size != 4) {
-        return omap_badwidth_read32(opaque, addr);
-    }
-
-    switch (addr) {
-    case 0x000:	/* PRCM_REVISION */
-        return 0x10;
-
-    case 0x010:	/* PRCM_SYSCONFIG */
-        return s->sysconfig;
-
-    case 0x018:	/* PRCM_IRQSTATUS_MPU */
-        return s->irqst[0];
-
-    case 0x01c:	/* PRCM_IRQENABLE_MPU */
-        return s->irqen[0];
-
-    case 0x050:	/* PRCM_VOLTCTRL */
-        return s->voltctrl;
-    case 0x054:	/* PRCM_VOLTST */
-        return s->voltctrl & 3;
-
-    case 0x060:	/* PRCM_CLKSRC_CTRL */
-        return s->clksrc[0];
-    case 0x070:	/* PRCM_CLKOUT_CTRL */
-        return s->clkout[0];
-    case 0x078:	/* PRCM_CLKEMUL_CTRL */
-        return s->clkemul[0];
-    case 0x080:	/* PRCM_CLKCFG_CTRL */
-    case 0x084:	/* PRCM_CLKCFG_STATUS */
-        return 0;
-
-    case 0x090:	/* PRCM_VOLTSETUP */
-        return s->setuptime[0];
-
-    case 0x094:	/* PRCM_CLKSSETUP */
-        return s->setuptime[1];
-
-    case 0x098:	/* PRCM_POLCTRL */
-        return s->clkpol[0];
-
-    case 0x0b0:	/* GENERAL_PURPOSE1 */
-    case 0x0b4:	/* GENERAL_PURPOSE2 */
-    case 0x0b8:	/* GENERAL_PURPOSE3 */
-    case 0x0bc:	/* GENERAL_PURPOSE4 */
-    case 0x0c0:	/* GENERAL_PURPOSE5 */
-    case 0x0c4:	/* GENERAL_PURPOSE6 */
-    case 0x0c8:	/* GENERAL_PURPOSE7 */
-    case 0x0cc:	/* GENERAL_PURPOSE8 */
-    case 0x0d0:	/* GENERAL_PURPOSE9 */
-    case 0x0d4:	/* GENERAL_PURPOSE10 */
-    case 0x0d8:	/* GENERAL_PURPOSE11 */
-    case 0x0dc:	/* GENERAL_PURPOSE12 */
-    case 0x0e0:	/* GENERAL_PURPOSE13 */
-    case 0x0e4:	/* GENERAL_PURPOSE14 */
-    case 0x0e8:	/* GENERAL_PURPOSE15 */
-    case 0x0ec:	/* GENERAL_PURPOSE16 */
-    case 0x0f0:	/* GENERAL_PURPOSE17 */
-    case 0x0f4:	/* GENERAL_PURPOSE18 */
-    case 0x0f8:	/* GENERAL_PURPOSE19 */
-    case 0x0fc:	/* GENERAL_PURPOSE20 */
-        return s->scratch[(addr - 0xb0) >> 2];
-
-    case 0x140:	/* CM_CLKSEL_MPU */
-        return s->clksel[0];
-    case 0x148:	/* CM_CLKSTCTRL_MPU */
-        return s->clkctrl[0];
-
-    case 0x158:	/* RM_RSTST_MPU */
-        return s->rst[0];
-    case 0x1c8:	/* PM_WKDEP_MPU */
-        return s->wkup[0];
-    case 0x1d4:	/* PM_EVGENCTRL_MPU */
-        return s->ev;
-    case 0x1d8:	/* PM_EVEGENONTIM_MPU */
-        return s->evtime[0];
-    case 0x1dc:	/* PM_EVEGENOFFTIM_MPU */
-        return s->evtime[1];
-    case 0x1e0:	/* PM_PWSTCTRL_MPU */
-        return s->power[0];
-    case 0x1e4:	/* PM_PWSTST_MPU */
-        return 0;
-
-    case 0x200:	/* CM_FCLKEN1_CORE */
-        return s->clken[0];
-    case 0x204:	/* CM_FCLKEN2_CORE */
-        return s->clken[1];
-    case 0x210:	/* CM_ICLKEN1_CORE */
-        return s->clken[2];
-    case 0x214:	/* CM_ICLKEN2_CORE */
-        return s->clken[3];
-    case 0x21c:	/* CM_ICLKEN4_CORE */
-        return s->clken[4];
-
-    case 0x220:	/* CM_IDLEST1_CORE */
-        /* TODO: check the actual iclk status */
-        return 0x7ffffff9;
-    case 0x224:	/* CM_IDLEST2_CORE */
-        /* TODO: check the actual iclk status */
-        return 0x00000007;
-    case 0x22c:	/* CM_IDLEST4_CORE */
-        /* TODO: check the actual iclk status */
-        return 0x0000001f;
-
-    case 0x230:	/* CM_AUTOIDLE1_CORE */
-        return s->clkidle[0];
-    case 0x234:	/* CM_AUTOIDLE2_CORE */
-        return s->clkidle[1];
-    case 0x238:	/* CM_AUTOIDLE3_CORE */
-        return s->clkidle[2];
-    case 0x23c:	/* CM_AUTOIDLE4_CORE */
-        return s->clkidle[3];
-
-    case 0x240:	/* CM_CLKSEL1_CORE */
-        return s->clksel[1];
-    case 0x244:	/* CM_CLKSEL2_CORE */
-        return s->clksel[2];
-
-    case 0x248:	/* CM_CLKSTCTRL_CORE */
-        return s->clkctrl[1];
-
-    case 0x2a0:	/* PM_WKEN1_CORE */
-        return s->wken[0];
-    case 0x2a4:	/* PM_WKEN2_CORE */
-        return s->wken[1];
-
-    case 0x2b0:	/* PM_WKST1_CORE */
-        return s->wkst[0];
-    case 0x2b4:	/* PM_WKST2_CORE */
-        return s->wkst[1];
-    case 0x2c8:	/* PM_WKDEP_CORE */
-        return 0x1e;
-
-    case 0x2e0:	/* PM_PWSTCTRL_CORE */
-        return s->power[1];
-    case 0x2e4:	/* PM_PWSTST_CORE */
-        return 0x000030 | (s->power[1] & 0xfc00);
-
-    case 0x300:	/* CM_FCLKEN_GFX */
-        return s->clken[5];
-    case 0x310:	/* CM_ICLKEN_GFX */
-        return s->clken[6];
-    case 0x320:	/* CM_IDLEST_GFX */
-        /* TODO: check the actual iclk status */
-        return 0x00000001;
-    case 0x340:	/* CM_CLKSEL_GFX */
-        return s->clksel[3];
-    case 0x348:	/* CM_CLKSTCTRL_GFX */
-        return s->clkctrl[2];
-    case 0x350:	/* RM_RSTCTRL_GFX */
-        return s->rstctrl[0];
-    case 0x358:	/* RM_RSTST_GFX */
-        return s->rst[1];
-    case 0x3c8:	/* PM_WKDEP_GFX */
-        return s->wkup[1];
-
-    case 0x3e0:	/* PM_PWSTCTRL_GFX */
-        return s->power[2];
-    case 0x3e4:	/* PM_PWSTST_GFX */
-        return s->power[2] & 3;
-
-    case 0x400:	/* CM_FCLKEN_WKUP */
-        return s->clken[7];
-    case 0x410:	/* CM_ICLKEN_WKUP */
-        return s->clken[8];
-    case 0x420:	/* CM_IDLEST_WKUP */
-        /* TODO: check the actual iclk status */
-        return 0x0000003f;
-    case 0x430:	/* CM_AUTOIDLE_WKUP */
-        return s->clkidle[4];
-    case 0x440:	/* CM_CLKSEL_WKUP */
-        return s->clksel[4];
-    case 0x450:	/* RM_RSTCTRL_WKUP */
-        return 0;
-    case 0x454:	/* RM_RSTTIME_WKUP */
-        return s->rsttime_wkup;
-    case 0x458:	/* RM_RSTST_WKUP */
-        return s->rst[2];
-    case 0x4a0:	/* PM_WKEN_WKUP */
-        return s->wken[2];
-    case 0x4b0:	/* PM_WKST_WKUP */
-        return s->wkst[2];
-
-    case 0x500:	/* CM_CLKEN_PLL */
-        return s->clken[9];
-    case 0x520:	/* CM_IDLEST_CKGEN */
-        ret = 0x0000070 | (s->apll_lock[0] << 9) | (s->apll_lock[1] << 8);
-        if (!(s->clksel[6] & 3))
-            /* Core uses 32-kHz clock */
-            ret |= 3 << 0;
-        else if (!s->dpll_lock)
-            /* DPLL not locked, core uses ref_clk */
-            ret |= 1 << 0;
-        else
-            /* Core uses DPLL */
-            ret |= 2 << 0;
-        return ret;
-    case 0x530:	/* CM_AUTOIDLE_PLL */
-        return s->clkidle[5];
-    case 0x540:	/* CM_CLKSEL1_PLL */
-        return s->clksel[5];
-    case 0x544:	/* CM_CLKSEL2_PLL */
-        return s->clksel[6];
-
-    case 0x800:	/* CM_FCLKEN_DSP */
-        return s->clken[10];
-    case 0x810:	/* CM_ICLKEN_DSP */
-        return s->clken[11];
-    case 0x820:	/* CM_IDLEST_DSP */
-        /* TODO: check the actual iclk status */
-        return 0x00000103;
-    case 0x830:	/* CM_AUTOIDLE_DSP */
-        return s->clkidle[6];
-    case 0x840:	/* CM_CLKSEL_DSP */
-        return s->clksel[7];
-    case 0x848:	/* CM_CLKSTCTRL_DSP */
-        return s->clkctrl[3];
-    case 0x850:	/* RM_RSTCTRL_DSP */
-        return 0;
-    case 0x858:	/* RM_RSTST_DSP */
-        return s->rst[3];
-    case 0x8c8:	/* PM_WKDEP_DSP */
-        return s->wkup[2];
-    case 0x8e0:	/* PM_PWSTCTRL_DSP */
-        return s->power[3];
-    case 0x8e4:	/* PM_PWSTST_DSP */
-        return 0x008030 | (s->power[3] & 0x3003);
-
-    case 0x8f0:	/* PRCM_IRQSTATUS_DSP */
-        return s->irqst[1];
-    case 0x8f4:	/* PRCM_IRQENABLE_DSP */
-        return s->irqen[1];
-
-    case 0x8f8:	/* PRCM_IRQSTATUS_IVA */
-        return s->irqst[2];
-    case 0x8fc:	/* PRCM_IRQENABLE_IVA */
-        return s->irqen[2];
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_prcm_apll_update(struct omap_prcm_s *s)
-{
-    int mode[2];
-
-    mode[0] = (s->clken[9] >> 6) & 3;
-    s->apll_lock[0] = (mode[0] == 3);
-    mode[1] = (s->clken[9] >> 2) & 3;
-    s->apll_lock[1] = (mode[1] == 3);
-    /* TODO: update clocks */
-
-    if (mode[0] == 1 || mode[0] == 2 || mode[1] == 1 || mode[1] == 2)
-        fprintf(stderr, "%s: bad EN_54M_PLL or bad EN_96M_PLL\n",
-                        __FUNCTION__);
-}
-
-static void omap_prcm_dpll_update(struct omap_prcm_s *s)
-{
-    omap_clk dpll = omap_findclk(s->mpu, "dpll");
-    omap_clk dpll_x2 = omap_findclk(s->mpu, "dpll");
-    omap_clk core = omap_findclk(s->mpu, "core_clk");
-    int mode = (s->clken[9] >> 0) & 3;
-    int mult, div;
-
-    mult = (s->clksel[5] >> 12) & 0x3ff;
-    div = (s->clksel[5] >> 8) & 0xf;
-    if (mult == 0 || mult == 1)
-        mode = 1;	/* Bypass */
-
-    s->dpll_lock = 0;
-    switch (mode) {
-    case 0:
-        fprintf(stderr, "%s: bad EN_DPLL\n", __FUNCTION__);
-        break;
-    case 1:	/* Low-power bypass mode (Default) */
-    case 2:	/* Fast-relock bypass mode */
-        omap_clk_setrate(dpll, 1, 1);
-        omap_clk_setrate(dpll_x2, 1, 1);
-        break;
-    case 3:	/* Lock mode */
-        s->dpll_lock = 1; /* After 20 FINT cycles (ref_clk / (div + 1)).  */
-
-        omap_clk_setrate(dpll, div + 1, mult);
-        omap_clk_setrate(dpll_x2, div + 1, mult * 2);
-        break;
-    }
-
-    switch ((s->clksel[6] >> 0) & 3) {
-    case 0:
-        omap_clk_reparent(core, omap_findclk(s->mpu, "clk32-kHz"));
-        break;
-    case 1:
-        omap_clk_reparent(core, dpll);
-        break;
-    case 2:
-        /* Default */
-        omap_clk_reparent(core, dpll_x2);
-        break;
-    case 3:
-        fprintf(stderr, "%s: bad CORE_CLK_SRC\n", __FUNCTION__);
-        break;
-    }
-}
-
-static void omap_prcm_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
-
-    if (size != 4) {
-        return omap_badwidth_write32(opaque, addr, value);
-    }
-
-    switch (addr) {
-    case 0x000:	/* PRCM_REVISION */
-    case 0x054:	/* PRCM_VOLTST */
-    case 0x084:	/* PRCM_CLKCFG_STATUS */
-    case 0x1e4:	/* PM_PWSTST_MPU */
-    case 0x220:	/* CM_IDLEST1_CORE */
-    case 0x224:	/* CM_IDLEST2_CORE */
-    case 0x22c:	/* CM_IDLEST4_CORE */
-    case 0x2c8:	/* PM_WKDEP_CORE */
-    case 0x2e4:	/* PM_PWSTST_CORE */
-    case 0x320:	/* CM_IDLEST_GFX */
-    case 0x3e4:	/* PM_PWSTST_GFX */
-    case 0x420:	/* CM_IDLEST_WKUP */
-    case 0x520:	/* CM_IDLEST_CKGEN */
-    case 0x820:	/* CM_IDLEST_DSP */
-    case 0x8e4:	/* PM_PWSTST_DSP */
-        OMAP_RO_REG(addr);
-        return;
-
-    case 0x010:	/* PRCM_SYSCONFIG */
-        s->sysconfig = value & 1;
-        break;
-
-    case 0x018:	/* PRCM_IRQSTATUS_MPU */
-        s->irqst[0] &= ~value;
-        omap_prcm_int_update(s, 0);
-        break;
-    case 0x01c:	/* PRCM_IRQENABLE_MPU */
-        s->irqen[0] = value & 0x3f;
-        omap_prcm_int_update(s, 0);
-        break;
-
-    case 0x050:	/* PRCM_VOLTCTRL */
-        s->voltctrl = value & 0xf1c3;
-        break;
-
-    case 0x060:	/* PRCM_CLKSRC_CTRL */
-        s->clksrc[0] = value & 0xdb;
-        /* TODO update clocks */
-        break;
-
-    case 0x070:	/* PRCM_CLKOUT_CTRL */
-        s->clkout[0] = value & 0xbbbb;
-        /* TODO update clocks */
-        break;
-
-    case 0x078:	/* PRCM_CLKEMUL_CTRL */
-        s->clkemul[0] = value & 1;
-        /* TODO update clocks */
-        break;
-
-    case 0x080:	/* PRCM_CLKCFG_CTRL */
-        break;
-
-    case 0x090:	/* PRCM_VOLTSETUP */
-        s->setuptime[0] = value & 0xffff;
-        break;
-    case 0x094:	/* PRCM_CLKSSETUP */
-        s->setuptime[1] = value & 0xffff;
-        break;
-
-    case 0x098:	/* PRCM_POLCTRL */
-        s->clkpol[0] = value & 0x701;
-        break;
-
-    case 0x0b0:	/* GENERAL_PURPOSE1 */
-    case 0x0b4:	/* GENERAL_PURPOSE2 */
-    case 0x0b8:	/* GENERAL_PURPOSE3 */
-    case 0x0bc:	/* GENERAL_PURPOSE4 */
-    case 0x0c0:	/* GENERAL_PURPOSE5 */
-    case 0x0c4:	/* GENERAL_PURPOSE6 */
-    case 0x0c8:	/* GENERAL_PURPOSE7 */
-    case 0x0cc:	/* GENERAL_PURPOSE8 */
-    case 0x0d0:	/* GENERAL_PURPOSE9 */
-    case 0x0d4:	/* GENERAL_PURPOSE10 */
-    case 0x0d8:	/* GENERAL_PURPOSE11 */
-    case 0x0dc:	/* GENERAL_PURPOSE12 */
-    case 0x0e0:	/* GENERAL_PURPOSE13 */
-    case 0x0e4:	/* GENERAL_PURPOSE14 */
-    case 0x0e8:	/* GENERAL_PURPOSE15 */
-    case 0x0ec:	/* GENERAL_PURPOSE16 */
-    case 0x0f0:	/* GENERAL_PURPOSE17 */
-    case 0x0f4:	/* GENERAL_PURPOSE18 */
-    case 0x0f8:	/* GENERAL_PURPOSE19 */
-    case 0x0fc:	/* GENERAL_PURPOSE20 */
-        s->scratch[(addr - 0xb0) >> 2] = value;
-        break;
-
-    case 0x140:	/* CM_CLKSEL_MPU */
-        s->clksel[0] = value & 0x1f;
-        /* TODO update clocks */
-        break;
-    case 0x148:	/* CM_CLKSTCTRL_MPU */
-        s->clkctrl[0] = value & 0x1f;
-        break;
-
-    case 0x158:	/* RM_RSTST_MPU */
-        s->rst[0] &= ~value;
-        break;
-    case 0x1c8:	/* PM_WKDEP_MPU */
-        s->wkup[0] = value & 0x15;
-        break;
-
-    case 0x1d4:	/* PM_EVGENCTRL_MPU */
-        s->ev = value & 0x1f;
-        break;
-    case 0x1d8:	/* PM_EVEGENONTIM_MPU */
-        s->evtime[0] = value;
-        break;
-    case 0x1dc:	/* PM_EVEGENOFFTIM_MPU */
-        s->evtime[1] = value;
-        break;
-
-    case 0x1e0:	/* PM_PWSTCTRL_MPU */
-        s->power[0] = value & 0xc0f;
-        break;
-
-    case 0x200:	/* CM_FCLKEN1_CORE */
-        s->clken[0] = value & 0xbfffffff;
-        /* TODO update clocks */
-        /* The EN_EAC bit only gets/puts func_96m_clk.  */
-        break;
-    case 0x204:	/* CM_FCLKEN2_CORE */
-        s->clken[1] = value & 0x00000007;
-        /* TODO update clocks */
-        break;
-    case 0x210:	/* CM_ICLKEN1_CORE */
-        s->clken[2] = value & 0xfffffff9;
-        /* TODO update clocks */
-        /* The EN_EAC bit only gets/puts core_l4_iclk.  */
-        break;
-    case 0x214:	/* CM_ICLKEN2_CORE */
-        s->clken[3] = value & 0x00000007;
-        /* TODO update clocks */
-        break;
-    case 0x21c:	/* CM_ICLKEN4_CORE */
-        s->clken[4] = value & 0x0000001f;
-        /* TODO update clocks */
-        break;
-
-    case 0x230:	/* CM_AUTOIDLE1_CORE */
-        s->clkidle[0] = value & 0xfffffff9;
-        /* TODO update clocks */
-        break;
-    case 0x234:	/* CM_AUTOIDLE2_CORE */
-        s->clkidle[1] = value & 0x00000007;
-        /* TODO update clocks */
-        break;
-    case 0x238:	/* CM_AUTOIDLE3_CORE */
-        s->clkidle[2] = value & 0x00000007;
-        /* TODO update clocks */
-        break;
-    case 0x23c:	/* CM_AUTOIDLE4_CORE */
-        s->clkidle[3] = value & 0x0000001f;
-        /* TODO update clocks */
-        break;
-
-    case 0x240:	/* CM_CLKSEL1_CORE */
-        s->clksel[1] = value & 0x0fffbf7f;
-        /* TODO update clocks */
-        break;
-
-    case 0x244:	/* CM_CLKSEL2_CORE */
-        s->clksel[2] = value & 0x00fffffc;
-        /* TODO update clocks */
-        break;
-
-    case 0x248:	/* CM_CLKSTCTRL_CORE */
-        s->clkctrl[1] = value & 0x7;
-        break;
-
-    case 0x2a0:	/* PM_WKEN1_CORE */
-        s->wken[0] = value & 0x04667ff8;
-        break;
-    case 0x2a4:	/* PM_WKEN2_CORE */
-        s->wken[1] = value & 0x00000005;
-        break;
-
-    case 0x2b0:	/* PM_WKST1_CORE */
-        s->wkst[0] &= ~value;
-        break;
-    case 0x2b4:	/* PM_WKST2_CORE */
-        s->wkst[1] &= ~value;
-        break;
-
-    case 0x2e0:	/* PM_PWSTCTRL_CORE */
-        s->power[1] = (value & 0x00fc3f) | (1 << 2);
-        break;
-
-    case 0x300:	/* CM_FCLKEN_GFX */
-        s->clken[5] = value & 6;
-        /* TODO update clocks */
-        break;
-    case 0x310:	/* CM_ICLKEN_GFX */
-        s->clken[6] = value & 1;
-        /* TODO update clocks */
-        break;
-    case 0x340:	/* CM_CLKSEL_GFX */
-        s->clksel[3] = value & 7;
-        /* TODO update clocks */
-        break;
-    case 0x348:	/* CM_CLKSTCTRL_GFX */
-        s->clkctrl[2] = value & 1;
-        break;
-    case 0x350:	/* RM_RSTCTRL_GFX */
-        s->rstctrl[0] = value & 1;
-        /* TODO: reset */
-        break;
-    case 0x358:	/* RM_RSTST_GFX */
-        s->rst[1] &= ~value;
-        break;
-    case 0x3c8:	/* PM_WKDEP_GFX */
-        s->wkup[1] = value & 0x13;
-        break;
-    case 0x3e0:	/* PM_PWSTCTRL_GFX */
-        s->power[2] = (value & 0x00c0f) | (3 << 2);
-        break;
-
-    case 0x400:	/* CM_FCLKEN_WKUP */
-        s->clken[7] = value & 0xd;
-        /* TODO update clocks */
-        break;
-    case 0x410:	/* CM_ICLKEN_WKUP */
-        s->clken[8] = value & 0x3f;
-        /* TODO update clocks */
-        break;
-    case 0x430:	/* CM_AUTOIDLE_WKUP */
-        s->clkidle[4] = value & 0x0000003f;
-        /* TODO update clocks */
-        break;
-    case 0x440:	/* CM_CLKSEL_WKUP */
-        s->clksel[4] = value & 3;
-        /* TODO update clocks */
-        break;
-    case 0x450:	/* RM_RSTCTRL_WKUP */
-        /* TODO: reset */
-        if (value & 2)
-            qemu_system_reset_request();
-        break;
-    case 0x454:	/* RM_RSTTIME_WKUP */
-        s->rsttime_wkup = value & 0x1fff;
-        break;
-    case 0x458:	/* RM_RSTST_WKUP */
-        s->rst[2] &= ~value;
-        break;
-    case 0x4a0:	/* PM_WKEN_WKUP */
-        s->wken[2] = value & 0x00000005;
-        break;
-    case 0x4b0:	/* PM_WKST_WKUP */
-        s->wkst[2] &= ~value;
-        break;
-
-    case 0x500:	/* CM_CLKEN_PLL */
-        if (value & 0xffffff30)
-            fprintf(stderr, "%s: write 0s in CM_CLKEN_PLL for "
-                            "future compatibility\n", __FUNCTION__);
-        if ((s->clken[9] ^ value) & 0xcc) {
-            s->clken[9] &= ~0xcc;
-            s->clken[9] |= value & 0xcc;
-            omap_prcm_apll_update(s);
-        }
-        if ((s->clken[9] ^ value) & 3) {
-            s->clken[9] &= ~3;
-            s->clken[9] |= value & 3;
-            omap_prcm_dpll_update(s);
-        }
-        break;
-    case 0x530:	/* CM_AUTOIDLE_PLL */
-        s->clkidle[5] = value & 0x000000cf;
-        /* TODO update clocks */
-        break;
-    case 0x540:	/* CM_CLKSEL1_PLL */
-        if (value & 0xfc4000d7)
-            fprintf(stderr, "%s: write 0s in CM_CLKSEL1_PLL for "
-                            "future compatibility\n", __FUNCTION__);
-        if ((s->clksel[5] ^ value) & 0x003fff00) {
-            s->clksel[5] = value & 0x03bfff28;
-            omap_prcm_dpll_update(s);
-        }
-        /* TODO update the other clocks */
-
-        s->clksel[5] = value & 0x03bfff28;
-        break;
-    case 0x544:	/* CM_CLKSEL2_PLL */
-        if (value & ~3)
-            fprintf(stderr, "%s: write 0s in CM_CLKSEL2_PLL[31:2] for "
-                            "future compatibility\n", __FUNCTION__);
-        if (s->clksel[6] != (value & 3)) {
-            s->clksel[6] = value & 3;
-            omap_prcm_dpll_update(s);
-        }
-        break;
-
-    case 0x800:	/* CM_FCLKEN_DSP */
-        s->clken[10] = value & 0x501;
-        /* TODO update clocks */
-        break;
-    case 0x810:	/* CM_ICLKEN_DSP */
-        s->clken[11] = value & 0x2;
-        /* TODO update clocks */
-        break;
-    case 0x830:	/* CM_AUTOIDLE_DSP */
-        s->clkidle[6] = value & 0x2;
-        /* TODO update clocks */
-        break;
-    case 0x840:	/* CM_CLKSEL_DSP */
-        s->clksel[7] = value & 0x3fff;
-        /* TODO update clocks */
-        break;
-    case 0x848:	/* CM_CLKSTCTRL_DSP */
-        s->clkctrl[3] = value & 0x101;
-        break;
-    case 0x850:	/* RM_RSTCTRL_DSP */
-        /* TODO: reset */
-        break;
-    case 0x858:	/* RM_RSTST_DSP */
-        s->rst[3] &= ~value;
-        break;
-    case 0x8c8:	/* PM_WKDEP_DSP */
-        s->wkup[2] = value & 0x13;
-        break;
-    case 0x8e0:	/* PM_PWSTCTRL_DSP */
-        s->power[3] = (value & 0x03017) | (3 << 2);
-        break;
-
-    case 0x8f0:	/* PRCM_IRQSTATUS_DSP */
-        s->irqst[1] &= ~value;
-        omap_prcm_int_update(s, 1);
-        break;
-    case 0x8f4:	/* PRCM_IRQENABLE_DSP */
-        s->irqen[1] = value & 0x7;
-        omap_prcm_int_update(s, 1);
-        break;
-
-    case 0x8f8:	/* PRCM_IRQSTATUS_IVA */
-        s->irqst[2] &= ~value;
-        omap_prcm_int_update(s, 2);
-        break;
-    case 0x8fc:	/* PRCM_IRQENABLE_IVA */
-        s->irqen[2] = value & 0x7;
-        omap_prcm_int_update(s, 2);
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_prcm_ops = {
-    .read = omap_prcm_read,
-    .write = omap_prcm_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_prcm_reset(struct omap_prcm_s *s)
-{
-    s->sysconfig = 0;
-    s->irqst[0] = 0;
-    s->irqst[1] = 0;
-    s->irqst[2] = 0;
-    s->irqen[0] = 0;
-    s->irqen[1] = 0;
-    s->irqen[2] = 0;
-    s->voltctrl = 0x1040;
-    s->ev = 0x14;
-    s->evtime[0] = 0;
-    s->evtime[1] = 0;
-    s->clkctrl[0] = 0;
-    s->clkctrl[1] = 0;
-    s->clkctrl[2] = 0;
-    s->clkctrl[3] = 0;
-    s->clken[1] = 7;
-    s->clken[3] = 7;
-    s->clken[4] = 0;
-    s->clken[5] = 0;
-    s->clken[6] = 0;
-    s->clken[7] = 0xc;
-    s->clken[8] = 0x3e;
-    s->clken[9] = 0x0d;
-    s->clken[10] = 0;
-    s->clken[11] = 0;
-    s->clkidle[0] = 0;
-    s->clkidle[2] = 7;
-    s->clkidle[3] = 0;
-    s->clkidle[4] = 0;
-    s->clkidle[5] = 0x0c;
-    s->clkidle[6] = 0;
-    s->clksel[0] = 0x01;
-    s->clksel[1] = 0x02100121;
-    s->clksel[2] = 0x00000000;
-    s->clksel[3] = 0x01;
-    s->clksel[4] = 0;
-    s->clksel[7] = 0x0121;
-    s->wkup[0] = 0x15;
-    s->wkup[1] = 0x13;
-    s->wkup[2] = 0x13;
-    s->wken[0] = 0x04667ff8;
-    s->wken[1] = 0x00000005;
-    s->wken[2] = 5;
-    s->wkst[0] = 0;
-    s->wkst[1] = 0;
-    s->wkst[2] = 0;
-    s->power[0] = 0x00c;
-    s->power[1] = 4;
-    s->power[2] = 0x0000c;
-    s->power[3] = 0x14;
-    s->rstctrl[0] = 1;
-    s->rst[3] = 1;
-    omap_prcm_apll_update(s);
-    omap_prcm_dpll_update(s);
-}
-
-static void omap_prcm_coldreset(struct omap_prcm_s *s)
-{
-    s->setuptime[0] = 0;
-    s->setuptime[1] = 0;
-    memset(&s->scratch, 0, sizeof(s->scratch));
-    s->rst[0] = 0x01;
-    s->rst[1] = 0x00;
-    s->rst[2] = 0x01;
-    s->clken[0] = 0;
-    s->clken[2] = 0;
-    s->clkidle[1] = 0;
-    s->clksel[5] = 0;
-    s->clksel[6] = 2;
-    s->clksrc[0] = 0x43;
-    s->clkout[0] = 0x0303;
-    s->clkemul[0] = 0;
-    s->clkpol[0] = 0x100;
-    s->rsttime_wkup = 0x1002;
-
-    omap_prcm_reset(s);
-}
-
-static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
-                qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
-                struct omap_mpu_state_s *mpu)
-{
-    struct omap_prcm_s *s = (struct omap_prcm_s *)
-            g_malloc0(sizeof(struct omap_prcm_s));
-
-    s->irq[0] = mpu_int;
-    s->irq[1] = dsp_int;
-    s->irq[2] = iva_int;
-    s->mpu = mpu;
-    omap_prcm_coldreset(s);
-
-    memory_region_init_io(&s->iomem0, &omap_prcm_ops, s, "omap.pcrm0",
-                          omap_l4_region_size(ta, 0));
-    memory_region_init_io(&s->iomem1, &omap_prcm_ops, s, "omap.pcrm1",
-                          omap_l4_region_size(ta, 1));
-    omap_l4_attach(ta, 0, &s->iomem0);
-    omap_l4_attach(ta, 1, &s->iomem1);
-
-    return s;
-}
-
-/* System and Pinout control */
-struct omap_sysctl_s {
-    struct omap_mpu_state_s *mpu;
-    MemoryRegion iomem;
-
-    uint32_t sysconfig;
-    uint32_t devconfig;
-    uint32_t psaconfig;
-    uint32_t padconf[0x45];
-    uint8_t obs;
-    uint32_t msuspendmux[5];
-};
-
-static uint32_t omap_sysctl_read8(void *opaque, hwaddr addr)
-{
-
-    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
-    int pad_offset, byte_offset;
-    int value;
-
-    switch (addr) {
-    case 0x030 ... 0x140:	/* CONTROL_PADCONF - only used in the POP */
-        pad_offset = (addr - 0x30) >> 2;
-        byte_offset = (addr - 0x30) & (4 - 1);
-
-        value = s->padconf[pad_offset];
-        value = (value >> (byte_offset * 8)) & 0xff;
-
-        return value;
-
-    default:
-        break;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static uint32_t omap_sysctl_read(void *opaque, hwaddr addr)
-{
-    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
-
-    switch (addr) {
-    case 0x000:	/* CONTROL_REVISION */
-        return 0x20;
-
-    case 0x010:	/* CONTROL_SYSCONFIG */
-        return s->sysconfig;
-
-    case 0x030 ... 0x140:	/* CONTROL_PADCONF - only used in the POP */
-        return s->padconf[(addr - 0x30) >> 2];
-
-    case 0x270:	/* CONTROL_DEBOBS */
-        return s->obs;
-
-    case 0x274:	/* CONTROL_DEVCONF */
-        return s->devconfig;
-
-    case 0x28c:	/* CONTROL_EMU_SUPPORT */
-        return 0;
-
-    case 0x290:	/* CONTROL_MSUSPENDMUX_0 */
-        return s->msuspendmux[0];
-    case 0x294:	/* CONTROL_MSUSPENDMUX_1 */
-        return s->msuspendmux[1];
-    case 0x298:	/* CONTROL_MSUSPENDMUX_2 */
-        return s->msuspendmux[2];
-    case 0x29c:	/* CONTROL_MSUSPENDMUX_3 */
-        return s->msuspendmux[3];
-    case 0x2a0:	/* CONTROL_MSUSPENDMUX_4 */
-        return s->msuspendmux[4];
-    case 0x2a4:	/* CONTROL_MSUSPENDMUX_5 */
-        return 0;
-
-    case 0x2b8:	/* CONTROL_PSA_CTRL */
-        return s->psaconfig;
-    case 0x2bc:	/* CONTROL_PSA_CMD */
-    case 0x2c0:	/* CONTROL_PSA_VALUE */
-        return 0;
-
-    case 0x2b0:	/* CONTROL_SEC_CTRL */
-        return 0x800000f1;
-    case 0x2d0:	/* CONTROL_SEC_EMU */
-        return 0x80000015;
-    case 0x2d4:	/* CONTROL_SEC_TAP */
-        return 0x8000007f;
-    case 0x2b4:	/* CONTROL_SEC_TEST */
-    case 0x2f0:	/* CONTROL_SEC_STATUS */
-    case 0x2f4:	/* CONTROL_SEC_ERR_STATUS */
-        /* Secure mode is not present on general-pusrpose device.  Outside
-         * secure mode these values cannot be read or written.  */
-        return 0;
-
-    case 0x2d8:	/* CONTROL_OCM_RAM_PERM */
-        return 0xff;
-    case 0x2dc:	/* CONTROL_OCM_PUB_RAM_ADD */
-    case 0x2e0:	/* CONTROL_EXT_SEC_RAM_START_ADD */
-    case 0x2e4:	/* CONTROL_EXT_SEC_RAM_STOP_ADD */
-        /* No secure mode so no Extended Secure RAM present.  */
-        return 0;
-
-    case 0x2f8:	/* CONTROL_STATUS */
-        /* Device Type => General-purpose */
-        return 0x0300;
-    case 0x2fc:	/* CONTROL_GENERAL_PURPOSE_STATUS */
-
-    case 0x300:	/* CONTROL_RPUB_KEY_H_0 */
-    case 0x304:	/* CONTROL_RPUB_KEY_H_1 */
-    case 0x308:	/* CONTROL_RPUB_KEY_H_2 */
-    case 0x30c:	/* CONTROL_RPUB_KEY_H_3 */
-        return 0xdecafbad;
-
-    case 0x310:	/* CONTROL_RAND_KEY_0 */
-    case 0x314:	/* CONTROL_RAND_KEY_1 */
-    case 0x318:	/* CONTROL_RAND_KEY_2 */
-    case 0x31c:	/* CONTROL_RAND_KEY_3 */
-    case 0x320:	/* CONTROL_CUST_KEY_0 */
-    case 0x324:	/* CONTROL_CUST_KEY_1 */
-    case 0x330:	/* CONTROL_TEST_KEY_0 */
-    case 0x334:	/* CONTROL_TEST_KEY_1 */
-    case 0x338:	/* CONTROL_TEST_KEY_2 */
-    case 0x33c:	/* CONTROL_TEST_KEY_3 */
-    case 0x340:	/* CONTROL_TEST_KEY_4 */
-    case 0x344:	/* CONTROL_TEST_KEY_5 */
-    case 0x348:	/* CONTROL_TEST_KEY_6 */
-    case 0x34c:	/* CONTROL_TEST_KEY_7 */
-    case 0x350:	/* CONTROL_TEST_KEY_8 */
-    case 0x354:	/* CONTROL_TEST_KEY_9 */
-        /* Can only be accessed in secure mode and when C_FieldAccEnable
-         * bit is set in CONTROL_SEC_CTRL.
-         * TODO: otherwise an interconnect access error is generated.  */
-        return 0;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_sysctl_write8(void *opaque, hwaddr addr,
-                uint32_t value)
-{
-    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
-    int pad_offset, byte_offset;
-    int prev_value;
-
-    switch (addr) {
-    case 0x030 ... 0x140:	/* CONTROL_PADCONF - only used in the POP */
-        pad_offset = (addr - 0x30) >> 2;
-        byte_offset = (addr - 0x30) & (4 - 1);
-
-        prev_value = s->padconf[pad_offset];
-        prev_value &= ~(0xff << (byte_offset * 8));
-        prev_value |= ((value & 0x1f1f1f1f) << (byte_offset * 8)) & 0x1f1f1f1f;
-        s->padconf[pad_offset] = prev_value;
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        break;
-    }
-}
-
-static void omap_sysctl_write(void *opaque, hwaddr addr,
-                uint32_t value)
-{
-    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
-
-    switch (addr) {
-    case 0x000:	/* CONTROL_REVISION */
-    case 0x2a4:	/* CONTROL_MSUSPENDMUX_5 */
-    case 0x2c0:	/* CONTROL_PSA_VALUE */
-    case 0x2f8:	/* CONTROL_STATUS */
-    case 0x2fc:	/* CONTROL_GENERAL_PURPOSE_STATUS */
-    case 0x300:	/* CONTROL_RPUB_KEY_H_0 */
-    case 0x304:	/* CONTROL_RPUB_KEY_H_1 */
-    case 0x308:	/* CONTROL_RPUB_KEY_H_2 */
-    case 0x30c:	/* CONTROL_RPUB_KEY_H_3 */
-    case 0x310:	/* CONTROL_RAND_KEY_0 */
-    case 0x314:	/* CONTROL_RAND_KEY_1 */
-    case 0x318:	/* CONTROL_RAND_KEY_2 */
-    case 0x31c:	/* CONTROL_RAND_KEY_3 */
-    case 0x320:	/* CONTROL_CUST_KEY_0 */
-    case 0x324:	/* CONTROL_CUST_KEY_1 */
-    case 0x330:	/* CONTROL_TEST_KEY_0 */
-    case 0x334:	/* CONTROL_TEST_KEY_1 */
-    case 0x338:	/* CONTROL_TEST_KEY_2 */
-    case 0x33c:	/* CONTROL_TEST_KEY_3 */
-    case 0x340:	/* CONTROL_TEST_KEY_4 */
-    case 0x344:	/* CONTROL_TEST_KEY_5 */
-    case 0x348:	/* CONTROL_TEST_KEY_6 */
-    case 0x34c:	/* CONTROL_TEST_KEY_7 */
-    case 0x350:	/* CONTROL_TEST_KEY_8 */
-    case 0x354:	/* CONTROL_TEST_KEY_9 */
-        OMAP_RO_REG(addr);
-        return;
-
-    case 0x010:	/* CONTROL_SYSCONFIG */
-        s->sysconfig = value & 0x1e;
-        break;
-
-    case 0x030 ... 0x140:	/* CONTROL_PADCONF - only used in the POP */
-        /* XXX: should check constant bits */
-        s->padconf[(addr - 0x30) >> 2] = value & 0x1f1f1f1f;
-        break;
-
-    case 0x270:	/* CONTROL_DEBOBS */
-        s->obs = value & 0xff;
-        break;
-
-    case 0x274:	/* CONTROL_DEVCONF */
-        s->devconfig = value & 0xffffc7ff;
-        break;
-
-    case 0x28c:	/* CONTROL_EMU_SUPPORT */
-        break;
-
-    case 0x290:	/* CONTROL_MSUSPENDMUX_0 */
-        s->msuspendmux[0] = value & 0x3fffffff;
-        break;
-    case 0x294:	/* CONTROL_MSUSPENDMUX_1 */
-        s->msuspendmux[1] = value & 0x3fffffff;
-        break;
-    case 0x298:	/* CONTROL_MSUSPENDMUX_2 */
-        s->msuspendmux[2] = value & 0x3fffffff;
-        break;
-    case 0x29c:	/* CONTROL_MSUSPENDMUX_3 */
-        s->msuspendmux[3] = value & 0x3fffffff;
-        break;
-    case 0x2a0:	/* CONTROL_MSUSPENDMUX_4 */
-        s->msuspendmux[4] = value & 0x3fffffff;
-        break;
-
-    case 0x2b8:	/* CONTROL_PSA_CTRL */
-        s->psaconfig = value & 0x1c;
-        s->psaconfig |= (value & 0x20) ? 2 : 1;
-        break;
-    case 0x2bc:	/* CONTROL_PSA_CMD */
-        break;
-
-    case 0x2b0:	/* CONTROL_SEC_CTRL */
-    case 0x2b4:	/* CONTROL_SEC_TEST */
-    case 0x2d0:	/* CONTROL_SEC_EMU */
-    case 0x2d4:	/* CONTROL_SEC_TAP */
-    case 0x2d8:	/* CONTROL_OCM_RAM_PERM */
-    case 0x2dc:	/* CONTROL_OCM_PUB_RAM_ADD */
-    case 0x2e0:	/* CONTROL_EXT_SEC_RAM_START_ADD */
-    case 0x2e4:	/* CONTROL_EXT_SEC_RAM_STOP_ADD */
-    case 0x2f0:	/* CONTROL_SEC_STATUS */
-    case 0x2f4:	/* CONTROL_SEC_ERR_STATUS */
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static const MemoryRegionOps omap_sysctl_ops = {
-    .old_mmio = {
-        .read = {
-            omap_sysctl_read8,
-            omap_badwidth_read32,	/* TODO */
-            omap_sysctl_read,
-        },
-        .write = {
-            omap_sysctl_write8,
-            omap_badwidth_write32,	/* TODO */
-            omap_sysctl_write,
-        },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void omap_sysctl_reset(struct omap_sysctl_s *s)
-{
-    /* (power-on reset) */
-    s->sysconfig = 0;
-    s->obs = 0;
-    s->devconfig = 0x0c000000;
-    s->msuspendmux[0] = 0x00000000;
-    s->msuspendmux[1] = 0x00000000;
-    s->msuspendmux[2] = 0x00000000;
-    s->msuspendmux[3] = 0x00000000;
-    s->msuspendmux[4] = 0x00000000;
-    s->psaconfig = 1;
-
-    s->padconf[0x00] = 0x000f0f0f;
-    s->padconf[0x01] = 0x00000000;
-    s->padconf[0x02] = 0x00000000;
-    s->padconf[0x03] = 0x00000000;
-    s->padconf[0x04] = 0x00000000;
-    s->padconf[0x05] = 0x00000000;
-    s->padconf[0x06] = 0x00000000;
-    s->padconf[0x07] = 0x00000000;
-    s->padconf[0x08] = 0x08080800;
-    s->padconf[0x09] = 0x08080808;
-    s->padconf[0x0a] = 0x08080808;
-    s->padconf[0x0b] = 0x08080808;
-    s->padconf[0x0c] = 0x08080808;
-    s->padconf[0x0d] = 0x08080800;
-    s->padconf[0x0e] = 0x08080808;
-    s->padconf[0x0f] = 0x08080808;
-    s->padconf[0x10] = 0x18181808;	/* | 0x07070700 if SBoot3 */
-    s->padconf[0x11] = 0x18181818;	/* | 0x07070707 if SBoot3 */
-    s->padconf[0x12] = 0x18181818;	/* | 0x07070707 if SBoot3 */
-    s->padconf[0x13] = 0x18181818;	/* | 0x07070707 if SBoot3 */
-    s->padconf[0x14] = 0x18181818;	/* | 0x00070707 if SBoot3 */
-    s->padconf[0x15] = 0x18181818;
-    s->padconf[0x16] = 0x18181818;	/* | 0x07000000 if SBoot3 */
-    s->padconf[0x17] = 0x1f001f00;
-    s->padconf[0x18] = 0x1f1f1f1f;
-    s->padconf[0x19] = 0x00000000;
-    s->padconf[0x1a] = 0x1f180000;
-    s->padconf[0x1b] = 0x00001f1f;
-    s->padconf[0x1c] = 0x1f001f00;
-    s->padconf[0x1d] = 0x00000000;
-    s->padconf[0x1e] = 0x00000000;
-    s->padconf[0x1f] = 0x08000000;
-    s->padconf[0x20] = 0x08080808;
-    s->padconf[0x21] = 0x08080808;
-    s->padconf[0x22] = 0x0f080808;
-    s->padconf[0x23] = 0x0f0f0f0f;
-    s->padconf[0x24] = 0x000f0f0f;
-    s->padconf[0x25] = 0x1f1f1f0f;
-    s->padconf[0x26] = 0x080f0f1f;
-    s->padconf[0x27] = 0x070f1808;
-    s->padconf[0x28] = 0x0f070707;
-    s->padconf[0x29] = 0x000f0f1f;
-    s->padconf[0x2a] = 0x0f0f0f1f;
-    s->padconf[0x2b] = 0x08000000;
-    s->padconf[0x2c] = 0x0000001f;
-    s->padconf[0x2d] = 0x0f0f1f00;
-    s->padconf[0x2e] = 0x1f1f0f0f;
-    s->padconf[0x2f] = 0x0f1f1f1f;
-    s->padconf[0x30] = 0x0f0f0f0f;
-    s->padconf[0x31] = 0x0f1f0f1f;
-    s->padconf[0x32] = 0x0f0f0f0f;
-    s->padconf[0x33] = 0x0f1f0f1f;
-    s->padconf[0x34] = 0x1f1f0f0f;
-    s->padconf[0x35] = 0x0f0f1f1f;
-    s->padconf[0x36] = 0x0f0f1f0f;
-    s->padconf[0x37] = 0x0f0f0f0f;
-    s->padconf[0x38] = 0x1f18180f;
-    s->padconf[0x39] = 0x1f1f1f1f;
-    s->padconf[0x3a] = 0x00001f1f;
-    s->padconf[0x3b] = 0x00000000;
-    s->padconf[0x3c] = 0x00000000;
-    s->padconf[0x3d] = 0x0f0f0f0f;
-    s->padconf[0x3e] = 0x18000f0f;
-    s->padconf[0x3f] = 0x00070000;
-    s->padconf[0x40] = 0x00000707;
-    s->padconf[0x41] = 0x0f1f0700;
-    s->padconf[0x42] = 0x1f1f070f;
-    s->padconf[0x43] = 0x0008081f;
-    s->padconf[0x44] = 0x00000800;
-}
-
-static struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
-                omap_clk iclk, struct omap_mpu_state_s *mpu)
-{
-    struct omap_sysctl_s *s = (struct omap_sysctl_s *)
-            g_malloc0(sizeof(struct omap_sysctl_s));
-
-    s->mpu = mpu;
-    omap_sysctl_reset(s);
-
-    memory_region_init_io(&s->iomem, &omap_sysctl_ops, s, "omap.sysctl",
-                          omap_l4_region_size(ta, 0));
-    omap_l4_attach(ta, 0, &s->iomem);
-
-    return s;
-}
-
-/* General chip reset */
-static void omap2_mpu_reset(void *opaque)
-{
-    struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
-
-    omap_dma_reset(mpu->dma);
-    omap_prcm_reset(mpu->prcm);
-    omap_sysctl_reset(mpu->sysc);
-    omap_gp_timer_reset(mpu->gptimer[0]);
-    omap_gp_timer_reset(mpu->gptimer[1]);
-    omap_gp_timer_reset(mpu->gptimer[2]);
-    omap_gp_timer_reset(mpu->gptimer[3]);
-    omap_gp_timer_reset(mpu->gptimer[4]);
-    omap_gp_timer_reset(mpu->gptimer[5]);
-    omap_gp_timer_reset(mpu->gptimer[6]);
-    omap_gp_timer_reset(mpu->gptimer[7]);
-    omap_gp_timer_reset(mpu->gptimer[8]);
-    omap_gp_timer_reset(mpu->gptimer[9]);
-    omap_gp_timer_reset(mpu->gptimer[10]);
-    omap_gp_timer_reset(mpu->gptimer[11]);
-    omap_synctimer_reset(mpu->synctimer);
-    omap_sdrc_reset(mpu->sdrc);
-    omap_gpmc_reset(mpu->gpmc);
-    omap_dss_reset(mpu->dss);
-    omap_uart_reset(mpu->uart[0]);
-    omap_uart_reset(mpu->uart[1]);
-    omap_uart_reset(mpu->uart[2]);
-    omap_mmc_reset(mpu->mmc);
-    omap_mcspi_reset(mpu->mcspi[0]);
-    omap_mcspi_reset(mpu->mcspi[1]);
-    cpu_reset(CPU(mpu->cpu));
-}
-
-static int omap2_validate_addr(struct omap_mpu_state_s *s,
-                hwaddr addr)
-{
-    return 1;
-}
-
-static const struct dma_irq_map omap2_dma_irq_map[] = {
-    { 0, OMAP_INT_24XX_SDMA_IRQ0 },
-    { 0, OMAP_INT_24XX_SDMA_IRQ1 },
-    { 0, OMAP_INT_24XX_SDMA_IRQ2 },
-    { 0, OMAP_INT_24XX_SDMA_IRQ3 },
-};
-
-struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
-                unsigned long sdram_size,
-                const char *core)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
-            g_malloc0(sizeof(struct omap_mpu_state_s));
-    qemu_irq *cpu_irq;
-    qemu_irq dma_irqs[4];
-    DriveInfo *dinfo;
-    int i;
-    SysBusDevice *busdev;
-    struct omap_target_agent_s *ta;
-
-    /* Core */
-    s->mpu_model = omap2420;
-    s->cpu = cpu_arm_init(core ?: "arm1136-r2");
-    if (s->cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    s->sdram_size = sdram_size;
-    s->sram_size = OMAP242X_SRAM_SIZE;
-
-    s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
-
-    /* Clocks */
-    omap_clk_init(s);
-
-    /* Memory-mapped stuff */
-    memory_region_init_ram(&s->sdram, "omap2.dram", s->sdram_size);
-    vmstate_register_ram_global(&s->sdram);
-    memory_region_add_subregion(sysmem, OMAP2_Q2_BASE, &s->sdram);
-    memory_region_init_ram(&s->sram, "omap2.sram", s->sram_size);
-    vmstate_register_ram_global(&s->sram);
-    memory_region_add_subregion(sysmem, OMAP2_SRAM_BASE, &s->sram);
-
-    s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54);
-
-    /* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */
-    cpu_irq = arm_pic_init_cpu(s->cpu);
-    s->ih[0] = qdev_create(NULL, "omap2-intc");
-    qdev_prop_set_uint8(s->ih[0], "revision", 0x21);
-    qdev_prop_set_ptr(s->ih[0], "fclk", omap_findclk(s, "mpu_intc_fclk"));
-    qdev_prop_set_ptr(s->ih[0], "iclk", omap_findclk(s, "mpu_intc_iclk"));
-    qdev_init_nofail(s->ih[0]);
-    busdev = SYS_BUS_DEVICE(s->ih[0]);
-    sysbus_connect_irq(busdev, 0, cpu_irq[ARM_PIC_CPU_IRQ]);
-    sysbus_connect_irq(busdev, 1, cpu_irq[ARM_PIC_CPU_FIQ]);
-    sysbus_mmio_map(busdev, 0, 0x480fe000);
-    s->prcm = omap_prcm_init(omap_l4tao(s->l4, 3),
-                             qdev_get_gpio_in(s->ih[0],
-                                              OMAP_INT_24XX_PRCM_MPU_IRQ),
-                             NULL, NULL, s);
-
-    s->sysc = omap_sysctl_init(omap_l4tao(s->l4, 1),
-                    omap_findclk(s, "omapctrl_iclk"), s);
-
-    for (i = 0; i < 4; i++) {
-        dma_irqs[i] = qdev_get_gpio_in(s->ih[omap2_dma_irq_map[i].ih],
-                                       omap2_dma_irq_map[i].intr);
-    }
-    s->dma = omap_dma4_init(0x48056000, dma_irqs, sysmem, s, 256, 32,
-                    omap_findclk(s, "sdma_iclk"),
-                    omap_findclk(s, "sdma_fclk"));
-    s->port->addr_valid = omap2_validate_addr;
-
-    /* Register SDRAM and SRAM ports for fast DMA transfers.  */
-    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sdram),
-                         OMAP2_Q2_BASE, s->sdram_size);
-    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sram),
-                         OMAP2_SRAM_BASE, s->sram_size);
-
-    s->uart[0] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 19),
-                                 qdev_get_gpio_in(s->ih[0],
-                                                  OMAP_INT_24XX_UART1_IRQ),
-                    omap_findclk(s, "uart1_fclk"),
-                    omap_findclk(s, "uart1_iclk"),
-                    s->drq[OMAP24XX_DMA_UART1_TX],
-                    s->drq[OMAP24XX_DMA_UART1_RX],
-                    "uart1",
-                    serial_hds[0]);
-    s->uart[1] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 20),
-                                 qdev_get_gpio_in(s->ih[0],
-                                                  OMAP_INT_24XX_UART2_IRQ),
-                    omap_findclk(s, "uart2_fclk"),
-                    omap_findclk(s, "uart2_iclk"),
-                    s->drq[OMAP24XX_DMA_UART2_TX],
-                    s->drq[OMAP24XX_DMA_UART2_RX],
-                    "uart2",
-                    serial_hds[0] ? serial_hds[1] : NULL);
-    s->uart[2] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 21),
-                                 qdev_get_gpio_in(s->ih[0],
-                                                  OMAP_INT_24XX_UART3_IRQ),
-                    omap_findclk(s, "uart3_fclk"),
-                    omap_findclk(s, "uart3_iclk"),
-                    s->drq[OMAP24XX_DMA_UART3_TX],
-                    s->drq[OMAP24XX_DMA_UART3_RX],
-                    "uart3",
-                    serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
-
-    s->gptimer[0] = omap_gp_timer_init(omap_l4ta(s->l4, 7),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER1),
-                    omap_findclk(s, "wu_gpt1_clk"),
-                    omap_findclk(s, "wu_l4_iclk"));
-    s->gptimer[1] = omap_gp_timer_init(omap_l4ta(s->l4, 8),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER2),
-                    omap_findclk(s, "core_gpt2_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[2] = omap_gp_timer_init(omap_l4ta(s->l4, 22),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER3),
-                    omap_findclk(s, "core_gpt3_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[3] = omap_gp_timer_init(omap_l4ta(s->l4, 23),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER4),
-                    omap_findclk(s, "core_gpt4_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[4] = omap_gp_timer_init(omap_l4ta(s->l4, 24),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER5),
-                    omap_findclk(s, "core_gpt5_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[5] = omap_gp_timer_init(omap_l4ta(s->l4, 25),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER6),
-                    omap_findclk(s, "core_gpt6_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[6] = omap_gp_timer_init(omap_l4ta(s->l4, 26),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER7),
-                    omap_findclk(s, "core_gpt7_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[7] = omap_gp_timer_init(omap_l4ta(s->l4, 27),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER8),
-                    omap_findclk(s, "core_gpt8_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[8] = omap_gp_timer_init(omap_l4ta(s->l4, 28),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER9),
-                    omap_findclk(s, "core_gpt9_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[9] = omap_gp_timer_init(omap_l4ta(s->l4, 29),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER10),
-                    omap_findclk(s, "core_gpt10_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[10] = omap_gp_timer_init(omap_l4ta(s->l4, 30),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER11),
-                    omap_findclk(s, "core_gpt11_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-    s->gptimer[11] = omap_gp_timer_init(omap_l4ta(s->l4, 31),
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER12),
-                    omap_findclk(s, "core_gpt12_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-
-    omap_tap_init(omap_l4ta(s->l4, 2), s);
-
-    s->synctimer = omap_synctimer_init(omap_l4tao(s->l4, 2), s,
-                    omap_findclk(s, "clk32-kHz"),
-                    omap_findclk(s, "core_l4_iclk"));
-
-    s->i2c[0] = qdev_create(NULL, "omap_i2c");
-    qdev_prop_set_uint8(s->i2c[0], "revision", 0x34);
-    qdev_prop_set_ptr(s->i2c[0], "iclk", omap_findclk(s, "i2c1.iclk"));
-    qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "i2c1.fclk"));
-    qdev_init_nofail(s->i2c[0]);
-    busdev = SYS_BUS_DEVICE(s->i2c[0]);
-    sysbus_connect_irq(busdev, 0,
-                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C1_IRQ));
-    sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C1_TX]);
-    sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C1_RX]);
-    sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 5), 0));
-
-    s->i2c[1] = qdev_create(NULL, "omap_i2c");
-    qdev_prop_set_uint8(s->i2c[1], "revision", 0x34);
-    qdev_prop_set_ptr(s->i2c[1], "iclk", omap_findclk(s, "i2c2.iclk"));
-    qdev_prop_set_ptr(s->i2c[1], "fclk", omap_findclk(s, "i2c2.fclk"));
-    qdev_init_nofail(s->i2c[1]);
-    busdev = SYS_BUS_DEVICE(s->i2c[1]);
-    sysbus_connect_irq(busdev, 0,
-                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C2_IRQ));
-    sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C2_TX]);
-    sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C2_RX]);
-    sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 6), 0));
-
-    s->gpio = qdev_create(NULL, "omap2-gpio");
-    qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
-    qdev_prop_set_ptr(s->gpio, "iclk", omap_findclk(s, "gpio_iclk"));
-    qdev_prop_set_ptr(s->gpio, "fclk0", omap_findclk(s, "gpio1_dbclk"));
-    qdev_prop_set_ptr(s->gpio, "fclk1", omap_findclk(s, "gpio2_dbclk"));
-    qdev_prop_set_ptr(s->gpio, "fclk2", omap_findclk(s, "gpio3_dbclk"));
-    qdev_prop_set_ptr(s->gpio, "fclk3", omap_findclk(s, "gpio4_dbclk"));
-    if (s->mpu_model == omap2430) {
-        qdev_prop_set_ptr(s->gpio, "fclk4", omap_findclk(s, "gpio5_dbclk"));
-    }
-    qdev_init_nofail(s->gpio);
-    busdev = SYS_BUS_DEVICE(s->gpio);
-    sysbus_connect_irq(busdev, 0,
-                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK1));
-    sysbus_connect_irq(busdev, 3,
-                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK2));
-    sysbus_connect_irq(busdev, 6,
-                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK3));
-    sysbus_connect_irq(busdev, 9,
-                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK4));
-    if (s->mpu_model == omap2430) {
-        sysbus_connect_irq(busdev, 12,
-                           qdev_get_gpio_in(s->ih[0],
-                                            OMAP_INT_243X_GPIO_BANK5));
-    }
-    ta = omap_l4ta(s->l4, 3);
-    sysbus_mmio_map(busdev, 0, omap_l4_region_base(ta, 1));
-    sysbus_mmio_map(busdev, 1, omap_l4_region_base(ta, 0));
-    sysbus_mmio_map(busdev, 2, omap_l4_region_base(ta, 2));
-    sysbus_mmio_map(busdev, 3, omap_l4_region_base(ta, 4));
-    sysbus_mmio_map(busdev, 4, omap_l4_region_base(ta, 5));
-
-    s->sdrc = omap_sdrc_init(sysmem, 0x68009000);
-    s->gpmc = omap_gpmc_init(s, 0x6800a000,
-                             qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPMC_IRQ),
-                             s->drq[OMAP24XX_DMA_GPMC]);
-
-    dinfo = drive_get(IF_SD, 0, 0);
-    if (!dinfo) {
-        fprintf(stderr, "qemu: missing SecureDigital device\n");
-        exit(1);
-    }
-    s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9), dinfo->bdrv,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MMC_IRQ),
-                    &s->drq[OMAP24XX_DMA_MMC1_TX],
-                    omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
-
-    s->mcspi[0] = omap_mcspi_init(omap_l4ta(s->l4, 35), 4,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI1_IRQ),
-                    &s->drq[OMAP24XX_DMA_SPI1_TX0],
-                    omap_findclk(s, "spi1_fclk"),
-                    omap_findclk(s, "spi1_iclk"));
-    s->mcspi[1] = omap_mcspi_init(omap_l4ta(s->l4, 36), 2,
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI2_IRQ),
-                    &s->drq[OMAP24XX_DMA_SPI2_TX0],
-                    omap_findclk(s, "spi2_fclk"),
-                    omap_findclk(s, "spi2_iclk"));
-
-    s->dss = omap_dss_init(omap_l4ta(s->l4, 10), sysmem, 0x68000800,
-                    /* XXX wire M_IRQ_25, D_L2_IRQ_30 and I_IRQ_13 together */
-                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_DSS_IRQ),
-                           s->drq[OMAP24XX_DMA_DSS],
-                    omap_findclk(s, "dss_clk1"), omap_findclk(s, "dss_clk2"),
-                    omap_findclk(s, "dss_54m_clk"),
-                    omap_findclk(s, "dss_l3_iclk"),
-                    omap_findclk(s, "dss_l4_iclk"));
-
-    omap_sti_init(omap_l4ta(s->l4, 18), sysmem, 0x54000000,
-                  qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_STI),
-                  omap_findclk(s, "emul_ck"),
-                    serial_hds[0] && serial_hds[1] && serial_hds[2] ?
-                    serial_hds[3] : NULL);
-
-    s->eac = omap_eac_init(omap_l4ta(s->l4, 32),
-                           qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_EAC_IRQ),
-                    /* Ten consecutive lines */
-                    &s->drq[OMAP24XX_DMA_EAC_AC_RD],
-                    omap_findclk(s, "func_96m_clk"),
-                    omap_findclk(s, "core_l4_iclk"));
-
-    /* All register mappings (includin those not currenlty implemented):
-     * SystemControlMod	48000000 - 48000fff
-     * SystemControlL4	48001000 - 48001fff
-     * 32kHz Timer Mod	48004000 - 48004fff
-     * 32kHz Timer L4	48005000 - 48005fff
-     * PRCM ModA	48008000 - 480087ff
-     * PRCM ModB	48008800 - 48008fff
-     * PRCM L4		48009000 - 48009fff
-     * TEST-BCM Mod	48012000 - 48012fff
-     * TEST-BCM L4	48013000 - 48013fff
-     * TEST-TAP Mod	48014000 - 48014fff
-     * TEST-TAP L4	48015000 - 48015fff
-     * GPIO1 Mod	48018000 - 48018fff
-     * GPIO Top		48019000 - 48019fff
-     * GPIO2 Mod	4801a000 - 4801afff
-     * GPIO L4		4801b000 - 4801bfff
-     * GPIO3 Mod	4801c000 - 4801cfff
-     * GPIO4 Mod	4801e000 - 4801efff
-     * WDTIMER1 Mod	48020000 - 48010fff
-     * WDTIMER Top	48021000 - 48011fff
-     * WDTIMER2 Mod	48022000 - 48012fff
-     * WDTIMER L4	48023000 - 48013fff
-     * WDTIMER3 Mod	48024000 - 48014fff
-     * WDTIMER3 L4	48025000 - 48015fff
-     * WDTIMER4 Mod	48026000 - 48016fff
-     * WDTIMER4 L4	48027000 - 48017fff
-     * GPTIMER1 Mod	48028000 - 48018fff
-     * GPTIMER1 L4	48029000 - 48019fff
-     * GPTIMER2 Mod	4802a000 - 4801afff
-     * GPTIMER2 L4	4802b000 - 4801bfff
-     * L4-Config AP	48040000 - 480407ff
-     * L4-Config IP	48040800 - 48040fff
-     * L4-Config LA	48041000 - 48041fff
-     * ARM11ETB Mod	48048000 - 48049fff
-     * ARM11ETB L4	4804a000 - 4804afff
-     * DISPLAY Top	48050000 - 480503ff
-     * DISPLAY DISPC	48050400 - 480507ff
-     * DISPLAY RFBI	48050800 - 48050bff
-     * DISPLAY VENC	48050c00 - 48050fff
-     * DISPLAY L4	48051000 - 48051fff
-     * CAMERA Top	48052000 - 480523ff
-     * CAMERA core	48052400 - 480527ff
-     * CAMERA DMA	48052800 - 48052bff
-     * CAMERA MMU	48052c00 - 48052fff
-     * CAMERA L4	48053000 - 48053fff
-     * SDMA Mod		48056000 - 48056fff
-     * SDMA L4		48057000 - 48057fff
-     * SSI Top		48058000 - 48058fff
-     * SSI GDD		48059000 - 48059fff
-     * SSI Port1	4805a000 - 4805afff
-     * SSI Port2	4805b000 - 4805bfff
-     * SSI L4		4805c000 - 4805cfff
-     * USB Mod		4805e000 - 480fefff
-     * USB L4		4805f000 - 480fffff
-     * WIN_TRACER1 Mod	48060000 - 48060fff
-     * WIN_TRACER1 L4	48061000 - 48061fff
-     * WIN_TRACER2 Mod	48062000 - 48062fff
-     * WIN_TRACER2 L4	48063000 - 48063fff
-     * WIN_TRACER3 Mod	48064000 - 48064fff
-     * WIN_TRACER3 L4	48065000 - 48065fff
-     * WIN_TRACER4 Top	48066000 - 480660ff
-     * WIN_TRACER4 ETT	48066100 - 480661ff
-     * WIN_TRACER4 WT	48066200 - 480662ff
-     * WIN_TRACER4 L4	48067000 - 48067fff
-     * XTI Mod		48068000 - 48068fff
-     * XTI L4		48069000 - 48069fff
-     * UART1 Mod	4806a000 - 4806afff
-     * UART1 L4		4806b000 - 4806bfff
-     * UART2 Mod	4806c000 - 4806cfff
-     * UART2 L4		4806d000 - 4806dfff
-     * UART3 Mod	4806e000 - 4806efff
-     * UART3 L4		4806f000 - 4806ffff
-     * I2C1 Mod		48070000 - 48070fff
-     * I2C1 L4		48071000 - 48071fff
-     * I2C2 Mod		48072000 - 48072fff
-     * I2C2 L4		48073000 - 48073fff
-     * McBSP1 Mod	48074000 - 48074fff
-     * McBSP1 L4	48075000 - 48075fff
-     * McBSP2 Mod	48076000 - 48076fff
-     * McBSP2 L4	48077000 - 48077fff
-     * GPTIMER3 Mod	48078000 - 48078fff
-     * GPTIMER3 L4	48079000 - 48079fff
-     * GPTIMER4 Mod	4807a000 - 4807afff
-     * GPTIMER4 L4	4807b000 - 4807bfff
-     * GPTIMER5 Mod	4807c000 - 4807cfff
-     * GPTIMER5 L4	4807d000 - 4807dfff
-     * GPTIMER6 Mod	4807e000 - 4807efff
-     * GPTIMER6 L4	4807f000 - 4807ffff
-     * GPTIMER7 Mod	48080000 - 48080fff
-     * GPTIMER7 L4	48081000 - 48081fff
-     * GPTIMER8 Mod	48082000 - 48082fff
-     * GPTIMER8 L4	48083000 - 48083fff
-     * GPTIMER9 Mod	48084000 - 48084fff
-     * GPTIMER9 L4	48085000 - 48085fff
-     * GPTIMER10 Mod	48086000 - 48086fff
-     * GPTIMER10 L4	48087000 - 48087fff
-     * GPTIMER11 Mod	48088000 - 48088fff
-     * GPTIMER11 L4	48089000 - 48089fff
-     * GPTIMER12 Mod	4808a000 - 4808afff
-     * GPTIMER12 L4	4808b000 - 4808bfff
-     * EAC Mod		48090000 - 48090fff
-     * EAC L4		48091000 - 48091fff
-     * FAC Mod		48092000 - 48092fff
-     * FAC L4		48093000 - 48093fff
-     * MAILBOX Mod	48094000 - 48094fff
-     * MAILBOX L4	48095000 - 48095fff
-     * SPI1 Mod		48098000 - 48098fff
-     * SPI1 L4		48099000 - 48099fff
-     * SPI2 Mod		4809a000 - 4809afff
-     * SPI2 L4		4809b000 - 4809bfff
-     * MMC/SDIO Mod	4809c000 - 4809cfff
-     * MMC/SDIO L4	4809d000 - 4809dfff
-     * MS_PRO Mod	4809e000 - 4809efff
-     * MS_PRO L4	4809f000 - 4809ffff
-     * RNG Mod		480a0000 - 480a0fff
-     * RNG L4		480a1000 - 480a1fff
-     * DES3DES Mod	480a2000 - 480a2fff
-     * DES3DES L4	480a3000 - 480a3fff
-     * SHA1MD5 Mod	480a4000 - 480a4fff
-     * SHA1MD5 L4	480a5000 - 480a5fff
-     * AES Mod		480a6000 - 480a6fff
-     * AES L4		480a7000 - 480a7fff
-     * PKA Mod		480a8000 - 480a9fff
-     * PKA L4		480aa000 - 480aafff
-     * MG Mod		480b0000 - 480b0fff
-     * MG L4		480b1000 - 480b1fff
-     * HDQ/1-wire Mod	480b2000 - 480b2fff
-     * HDQ/1-wire L4	480b3000 - 480b3fff
-     * MPU interrupt	480fe000 - 480fefff
-     * STI channel base	54000000 - 5400ffff
-     * IVA RAM		5c000000 - 5c01ffff
-     * IVA ROM		5c020000 - 5c027fff
-     * IMG_BUF_A	5c040000 - 5c040fff
-     * IMG_BUF_B	5c042000 - 5c042fff
-     * VLCDS		5c048000 - 5c0487ff
-     * IMX_COEF		5c049000 - 5c04afff
-     * IMX_CMD		5c051000 - 5c051fff
-     * VLCDQ		5c053000 - 5c0533ff
-     * VLCDH		5c054000 - 5c054fff
-     * SEQ_CMD		5c055000 - 5c055fff
-     * IMX_REG		5c056000 - 5c0560ff
-     * VLCD_REG		5c056100 - 5c0561ff
-     * SEQ_REG		5c056200 - 5c0562ff
-     * IMG_BUF_REG	5c056300 - 5c0563ff
-     * SEQIRQ_REG	5c056400 - 5c0564ff
-     * OCP_REG		5c060000 - 5c060fff
-     * SYSC_REG		5c070000 - 5c070fff
-     * MMU_REG		5d000000 - 5d000fff
-     * sDMA R		68000400 - 680005ff
-     * sDMA W		68000600 - 680007ff
-     * Display Control	68000800 - 680009ff
-     * DSP subsystem	68000a00 - 68000bff
-     * MPU subsystem	68000c00 - 68000dff
-     * IVA subsystem	68001000 - 680011ff
-     * USB		68001200 - 680013ff
-     * Camera		68001400 - 680015ff
-     * VLYNQ (firewall)	68001800 - 68001bff
-     * VLYNQ		68001e00 - 68001fff
-     * SSI		68002000 - 680021ff
-     * L4		68002400 - 680025ff
-     * DSP (firewall)	68002800 - 68002bff
-     * DSP subsystem	68002e00 - 68002fff
-     * IVA (firewall)	68003000 - 680033ff
-     * IVA		68003600 - 680037ff
-     * GFX		68003a00 - 68003bff
-     * CMDWR emulation	68003c00 - 68003dff
-     * SMS		68004000 - 680041ff
-     * OCM		68004200 - 680043ff
-     * GPMC		68004400 - 680045ff
-     * RAM (firewall)	68005000 - 680053ff
-     * RAM (err login)	68005400 - 680057ff
-     * ROM (firewall)	68005800 - 68005bff
-     * ROM (err login)	68005c00 - 68005fff
-     * GPMC (firewall)	68006000 - 680063ff
-     * GPMC (err login)	68006400 - 680067ff
-     * SMS (err login)	68006c00 - 68006fff
-     * SMS registers	68008000 - 68008fff
-     * SDRC registers	68009000 - 68009fff
-     * GPMC registers	6800a000   6800afff
-     */
-
-    qemu_register_reset(omap2_mpu_reset, s);
-
-    return s;
-}
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
deleted file mode 100644
index c0f50c9..0000000
--- a/hw/pxa2xx.c
+++ /dev/null
@@ -1,2291 +0,0 @@
-/*
- * Intel XScale PXA255/270 processor support.
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Written by Andrzej Zaborowski <balrog at zabor.org>
- *
- * This code is licensed under the GPL.
- */
-
-#include "hw/sysbus.h"
-#include "hw/pxa.h"
-#include "sysemu/sysemu.h"
-#include "hw/serial.h"
-#include "hw/i2c.h"
-#include "hw/ssi.h"
-#include "char/char.h"
-#include "sysemu/blockdev.h"
-
-static struct {
-    hwaddr io_base;
-    int irqn;
-} pxa255_serial[] = {
-    { 0x40100000, PXA2XX_PIC_FFUART },
-    { 0x40200000, PXA2XX_PIC_BTUART },
-    { 0x40700000, PXA2XX_PIC_STUART },
-    { 0x41600000, PXA25X_PIC_HWUART },
-    { 0, 0 }
-}, pxa270_serial[] = {
-    { 0x40100000, PXA2XX_PIC_FFUART },
-    { 0x40200000, PXA2XX_PIC_BTUART },
-    { 0x40700000, PXA2XX_PIC_STUART },
-    { 0, 0 }
-};
-
-typedef struct PXASSPDef {
-    hwaddr io_base;
-    int irqn;
-} PXASSPDef;
-
-#if 0
-static PXASSPDef pxa250_ssp[] = {
-    { 0x41000000, PXA2XX_PIC_SSP },
-    { 0, 0 }
-};
-#endif
-
-static PXASSPDef pxa255_ssp[] = {
-    { 0x41000000, PXA2XX_PIC_SSP },
-    { 0x41400000, PXA25X_PIC_NSSP },
-    { 0, 0 }
-};
-
-#if 0
-static PXASSPDef pxa26x_ssp[] = {
-    { 0x41000000, PXA2XX_PIC_SSP },
-    { 0x41400000, PXA25X_PIC_NSSP },
-    { 0x41500000, PXA26X_PIC_ASSP },
-    { 0, 0 }
-};
-#endif
-
-static PXASSPDef pxa27x_ssp[] = {
-    { 0x41000000, PXA2XX_PIC_SSP },
-    { 0x41700000, PXA27X_PIC_SSP2 },
-    { 0x41900000, PXA2XX_PIC_SSP3 },
-    { 0, 0 }
-};
-
-#define PMCR	0x00	/* Power Manager Control register */
-#define PSSR	0x04	/* Power Manager Sleep Status register */
-#define PSPR	0x08	/* Power Manager Scratch-Pad register */
-#define PWER	0x0c	/* Power Manager Wake-Up Enable register */
-#define PRER	0x10	/* Power Manager Rising-Edge Detect Enable register */
-#define PFER	0x14	/* Power Manager Falling-Edge Detect Enable register */
-#define PEDR	0x18	/* Power Manager Edge-Detect Status register */
-#define PCFR	0x1c	/* Power Manager General Configuration register */
-#define PGSR0	0x20	/* Power Manager GPIO Sleep-State register 0 */
-#define PGSR1	0x24	/* Power Manager GPIO Sleep-State register 1 */
-#define PGSR2	0x28	/* Power Manager GPIO Sleep-State register 2 */
-#define PGSR3	0x2c	/* Power Manager GPIO Sleep-State register 3 */
-#define RCSR	0x30	/* Reset Controller Status register */
-#define PSLR	0x34	/* Power Manager Sleep Configuration register */
-#define PTSR	0x38	/* Power Manager Standby Configuration register */
-#define PVCR	0x40	/* Power Manager Voltage Change Control register */
-#define PUCR	0x4c	/* Power Manager USIM Card Control/Status register */
-#define PKWR	0x50	/* Power Manager Keyboard Wake-Up Enable register */
-#define PKSR	0x54	/* Power Manager Keyboard Level-Detect Status */
-#define PCMD0	0x80	/* Power Manager I2C Command register File 0 */
-#define PCMD31	0xfc	/* Power Manager I2C Command register File 31 */
-
-static uint64_t pxa2xx_pm_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-
-    switch (addr) {
-    case PMCR ... PCMD31:
-        if (addr & 3)
-            goto fail;
-
-        return s->pm_regs[addr >> 2];
-    default:
-    fail:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_pm_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-
-    switch (addr) {
-    case PMCR:
-        /* Clear the write-one-to-clear bits... */
-        s->pm_regs[addr >> 2] &= ~(value & 0x2a);
-        /* ...and set the plain r/w bits */
-        s->pm_regs[addr >> 2] &= ~0x15;
-        s->pm_regs[addr >> 2] |= value & 0x15;
-        break;
-
-    case PSSR:	/* Read-clean registers */
-    case RCSR:
-    case PKSR:
-        s->pm_regs[addr >> 2] &= ~value;
-        break;
-
-    default:	/* Read-write registers */
-        if (!(addr & 3)) {
-            s->pm_regs[addr >> 2] = value;
-            break;
-        }
-
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-}
-
-static const MemoryRegionOps pxa2xx_pm_ops = {
-    .read = pxa2xx_pm_read,
-    .write = pxa2xx_pm_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-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 */
-#define OSCC	0x08	/* Oscillator Configuration register */
-#define CCSR	0x0c	/* Core Clock Status register */
-
-static uint64_t pxa2xx_cm_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-
-    switch (addr) {
-    case CCCR:
-    case CKEN:
-    case OSCC:
-        return s->cm_regs[addr >> 2];
-
-    case CCSR:
-        return s->cm_regs[CCCR >> 2] | (3 << 28);
-
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_cm_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-
-    switch (addr) {
-    case CCCR:
-    case CKEN:
-        s->cm_regs[addr >> 2] = value;
-        break;
-
-    case OSCC:
-        s->cm_regs[addr >> 2] &= ~0x6c;
-        s->cm_regs[addr >> 2] |= value & 0x6e;
-        if ((value >> 1) & 1)			/* OON */
-            s->cm_regs[addr >> 2] |= 1 << 0;	/* Oscillator is now stable */
-        break;
-
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-}
-
-static const MemoryRegionOps pxa2xx_cm_ops = {
-    .read = pxa2xx_cm_read,
-    .write = pxa2xx_cm_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-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 int pxa2xx_clkcfg_read(CPUARMState *env, const ARMCPRegInfo *ri,
-                              uint64_t *value)
-{
-    PXA2xxState *s = (PXA2xxState *)ri->opaque;
-    *value = s->clkcfg;
-    return 0;
-}
-
-static int pxa2xx_clkcfg_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                               uint64_t value)
-{
-    PXA2xxState *s = (PXA2xxState *)ri->opaque;
-    s->clkcfg = value & 0xf;
-    if (value & 2) {
-        printf("%s: CPU frequency change attempt\n", __func__);
-    }
-    return 0;
-}
-
-static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                                uint64_t value)
-{
-    PXA2xxState *s = (PXA2xxState *)ri->opaque;
-    static const char *pwrmode[8] = {
-        "Normal", "Idle", "Deep-idle", "Standby",
-        "Sleep", "reserved (!)", "reserved (!)", "Deep-sleep",
-    };
-
-    if (value & 8) {
-        printf("%s: CPU voltage change attempt\n", __func__);
-    }
-    switch (value & 7) {
-    case 0:
-        /* Do nothing */
-        break;
-
-    case 1:
-        /* Idle */
-        if (!(s->cm_regs[CCCR >> 2] & (1 << 31))) { /* CPDIS */
-            cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
-            break;
-        }
-        /* Fall through.  */
-
-    case 2:
-        /* Deep-Idle */
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HALT);
-        s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
-        goto message;
-
-    case 3:
-        s->cpu->env.uncached_cpsr =
-            ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
-        s->cpu->env.cp15.c1_sys = 0;
-        s->cpu->env.cp15.c1_coproc = 0;
-        s->cpu->env.cp15.c2_base0 = 0;
-        s->cpu->env.cp15.c3 = 0;
-        s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */
-        s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
-
-        /*
-         * The scratch-pad register is almost universally used
-         * for storing the return address on suspend.  For the
-         * lack of a resuming bootloader, perform a jump
-         * directly to that address.
-         */
-        memset(s->cpu->env.regs, 0, 4 * 15);
-        s->cpu->env.regs[15] = s->pm_regs[PSPR >> 2];
-
-#if 0
-        buffer = 0xe59ff000; /* ldr     pc, [pc, #0] */
-        cpu_physical_memory_write(0, &buffer, 4);
-        buffer = s->pm_regs[PSPR >> 2];
-        cpu_physical_memory_write(8, &buffer, 4);
-#endif
-
-        /* Suspend */
-        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
-
-        goto message;
-
-    default:
-    message:
-        printf("%s: machine entered %s mode\n", __func__,
-               pwrmode[value & 7]);
-    }
-
-    return 0;
-}
-
-static int pxa2xx_cppmnc_read(CPUARMState *env, const ARMCPRegInfo *ri,
-                              uint64_t *value)
-{
-    PXA2xxState *s = (PXA2xxState *)ri->opaque;
-    *value = s->pmnc;
-    return 0;
-}
-
-static int pxa2xx_cppmnc_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                               uint64_t value)
-{
-    PXA2xxState *s = (PXA2xxState *)ri->opaque;
-    s->pmnc = value;
-    return 0;
-}
-
-static int pxa2xx_cpccnt_read(CPUARMState *env, const ARMCPRegInfo *ri,
-                              uint64_t *value)
-{
-    PXA2xxState *s = (PXA2xxState *)ri->opaque;
-    if (s->pmnc & 1) {
-        *value = qemu_get_clock_ns(vm_clock);
-    } else {
-        *value = 0;
-    }
-    return 0;
-}
-
-static const ARMCPRegInfo pxa_cp_reginfo[] = {
-    /* cp14 crm==1: perf registers */
-    { .name = "CPPMNC", .cp = 14, .crn = 0, .crm = 1, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW,
-      .readfn = pxa2xx_cppmnc_read, .writefn = pxa2xx_cppmnc_write },
-    { .name = "CPCCNT", .cp = 14, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW,
-      .readfn = pxa2xx_cpccnt_read, .writefn = arm_cp_write_ignore },
-    { .name = "CPINTEN", .cp = 14, .crn = 4, .crm = 1, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    { .name = "CPFLAG", .cp = 14, .crn = 5, .crm = 1, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    { .name = "CPEVTSEL", .cp = 14, .crn = 8, .crm = 1, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    /* cp14 crm==2: performance count registers */
-    { .name = "CPPMN0", .cp = 14, .crn = 0, .crm = 2, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    { .name = "CPPMN1", .cp = 14, .crn = 1, .crm = 2, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    { .name = "CPPMN2", .cp = 14, .crn = 2, .crm = 2, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    { .name = "CPPMN3", .cp = 14, .crn = 2, .crm = 3, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    /* cp14 crn==6: CLKCFG */
-    { .name = "CLKCFG", .cp = 14, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW,
-      .readfn = pxa2xx_clkcfg_read, .writefn = pxa2xx_clkcfg_write },
-    /* cp14 crn==7: PWRMODE */
-    { .name = "PWRMODE", .cp = 14, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW,
-      .readfn = arm_cp_read_zero, .writefn = pxa2xx_pwrmode_write },
-    REGINFO_SENTINEL
-};
-
-static void pxa2xx_setup_cp14(PXA2xxState *s)
-{
-    define_arm_cp_regs_with_opaque(s->cpu, pxa_cp_reginfo, s);
-}
-
-#define MDCNFG		0x00	/* SDRAM Configuration register */
-#define MDREFR		0x04	/* SDRAM Refresh Control register */
-#define MSC0		0x08	/* Static Memory Control register 0 */
-#define MSC1		0x0c	/* Static Memory Control register 1 */
-#define MSC2		0x10	/* Static Memory Control register 2 */
-#define MECR		0x14	/* Expansion Memory Bus Config register */
-#define SXCNFG		0x1c	/* Synchronous Static Memory Config register */
-#define MCMEM0		0x28	/* PC Card Memory Socket 0 Timing register */
-#define MCMEM1		0x2c	/* PC Card Memory Socket 1 Timing register */
-#define MCATT0		0x30	/* PC Card Attribute Socket 0 register */
-#define MCATT1		0x34	/* PC Card Attribute Socket 1 register */
-#define MCIO0		0x38	/* PC Card I/O Socket 0 Timing register */
-#define MCIO1		0x3c	/* PC Card I/O Socket 1 Timing register */
-#define MDMRS		0x40	/* SDRAM Mode Register Set Config register */
-#define BOOT_DEF	0x44	/* Boot-time Default Configuration register */
-#define ARB_CNTL	0x48	/* Arbiter Control register */
-#define BSCNTR0		0x4c	/* Memory Buffer Strength Control register 0 */
-#define BSCNTR1		0x50	/* Memory Buffer Strength Control register 1 */
-#define LCDBSCNTR	0x54	/* LCD Buffer Strength Control register */
-#define MDMRSLP		0x58	/* Low Power SDRAM Mode Set Config register */
-#define BSCNTR2		0x5c	/* Memory Buffer Strength Control register 2 */
-#define BSCNTR3		0x60	/* Memory Buffer Strength Control register 3 */
-#define SA1110		0x64	/* SA-1110 Memory Compatibility register */
-
-static uint64_t pxa2xx_mm_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-
-    switch (addr) {
-    case MDCNFG ... SA1110:
-        if ((addr & 3) == 0)
-            return s->mm_regs[addr >> 2];
-
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_mm_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-
-    switch (addr) {
-    case MDCNFG ... SA1110:
-        if ((addr & 3) == 0) {
-            s->mm_regs[addr >> 2] = value;
-            break;
-        }
-
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-}
-
-static const MemoryRegionOps pxa2xx_mm_ops = {
-    .read = pxa2xx_mm_read,
-    .write = pxa2xx_mm_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-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 {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    qemu_irq irq;
-    int enable;
-    SSIBus *bus;
-
-    uint32_t sscr[2];
-    uint32_t sspsp;
-    uint32_t ssto;
-    uint32_t ssitr;
-    uint32_t sssr;
-    uint8_t sstsa;
-    uint8_t ssrsa;
-    uint8_t ssacd;
-
-    uint32_t rx_fifo[16];
-    int rx_level;
-    int rx_start;
-} PXA2xxSSPState;
-
-#define SSCR0	0x00	/* SSP Control register 0 */
-#define SSCR1	0x04	/* SSP Control register 1 */
-#define SSSR	0x08	/* SSP Status register */
-#define SSITR	0x0c	/* SSP Interrupt Test register */
-#define SSDR	0x10	/* SSP Data register */
-#define SSTO	0x28	/* SSP Time-Out register */
-#define SSPSP	0x2c	/* SSP Programmable Serial Protocol register */
-#define SSTSA	0x30	/* SSP TX Time Slot Active register */
-#define SSRSA	0x34	/* SSP RX Time Slot Active register */
-#define SSTSS	0x38	/* SSP Time Slot Status register */
-#define SSACD	0x3c	/* SSP Audio Clock Divider 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_RIM	(1 << 22)
-#define SSCR0_TIM	(1 << 23)
-#define SSCR0_MOD	(1 << 31)
-#define SSCR0_DSS(x)	(((((x) >> 16) & 0x10) | ((x) & 0xf)) + 1)
-#define SSCR1_RIE	(1 << 0)
-#define SSCR1_TIE	(1 << 1)
-#define SSCR1_LBM	(1 << 2)
-#define SSCR1_MWDS	(1 << 5)
-#define SSCR1_TFT(x)	((((x) >> 6) & 0xf) + 1)
-#define SSCR1_RFT(x)	((((x) >> 10) & 0xf) + 1)
-#define SSCR1_EFWR	(1 << 14)
-#define SSCR1_PINTE	(1 << 18)
-#define SSCR1_TINTE	(1 << 19)
-#define SSCR1_RSRE	(1 << 20)
-#define SSCR1_TSRE	(1 << 21)
-#define SSCR1_EBCEI	(1 << 29)
-#define SSITR_INT	(7 << 5)
-#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_PINT	(1 << 18)
-#define SSSR_TINT	(1 << 19)
-#define SSSR_EOC	(1 << 20)
-#define SSSR_TUR	(1 << 21)
-#define SSSR_BCE	(1 << 23)
-#define SSSR_RW		0x00bc0080
-
-static void pxa2xx_ssp_int_update(PXA2xxSSPState *s)
-{
-    int level = 0;
-
-    level |= s->ssitr & SSITR_INT;
-    level |= (s->sssr & SSSR_BCE)  &&  (s->sscr[1] & SSCR1_EBCEI);
-    level |= (s->sssr & SSSR_TUR)  && !(s->sscr[0] & SSCR0_TIM);
-    level |= (s->sssr & SSSR_EOC)  &&  (s->sssr & (SSSR_TINT | SSSR_PINT));
-    level |= (s->sssr & SSSR_TINT) &&  (s->sscr[1] & SSCR1_TINTE);
-    level |= (s->sssr & SSSR_PINT) &&  (s->sscr[1] & SSCR1_PINTE);
-    level |= (s->sssr & SSSR_ROR)  && !(s->sscr[0] & SSCR0_RIM);
-    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 pxa2xx_ssp_fifo_update(PXA2xxSSPState *s)
-{
-    s->sssr &= ~(0xf << 12);	/* Clear RFL */
-    s->sssr &= ~(0xf << 8);	/* Clear TFL */
-    s->sssr &= ~SSSR_TFS;
-    s->sssr &= ~SSSR_TNF;
-    if (s->enable) {
-        s->sssr |= ((s->rx_level - 1) & 0xf) << 12;
-        if (s->rx_level >= SSCR1_RFT(s->sscr[1]))
-            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;
-    }
-
-    pxa2xx_ssp_int_update(s);
-}
-
-static uint64_t pxa2xx_ssp_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
-    uint32_t retval;
-
-    switch (addr) {
-    case SSCR0:
-        return s->sscr[0];
-    case SSCR1:
-        return s->sscr[1];
-    case SSPSP:
-        return s->sspsp;
-    case SSTO:
-        return s->ssto;
-    case SSITR:
-        return s->ssitr;
-    case SSSR:
-        return s->sssr | s->ssitr;
-    case SSDR:
-        if (!s->enable)
-            return 0xffffffff;
-        if (s->rx_level < 1) {
-            printf("%s: SSP Rx Underrun\n", __FUNCTION__);
-            return 0xffffffff;
-        }
-        s->rx_level --;
-        retval = s->rx_fifo[s->rx_start ++];
-        s->rx_start &= 0xf;
-        pxa2xx_ssp_fifo_update(s);
-        return retval;
-    case SSTSA:
-        return s->sstsa;
-    case SSRSA:
-        return s->ssrsa;
-    case SSTSS:
-        return 0;
-    case SSACD:
-        return s->ssacd;
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_ssp_write(void *opaque, hwaddr addr,
-                             uint64_t value64, unsigned size)
-{
-    PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
-    uint32_t value = value64;
-
-    switch (addr) {
-    case SSCR0:
-        s->sscr[0] = value & 0xc7ffffff;
-        s->enable = value & SSCR0_SSE;
-        if (value & SSCR0_MOD)
-            printf("%s: Attempt to use network mode\n", __FUNCTION__);
-        if (s->enable && SSCR0_DSS(value) < 4)
-            printf("%s: Wrong data size: %i bits\n", __FUNCTION__,
-                            SSCR0_DSS(value));
-        if (!(value & SSCR0_SSE)) {
-            s->sssr = 0;
-            s->ssitr = 0;
-            s->rx_level = 0;
-        }
-        pxa2xx_ssp_fifo_update(s);
-        break;
-
-    case SSCR1:
-        s->sscr[1] = value;
-        if (value & (SSCR1_LBM | SSCR1_EFWR))
-            printf("%s: Attempt to use SSP test mode\n", __FUNCTION__);
-        pxa2xx_ssp_fifo_update(s);
-        break;
-
-    case SSPSP:
-        s->sspsp = value;
-        break;
-
-    case SSTO:
-        s->ssto = value;
-        break;
-
-    case SSITR:
-        s->ssitr = value & SSITR_INT;
-        pxa2xx_ssp_int_update(s);
-        break;
-
-    case SSSR:
-        s->sssr &= ~(value & SSSR_RW);
-        pxa2xx_ssp_int_update(s);
-        break;
-
-    case SSDR:
-        if (SSCR0_UWIRE(s->sscr[0])) {
-            if (s->sscr[1] & SSCR1_MWDS)
-                value &= 0xffff;
-            else
-                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->enable) {
-            uint32_t readval;
-            readval = ssi_transfer(s->bus, value);
-            if (s->rx_level < 0x10) {
-                s->rx_fifo[(s->rx_start + s->rx_level ++) & 0xf] = readval;
-            } else {
-                s->sssr |= SSSR_ROR;
-            }
-        }
-        pxa2xx_ssp_fifo_update(s);
-        break;
-
-    case SSTSA:
-        s->sstsa = value;
-        break;
-
-    case SSRSA:
-        s->ssrsa = value;
-        break;
-
-    case SSACD:
-        s->ssacd = value;
-        break;
-
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-}
-
-static const MemoryRegionOps pxa2xx_ssp_ops = {
-    .read = pxa2xx_ssp_read,
-    .write = pxa2xx_ssp_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void pxa2xx_ssp_save(QEMUFile *f, void *opaque)
-{
-    PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
-    int i;
-
-    qemu_put_be32(f, s->enable);
-
-    qemu_put_be32s(f, &s->sscr[0]);
-    qemu_put_be32s(f, &s->sscr[1]);
-    qemu_put_be32s(f, &s->sspsp);
-    qemu_put_be32s(f, &s->ssto);
-    qemu_put_be32s(f, &s->ssitr);
-    qemu_put_be32s(f, &s->sssr);
-    qemu_put_8s(f, &s->sstsa);
-    qemu_put_8s(f, &s->ssrsa);
-    qemu_put_8s(f, &s->ssacd);
-
-    qemu_put_byte(f, s->rx_level);
-    for (i = 0; i < s->rx_level; i ++)
-        qemu_put_byte(f, s->rx_fifo[(s->rx_start + i) & 0xf]);
-}
-
-static int pxa2xx_ssp_load(QEMUFile *f, void *opaque, int version_id)
-{
-    PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
-    int i;
-
-    s->enable = qemu_get_be32(f);
-
-    qemu_get_be32s(f, &s->sscr[0]);
-    qemu_get_be32s(f, &s->sscr[1]);
-    qemu_get_be32s(f, &s->sspsp);
-    qemu_get_be32s(f, &s->ssto);
-    qemu_get_be32s(f, &s->ssitr);
-    qemu_get_be32s(f, &s->sssr);
-    qemu_get_8s(f, &s->sstsa);
-    qemu_get_8s(f, &s->ssrsa);
-    qemu_get_8s(f, &s->ssacd);
-
-    s->rx_level = qemu_get_byte(f);
-    s->rx_start = 0;
-    for (i = 0; i < s->rx_level; i ++)
-        s->rx_fifo[i] = qemu_get_byte(f);
-
-    return 0;
-}
-
-static int pxa2xx_ssp_init(SysBusDevice *dev)
-{
-    PXA2xxSSPState *s = FROM_SYSBUS(PXA2xxSSPState, dev);
-
-    sysbus_init_irq(dev, &s->irq);
-
-    memory_region_init_io(&s->iomem, &pxa2xx_ssp_ops, s, "pxa2xx-ssp", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    register_savevm(&dev->qdev, "pxa2xx_ssp", -1, 0,
-                    pxa2xx_ssp_save, pxa2xx_ssp_load, s);
-
-    s->bus = ssi_create_bus(&dev->qdev, "ssi");
-    return 0;
-}
-
-/* Real-Time Clock */
-#define RCNR		0x00	/* RTC Counter register */
-#define RTAR		0x04	/* RTC Alarm register */
-#define RTSR		0x08	/* RTC Status register */
-#define RTTR		0x0c	/* RTC Timer Trim register */
-#define RDCR		0x10	/* RTC Day Counter register */
-#define RYCR		0x14	/* RTC Year Counter register */
-#define RDAR1		0x18	/* RTC Wristwatch Day Alarm register 1 */
-#define RYAR1		0x1c	/* RTC Wristwatch Year Alarm register 1 */
-#define RDAR2		0x20	/* RTC Wristwatch Day Alarm register 2 */
-#define RYAR2		0x24	/* RTC Wristwatch Year Alarm register 2 */
-#define SWCR		0x28	/* RTC Stopwatch Counter register */
-#define SWAR1		0x2c	/* RTC Stopwatch Alarm register 1 */
-#define SWAR2		0x30	/* RTC Stopwatch Alarm register 2 */
-#define RTCPICR		0x34	/* RTC Periodic Interrupt Counter register */
-#define PIAR		0x38	/* RTC Periodic Interrupt Alarm register */
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    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(PXA2xxRTCState *s)
-{
-    int64_t rt = qemu_get_clock_ms(rtc_clock);
-    s->last_rcnr += ((rt - s->last_hz) << 15) /
-            (1000 * ((s->rttr & 0xffff) + 1));
-    s->last_rdcr += ((rt - s->last_hz) << 15) /
-            (1000 * ((s->rttr & 0xffff) + 1));
-    s->last_hz = rt;
-}
-
-static void pxa2xx_rtc_swupdate(PXA2xxRTCState *s)
-{
-    int64_t rt = qemu_get_clock_ms(rtc_clock);
-    if (s->rtsr & (1 << 12))
-        s->last_swcr += (rt - s->last_sw) / 10;
-    s->last_sw = rt;
-}
-
-static void pxa2xx_rtc_piupdate(PXA2xxRTCState *s)
-{
-    int64_t rt = qemu_get_clock_ms(rtc_clock);
-    if (s->rtsr & (1 << 15))
-        s->last_swcr += rt - s->last_pi;
-    s->last_pi = rt;
-}
-
-static inline void pxa2xx_rtc_alarm_update(PXA2xxRTCState *s,
-                uint32_t rtsr)
-{
-    if ((rtsr & (1 << 2)) && !(rtsr & (1 << 0)))
-        qemu_mod_timer(s->rtc_hz, s->last_hz +
-                (((s->rtar - s->last_rcnr) * 1000 *
-                  ((s->rttr & 0xffff) + 1)) >> 15));
-    else
-        qemu_del_timer(s->rtc_hz);
-
-    if ((rtsr & (1 << 5)) && !(rtsr & (1 << 4)))
-        qemu_mod_timer(s->rtc_rdal1, s->last_hz +
-                (((s->rdar1 - s->last_rdcr) * 1000 *
-                  ((s->rttr & 0xffff) + 1)) >> 15)); /* TODO: fixup */
-    else
-        qemu_del_timer(s->rtc_rdal1);
-
-    if ((rtsr & (1 << 7)) && !(rtsr & (1 << 6)))
-        qemu_mod_timer(s->rtc_rdal2, s->last_hz +
-                (((s->rdar2 - s->last_rdcr) * 1000 *
-                  ((s->rttr & 0xffff) + 1)) >> 15)); /* TODO: fixup */
-    else
-        qemu_del_timer(s->rtc_rdal2);
-
-    if ((rtsr & 0x1200) == 0x1200 && !(rtsr & (1 << 8)))
-        qemu_mod_timer(s->rtc_swal1, s->last_sw +
-                        (s->swar1 - s->last_swcr) * 10); /* TODO: fixup */
-    else
-        qemu_del_timer(s->rtc_swal1);
-
-    if ((rtsr & 0x1800) == 0x1800 && !(rtsr & (1 << 10)))
-        qemu_mod_timer(s->rtc_swal2, s->last_sw +
-                        (s->swar2 - s->last_swcr) * 10); /* TODO: fixup */
-    else
-        qemu_del_timer(s->rtc_swal2);
-
-    if ((rtsr & 0xc000) == 0xc000 && !(rtsr & (1 << 13)))
-        qemu_mod_timer(s->rtc_pi, s->last_pi +
-                        (s->piar & 0xffff) - s->last_rtcpicr);
-    else
-        qemu_del_timer(s->rtc_pi);
-}
-
-static inline void pxa2xx_rtc_hz_tick(void *opaque)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-    s->rtsr |= (1 << 0);
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static inline void pxa2xx_rtc_rdal1_tick(void *opaque)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-    s->rtsr |= (1 << 4);
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static inline void pxa2xx_rtc_rdal2_tick(void *opaque)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-    s->rtsr |= (1 << 6);
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static inline void pxa2xx_rtc_swal1_tick(void *opaque)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-    s->rtsr |= (1 << 8);
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static inline void pxa2xx_rtc_swal2_tick(void *opaque)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-    s->rtsr |= (1 << 10);
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static inline void pxa2xx_rtc_pi_tick(void *opaque)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-    s->rtsr |= (1 << 13);
-    pxa2xx_rtc_piupdate(s);
-    s->last_rtcpicr = 0;
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static uint64_t pxa2xx_rtc_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-
-    switch (addr) {
-    case RTTR:
-        return s->rttr;
-    case RTSR:
-        return s->rtsr;
-    case RTAR:
-        return s->rtar;
-    case RDAR1:
-        return s->rdar1;
-    case RDAR2:
-        return s->rdar2;
-    case RYAR1:
-        return s->ryar1;
-    case RYAR2:
-        return s->ryar2;
-    case SWAR1:
-        return s->swar1;
-    case SWAR2:
-        return s->swar2;
-    case PIAR:
-        return s->piar;
-    case RCNR:
-        return s->last_rcnr + ((qemu_get_clock_ms(rtc_clock) - s->last_hz) << 15) /
-                (1000 * ((s->rttr & 0xffff) + 1));
-    case RDCR:
-        return s->last_rdcr + ((qemu_get_clock_ms(rtc_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_ms(rtc_clock) - s->last_sw) / 10;
-        else
-            return s->last_swcr;
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_rtc_write(void *opaque, hwaddr addr,
-                             uint64_t value64, unsigned size)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-    uint32_t value = value64;
-
-    switch (addr) {
-    case RTTR:
-        if (!(s->rttr & (1 << 31))) {
-            pxa2xx_rtc_hzupdate(s);
-            s->rttr = value;
-            pxa2xx_rtc_alarm_update(s, s->rtsr);
-        }
-        break;
-
-    case RTSR:
-        if ((s->rtsr ^ value) & (1 << 15))
-            pxa2xx_rtc_piupdate(s);
-
-        if ((s->rtsr ^ value) & (1 << 12))
-            pxa2xx_rtc_swupdate(s);
-
-        if (((s->rtsr ^ value) & 0x4aac) | (value & ~0xdaac))
-            pxa2xx_rtc_alarm_update(s, value);
-
-        s->rtsr = (value & 0xdaac) | (s->rtsr & ~(value & ~0xdaac));
-        pxa2xx_rtc_int_update(s);
-        break;
-
-    case RTAR:
-        s->rtar = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RDAR1:
-        s->rdar1 = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RDAR2:
-        s->rdar2 = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RYAR1:
-        s->ryar1 = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RYAR2:
-        s->ryar2 = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case SWAR1:
-        pxa2xx_rtc_swupdate(s);
-        s->swar1 = value;
-        s->last_swcr = 0;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case SWAR2:
-        s->swar2 = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case PIAR:
-        s->piar = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RCNR:
-        pxa2xx_rtc_hzupdate(s);
-        s->last_rcnr = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RDCR:
-        pxa2xx_rtc_hzupdate(s);
-        s->last_rdcr = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RYCR:
-        s->last_rycr = value;
-        break;
-
-    case SWCR:
-        pxa2xx_rtc_swupdate(s);
-        s->last_swcr = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RTCPICR:
-        pxa2xx_rtc_piupdate(s);
-        s->last_rtcpicr = value & 0xffff;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-    }
-}
-
-static const MemoryRegionOps pxa2xx_rtc_ops = {
-    .read = pxa2xx_rtc_read,
-    .write = pxa2xx_rtc_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int pxa2xx_rtc_init(SysBusDevice *dev)
-{
-    PXA2xxRTCState *s = FROM_SYSBUS(PXA2xxRTCState, dev);
-    struct tm tm;
-    int wom;
-
-    s->rttr = 0x7fff;
-    s->rtsr = 0;
-
-    qemu_get_timedate(&tm, 0);
-    wom = ((tm.tm_mday - 1) / 7) + 1;
-
-    s->last_rcnr = (uint32_t) mktimegm(&tm);
-    s->last_rdcr = (wom << 20) | ((tm.tm_wday + 1) << 17) |
-            (tm.tm_hour << 12) | (tm.tm_min << 6) | tm.tm_sec;
-    s->last_rycr = ((tm.tm_year + 1900) << 9) |
-            ((tm.tm_mon + 1) << 5) | tm.tm_mday;
-    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_ms(rtc_clock);
-
-    s->rtc_hz    = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_hz_tick,    s);
-    s->rtc_rdal1 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_rdal1_tick, s);
-    s->rtc_rdal2 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_rdal2_tick, s);
-    s->rtc_swal1 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_swal1_tick, s);
-    s->rtc_swal2 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_swal2_tick, s);
-    s->rtc_pi    = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_pi_tick,    s);
-
-    sysbus_init_irq(dev, &s->rtc_irq);
-
-    memory_region_init_io(&s->iomem, &pxa2xx_rtc_ops, s, "pxa2xx-rtc", 0x10000);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    return 0;
-}
-
-static void pxa2xx_rtc_pre_save(void *opaque)
-{
-    PXA2xxRTCState *s = (PXA2xxRTCState *) opaque;
-
-    pxa2xx_rtc_hzupdate(s);
-    pxa2xx_rtc_piupdate(s);
-    pxa2xx_rtc_swupdate(s);
-}
-
-static int pxa2xx_rtc_post_load(void *opaque, int version_id)
-{
-    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 void pxa2xx_rtc_sysbus_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = pxa2xx_rtc_init;
-    dc->desc = "PXA2xx RTC Controller";
-    dc->vmsd = &vmstate_pxa2xx_rtc_regs;
-}
-
-static const TypeInfo pxa2xx_rtc_sysbus_info = {
-    .name          = "pxa2xx_rtc",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(PXA2xxRTCState),
-    .class_init    = pxa2xx_rtc_sysbus_class_init,
-};
-
-/* I2C Interface */
-typedef struct {
-    I2CSlave i2c;
-    PXA2xxI2CState *host;
-} PXA2xxI2CSlaveState;
-
-struct PXA2xxI2CState {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    PXA2xxI2CSlaveState *slave;
-    i2c_bus *bus;
-    qemu_irq irq;
-    uint32_t offset;
-    uint32_t region_size;
-
-    uint16_t control;
-    uint16_t status;
-    uint8_t ibmr;
-    uint8_t data;
-};
-
-#define IBMR	0x80	/* I2C Bus Monitor register */
-#define IDBR	0x88	/* I2C Data Buffer register */
-#define ICR	0x90	/* I2C Control register */
-#define ISR	0x98	/* I2C Status register */
-#define ISAR	0xa0	/* I2C Slave Address register */
-
-static void pxa2xx_i2c_update(PXA2xxI2CState *s)
-{
-    uint16_t level = 0;
-    level |= s->status & s->control & (1 << 10);		/* BED */
-    level |= (s->status & (1 << 7)) && (s->control & (1 << 9));	/* IRF */
-    level |= (s->status & (1 << 6)) && (s->control & (1 << 8));	/* ITE */
-    level |= s->status & (1 << 9);				/* SAD */
-    qemu_set_irq(s->irq, !!level);
-}
-
-/* These are only stubs now.  */
-static void pxa2xx_i2c_event(I2CSlave *i2c, enum i2c_event event)
-{
-    PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
-    PXA2xxI2CState *s = slave->host;
-
-    switch (event) {
-    case I2C_START_SEND:
-        s->status |= (1 << 9);				/* set SAD */
-        s->status &= ~(1 << 0);				/* clear RWM */
-        break;
-    case I2C_START_RECV:
-        s->status |= (1 << 9);				/* set SAD */
-        s->status |= 1 << 0;				/* set RWM */
-        break;
-    case I2C_FINISH:
-        s->status |= (1 << 4);				/* set SSD */
-        break;
-    case I2C_NACK:
-        s->status |= 1 << 1;				/* set ACKNAK */
-        break;
-    }
-    pxa2xx_i2c_update(s);
-}
-
-static int pxa2xx_i2c_rx(I2CSlave *i2c)
-{
-    PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
-    PXA2xxI2CState *s = slave->host;
-    if ((s->control & (1 << 14)) || !(s->control & (1 << 6)))
-        return 0;
-
-    if (s->status & (1 << 0)) {			/* RWM */
-        s->status |= 1 << 6;			/* set ITE */
-    }
-    pxa2xx_i2c_update(s);
-
-    return s->data;
-}
-
-static int pxa2xx_i2c_tx(I2CSlave *i2c, uint8_t data)
-{
-    PXA2xxI2CSlaveState *slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, i2c);
-    PXA2xxI2CState *s = slave->host;
-    if ((s->control & (1 << 14)) || !(s->control & (1 << 6)))
-        return 1;
-
-    if (!(s->status & (1 << 0))) {		/* RWM */
-        s->status |= 1 << 7;			/* set IRF */
-        s->data = data;
-    }
-    pxa2xx_i2c_update(s);
-
-    return 1;
-}
-
-static uint64_t pxa2xx_i2c_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    PXA2xxI2CState *s = (PXA2xxI2CState *) opaque;
-
-    addr -= s->offset;
-    switch (addr) {
-    case ICR:
-        return s->control;
-    case ISR:
-        return s->status | (i2c_bus_busy(s->bus) << 2);
-    case ISAR:
-        return s->slave->i2c.address;
-    case IDBR:
-        return s->data;
-    case IBMR:
-        if (s->status & (1 << 2))
-            s->ibmr ^= 3;	/* Fake SCL and SDA pin changes */
-        else
-            s->ibmr = 0;
-        return s->ibmr;
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_i2c_write(void *opaque, hwaddr addr,
-                             uint64_t value64, unsigned size)
-{
-    PXA2xxI2CState *s = (PXA2xxI2CState *) opaque;
-    uint32_t value = value64;
-    int ack;
-
-    addr -= s->offset;
-    switch (addr) {
-    case ICR:
-        s->control = value & 0xfff7;
-        if ((value & (1 << 3)) && (value & (1 << 6))) {	/* TB and IUE */
-            /* TODO: slave mode */
-            if (value & (1 << 0)) {			/* START condition */
-                if (s->data & 1)
-                    s->status |= 1 << 0;		/* set RWM */
-                else
-                    s->status &= ~(1 << 0);		/* clear RWM */
-                ack = !i2c_start_transfer(s->bus, s->data >> 1, s->data & 1);
-            } else {
-                if (s->status & (1 << 0)) {		/* RWM */
-                    s->data = i2c_recv(s->bus);
-                    if (value & (1 << 2))		/* ACKNAK */
-                        i2c_nack(s->bus);
-                    ack = 1;
-                } else
-                    ack = !i2c_send(s->bus, s->data);
-            }
-
-            if (value & (1 << 1))			/* STOP condition */
-                i2c_end_transfer(s->bus);
-
-            if (ack) {
-                if (value & (1 << 0))			/* START condition */
-                    s->status |= 1 << 6;		/* set ITE */
-                else
-                    if (s->status & (1 << 0))		/* RWM */
-                        s->status |= 1 << 7;		/* set IRF */
-                    else
-                        s->status |= 1 << 6;		/* set ITE */
-                s->status &= ~(1 << 1);			/* clear ACKNAK */
-            } else {
-                s->status |= 1 << 6;			/* set ITE */
-                s->status |= 1 << 10;			/* set BED */
-                s->status |= 1 << 1;			/* set ACKNAK */
-            }
-        }
-        if (!(value & (1 << 3)) && (value & (1 << 6)))	/* !TB and IUE */
-            if (value & (1 << 4))			/* MA */
-                i2c_end_transfer(s->bus);
-        pxa2xx_i2c_update(s);
-        break;
-
-    case ISR:
-        s->status &= ~(value & 0x07f0);
-        pxa2xx_i2c_update(s);
-        break;
-
-    case ISAR:
-        i2c_set_slave_address(&s->slave->i2c, value & 0x7f);
-        break;
-
-    case IDBR:
-        s->data = value & 0xff;
-        break;
-
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-    }
-}
-
-static const MemoryRegionOps pxa2xx_i2c_ops = {
-    .read = pxa2xx_i2c_read,
-    .write = pxa2xx_i2c_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_pxa2xx_i2c_slave = {
-    .name = "pxa2xx_i2c_slave",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField []) {
-        VMSTATE_I2C_SLAVE(i2c, PXA2xxI2CSlaveState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription vmstate_pxa2xx_i2c = {
-    .name = "pxa2xx_i2c",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField []) {
-        VMSTATE_UINT16(control, PXA2xxI2CState),
-        VMSTATE_UINT16(status, PXA2xxI2CState),
-        VMSTATE_UINT8(ibmr, PXA2xxI2CState),
-        VMSTATE_UINT8(data, PXA2xxI2CState),
-        VMSTATE_STRUCT_POINTER(slave, PXA2xxI2CState,
-                               vmstate_pxa2xx_i2c_slave, PXA2xxI2CSlaveState *),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int pxa2xx_i2c_slave_init(I2CSlave *i2c)
-{
-    /* Nothing to do.  */
-    return 0;
-}
-
-static void pxa2xx_i2c_slave_class_init(ObjectClass *klass, void *data)
-{
-    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
-
-    k->init = pxa2xx_i2c_slave_init;
-    k->event = pxa2xx_i2c_event;
-    k->recv = pxa2xx_i2c_rx;
-    k->send = pxa2xx_i2c_tx;
-}
-
-static const TypeInfo pxa2xx_i2c_slave_info = {
-    .name          = "pxa2xx-i2c-slave",
-    .parent        = TYPE_I2C_SLAVE,
-    .instance_size = sizeof(PXA2xxI2CSlaveState),
-    .class_init    = pxa2xx_i2c_slave_class_init,
-};
-
-PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base,
-                qemu_irq irq, uint32_t region_size)
-{
-    DeviceState *dev;
-    SysBusDevice *i2c_dev;
-    PXA2xxI2CState *s;
-
-    i2c_dev = SYS_BUS_DEVICE(qdev_create(NULL, "pxa2xx_i2c"));
-    qdev_prop_set_uint32(&i2c_dev->qdev, "size", region_size + 1);
-    qdev_prop_set_uint32(&i2c_dev->qdev, "offset", base & region_size);
-
-    qdev_init_nofail(&i2c_dev->qdev);
-
-    sysbus_mmio_map(i2c_dev, 0, base & ~region_size);
-    sysbus_connect_irq(i2c_dev, 0, irq);
-
-    s = FROM_SYSBUS(PXA2xxI2CState, i2c_dev);
-    /* FIXME: Should the slave device really be on a separate bus?  */
-    dev = i2c_create_slave(i2c_init_bus(NULL, "dummy"), "pxa2xx-i2c-slave", 0);
-    s->slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, I2C_SLAVE(dev));
-    s->slave->host = s;
-
-    return s;
-}
-
-static int pxa2xx_i2c_initfn(SysBusDevice *dev)
-{
-    PXA2xxI2CState *s = FROM_SYSBUS(PXA2xxI2CState, dev);
-
-    s->bus = i2c_init_bus(&dev->qdev, "i2c");
-
-    memory_region_init_io(&s->iomem, &pxa2xx_i2c_ops, s,
-                          "pxa2xx-i2x", s->region_size);
-    sysbus_init_mmio(dev, &s->iomem);
-    sysbus_init_irq(dev, &s->irq);
-
-    return 0;
-}
-
-i2c_bus *pxa2xx_i2c_bus(PXA2xxI2CState *s)
-{
-    return s->bus;
-}
-
-static Property pxa2xx_i2c_properties[] = {
-    DEFINE_PROP_UINT32("size", PXA2xxI2CState, region_size, 0x10000),
-    DEFINE_PROP_UINT32("offset", PXA2xxI2CState, offset, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void pxa2xx_i2c_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = pxa2xx_i2c_initfn;
-    dc->desc = "PXA2xx I2C Bus Controller";
-    dc->vmsd = &vmstate_pxa2xx_i2c;
-    dc->props = pxa2xx_i2c_properties;
-}
-
-static const TypeInfo pxa2xx_i2c_info = {
-    .name          = "pxa2xx_i2c",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(PXA2xxI2CState),
-    .class_init    = pxa2xx_i2c_class_init,
-};
-
-/* PXA Inter-IC Sound Controller */
-static void pxa2xx_i2s_reset(PXA2xxI2SState *i2s)
-{
-    i2s->rx_len = 0;
-    i2s->tx_len = 0;
-    i2s->fifo_len = 0;
-    i2s->clk = 0x1a;
-    i2s->control[0] = 0x00;
-    i2s->control[1] = 0x00;
-    i2s->status = 0x00;
-    i2s->mask = 0x00;
-}
-
-#define SACR_TFTH(val)	((val >> 8) & 0xf)
-#define SACR_RFTH(val)	((val >> 12) & 0xf)
-#define SACR_DREC(val)	(val & (1 << 3))
-#define SACR_DPRL(val)	(val & (1 << 4))
-
-static inline void pxa2xx_i2s_update(PXA2xxI2SState *i2s)
-{
-    int rfs, tfs;
-    rfs = SACR_RFTH(i2s->control[0]) < i2s->rx_len &&
-            !SACR_DREC(i2s->control[1]);
-    tfs = (i2s->tx_len || i2s->fifo_len < SACR_TFTH(i2s->control[0])) &&
-            i2s->enable && !SACR_DPRL(i2s->control[1]);
-
-    qemu_set_irq(i2s->rx_dma, rfs);
-    qemu_set_irq(i2s->tx_dma, tfs);
-
-    i2s->status &= 0xe0;
-    if (i2s->fifo_len < 16 || !i2s->enable)
-        i2s->status |= 1 << 0;			/* TNF */
-    if (i2s->rx_len)
-        i2s->status |= 1 << 1;			/* RNE */
-    if (i2s->enable)
-        i2s->status |= 1 << 2;			/* BSY */
-    if (tfs)
-        i2s->status |= 1 << 3;			/* TFS */
-    if (rfs)
-        i2s->status |= 1 << 4;			/* RFS */
-    if (!(i2s->tx_len && i2s->enable))
-        i2s->status |= i2s->fifo_len << 8;	/* TFL */
-    i2s->status |= MAX(i2s->rx_len, 0xf) << 12;	/* RFL */
-
-    qemu_set_irq(i2s->irq, i2s->status & i2s->mask);
-}
-
-#define SACR0	0x00	/* Serial Audio Global Control register */
-#define SACR1	0x04	/* Serial Audio I2S/MSB-Justified Control register */
-#define SASR0	0x0c	/* Serial Audio Interface and FIFO Status register */
-#define SAIMR	0x14	/* Serial Audio Interrupt Mask register */
-#define SAICR	0x18	/* Serial Audio Interrupt Clear register */
-#define SADIV	0x60	/* Serial Audio Clock Divider register */
-#define SADR	0x80	/* Serial Audio Data register */
-
-static uint64_t pxa2xx_i2s_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
-
-    switch (addr) {
-    case SACR0:
-        return s->control[0];
-    case SACR1:
-        return s->control[1];
-    case SASR0:
-        return s->status;
-    case SAIMR:
-        return s->mask;
-    case SAICR:
-        return 0;
-    case SADIV:
-        return s->clk;
-    case SADR:
-        if (s->rx_len > 0) {
-            s->rx_len --;
-            pxa2xx_i2s_update(s);
-            return s->codec_in(s->opaque);
-        }
-        return 0;
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_i2s_write(void *opaque, hwaddr addr,
-                             uint64_t value, unsigned size)
-{
-    PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
-    uint32_t *sample;
-
-    switch (addr) {
-    case SACR0:
-        if (value & (1 << 3))				/* RST */
-            pxa2xx_i2s_reset(s);
-        s->control[0] = value & 0xff3d;
-        if (!s->enable && (value & 1) && s->tx_len) {	/* ENB */
-            for (sample = s->fifo; s->fifo_len > 0; s->fifo_len --, sample ++)
-                s->codec_out(s->opaque, *sample);
-            s->status &= ~(1 << 7);			/* I2SOFF */
-        }
-        if (value & (1 << 4))				/* EFWR */
-            printf("%s: Attempt to use special function\n", __FUNCTION__);
-        s->enable = (value & 9) == 1;			/* ENB && !RST*/
-        pxa2xx_i2s_update(s);
-        break;
-    case SACR1:
-        s->control[1] = value & 0x0039;
-        if (value & (1 << 5))				/* ENLBF */
-            printf("%s: Attempt to use loopback function\n", __FUNCTION__);
-        if (value & (1 << 4))				/* DPRL */
-            s->fifo_len = 0;
-        pxa2xx_i2s_update(s);
-        break;
-    case SAIMR:
-        s->mask = value & 0x0078;
-        pxa2xx_i2s_update(s);
-        break;
-    case SAICR:
-        s->status &= ~(value & (3 << 5));
-        pxa2xx_i2s_update(s);
-        break;
-    case SADIV:
-        s->clk = value & 0x007f;
-        break;
-    case SADR:
-        if (s->tx_len && s->enable) {
-            s->tx_len --;
-            pxa2xx_i2s_update(s);
-            s->codec_out(s->opaque, value);
-        } else if (s->fifo_len < 16) {
-            s->fifo[s->fifo_len ++] = value;
-            pxa2xx_i2s_update(s);
-        }
-        break;
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-    }
-}
-
-static const MemoryRegionOps pxa2xx_i2s_ops = {
-    .read = pxa2xx_i2s_read,
-    .write = pxa2xx_i2s_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-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)
-{
-    PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
-    uint32_t *sample;
-
-    /* Signal FIFO errors */
-    if (s->enable && s->tx_len)
-        s->status |= 1 << 5;		/* TUR */
-    if (s->enable && s->rx_len)
-        s->status |= 1 << 6;		/* ROR */
-
-    /* Should be tx - MIN(tx, s->fifo_len) but we don't really need to
-     * handle the cases where it makes a difference.  */
-    s->tx_len = tx - s->fifo_len;
-    s->rx_len = rx;
-    /* Note that is s->codec_out wasn't set, we wouldn't get called.  */
-    if (s->enable)
-        for (sample = s->fifo; s->fifo_len; s->fifo_len --, sample ++)
-            s->codec_out(s->opaque, *sample);
-    pxa2xx_i2s_update(s);
-}
-
-static PXA2xxI2SState *pxa2xx_i2s_init(MemoryRegion *sysmem,
-                hwaddr base,
-                qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma)
-{
-    PXA2xxI2SState *s = (PXA2xxI2SState *)
-            g_malloc0(sizeof(PXA2xxI2SState));
-
-    s->irq = irq;
-    s->rx_dma = rx_dma;
-    s->tx_dma = tx_dma;
-    s->data_req = pxa2xx_i2s_data_req;
-
-    pxa2xx_i2s_reset(s);
-
-    memory_region_init_io(&s->iomem, &pxa2xx_i2s_ops, s,
-                          "pxa2xx-i2s", 0x100000);
-    memory_region_add_subregion(sysmem, base, &s->iomem);
-
-    vmstate_register(NULL, base, &vmstate_pxa2xx_i2s, s);
-
-    return s;
-}
-
-/* PXA Fast Infra-red Communications Port */
-struct PXA2xxFIrState {
-    MemoryRegion iomem;
-    qemu_irq irq;
-    qemu_irq rx_dma;
-    qemu_irq tx_dma;
-    int enable;
-    CharDriverState *chr;
-
-    uint8_t control[3];
-    uint8_t status[2];
-
-    int rx_len;
-    int rx_start;
-    uint8_t rx_fifo[64];
-};
-
-static void pxa2xx_fir_reset(PXA2xxFIrState *s)
-{
-    s->control[0] = 0x00;
-    s->control[1] = 0x00;
-    s->control[2] = 0x00;
-    s->status[0] = 0x00;
-    s->status[1] = 0x00;
-    s->enable = 0;
-}
-
-static inline void pxa2xx_fir_update(PXA2xxFIrState *s)
-{
-    static const int tresh[4] = { 8, 16, 32, 0 };
-    int intr = 0;
-    if ((s->control[0] & (1 << 4)) &&			/* RXE */
-                    s->rx_len >= tresh[s->control[2] & 3])	/* TRIG */
-        s->status[0] |= 1 << 4;				/* RFS */
-    else
-        s->status[0] &= ~(1 << 4);			/* RFS */
-    if (s->control[0] & (1 << 3))			/* TXE */
-        s->status[0] |= 1 << 3;				/* TFS */
-    else
-        s->status[0] &= ~(1 << 3);			/* TFS */
-    if (s->rx_len)
-        s->status[1] |= 1 << 2;				/* RNE */
-    else
-        s->status[1] &= ~(1 << 2);			/* RNE */
-    if (s->control[0] & (1 << 4))			/* RXE */
-        s->status[1] |= 1 << 0;				/* RSY */
-    else
-        s->status[1] &= ~(1 << 0);			/* RSY */
-
-    intr |= (s->control[0] & (1 << 5)) &&		/* RIE */
-            (s->status[0] & (1 << 4));			/* RFS */
-    intr |= (s->control[0] & (1 << 6)) &&		/* TIE */
-            (s->status[0] & (1 << 3));			/* TFS */
-    intr |= (s->control[2] & (1 << 4)) &&		/* TRAIL */
-            (s->status[0] & (1 << 6));			/* EOC */
-    intr |= (s->control[0] & (1 << 2)) &&		/* TUS */
-            (s->status[0] & (1 << 1));			/* TUR */
-    intr |= s->status[0] & 0x25;			/* FRE, RAB, EIF */
-
-    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);
-}
-
-#define ICCR0	0x00	/* FICP Control register 0 */
-#define ICCR1	0x04	/* FICP Control register 1 */
-#define ICCR2	0x08	/* FICP Control register 2 */
-#define ICDR	0x0c	/* FICP Data register */
-#define ICSR0	0x14	/* FICP Status register 0 */
-#define ICSR1	0x18	/* FICP Status register 1 */
-#define ICFOR	0x1c	/* FICP FIFO Occupancy Status register */
-
-static uint64_t pxa2xx_fir_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
-    uint8_t ret;
-
-    switch (addr) {
-    case ICCR0:
-        return s->control[0];
-    case ICCR1:
-        return s->control[1];
-    case ICCR2:
-        return s->control[2];
-    case ICDR:
-        s->status[0] &= ~0x01;
-        s->status[1] &= ~0x72;
-        if (s->rx_len) {
-            s->rx_len --;
-            ret = s->rx_fifo[s->rx_start ++];
-            s->rx_start &= 63;
-            pxa2xx_fir_update(s);
-            return ret;
-        }
-        printf("%s: Rx FIFO underrun.\n", __FUNCTION__);
-        break;
-    case ICSR0:
-        return s->status[0];
-    case ICSR1:
-        return s->status[1] | (1 << 3);			/* TNF */
-    case ICFOR:
-        return s->rx_len;
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_fir_write(void *opaque, hwaddr addr,
-                             uint64_t value64, unsigned size)
-{
-    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
-    uint32_t value = value64;
-    uint8_t ch;
-
-    switch (addr) {
-    case ICCR0:
-        s->control[0] = value;
-        if (!(value & (1 << 4)))			/* RXE */
-            s->rx_len = s->rx_start = 0;
-        if (!(value & (1 << 3))) {                      /* TXE */
-            /* Nop */
-        }
-        s->enable = value & 1;				/* ITR */
-        if (!s->enable)
-            s->status[0] = 0;
-        pxa2xx_fir_update(s);
-        break;
-    case ICCR1:
-        s->control[1] = value;
-        break;
-    case ICCR2:
-        s->control[2] = value & 0x3f;
-        pxa2xx_fir_update(s);
-        break;
-    case ICDR:
-        if (s->control[2] & (1 << 2))			/* TXP */
-            ch = value;
-        else
-            ch = ~value;
-        if (s->chr && s->enable && (s->control[0] & (1 << 3)))	/* TXE */
-            qemu_chr_fe_write(s->chr, &ch, 1);
-        break;
-    case ICSR0:
-        s->status[0] &= ~(value & 0x66);
-        pxa2xx_fir_update(s);
-        break;
-    case ICFOR:
-        break;
-    default:
-        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
-    }
-}
-
-static const MemoryRegionOps pxa2xx_fir_ops = {
-    .read = pxa2xx_fir_read,
-    .write = pxa2xx_fir_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int pxa2xx_fir_is_empty(void *opaque)
-{
-    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
-    return (s->rx_len < 64);
-}
-
-static void pxa2xx_fir_rx(void *opaque, const uint8_t *buf, int size)
-{
-    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
-    if (!(s->control[0] & (1 << 4)))			/* RXE */
-        return;
-
-    while (size --) {
-        s->status[1] |= 1 << 4;				/* EOF */
-        if (s->rx_len >= 64) {
-            s->status[1] |= 1 << 6;			/* ROR */
-            break;
-        }
-
-        if (s->control[2] & (1 << 3))			/* RXP */
-            s->rx_fifo[(s->rx_start + s->rx_len ++) & 63] = *(buf ++);
-        else
-            s->rx_fifo[(s->rx_start + s->rx_len ++) & 63] = ~*(buf ++);
-    }
-
-    pxa2xx_fir_update(s);
-}
-
-static void pxa2xx_fir_event(void *opaque, int event)
-{
-}
-
-static void pxa2xx_fir_save(QEMUFile *f, void *opaque)
-{
-    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
-    int i;
-
-    qemu_put_be32(f, s->enable);
-
-    qemu_put_8s(f, &s->control[0]);
-    qemu_put_8s(f, &s->control[1]);
-    qemu_put_8s(f, &s->control[2]);
-    qemu_put_8s(f, &s->status[0]);
-    qemu_put_8s(f, &s->status[1]);
-
-    qemu_put_byte(f, s->rx_len);
-    for (i = 0; i < s->rx_len; i ++)
-        qemu_put_byte(f, s->rx_fifo[(s->rx_start + i) & 63]);
-}
-
-static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
-{
-    PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
-    int i;
-
-    s->enable = qemu_get_be32(f);
-
-    qemu_get_8s(f, &s->control[0]);
-    qemu_get_8s(f, &s->control[1]);
-    qemu_get_8s(f, &s->control[2]);
-    qemu_get_8s(f, &s->status[0]);
-    qemu_get_8s(f, &s->status[1]);
-
-    s->rx_len = qemu_get_byte(f);
-    s->rx_start = 0;
-    for (i = 0; i < s->rx_len; i ++)
-        s->rx_fifo[i] = qemu_get_byte(f);
-
-    return 0;
-}
-
-static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
-                hwaddr base,
-                qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma,
-                CharDriverState *chr)
-{
-    PXA2xxFIrState *s = (PXA2xxFIrState *)
-            g_malloc0(sizeof(PXA2xxFIrState));
-
-    s->irq = irq;
-    s->rx_dma = rx_dma;
-    s->tx_dma = tx_dma;
-    s->chr = chr;
-
-    pxa2xx_fir_reset(s);
-
-    memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000);
-    memory_region_add_subregion(sysmem, base, &s->iomem);
-
-    if (chr)
-        qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
-                        pxa2xx_fir_rx, pxa2xx_fir_event, s);
-
-    register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
-                    pxa2xx_fir_load, s);
-
-    return s;
-}
-
-static void pxa2xx_reset(void *opaque, int line, int level)
-{
-    PXA2xxState *s = (PXA2xxState *) opaque;
-
-    if (level && (s->pm_regs[PCFR >> 2] & 0x10)) {	/* GPR_EN */
-        cpu_reset(CPU(s->cpu));
-        /* TODO: reset peripherals */
-    }
-}
-
-/* Initialise a PXA270 integrated chip (ARM based core).  */
-PXA2xxState *pxa270_init(MemoryRegion *address_space,
-                         unsigned int sdram_size, const char *revision)
-{
-    PXA2xxState *s;
-    int i;
-    DriveInfo *dinfo;
-    s = (PXA2xxState *) g_malloc0(sizeof(PXA2xxState));
-
-    if (revision && strncmp(revision, "pxa27", 5)) {
-        fprintf(stderr, "Machine requires a PXA27x processor.\n");
-        exit(1);
-    }
-    if (!revision)
-        revision = "pxa270";
-    
-    s->cpu = cpu_arm_init(revision);
-    if (s->cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
-
-    /* SDRAM & Internal Memory Storage */
-    memory_region_init_ram(&s->sdram, "pxa270.sdram", sdram_size);
-    vmstate_register_ram_global(&s->sdram);
-    memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram);
-    memory_region_init_ram(&s->internal, "pxa270.internal", 0x40000);
-    vmstate_register_ram_global(&s->internal);
-    memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
-                                &s->internal);
-
-    s->pic = pxa2xx_pic_init(0x40d00000, s->cpu);
-
-    s->dma = pxa27x_dma_init(0x40000000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
-
-    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->cpu, s->pic, 121);
-
-    dinfo = drive_get(IF_SD, 0, 0);
-    if (!dinfo) {
-        fprintf(stderr, "qemu: missing SecureDigital device\n");
-        exit(1);
-    }
-    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv,
-                    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]) {
-            serial_mm_init(address_space, pxa270_serial[i].io_base, 2,
-                           qdev_get_gpio_in(s->pic, pxa270_serial[i].irqn),
-                           14857000 / 16, serial_hds[i],
-                           DEVICE_NATIVE_ENDIAN);
-        } else {
-            break;
-        }
-    }
-    if (serial_hds[i])
-        s->fir = pxa2xx_fir_init(address_space, 0x40800000,
-                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_ICP),
-                        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(address_space, 0x44000000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_LCD));
-
-    s->cm_base = 0x41300000;
-    s->cm_regs[CCCR >> 2] = 0x02000210;	/* 416.0 MHz */
-    s->clkcfg = 0x00000009;		/* Turbo mode active */
-    memory_region_init_io(&s->cm_iomem, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000);
-    memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
-    vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
-
-    pxa2xx_setup_cp14(s);
-
-    s->mm_base = 0x48000000;
-    s->mm_regs[MDMRS >> 2] = 0x00020002;
-    s->mm_regs[MDREFR >> 2] = 0x03ca4000;
-    s->mm_regs[MECR >> 2] = 0x00000001;	/* Two PC Card sockets */
-    memory_region_init_io(&s->mm_iomem, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000);
-    memory_region_add_subregion(address_space, s->mm_base, &s->mm_iomem);
-    vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
-
-    s->pm_base = 0x40f00000;
-    memory_region_init_io(&s->pm_iomem, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100);
-    memory_region_add_subregion(address_space, s->pm_base, &s->pm_iomem);
-    vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
-
-    for (i = 0; pxa27x_ssp[i].io_base; i ++);
-    s->ssp = (SSIBus **)g_malloc0(sizeof(SSIBus *) * i);
-    for (i = 0; pxa27x_ssp[i].io_base; i ++) {
-        DeviceState *dev;
-        dev = sysbus_create_simple("pxa2xx-ssp", pxa27x_ssp[i].io_base,
-                        qdev_get_gpio_in(s->pic, pxa27x_ssp[i].irqn));
-        s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
-    }
-
-    if (usb_enabled(false)) {
-        sysbus_create_simple("sysbus-ohci", 0x4c000000,
-                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
-    }
-
-    s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
-    s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
-
-    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);
-    s->i2c[1] = pxa2xx_i2c_init(0x40f00100,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_PWRI2C), 0xff);
-
-    s->i2s = pxa2xx_i2s_init(address_space, 0x40400000,
-                    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(address_space, 0x41500000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_KEYPAD));
-
-    /* GPIO1 resets the processor */
-    /* The handler can be overridden by board-specific code */
-    qdev_connect_gpio_out(s->gpio, 1, s->reset);
-    return s;
-}
-
-/* Initialise a PXA255 integrated chip (ARM based core).  */
-PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
-{
-    PXA2xxState *s;
-    int i;
-    DriveInfo *dinfo;
-
-    s = (PXA2xxState *) g_malloc0(sizeof(PXA2xxState));
-
-    s->cpu = cpu_arm_init("pxa255");
-    if (s->cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0];
-
-    /* SDRAM & Internal Memory Storage */
-    memory_region_init_ram(&s->sdram, "pxa255.sdram", sdram_size);
-    vmstate_register_ram_global(&s->sdram);
-    memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram);
-    memory_region_init_ram(&s->internal, "pxa255.internal",
-                           PXA2XX_INTERNAL_SIZE);
-    vmstate_register_ram_global(&s->internal);
-    memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE,
-                                &s->internal);
-
-    s->pic = pxa2xx_pic_init(0x40d00000, s->cpu);
-
-    s->dma = pxa255_dma_init(0x40000000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
-
-    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->cpu, s->pic, 85);
-
-    dinfo = drive_get(IF_SD, 0, 0);
-    if (!dinfo) {
-        fprintf(stderr, "qemu: missing SecureDigital device\n");
-        exit(1);
-    }
-    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv,
-                    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]) {
-            serial_mm_init(address_space, pxa255_serial[i].io_base, 2,
-                           qdev_get_gpio_in(s->pic, pxa255_serial[i].irqn),
-                           14745600 / 16, serial_hds[i],
-                           DEVICE_NATIVE_ENDIAN);
-        } else {
-            break;
-        }
-    }
-    if (serial_hds[i])
-        s->fir = pxa2xx_fir_init(address_space, 0x40800000,
-                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_ICP),
-                        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(address_space, 0x44000000,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_LCD));
-
-    s->cm_base = 0x41300000;
-    s->cm_regs[CCCR >> 2] = 0x02000210;	/* 416.0 MHz */
-    s->clkcfg = 0x00000009;		/* Turbo mode active */
-    memory_region_init_io(&s->cm_iomem, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000);
-    memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem);
-    vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
-
-    pxa2xx_setup_cp14(s);
-
-    s->mm_base = 0x48000000;
-    s->mm_regs[MDMRS >> 2] = 0x00020002;
-    s->mm_regs[MDREFR >> 2] = 0x03ca4000;
-    s->mm_regs[MECR >> 2] = 0x00000001;	/* Two PC Card sockets */
-    memory_region_init_io(&s->mm_iomem, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000);
-    memory_region_add_subregion(address_space, s->mm_base, &s->mm_iomem);
-    vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
-
-    s->pm_base = 0x40f00000;
-    memory_region_init_io(&s->pm_iomem, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100);
-    memory_region_add_subregion(address_space, s->pm_base, &s->pm_iomem);
-    vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
-
-    for (i = 0; pxa255_ssp[i].io_base; i ++);
-    s->ssp = (SSIBus **)g_malloc0(sizeof(SSIBus *) * i);
-    for (i = 0; pxa255_ssp[i].io_base; i ++) {
-        DeviceState *dev;
-        dev = sysbus_create_simple("pxa2xx-ssp", pxa255_ssp[i].io_base,
-                        qdev_get_gpio_in(s->pic, pxa255_ssp[i].irqn));
-        s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
-    }
-
-    if (usb_enabled(false)) {
-        sysbus_create_simple("sysbus-ohci", 0x4c000000,
-                        qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
-    }
-
-    s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
-    s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
-
-    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);
-    s->i2c[1] = pxa2xx_i2c_init(0x40f00100,
-                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_PWRI2C), 0xff);
-
-    s->i2s = pxa2xx_i2s_init(address_space, 0x40400000,
-                    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 */
-    qdev_connect_gpio_out(s->gpio, 1, s->reset);
-    return s;
-}
-
-static void pxa2xx_ssp_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = pxa2xx_ssp_init;
-}
-
-static const TypeInfo pxa2xx_ssp_info = {
-    .name          = "pxa2xx-ssp",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(PXA2xxSSPState),
-    .class_init    = pxa2xx_ssp_class_init,
-};
-
-static void pxa2xx_register_types(void)
-{
-    type_register_static(&pxa2xx_i2c_slave_info);
-    type_register_static(&pxa2xx_ssp_info);
-    type_register_static(&pxa2xx_i2c_info);
-    type_register_static(&pxa2xx_rtc_sysbus_info);
-}
-
-type_init(pxa2xx_register_types)
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
deleted file mode 100644
index eef8411..0000000
--- a/hw/pxa2xx_gpio.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Intel XScale PXA255/270 GPIO controller emulation.
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Written by Andrzej Zaborowski <balrog at zabor.org>
- *
- * This code is licensed under the GPL.
- */
-
-#include "hw/hw.h"
-#include "hw/sysbus.h"
-#include "hw/pxa.h"
-
-#define PXA2XX_GPIO_BANKS	4
-
-typedef struct PXA2xxGPIOInfo PXA2xxGPIOInfo;
-struct PXA2xxGPIOInfo {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    qemu_irq irq0, irq1, irqX;
-    int lines;
-    int ncpu;
-    ARMCPU *cpu;
-
-    /* XXX: GNU C vectors are more suitable */
-    uint32_t ilevel[PXA2XX_GPIO_BANKS];
-    uint32_t olevel[PXA2XX_GPIO_BANKS];
-    uint32_t dir[PXA2XX_GPIO_BANKS];
-    uint32_t rising[PXA2XX_GPIO_BANKS];
-    uint32_t falling[PXA2XX_GPIO_BANKS];
-    uint32_t status[PXA2XX_GPIO_BANKS];
-    uint32_t gpsr[PXA2XX_GPIO_BANKS];
-    uint32_t gafr[PXA2XX_GPIO_BANKS * 2];
-
-    uint32_t prev_level[PXA2XX_GPIO_BANKS];
-    qemu_irq handler[PXA2XX_GPIO_BANKS * 32];
-    qemu_irq read_notify;
-};
-
-static struct {
-    enum {
-        GPIO_NONE,
-        GPLR,
-        GPSR,
-        GPCR,
-        GPDR,
-        GRER,
-        GFER,
-        GEDR,
-        GAFR_L,
-        GAFR_U,
-    } reg;
-    int bank;
-} pxa2xx_gpio_regs[0x200] = {
-    [0 ... 0x1ff] = { GPIO_NONE, 0 },
-#define PXA2XX_REG(reg, a0, a1, a2, a3)	\
-    [a0] = { reg, 0 }, [a1] = { reg, 1 }, [a2] = { reg, 2 }, [a3] = { reg, 3 },
-
-    PXA2XX_REG(GPLR, 0x000, 0x004, 0x008, 0x100)
-    PXA2XX_REG(GPSR, 0x018, 0x01c, 0x020, 0x118)
-    PXA2XX_REG(GPCR, 0x024, 0x028, 0x02c, 0x124)
-    PXA2XX_REG(GPDR, 0x00c, 0x010, 0x014, 0x10c)
-    PXA2XX_REG(GRER, 0x030, 0x034, 0x038, 0x130)
-    PXA2XX_REG(GFER, 0x03c, 0x040, 0x044, 0x13c)
-    PXA2XX_REG(GEDR, 0x048, 0x04c, 0x050, 0x148)
-    PXA2XX_REG(GAFR_L, 0x054, 0x05c, 0x064, 0x06c)
-    PXA2XX_REG(GAFR_U, 0x058, 0x060, 0x068, 0x070)
-};
-
-static void pxa2xx_gpio_irq_update(PXA2xxGPIOInfo *s)
-{
-    if (s->status[0] & (1 << 0))
-        qemu_irq_raise(s->irq0);
-    else
-        qemu_irq_lower(s->irq0);
-
-    if (s->status[0] & (1 << 1))
-        qemu_irq_raise(s->irq1);
-    else
-        qemu_irq_lower(s->irq1);
-
-    if ((s->status[0] & ~3) | s->status[1] | s->status[2] | s->status[3])
-        qemu_irq_raise(s->irqX);
-    else
-        qemu_irq_lower(s->irqX);
-}
-
-/* Bitmap of pins used as standby and sleep wake-up sources.  */
-static const int pxa2xx_gpio_wake[PXA2XX_GPIO_BANKS] = {
-    0x8003fe1b, 0x002001fc, 0xec080000, 0x0012007f,
-};
-
-static void pxa2xx_gpio_set(void *opaque, int line, int level)
-{
-    PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
-    int bank;
-    uint32_t mask;
-
-    if (line >= s->lines) {
-        printf("%s: No GPIO pin %i\n", __FUNCTION__, line);
-        return;
-    }
-
-    bank = line >> 5;
-    mask = 1 << (line & 31);
-
-    if (level) {
-        s->status[bank] |= s->rising[bank] & mask &
-                ~s->ilevel[bank] & ~s->dir[bank];
-        s->ilevel[bank] |= mask;
-    } else {
-        s->status[bank] |= s->falling[bank] & mask &
-                s->ilevel[bank] & ~s->dir[bank];
-        s->ilevel[bank] &= ~mask;
-    }
-
-    if (s->status[bank] & mask)
-        pxa2xx_gpio_irq_update(s);
-
-    /* Wake-up GPIOs */
-    if (s->cpu->env.halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
-    }
-}
-
-static void pxa2xx_gpio_handler_update(PXA2xxGPIOInfo *s) {
-    uint32_t level, diff;
-    int i, bit, line;
-    for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) {
-        level = s->olevel[i] & s->dir[i];
-
-        for (diff = s->prev_level[i] ^ level; diff; diff ^= 1 << bit) {
-            bit = ffs(diff) - 1;
-            line = bit + 32 * i;
-            qemu_set_irq(s->handler[line], (level >> bit) & 1);
-        }
-
-        s->prev_level[i] = level;
-    }
-}
-
-static uint64_t pxa2xx_gpio_read(void *opaque, hwaddr offset,
-                                 unsigned size)
-{
-    PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
-    uint32_t ret;
-    int bank;
-    if (offset >= 0x200)
-        return 0;
-
-    bank = pxa2xx_gpio_regs[offset].bank;
-    switch (pxa2xx_gpio_regs[offset].reg) {
-    case GPDR:		/* GPIO Pin-Direction registers */
-        return s->dir[bank];
-
-    case GPSR:		/* GPIO Pin-Output Set registers */
-        printf("%s: Read from a write-only register " REG_FMT "\n",
-                        __FUNCTION__, offset);
-        return s->gpsr[bank];	/* Return last written value.  */
-
-    case GPCR:		/* GPIO Pin-Output Clear registers */
-        printf("%s: Read from a write-only register " REG_FMT "\n",
-                        __FUNCTION__, offset);
-        return 31337;		/* Specified as unpredictable in the docs.  */
-
-    case GRER:		/* GPIO Rising-Edge Detect Enable registers */
-        return s->rising[bank];
-
-    case GFER:		/* GPIO Falling-Edge Detect Enable registers */
-        return s->falling[bank];
-
-    case GAFR_L:	/* GPIO Alternate Function registers */
-        return s->gafr[bank * 2];
-
-    case GAFR_U:	/* GPIO Alternate Function registers */
-        return s->gafr[bank * 2 + 1];
-
-    case GPLR:		/* GPIO Pin-Level registers */
-        ret = (s->olevel[bank] & s->dir[bank]) |
-                (s->ilevel[bank] & ~s->dir[bank]);
-        qemu_irq_raise(s->read_notify);
-        return ret;
-
-    case GEDR:		/* GPIO Edge Detect Status registers */
-        return s->status[bank];
-
-    default:
-        hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
-    }
-
-    return 0;
-}
-
-static void pxa2xx_gpio_write(void *opaque, hwaddr offset,
-                              uint64_t value, unsigned size)
-{
-    PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
-    int bank;
-    if (offset >= 0x200)
-        return;
-
-    bank = pxa2xx_gpio_regs[offset].bank;
-    switch (pxa2xx_gpio_regs[offset].reg) {
-    case GPDR:		/* GPIO Pin-Direction registers */
-        s->dir[bank] = value;
-        pxa2xx_gpio_handler_update(s);
-        break;
-
-    case GPSR:		/* GPIO Pin-Output Set registers */
-        s->olevel[bank] |= value;
-        pxa2xx_gpio_handler_update(s);
-        s->gpsr[bank] = value;
-        break;
-
-    case GPCR:		/* GPIO Pin-Output Clear registers */
-        s->olevel[bank] &= ~value;
-        pxa2xx_gpio_handler_update(s);
-        break;
-
-    case GRER:		/* GPIO Rising-Edge Detect Enable registers */
-        s->rising[bank] = value;
-        break;
-
-    case GFER:		/* GPIO Falling-Edge Detect Enable registers */
-        s->falling[bank] = value;
-        break;
-
-    case GAFR_L:	/* GPIO Alternate Function registers */
-        s->gafr[bank * 2] = value;
-        break;
-
-    case GAFR_U:	/* GPIO Alternate Function registers */
-        s->gafr[bank * 2 + 1] = value;
-        break;
-
-    case GEDR:		/* GPIO Edge Detect Status registers */
-        s->status[bank] &= ~value;
-        pxa2xx_gpio_irq_update(s);
-        break;
-
-    default:
-        hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
-    }
-}
-
-static const MemoryRegionOps pxa_gpio_ops = {
-    .read = pxa2xx_gpio_read,
-    .write = pxa2xx_gpio_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-DeviceState *pxa2xx_gpio_init(hwaddr base,
-                              ARMCPU *cpu, DeviceState *pic, int lines)
-{
-    CPUState *cs = CPU(cpu);
-    DeviceState *dev;
-
-    dev = qdev_create(NULL, "pxa2xx-gpio");
-    qdev_prop_set_int32(dev, "lines", lines);
-    qdev_prop_set_int32(dev, "ncpu", cs->cpu_index);
-    qdev_init_nofail(dev);
-
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
-                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_0));
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1,
-                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_1));
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2,
-                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_X));
-
-    return dev;
-}
-
-static int pxa2xx_gpio_initfn(SysBusDevice *dev)
-{
-    PXA2xxGPIOInfo *s;
-
-    s = FROM_SYSBUS(PXA2xxGPIOInfo, dev);
-
-    s->cpu = ARM_CPU(qemu_get_cpu(s->ncpu));
-
-    qdev_init_gpio_in(&dev->qdev, pxa2xx_gpio_set, s->lines);
-    qdev_init_gpio_out(&dev->qdev, s->handler, s->lines);
-
-    memory_region_init_io(&s->iomem, &pxa_gpio_ops, s, "pxa2xx-gpio", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    sysbus_init_irq(dev, &s->irq0);
-    sysbus_init_irq(dev, &s->irq1);
-    sysbus_init_irq(dev, &s->irqX);
-
-    return 0;
-}
-
-/*
- * Registers a callback to notify on GPLR reads.  This normally
- * shouldn't be needed but it is used for the hack on Spitz machines.
- */
-void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler)
-{
-    PXA2xxGPIOInfo *s = FROM_SYSBUS(PXA2xxGPIOInfo, SYS_BUS_DEVICE(dev));
-    s->read_notify = handler;
-}
-
-static const VMStateDescription vmstate_pxa2xx_gpio_regs = {
-    .name = "pxa2xx-gpio",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField []) {
-        VMSTATE_INT32(lines, PXA2xxGPIOInfo),
-        VMSTATE_UINT32_ARRAY(ilevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
-        VMSTATE_UINT32_ARRAY(olevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
-        VMSTATE_UINT32_ARRAY(dir, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
-        VMSTATE_UINT32_ARRAY(rising, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
-        VMSTATE_UINT32_ARRAY(falling, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
-        VMSTATE_UINT32_ARRAY(status, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
-        VMSTATE_UINT32_ARRAY(gafr, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS * 2),
-        VMSTATE_END_OF_LIST(),
-    },
-};
-
-static Property pxa2xx_gpio_properties[] = {
-    DEFINE_PROP_INT32("lines", PXA2xxGPIOInfo, lines, 0),
-    DEFINE_PROP_INT32("ncpu", PXA2xxGPIOInfo, ncpu, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void pxa2xx_gpio_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = pxa2xx_gpio_initfn;
-    dc->desc = "PXA2xx GPIO controller";
-    dc->props = pxa2xx_gpio_properties;
-}
-
-static const TypeInfo pxa2xx_gpio_info = {
-    .name          = "pxa2xx-gpio",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(PXA2xxGPIOInfo),
-    .class_init    = pxa2xx_gpio_class_init,
-};
-
-static void pxa2xx_gpio_register_types(void)
-{
-    type_register_static(&pxa2xx_gpio_info);
-}
-
-type_init(pxa2xx_gpio_register_types)
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
deleted file mode 100644
index 145fc78..0000000
--- a/hw/pxa2xx_pic.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Intel XScale PXA Programmable Interrupt Controller.
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Copyright (c) 2006 Thorsten Zitterell
- * Written by Andrzej Zaborowski <balrog at zabor.org>
- *
- * This code is licensed under the GPL.
- */
-
-#include "hw/hw.h"
-#include "hw/pxa.h"
-#include "hw/sysbus.h"
-
-#define ICIP	0x00	/* Interrupt Controller IRQ Pending register */
-#define ICMR	0x04	/* Interrupt Controller Mask register */
-#define ICLR	0x08	/* Interrupt Controller Level register */
-#define ICFP	0x0c	/* Interrupt Controller FIQ Pending register */
-#define ICPR	0x10	/* Interrupt Controller Pending register */
-#define ICCR	0x14	/* Interrupt Controller Control register */
-#define ICHP	0x18	/* Interrupt Controller Highest Priority register */
-#define IPR0	0x1c	/* Interrupt Controller Priority register 0 */
-#define IPR31	0x98	/* Interrupt Controller Priority register 31 */
-#define ICIP2	0x9c	/* Interrupt Controller IRQ Pending register 2 */
-#define ICMR2	0xa0	/* Interrupt Controller Mask register 2 */
-#define ICLR2	0xa4	/* Interrupt Controller Level register 2 */
-#define ICFP2	0xa8	/* Interrupt Controller FIQ Pending register 2 */
-#define ICPR2	0xac	/* Interrupt Controller Pending register 2 */
-#define IPR32	0xb0	/* Interrupt Controller Priority register 32 */
-#define IPR39	0xcc	/* Interrupt Controller Priority register 39 */
-
-#define PXA2XX_PIC_SRCS	40
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    ARMCPU *cpu;
-    uint32_t int_enabled[2];
-    uint32_t int_pending[2];
-    uint32_t is_fiq[2];
-    uint32_t int_idle;
-    uint32_t priority[PXA2XX_PIC_SRCS];
-} PXA2xxPICState;
-
-static void pxa2xx_pic_update(void *opaque)
-{
-    uint32_t mask[2];
-    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
-
-    if (s->cpu->env.halted) {
-        mask[0] = s->int_pending[0] & (s->int_enabled[0] | s->int_idle);
-        mask[1] = s->int_pending[1] & (s->int_enabled[1] | s->int_idle);
-        if (mask[0] || mask[1]) {
-            cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_EXITTB);
-        }
-    }
-
-    mask[0] = s->int_pending[0] & s->int_enabled[0];
-    mask[1] = s->int_pending[1] & s->int_enabled[1];
-
-    if ((mask[0] & s->is_fiq[0]) || (mask[1] & s->is_fiq[1])) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
-    } else {
-        cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_FIQ);
-    }
-
-    if ((mask[0] & ~s->is_fiq[0]) || (mask[1] & ~s->is_fiq[1])) {
-        cpu_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
-    } else {
-        cpu_reset_interrupt(&s->cpu->env, CPU_INTERRUPT_HARD);
-    }
-}
-
-/* Note: Here level means state of the signal on a pin, not
- * IRQ/FIQ distinction as in PXA Developer Manual.  */
-static void pxa2xx_pic_set_irq(void *opaque, int irq, int level)
-{
-    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
-    int int_set = (irq >= 32);
-    irq &= 31;
-
-    if (level)
-        s->int_pending[int_set] |= 1 << irq;
-    else
-        s->int_pending[int_set] &= ~(1 << irq);
-
-    pxa2xx_pic_update(opaque);
-}
-
-static inline uint32_t pxa2xx_pic_highest(PXA2xxPICState *s) {
-    int i, int_set, irq;
-    uint32_t bit, mask[2];
-    uint32_t ichp = 0x003f003f;	/* Both IDs invalid */
-
-    mask[0] = s->int_pending[0] & s->int_enabled[0];
-    mask[1] = s->int_pending[1] & s->int_enabled[1];
-
-    for (i = PXA2XX_PIC_SRCS - 1; i >= 0; i --) {
-        irq = s->priority[i] & 0x3f;
-        if ((s->priority[i] & (1 << 31)) && irq < PXA2XX_PIC_SRCS) {
-            /* Source peripheral ID is valid.  */
-            bit = 1 << (irq & 31);
-            int_set = (irq >= 32);
-
-            if (mask[int_set] & bit & s->is_fiq[int_set]) {
-                /* FIQ asserted */
-                ichp &= 0xffff0000;
-                ichp |= (1 << 15) | irq;
-            }
-
-            if (mask[int_set] & bit & ~s->is_fiq[int_set]) {
-                /* IRQ asserted */
-                ichp &= 0x0000ffff;
-                ichp |= (1 << 31) | (irq << 16);
-            }
-        }
-    }
-
-    return ichp;
-}
-
-static uint64_t pxa2xx_pic_mem_read(void *opaque, hwaddr offset,
-                                    unsigned size)
-{
-    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
-
-    switch (offset) {
-    case ICIP:	/* IRQ Pending register */
-        return s->int_pending[0] & ~s->is_fiq[0] & s->int_enabled[0];
-    case ICIP2:	/* IRQ Pending register 2 */
-        return s->int_pending[1] & ~s->is_fiq[1] & s->int_enabled[1];
-    case ICMR:	/* Mask register */
-        return s->int_enabled[0];
-    case ICMR2:	/* Mask register 2 */
-        return s->int_enabled[1];
-    case ICLR:	/* Level register */
-        return s->is_fiq[0];
-    case ICLR2:	/* Level register 2 */
-        return s->is_fiq[1];
-    case ICCR:	/* Idle mask */
-        return (s->int_idle == 0);
-    case ICFP:	/* FIQ Pending register */
-        return s->int_pending[0] & s->is_fiq[0] & s->int_enabled[0];
-    case ICFP2:	/* FIQ Pending register 2 */
-        return s->int_pending[1] & s->is_fiq[1] & s->int_enabled[1];
-    case ICPR:	/* Pending register */
-        return s->int_pending[0];
-    case ICPR2:	/* Pending register 2 */
-        return s->int_pending[1];
-    case IPR0  ... IPR31:
-        return s->priority[0  + ((offset - IPR0 ) >> 2)];
-    case IPR32 ... IPR39:
-        return s->priority[32 + ((offset - IPR32) >> 2)];
-    case ICHP:	/* Highest Priority register */
-        return pxa2xx_pic_highest(s);
-    default:
-        printf("%s: Bad register offset " REG_FMT "\n", __FUNCTION__, offset);
-        return 0;
-    }
-}
-
-static void pxa2xx_pic_mem_write(void *opaque, hwaddr offset,
-                                 uint64_t value, unsigned size)
-{
-    PXA2xxPICState *s = (PXA2xxPICState *) opaque;
-
-    switch (offset) {
-    case ICMR:	/* Mask register */
-        s->int_enabled[0] = value;
-        break;
-    case ICMR2:	/* Mask register 2 */
-        s->int_enabled[1] = value;
-        break;
-    case ICLR:	/* Level register */
-        s->is_fiq[0] = value;
-        break;
-    case ICLR2:	/* Level register 2 */
-        s->is_fiq[1] = value;
-        break;
-    case ICCR:	/* Idle mask */
-        s->int_idle = (value & 1) ? 0 : ~0;
-        break;
-    case IPR0  ... IPR31:
-        s->priority[0  + ((offset - IPR0 ) >> 2)] = value & 0x8000003f;
-        break;
-    case IPR32 ... IPR39:
-        s->priority[32 + ((offset - IPR32) >> 2)] = value & 0x8000003f;
-        break;
-    default:
-        printf("%s: Bad register offset " REG_FMT "\n", __FUNCTION__, offset);
-        return;
-    }
-    pxa2xx_pic_update(opaque);
-}
-
-/* Interrupt Controller Coprocessor Space Register Mapping */
-static const int pxa2xx_cp_reg_map[0x10] = {
-    [0x0 ... 0xf] = -1,
-    [0x0] = ICIP,
-    [0x1] = ICMR,
-    [0x2] = ICLR,
-    [0x3] = ICFP,
-    [0x4] = ICPR,
-    [0x5] = ICHP,
-    [0x6] = ICIP2,
-    [0x7] = ICMR2,
-    [0x8] = ICLR2,
-    [0x9] = ICFP2,
-    [0xa] = ICPR2,
-};
-
-static int pxa2xx_pic_cp_read(CPUARMState *env, const ARMCPRegInfo *ri,
-                              uint64_t *value)
-{
-    int offset = pxa2xx_cp_reg_map[ri->crn];
-    *value = pxa2xx_pic_mem_read(ri->opaque, offset, 4);
-    return 0;
-}
-
-static int pxa2xx_pic_cp_write(CPUARMState *env, const ARMCPRegInfo *ri,
-                               uint64_t value)
-{
-    int offset = pxa2xx_cp_reg_map[ri->crn];
-    pxa2xx_pic_mem_write(ri->opaque, offset, value, 4);
-    return 0;
-}
-
-#define REGINFO_FOR_PIC_CP(NAME, CRN) \
-    { .name = NAME, .cp = 6, .crn = CRN, .crm = 0, .opc1 = 0, .opc2 = 0, \
-      .access = PL1_RW, \
-      .readfn = pxa2xx_pic_cp_read, .writefn = pxa2xx_pic_cp_write }
-
-static const ARMCPRegInfo pxa_pic_cp_reginfo[] = {
-    REGINFO_FOR_PIC_CP("ICIP", 0),
-    REGINFO_FOR_PIC_CP("ICMR", 1),
-    REGINFO_FOR_PIC_CP("ICLR", 2),
-    REGINFO_FOR_PIC_CP("ICFP", 3),
-    REGINFO_FOR_PIC_CP("ICPR", 4),
-    REGINFO_FOR_PIC_CP("ICHP", 5),
-    REGINFO_FOR_PIC_CP("ICIP2", 6),
-    REGINFO_FOR_PIC_CP("ICMR2", 7),
-    REGINFO_FOR_PIC_CP("ICLR2", 8),
-    REGINFO_FOR_PIC_CP("ICFP2", 9),
-    REGINFO_FOR_PIC_CP("ICPR2", 0xa),
-    REGINFO_SENTINEL
-};
-
-static const MemoryRegionOps pxa2xx_pic_ops = {
-    .read = pxa2xx_pic_mem_read,
-    .write = pxa2xx_pic_mem_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int pxa2xx_pic_post_load(void *opaque, int version_id)
-{
-    pxa2xx_pic_update(opaque);
-    return 0;
-}
-
-DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu)
-{
-    CPUARMState *env = &cpu->env;
-    DeviceState *dev = qdev_create(NULL, "pxa2xx_pic");
-    PXA2xxPICState *s = FROM_SYSBUS(PXA2xxPICState, SYS_BUS_DEVICE(dev));
-
-    s->cpu = cpu;
-
-    s->int_pending[0] = 0;
-    s->int_pending[1] = 0;
-    s->int_enabled[0] = 0;
-    s->int_enabled[1] = 0;
-    s->is_fiq[0] = 0;
-    s->is_fiq[1] = 0;
-
-    qdev_init_nofail(dev);
-
-    qdev_init_gpio_in(dev, pxa2xx_pic_set_irq, PXA2XX_PIC_SRCS);
-
-    /* Enable IC memory-mapped registers access.  */
-    memory_region_init_io(&s->iomem, &pxa2xx_pic_ops, s,
-                          "pxa2xx-pic", 0x00100000);
-    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
-
-    /* Enable IC coprocessor access.  */
-    define_arm_cp_regs_with_opaque(arm_env_get_cpu(env), pxa_pic_cp_reginfo, 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(),
-    },
-};
-
-static int pxa2xx_pic_initfn(SysBusDevice *dev)
-{
-    return 0;
-}
-
-static void pxa2xx_pic_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = pxa2xx_pic_initfn;
-    dc->desc = "PXA2xx PIC";
-    dc->vmsd = &vmstate_pxa2xx_pic_regs;
-}
-
-static const TypeInfo pxa2xx_pic_info = {
-    .name          = "pxa2xx_pic",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(PXA2xxPICState),
-    .class_init    = pxa2xx_pic_class_init,
-};
-
-static void pxa2xx_pic_register_types(void)
-{
-    type_register_static(&pxa2xx_pic_info);
-}
-
-type_init(pxa2xx_pic_register_types)
commit 530182169e897c0e401b245552a4c58dc6846912
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Feb 5 12:03:15 2013 +0100

    hw: move boards and other isolated files to hw/ARCH
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 43f467a..eb7eb31 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -206,7 +206,6 @@ obj-$(CONFIG_SOFTMMU) += vhost_net.o
 obj-$(CONFIG_VHOST_NET) += vhost.o
 obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/
 obj-$(CONFIG_VGA) += vga.o
-obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
 
 # Inter-VM PCI shared memory & VFIO PCI device assignment
 ifeq ($(CONFIG_PCI), y)
diff --git a/hw/alpha/Makefile.objs b/hw/alpha/Makefile.objs
index af1c07f..db868d2 100644
--- a/hw/alpha/Makefile.objs
+++ b/hw/alpha/Makefile.objs
@@ -1,4 +1,6 @@
 obj-y = mc146818rtc.o
-obj-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o
+obj-y += alpha_typhoon.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += dp264.o pci.o
diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
new file mode 100644
index 0000000..13aaa57
--- /dev/null
+++ b/hw/alpha/dp264.c
@@ -0,0 +1,182 @@
+/*
+ * QEMU Alpha DP264/CLIPPER hardware system emulator.
+ *
+ * Choose CLIPPER IRQ mappings over, say, DP264, MONET, or WEBBRICK
+ * variants because CLIPPER doesn't have an SMC669 SuperIO controller
+ * that we need to emulate as well.
+ */
+
+#include "hw/hw.h"
+#include "elf.h"
+#include "hw/loader.h"
+#include "hw/boards.h"
+#include "hw/alpha_sys.h"
+#include "sysemu/sysemu.h"
+#include "hw/mc146818rtc.h"
+#include "hw/ide.h"
+#include "hw/i8254.h"
+#include "hw/serial.h"
+
+#define MAX_IDE_BUS 2
+
+static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr)
+{
+    if (((addr >> 41) & 3) == 2) {
+        addr &= 0xffffffffffull;
+    }
+    return addr;
+}
+
+/* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems.
+    (0) The dev_irq_n lines into the cpu, which we totally ignore,
+    (1) The DRIR lines in the typhoon chipset,
+    (2) The "vector" aka mangled interrupt number reported by SRM PALcode,
+    (3) The interrupt number assigned by the kernel.
+   The following function is concerned with (1) only.  */
+
+static int clipper_pci_map_irq(PCIDevice *d, int irq_num)
+{
+    int slot = d->devfn >> 3;
+
+    assert(irq_num >= 0 && irq_num <= 3);
+
+    return (slot + 1) * 4 + irq_num;
+}
+
+static void clipper_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    AlphaCPU *cpus[4];
+    PCIBus *pci_bus;
+    ISABus *isa_bus;
+    qemu_irq rtc_irq;
+    long size, i;
+    const char *palcode_filename;
+    uint64_t palcode_entry, palcode_low, palcode_high;
+    uint64_t kernel_entry, kernel_low, kernel_high;
+
+    /* Create up to 4 cpus.  */
+    memset(cpus, 0, sizeof(cpus));
+    for (i = 0; i < smp_cpus; ++i) {
+        cpus[i] = cpu_alpha_init(cpu_model ? cpu_model : "ev67");
+    }
+
+    cpus[0]->env.trap_arg0 = ram_size;
+    cpus[0]->env.trap_arg1 = 0;
+    cpus[0]->env.trap_arg2 = smp_cpus;
+
+    /* Init the chipset.  */
+    pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus,
+                           clipper_pci_map_irq);
+
+    rtc_init(isa_bus, 1980, rtc_irq);
+    pit_init(isa_bus, 0x40, 0, NULL);
+    isa_create_simple(isa_bus, "i8042");
+
+    /* VGA setup.  Don't bother loading the bios.  */
+    pci_vga_init(pci_bus);
+
+    /* Serial code setup.  */
+    for (i = 0; i < MAX_SERIAL_PORTS; ++i) {
+        if (serial_hds[i]) {
+            serial_isa_init(isa_bus, i, serial_hds[i]);
+        }
+    }
+
+    /* Network setup.  e1000 is good enough, failing Tulip support.  */
+    for (i = 0; i < nb_nics; i++) {
+        pci_nic_init_nofail(&nd_table[i], "e1000", NULL);
+    }
+
+    /* IDE disk setup.  */
+    {
+        DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+        ide_drive_get(hd, MAX_IDE_BUS);
+
+        pci_cmd646_ide_init(pci_bus, hd, 0);
+    }
+
+    /* Load PALcode.  Given that this is not "real" cpu palcode,
+       but one explicitly written for the emulation, we might as
+       well load it directly from and ELF image.  */
+    palcode_filename = (bios_name ? bios_name : "palcode-clipper");
+    palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, palcode_filename);
+    if (palcode_filename == NULL) {
+        hw_error("no palcode provided\n");
+        exit(1);
+    }
+    size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys,
+                    NULL, &palcode_entry, &palcode_low, &palcode_high,
+                    0, EM_ALPHA, 0);
+    if (size < 0) {
+        hw_error("could not load palcode '%s'\n", palcode_filename);
+        exit(1);
+    }
+
+    /* Start all cpus at the PALcode RESET entry point.  */
+    for (i = 0; i < smp_cpus; ++i) {
+        cpus[i]->env.pal_mode = 1;
+        cpus[i]->env.pc = palcode_entry;
+        cpus[i]->env.palbr = palcode_entry;
+    }
+
+    /* Load a kernel.  */
+    if (kernel_filename) {
+        uint64_t param_offset;
+
+        size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys,
+                        NULL, &kernel_entry, &kernel_low, &kernel_high,
+                        0, EM_ALPHA, 0);
+        if (size < 0) {
+            hw_error("could not load kernel '%s'\n", kernel_filename);
+            exit(1);
+        }
+
+        cpus[0]->env.trap_arg1 = kernel_entry;
+
+        param_offset = kernel_low - 0x6000;
+
+        if (kernel_cmdline) {
+            pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline);
+        }
+
+        if (initrd_filename) {
+            long initrd_base, initrd_size;
+
+            initrd_size = get_image_size(initrd_filename);
+            if (initrd_size < 0) {
+                hw_error("could not load initial ram disk '%s'\n",
+                         initrd_filename);
+                exit(1);
+            }
+
+            /* Put the initrd image as high in memory as possible.  */
+            initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK;
+            load_image_targphys(initrd_filename, initrd_base,
+                                ram_size - initrd_base);
+
+            stq_phys(param_offset + 0x100, initrd_base + 0xfffffc0000000000ULL);
+            stq_phys(param_offset + 0x108, initrd_size);
+        }
+    }
+}
+
+static QEMUMachine clipper_machine = {
+    .name = "clipper",
+    .desc = "Alpha DP264/CLIPPER",
+    .init = clipper_init,
+    .max_cpus = 4,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void clipper_machine_init(void)
+{
+    qemu_register_machine(&clipper_machine);
+}
+
+machine_init(clipper_machine_init);
diff --git a/hw/alpha/pci.c b/hw/alpha/pci.c
new file mode 100644
index 0000000..8462868
--- /dev/null
+++ b/hw/alpha/pci.c
@@ -0,0 +1,109 @@
+/*
+ * QEMU Alpha PCI support functions.
+ *
+ * Some of this isn't very Alpha specific at all.
+ *
+ * ??? Sparse memory access not implemented.
+ */
+
+#include "config.h"
+#include "hw/alpha_sys.h"
+#include "qemu/log.h"
+#include "sysemu/sysemu.h"
+
+
+/* PCI IO reads/writes, to byte-word addressable memory.  */
+/* ??? Doesn't handle multiple PCI busses.  */
+
+static uint64_t bw_io_read(void *opaque, hwaddr addr, unsigned size)
+{
+    switch (size) {
+    case 1:
+        return cpu_inb(addr);
+    case 2:
+        return cpu_inw(addr);
+    case 4:
+        return cpu_inl(addr);
+    }
+    abort();
+}
+
+static void bw_io_write(void *opaque, hwaddr addr,
+                        uint64_t val, unsigned size)
+{
+    switch (size) {
+    case 1:
+        cpu_outb(addr, val);
+        break;
+    case 2:
+        cpu_outw(addr, val);
+        break;
+    case 4:
+        cpu_outl(addr, val);
+        break;
+    default:
+        abort();
+    }
+}
+
+const MemoryRegionOps alpha_pci_bw_io_ops = {
+    .read = bw_io_read,
+    .write = bw_io_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+/* PCI config space reads/writes, to byte-word addressable memory.  */
+static uint64_t bw_conf1_read(void *opaque, hwaddr addr,
+                              unsigned size)
+{
+    PCIBus *b = opaque;
+    return pci_data_read(b, addr, size);
+}
+
+static void bw_conf1_write(void *opaque, hwaddr addr,
+                           uint64_t val, unsigned size)
+{
+    PCIBus *b = opaque;
+    pci_data_write(b, addr, val, size);
+}
+
+const MemoryRegionOps alpha_pci_conf1_ops = {
+    .read = bw_conf1_read,
+    .write = bw_conf1_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+/* PCI/EISA Interrupt Acknowledge Cycle.  */
+
+static uint64_t iack_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return pic_read_irq(isa_pic);
+}
+
+static void special_write(void *opaque, hwaddr addr,
+                          uint64_t val, unsigned size)
+{
+    qemu_log("pci: special write cycle");
+}
+
+const MemoryRegionOps alpha_pci_iack_ops = {
+    .read = iack_read,
+    .write = special_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c
deleted file mode 100644
index 13aaa57..0000000
--- a/hw/alpha_dp264.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * QEMU Alpha DP264/CLIPPER hardware system emulator.
- *
- * Choose CLIPPER IRQ mappings over, say, DP264, MONET, or WEBBRICK
- * variants because CLIPPER doesn't have an SMC669 SuperIO controller
- * that we need to emulate as well.
- */
-
-#include "hw/hw.h"
-#include "elf.h"
-#include "hw/loader.h"
-#include "hw/boards.h"
-#include "hw/alpha_sys.h"
-#include "sysemu/sysemu.h"
-#include "hw/mc146818rtc.h"
-#include "hw/ide.h"
-#include "hw/i8254.h"
-#include "hw/serial.h"
-
-#define MAX_IDE_BUS 2
-
-static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr)
-{
-    if (((addr >> 41) & 3) == 2) {
-        addr &= 0xffffffffffull;
-    }
-    return addr;
-}
-
-/* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems.
-    (0) The dev_irq_n lines into the cpu, which we totally ignore,
-    (1) The DRIR lines in the typhoon chipset,
-    (2) The "vector" aka mangled interrupt number reported by SRM PALcode,
-    (3) The interrupt number assigned by the kernel.
-   The following function is concerned with (1) only.  */
-
-static int clipper_pci_map_irq(PCIDevice *d, int irq_num)
-{
-    int slot = d->devfn >> 3;
-
-    assert(irq_num >= 0 && irq_num <= 3);
-
-    return (slot + 1) * 4 + irq_num;
-}
-
-static void clipper_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    AlphaCPU *cpus[4];
-    PCIBus *pci_bus;
-    ISABus *isa_bus;
-    qemu_irq rtc_irq;
-    long size, i;
-    const char *palcode_filename;
-    uint64_t palcode_entry, palcode_low, palcode_high;
-    uint64_t kernel_entry, kernel_low, kernel_high;
-
-    /* Create up to 4 cpus.  */
-    memset(cpus, 0, sizeof(cpus));
-    for (i = 0; i < smp_cpus; ++i) {
-        cpus[i] = cpu_alpha_init(cpu_model ? cpu_model : "ev67");
-    }
-
-    cpus[0]->env.trap_arg0 = ram_size;
-    cpus[0]->env.trap_arg1 = 0;
-    cpus[0]->env.trap_arg2 = smp_cpus;
-
-    /* Init the chipset.  */
-    pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus,
-                           clipper_pci_map_irq);
-
-    rtc_init(isa_bus, 1980, rtc_irq);
-    pit_init(isa_bus, 0x40, 0, NULL);
-    isa_create_simple(isa_bus, "i8042");
-
-    /* VGA setup.  Don't bother loading the bios.  */
-    pci_vga_init(pci_bus);
-
-    /* Serial code setup.  */
-    for (i = 0; i < MAX_SERIAL_PORTS; ++i) {
-        if (serial_hds[i]) {
-            serial_isa_init(isa_bus, i, serial_hds[i]);
-        }
-    }
-
-    /* Network setup.  e1000 is good enough, failing Tulip support.  */
-    for (i = 0; i < nb_nics; i++) {
-        pci_nic_init_nofail(&nd_table[i], "e1000", NULL);
-    }
-
-    /* IDE disk setup.  */
-    {
-        DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-        ide_drive_get(hd, MAX_IDE_BUS);
-
-        pci_cmd646_ide_init(pci_bus, hd, 0);
-    }
-
-    /* Load PALcode.  Given that this is not "real" cpu palcode,
-       but one explicitly written for the emulation, we might as
-       well load it directly from and ELF image.  */
-    palcode_filename = (bios_name ? bios_name : "palcode-clipper");
-    palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, palcode_filename);
-    if (palcode_filename == NULL) {
-        hw_error("no palcode provided\n");
-        exit(1);
-    }
-    size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys,
-                    NULL, &palcode_entry, &palcode_low, &palcode_high,
-                    0, EM_ALPHA, 0);
-    if (size < 0) {
-        hw_error("could not load palcode '%s'\n", palcode_filename);
-        exit(1);
-    }
-
-    /* Start all cpus at the PALcode RESET entry point.  */
-    for (i = 0; i < smp_cpus; ++i) {
-        cpus[i]->env.pal_mode = 1;
-        cpus[i]->env.pc = palcode_entry;
-        cpus[i]->env.palbr = palcode_entry;
-    }
-
-    /* Load a kernel.  */
-    if (kernel_filename) {
-        uint64_t param_offset;
-
-        size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys,
-                        NULL, &kernel_entry, &kernel_low, &kernel_high,
-                        0, EM_ALPHA, 0);
-        if (size < 0) {
-            hw_error("could not load kernel '%s'\n", kernel_filename);
-            exit(1);
-        }
-
-        cpus[0]->env.trap_arg1 = kernel_entry;
-
-        param_offset = kernel_low - 0x6000;
-
-        if (kernel_cmdline) {
-            pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline);
-        }
-
-        if (initrd_filename) {
-            long initrd_base, initrd_size;
-
-            initrd_size = get_image_size(initrd_filename);
-            if (initrd_size < 0) {
-                hw_error("could not load initial ram disk '%s'\n",
-                         initrd_filename);
-                exit(1);
-            }
-
-            /* Put the initrd image as high in memory as possible.  */
-            initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK;
-            load_image_targphys(initrd_filename, initrd_base,
-                                ram_size - initrd_base);
-
-            stq_phys(param_offset + 0x100, initrd_base + 0xfffffc0000000000ULL);
-            stq_phys(param_offset + 0x108, initrd_size);
-        }
-    }
-}
-
-static QEMUMachine clipper_machine = {
-    .name = "clipper",
-    .desc = "Alpha DP264/CLIPPER",
-    .init = clipper_init,
-    .max_cpus = 4,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void clipper_machine_init(void)
-{
-    qemu_register_machine(&clipper_machine);
-}
-
-machine_init(clipper_machine_init);
diff --git a/hw/alpha_pci.c b/hw/alpha_pci.c
deleted file mode 100644
index 8462868..0000000
--- a/hw/alpha_pci.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * QEMU Alpha PCI support functions.
- *
- * Some of this isn't very Alpha specific at all.
- *
- * ??? Sparse memory access not implemented.
- */
-
-#include "config.h"
-#include "hw/alpha_sys.h"
-#include "qemu/log.h"
-#include "sysemu/sysemu.h"
-
-
-/* PCI IO reads/writes, to byte-word addressable memory.  */
-/* ??? Doesn't handle multiple PCI busses.  */
-
-static uint64_t bw_io_read(void *opaque, hwaddr addr, unsigned size)
-{
-    switch (size) {
-    case 1:
-        return cpu_inb(addr);
-    case 2:
-        return cpu_inw(addr);
-    case 4:
-        return cpu_inl(addr);
-    }
-    abort();
-}
-
-static void bw_io_write(void *opaque, hwaddr addr,
-                        uint64_t val, unsigned size)
-{
-    switch (size) {
-    case 1:
-        cpu_outb(addr, val);
-        break;
-    case 2:
-        cpu_outw(addr, val);
-        break;
-    case 4:
-        cpu_outl(addr, val);
-        break;
-    default:
-        abort();
-    }
-}
-
-const MemoryRegionOps alpha_pci_bw_io_ops = {
-    .read = bw_io_read,
-    .write = bw_io_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-    .impl = {
-        .min_access_size = 1,
-        .max_access_size = 4,
-    },
-};
-
-/* PCI config space reads/writes, to byte-word addressable memory.  */
-static uint64_t bw_conf1_read(void *opaque, hwaddr addr,
-                              unsigned size)
-{
-    PCIBus *b = opaque;
-    return pci_data_read(b, addr, size);
-}
-
-static void bw_conf1_write(void *opaque, hwaddr addr,
-                           uint64_t val, unsigned size)
-{
-    PCIBus *b = opaque;
-    pci_data_write(b, addr, val, size);
-}
-
-const MemoryRegionOps alpha_pci_conf1_ops = {
-    .read = bw_conf1_read,
-    .write = bw_conf1_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-    .impl = {
-        .min_access_size = 1,
-        .max_access_size = 4,
-    },
-};
-
-/* PCI/EISA Interrupt Acknowledge Cycle.  */
-
-static uint64_t iack_read(void *opaque, hwaddr addr, unsigned size)
-{
-    return pic_read_irq(isa_pic);
-}
-
-static void special_write(void *opaque, hwaddr addr,
-                          uint64_t val, unsigned size)
-{
-    qemu_log("pci: special write cycle");
-}
-
-const MemoryRegionOps alpha_pci_iack_ops = {
-    .read = iack_read,
-    .write = special_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-    .valid = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-    .impl = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-};
diff --git a/hw/an5206.c b/hw/an5206.c
deleted file mode 100644
index 7c21c66..0000000
--- a/hw/an5206.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Arnewsh 5206 ColdFire system emulation.
- *
- * Copyright (c) 2007 CodeSourcery.
- *
- * This code is licensed under the GPL
- */
-
-#include "hw/hw.h"
-#include "hw/mcf.h"
-#include "hw/boards.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "exec/address-spaces.h"
-
-#define KERNEL_LOAD_ADDR 0x10000
-#define AN5206_MBAR_ADDR 0x10000000
-#define AN5206_RAMBAR_ADDR 0x20000000
-
-/* Board init.  */
-
-static void an5206_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    M68kCPU *cpu;
-    CPUM68KState *env;
-    int kernel_size;
-    uint64_t elf_entry;
-    hwaddr entry;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-
-    if (!cpu_model) {
-        cpu_model = "m5206";
-    }
-    cpu = cpu_m68k_init(cpu_model);
-    if (!cpu) {
-        hw_error("Unable to find m68k CPU definition\n");
-    }
-    env = &cpu->env;
-
-    /* Initialize CPU registers.  */
-    env->vbr = 0;
-    /* TODO: allow changing MBAR and RAMBAR.  */
-    env->mbar = AN5206_MBAR_ADDR | 1;
-    env->rambar0 = AN5206_RAMBAR_ADDR | 1;
-
-    /* DRAM at address zero */
-    memory_region_init_ram(ram, "an5206.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(address_space_mem, 0, ram);
-
-    /* Internal SRAM.  */
-    memory_region_init_ram(sram, "an5206.sram", 512);
-    vmstate_register_ram_global(sram);
-    memory_region_add_subregion(address_space_mem, AN5206_RAMBAR_ADDR, sram);
-
-    mcf5206_init(address_space_mem, AN5206_MBAR_ADDR, cpu);
-
-    /* Load kernel.  */
-    if (!kernel_filename) {
-        fprintf(stderr, "Kernel image must be specified\n");
-        exit(1);
-    }
-
-    kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                           NULL, NULL, 1, ELF_MACHINE, 0);
-    entry = elf_entry;
-    if (kernel_size < 0) {
-        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
-    }
-    if (kernel_size < 0) {
-        kernel_size = load_image_targphys(kernel_filename, KERNEL_LOAD_ADDR,
-                                          ram_size - KERNEL_LOAD_ADDR);
-        entry = KERNEL_LOAD_ADDR;
-    }
-    if (kernel_size < 0) {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
-        exit(1);
-    }
-
-    env->pc = entry;
-}
-
-static QEMUMachine an5206_machine = {
-    .name = "an5206",
-    .desc = "Arnewsh 5206",
-    .init = an5206_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void an5206_machine_init(void)
-{
-    qemu_register_machine(&an5206_machine);
-}
-
-machine_init(an5206_machine_init);
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 3eb1366..c09cc3a 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -1,35 +1,32 @@
-obj-y = integratorcp.o versatilepb.o arm_pic.o
-obj-y += arm_boot.o
-obj-y += xilinx_zynq.o zynq_slcr.o
+obj-y += zynq_slcr.o
 obj-y += xilinx_spips.o
 obj-y += arm_gic.o arm_gic_common.o
 obj-y += a9scu.o
-obj-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
+obj-y += realview_gic.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
-obj-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o
+obj-y += exynos4210_uart.o exynos4210_pwm.o
 obj-y += exynos4210_pmu.o exynos4210_mct.o exynos4210_fimd.o
 obj-y += exynos4210_rtc.o exynos4210_i2c.o
 obj-y += arm_mptimer.o a15mpcore.o
-obj-y += armv7m.o armv7m_nvic.o stellaris.o stellaris_enet.o
-obj-y += highbank.o
+obj-y += armv7m.o armv7m_nvic.o stellaris_enet.o
 obj-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 obj-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
-obj-y += gumstix.o
-obj-y += zaurus.o ide/microdrive.o spitz.o tosa.o tc6393xb.o
+obj-y += zaurus.o ide/microdrive.o tc6393xb.o
 obj-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o \
                 omap_gpio.o omap_intc.o omap_uart.o
 obj-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
                 omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o omap_l4.o
-obj-y += omap_sx1.o palm.o tsc210x.o
-obj-y += nseries.o blizzard.o onenand.o cbus.o tusb6010.o usb/hcd-musb.o
-obj-y += mst_fpga.o mainstone.o
-obj-y += z2.o
-obj-y += musicpal.o bitbang_i2c.o marvell_88w8618_audio.o
+obj-y += tsc210x.o
+obj-y += blizzard.o onenand.o cbus.o tusb6010.o usb/hcd-musb.o
+obj-y += mst_fpga.o
+obj-y += bitbang_i2c.o marvell_88w8618_audio.o
 obj-y += framebuffer.o
-obj-y += vexpress.o
 obj-y += strongarm.o
-obj-y += collie.o
 obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
-obj-y += kzm.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
+obj-y += integratorcp.o kzm.o mainstone.o musicpal.o nseries.o
+obj-y += omap_sx1.o palm.o pic_cpu.o realview.o spitz.o stellaris.o
+obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
new file mode 100644
index 0000000..43253fd
--- /dev/null
+++ b/hw/arm/boot.c
@@ -0,0 +1,480 @@
+/*
+ * ARM kernel loader.
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "config.h"
+#include "hw/hw.h"
+#include "hw/arm-misc.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "sysemu/device_tree.h"
+#include "qemu/config-file.h"
+
+#define KERNEL_ARGS_ADDR 0x100
+#define KERNEL_LOAD_ADDR 0x00010000
+
+/* The worlds second smallest bootloader.  Set r0-r2, then jump to kernel.  */
+static uint32_t bootloader[] = {
+  0xe3a00000, /* mov     r0, #0 */
+  0xe59f1004, /* ldr     r1, [pc, #4] */
+  0xe59f2004, /* ldr     r2, [pc, #4] */
+  0xe59ff004, /* ldr     pc, [pc, #4] */
+  0, /* Board ID */
+  0, /* Address of kernel args.  Set by integratorcp_init.  */
+  0  /* Kernel entry point.  Set by integratorcp_init.  */
+};
+
+/* Handling for secondary CPU boot in a multicore system.
+ * Unlike the uniprocessor/primary CPU boot, this is platform
+ * dependent. The default code here is based on the secondary
+ * CPU boot protocol used on realview/vexpress boards, with
+ * some parameterisation to increase its flexibility.
+ * QEMU platform models for which this code is not appropriate
+ * should override write_secondary_boot and secondary_cpu_reset_hook
+ * instead.
+ *
+ * This code enables the interrupt controllers for the secondary
+ * CPUs and then puts all the secondary CPUs into a loop waiting
+ * for an interprocessor interrupt and polling a configurable
+ * location for the kernel secondary CPU entry point.
+ */
+#define DSB_INSN 0xf57ff04f
+#define CP15_DSB_INSN 0xee070f9a /* mcr cp15, 0, r0, c7, c10, 4 */
+
+static uint32_t smpboot[] = {
+  0xe59f2028, /* ldr r2, gic_cpu_if */
+  0xe59f0028, /* ldr r0, startaddr */
+  0xe3a01001, /* mov r1, #1 */
+  0xe5821000, /* str r1, [r2] - set GICC_CTLR.Enable */
+  0xe3a010ff, /* mov r1, #0xff */
+  0xe5821004, /* str r1, [r2, 4] - set GIC_PMR.Priority to 0xff */
+  DSB_INSN,   /* dsb */
+  0xe320f003, /* wfi */
+  0xe5901000, /* ldr     r1, [r0] */
+  0xe1110001, /* tst     r1, r1 */
+  0x0afffffb, /* beq     <wfi> */
+  0xe12fff11, /* bx      r1 */
+  0,          /* gic_cpu_if: base address of GIC CPU interface */
+  0           /* bootreg: Boot register address is held here */
+};
+
+static void default_write_secondary(ARMCPU *cpu,
+                                    const struct arm_boot_info *info)
+{
+    int n;
+    smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
+    smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr;
+    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
+        /* Replace DSB with the pre-v7 DSB if necessary. */
+        if (!arm_feature(&cpu->env, ARM_FEATURE_V7) &&
+            smpboot[n] == DSB_INSN) {
+            smpboot[n] = CP15_DSB_INSN;
+        }
+        smpboot[n] = tswap32(smpboot[n]);
+    }
+    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
+                       info->smp_loader_start);
+}
+
+static void default_reset_secondary(ARMCPU *cpu,
+                                    const struct arm_boot_info *info)
+{
+    CPUARMState *env = &cpu->env;
+
+    stl_phys_notdirty(info->smp_bootreg_addr, 0);
+    env->regs[15] = info->smp_loader_start;
+}
+
+#define WRITE_WORD(p, value) do { \
+    stl_phys_notdirty(p, value);  \
+    p += 4;                       \
+} while (0)
+
+static void set_kernel_args(const struct arm_boot_info *info)
+{
+    int initrd_size = info->initrd_size;
+    hwaddr base = info->loader_start;
+    hwaddr p;
+
+    p = base + KERNEL_ARGS_ADDR;
+    /* ATAG_CORE */
+    WRITE_WORD(p, 5);
+    WRITE_WORD(p, 0x54410001);
+    WRITE_WORD(p, 1);
+    WRITE_WORD(p, 0x1000);
+    WRITE_WORD(p, 0);
+    /* ATAG_MEM */
+    /* TODO: handle multiple chips on one ATAG list */
+    WRITE_WORD(p, 4);
+    WRITE_WORD(p, 0x54410002);
+    WRITE_WORD(p, info->ram_size);
+    WRITE_WORD(p, info->loader_start);
+    if (initrd_size) {
+        /* ATAG_INITRD2 */
+        WRITE_WORD(p, 4);
+        WRITE_WORD(p, 0x54420005);
+        WRITE_WORD(p, info->initrd_start);
+        WRITE_WORD(p, initrd_size);
+    }
+    if (info->kernel_cmdline && *info->kernel_cmdline) {
+        /* ATAG_CMDLINE */
+        int cmdline_size;
+
+        cmdline_size = strlen(info->kernel_cmdline);
+        cpu_physical_memory_write(p + 8, (void *)info->kernel_cmdline,
+                                  cmdline_size + 1);
+        cmdline_size = (cmdline_size >> 2) + 1;
+        WRITE_WORD(p, cmdline_size + 2);
+        WRITE_WORD(p, 0x54410009);
+        p += cmdline_size * 4;
+    }
+    if (info->atag_board) {
+        /* ATAG_BOARD */
+        int atag_board_len;
+        uint8_t atag_board_buf[0x1000];
+
+        atag_board_len = (info->atag_board(info, atag_board_buf) + 3) & ~3;
+        WRITE_WORD(p, (atag_board_len + 8) >> 2);
+        WRITE_WORD(p, 0x414f4d50);
+        cpu_physical_memory_write(p, atag_board_buf, atag_board_len);
+        p += atag_board_len;
+    }
+    /* ATAG_END */
+    WRITE_WORD(p, 0);
+    WRITE_WORD(p, 0);
+}
+
+static void set_kernel_args_old(const struct arm_boot_info *info)
+{
+    hwaddr p;
+    const char *s;
+    int initrd_size = info->initrd_size;
+    hwaddr base = info->loader_start;
+
+    /* see linux/include/asm-arm/setup.h */
+    p = base + KERNEL_ARGS_ADDR;
+    /* page_size */
+    WRITE_WORD(p, 4096);
+    /* nr_pages */
+    WRITE_WORD(p, info->ram_size / 4096);
+    /* ramdisk_size */
+    WRITE_WORD(p, 0);
+#define FLAG_READONLY	1
+#define FLAG_RDLOAD	4
+#define FLAG_RDPROMPT	8
+    /* flags */
+    WRITE_WORD(p, FLAG_READONLY | FLAG_RDLOAD | FLAG_RDPROMPT);
+    /* rootdev */
+    WRITE_WORD(p, (31 << 8) | 0);	/* /dev/mtdblock0 */
+    /* video_num_cols */
+    WRITE_WORD(p, 0);
+    /* video_num_rows */
+    WRITE_WORD(p, 0);
+    /* video_x */
+    WRITE_WORD(p, 0);
+    /* video_y */
+    WRITE_WORD(p, 0);
+    /* memc_control_reg */
+    WRITE_WORD(p, 0);
+    /* unsigned char sounddefault */
+    /* unsigned char adfsdrives */
+    /* unsigned char bytes_per_char_h */
+    /* unsigned char bytes_per_char_v */
+    WRITE_WORD(p, 0);
+    /* pages_in_bank[4] */
+    WRITE_WORD(p, 0);
+    WRITE_WORD(p, 0);
+    WRITE_WORD(p, 0);
+    WRITE_WORD(p, 0);
+    /* pages_in_vram */
+    WRITE_WORD(p, 0);
+    /* initrd_start */
+    if (initrd_size) {
+        WRITE_WORD(p, info->initrd_start);
+    } else {
+        WRITE_WORD(p, 0);
+    }
+    /* initrd_size */
+    WRITE_WORD(p, initrd_size);
+    /* rd_start */
+    WRITE_WORD(p, 0);
+    /* system_rev */
+    WRITE_WORD(p, 0);
+    /* system_serial_low */
+    WRITE_WORD(p, 0);
+    /* system_serial_high */
+    WRITE_WORD(p, 0);
+    /* mem_fclk_21285 */
+    WRITE_WORD(p, 0);
+    /* zero unused fields */
+    while (p < base + KERNEL_ARGS_ADDR + 256 + 1024) {
+        WRITE_WORD(p, 0);
+    }
+    s = info->kernel_cmdline;
+    if (s) {
+        cpu_physical_memory_write(p, (void *)s, strlen(s) + 1);
+    } else {
+        WRITE_WORD(p, 0);
+    }
+}
+
+static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
+{
+#ifdef CONFIG_FDT
+    uint32_t *mem_reg_property;
+    uint32_t mem_reg_propsize;
+    void *fdt = NULL;
+    char *filename;
+    int size, rc;
+    uint32_t acells, scells, hival;
+
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, binfo->dtb_filename);
+    if (!filename) {
+        fprintf(stderr, "Couldn't open dtb file %s\n", binfo->dtb_filename);
+        return -1;
+    }
+
+    fdt = load_device_tree(filename, &size);
+    if (!fdt) {
+        fprintf(stderr, "Couldn't open dtb file %s\n", filename);
+        g_free(filename);
+        return -1;
+    }
+    g_free(filename);
+
+    acells = qemu_devtree_getprop_cell(fdt, "/", "#address-cells");
+    scells = qemu_devtree_getprop_cell(fdt, "/", "#size-cells");
+    if (acells == 0 || scells == 0) {
+        fprintf(stderr, "dtb file invalid (#address-cells or #size-cells 0)\n");
+        return -1;
+    }
+
+    mem_reg_propsize = acells + scells;
+    mem_reg_property = g_new0(uint32_t, mem_reg_propsize);
+    mem_reg_property[acells - 1] = cpu_to_be32(binfo->loader_start);
+    hival = cpu_to_be32(binfo->loader_start >> 32);
+    if (acells > 1) {
+        mem_reg_property[acells - 2] = hival;
+    } else if (hival != 0) {
+        fprintf(stderr, "qemu: dtb file not compatible with "
+                "RAM start address > 4GB\n");
+        exit(1);
+    }
+    mem_reg_property[acells + scells - 1] = cpu_to_be32(binfo->ram_size);
+    hival = cpu_to_be32(binfo->ram_size >> 32);
+    if (scells > 1) {
+        mem_reg_property[acells + scells - 2] = hival;
+    } else if (hival != 0) {
+        fprintf(stderr, "qemu: dtb file not compatible with "
+                "RAM size > 4GB\n");
+        exit(1);
+    }
+
+    rc = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
+                              mem_reg_propsize * sizeof(uint32_t));
+    if (rc < 0) {
+        fprintf(stderr, "couldn't set /memory/reg\n");
+    }
+
+    if (binfo->kernel_cmdline && *binfo->kernel_cmdline) {
+        rc = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
+                                          binfo->kernel_cmdline);
+        if (rc < 0) {
+            fprintf(stderr, "couldn't set /chosen/bootargs\n");
+        }
+    }
+
+    if (binfo->initrd_size) {
+        rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
+                binfo->initrd_start);
+        if (rc < 0) {
+            fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
+        }
+
+        rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
+                    binfo->initrd_start + binfo->initrd_size);
+        if (rc < 0) {
+            fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
+        }
+    }
+
+    cpu_physical_memory_write(addr, fdt, size);
+
+    return 0;
+
+#else
+    fprintf(stderr, "Device tree requested, "
+                "but qemu was compiled without fdt support\n");
+    return -1;
+#endif
+}
+
+static void do_cpu_reset(void *opaque)
+{
+    ARMCPU *cpu = opaque;
+    CPUARMState *env = &cpu->env;
+    const struct arm_boot_info *info = env->boot_info;
+
+    cpu_reset(CPU(cpu));
+    if (info) {
+        if (!info->is_linux) {
+            /* Jump to the entry point.  */
+            env->regs[15] = info->entry & 0xfffffffe;
+            env->thumb = info->entry & 1;
+        } else {
+            if (env == first_cpu) {
+                env->regs[15] = info->loader_start;
+                if (!info->dtb_filename) {
+                    if (old_param) {
+                        set_kernel_args_old(info);
+                    } else {
+                        set_kernel_args(info);
+                    }
+                }
+            } else {
+                info->secondary_cpu_reset_hook(cpu, info);
+            }
+        }
+    }
+}
+
+void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
+{
+    CPUARMState *env = &cpu->env;
+    int kernel_size;
+    int initrd_size;
+    int n;
+    int is_linux = 0;
+    uint64_t elf_entry;
+    hwaddr entry;
+    int big_endian;
+    QemuOpts *machine_opts;
+
+    /* Load the kernel.  */
+    if (!info->kernel_filename) {
+        fprintf(stderr, "Kernel image must be specified\n");
+        exit(1);
+    }
+
+    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
+    if (machine_opts) {
+        info->dtb_filename = qemu_opt_get(machine_opts, "dtb");
+    } else {
+        info->dtb_filename = NULL;
+    }
+
+    if (!info->secondary_cpu_reset_hook) {
+        info->secondary_cpu_reset_hook = default_reset_secondary;
+    }
+    if (!info->write_secondary_boot) {
+        info->write_secondary_boot = default_write_secondary;
+    }
+
+    if (info->nb_cpus == 0)
+        info->nb_cpus = 1;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    big_endian = 1;
+#else
+    big_endian = 0;
+#endif
+
+    /* We want to put the initrd far enough into RAM that when the
+     * kernel is uncompressed it will not clobber the initrd. However
+     * on boards without much RAM we must ensure that we still leave
+     * enough room for a decent sized initrd, and on boards with large
+     * amounts of RAM we must avoid the initrd being so far up in RAM
+     * that it is outside lowmem and inaccessible to the kernel.
+     * So for boards with less  than 256MB of RAM we put the initrd
+     * halfway into RAM, and for boards with 256MB of RAM or more we put
+     * the initrd at 128MB.
+     */
+    info->initrd_start = info->loader_start +
+        MIN(info->ram_size / 2, 128 * 1024 * 1024);
+
+    /* Assume that raw images are linux kernels, and ELF images are not.  */
+    kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
+                           NULL, NULL, big_endian, ELF_MACHINE, 1);
+    entry = elf_entry;
+    if (kernel_size < 0) {
+        kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
+                                  &is_linux);
+    }
+    if (kernel_size < 0) {
+        entry = info->loader_start + KERNEL_LOAD_ADDR;
+        kernel_size = load_image_targphys(info->kernel_filename, entry,
+                                          info->ram_size - KERNEL_LOAD_ADDR);
+        is_linux = 1;
+    }
+    if (kernel_size < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                info->kernel_filename);
+        exit(1);
+    }
+    info->entry = entry;
+    if (is_linux) {
+        if (info->initrd_filename) {
+            initrd_size = load_image_targphys(info->initrd_filename,
+                                              info->initrd_start,
+                                              info->ram_size -
+                                              info->initrd_start);
+            if (initrd_size < 0) {
+                fprintf(stderr, "qemu: could not load initrd '%s'\n",
+                        info->initrd_filename);
+                exit(1);
+            }
+        } else {
+            initrd_size = 0;
+        }
+        info->initrd_size = initrd_size;
+
+        bootloader[4] = info->board_id;
+
+        /* for device tree boot, we pass the DTB directly in r2. Otherwise
+         * we point to the kernel args.
+         */
+        if (info->dtb_filename) {
+            /* Place the DTB after the initrd in memory. Note that some
+             * kernels will trash anything in the 4K page the initrd
+             * ends in, so make sure the DTB isn't caught up in that.
+             */
+            hwaddr dtb_start = QEMU_ALIGN_UP(info->initrd_start + initrd_size,
+                                             4096);
+            if (load_dtb(dtb_start, info)) {
+                exit(1);
+            }
+            bootloader[5] = dtb_start;
+        } else {
+            bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR;
+            if (info->ram_size >= (1ULL << 32)) {
+                fprintf(stderr, "qemu: RAM size must be less than 4GB to boot"
+                        " Linux kernel using ATAGS (try passing a device tree"
+                        " using -dtb)\n");
+                exit(1);
+            }
+        }
+        bootloader[6] = entry;
+        for (n = 0; n < sizeof(bootloader) / 4; n++) {
+            bootloader[n] = tswap32(bootloader[n]);
+        }
+        rom_add_blob_fixed("bootloader", bootloader, sizeof(bootloader),
+                           info->loader_start);
+        if (info->nb_cpus > 1) {
+            info->write_secondary_boot(cpu, info);
+        }
+    }
+    info->is_linux = is_linux;
+
+    for (; env; env = env->next_cpu) {
+        cpu = arm_env_get_cpu(env);
+        env->boot_info = info;
+        qemu_register_reset(do_cpu_reset, cpu);
+    }
+}
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
new file mode 100644
index 0000000..17fddc8
--- /dev/null
+++ b/hw/arm/collie.c
@@ -0,0 +1,73 @@
+/*
+ * SA-1110-based Sharp Zaurus SL-5500 platform.
+ *
+ * Copyright (C) 2011 Dmitry Eremin-Solenikov
+ *
+ * This code is licensed under GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+#include "hw/hw.h"
+#include "hw/sysbus.h"
+#include "hw/boards.h"
+#include "hw/devices.h"
+#include "hw/strongarm.h"
+#include "hw/arm-misc.h"
+#include "hw/flash.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+static struct arm_boot_info collie_binfo = {
+    .loader_start = SA_SDCS0,
+    .ram_size = 0x20000000,
+};
+
+static void collie_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    StrongARMState *s;
+    DriveInfo *dinfo;
+    MemoryRegion *sysmem = get_system_memory();
+
+    if (!cpu_model) {
+        cpu_model = "sa1110";
+    }
+
+    s = sa1110_init(sysmem, collie_binfo.ram_size, cpu_model);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    pflash_cfi01_register(SA_CS0, NULL, "collie.fl1", 0x02000000,
+                    dinfo ? dinfo->bdrv : NULL, (64 * 1024),
+                    512, 4, 0x00, 0x00, 0x00, 0x00, 0);
+
+    dinfo = drive_get(IF_PFLASH, 0, 1);
+    pflash_cfi01_register(SA_CS1, NULL, "collie.fl2", 0x02000000,
+                    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->cpu, &collie_binfo);
+}
+
+static QEMUMachine collie_machine = {
+    .name = "collie",
+    .desc = "Collie PDA (SA-1110)",
+    .init = collie_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void collie_machine_init(void)
+{
+    qemu_register_machine(&collie_machine);
+}
+
+machine_init(collie_machine_init)
diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
new file mode 100644
index 0000000..473da34
--- /dev/null
+++ b/hw/arm/exynos4_boards.c
@@ -0,0 +1,170 @@
+/*
+ *  Samsung exynos4 SoC based boards emulation
+ *
+ *  Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *    Maksim Kozlov <m.kozlov at samsung.com>
+ *    Evgeny Voevodin <e.voevodin at samsung.com>
+ *    Igor Mitsyanko  <i.mitsyanko at samsung.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+#include "net/net.h"
+#include "hw/arm-misc.h"
+#include "exec/address-spaces.h"
+#include "hw/exynos4210.h"
+#include "hw/boards.h"
+
+#undef DEBUG
+
+//#define DEBUG
+
+#ifdef DEBUG
+    #undef PRINT_DEBUG
+    #define  PRINT_DEBUG(fmt, args...) \
+        do { \
+            fprintf(stderr, "  [%s:%d]   "fmt, __func__, __LINE__, ##args); \
+        } while (0)
+#else
+    #define  PRINT_DEBUG(fmt, args...)  do {} while (0)
+#endif
+
+#define SMDK_LAN9118_BASE_ADDR      0x05000000
+
+typedef enum Exynos4BoardType {
+    EXYNOS4_BOARD_NURI,
+    EXYNOS4_BOARD_SMDKC210,
+    EXYNOS4_NUM_OF_BOARDS
+} Exynos4BoardType;
+
+static int exynos4_board_id[EXYNOS4_NUM_OF_BOARDS] = {
+    [EXYNOS4_BOARD_NURI]     = 0xD33,
+    [EXYNOS4_BOARD_SMDKC210] = 0xB16,
+};
+
+static int exynos4_board_smp_bootreg_addr[EXYNOS4_NUM_OF_BOARDS] = {
+    [EXYNOS4_BOARD_NURI]     = EXYNOS4210_SECOND_CPU_BOOTREG,
+    [EXYNOS4_BOARD_SMDKC210] = EXYNOS4210_SECOND_CPU_BOOTREG,
+};
+
+static unsigned long exynos4_board_ram_size[EXYNOS4_NUM_OF_BOARDS] = {
+    [EXYNOS4_BOARD_NURI]     = 0x40000000,
+    [EXYNOS4_BOARD_SMDKC210] = 0x40000000,
+};
+
+static struct arm_boot_info exynos4_board_binfo = {
+    .loader_start     = EXYNOS4210_BASE_BOOT_ADDR,
+    .smp_loader_start = EXYNOS4210_SMP_BOOT_ADDR,
+    .nb_cpus          = EXYNOS4210_NCPUS,
+    .write_secondary_boot = exynos4210_write_secondary,
+};
+
+static QEMUMachine exynos4_machines[EXYNOS4_NUM_OF_BOARDS];
+
+static void lan9215_init(uint32_t base, qemu_irq irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    /* This should be a 9215 but the 9118 is close enough */
+    if (nd_table[0].used) {
+        qemu_check_nic_model(&nd_table[0], "lan9118");
+        dev = qdev_create(NULL, "lan9118");
+        qdev_set_nic_properties(dev, &nd_table[0]);
+        qdev_prop_set_uint32(dev, "mode_16bit", 1);
+        qdev_init_nofail(dev);
+        s = SYS_BUS_DEVICE(dev);
+        sysbus_mmio_map(s, 0, base);
+        sysbus_connect_irq(s, 0, irq);
+    }
+}
+
+static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args,
+                                                   Exynos4BoardType board_type)
+{
+    if (smp_cpus != EXYNOS4210_NCPUS) {
+        fprintf(stderr, "%s board supports only %d CPU cores. Ignoring smp_cpus"
+                " value.\n",
+                exynos4_machines[board_type].name,
+                exynos4_machines[board_type].max_cpus);
+    }
+
+    exynos4_board_binfo.ram_size = exynos4_board_ram_size[board_type];
+    exynos4_board_binfo.board_id = exynos4_board_id[board_type];
+    exynos4_board_binfo.smp_bootreg_addr =
+            exynos4_board_smp_bootreg_addr[board_type];
+    exynos4_board_binfo.kernel_filename = args->kernel_filename;
+    exynos4_board_binfo.initrd_filename = args->initrd_filename;
+    exynos4_board_binfo.kernel_cmdline = args->kernel_cmdline;
+    exynos4_board_binfo.gic_cpu_if_addr =
+            EXYNOS4210_SMP_PRIVATE_BASE_ADDR + 0x100;
+
+    PRINT_DEBUG("\n ram_size: %luMiB [0x%08lx]\n"
+            " kernel_filename: %s\n"
+            " kernel_cmdline: %s\n"
+            " initrd_filename: %s\n",
+            exynos4_board_ram_size[board_type] / 1048576,
+            exynos4_board_ram_size[board_type],
+            args->kernel_filename,
+            args->kernel_cmdline,
+            args->initrd_filename);
+
+    return exynos4210_init(get_system_memory(),
+            exynos4_board_ram_size[board_type]);
+}
+
+static void nuri_init(QEMUMachineInitArgs *args)
+{
+    exynos4_boards_init_common(args, EXYNOS4_BOARD_NURI);
+
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
+}
+
+static void smdkc210_init(QEMUMachineInitArgs *args)
+{
+    Exynos4210State *s = exynos4_boards_init_common(args,
+                                                    EXYNOS4_BOARD_SMDKC210);
+
+    lan9215_init(SMDK_LAN9118_BASE_ADDR,
+            qemu_irq_invert(s->irq_table[exynos4210_get_irq(37, 1)]));
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
+}
+
+static QEMUMachine exynos4_machines[EXYNOS4_NUM_OF_BOARDS] = {
+    [EXYNOS4_BOARD_NURI] = {
+        .name = "nuri",
+        .desc = "Samsung NURI board (Exynos4210)",
+        .init = nuri_init,
+        .max_cpus = EXYNOS4210_NCPUS,
+        DEFAULT_MACHINE_OPTIONS,
+    },
+    [EXYNOS4_BOARD_SMDKC210] = {
+        .name = "smdkc210",
+        .desc = "Samsung SMDKC210 board (Exynos4210)",
+        .init = smdkc210_init,
+        .max_cpus = EXYNOS4210_NCPUS,
+        DEFAULT_MACHINE_OPTIONS,
+    },
+};
+
+static void exynos4_machine_init(void)
+{
+    qemu_register_machine(&exynos4_machines[EXYNOS4_BOARD_NURI]);
+    qemu_register_machine(&exynos4_machines[EXYNOS4_BOARD_SMDKC210]);
+}
+
+machine_init(exynos4_machine_init);
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
new file mode 100644
index 0000000..8859b73
--- /dev/null
+++ b/hw/arm/gumstix.c
@@ -0,0 +1,141 @@
+/*
+ * Gumstix Platforms
+ *
+ * Copyright (c) 2007 by Thorsten Zitterell <info at bitmux.org>
+ *
+ * Code based on spitz platform by Andrzej Zaborowski <balrog at zabor.org>
+ *
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+ 
+/* 
+ * Example usage:
+ * 
+ * connex:
+ * =======
+ * create image:
+ * # dd of=flash bs=1k count=16k if=/dev/zero
+ * # dd of=flash bs=1k conv=notrunc if=u-boot.bin
+ * # dd of=flash bs=1k conv=notrunc seek=256 if=rootfs.arm_nofpu.jffs2
+ * start it:
+ * # qemu-system-arm -M connex -pflash flash -monitor null -nographic
+ *
+ * verdex:
+ * =======
+ * create image:
+ * # dd of=flash bs=1k count=32k if=/dev/zero
+ * # dd of=flash bs=1k conv=notrunc if=u-boot.bin
+ * # dd of=flash bs=1k conv=notrunc seek=256 if=rootfs.arm_nofpu.jffs2
+ * # dd of=flash bs=1k conv=notrunc seek=31744 if=uImage
+ * start it:
+ * # qemu-system-arm -M verdex -pflash flash -monitor null -nographic -m 289
+ */
+
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "net/net.h"
+#include "hw/flash.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+static const int sector_len = 128 * 1024;
+
+static void connex_init(QEMUMachineInitArgs *args)
+{
+    PXA2xxState *cpu;
+    DriveInfo *dinfo;
+    int be;
+    MemoryRegion *address_space_mem = get_system_memory();
+
+    uint32_t connex_rom = 0x01000000;
+    uint32_t connex_ram = 0x04000000;
+
+    cpu = pxa255_init(address_space_mem, connex_ram);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (!dinfo) {
+        fprintf(stderr, "A flash image must be given with the "
+                "'pflash' parameter\n");
+        exit(1);
+    }
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    be = 1;
+#else
+    be = 0;
+#endif
+    if (!pflash_cfi01_register(0x00000000, NULL, "connext.rom", connex_rom,
+                               dinfo->bdrv, sector_len, connex_rom / sector_len,
+                               2, 0, 0, 0, 0, be)) {
+        fprintf(stderr, "qemu: Error registering flash memory.\n");
+        exit(1);
+    }
+
+    /* Interrupt line of NIC is connected to GPIO line 36 */
+    smc91c111_init(&nd_table[0], 0x04000300,
+                    qdev_get_gpio_in(cpu->gpio, 36));
+}
+
+static void verdex_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    PXA2xxState *cpu;
+    DriveInfo *dinfo;
+    int be;
+    MemoryRegion *address_space_mem = get_system_memory();
+
+    uint32_t verdex_rom = 0x02000000;
+    uint32_t verdex_ram = 0x10000000;
+
+    cpu = pxa270_init(address_space_mem, verdex_ram, cpu_model ?: "pxa270-c0");
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (!dinfo) {
+        fprintf(stderr, "A flash image must be given with the "
+                "'pflash' parameter\n");
+        exit(1);
+    }
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    be = 1;
+#else
+    be = 0;
+#endif
+    if (!pflash_cfi01_register(0x00000000, NULL, "verdex.rom", verdex_rom,
+                               dinfo->bdrv, sector_len, verdex_rom / sector_len,
+                               2, 0, 0, 0, 0, be)) {
+        fprintf(stderr, "qemu: Error registering flash memory.\n");
+        exit(1);
+    }
+
+    /* Interrupt line of NIC is connected to GPIO line 99 */
+    smc91c111_init(&nd_table[0], 0x04000300,
+                    qdev_get_gpio_in(cpu->gpio, 99));
+}
+
+static QEMUMachine connex_machine = {
+    .name = "connex",
+    .desc = "Gumstix Connex (PXA255)",
+    .init = connex_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine verdex_machine = {
+    .name = "verdex",
+    .desc = "Gumstix Verdex (PXA270)",
+    .init = verdex_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void gumstix_machine_init(void)
+{
+    qemu_register_machine(&connex_machine);
+    qemu_register_machine(&verdex_machine);
+}
+
+machine_init(gumstix_machine_init);
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
new file mode 100644
index 0000000..a622224
--- /dev/null
+++ b/hw/arm/highbank.c
@@ -0,0 +1,342 @@
+/*
+ * Calxeda Highbank SoC emulation
+ *
+ * Copyright (c) 2010-2012 Calxeda
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "hw/loader.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/sysbus.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+#define SMP_BOOT_ADDR 0x100
+#define SMP_BOOT_REG  0x40
+#define GIC_BASE_ADDR 0xfff10000
+
+#define NIRQ_GIC      160
+
+/* Board init.  */
+
+static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
+{
+    int n;
+    uint32_t smpboot[] = {
+        0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 - read current core id */
+        0xe210000f, /* ands r0, r0, #0x0f */
+        0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */
+        0xe0830200, /* add r0, r3, r0, lsl #4 */
+        0xe59f2024, /* ldr r2, privbase */
+        0xe3a01001, /* mov r1, #1 */
+        0xe5821100, /* str r1, [r2, #256] - set GICC_CTLR.Enable */
+        0xe3a010ff, /* mov r1, #0xff */
+        0xe5821104, /* str r1, [r2, #260] - set GICC_PMR.Priority to 0xff */
+        0xf57ff04f, /* dsb */
+        0xe320f003, /* wfi */
+        0xe5901000, /* ldr     r1, [r0] */
+        0xe1110001, /* tst     r1, r1 */
+        0x0afffffb, /* beq     <wfi> */
+        0xe12fff11, /* bx      r1 */
+        GIC_BASE_ADDR      /* privbase: gic address.  */
+    };
+    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
+        smpboot[n] = tswap32(smpboot[n]);
+    }
+    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR);
+}
+
+static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
+{
+    CPUARMState *env = &cpu->env;
+
+    switch (info->nb_cpus) {
+    case 4:
+        stl_phys_notdirty(SMP_BOOT_REG + 0x30, 0);
+    case 3:
+        stl_phys_notdirty(SMP_BOOT_REG + 0x20, 0);
+    case 2:
+        stl_phys_notdirty(SMP_BOOT_REG + 0x10, 0);
+        env->regs[15] = SMP_BOOT_ADDR;
+        break;
+    default:
+        break;
+    }
+}
+
+#define NUM_REGS      0x200
+static void hb_regs_write(void *opaque, hwaddr offset,
+                          uint64_t value, unsigned size)
+{
+    uint32_t *regs = opaque;
+
+    if (offset == 0xf00) {
+        if (value == 1 || value == 2) {
+            qemu_system_reset_request();
+        } else if (value == 3) {
+            qemu_system_shutdown_request();
+        }
+    }
+
+    regs[offset/4] = value;
+}
+
+static uint64_t hb_regs_read(void *opaque, hwaddr offset,
+                             unsigned size)
+{
+    uint32_t *regs = opaque;
+    uint32_t value = regs[offset/4];
+
+    if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) {
+        value |= 0x30000000;
+    }
+
+    return value;
+}
+
+static const MemoryRegionOps hb_mem_ops = {
+    .read = hb_regs_read,
+    .write = hb_regs_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion *iomem;
+    uint32_t regs[NUM_REGS];
+} HighbankRegsState;
+
+static VMStateDescription vmstate_highbank_regs = {
+    .name = "highbank-regs",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, HighbankRegsState, NUM_REGS),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static void highbank_regs_reset(DeviceState *dev)
+{
+    SysBusDevice *sys_dev = SYS_BUS_DEVICE(dev);
+    HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, sys_dev);
+
+    s->regs[0x40] = 0x05F20121;
+    s->regs[0x41] = 0x2;
+    s->regs[0x42] = 0x05F30121;
+    s->regs[0x43] = 0x05F40121;
+}
+
+static int highbank_regs_init(SysBusDevice *dev)
+{
+    HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, dev);
+
+    s->iomem = g_new(MemoryRegion, 1);
+    memory_region_init_io(s->iomem, &hb_mem_ops, s->regs, "highbank_regs",
+                          0x1000);
+    sysbus_init_mmio(dev, s->iomem);
+
+    return 0;
+}
+
+static void highbank_regs_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    sbc->init = highbank_regs_init;
+    dc->desc = "Calxeda Highbank registers";
+    dc->vmsd = &vmstate_highbank_regs;
+    dc->reset = highbank_regs_reset;
+}
+
+static const TypeInfo highbank_regs_info = {
+    .name          = "highbank-regs",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(HighbankRegsState),
+    .class_init    = highbank_regs_class_init,
+};
+
+static void highbank_regs_register_types(void)
+{
+    type_register_static(&highbank_regs_info);
+}
+
+type_init(highbank_regs_register_types)
+
+static struct arm_boot_info highbank_binfo;
+
+/* ram_size must be set to match the upper bound of memory in the
+ * device tree (linux/arch/arm/boot/dts/highbank.dts), which is
+ * normally 0xff900000 or -m 4089. When running this board on a
+ * 32-bit host, set the reg value of memory to 0xf7ff00000 in the
+ * device tree and pass -m 2047 to QEMU.
+ */
+static void highbank_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[128];
+    int n;
+    qemu_irq cpu_irq[4];
+    MemoryRegion *sysram;
+    MemoryRegion *dram;
+    MemoryRegion *sysmem;
+    char *sysboot_filename;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        ARMCPU *cpu;
+        cpu = cpu_arm_init(cpu_model);
+        if (cpu == NULL) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+
+        /* This will become a QOM property eventually */
+        cpu->reset_cbar = GIC_BASE_ADDR;
+        irqp = arm_pic_init_cpu(cpu);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+    }
+
+    sysmem = get_system_memory();
+    dram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(dram, "highbank.dram", ram_size);
+    /* SDRAM at address zero.  */
+    memory_region_add_subregion(sysmem, 0, dram);
+
+    sysram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
+    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
+    if (bios_name != NULL) {
+        sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (sysboot_filename != NULL) {
+            uint32_t filesize = get_image_size(sysboot_filename);
+            if (load_image_targphys("sysram.bin", 0xfff88000, filesize) < 0) {
+                hw_error("Unable to load %s\n", bios_name);
+            }
+        } else {
+           hw_error("Unable to find %s\n", bios_name);
+        }
+    }
+
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, GIC_BASE_ADDR);
+    for (n = 0; n < smp_cpus; n++) {
+        sysbus_connect_irq(busdev, n, cpu_irq[n]);
+    }
+
+    for (n = 0; n < 128; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    dev = qdev_create(NULL, "l2x0");
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff12000);
+
+    dev = qdev_create(NULL, "sp804");
+    qdev_prop_set_uint32(dev, "freq0", 150000000);
+    qdev_prop_set_uint32(dev, "freq1", 150000000);
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff34000);
+    sysbus_connect_irq(busdev, 0, pic[18]);
+    sysbus_create_simple("pl011", 0xfff36000, pic[20]);
+
+    dev = qdev_create(NULL, "highbank-regs");
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff3c000);
+
+    sysbus_create_simple("pl061", 0xfff30000, pic[14]);
+    sysbus_create_simple("pl061", 0xfff31000, pic[15]);
+    sysbus_create_simple("pl061", 0xfff32000, pic[16]);
+    sysbus_create_simple("pl061", 0xfff33000, pic[17]);
+    sysbus_create_simple("pl031", 0xfff35000, pic[19]);
+    sysbus_create_simple("pl022", 0xfff39000, pic[23]);
+
+    sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]);
+
+    if (nd_table[0].used) {
+        qemu_check_nic_model(&nd_table[0], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[0]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff50000);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[77]);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[78]);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[79]);
+
+        qemu_check_nic_model(&nd_table[1], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[1]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff51000);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[80]);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[81]);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[82]);
+    }
+
+    highbank_binfo.ram_size = ram_size;
+    highbank_binfo.kernel_filename = kernel_filename;
+    highbank_binfo.kernel_cmdline = kernel_cmdline;
+    highbank_binfo.initrd_filename = initrd_filename;
+    /* highbank requires a dtb in order to boot, and the dtb will override
+     * the board ID. The following value is ignored, so set it to -1 to be
+     * clear that the value is meaningless.
+     */
+    highbank_binfo.board_id = -1;
+    highbank_binfo.nb_cpus = smp_cpus;
+    highbank_binfo.loader_start = 0;
+    highbank_binfo.write_secondary_boot = hb_write_secondary;
+    highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &highbank_binfo);
+}
+
+static QEMUMachine highbank_machine = {
+    .name = "highbank",
+    .desc = "Calxeda Highbank (ECX-1000)",
+    .init = highbank_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void highbank_machine_init(void)
+{
+    qemu_register_machine(&highbank_machine);
+}
+
+machine_init(highbank_machine_init);
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
new file mode 100644
index 0000000..e0ba327
--- /dev/null
+++ b/hw/arm/integratorcp.c
@@ -0,0 +1,566 @@
+/*
+ * ARM Integrator CP System emulation.
+ *
+ * Copyright (c) 2005-2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL
+ */
+
+#include "hw/sysbus.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/arm-misc.h"
+#include "net/net.h"
+#include "exec/address-spaces.h"
+#include "sysemu/sysemu.h"
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t memsz;
+    MemoryRegion flash;
+    uint32_t cm_osc;
+    uint32_t cm_ctrl;
+    uint32_t cm_lock;
+    uint32_t cm_auxosc;
+    uint32_t cm_sdram;
+    uint32_t cm_init;
+    uint32_t cm_flags;
+    uint32_t cm_nvflags;
+    uint32_t int_level;
+    uint32_t irq_enabled;
+    uint32_t fiq_enabled;
+} integratorcm_state;
+
+static uint8_t integrator_spd[128] = {
+   128, 8, 4, 11, 9, 1, 64, 0,  2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
+   0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
+};
+
+static uint64_t integratorcm_read(void *opaque, hwaddr offset,
+                                  unsigned size)
+{
+    integratorcm_state *s = (integratorcm_state *)opaque;
+    if (offset >= 0x100 && offset < 0x200) {
+        /* CM_SPD */
+        if (offset >= 0x180)
+            return 0;
+        return integrator_spd[offset >> 2];
+    }
+    switch (offset >> 2) {
+    case 0: /* CM_ID */
+        return 0x411a3001;
+    case 1: /* CM_PROC */
+        return 0;
+    case 2: /* CM_OSC */
+        return s->cm_osc;
+    case 3: /* CM_CTRL */
+        return s->cm_ctrl;
+    case 4: /* CM_STAT */
+        return 0x00100000;
+    case 5: /* CM_LOCK */
+        if (s->cm_lock == 0xa05f) {
+            return 0x1a05f;
+        } else {
+            return s->cm_lock;
+        }
+    case 6: /* CM_LMBUSCNT */
+        /* ??? High frequency timer.  */
+        hw_error("integratorcm_read: CM_LMBUSCNT");
+    case 7: /* CM_AUXOSC */
+        return s->cm_auxosc;
+    case 8: /* CM_SDRAM */
+        return s->cm_sdram;
+    case 9: /* CM_INIT */
+        return s->cm_init;
+    case 10: /* CM_REFCT */
+        /* ??? High frequency timer.  */
+        hw_error("integratorcm_read: CM_REFCT");
+    case 12: /* CM_FLAGS */
+        return s->cm_flags;
+    case 14: /* CM_NVFLAGS */
+        return s->cm_nvflags;
+    case 16: /* CM_IRQ_STAT */
+        return s->int_level & s->irq_enabled;
+    case 17: /* CM_IRQ_RSTAT */
+        return s->int_level;
+    case 18: /* CM_IRQ_ENSET */
+        return s->irq_enabled;
+    case 20: /* CM_SOFT_INTSET */
+        return s->int_level & 1;
+    case 24: /* CM_FIQ_STAT */
+        return s->int_level & s->fiq_enabled;
+    case 25: /* CM_FIQ_RSTAT */
+        return s->int_level;
+    case 26: /* CM_FIQ_ENSET */
+        return s->fiq_enabled;
+    case 32: /* CM_VOLTAGE_CTL0 */
+    case 33: /* CM_VOLTAGE_CTL1 */
+    case 34: /* CM_VOLTAGE_CTL2 */
+    case 35: /* CM_VOLTAGE_CTL3 */
+        /* ??? Voltage control unimplemented.  */
+        return 0;
+    default:
+        hw_error("integratorcm_read: Unimplemented offset 0x%x\n",
+                 (int)offset);
+        return 0;
+    }
+}
+
+static void integratorcm_do_remap(integratorcm_state *s)
+{
+    /* Sync memory region state with CM_CTRL REMAP bit:
+     * bit 0 => flash at address 0; bit 1 => RAM
+     */
+    memory_region_set_enabled(&s->flash, !(s->cm_ctrl & 4));
+}
+
+static void integratorcm_set_ctrl(integratorcm_state *s, uint32_t value)
+{
+    if (value & 8) {
+        qemu_system_reset_request();
+    }
+    if ((s->cm_ctrl ^ value) & 1) {
+        /* (value & 1) != 0 means the green "MISC LED" is lit.
+         * We don't have any nice place to display LEDs. printf is a bad
+         * idea because Linux uses the LED as a heartbeat and the output
+         * will swamp anything else on the terminal.
+         */
+    }
+    /* Note that the RESET bit [3] always reads as zero */
+    s->cm_ctrl = (s->cm_ctrl & ~5) | (value & 5);
+    integratorcm_do_remap(s);
+}
+
+static void integratorcm_update(integratorcm_state *s)
+{
+    /* ??? The CPU irq/fiq is raised when either the core module or base PIC
+       are active.  */
+    if (s->int_level & (s->irq_enabled | s->fiq_enabled))
+        hw_error("Core module interrupt\n");
+}
+
+static void integratorcm_write(void *opaque, hwaddr offset,
+                               uint64_t value, unsigned size)
+{
+    integratorcm_state *s = (integratorcm_state *)opaque;
+    switch (offset >> 2) {
+    case 2: /* CM_OSC */
+        if (s->cm_lock == 0xa05f)
+            s->cm_osc = value;
+        break;
+    case 3: /* CM_CTRL */
+        integratorcm_set_ctrl(s, value);
+        break;
+    case 5: /* CM_LOCK */
+        s->cm_lock = value & 0xffff;
+        break;
+    case 7: /* CM_AUXOSC */
+        if (s->cm_lock == 0xa05f)
+            s->cm_auxosc = value;
+        break;
+    case 8: /* CM_SDRAM */
+        s->cm_sdram = value;
+        break;
+    case 9: /* CM_INIT */
+        /* ??? This can change the memory bus frequency.  */
+        s->cm_init = value;
+        break;
+    case 12: /* CM_FLAGSS */
+        s->cm_flags |= value;
+        break;
+    case 13: /* CM_FLAGSC */
+        s->cm_flags &= ~value;
+        break;
+    case 14: /* CM_NVFLAGSS */
+        s->cm_nvflags |= value;
+        break;
+    case 15: /* CM_NVFLAGSS */
+        s->cm_nvflags &= ~value;
+        break;
+    case 18: /* CM_IRQ_ENSET */
+        s->irq_enabled |= value;
+        integratorcm_update(s);
+        break;
+    case 19: /* CM_IRQ_ENCLR */
+        s->irq_enabled &= ~value;
+        integratorcm_update(s);
+        break;
+    case 20: /* CM_SOFT_INTSET */
+        s->int_level |= (value & 1);
+        integratorcm_update(s);
+        break;
+    case 21: /* CM_SOFT_INTCLR */
+        s->int_level &= ~(value & 1);
+        integratorcm_update(s);
+        break;
+    case 26: /* CM_FIQ_ENSET */
+        s->fiq_enabled |= value;
+        integratorcm_update(s);
+        break;
+    case 27: /* CM_FIQ_ENCLR */
+        s->fiq_enabled &= ~value;
+        integratorcm_update(s);
+        break;
+    case 32: /* CM_VOLTAGE_CTL0 */
+    case 33: /* CM_VOLTAGE_CTL1 */
+    case 34: /* CM_VOLTAGE_CTL2 */
+    case 35: /* CM_VOLTAGE_CTL3 */
+        /* ??? Voltage control unimplemented.  */
+        break;
+    default:
+        hw_error("integratorcm_write: Unimplemented offset 0x%x\n",
+                 (int)offset);
+        break;
+    }
+}
+
+/* Integrator/CM control registers.  */
+
+static const MemoryRegionOps integratorcm_ops = {
+    .read = integratorcm_read,
+    .write = integratorcm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int integratorcm_init(SysBusDevice *dev)
+{
+    integratorcm_state *s = FROM_SYSBUS(integratorcm_state, dev);
+
+    s->cm_osc = 0x01000048;
+    /* ??? What should the high bits of this value be?  */
+    s->cm_auxosc = 0x0007feff;
+    s->cm_sdram = 0x00011122;
+    if (s->memsz >= 256) {
+        integrator_spd[31] = 64;
+        s->cm_sdram |= 0x10;
+    } else if (s->memsz >= 128) {
+        integrator_spd[31] = 32;
+        s->cm_sdram |= 0x0c;
+    } else if (s->memsz >= 64) {
+        integrator_spd[31] = 16;
+        s->cm_sdram |= 0x08;
+    } else if (s->memsz >= 32) {
+        integrator_spd[31] = 4;
+        s->cm_sdram |= 0x04;
+    } else {
+        integrator_spd[31] = 2;
+    }
+    memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
+    s->cm_init = 0x00000112;
+    memory_region_init_ram(&s->flash, "integrator.flash", 0x100000);
+    vmstate_register_ram_global(&s->flash);
+
+    memory_region_init_io(&s->iomem, &integratorcm_ops, s,
+                          "integratorcm", 0x00800000);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    integratorcm_do_remap(s);
+    /* ??? Save/restore.  */
+    return 0;
+}
+
+/* Integrator/CP hardware emulation.  */
+/* Primary interrupt controller.  */
+
+typedef struct icp_pic_state
+{
+  SysBusDevice busdev;
+  MemoryRegion iomem;
+  uint32_t level;
+  uint32_t irq_enabled;
+  uint32_t fiq_enabled;
+  qemu_irq parent_irq;
+  qemu_irq parent_fiq;
+} icp_pic_state;
+
+static void icp_pic_update(icp_pic_state *s)
+{
+    uint32_t flags;
+
+    flags = (s->level & s->irq_enabled);
+    qemu_set_irq(s->parent_irq, flags != 0);
+    flags = (s->level & s->fiq_enabled);
+    qemu_set_irq(s->parent_fiq, flags != 0);
+}
+
+static void icp_pic_set_irq(void *opaque, int irq, int level)
+{
+    icp_pic_state *s = (icp_pic_state *)opaque;
+    if (level)
+        s->level |= 1 << irq;
+    else
+        s->level &= ~(1 << irq);
+    icp_pic_update(s);
+}
+
+static uint64_t icp_pic_read(void *opaque, hwaddr offset,
+                             unsigned size)
+{
+    icp_pic_state *s = (icp_pic_state *)opaque;
+
+    switch (offset >> 2) {
+    case 0: /* IRQ_STATUS */
+        return s->level & s->irq_enabled;
+    case 1: /* IRQ_RAWSTAT */
+        return s->level;
+    case 2: /* IRQ_ENABLESET */
+        return s->irq_enabled;
+    case 4: /* INT_SOFTSET */
+        return s->level & 1;
+    case 8: /* FRQ_STATUS */
+        return s->level & s->fiq_enabled;
+    case 9: /* FRQ_RAWSTAT */
+        return s->level;
+    case 10: /* FRQ_ENABLESET */
+        return s->fiq_enabled;
+    case 3: /* IRQ_ENABLECLR */
+    case 5: /* INT_SOFTCLR */
+    case 11: /* FRQ_ENABLECLR */
+    default:
+        printf ("icp_pic_read: Bad register offset 0x%x\n", (int)offset);
+        return 0;
+    }
+}
+
+static void icp_pic_write(void *opaque, hwaddr offset,
+                          uint64_t value, unsigned size)
+{
+    icp_pic_state *s = (icp_pic_state *)opaque;
+
+    switch (offset >> 2) {
+    case 2: /* IRQ_ENABLESET */
+        s->irq_enabled |= value;
+        break;
+    case 3: /* IRQ_ENABLECLR */
+        s->irq_enabled &= ~value;
+        break;
+    case 4: /* INT_SOFTSET */
+        if (value & 1)
+            icp_pic_set_irq(s, 0, 1);
+        break;
+    case 5: /* INT_SOFTCLR */
+        if (value & 1)
+            icp_pic_set_irq(s, 0, 0);
+        break;
+    case 10: /* FRQ_ENABLESET */
+        s->fiq_enabled |= value;
+        break;
+    case 11: /* FRQ_ENABLECLR */
+        s->fiq_enabled &= ~value;
+        break;
+    case 0: /* IRQ_STATUS */
+    case 1: /* IRQ_RAWSTAT */
+    case 8: /* FRQ_STATUS */
+    case 9: /* FRQ_RAWSTAT */
+    default:
+        printf ("icp_pic_write: Bad register offset 0x%x\n", (int)offset);
+        return;
+    }
+    icp_pic_update(s);
+}
+
+static const MemoryRegionOps icp_pic_ops = {
+    .read = icp_pic_read,
+    .write = icp_pic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int icp_pic_init(SysBusDevice *dev)
+{
+    icp_pic_state *s = FROM_SYSBUS(icp_pic_state, dev);
+
+    qdev_init_gpio_in(&dev->qdev, icp_pic_set_irq, 32);
+    sysbus_init_irq(dev, &s->parent_irq);
+    sysbus_init_irq(dev, &s->parent_fiq);
+    memory_region_init_io(&s->iomem, &icp_pic_ops, s, "icp-pic", 0x00800000);
+    sysbus_init_mmio(dev, &s->iomem);
+    return 0;
+}
+
+/* CP control registers.  */
+
+static uint64_t icp_control_read(void *opaque, hwaddr offset,
+                                 unsigned size)
+{
+    switch (offset >> 2) {
+    case 0: /* CP_IDFIELD */
+        return 0x41034003;
+    case 1: /* CP_FLASHPROG */
+        return 0;
+    case 2: /* CP_INTREG */
+        return 0;
+    case 3: /* CP_DECODE */
+        return 0x11;
+    default:
+        hw_error("icp_control_read: Bad offset %x\n", (int)offset);
+        return 0;
+    }
+}
+
+static void icp_control_write(void *opaque, hwaddr offset,
+                          uint64_t value, unsigned size)
+{
+    switch (offset >> 2) {
+    case 1: /* CP_FLASHPROG */
+    case 2: /* CP_INTREG */
+    case 3: /* CP_DECODE */
+        /* Nothing interesting implemented yet.  */
+        break;
+    default:
+        hw_error("icp_control_write: Bad offset %x\n", (int)offset);
+    }
+}
+
+static const MemoryRegionOps icp_control_ops = {
+    .read = icp_control_read,
+    .write = icp_control_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void icp_control_init(hwaddr base)
+{
+    MemoryRegion *io;
+
+    io = (MemoryRegion *)g_malloc0(sizeof(MemoryRegion));
+    memory_region_init_io(io, &icp_control_ops, NULL,
+                          "control", 0x00800000);
+    memory_region_add_subregion(get_system_memory(), base, io);
+    /* ??? Save/restore.  */
+}
+
+
+/* Board init.  */
+
+static struct arm_boot_info integrator_binfo = {
+    .loader_start = 0x0,
+    .board_id = 0x113,
+};
+
+static void integratorcp_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    ARMCPU *cpu;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
+    qemu_irq pic[32];
+    qemu_irq *cpu_pic;
+    DeviceState *dev;
+    int i;
+
+    if (!cpu_model) {
+        cpu_model = "arm926";
+    }
+    cpu = cpu_arm_init(cpu_model);
+    if (!cpu) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+
+    memory_region_init_ram(ram, "integrator.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
+    /* ??? RAM should repeat to fill physical memory space.  */
+    /* SDRAM at address zero*/
+    memory_region_add_subregion(address_space_mem, 0, ram);
+    /* And again at address 0x80000000 */
+    memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size);
+    memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
+
+    dev = qdev_create(NULL, "integrator_core");
+    qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
+
+    cpu_pic = arm_pic_init_cpu(cpu);
+    dev = sysbus_create_varargs("integrator_pic", 0x14000000,
+                                cpu_pic[ARM_PIC_CPU_IRQ],
+                                cpu_pic[ARM_PIC_CPU_FIQ], NULL);
+    for (i = 0; i < 32; i++) {
+        pic[i] = qdev_get_gpio_in(dev, i);
+    }
+    sysbus_create_simple("integrator_pic", 0xca000000, pic[26]);
+    sysbus_create_varargs("integrator_pit", 0x13000000,
+                          pic[5], pic[6], pic[7], NULL);
+    sysbus_create_simple("pl031", 0x15000000, pic[8]);
+    sysbus_create_simple("pl011", 0x16000000, pic[1]);
+    sysbus_create_simple("pl011", 0x17000000, pic[2]);
+    icp_control_init(0xcb000000);
+    sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
+    sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]);
+    sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL);
+    if (nd_table[0].used)
+        smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
+
+    sysbus_create_simple("pl110", 0xc0000000, pic[22]);
+
+    integrator_binfo.ram_size = ram_size;
+    integrator_binfo.kernel_filename = kernel_filename;
+    integrator_binfo.kernel_cmdline = kernel_cmdline;
+    integrator_binfo.initrd_filename = initrd_filename;
+    arm_load_kernel(cpu, &integrator_binfo);
+}
+
+static QEMUMachine integratorcp_machine = {
+    .name = "integratorcp",
+    .desc = "ARM Integrator/CP (ARM926EJ-S)",
+    .init = integratorcp_init,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void integratorcp_machine_init(void)
+{
+    qemu_register_machine(&integratorcp_machine);
+}
+
+machine_init(integratorcp_machine_init);
+
+static Property core_properties[] = {
+    DEFINE_PROP_UINT32("memsz", integratorcm_state, memsz, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void core_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = integratorcm_init;
+    dc->props = core_properties;
+}
+
+static const TypeInfo core_info = {
+    .name          = "integrator_core",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(integratorcm_state),
+    .class_init    = core_class_init,
+};
+
+static void icp_pic_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = icp_pic_init;
+}
+
+static const TypeInfo icp_pic_info = {
+    .name          = "integrator_pic",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(icp_pic_state),
+    .class_init    = icp_pic_class_init,
+};
+
+static void integratorcp_register_types(void)
+{
+    type_register_static(&icp_pic_info);
+    type_register_static(&core_info);
+}
+
+type_init(integratorcp_register_types)
diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c
new file mode 100644
index 0000000..ec50a31
--- /dev/null
+++ b/hw/arm/kzm.c
@@ -0,0 +1,157 @@
+/*
+ * KZM Board System emulation.
+ *
+ * Copyright (c) 2008 OKL and 2011 NICTA
+ * Written by Hans at OK-Labs
+ * Updated by Peter Chubb.
+ *
+ * This code is licensed under the GPL, version 2 or later.
+ * See the file `COPYING' in the top level directory.
+ *
+ * It (partially) emulates a Kyoto Microcomputer
+ * KZM-ARM11-01 evaluation board, with a Freescale
+ * i.MX31 SoC
+ */
+
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+#include "hw/hw.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/serial.h"
+#include "hw/imx.h"
+
+    /* Memory map for Kzm Emulation Baseboard:
+     * 0x00000000-0x00003fff 16k secure ROM       IGNORED
+     * 0x00004000-0x00407fff Reserved             IGNORED
+     * 0x00404000-0x00407fff ROM                  IGNORED
+     * 0x00408000-0x0fffffff Reserved             IGNORED
+     * 0x10000000-0x1fffbfff RAM aliasing         IGNORED
+     * 0x1fffc000-0x1fffffff RAM                  EMULATED
+     * 0x20000000-0x2fffffff Reserved             IGNORED
+     * 0x30000000-0x7fffffff I.MX31 Internal Register Space
+     *   0x43f00000 IO_AREA0
+     *   0x43f90000 UART1                         EMULATED
+     *   0x43f94000 UART2                         EMULATED
+     *   0x68000000 AVIC                          EMULATED
+     *   0x53f80000 CCM                           EMULATED
+     *   0x53f94000 PIT 1                         EMULATED
+     *   0x53f98000 PIT 2                         EMULATED
+     *   0x53f90000 GPT                           EMULATED
+     * 0x80000000-0x87ffffff RAM                  EMULATED
+     * 0x88000000-0x8fffffff RAM Aliasing         EMULATED
+     * 0xa0000000-0xafffffff NAND Flash           IGNORED
+     * 0xb0000000-0xb3ffffff Unavailable          IGNORED
+     * 0xb4000000-0xb4000fff 8-bit free space     IGNORED
+     * 0xb4001000-0xb400100f Board control        IGNORED
+     *  0xb4001003           DIP switch
+     * 0xb4001010-0xb400101f 7-segment LED        IGNORED
+     * 0xb4001020-0xb400102f LED                  IGNORED
+     * 0xb4001030-0xb400103f LED                  IGNORED
+     * 0xb4001040-0xb400104f FPGA, UART           EMULATED
+     * 0xb4001050-0xb400105f FPGA, UART           EMULATED
+     * 0xb4001060-0xb40fffff FPGA                 IGNORED
+     * 0xb6000000-0xb61fffff LAN controller       EMULATED
+     * 0xb6200000-0xb62fffff FPGA NAND Controller IGNORED
+     * 0xb6300000-0xb7ffffff Free                 IGNORED
+     * 0xb8000000-0xb8004fff Memory control registers IGNORED
+     * 0xc0000000-0xc3ffffff PCMCIA/CF            IGNORED
+     * 0xc4000000-0xffffffff Reserved             IGNORED
+     */
+
+#define KZM_RAMADDRESS (0x80000000)
+#define KZM_FPGA       (0xb4001040)
+
+static struct arm_boot_info kzm_binfo = {
+    .loader_start = KZM_RAMADDRESS,
+    .board_id = 1722,
+};
+
+static void kzm_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    ARMCPU *cpu;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
+    qemu_irq *cpu_pic;
+    DeviceState *dev;
+    DeviceState *ccm;
+
+    if (!cpu_model) {
+        cpu_model = "arm1136";
+    }
+
+    cpu = cpu_arm_init(cpu_model);
+    if (!cpu) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+
+    /* On a real system, the first 16k is a `secure boot rom' */
+
+    memory_region_init_ram(ram, "kzm.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(address_space_mem, KZM_RAMADDRESS, ram);
+
+    memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size);
+    memory_region_add_subregion(address_space_mem, 0x88000000, ram_alias);
+
+    memory_region_init_ram(sram, "kzm.sram", 0x4000);
+    memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram);
+
+    cpu_pic = arm_pic_init_cpu(cpu);
+    dev = sysbus_create_varargs("imx_avic", 0x68000000,
+                                cpu_pic[ARM_PIC_CPU_IRQ],
+                                cpu_pic[ARM_PIC_CPU_FIQ], NULL);
+
+
+    imx_serial_create(0, 0x43f90000, qdev_get_gpio_in(dev, 45));
+    imx_serial_create(1, 0x43f94000, qdev_get_gpio_in(dev, 32));
+
+    ccm = sysbus_create_simple("imx_ccm", 0x53f80000, NULL);
+
+    imx_timerp_create(0x53f94000, qdev_get_gpio_in(dev, 28), ccm);
+    imx_timerp_create(0x53f98000, qdev_get_gpio_in(dev, 27), ccm);
+    imx_timerg_create(0x53f90000, qdev_get_gpio_in(dev, 29), ccm);
+
+    if (nd_table[0].used) {
+        lan9118_init(&nd_table[0], 0xb6000000, qdev_get_gpio_in(dev, 52));
+    }
+
+    if (serial_hds[2]) { /* touchscreen */
+        serial_mm_init(address_space_mem, KZM_FPGA+0x10, 0,
+                       qdev_get_gpio_in(dev, 52),
+                       14745600, serial_hds[2],
+                       DEVICE_NATIVE_ENDIAN);
+    }
+
+    kzm_binfo.ram_size = ram_size;
+    kzm_binfo.kernel_filename = kernel_filename;
+    kzm_binfo.kernel_cmdline = kernel_cmdline;
+    kzm_binfo.initrd_filename = initrd_filename;
+    kzm_binfo.nb_cpus = 1;
+    arm_load_kernel(cpu, &kzm_binfo);
+}
+
+static QEMUMachine kzm_machine = {
+    .name = "kzm",
+    .desc = "ARM KZM Emulation Baseboard (ARM1136)",
+    .init = kzm_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void kzm_machine_init(void)
+{
+    qemu_register_machine(&kzm_machine);
+}
+
+machine_init(kzm_machine_init)
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
new file mode 100644
index 0000000..aea908f
--- /dev/null
+++ b/hw/arm/mainstone.c
@@ -0,0 +1,190 @@
+/*
+ * PXA270-based Intel Mainstone platforms.
+ *
+ * Copyright (c) 2007 by Armin Kuster <akuster at kama-aina.net> or
+ *                                    <akuster at mvista.com>
+ *
+ * Code based on spitz platform by Andrzej Zaborowski <balrog at zabor.org>
+ *
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/arm-misc.h"
+#include "net/net.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/flash.h"
+#include "sysemu/blockdev.h"
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+
+/* Device addresses */
+#define MST_FPGA_PHYS	0x08000000
+#define MST_ETH_PHYS	0x10000300
+#define MST_FLASH_0		0x00000000
+#define MST_FLASH_1		0x04000000
+
+/* IRQ definitions */
+#define MMC_IRQ       0
+#define USIM_IRQ      1
+#define USBC_IRQ      2
+#define ETHERNET_IRQ  3
+#define AC97_IRQ      4
+#define PEN_IRQ       5
+#define MSINS_IRQ     6
+#define EXBRD_IRQ     7
+#define S0_CD_IRQ     9
+#define S0_STSCHG_IRQ 10
+#define S0_IRQ        11
+#define S1_CD_IRQ     13
+#define S1_STSCHG_IRQ 14
+#define S1_IRQ        15
+
+static struct keymap map[0xE0] = {
+    [0 ... 0xDF] = { -1, -1 },
+    [0x1e] = {0,0}, /* a */
+    [0x30] = {0,1}, /* b */
+    [0x2e] = {0,2}, /* c */
+    [0x20] = {0,3}, /* d */
+    [0x12] = {0,4}, /* e */
+    [0x21] = {0,5}, /* f */
+    [0x22] = {1,0}, /* g */
+    [0x23] = {1,1}, /* h */
+    [0x17] = {1,2}, /* i */
+    [0x24] = {1,3}, /* j */
+    [0x25] = {1,4}, /* k */
+    [0x26] = {1,5}, /* l */
+    [0x32] = {2,0}, /* m */
+    [0x31] = {2,1}, /* n */
+    [0x18] = {2,2}, /* o */
+    [0x19] = {2,3}, /* p */
+    [0x10] = {2,4}, /* q */
+    [0x13] = {2,5}, /* r */
+    [0x1f] = {3,0}, /* s */
+    [0x14] = {3,1}, /* t */
+    [0x16] = {3,2}, /* u */
+    [0x2f] = {3,3}, /* v */
+    [0x11] = {3,4}, /* w */
+    [0x2d] = {3,5}, /* x */
+    [0x15] = {4,2}, /* y */
+    [0x2c] = {4,3}, /* z */
+    [0xc7] = {5,0}, /* Home */
+    [0x2a] = {5,1}, /* shift */
+    [0x39] = {5,2}, /* space */
+    [0x39] = {5,3}, /* space */
+    [0x1c] = {5,5}, /*  enter */
+    [0xc8] = {6,0}, /* up */
+    [0xd0] = {6,1}, /* down */
+    [0xcb] = {6,2}, /* left */
+    [0xcd] = {6,3}, /* right */
+};
+
+enum mainstone_model_e { mainstone };
+
+#define MAINSTONE_RAM	0x04000000
+#define MAINSTONE_ROM	0x00800000
+#define MAINSTONE_FLASH	0x02000000
+
+static struct arm_boot_info mainstone_binfo = {
+    .loader_start = PXA2XX_SDRAM_BASE,
+    .ram_size = 0x04000000,
+};
+
+static void mainstone_common_init(MemoryRegion *address_space_mem,
+                                  QEMUMachineInitArgs *args,
+                                  enum mainstone_model_e model, int arm_id)
+{
+    uint32_t sector_len = 256 * 1024;
+    hwaddr mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 };
+    PXA2xxState *mpu;
+    DeviceState *mst_irq;
+    DriveInfo *dinfo;
+    int i;
+    int be;
+    MemoryRegion *rom = g_new(MemoryRegion, 1);
+    const char *cpu_model = args->cpu_model;
+
+    if (!cpu_model)
+        cpu_model = "pxa270-c5";
+
+    /* Setup CPU & memory */
+    mpu = pxa270_init(address_space_mem, mainstone_binfo.ram_size, cpu_model);
+    memory_region_init_ram(rom, "mainstone.rom", MAINSTONE_ROM);
+    vmstate_register_ram_global(rom);
+    memory_region_set_readonly(rom, true);
+    memory_region_add_subregion(address_space_mem, 0, rom);
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    be = 1;
+#else
+    be = 0;
+#endif
+    /* There are two 32MiB flash devices on the board */
+    for (i = 0; i < 2; i ++) {
+        dinfo = drive_get(IF_PFLASH, 0, i);
+        if (!dinfo) {
+            fprintf(stderr, "Two flash images must be given with the "
+                    "'pflash' parameter\n");
+            exit(1);
+        }
+
+        if (!pflash_cfi01_register(mainstone_flash_base[i], NULL,
+                                   i ? "mainstone.flash1" : "mainstone.flash0",
+                                   MAINSTONE_FLASH,
+                                   dinfo->bdrv, sector_len,
+                                   MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0,
+                                   be)) {
+            fprintf(stderr, "qemu: Error registering flash memory.\n");
+            exit(1);
+        }
+    }
+
+    mst_irq = sysbus_create_simple("mainstone-fpga", MST_FPGA_PHYS,
+                    qdev_get_gpio_in(mpu->gpio, 0));
+
+    /* setup keypad */
+    printf("map addr %p\n", &map);
+    pxa27x_register_keypad(mpu->kp, map, 0xe0);
+
+    /* MMC/SD host */
+    pxa2xx_mmci_handlers(mpu->mmc, NULL, qdev_get_gpio_in(mst_irq, MMC_IRQ));
+
+    pxa2xx_pcmcia_set_irq_cb(mpu->pcmcia[0],
+            qdev_get_gpio_in(mst_irq, S0_IRQ),
+            qdev_get_gpio_in(mst_irq, S0_CD_IRQ));
+    pxa2xx_pcmcia_set_irq_cb(mpu->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));
+
+    mainstone_binfo.kernel_filename = args->kernel_filename;
+    mainstone_binfo.kernel_cmdline = args->kernel_cmdline;
+    mainstone_binfo.initrd_filename = args->initrd_filename;
+    mainstone_binfo.board_id = arm_id;
+    arm_load_kernel(mpu->cpu, &mainstone_binfo);
+}
+
+static void mainstone_init(QEMUMachineInitArgs *args)
+{
+    mainstone_common_init(get_system_memory(), args, mainstone, 0x196);
+}
+
+static QEMUMachine mainstone2_machine = {
+    .name = "mainstone",
+    .desc = "Mainstone II (PXA27x)",
+    .init = mainstone_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void mainstone_machine_init(void)
+{
+    qemu_register_machine(&mainstone2_machine);
+}
+
+machine_init(mainstone_machine_init);
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
new file mode 100644
index 0000000..a37dbd7
--- /dev/null
+++ b/hw/arm/musicpal.c
@@ -0,0 +1,1697 @@
+/*
+ * Marvell MV88W8618 / Freecom MusicPal emulation.
+ *
+ * Copyright (c) 2008 Jan Kiszka
+ *
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/serial.h"
+#include "qemu/timer.h"
+#include "hw/ptimer.h"
+#include "block/block.h"
+#include "hw/flash.h"
+#include "ui/console.h"
+#include "hw/i2c.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+#include "ui/pixel_ops.h"
+
+#define MP_MISC_BASE            0x80002000
+#define MP_MISC_SIZE            0x00001000
+
+#define MP_ETH_BASE             0x80008000
+#define MP_ETH_SIZE             0x00001000
+
+#define MP_WLAN_BASE            0x8000C000
+#define MP_WLAN_SIZE            0x00000800
+
+#define MP_UART1_BASE           0x8000C840
+#define MP_UART2_BASE           0x8000C940
+
+#define MP_GPIO_BASE            0x8000D000
+#define MP_GPIO_SIZE            0x00001000
+
+#define MP_FLASHCFG_BASE        0x90006000
+#define MP_FLASHCFG_SIZE        0x00001000
+
+#define MP_AUDIO_BASE           0x90007000
+
+#define MP_PIC_BASE             0x90008000
+#define MP_PIC_SIZE             0x00001000
+
+#define MP_PIT_BASE             0x90009000
+#define MP_PIT_SIZE             0x00001000
+
+#define MP_LCD_BASE             0x9000c000
+#define MP_LCD_SIZE             0x00001000
+
+#define MP_SRAM_BASE            0xC0000000
+#define MP_SRAM_SIZE            0x00020000
+
+#define MP_RAM_DEFAULT_SIZE     32*1024*1024
+#define MP_FLASH_SIZE_MAX       32*1024*1024
+
+#define MP_TIMER1_IRQ           4
+#define MP_TIMER2_IRQ           5
+#define MP_TIMER3_IRQ           6
+#define MP_TIMER4_IRQ           7
+#define MP_EHCI_IRQ             8
+#define MP_ETH_IRQ              9
+#define MP_UART1_IRQ            11
+#define MP_UART2_IRQ            11
+#define MP_GPIO_IRQ             12
+#define MP_RTC_IRQ              28
+#define MP_AUDIO_IRQ            30
+
+/* Wolfson 8750 I2C address */
+#define MP_WM_ADDR              0x1A
+
+/* Ethernet register offsets */
+#define MP_ETH_SMIR             0x010
+#define MP_ETH_PCXR             0x408
+#define MP_ETH_SDCMR            0x448
+#define MP_ETH_ICR              0x450
+#define MP_ETH_IMR              0x458
+#define MP_ETH_FRDP0            0x480
+#define MP_ETH_FRDP1            0x484
+#define MP_ETH_FRDP2            0x488
+#define MP_ETH_FRDP3            0x48C
+#define MP_ETH_CRDP0            0x4A0
+#define MP_ETH_CRDP1            0x4A4
+#define MP_ETH_CRDP2            0x4A8
+#define MP_ETH_CRDP3            0x4AC
+#define MP_ETH_CTDP0            0x4E0
+#define MP_ETH_CTDP1            0x4E4
+#define MP_ETH_CTDP2            0x4E8
+#define MP_ETH_CTDP3            0x4EC
+
+/* MII PHY access */
+#define MP_ETH_SMIR_DATA        0x0000FFFF
+#define MP_ETH_SMIR_ADDR        0x03FF0000
+#define MP_ETH_SMIR_OPCODE      (1 << 26) /* Read value */
+#define MP_ETH_SMIR_RDVALID     (1 << 27)
+
+/* PHY registers */
+#define MP_ETH_PHY1_BMSR        0x00210000
+#define MP_ETH_PHY1_PHYSID1     0x00410000
+#define MP_ETH_PHY1_PHYSID2     0x00610000
+
+#define MP_PHY_BMSR_LINK        0x0004
+#define MP_PHY_BMSR_AUTONEG     0x0008
+
+#define MP_PHY_88E3015          0x01410E20
+
+/* TX descriptor status */
+#define MP_ETH_TX_OWN           (1 << 31)
+
+/* RX descriptor status */
+#define MP_ETH_RX_OWN           (1 << 31)
+
+/* Interrupt cause/mask bits */
+#define MP_ETH_IRQ_RX_BIT       0
+#define MP_ETH_IRQ_RX           (1 << MP_ETH_IRQ_RX_BIT)
+#define MP_ETH_IRQ_TXHI_BIT     2
+#define MP_ETH_IRQ_TXLO_BIT     3
+
+/* Port config bits */
+#define MP_ETH_PCXR_2BSM_BIT    28 /* 2-byte incoming suffix */
+
+/* SDMA command bits */
+#define MP_ETH_CMD_TXHI         (1 << 23)
+#define MP_ETH_CMD_TXLO         (1 << 22)
+
+typedef struct mv88w8618_tx_desc {
+    uint32_t cmdstat;
+    uint16_t res;
+    uint16_t bytes;
+    uint32_t buffer;
+    uint32_t next;
+} mv88w8618_tx_desc;
+
+typedef struct mv88w8618_rx_desc {
+    uint32_t cmdstat;
+    uint16_t bytes;
+    uint16_t buffer_size;
+    uint32_t buffer;
+    uint32_t next;
+} mv88w8618_rx_desc;
+
+typedef struct mv88w8618_eth_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq irq;
+    uint32_t smir;
+    uint32_t icr;
+    uint32_t imr;
+    int mmio_index;
+    uint32_t vlan_header;
+    uint32_t tx_queue[2];
+    uint32_t rx_queue[4];
+    uint32_t frx_queue[4];
+    uint32_t cur_rx[4];
+    NICState *nic;
+    NICConf conf;
+} mv88w8618_eth_state;
+
+static void eth_rx_desc_put(uint32_t addr, mv88w8618_rx_desc *desc)
+{
+    cpu_to_le32s(&desc->cmdstat);
+    cpu_to_le16s(&desc->bytes);
+    cpu_to_le16s(&desc->buffer_size);
+    cpu_to_le32s(&desc->buffer);
+    cpu_to_le32s(&desc->next);
+    cpu_physical_memory_write(addr, (void *)desc, sizeof(*desc));
+}
+
+static void eth_rx_desc_get(uint32_t addr, mv88w8618_rx_desc *desc)
+{
+    cpu_physical_memory_read(addr, (void *)desc, sizeof(*desc));
+    le32_to_cpus(&desc->cmdstat);
+    le16_to_cpus(&desc->bytes);
+    le16_to_cpus(&desc->buffer_size);
+    le32_to_cpus(&desc->buffer);
+    le32_to_cpus(&desc->next);
+}
+
+static int eth_can_receive(NetClientState *nc)
+{
+    return 1;
+}
+
+static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size)
+{
+    mv88w8618_eth_state *s = qemu_get_nic_opaque(nc);
+    uint32_t desc_addr;
+    mv88w8618_rx_desc desc;
+    int i;
+
+    for (i = 0; i < 4; i++) {
+        desc_addr = s->cur_rx[i];
+        if (!desc_addr) {
+            continue;
+        }
+        do {
+            eth_rx_desc_get(desc_addr, &desc);
+            if ((desc.cmdstat & MP_ETH_RX_OWN) && desc.buffer_size >= size) {
+                cpu_physical_memory_write(desc.buffer + s->vlan_header,
+                                          buf, size);
+                desc.bytes = size + s->vlan_header;
+                desc.cmdstat &= ~MP_ETH_RX_OWN;
+                s->cur_rx[i] = desc.next;
+
+                s->icr |= MP_ETH_IRQ_RX;
+                if (s->icr & s->imr) {
+                    qemu_irq_raise(s->irq);
+                }
+                eth_rx_desc_put(desc_addr, &desc);
+                return size;
+            }
+            desc_addr = desc.next;
+        } while (desc_addr != s->rx_queue[i]);
+    }
+    return size;
+}
+
+static void eth_tx_desc_put(uint32_t addr, mv88w8618_tx_desc *desc)
+{
+    cpu_to_le32s(&desc->cmdstat);
+    cpu_to_le16s(&desc->res);
+    cpu_to_le16s(&desc->bytes);
+    cpu_to_le32s(&desc->buffer);
+    cpu_to_le32s(&desc->next);
+    cpu_physical_memory_write(addr, (void *)desc, sizeof(*desc));
+}
+
+static void eth_tx_desc_get(uint32_t addr, mv88w8618_tx_desc *desc)
+{
+    cpu_physical_memory_read(addr, (void *)desc, sizeof(*desc));
+    le32_to_cpus(&desc->cmdstat);
+    le16_to_cpus(&desc->res);
+    le16_to_cpus(&desc->bytes);
+    le32_to_cpus(&desc->buffer);
+    le32_to_cpus(&desc->next);
+}
+
+static void eth_send(mv88w8618_eth_state *s, int queue_index)
+{
+    uint32_t desc_addr = s->tx_queue[queue_index];
+    mv88w8618_tx_desc desc;
+    uint32_t next_desc;
+    uint8_t buf[2048];
+    int len;
+
+    do {
+        eth_tx_desc_get(desc_addr, &desc);
+        next_desc = desc.next;
+        if (desc.cmdstat & MP_ETH_TX_OWN) {
+            len = desc.bytes;
+            if (len < 2048) {
+                cpu_physical_memory_read(desc.buffer, buf, len);
+                qemu_send_packet(qemu_get_queue(s->nic), buf, len);
+            }
+            desc.cmdstat &= ~MP_ETH_TX_OWN;
+            s->icr |= 1 << (MP_ETH_IRQ_TXLO_BIT - queue_index);
+            eth_tx_desc_put(desc_addr, &desc);
+        }
+        desc_addr = next_desc;
+    } while (desc_addr != s->tx_queue[queue_index]);
+}
+
+static uint64_t mv88w8618_eth_read(void *opaque, hwaddr offset,
+                                   unsigned size)
+{
+    mv88w8618_eth_state *s = opaque;
+
+    switch (offset) {
+    case MP_ETH_SMIR:
+        if (s->smir & MP_ETH_SMIR_OPCODE) {
+            switch (s->smir & MP_ETH_SMIR_ADDR) {
+            case MP_ETH_PHY1_BMSR:
+                return MP_PHY_BMSR_LINK | MP_PHY_BMSR_AUTONEG |
+                       MP_ETH_SMIR_RDVALID;
+            case MP_ETH_PHY1_PHYSID1:
+                return (MP_PHY_88E3015 >> 16) | MP_ETH_SMIR_RDVALID;
+            case MP_ETH_PHY1_PHYSID2:
+                return (MP_PHY_88E3015 & 0xFFFF) | MP_ETH_SMIR_RDVALID;
+            default:
+                return MP_ETH_SMIR_RDVALID;
+            }
+        }
+        return 0;
+
+    case MP_ETH_ICR:
+        return s->icr;
+
+    case MP_ETH_IMR:
+        return s->imr;
+
+    case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
+        return s->frx_queue[(offset - MP_ETH_FRDP0)/4];
+
+    case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
+        return s->rx_queue[(offset - MP_ETH_CRDP0)/4];
+
+    case MP_ETH_CTDP0 ... MP_ETH_CTDP3:
+        return s->tx_queue[(offset - MP_ETH_CTDP0)/4];
+
+    default:
+        return 0;
+    }
+}
+
+static void mv88w8618_eth_write(void *opaque, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+    mv88w8618_eth_state *s = opaque;
+
+    switch (offset) {
+    case MP_ETH_SMIR:
+        s->smir = value;
+        break;
+
+    case MP_ETH_PCXR:
+        s->vlan_header = ((value >> MP_ETH_PCXR_2BSM_BIT) & 1) * 2;
+        break;
+
+    case MP_ETH_SDCMR:
+        if (value & MP_ETH_CMD_TXHI) {
+            eth_send(s, 1);
+        }
+        if (value & MP_ETH_CMD_TXLO) {
+            eth_send(s, 0);
+        }
+        if (value & (MP_ETH_CMD_TXHI | MP_ETH_CMD_TXLO) && s->icr & s->imr) {
+            qemu_irq_raise(s->irq);
+        }
+        break;
+
+    case MP_ETH_ICR:
+        s->icr &= value;
+        break;
+
+    case MP_ETH_IMR:
+        s->imr = value;
+        if (s->icr & s->imr) {
+            qemu_irq_raise(s->irq);
+        }
+        break;
+
+    case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
+        s->frx_queue[(offset - MP_ETH_FRDP0)/4] = value;
+        break;
+
+    case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
+        s->rx_queue[(offset - MP_ETH_CRDP0)/4] =
+            s->cur_rx[(offset - MP_ETH_CRDP0)/4] = value;
+        break;
+
+    case MP_ETH_CTDP0 ... MP_ETH_CTDP3:
+        s->tx_queue[(offset - MP_ETH_CTDP0)/4] = value;
+        break;
+    }
+}
+
+static const MemoryRegionOps mv88w8618_eth_ops = {
+    .read = mv88w8618_eth_read,
+    .write = mv88w8618_eth_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void eth_cleanup(NetClientState *nc)
+{
+    mv88w8618_eth_state *s = qemu_get_nic_opaque(nc);
+
+    s->nic = NULL;
+}
+
+static NetClientInfo net_mv88w8618_info = {
+    .type = NET_CLIENT_OPTIONS_KIND_NIC,
+    .size = sizeof(NICState),
+    .can_receive = eth_can_receive,
+    .receive = eth_receive,
+    .cleanup = eth_cleanup,
+};
+
+static int mv88w8618_eth_init(SysBusDevice *dev)
+{
+    mv88w8618_eth_state *s = FROM_SYSBUS(mv88w8618_eth_state, dev);
+
+    sysbus_init_irq(dev, &s->irq);
+    s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf,
+                          object_get_typename(OBJECT(dev)), dev->qdev.id, s);
+    memory_region_init_io(&s->iomem, &mv88w8618_eth_ops, s, "mv88w8618-eth",
+                          MP_ETH_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
+    return 0;
+}
+
+static const VMStateDescription mv88w8618_eth_vmsd = {
+    .name = "mv88w8618_eth",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(smir, mv88w8618_eth_state),
+        VMSTATE_UINT32(icr, mv88w8618_eth_state),
+        VMSTATE_UINT32(imr, mv88w8618_eth_state),
+        VMSTATE_UINT32(vlan_header, mv88w8618_eth_state),
+        VMSTATE_UINT32_ARRAY(tx_queue, mv88w8618_eth_state, 2),
+        VMSTATE_UINT32_ARRAY(rx_queue, mv88w8618_eth_state, 4),
+        VMSTATE_UINT32_ARRAY(frx_queue, mv88w8618_eth_state, 4),
+        VMSTATE_UINT32_ARRAY(cur_rx, mv88w8618_eth_state, 4),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property mv88w8618_eth_properties[] = {
+    DEFINE_NIC_PROPERTIES(mv88w8618_eth_state, conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void mv88w8618_eth_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = mv88w8618_eth_init;
+    dc->vmsd = &mv88w8618_eth_vmsd;
+    dc->props = mv88w8618_eth_properties;
+}
+
+static const TypeInfo mv88w8618_eth_info = {
+    .name          = "mv88w8618_eth",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(mv88w8618_eth_state),
+    .class_init    = mv88w8618_eth_class_init,
+};
+
+/* LCD register offsets */
+#define MP_LCD_IRQCTRL          0x180
+#define MP_LCD_IRQSTAT          0x184
+#define MP_LCD_SPICTRL          0x1ac
+#define MP_LCD_INST             0x1bc
+#define MP_LCD_DATA             0x1c0
+
+/* Mode magics */
+#define MP_LCD_SPI_DATA         0x00100011
+#define MP_LCD_SPI_CMD          0x00104011
+#define MP_LCD_SPI_INVALID      0x00000000
+
+/* Commmands */
+#define MP_LCD_INST_SETPAGE0    0xB0
+/* ... */
+#define MP_LCD_INST_SETPAGE7    0xB7
+
+#define MP_LCD_TEXTCOLOR        0xe0e0ff /* RRGGBB */
+
+typedef struct musicpal_lcd_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t brightness;
+    uint32_t mode;
+    uint32_t irqctrl;
+    uint32_t page;
+    uint32_t page_off;
+    DisplayState *ds;
+    uint8_t video_ram[128*64/8];
+} musicpal_lcd_state;
+
+static uint8_t scale_lcd_color(musicpal_lcd_state *s, uint8_t col)
+{
+    switch (s->brightness) {
+    case 7:
+        return col;
+    case 0:
+        return 0;
+    default:
+        return (col * s->brightness) / 7;
+    }
+}
+
+#define SET_LCD_PIXEL(depth, type) \
+static inline void glue(set_lcd_pixel, depth) \
+        (musicpal_lcd_state *s, int x, int y, type col) \
+{ \
+    int dx, dy; \
+    type *pixel = &((type *) ds_get_data(s->ds))[(y * 128 * 3 + x) * 3]; \
+\
+    for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
+        for (dx = 0; dx < 3; dx++, pixel++) \
+            *pixel = col; \
+}
+SET_LCD_PIXEL(8, uint8_t)
+SET_LCD_PIXEL(16, uint16_t)
+SET_LCD_PIXEL(32, uint32_t)
+
+static void lcd_refresh(void *opaque)
+{
+    musicpal_lcd_state *s = opaque;
+    int x, y, col;
+
+    switch (ds_get_bits_per_pixel(s->ds)) {
+    case 0:
+        return;
+#define LCD_REFRESH(depth, func) \
+    case depth: \
+        col = func(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff), \
+                   scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff), \
+                   scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff)); \
+        for (x = 0; x < 128; x++) { \
+            for (y = 0; y < 64; y++) { \
+                if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) { \
+                    glue(set_lcd_pixel, depth)(s, x, y, col); \
+                } else { \
+                    glue(set_lcd_pixel, depth)(s, x, y, 0); \
+                } \
+            } \
+        } \
+        break;
+    LCD_REFRESH(8, rgb_to_pixel8)
+    LCD_REFRESH(16, rgb_to_pixel16)
+    LCD_REFRESH(32, (is_surface_bgr(s->ds->surface) ?
+                     rgb_to_pixel32bgr : rgb_to_pixel32))
+    default:
+        hw_error("unsupported colour depth %i\n",
+                  ds_get_bits_per_pixel(s->ds));
+    }
+
+    dpy_gfx_update(s->ds, 0, 0, 128*3, 64*3);
+}
+
+static void lcd_invalidate(void *opaque)
+{
+}
+
+static void musicpal_lcd_gpio_brigthness_in(void *opaque, int irq, int level)
+{
+    musicpal_lcd_state *s = opaque;
+    s->brightness &= ~(1 << irq);
+    s->brightness |= level << irq;
+}
+
+static uint64_t musicpal_lcd_read(void *opaque, hwaddr offset,
+                                  unsigned size)
+{
+    musicpal_lcd_state *s = opaque;
+
+    switch (offset) {
+    case MP_LCD_IRQCTRL:
+        return s->irqctrl;
+
+    default:
+        return 0;
+    }
+}
+
+static void musicpal_lcd_write(void *opaque, hwaddr offset,
+                               uint64_t value, unsigned size)
+{
+    musicpal_lcd_state *s = opaque;
+
+    switch (offset) {
+    case MP_LCD_IRQCTRL:
+        s->irqctrl = value;
+        break;
+
+    case MP_LCD_SPICTRL:
+        if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD) {
+            s->mode = value;
+        } else {
+            s->mode = MP_LCD_SPI_INVALID;
+        }
+        break;
+
+    case MP_LCD_INST:
+        if (value >= MP_LCD_INST_SETPAGE0 && value <= MP_LCD_INST_SETPAGE7) {
+            s->page = value - MP_LCD_INST_SETPAGE0;
+            s->page_off = 0;
+        }
+        break;
+
+    case MP_LCD_DATA:
+        if (s->mode == MP_LCD_SPI_CMD) {
+            if (value >= MP_LCD_INST_SETPAGE0 &&
+                value <= MP_LCD_INST_SETPAGE7) {
+                s->page = value - MP_LCD_INST_SETPAGE0;
+                s->page_off = 0;
+            }
+        } else if (s->mode == MP_LCD_SPI_DATA) {
+            s->video_ram[s->page*128 + s->page_off] = value;
+            s->page_off = (s->page_off + 1) & 127;
+        }
+        break;
+    }
+}
+
+static const MemoryRegionOps musicpal_lcd_ops = {
+    .read = musicpal_lcd_read,
+    .write = musicpal_lcd_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int musicpal_lcd_init(SysBusDevice *dev)
+{
+    musicpal_lcd_state *s = FROM_SYSBUS(musicpal_lcd_state, dev);
+
+    s->brightness = 7;
+
+    memory_region_init_io(&s->iomem, &musicpal_lcd_ops, s,
+                          "musicpal-lcd", MP_LCD_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    s->ds = graphic_console_init(lcd_refresh, lcd_invalidate,
+                                 NULL, NULL, s);
+    qemu_console_resize(s->ds, 128*3, 64*3);
+
+    qdev_init_gpio_in(&dev->qdev, musicpal_lcd_gpio_brigthness_in, 3);
+
+    return 0;
+}
+
+static const VMStateDescription musicpal_lcd_vmsd = {
+    .name = "musicpal_lcd",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(brightness, musicpal_lcd_state),
+        VMSTATE_UINT32(mode, musicpal_lcd_state),
+        VMSTATE_UINT32(irqctrl, musicpal_lcd_state),
+        VMSTATE_UINT32(page, musicpal_lcd_state),
+        VMSTATE_UINT32(page_off, musicpal_lcd_state),
+        VMSTATE_BUFFER(video_ram, musicpal_lcd_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void musicpal_lcd_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = musicpal_lcd_init;
+    dc->vmsd = &musicpal_lcd_vmsd;
+}
+
+static const TypeInfo musicpal_lcd_info = {
+    .name          = "musicpal_lcd",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(musicpal_lcd_state),
+    .class_init    = musicpal_lcd_class_init,
+};
+
+/* PIC register offsets */
+#define MP_PIC_STATUS           0x00
+#define MP_PIC_ENABLE_SET       0x08
+#define MP_PIC_ENABLE_CLR       0x0C
+
+typedef struct mv88w8618_pic_state
+{
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t level;
+    uint32_t enabled;
+    qemu_irq parent_irq;
+} mv88w8618_pic_state;
+
+static void mv88w8618_pic_update(mv88w8618_pic_state *s)
+{
+    qemu_set_irq(s->parent_irq, (s->level & s->enabled));
+}
+
+static void mv88w8618_pic_set_irq(void *opaque, int irq, int level)
+{
+    mv88w8618_pic_state *s = opaque;
+
+    if (level) {
+        s->level |= 1 << irq;
+    } else {
+        s->level &= ~(1 << irq);
+    }
+    mv88w8618_pic_update(s);
+}
+
+static uint64_t mv88w8618_pic_read(void *opaque, hwaddr offset,
+                                   unsigned size)
+{
+    mv88w8618_pic_state *s = opaque;
+
+    switch (offset) {
+    case MP_PIC_STATUS:
+        return s->level & s->enabled;
+
+    default:
+        return 0;
+    }
+}
+
+static void mv88w8618_pic_write(void *opaque, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+    mv88w8618_pic_state *s = opaque;
+
+    switch (offset) {
+    case MP_PIC_ENABLE_SET:
+        s->enabled |= value;
+        break;
+
+    case MP_PIC_ENABLE_CLR:
+        s->enabled &= ~value;
+        s->level &= ~value;
+        break;
+    }
+    mv88w8618_pic_update(s);
+}
+
+static void mv88w8618_pic_reset(DeviceState *d)
+{
+    mv88w8618_pic_state *s = FROM_SYSBUS(mv88w8618_pic_state,
+                                         SYS_BUS_DEVICE(d));
+
+    s->level = 0;
+    s->enabled = 0;
+}
+
+static const MemoryRegionOps mv88w8618_pic_ops = {
+    .read = mv88w8618_pic_read,
+    .write = mv88w8618_pic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int mv88w8618_pic_init(SysBusDevice *dev)
+{
+    mv88w8618_pic_state *s = FROM_SYSBUS(mv88w8618_pic_state, dev);
+
+    qdev_init_gpio_in(&dev->qdev, mv88w8618_pic_set_irq, 32);
+    sysbus_init_irq(dev, &s->parent_irq);
+    memory_region_init_io(&s->iomem, &mv88w8618_pic_ops, s,
+                          "musicpal-pic", MP_PIC_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
+    return 0;
+}
+
+static const VMStateDescription mv88w8618_pic_vmsd = {
+    .name = "mv88w8618_pic",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(level, mv88w8618_pic_state),
+        VMSTATE_UINT32(enabled, mv88w8618_pic_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void mv88w8618_pic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = mv88w8618_pic_init;
+    dc->reset = mv88w8618_pic_reset;
+    dc->vmsd = &mv88w8618_pic_vmsd;
+}
+
+static const TypeInfo mv88w8618_pic_info = {
+    .name          = "mv88w8618_pic",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(mv88w8618_pic_state),
+    .class_init    = mv88w8618_pic_class_init,
+};
+
+/* PIT register offsets */
+#define MP_PIT_TIMER1_LENGTH    0x00
+/* ... */
+#define MP_PIT_TIMER4_LENGTH    0x0C
+#define MP_PIT_CONTROL          0x10
+#define MP_PIT_TIMER1_VALUE     0x14
+/* ... */
+#define MP_PIT_TIMER4_VALUE     0x20
+#define MP_BOARD_RESET          0x34
+
+/* Magic board reset value (probably some watchdog behind it) */
+#define MP_BOARD_RESET_MAGIC    0x10000
+
+typedef struct mv88w8618_timer_state {
+    ptimer_state *ptimer;
+    uint32_t limit;
+    int freq;
+    qemu_irq irq;
+} mv88w8618_timer_state;
+
+typedef struct mv88w8618_pit_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    mv88w8618_timer_state timer[4];
+} mv88w8618_pit_state;
+
+static void mv88w8618_timer_tick(void *opaque)
+{
+    mv88w8618_timer_state *s = opaque;
+
+    qemu_irq_raise(s->irq);
+}
+
+static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s,
+                                 uint32_t freq)
+{
+    QEMUBH *bh;
+
+    sysbus_init_irq(dev, &s->irq);
+    s->freq = freq;
+
+    bh = qemu_bh_new(mv88w8618_timer_tick, s);
+    s->ptimer = ptimer_init(bh);
+}
+
+static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset,
+                                   unsigned size)
+{
+    mv88w8618_pit_state *s = opaque;
+    mv88w8618_timer_state *t;
+
+    switch (offset) {
+    case MP_PIT_TIMER1_VALUE ... MP_PIT_TIMER4_VALUE:
+        t = &s->timer[(offset-MP_PIT_TIMER1_VALUE) >> 2];
+        return ptimer_get_count(t->ptimer);
+
+    default:
+        return 0;
+    }
+}
+
+static void mv88w8618_pit_write(void *opaque, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+    mv88w8618_pit_state *s = opaque;
+    mv88w8618_timer_state *t;
+    int i;
+
+    switch (offset) {
+    case MP_PIT_TIMER1_LENGTH ... MP_PIT_TIMER4_LENGTH:
+        t = &s->timer[offset >> 2];
+        t->limit = value;
+        if (t->limit > 0) {
+            ptimer_set_limit(t->ptimer, t->limit, 1);
+        } else {
+            ptimer_stop(t->ptimer);
+        }
+        break;
+
+    case MP_PIT_CONTROL:
+        for (i = 0; i < 4; i++) {
+            t = &s->timer[i];
+            if (value & 0xf && t->limit > 0) {
+                ptimer_set_limit(t->ptimer, t->limit, 0);
+                ptimer_set_freq(t->ptimer, t->freq);
+                ptimer_run(t->ptimer, 0);
+            } else {
+                ptimer_stop(t->ptimer);
+            }
+            value >>= 4;
+        }
+        break;
+
+    case MP_BOARD_RESET:
+        if (value == MP_BOARD_RESET_MAGIC) {
+            qemu_system_reset_request();
+        }
+        break;
+    }
+}
+
+static void mv88w8618_pit_reset(DeviceState *d)
+{
+    mv88w8618_pit_state *s = FROM_SYSBUS(mv88w8618_pit_state,
+                                         SYS_BUS_DEVICE(d));
+    int i;
+
+    for (i = 0; i < 4; i++) {
+        ptimer_stop(s->timer[i].ptimer);
+        s->timer[i].limit = 0;
+    }
+}
+
+static const MemoryRegionOps mv88w8618_pit_ops = {
+    .read = mv88w8618_pit_read,
+    .write = mv88w8618_pit_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int mv88w8618_pit_init(SysBusDevice *dev)
+{
+    mv88w8618_pit_state *s = FROM_SYSBUS(mv88w8618_pit_state, dev);
+    int i;
+
+    /* Letting them all run at 1 MHz is likely just a pragmatic
+     * simplification. */
+    for (i = 0; i < 4; i++) {
+        mv88w8618_timer_init(dev, &s->timer[i], 1000000);
+    }
+
+    memory_region_init_io(&s->iomem, &mv88w8618_pit_ops, s,
+                          "musicpal-pit", MP_PIT_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
+    return 0;
+}
+
+static const VMStateDescription mv88w8618_timer_vmsd = {
+    .name = "timer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_PTIMER(ptimer, mv88w8618_timer_state),
+        VMSTATE_UINT32(limit, mv88w8618_timer_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription mv88w8618_pit_vmsd = {
+    .name = "mv88w8618_pit",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT_ARRAY(timer, mv88w8618_pit_state, 4, 1,
+                             mv88w8618_timer_vmsd, mv88w8618_timer_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void mv88w8618_pit_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = mv88w8618_pit_init;
+    dc->reset = mv88w8618_pit_reset;
+    dc->vmsd = &mv88w8618_pit_vmsd;
+}
+
+static const TypeInfo mv88w8618_pit_info = {
+    .name          = "mv88w8618_pit",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(mv88w8618_pit_state),
+    .class_init    = mv88w8618_pit_class_init,
+};
+
+/* Flash config register offsets */
+#define MP_FLASHCFG_CFGR0    0x04
+
+typedef struct mv88w8618_flashcfg_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t cfgr0;
+} mv88w8618_flashcfg_state;
+
+static uint64_t mv88w8618_flashcfg_read(void *opaque,
+                                        hwaddr offset,
+                                        unsigned size)
+{
+    mv88w8618_flashcfg_state *s = opaque;
+
+    switch (offset) {
+    case MP_FLASHCFG_CFGR0:
+        return s->cfgr0;
+
+    default:
+        return 0;
+    }
+}
+
+static void mv88w8618_flashcfg_write(void *opaque, hwaddr offset,
+                                     uint64_t value, unsigned size)
+{
+    mv88w8618_flashcfg_state *s = opaque;
+
+    switch (offset) {
+    case MP_FLASHCFG_CFGR0:
+        s->cfgr0 = value;
+        break;
+    }
+}
+
+static const MemoryRegionOps mv88w8618_flashcfg_ops = {
+    .read = mv88w8618_flashcfg_read,
+    .write = mv88w8618_flashcfg_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int mv88w8618_flashcfg_init(SysBusDevice *dev)
+{
+    mv88w8618_flashcfg_state *s = FROM_SYSBUS(mv88w8618_flashcfg_state, dev);
+
+    s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
+    memory_region_init_io(&s->iomem, &mv88w8618_flashcfg_ops, s,
+                          "musicpal-flashcfg", MP_FLASHCFG_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
+    return 0;
+}
+
+static const VMStateDescription mv88w8618_flashcfg_vmsd = {
+    .name = "mv88w8618_flashcfg",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(cfgr0, mv88w8618_flashcfg_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void mv88w8618_flashcfg_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = mv88w8618_flashcfg_init;
+    dc->vmsd = &mv88w8618_flashcfg_vmsd;
+}
+
+static const TypeInfo mv88w8618_flashcfg_info = {
+    .name          = "mv88w8618_flashcfg",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(mv88w8618_flashcfg_state),
+    .class_init    = mv88w8618_flashcfg_class_init,
+};
+
+/* Misc register offsets */
+#define MP_MISC_BOARD_REVISION  0x18
+
+#define MP_BOARD_REVISION       0x31
+
+static uint64_t musicpal_misc_read(void *opaque, hwaddr offset,
+                                   unsigned size)
+{
+    switch (offset) {
+    case MP_MISC_BOARD_REVISION:
+        return MP_BOARD_REVISION;
+
+    default:
+        return 0;
+    }
+}
+
+static void musicpal_misc_write(void *opaque, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+}
+
+static const MemoryRegionOps musicpal_misc_ops = {
+    .read = musicpal_misc_read,
+    .write = musicpal_misc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void musicpal_misc_init(SysBusDevice *dev)
+{
+    MemoryRegion *iomem = g_new(MemoryRegion, 1);
+
+    memory_region_init_io(iomem, &musicpal_misc_ops, NULL,
+                          "musicpal-misc", MP_MISC_SIZE);
+    sysbus_add_memory(dev, MP_MISC_BASE, iomem);
+}
+
+/* WLAN register offsets */
+#define MP_WLAN_MAGIC1          0x11c
+#define MP_WLAN_MAGIC2          0x124
+
+static uint64_t mv88w8618_wlan_read(void *opaque, hwaddr offset,
+                                    unsigned size)
+{
+    switch (offset) {
+    /* Workaround to allow loading the binary-only wlandrv.ko crap
+     * from the original Freecom firmware. */
+    case MP_WLAN_MAGIC1:
+        return ~3;
+    case MP_WLAN_MAGIC2:
+        return -1;
+
+    default:
+        return 0;
+    }
+}
+
+static void mv88w8618_wlan_write(void *opaque, hwaddr offset,
+                                 uint64_t value, unsigned size)
+{
+}
+
+static const MemoryRegionOps mv88w8618_wlan_ops = {
+    .read = mv88w8618_wlan_read,
+    .write =mv88w8618_wlan_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int mv88w8618_wlan_init(SysBusDevice *dev)
+{
+    MemoryRegion *iomem = g_new(MemoryRegion, 1);
+
+    memory_region_init_io(iomem, &mv88w8618_wlan_ops, NULL,
+                          "musicpal-wlan", MP_WLAN_SIZE);
+    sysbus_init_mmio(dev, iomem);
+    return 0;
+}
+
+/* GPIO register offsets */
+#define MP_GPIO_OE_LO           0x008
+#define MP_GPIO_OUT_LO          0x00c
+#define MP_GPIO_IN_LO           0x010
+#define MP_GPIO_IER_LO          0x014
+#define MP_GPIO_IMR_LO          0x018
+#define MP_GPIO_ISR_LO          0x020
+#define MP_GPIO_OE_HI           0x508
+#define MP_GPIO_OUT_HI          0x50c
+#define MP_GPIO_IN_HI           0x510
+#define MP_GPIO_IER_HI          0x514
+#define MP_GPIO_IMR_HI          0x518
+#define MP_GPIO_ISR_HI          0x520
+
+/* GPIO bits & masks */
+#define MP_GPIO_LCD_BRIGHTNESS  0x00070000
+#define MP_GPIO_I2C_DATA_BIT    29
+#define MP_GPIO_I2C_CLOCK_BIT   30
+
+/* LCD brightness bits in GPIO_OE_HI */
+#define MP_OE_LCD_BRIGHTNESS    0x0007
+
+typedef struct musicpal_gpio_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t lcd_brightness;
+    uint32_t out_state;
+    uint32_t in_state;
+    uint32_t ier;
+    uint32_t imr;
+    uint32_t isr;
+    qemu_irq irq;
+    qemu_irq out[5]; /* 3 brightness out + 2 lcd (data and clock ) */
+} musicpal_gpio_state;
+
+static void musicpal_gpio_brightness_update(musicpal_gpio_state *s) {
+    int i;
+    uint32_t brightness;
+
+    /* compute brightness ratio */
+    switch (s->lcd_brightness) {
+    case 0x00000007:
+        brightness = 0;
+        break;
+
+    case 0x00020000:
+        brightness = 1;
+        break;
+
+    case 0x00020001:
+        brightness = 2;
+        break;
+
+    case 0x00040000:
+        brightness = 3;
+        break;
+
+    case 0x00010006:
+        brightness = 4;
+        break;
+
+    case 0x00020005:
+        brightness = 5;
+        break;
+
+    case 0x00040003:
+        brightness = 6;
+        break;
+
+    case 0x00030004:
+    default:
+        brightness = 7;
+    }
+
+    /* set lcd brightness GPIOs  */
+    for (i = 0; i <= 2; i++) {
+        qemu_set_irq(s->out[i], (brightness >> i) & 1);
+    }
+}
+
+static void musicpal_gpio_pin_event(void *opaque, int pin, int level)
+{
+    musicpal_gpio_state *s = opaque;
+    uint32_t mask = 1 << pin;
+    uint32_t delta = level << pin;
+    uint32_t old = s->in_state & mask;
+
+    s->in_state &= ~mask;
+    s->in_state |= delta;
+
+    if ((old ^ delta) &&
+        ((level && (s->imr & mask)) || (!level && (s->ier & mask)))) {
+        s->isr = mask;
+        qemu_irq_raise(s->irq);
+    }
+}
+
+static uint64_t musicpal_gpio_read(void *opaque, hwaddr offset,
+                                   unsigned size)
+{
+    musicpal_gpio_state *s = opaque;
+
+    switch (offset) {
+    case MP_GPIO_OE_HI: /* used for LCD brightness control */
+        return s->lcd_brightness & MP_OE_LCD_BRIGHTNESS;
+
+    case MP_GPIO_OUT_LO:
+        return s->out_state & 0xFFFF;
+    case MP_GPIO_OUT_HI:
+        return s->out_state >> 16;
+
+    case MP_GPIO_IN_LO:
+        return s->in_state & 0xFFFF;
+    case MP_GPIO_IN_HI:
+        return s->in_state >> 16;
+
+    case MP_GPIO_IER_LO:
+        return s->ier & 0xFFFF;
+    case MP_GPIO_IER_HI:
+        return s->ier >> 16;
+
+    case MP_GPIO_IMR_LO:
+        return s->imr & 0xFFFF;
+    case MP_GPIO_IMR_HI:
+        return s->imr >> 16;
+
+    case MP_GPIO_ISR_LO:
+        return s->isr & 0xFFFF;
+    case MP_GPIO_ISR_HI:
+        return s->isr >> 16;
+
+    default:
+        return 0;
+    }
+}
+
+static void musicpal_gpio_write(void *opaque, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+    musicpal_gpio_state *s = opaque;
+    switch (offset) {
+    case MP_GPIO_OE_HI: /* used for LCD brightness control */
+        s->lcd_brightness = (s->lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
+                         (value & MP_OE_LCD_BRIGHTNESS);
+        musicpal_gpio_brightness_update(s);
+        break;
+
+    case MP_GPIO_OUT_LO:
+        s->out_state = (s->out_state & 0xFFFF0000) | (value & 0xFFFF);
+        break;
+    case MP_GPIO_OUT_HI:
+        s->out_state = (s->out_state & 0xFFFF) | (value << 16);
+        s->lcd_brightness = (s->lcd_brightness & 0xFFFF) |
+                            (s->out_state & MP_GPIO_LCD_BRIGHTNESS);
+        musicpal_gpio_brightness_update(s);
+        qemu_set_irq(s->out[3], (s->out_state >> MP_GPIO_I2C_DATA_BIT) & 1);
+        qemu_set_irq(s->out[4], (s->out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
+        break;
+
+    case MP_GPIO_IER_LO:
+        s->ier = (s->ier & 0xFFFF0000) | (value & 0xFFFF);
+        break;
+    case MP_GPIO_IER_HI:
+        s->ier = (s->ier & 0xFFFF) | (value << 16);
+        break;
+
+    case MP_GPIO_IMR_LO:
+        s->imr = (s->imr & 0xFFFF0000) | (value & 0xFFFF);
+        break;
+    case MP_GPIO_IMR_HI:
+        s->imr = (s->imr & 0xFFFF) | (value << 16);
+        break;
+    }
+}
+
+static const MemoryRegionOps musicpal_gpio_ops = {
+    .read = musicpal_gpio_read,
+    .write = musicpal_gpio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void musicpal_gpio_reset(DeviceState *d)
+{
+    musicpal_gpio_state *s = FROM_SYSBUS(musicpal_gpio_state,
+                                         SYS_BUS_DEVICE(d));
+
+    s->lcd_brightness = 0;
+    s->out_state = 0;
+    s->in_state = 0xffffffff;
+    s->ier = 0;
+    s->imr = 0;
+    s->isr = 0;
+}
+
+static int musicpal_gpio_init(SysBusDevice *dev)
+{
+    musicpal_gpio_state *s = FROM_SYSBUS(musicpal_gpio_state, dev);
+
+    sysbus_init_irq(dev, &s->irq);
+
+    memory_region_init_io(&s->iomem, &musicpal_gpio_ops, s,
+                          "musicpal-gpio", MP_GPIO_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
+
+    qdev_init_gpio_in(&dev->qdev, musicpal_gpio_pin_event, 32);
+
+    return 0;
+}
+
+static const VMStateDescription musicpal_gpio_vmsd = {
+    .name = "musicpal_gpio",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(lcd_brightness, musicpal_gpio_state),
+        VMSTATE_UINT32(out_state, musicpal_gpio_state),
+        VMSTATE_UINT32(in_state, musicpal_gpio_state),
+        VMSTATE_UINT32(ier, musicpal_gpio_state),
+        VMSTATE_UINT32(imr, musicpal_gpio_state),
+        VMSTATE_UINT32(isr, musicpal_gpio_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void musicpal_gpio_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = musicpal_gpio_init;
+    dc->reset = musicpal_gpio_reset;
+    dc->vmsd = &musicpal_gpio_vmsd;
+}
+
+static const TypeInfo musicpal_gpio_info = {
+    .name          = "musicpal_gpio",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(musicpal_gpio_state),
+    .class_init    = musicpal_gpio_class_init,
+};
+
+/* Keyboard codes & masks */
+#define KEY_RELEASED            0x80
+#define KEY_CODE                0x7f
+
+#define KEYCODE_TAB             0x0f
+#define KEYCODE_ENTER           0x1c
+#define KEYCODE_F               0x21
+#define KEYCODE_M               0x32
+
+#define KEYCODE_EXTENDED        0xe0
+#define KEYCODE_UP              0x48
+#define KEYCODE_DOWN            0x50
+#define KEYCODE_LEFT            0x4b
+#define KEYCODE_RIGHT           0x4d
+
+#define MP_KEY_WHEEL_VOL       (1 << 0)
+#define MP_KEY_WHEEL_VOL_INV   (1 << 1)
+#define MP_KEY_WHEEL_NAV       (1 << 2)
+#define MP_KEY_WHEEL_NAV_INV   (1 << 3)
+#define MP_KEY_BTN_FAVORITS    (1 << 4)
+#define MP_KEY_BTN_MENU        (1 << 5)
+#define MP_KEY_BTN_VOLUME      (1 << 6)
+#define MP_KEY_BTN_NAVIGATION  (1 << 7)
+
+typedef struct musicpal_key_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t kbd_extended;
+    uint32_t pressed_keys;
+    qemu_irq out[8];
+} musicpal_key_state;
+
+static void musicpal_key_event(void *opaque, int keycode)
+{
+    musicpal_key_state *s = opaque;
+    uint32_t event = 0;
+    int i;
+
+    if (keycode == KEYCODE_EXTENDED) {
+        s->kbd_extended = 1;
+        return;
+    }
+
+    if (s->kbd_extended) {
+        switch (keycode & KEY_CODE) {
+        case KEYCODE_UP:
+            event = MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_NAV_INV;
+            break;
+
+        case KEYCODE_DOWN:
+            event = MP_KEY_WHEEL_NAV;
+            break;
+
+        case KEYCODE_LEFT:
+            event = MP_KEY_WHEEL_VOL | MP_KEY_WHEEL_VOL_INV;
+            break;
+
+        case KEYCODE_RIGHT:
+            event = MP_KEY_WHEEL_VOL;
+            break;
+        }
+    } else {
+        switch (keycode & KEY_CODE) {
+        case KEYCODE_F:
+            event = MP_KEY_BTN_FAVORITS;
+            break;
+
+        case KEYCODE_TAB:
+            event = MP_KEY_BTN_VOLUME;
+            break;
+
+        case KEYCODE_ENTER:
+            event = MP_KEY_BTN_NAVIGATION;
+            break;
+
+        case KEYCODE_M:
+            event = MP_KEY_BTN_MENU;
+            break;
+        }
+        /* Do not repeat already pressed buttons */
+        if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
+            event = 0;
+        }
+    }
+
+    if (event) {
+        /* Raise GPIO pin first if repeating a key */
+        if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
+            for (i = 0; i <= 7; i++) {
+                if (event & (1 << i)) {
+                    qemu_set_irq(s->out[i], 1);
+                }
+            }
+        }
+        for (i = 0; i <= 7; i++) {
+            if (event & (1 << i)) {
+                qemu_set_irq(s->out[i], !!(keycode & KEY_RELEASED));
+            }
+        }
+        if (keycode & KEY_RELEASED) {
+            s->pressed_keys &= ~event;
+        } else {
+            s->pressed_keys |= event;
+        }
+    }
+
+    s->kbd_extended = 0;
+}
+
+static int musicpal_key_init(SysBusDevice *dev)
+{
+    musicpal_key_state *s = FROM_SYSBUS(musicpal_key_state, dev);
+
+    memory_region_init(&s->iomem, "dummy", 0);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    s->kbd_extended = 0;
+    s->pressed_keys = 0;
+
+    qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
+
+    qemu_add_kbd_event_handler(musicpal_key_event, s);
+
+    return 0;
+}
+
+static const VMStateDescription musicpal_key_vmsd = {
+    .name = "musicpal_key",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(kbd_extended, musicpal_key_state),
+        VMSTATE_UINT32(pressed_keys, musicpal_key_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void musicpal_key_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = musicpal_key_init;
+    dc->vmsd = &musicpal_key_vmsd;
+}
+
+static const TypeInfo musicpal_key_info = {
+    .name          = "musicpal_key",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(musicpal_key_state),
+    .class_init    = musicpal_key_class_init,
+};
+
+static struct arm_boot_info musicpal_binfo = {
+    .loader_start = 0x0,
+    .board_id = 0x20e,
+};
+
+static void musicpal_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    ARMCPU *cpu;
+    qemu_irq *cpu_pic;
+    qemu_irq pic[32];
+    DeviceState *dev;
+    DeviceState *i2c_dev;
+    DeviceState *lcd_dev;
+    DeviceState *key_dev;
+    DeviceState *wm8750_dev;
+    SysBusDevice *s;
+    i2c_bus *i2c;
+    int i;
+    unsigned long flash_size;
+    DriveInfo *dinfo;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+
+    if (!cpu_model) {
+        cpu_model = "arm926";
+    }
+    cpu = cpu_arm_init(cpu_model);
+    if (!cpu) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    cpu_pic = arm_pic_init_cpu(cpu);
+
+    /* For now we use a fixed - the original - RAM size */
+    memory_region_init_ram(ram, "musicpal.ram", MP_RAM_DEFAULT_SIZE);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(address_space_mem, 0, ram);
+
+    memory_region_init_ram(sram, "musicpal.sram", MP_SRAM_SIZE);
+    vmstate_register_ram_global(sram);
+    memory_region_add_subregion(address_space_mem, MP_SRAM_BASE, sram);
+
+    dev = sysbus_create_simple("mv88w8618_pic", MP_PIC_BASE,
+                               cpu_pic[ARM_PIC_CPU_IRQ]);
+    for (i = 0; i < 32; i++) {
+        pic[i] = qdev_get_gpio_in(dev, i);
+    }
+    sysbus_create_varargs("mv88w8618_pit", MP_PIT_BASE, pic[MP_TIMER1_IRQ],
+                          pic[MP_TIMER2_IRQ], pic[MP_TIMER3_IRQ],
+                          pic[MP_TIMER4_IRQ], NULL);
+
+    if (serial_hds[0]) {
+        serial_mm_init(address_space_mem, MP_UART1_BASE, 2, pic[MP_UART1_IRQ],
+                       1825000, serial_hds[0], DEVICE_NATIVE_ENDIAN);
+    }
+    if (serial_hds[1]) {
+        serial_mm_init(address_space_mem, MP_UART2_BASE, 2, pic[MP_UART2_IRQ],
+                       1825000, serial_hds[1], DEVICE_NATIVE_ENDIAN);
+    }
+
+    /* Register flash */
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (dinfo) {
+        flash_size = bdrv_getlength(dinfo->bdrv);
+        if (flash_size != 8*1024*1024 && flash_size != 16*1024*1024 &&
+            flash_size != 32*1024*1024) {
+            fprintf(stderr, "Invalid flash image size\n");
+            exit(1);
+        }
+
+        /*
+         * The original U-Boot accesses the flash at 0xFE000000 instead of
+         * 0xFF800000 (if there is 8 MB flash). So remap flash access if the
+         * image is smaller than 32 MB.
+         */
+#ifdef TARGET_WORDS_BIGENDIAN
+        pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
+                              "musicpal.flash", flash_size,
+                              dinfo->bdrv, 0x10000,
+                              (flash_size + 0xffff) >> 16,
+                              MP_FLASH_SIZE_MAX / flash_size,
+                              2, 0x00BF, 0x236D, 0x0000, 0x0000,
+                              0x5555, 0x2AAA, 1);
+#else
+        pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
+                              "musicpal.flash", flash_size,
+                              dinfo->bdrv, 0x10000,
+                              (flash_size + 0xffff) >> 16,
+                              MP_FLASH_SIZE_MAX / flash_size,
+                              2, 0x00BF, 0x236D, 0x0000, 0x0000,
+                              0x5555, 0x2AAA, 0);
+#endif
+
+    }
+    sysbus_create_simple("mv88w8618_flashcfg", MP_FLASHCFG_BASE, NULL);
+
+    qemu_check_nic_model(&nd_table[0], "mv88w8618");
+    dev = qdev_create(NULL, "mv88w8618_eth");
+    qdev_set_nic_properties(dev, &nd_table[0]);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, MP_ETH_BASE);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[MP_ETH_IRQ]);
+
+    sysbus_create_simple("mv88w8618_wlan", MP_WLAN_BASE, NULL);
+
+    musicpal_misc_init(SYS_BUS_DEVICE(dev));
+
+    dev = sysbus_create_simple("musicpal_gpio", MP_GPIO_BASE, pic[MP_GPIO_IRQ]);
+    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", -1, NULL);
+
+    /* I2C read data */
+    qdev_connect_gpio_out(i2c_dev, 0,
+                          qdev_get_gpio_in(dev, MP_GPIO_I2C_DATA_BIT));
+    /* I2C data */
+    qdev_connect_gpio_out(dev, 3, qdev_get_gpio_in(i2c_dev, 0));
+    /* I2C clock */
+    qdev_connect_gpio_out(dev, 4, qdev_get_gpio_in(i2c_dev, 1));
+
+    for (i = 0; i < 3; i++) {
+        qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(lcd_dev, i));
+    }
+    for (i = 0; i < 4; i++) {
+        qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 8));
+    }
+    for (i = 4; i < 8; i++) {
+        qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15));
+    }
+
+    wm8750_dev = i2c_create_slave(i2c, "wm8750", MP_WM_ADDR);
+    dev = qdev_create(NULL, "mv88w8618_audio");
+    s = SYS_BUS_DEVICE(dev);
+    qdev_prop_set_ptr(dev, "wm8750", wm8750_dev);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(s, 0, MP_AUDIO_BASE);
+    sysbus_connect_irq(s, 0, pic[MP_AUDIO_IRQ]);
+
+    musicpal_binfo.ram_size = MP_RAM_DEFAULT_SIZE;
+    musicpal_binfo.kernel_filename = kernel_filename;
+    musicpal_binfo.kernel_cmdline = kernel_cmdline;
+    musicpal_binfo.initrd_filename = initrd_filename;
+    arm_load_kernel(cpu, &musicpal_binfo);
+}
+
+static QEMUMachine musicpal_machine = {
+    .name = "musicpal",
+    .desc = "Marvell 88w8618 / MusicPal (ARM926EJ-S)",
+    .init = musicpal_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void musicpal_machine_init(void)
+{
+    qemu_register_machine(&musicpal_machine);
+}
+
+machine_init(musicpal_machine_init);
+
+static void mv88w8618_wlan_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = mv88w8618_wlan_init;
+}
+
+static const TypeInfo mv88w8618_wlan_info = {
+    .name          = "mv88w8618_wlan",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(SysBusDevice),
+    .class_init    = mv88w8618_wlan_class_init,
+};
+
+static void musicpal_register_types(void)
+{
+    type_register_static(&mv88w8618_pic_info);
+    type_register_static(&mv88w8618_pit_info);
+    type_register_static(&mv88w8618_flashcfg_info);
+    type_register_static(&mv88w8618_eth_info);
+    type_register_static(&mv88w8618_wlan_info);
+    type_register_static(&musicpal_lcd_info);
+    type_register_static(&musicpal_gpio_info);
+    type_register_static(&musicpal_key_info);
+}
+
+type_init(musicpal_register_types)
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
new file mode 100644
index 0000000..c5bf9f9
--- /dev/null
+++ b/hw/arm/nseries.c
@@ -0,0 +1,1430 @@
+/*
+ * Nokia N-series internet tablets.
+ *
+ * Copyright (C) 2007 Nokia Corporation
+ * Written by Andrzej Zaborowski <andrew at openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 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 "qemu-common.h"
+#include "sysemu/sysemu.h"
+#include "hw/omap.h"
+#include "hw/arm-misc.h"
+#include "hw/irq.h"
+#include "ui/console.h"
+#include "hw/boards.h"
+#include "hw/i2c.h"
+#include "hw/devices.h"
+#include "hw/flash.h"
+#include "hw/hw.h"
+#include "hw/bt.h"
+#include "hw/loader.h"
+#include "sysemu/blockdev.h"
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+
+/* Nokia N8x0 support */
+struct n800_s {
+    struct omap_mpu_state_s *mpu;
+
+    struct rfbi_chip_s blizzard;
+    struct {
+        void *opaque;
+        uint32_t (*txrx)(void *opaque, uint32_t value, int len);
+        uWireSlave *chip;
+    } ts;
+
+    int keymap[0x80];
+    DeviceState *kbd;
+
+    DeviceState *usb;
+    void *retu;
+    void *tahvo;
+    DeviceState *nand;
+};
+
+/* GPIO pins */
+#define N8X0_TUSB_ENABLE_GPIO		0
+#define N800_MMC2_WP_GPIO		8
+#define N800_UNKNOWN_GPIO0		9	/* out */
+#define N810_MMC2_VIOSD_GPIO		9
+#define N810_HEADSET_AMP_GPIO		10
+#define N800_CAM_TURN_GPIO		12
+#define N810_GPS_RESET_GPIO		12
+#define N800_BLIZZARD_POWERDOWN_GPIO	15
+#define N800_MMC1_WP_GPIO		23
+#define N810_MMC2_VSD_GPIO		23
+#define N8X0_ONENAND_GPIO		26
+#define N810_BLIZZARD_RESET_GPIO	30
+#define N800_UNKNOWN_GPIO2		53	/* out */
+#define N8X0_TUSB_INT_GPIO		58
+#define N8X0_BT_WKUP_GPIO		61
+#define N8X0_STI_GPIO			62
+#define N8X0_CBUS_SEL_GPIO		64
+#define N8X0_CBUS_DAT_GPIO		65
+#define N8X0_CBUS_CLK_GPIO		66
+#define N8X0_WLAN_IRQ_GPIO		87
+#define N8X0_BT_RESET_GPIO		92
+#define N8X0_TEA5761_CS_GPIO		93
+#define N800_UNKNOWN_GPIO		94
+#define N810_TSC_RESET_GPIO		94
+#define N800_CAM_ACT_GPIO		95
+#define N810_GPS_WAKEUP_GPIO		95
+#define N8X0_MMC_CS_GPIO		96
+#define N8X0_WLAN_PWR_GPIO		97
+#define N8X0_BT_HOST_WKUP_GPIO		98
+#define N810_SPEAKER_AMP_GPIO		101
+#define N810_KB_LOCK_GPIO		102
+#define N800_TSC_TS_GPIO		103
+#define N810_TSC_TS_GPIO		106
+#define N8X0_HEADPHONE_GPIO		107
+#define N8X0_RETU_GPIO			108
+#define N800_TSC_KP_IRQ_GPIO		109
+#define N810_KEYBOARD_GPIO		109
+#define N800_BAT_COVER_GPIO		110
+#define N810_SLIDE_GPIO			110
+#define N8X0_TAHVO_GPIO			111
+#define N800_UNKNOWN_GPIO4		112	/* out */
+#define N810_SLEEPX_LED_GPIO		112
+#define N800_TSC_RESET_GPIO		118	/* ? */
+#define N810_AIC33_RESET_GPIO		118
+#define N800_TSC_UNKNOWN_GPIO		119	/* out */
+#define N8X0_TMP105_GPIO		125
+
+/* Config */
+#define BT_UART				0
+#define XLDR_LL_UART			1
+
+/* Addresses on the I2C bus 0 */
+#define N810_TLV320AIC33_ADDR		0x18	/* Audio CODEC */
+#define N8X0_TCM825x_ADDR		0x29	/* Camera */
+#define N810_LP5521_ADDR		0x32	/* LEDs */
+#define N810_TSL2563_ADDR		0x3d	/* Light sensor */
+#define N810_LM8323_ADDR		0x45	/* Keyboard */
+/* Addresses on the I2C bus 1 */
+#define N8X0_TMP105_ADDR		0x48	/* Temperature sensor */
+#define N8X0_MENELAUS_ADDR		0x72	/* Power management */
+
+/* Chipselects on GPMC NOR interface */
+#define N8X0_ONENAND_CS			0
+#define N8X0_USB_ASYNC_CS		1
+#define N8X0_USB_SYNC_CS		4
+
+#define N8X0_BD_ADDR			0x00, 0x1a, 0x89, 0x9e, 0x3e, 0x81
+
+static void n800_mmc_cs_cb(void *opaque, int line, int level)
+{
+    /* TODO: this seems to actually be connected to the menelaus, to
+     * which also both MMC slots connect.  */
+    omap_mmc_enable((struct omap_mmc_s *) opaque, !level);
+
+    printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);
+}
+
+static void n8x0_gpio_setup(struct n800_s *s)
+{
+    qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->mpu->mmc, 1);
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_MMC_CS_GPIO, mmc_cs[0]);
+
+    qemu_irq_lower(qdev_get_gpio_in(s->mpu->gpio, N800_BAT_COVER_GPIO));
+}
+
+#define MAEMO_CAL_HEADER(...)				\
+    'C',  'o',  'n',  'F',  0x02, 0x00, 0x04, 0x00,	\
+    __VA_ARGS__,					\
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+static const uint8_t n8x0_cal_wlan_mac[] = {
+    MAEMO_CAL_HEADER('w', 'l', 'a', 'n', '-', 'm', 'a', 'c')
+    0x1c, 0x00, 0x00, 0x00, 0x47, 0xd6, 0x69, 0xb3,
+    0x30, 0x08, 0xa0, 0x83, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
+    0x89, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
+    0x5d, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00,
+};
+
+static const uint8_t n8x0_cal_bt_id[] = {
+    MAEMO_CAL_HEADER('b', 't', '-', 'i', 'd', 0, 0, 0)
+    0x0a, 0x00, 0x00, 0x00, 0xa3, 0x4b, 0xf6, 0x96,
+    0xa8, 0xeb, 0xb2, 0x41, 0x00, 0x00, 0x00, 0x00,
+    N8X0_BD_ADDR,
+};
+
+static void n8x0_nand_setup(struct n800_s *s)
+{
+    char *otp_region;
+    DriveInfo *dinfo;
+
+    s->nand = qdev_create(NULL, "onenand");
+    qdev_prop_set_uint16(s->nand, "manufacturer_id", NAND_MFR_SAMSUNG);
+    /* Either 0x40 or 0x48 are OK for the device ID */
+    qdev_prop_set_uint16(s->nand, "device_id", 0x48);
+    qdev_prop_set_uint16(s->nand, "version_id", 0);
+    qdev_prop_set_int32(s->nand, "shift", 1);
+    dinfo = drive_get(IF_MTD, 0, 0);
+    if (dinfo && dinfo->bdrv) {
+        qdev_prop_set_drive_nofail(s->nand, "drive", dinfo->bdrv);
+    }
+    qdev_init_nofail(s->nand);
+    sysbus_connect_irq(SYS_BUS_DEVICE(s->nand), 0,
+                       qdev_get_gpio_in(s->mpu->gpio, N8X0_ONENAND_GPIO));
+    omap_gpmc_attach(s->mpu->gpmc, N8X0_ONENAND_CS,
+                     sysbus_mmio_get_region(SYS_BUS_DEVICE(s->nand), 0));
+    otp_region = onenand_raw_otp(s->nand);
+
+    memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac));
+    memcpy(otp_region + 0x800, n8x0_cal_bt_id, sizeof(n8x0_cal_bt_id));
+    /* XXX: in theory should also update the OOB for both pages */
+}
+
+static qemu_irq n8x0_system_powerdown;
+
+static void n8x0_powerdown_req(Notifier *n, void *opaque)
+{
+    qemu_irq_raise(n8x0_system_powerdown);
+}
+
+static Notifier n8x0_system_powerdown_notifier = {
+    .notify = n8x0_powerdown_req
+};
+
+static void n8x0_i2c_setup(struct n800_s *s)
+{
+    DeviceState *dev;
+    qemu_irq tmp_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TMP105_GPIO);
+    i2c_bus *i2c = omap_i2c_bus(s->mpu->i2c[0]);
+
+    /* Attach a menelaus PM chip */
+    dev = i2c_create_slave(i2c, "twl92230", N8X0_MENELAUS_ADDR);
+    qdev_connect_gpio_out(dev, 3,
+                          qdev_get_gpio_in(s->mpu->ih[0],
+                                           OMAP_INT_24XX_SYS_NIRQ));
+
+    n8x0_system_powerdown = qdev_get_gpio_in(dev, 3);
+    qemu_register_powerdown_notifier(&n8x0_system_powerdown_notifier);
+
+    /* Attach a TMP105 PM chip (A0 wired to ground) */
+    dev = i2c_create_slave(i2c, "tmp105", N8X0_TMP105_ADDR);
+    qdev_connect_gpio_out(dev, 0, tmp_irq);
+}
+
+/* Touchscreen and keypad controller */
+static MouseTransformInfo n800_pointercal = {
+    .x = 800,
+    .y = 480,
+    .a = { 14560, -68, -3455208, -39, -9621, 35152972, 65536 },
+};
+
+static MouseTransformInfo n810_pointercal = {
+    .x = 800,
+    .y = 480,
+    .a = { 15041, 148, -4731056, 171, -10238, 35933380, 65536 },
+};
+
+#define RETU_KEYCODE	61	/* F3 */
+
+static void n800_key_event(void *opaque, int keycode)
+{
+    struct n800_s *s = (struct n800_s *) opaque;
+    int code = s->keymap[keycode & 0x7f];
+
+    if (code == -1) {
+        if ((keycode & 0x7f) == RETU_KEYCODE)
+            retu_key_event(s->retu, !(keycode & 0x80));
+        return;
+    }
+
+    tsc210x_key_event(s->ts.chip, code, !(keycode & 0x80));
+}
+
+static const int n800_keys[16] = {
+    -1,
+    72,	/* Up */
+    63,	/* Home (F5) */
+    -1,
+    75,	/* Left */
+    28,	/* Enter */
+    77,	/* Right */
+    -1,
+     1,	/* Cycle (ESC) */
+    80,	/* Down */
+    62,	/* Menu (F4) */
+    -1,
+    66,	/* Zoom- (F8) */
+    64,	/* FullScreen (F6) */
+    65,	/* Zoom+ (F7) */
+    -1,
+};
+
+static void n800_tsc_kbd_setup(struct n800_s *s)
+{
+    int i;
+
+    /* XXX: are the three pins inverted inside the chip between the
+     * tsc and the cpu (N4111)?  */
+    qemu_irq penirq = NULL;	/* NC */
+    qemu_irq kbirq = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_KP_IRQ_GPIO);
+    qemu_irq dav = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_TS_GPIO);
+
+    s->ts.chip = tsc2301_init(penirq, kbirq, dav);
+    s->ts.opaque = s->ts.chip->opaque;
+    s->ts.txrx = tsc210x_txrx;
+
+    for (i = 0; i < 0x80; i ++)
+        s->keymap[i] = -1;
+    for (i = 0; i < 0x10; i ++)
+        if (n800_keys[i] >= 0)
+            s->keymap[n800_keys[i]] = i;
+
+    qemu_add_kbd_event_handler(n800_key_event, s);
+
+    tsc210x_set_transform(s->ts.chip, &n800_pointercal);
+}
+
+static void n810_tsc_setup(struct n800_s *s)
+{
+    qemu_irq pintdav = qdev_get_gpio_in(s->mpu->gpio, N810_TSC_TS_GPIO);
+
+    s->ts.opaque = tsc2005_init(pintdav);
+    s->ts.txrx = tsc2005_txrx;
+
+    tsc2005_set_transform(s->ts.opaque, &n810_pointercal);
+}
+
+/* N810 Keyboard controller */
+static void n810_key_event(void *opaque, int keycode)
+{
+    struct n800_s *s = (struct n800_s *) opaque;
+    int code = s->keymap[keycode & 0x7f];
+
+    if (code == -1) {
+        if ((keycode & 0x7f) == RETU_KEYCODE)
+            retu_key_event(s->retu, !(keycode & 0x80));
+        return;
+    }
+
+    lm832x_key_event(s->kbd, code, !(keycode & 0x80));
+}
+
+#define M	0
+
+static int n810_keys[0x80] = {
+    [0x01] = 16,	/* Q */
+    [0x02] = 37,	/* K */
+    [0x03] = 24,	/* O */
+    [0x04] = 25,	/* P */
+    [0x05] = 14,	/* Backspace */
+    [0x06] = 30,	/* A */
+    [0x07] = 31,	/* S */
+    [0x08] = 32,	/* D */
+    [0x09] = 33,	/* F */
+    [0x0a] = 34,	/* G */
+    [0x0b] = 35,	/* H */
+    [0x0c] = 36,	/* J */
+
+    [0x11] = 17,	/* W */
+    [0x12] = 62,	/* Menu (F4) */
+    [0x13] = 38,	/* L */
+    [0x14] = 40,	/* ' (Apostrophe) */
+    [0x16] = 44,	/* Z */
+    [0x17] = 45,	/* X */
+    [0x18] = 46,	/* C */
+    [0x19] = 47,	/* V */
+    [0x1a] = 48,	/* B */
+    [0x1b] = 49,	/* N */
+    [0x1c] = 42,	/* Shift (Left shift) */
+    [0x1f] = 65,	/* Zoom+ (F7) */
+
+    [0x21] = 18,	/* E */
+    [0x22] = 39,	/* ; (Semicolon) */
+    [0x23] = 12,	/* - (Minus) */
+    [0x24] = 13,	/* = (Equal) */
+    [0x2b] = 56,	/* Fn (Left Alt) */
+    [0x2c] = 50,	/* M */
+    [0x2f] = 66,	/* Zoom- (F8) */
+
+    [0x31] = 19,	/* R */
+    [0x32] = 29 | M,	/* Right Ctrl */
+    [0x34] = 57,	/* Space */
+    [0x35] = 51,	/* , (Comma) */
+    [0x37] = 72 | M,	/* Up */
+    [0x3c] = 82 | M,	/* Compose (Insert) */
+    [0x3f] = 64,	/* FullScreen (F6) */
+
+    [0x41] = 20,	/* T */
+    [0x44] = 52,	/* . (Dot) */
+    [0x46] = 77 | M,	/* Right */
+    [0x4f] = 63,	/* Home (F5) */
+    [0x51] = 21,	/* Y */
+    [0x53] = 80 | M,	/* Down */
+    [0x55] = 28,	/* Enter */
+    [0x5f] =  1,	/* Cycle (ESC) */
+
+    [0x61] = 22,	/* U */
+    [0x64] = 75 | M,	/* Left */
+
+    [0x71] = 23,	/* I */
+#if 0
+    [0x75] = 28 | M,	/* KP Enter (KP Enter) */
+#else
+    [0x75] = 15,	/* KP Enter (Tab) */
+#endif
+};
+
+#undef M
+
+static void n810_kbd_setup(struct n800_s *s)
+{
+    qemu_irq kbd_irq = qdev_get_gpio_in(s->mpu->gpio, N810_KEYBOARD_GPIO);
+    int i;
+
+    for (i = 0; i < 0x80; i ++)
+        s->keymap[i] = -1;
+    for (i = 0; i < 0x80; i ++)
+        if (n810_keys[i] > 0)
+            s->keymap[n810_keys[i]] = i;
+
+    qemu_add_kbd_event_handler(n810_key_event, s);
+
+    /* Attach the LM8322 keyboard to the I2C bus,
+     * should happen in n8x0_i2c_setup and s->kbd be initialised here.  */
+    s->kbd = i2c_create_slave(omap_i2c_bus(s->mpu->i2c[0]),
+                           "lm8323", N810_LM8323_ADDR);
+    qdev_connect_gpio_out(s->kbd, 0, kbd_irq);
+}
+
+/* LCD MIPI DBI-C controller (URAL) */
+struct mipid_s {
+    int resp[4];
+    int param[4];
+    int p;
+    int pm;
+    int cmd;
+
+    int sleep;
+    int booster;
+    int te;
+    int selfcheck;
+    int partial;
+    int normal;
+    int vscr;
+    int invert;
+    int onoff;
+    int gamma;
+    uint32_t id;
+};
+
+static void mipid_reset(struct mipid_s *s)
+{
+    if (!s->sleep)
+        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
+
+    s->pm = 0;
+    s->cmd = 0;
+
+    s->sleep = 1;
+    s->booster = 0;
+    s->selfcheck =
+            (1 << 7) |	/* Register loading OK.  */
+            (1 << 5) |	/* The chip is attached.  */
+            (1 << 4);	/* Display glass still in one piece.  */
+    s->te = 0;
+    s->partial = 0;
+    s->normal = 1;
+    s->vscr = 0;
+    s->invert = 0;
+    s->onoff = 1;
+    s->gamma = 0;
+}
+
+static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
+{
+    struct mipid_s *s = (struct mipid_s *) opaque;
+    uint8_t ret;
+
+    if (len > 9)
+        hw_error("%s: FIXME: bad SPI word width %i\n", __FUNCTION__, len);
+
+    if (s->p >= ARRAY_SIZE(s->resp))
+        ret = 0;
+    else
+        ret = s->resp[s->p ++];
+    if (s->pm --> 0)
+        s->param[s->pm] = cmd;
+    else
+        s->cmd = cmd;
+
+    switch (s->cmd) {
+    case 0x00:	/* NOP */
+        break;
+
+    case 0x01:	/* SWRESET */
+        mipid_reset(s);
+        break;
+
+    case 0x02:	/* BSTROFF */
+        s->booster = 0;
+        break;
+    case 0x03:	/* BSTRON */
+        s->booster = 1;
+        break;
+
+    case 0x04:	/* RDDID */
+        s->p = 0;
+        s->resp[0] = (s->id >> 16) & 0xff;
+        s->resp[1] = (s->id >>  8) & 0xff;
+        s->resp[2] = (s->id >>  0) & 0xff;
+        break;
+
+    case 0x06:	/* RD_RED */
+    case 0x07:	/* RD_GREEN */
+        /* XXX the bootloader sometimes issues RD_BLUE meaning RDDID so
+         * for the bootloader one needs to change this.  */
+    case 0x08:	/* RD_BLUE */
+        s->p = 0;
+        /* TODO: return first pixel components */
+        s->resp[0] = 0x01;
+        break;
+
+    case 0x09:	/* RDDST */
+        s->p = 0;
+        s->resp[0] = s->booster << 7;
+        s->resp[1] = (5 << 4) | (s->partial << 2) |
+                (s->sleep << 1) | s->normal;
+        s->resp[2] = (s->vscr << 7) | (s->invert << 5) |
+                (s->onoff << 2) | (s->te << 1) | (s->gamma >> 2);
+        s->resp[3] = s->gamma << 6;
+        break;
+
+    case 0x0a:	/* RDDPM */
+        s->p = 0;
+        s->resp[0] = (s->onoff << 2) | (s->normal << 3) | (s->sleep << 4) |
+                (s->partial << 5) | (s->sleep << 6) | (s->booster << 7);
+        break;
+    case 0x0b:	/* RDDMADCTR */
+        s->p = 0;
+        s->resp[0] = 0;
+        break;
+    case 0x0c:	/* RDDCOLMOD */
+        s->p = 0;
+        s->resp[0] = 5;	/* 65K colours */
+        break;
+    case 0x0d:	/* RDDIM */
+        s->p = 0;
+        s->resp[0] = (s->invert << 5) | (s->vscr << 7) | s->gamma;
+        break;
+    case 0x0e:	/* RDDSM */
+        s->p = 0;
+        s->resp[0] = s->te << 7;
+        break;
+    case 0x0f:	/* RDDSDR */
+        s->p = 0;
+        s->resp[0] = s->selfcheck;
+        break;
+
+    case 0x10:	/* SLPIN */
+        s->sleep = 1;
+        break;
+    case 0x11:	/* SLPOUT */
+        s->sleep = 0;
+        s->selfcheck ^= 1 << 6;	/* POFF self-diagnosis Ok */
+        break;
+
+    case 0x12:	/* PTLON */
+        s->partial = 1;
+        s->normal = 0;
+        s->vscr = 0;
+        break;
+    case 0x13:	/* NORON */
+        s->partial = 0;
+        s->normal = 1;
+        s->vscr = 0;
+        break;
+
+    case 0x20:	/* INVOFF */
+        s->invert = 0;
+        break;
+    case 0x21:	/* INVON */
+        s->invert = 1;
+        break;
+
+    case 0x22:	/* APOFF */
+    case 0x23:	/* APON */
+        goto bad_cmd;
+
+    case 0x25:	/* WRCNTR */
+        if (s->pm < 0)
+            s->pm = 1;
+        goto bad_cmd;
+
+    case 0x26:	/* GAMSET */
+        if (!s->pm)
+            s->gamma = ffs(s->param[0] & 0xf) - 1;
+        else if (s->pm < 0)
+            s->pm = 1;
+        break;
+
+    case 0x28:	/* DISPOFF */
+        s->onoff = 0;
+        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
+        break;
+    case 0x29:	/* DISPON */
+        s->onoff = 1;
+        fprintf(stderr, "%s: Display on\n", __FUNCTION__);
+        break;
+
+    case 0x2a:	/* CASET */
+    case 0x2b:	/* RASET */
+    case 0x2c:	/* RAMWR */
+    case 0x2d:	/* RGBSET */
+    case 0x2e:	/* RAMRD */
+    case 0x30:	/* PTLAR */
+    case 0x33:	/* SCRLAR */
+        goto bad_cmd;
+
+    case 0x34:	/* TEOFF */
+        s->te = 0;
+        break;
+    case 0x35:	/* TEON */
+        if (!s->pm)
+            s->te = 1;
+        else if (s->pm < 0)
+            s->pm = 1;
+        break;
+
+    case 0x36:	/* MADCTR */
+        goto bad_cmd;
+
+    case 0x37:	/* VSCSAD */
+        s->partial = 0;
+        s->normal = 0;
+        s->vscr = 1;
+        break;
+
+    case 0x38:	/* IDMOFF */
+    case 0x39:	/* IDMON */
+    case 0x3a:	/* COLMOD */
+        goto bad_cmd;
+
+    case 0xb0:	/* CLKINT / DISCTL */
+    case 0xb1:	/* CLKEXT */
+        if (s->pm < 0)
+            s->pm = 2;
+        break;
+
+    case 0xb4:	/* FRMSEL */
+        break;
+
+    case 0xb5:	/* FRM8SEL */
+    case 0xb6:	/* TMPRNG / INIESC */
+    case 0xb7:	/* TMPHIS / NOP2 */
+    case 0xb8:	/* TMPREAD / MADCTL */
+    case 0xba:	/* DISTCTR */
+    case 0xbb:	/* EPVOL */
+        goto bad_cmd;
+
+    case 0xbd:	/* Unknown */
+        s->p = 0;
+        s->resp[0] = 0;
+        s->resp[1] = 1;
+        break;
+
+    case 0xc2:	/* IFMOD */
+        if (s->pm < 0)
+            s->pm = 2;
+        break;
+
+    case 0xc6:	/* PWRCTL */
+    case 0xc7:	/* PPWRCTL */
+    case 0xd0:	/* EPWROUT */
+    case 0xd1:	/* EPWRIN */
+    case 0xd4:	/* RDEV */
+    case 0xd5:	/* RDRR */
+        goto bad_cmd;
+
+    case 0xda:	/* RDID1 */
+        s->p = 0;
+        s->resp[0] = (s->id >> 16) & 0xff;
+        break;
+    case 0xdb:	/* RDID2 */
+        s->p = 0;
+        s->resp[0] = (s->id >>  8) & 0xff;
+        break;
+    case 0xdc:	/* RDID3 */
+        s->p = 0;
+        s->resp[0] = (s->id >>  0) & 0xff;
+        break;
+
+    default:
+    bad_cmd:
+        fprintf(stderr, "%s: unknown command %02x\n", __FUNCTION__, s->cmd);
+        break;
+    }
+
+    return ret;
+}
+
+static void *mipid_init(void)
+{
+    struct mipid_s *s = (struct mipid_s *) g_malloc0(sizeof(*s));
+
+    s->id = 0x838f03;
+    mipid_reset(s);
+
+    return s;
+}
+
+static void n8x0_spi_setup(struct n800_s *s)
+{
+    void *tsc = s->ts.opaque;
+    void *mipid = mipid_init();
+
+    omap_mcspi_attach(s->mpu->mcspi[0], s->ts.txrx, tsc, 0);
+    omap_mcspi_attach(s->mpu->mcspi[0], mipid_txrx, mipid, 1);
+}
+
+/* This task is normally performed by the bootloader.  If we're loading
+ * a kernel directly, we need to enable the Blizzard ourselves.  */
+static void n800_dss_init(struct rfbi_chip_s *chip)
+{
+    uint8_t *fb_blank;
+
+    chip->write(chip->opaque, 0, 0x2a);		/* LCD Width register */
+    chip->write(chip->opaque, 1, 0x64);
+    chip->write(chip->opaque, 0, 0x2c);		/* LCD HNDP register */
+    chip->write(chip->opaque, 1, 0x1e);
+    chip->write(chip->opaque, 0, 0x2e);		/* LCD Height 0 register */
+    chip->write(chip->opaque, 1, 0xe0);
+    chip->write(chip->opaque, 0, 0x30);		/* LCD Height 1 register */
+    chip->write(chip->opaque, 1, 0x01);
+    chip->write(chip->opaque, 0, 0x32);		/* LCD VNDP register */
+    chip->write(chip->opaque, 1, 0x06);
+    chip->write(chip->opaque, 0, 0x68);		/* Display Mode register */
+    chip->write(chip->opaque, 1, 1);		/* Enable bit */
+
+    chip->write(chip->opaque, 0, 0x6c);	
+    chip->write(chip->opaque, 1, 0x00);		/* Input X Start Position */
+    chip->write(chip->opaque, 1, 0x00);		/* Input X Start Position */
+    chip->write(chip->opaque, 1, 0x00);		/* Input Y Start Position */
+    chip->write(chip->opaque, 1, 0x00);		/* Input Y Start Position */
+    chip->write(chip->opaque, 1, 0x1f);		/* Input X End Position */
+    chip->write(chip->opaque, 1, 0x03);		/* Input X End Position */
+    chip->write(chip->opaque, 1, 0xdf);		/* Input Y End Position */
+    chip->write(chip->opaque, 1, 0x01);		/* Input Y End Position */
+    chip->write(chip->opaque, 1, 0x00);		/* Output X Start Position */
+    chip->write(chip->opaque, 1, 0x00);		/* Output X Start Position */
+    chip->write(chip->opaque, 1, 0x00);		/* Output Y Start Position */
+    chip->write(chip->opaque, 1, 0x00);		/* Output Y Start Position */
+    chip->write(chip->opaque, 1, 0x1f);		/* Output X End Position */
+    chip->write(chip->opaque, 1, 0x03);		/* Output X End Position */
+    chip->write(chip->opaque, 1, 0xdf);		/* Output Y End Position */
+    chip->write(chip->opaque, 1, 0x01);		/* Output Y End Position */
+    chip->write(chip->opaque, 1, 0x01);		/* Input Data Format */
+    chip->write(chip->opaque, 1, 0x01);		/* Data Source Select */
+
+    fb_blank = memset(g_malloc(800 * 480 * 2), 0xff, 800 * 480 * 2);
+    /* Display Memory Data Port */
+    chip->block(chip->opaque, 1, fb_blank, 800 * 480 * 2, 800);
+    g_free(fb_blank);
+}
+
+static void n8x0_dss_setup(struct n800_s *s)
+{
+    s->blizzard.opaque = s1d13745_init(NULL);
+    s->blizzard.block = s1d13745_write_block;
+    s->blizzard.write = s1d13745_write;
+    s->blizzard.read = s1d13745_read;
+
+    omap_rfbi_attach(s->mpu->dss, 0, &s->blizzard);
+}
+
+static void n8x0_cbus_setup(struct n800_s *s)
+{
+    qemu_irq dat_out = qdev_get_gpio_in(s->mpu->gpio, N8X0_CBUS_DAT_GPIO);
+    qemu_irq retu_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_RETU_GPIO);
+    qemu_irq tahvo_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TAHVO_GPIO);
+
+    CBus *cbus = cbus_init(dat_out);
+
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_CLK_GPIO, cbus->clk);
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_DAT_GPIO, cbus->dat);
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_SEL_GPIO, cbus->sel);
+
+    cbus_attach(cbus, s->retu = retu_init(retu_irq, 1));
+    cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1));
+}
+
+static void n8x0_uart_setup(struct n800_s *s)
+{
+    CharDriverState *radio = uart_hci_init(
+                    qdev_get_gpio_in(s->mpu->gpio, N8X0_BT_HOST_WKUP_GPIO));
+
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_RESET_GPIO,
+                    csrhci_pins_get(radio)[csrhci_pin_reset]);
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_WKUP_GPIO,
+                    csrhci_pins_get(radio)[csrhci_pin_wakeup]);
+
+    omap_uart_attach(s->mpu->uart[BT_UART], radio);
+}
+
+static void n8x0_usb_setup(struct n800_s *s)
+{
+    SysBusDevice *dev;
+    s->usb = qdev_create(NULL, "tusb6010");
+    dev = SYS_BUS_DEVICE(s->usb);
+    qdev_init_nofail(s->usb);
+    sysbus_connect_irq(dev, 0,
+                       qdev_get_gpio_in(s->mpu->gpio, N8X0_TUSB_INT_GPIO));
+    /* Using the NOR interface */
+    omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_ASYNC_CS,
+                     sysbus_mmio_get_region(dev, 0));
+    omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_SYNC_CS,
+                     sysbus_mmio_get_region(dev, 1));
+    qdev_connect_gpio_out(s->mpu->gpio, N8X0_TUSB_ENABLE_GPIO,
+                          qdev_get_gpio_in(s->usb, 0)); /* tusb_pwr */
+}
+
+/* Setup done before the main bootloader starts by some early setup code
+ * - used when we want to run the main bootloader in emulation.  This
+ * isn't documented.  */
+static uint32_t n800_pinout[104] = {
+    0x080f00d8, 0x00d40808, 0x03080808, 0x080800d0,
+    0x00dc0808, 0x0b0f0f00, 0x080800b4, 0x00c00808,
+    0x08080808, 0x180800c4, 0x00b80000, 0x08080808,
+    0x080800bc, 0x00cc0808, 0x08081818, 0x18180128,
+    0x01241800, 0x18181818, 0x000000f0, 0x01300000,
+    0x00001b0b, 0x1b0f0138, 0x00e0181b, 0x1b031b0b,
+    0x180f0078, 0x00740018, 0x0f0f0f1a, 0x00000080,
+    0x007c0000, 0x00000000, 0x00000088, 0x00840000,
+    0x00000000, 0x00000094, 0x00980300, 0x0f180003,
+    0x0000008c, 0x00900f0f, 0x0f0f1b00, 0x0f00009c,
+    0x01140000, 0x1b1b0f18, 0x0818013c, 0x01400008,
+    0x00001818, 0x000b0110, 0x010c1800, 0x0b030b0f,
+    0x181800f4, 0x00f81818, 0x00000018, 0x000000fc,
+    0x00401808, 0x00000000, 0x0f1b0030, 0x003c0008,
+    0x00000000, 0x00000038, 0x00340000, 0x00000000,
+    0x1a080070, 0x00641a1a, 0x08080808, 0x08080060,
+    0x005c0808, 0x08080808, 0x08080058, 0x00540808,
+    0x08080808, 0x0808006c, 0x00680808, 0x08080808,
+    0x000000a8, 0x00b00000, 0x08080808, 0x000000a0,
+    0x00a40000, 0x00000000, 0x08ff0050, 0x004c0808,
+    0xffffffff, 0xffff0048, 0x0044ffff, 0xffffffff,
+    0x000000ac, 0x01040800, 0x08080b0f, 0x18180100,
+    0x01081818, 0x0b0b1808, 0x1a0300e4, 0x012c0b1a,
+    0x02020018, 0x0b000134, 0x011c0800, 0x0b1b1b00,
+    0x0f0000c8, 0x00ec181b, 0x000f0f02, 0x00180118,
+    0x01200000, 0x0f0b1b1b, 0x0f0200e8, 0x0000020b,
+};
+
+static void n800_setup_nolo_tags(void *sram_base)
+{
+    int i;
+    uint32_t *p = sram_base + 0x8000;
+    uint32_t *v = sram_base + 0xa000;
+
+    memset(p, 0, 0x3000);
+
+    strcpy((void *) (p + 0), "QEMU N800");
+
+    strcpy((void *) (p + 8), "F5");
+
+    stl_raw(p + 10, 0x04f70000);
+    strcpy((void *) (p + 9), "RX-34");
+
+    /* RAM size in MB? */
+    stl_raw(p + 12, 0x80);
+
+    /* Pointer to the list of tags */
+    stl_raw(p + 13, OMAP2_SRAM_BASE + 0x9000);
+
+    /* The NOLO tags start here */
+    p = sram_base + 0x9000;
+#define ADD_TAG(tag, len)				\
+    stw_raw((uint16_t *) p + 0, tag);			\
+    stw_raw((uint16_t *) p + 1, len); p ++;		\
+    stl_raw(p ++, OMAP2_SRAM_BASE | (((void *) v - sram_base) & 0xffff));
+
+    /* OMAP STI console? Pin out settings? */
+    ADD_TAG(0x6e01, 414);
+    for (i = 0; i < ARRAY_SIZE(n800_pinout); i ++)
+        stl_raw(v ++, n800_pinout[i]);
+
+    /* Kernel memsize? */
+    ADD_TAG(0x6e05, 1);
+    stl_raw(v ++, 2);
+
+    /* NOLO serial console */
+    ADD_TAG(0x6e02, 4);
+    stl_raw(v ++, XLDR_LL_UART);	/* UART number (1 - 3) */
+
+#if 0
+    /* CBUS settings (Retu/AVilma) */
+    ADD_TAG(0x6e03, 6);
+    stw_raw((uint16_t *) v + 0, 65);	/* CBUS GPIO0 */
+    stw_raw((uint16_t *) v + 1, 66);	/* CBUS GPIO1 */
+    stw_raw((uint16_t *) v + 2, 64);	/* CBUS GPIO2 */
+    v += 2;
+#endif
+
+    /* Nokia ASIC BB5 (Retu/Tahvo) */
+    ADD_TAG(0x6e0a, 4);
+    stw_raw((uint16_t *) v + 0, 111);	/* "Retu" interrupt GPIO */
+    stw_raw((uint16_t *) v + 1, 108);	/* "Tahvo" interrupt GPIO */
+    v ++;
+
+    /* LCD console? */
+    ADD_TAG(0x6e04, 4);
+    stw_raw((uint16_t *) v + 0, 30);	/* ??? */
+    stw_raw((uint16_t *) v + 1, 24);	/* ??? */
+    v ++;
+
+#if 0
+    /* LCD settings */
+    ADD_TAG(0x6e06, 2);
+    stw_raw((uint16_t *) (v ++), 15);	/* ??? */
+#endif
+
+    /* I^2C (Menelaus) */
+    ADD_TAG(0x6e07, 4);
+    stl_raw(v ++, 0x00720000);		/* ??? */
+
+    /* Unknown */
+    ADD_TAG(0x6e0b, 6);
+    stw_raw((uint16_t *) v + 0, 94);	/* ??? */
+    stw_raw((uint16_t *) v + 1, 23);	/* ??? */
+    stw_raw((uint16_t *) v + 2, 0);	/* ??? */
+    v += 2;
+
+    /* OMAP gpio switch info */
+    ADD_TAG(0x6e0c, 80);
+    strcpy((void *) v, "bat_cover");	v += 3;
+    stw_raw((uint16_t *) v + 0, 110);	/* GPIO num ??? */
+    stw_raw((uint16_t *) v + 1, 1);	/* GPIO num ??? */
+    v += 2;
+    strcpy((void *) v, "cam_act");	v += 3;
+    stw_raw((uint16_t *) v + 0, 95);	/* GPIO num ??? */
+    stw_raw((uint16_t *) v + 1, 32);	/* GPIO num ??? */
+    v += 2;
+    strcpy((void *) v, "cam_turn");	v += 3;
+    stw_raw((uint16_t *) v + 0, 12);	/* GPIO num ??? */
+    stw_raw((uint16_t *) v + 1, 33);	/* GPIO num ??? */
+    v += 2;
+    strcpy((void *) v, "headphone");	v += 3;
+    stw_raw((uint16_t *) v + 0, 107);	/* GPIO num ??? */
+    stw_raw((uint16_t *) v + 1, 17);	/* GPIO num ??? */
+    v += 2;
+
+    /* Bluetooth */
+    ADD_TAG(0x6e0e, 12);
+    stl_raw(v ++, 0x5c623d01);		/* ??? */
+    stl_raw(v ++, 0x00000201);		/* ??? */
+    stl_raw(v ++, 0x00000000);		/* ??? */
+
+    /* CX3110x WLAN settings */
+    ADD_TAG(0x6e0f, 8);
+    stl_raw(v ++, 0x00610025);		/* ??? */
+    stl_raw(v ++, 0xffff0057);		/* ??? */
+
+    /* MMC host settings */
+    ADD_TAG(0x6e10, 12);
+    stl_raw(v ++, 0xffff000f);		/* ??? */
+    stl_raw(v ++, 0xffffffff);		/* ??? */
+    stl_raw(v ++, 0x00000060);		/* ??? */
+
+    /* OneNAND chip select */
+    ADD_TAG(0x6e11, 10);
+    stl_raw(v ++, 0x00000401);		/* ??? */
+    stl_raw(v ++, 0x0002003a);		/* ??? */
+    stl_raw(v ++, 0x00000002);		/* ??? */
+
+    /* TEA5761 sensor settings */
+    ADD_TAG(0x6e12, 2);
+    stl_raw(v ++, 93);			/* GPIO num ??? */
+
+#if 0
+    /* Unknown tag */
+    ADD_TAG(6e09, 0);
+
+    /* Kernel UART / console */
+    ADD_TAG(6e12, 0);
+#endif
+
+    /* End of the list */
+    stl_raw(p ++, 0x00000000);
+    stl_raw(p ++, 0x00000000);
+}
+
+/* This task is normally performed by the bootloader.  If we're loading
+ * a kernel directly, we need to set up GPMC mappings ourselves.  */
+static void n800_gpmc_init(struct n800_s *s)
+{
+    uint32_t config7 =
+            (0xf << 8) |	/* MASKADDRESS */
+            (1 << 6) |		/* CSVALID */
+            (4 << 0);		/* BASEADDRESS */
+
+    cpu_physical_memory_write(0x6800a078,		/* GPMC_CONFIG7_0 */
+                    (void *) &config7, sizeof(config7));
+}
+
+/* Setup sequence done by the bootloader */
+static void n8x0_boot_init(void *opaque)
+{
+    struct n800_s *s = (struct n800_s *) opaque;
+    uint32_t buf;
+
+    /* PRCM setup */
+#define omap_writel(addr, val)	\
+    buf = (val);			\
+    cpu_physical_memory_write(addr, (void *) &buf, sizeof(buf))
+
+    omap_writel(0x48008060, 0x41);		/* PRCM_CLKSRC_CTRL */
+    omap_writel(0x48008070, 1);			/* PRCM_CLKOUT_CTRL */
+    omap_writel(0x48008078, 0);			/* PRCM_CLKEMUL_CTRL */
+    omap_writel(0x48008090, 0);			/* PRCM_VOLTSETUP */
+    omap_writel(0x48008094, 0);			/* PRCM_CLKSSETUP */
+    omap_writel(0x48008098, 0);			/* PRCM_POLCTRL */
+    omap_writel(0x48008140, 2);			/* CM_CLKSEL_MPU */
+    omap_writel(0x48008148, 0);			/* CM_CLKSTCTRL_MPU */
+    omap_writel(0x48008158, 1);			/* RM_RSTST_MPU */
+    omap_writel(0x480081c8, 0x15);		/* PM_WKDEP_MPU */
+    omap_writel(0x480081d4, 0x1d4);		/* PM_EVGENCTRL_MPU */
+    omap_writel(0x480081d8, 0);			/* PM_EVEGENONTIM_MPU */
+    omap_writel(0x480081dc, 0);			/* PM_EVEGENOFFTIM_MPU */
+    omap_writel(0x480081e0, 0xc);		/* PM_PWSTCTRL_MPU */
+    omap_writel(0x48008200, 0x047e7ff7);	/* CM_FCLKEN1_CORE */
+    omap_writel(0x48008204, 0x00000004);	/* CM_FCLKEN2_CORE */
+    omap_writel(0x48008210, 0x047e7ff1);	/* CM_ICLKEN1_CORE */
+    omap_writel(0x48008214, 0x00000004);	/* CM_ICLKEN2_CORE */
+    omap_writel(0x4800821c, 0x00000000);	/* CM_ICLKEN4_CORE */
+    omap_writel(0x48008230, 0);			/* CM_AUTOIDLE1_CORE */
+    omap_writel(0x48008234, 0);			/* CM_AUTOIDLE2_CORE */
+    omap_writel(0x48008238, 7);			/* CM_AUTOIDLE3_CORE */
+    omap_writel(0x4800823c, 0);			/* CM_AUTOIDLE4_CORE */
+    omap_writel(0x48008240, 0x04360626);	/* CM_CLKSEL1_CORE */
+    omap_writel(0x48008244, 0x00000014);	/* CM_CLKSEL2_CORE */
+    omap_writel(0x48008248, 0);			/* CM_CLKSTCTRL_CORE */
+    omap_writel(0x48008300, 0x00000000);	/* CM_FCLKEN_GFX */
+    omap_writel(0x48008310, 0x00000000);	/* CM_ICLKEN_GFX */
+    omap_writel(0x48008340, 0x00000001);	/* CM_CLKSEL_GFX */
+    omap_writel(0x48008400, 0x00000004);	/* CM_FCLKEN_WKUP */
+    omap_writel(0x48008410, 0x00000004);	/* CM_ICLKEN_WKUP */
+    omap_writel(0x48008440, 0x00000000);	/* CM_CLKSEL_WKUP */
+    omap_writel(0x48008500, 0x000000cf);	/* CM_CLKEN_PLL */
+    omap_writel(0x48008530, 0x0000000c);	/* CM_AUTOIDLE_PLL */
+    omap_writel(0x48008540,			/* CM_CLKSEL1_PLL */
+                    (0x78 << 12) | (6 << 8));
+    omap_writel(0x48008544, 2);			/* CM_CLKSEL2_PLL */
+
+    /* GPMC setup */
+    n800_gpmc_init(s);
+
+    /* Video setup */
+    n800_dss_init(&s->blizzard);
+
+    /* CPU setup */
+    s->mpu->cpu->env.GE = 0x5;
+
+    /* If the machine has a slided keyboard, open it */
+    if (s->kbd)
+        qemu_irq_raise(qdev_get_gpio_in(s->mpu->gpio, N810_SLIDE_GPIO));
+}
+
+#define OMAP_TAG_NOKIA_BT	0x4e01
+#define OMAP_TAG_WLAN_CX3110X	0x4e02
+#define OMAP_TAG_CBUS		0x4e03
+#define OMAP_TAG_EM_ASIC_BB5	0x4e04
+
+static struct omap_gpiosw_info_s {
+    const char *name;
+    int line;
+    int type;
+} n800_gpiosw_info[] = {
+    {
+        "bat_cover", N800_BAT_COVER_GPIO,
+        OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
+    }, {
+        "cam_act", N800_CAM_ACT_GPIO,
+        OMAP_GPIOSW_TYPE_ACTIVITY,
+    }, {
+        "cam_turn", N800_CAM_TURN_GPIO,
+        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED,
+    }, {
+        "headphone", N8X0_HEADPHONE_GPIO,
+        OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED,
+    },
+    { NULL }
+}, n810_gpiosw_info[] = {
+    {
+        "gps_reset", N810_GPS_RESET_GPIO,
+        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT,
+    }, {
+        "gps_wakeup", N810_GPS_WAKEUP_GPIO,
+        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT,
+    }, {
+        "headphone", N8X0_HEADPHONE_GPIO,
+        OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED,
+    }, {
+        "kb_lock", N810_KB_LOCK_GPIO,
+        OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
+    }, {
+        "sleepx_led", N810_SLEEPX_LED_GPIO,
+        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED | OMAP_GPIOSW_OUTPUT,
+    }, {
+        "slide", N810_SLIDE_GPIO,
+        OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
+    },
+    { NULL }
+};
+
+static struct omap_partition_info_s {
+    uint32_t offset;
+    uint32_t size;
+    int mask;
+    const char *name;
+} n800_part_info[] = {
+    { 0x00000000, 0x00020000, 0x3, "bootloader" },
+    { 0x00020000, 0x00060000, 0x0, "config" },
+    { 0x00080000, 0x00200000, 0x0, "kernel" },
+    { 0x00280000, 0x00200000, 0x3, "initfs" },
+    { 0x00480000, 0x0fb80000, 0x3, "rootfs" },
+
+    { 0, 0, 0, NULL }
+}, n810_part_info[] = {
+    { 0x00000000, 0x00020000, 0x3, "bootloader" },
+    { 0x00020000, 0x00060000, 0x0, "config" },
+    { 0x00080000, 0x00220000, 0x0, "kernel" },
+    { 0x002a0000, 0x00400000, 0x0, "initfs" },
+    { 0x006a0000, 0x0f960000, 0x0, "rootfs" },
+
+    { 0, 0, 0, NULL }
+};
+
+static bdaddr_t n8x0_bd_addr = {{ N8X0_BD_ADDR }};
+
+static int n8x0_atag_setup(void *p, int model)
+{
+    uint8_t *b;
+    uint16_t *w;
+    uint32_t *l;
+    struct omap_gpiosw_info_s *gpiosw;
+    struct omap_partition_info_s *partition;
+    const char *tag;
+
+    w = p;
+
+    stw_raw(w ++, OMAP_TAG_UART);		/* u16 tag */
+    stw_raw(w ++, 4);				/* u16 len */
+    stw_raw(w ++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
+    w ++;
+
+#if 0
+    stw_raw(w ++, OMAP_TAG_SERIAL_CONSOLE);	/* u16 tag */
+    stw_raw(w ++, 4);				/* u16 len */
+    stw_raw(w ++, XLDR_LL_UART + 1);		/* u8 console_uart */
+    stw_raw(w ++, 115200);			/* u32 console_speed */
+#endif
+
+    stw_raw(w ++, OMAP_TAG_LCD);		/* u16 tag */
+    stw_raw(w ++, 36);				/* u16 len */
+    strcpy((void *) w, "QEMU LCD panel");	/* char panel_name[16] */
+    w += 8;
+    strcpy((void *) w, "blizzard");		/* char ctrl_name[16] */
+    w += 8;
+    stw_raw(w ++, N810_BLIZZARD_RESET_GPIO);	/* TODO: n800 s16 nreset_gpio */
+    stw_raw(w ++, 24);				/* u8 data_lines */
+
+    stw_raw(w ++, OMAP_TAG_CBUS);		/* u16 tag */
+    stw_raw(w ++, 8);				/* u16 len */
+    stw_raw(w ++, N8X0_CBUS_CLK_GPIO);		/* s16 clk_gpio */
+    stw_raw(w ++, N8X0_CBUS_DAT_GPIO);		/* s16 dat_gpio */
+    stw_raw(w ++, N8X0_CBUS_SEL_GPIO);		/* s16 sel_gpio */
+    w ++;
+
+    stw_raw(w ++, OMAP_TAG_EM_ASIC_BB5);	/* u16 tag */
+    stw_raw(w ++, 4);				/* u16 len */
+    stw_raw(w ++, N8X0_RETU_GPIO);		/* s16 retu_irq_gpio */
+    stw_raw(w ++, N8X0_TAHVO_GPIO);		/* s16 tahvo_irq_gpio */
+
+    gpiosw = (model == 810) ? n810_gpiosw_info : n800_gpiosw_info;
+    for (; gpiosw->name; gpiosw ++) {
+        stw_raw(w ++, OMAP_TAG_GPIO_SWITCH);	/* u16 tag */
+        stw_raw(w ++, 20);			/* u16 len */
+        strcpy((void *) w, gpiosw->name);	/* char name[12] */
+        w += 6;
+        stw_raw(w ++, gpiosw->line);		/* u16 gpio */
+        stw_raw(w ++, gpiosw->type);
+        stw_raw(w ++, 0);
+        stw_raw(w ++, 0);
+    }
+
+    stw_raw(w ++, OMAP_TAG_NOKIA_BT);		/* u16 tag */
+    stw_raw(w ++, 12);				/* u16 len */
+    b = (void *) w;
+    stb_raw(b ++, 0x01);			/* u8 chip_type	(CSR) */
+    stb_raw(b ++, N8X0_BT_WKUP_GPIO);		/* u8 bt_wakeup_gpio */
+    stb_raw(b ++, N8X0_BT_HOST_WKUP_GPIO);	/* u8 host_wakeup_gpio */
+    stb_raw(b ++, N8X0_BT_RESET_GPIO);		/* u8 reset_gpio */
+    stb_raw(b ++, BT_UART + 1);			/* u8 bt_uart */
+    memcpy(b, &n8x0_bd_addr, 6);		/* u8 bd_addr[6] */
+    b += 6;
+    stb_raw(b ++, 0x02);			/* u8 bt_sysclk (38.4) */
+    w = (void *) b;
+
+    stw_raw(w ++, OMAP_TAG_WLAN_CX3110X);	/* u16 tag */
+    stw_raw(w ++, 8);				/* u16 len */
+    stw_raw(w ++, 0x25);			/* u8 chip_type */
+    stw_raw(w ++, N8X0_WLAN_PWR_GPIO);		/* s16 power_gpio */
+    stw_raw(w ++, N8X0_WLAN_IRQ_GPIO);		/* s16 irq_gpio */
+    stw_raw(w ++, -1);				/* s16 spi_cs_gpio */
+
+    stw_raw(w ++, OMAP_TAG_MMC);		/* u16 tag */
+    stw_raw(w ++, 16);				/* u16 len */
+    if (model == 810) {
+        stw_raw(w ++, 0x23f);			/* unsigned flags */
+        stw_raw(w ++, -1);			/* s16 power_pin */
+        stw_raw(w ++, -1);			/* s16 switch_pin */
+        stw_raw(w ++, -1);			/* s16 wp_pin */
+        stw_raw(w ++, 0x240);			/* unsigned flags */
+        stw_raw(w ++, 0xc000);			/* s16 power_pin */
+        stw_raw(w ++, 0x0248);			/* s16 switch_pin */
+        stw_raw(w ++, 0xc000);			/* s16 wp_pin */
+    } else {
+        stw_raw(w ++, 0xf);			/* unsigned flags */
+        stw_raw(w ++, -1);			/* s16 power_pin */
+        stw_raw(w ++, -1);			/* s16 switch_pin */
+        stw_raw(w ++, -1);			/* s16 wp_pin */
+        stw_raw(w ++, 0);			/* unsigned flags */
+        stw_raw(w ++, 0);			/* s16 power_pin */
+        stw_raw(w ++, 0);			/* s16 switch_pin */
+        stw_raw(w ++, 0);			/* s16 wp_pin */
+    }
+
+    stw_raw(w ++, OMAP_TAG_TEA5761);		/* u16 tag */
+    stw_raw(w ++, 4);				/* u16 len */
+    stw_raw(w ++, N8X0_TEA5761_CS_GPIO);	/* u16 enable_gpio */
+    w ++;
+
+    partition = (model == 810) ? n810_part_info : n800_part_info;
+    for (; partition->name; partition ++) {
+        stw_raw(w ++, OMAP_TAG_PARTITION);	/* u16 tag */
+        stw_raw(w ++, 28);			/* u16 len */
+        strcpy((void *) w, partition->name);	/* char name[16] */
+        l = (void *) (w + 8);
+        stl_raw(l ++, partition->size);		/* unsigned int size */
+        stl_raw(l ++, partition->offset);	/* unsigned int offset */
+        stl_raw(l ++, partition->mask);		/* unsigned int mask_flags */
+        w = (void *) l;
+    }
+
+    stw_raw(w ++, OMAP_TAG_BOOT_REASON);	/* u16 tag */
+    stw_raw(w ++, 12);				/* u16 len */
+#if 0
+    strcpy((void *) w, "por");			/* char reason_str[12] */
+    strcpy((void *) w, "charger");		/* char reason_str[12] */
+    strcpy((void *) w, "32wd_to");		/* char reason_str[12] */
+    strcpy((void *) w, "sw_rst");		/* char reason_str[12] */
+    strcpy((void *) w, "mbus");			/* char reason_str[12] */
+    strcpy((void *) w, "unknown");		/* char reason_str[12] */
+    strcpy((void *) w, "swdg_to");		/* char reason_str[12] */
+    strcpy((void *) w, "sec_vio");		/* char reason_str[12] */
+    strcpy((void *) w, "pwr_key");		/* char reason_str[12] */
+    strcpy((void *) w, "rtc_alarm");		/* char reason_str[12] */
+#else
+    strcpy((void *) w, "pwr_key");		/* char reason_str[12] */
+#endif
+    w += 6;
+
+    tag = (model == 810) ? "RX-44" : "RX-34";
+    stw_raw(w ++, OMAP_TAG_VERSION_STR);	/* u16 tag */
+    stw_raw(w ++, 24);				/* u16 len */
+    strcpy((void *) w, "product");		/* char component[12] */
+    w += 6;
+    strcpy((void *) w, tag);			/* char version[12] */
+    w += 6;
+
+    stw_raw(w ++, OMAP_TAG_VERSION_STR);	/* u16 tag */
+    stw_raw(w ++, 24);				/* u16 len */
+    strcpy((void *) w, "hw-build");		/* char component[12] */
+    w += 6;
+    strcpy((void *) w, "QEMU ");
+    pstrcat((void *) w, 12, qemu_get_version()); /* char version[12] */
+    w += 6;
+
+    tag = (model == 810) ? "1.1.10-qemu" : "1.1.6-qemu";
+    stw_raw(w ++, OMAP_TAG_VERSION_STR);	/* u16 tag */
+    stw_raw(w ++, 24);				/* u16 len */
+    strcpy((void *) w, "nolo");			/* char component[12] */
+    w += 6;
+    strcpy((void *) w, tag);			/* char version[12] */
+    w += 6;
+
+    return (void *) w - p;
+}
+
+static int n800_atag_setup(const struct arm_boot_info *info, void *p)
+{
+    return n8x0_atag_setup(p, 800);
+}
+
+static int n810_atag_setup(const struct arm_boot_info *info, void *p)
+{
+    return n8x0_atag_setup(p, 810);
+}
+
+static void n8x0_init(QEMUMachineInitArgs *args,
+                      struct arm_boot_info *binfo, int model)
+{
+    MemoryRegion *sysmem = get_system_memory();
+    struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s));
+    int sdram_size = binfo->ram_size;
+    DisplayState *ds;
+
+    s->mpu = omap2420_mpu_init(sysmem, sdram_size, args->cpu_model);
+
+    /* Setup peripherals
+     *
+     * Believed external peripherals layout in the N810:
+     * (spi bus 1)
+     *   tsc2005
+     *   lcd_mipid
+     * (spi bus 2)
+     *   Conexant cx3110x (WLAN)
+     *   optional: pc2400m (WiMAX)
+     * (i2c bus 0)
+     *   TLV320AIC33 (audio codec)
+     *   TCM825x (camera by Toshiba)
+     *   lp5521 (clever LEDs)
+     *   tsl2563 (light sensor, hwmon, model 7, rev. 0)
+     *   lm8323 (keypad, manf 00, rev 04)
+     * (i2c bus 1)
+     *   tmp105 (temperature sensor, hwmon)
+     *   menelaus (pm)
+     * (somewhere on i2c - maybe N800-only)
+     *   tea5761 (FM tuner)
+     * (serial 0)
+     *   GPS
+     * (some serial port)
+     *   csr41814 (Bluetooth)
+     */
+    n8x0_gpio_setup(s);
+    n8x0_nand_setup(s);
+    n8x0_i2c_setup(s);
+    if (model == 800)
+        n800_tsc_kbd_setup(s);
+    else if (model == 810) {
+        n810_tsc_setup(s);
+        n810_kbd_setup(s);
+    }
+    n8x0_spi_setup(s);
+    n8x0_dss_setup(s);
+    n8x0_cbus_setup(s);
+    n8x0_uart_setup(s);
+    if (usb_enabled(false)) {
+        n8x0_usb_setup(s);
+    }
+
+    if (args->kernel_filename) {
+        /* Or at the linux loader.  */
+        binfo->kernel_filename = args->kernel_filename;
+        binfo->kernel_cmdline = args->kernel_cmdline;
+        binfo->initrd_filename = args->initrd_filename;
+        arm_load_kernel(s->mpu->cpu, binfo);
+
+        qemu_register_reset(n8x0_boot_init, s);
+    }
+
+    if (option_rom[0].name &&
+        (args->boot_device[0] == 'n' || !args->kernel_filename)) {
+        int rom_size;
+        uint8_t nolo_tags[0x10000];
+        /* No, wait, better start at the ROM.  */
+        s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
+
+        /* This is intended for loading the `secondary.bin' program from
+         * Nokia images (the NOLO bootloader).  The entry point seems
+         * to be at OMAP2_Q2_BASE + 0x400000.
+         *
+         * The `2nd.bin' files contain some kind of earlier boot code and
+         * for them the entry point needs to be set to OMAP2_SRAM_BASE.
+         *
+         * The code above is for loading the `zImage' file from Nokia
+         * images.  */
+        rom_size = load_image_targphys(option_rom[0].name,
+                                       OMAP2_Q2_BASE + 0x400000,
+                                       sdram_size - 0x400000);
+        printf("%i bytes of image loaded\n", rom_size);
+
+        n800_setup_nolo_tags(nolo_tags);
+        cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000);
+    }
+    /* FIXME: We shouldn't really be doing this here.  The LCD controller
+       will set the size once configured, so this just sets an initial
+       size until the guest activates the display.  */
+    ds = get_displaystate();
+    ds->surface = qemu_resize_displaysurface(ds, 800, 480);
+    dpy_gfx_resize(ds);
+}
+
+static struct arm_boot_info n800_binfo = {
+    .loader_start = OMAP2_Q2_BASE,
+    /* Actually two chips of 0x4000000 bytes each */
+    .ram_size = 0x08000000,
+    .board_id = 0x4f7,
+    .atag_board = n800_atag_setup,
+};
+
+static struct arm_boot_info n810_binfo = {
+    .loader_start = OMAP2_Q2_BASE,
+    /* Actually two chips of 0x4000000 bytes each */
+    .ram_size = 0x08000000,
+    /* 0x60c and 0x6bf (WiMAX Edition) have been assigned but are not
+     * used by some older versions of the bootloader and 5555 is used
+     * instead (including versions that shipped with many devices).  */
+    .board_id = 0x60c,
+    .atag_board = n810_atag_setup,
+};
+
+static void n800_init(QEMUMachineInitArgs *args)
+{
+    return n8x0_init(args, &n800_binfo, 800);
+}
+
+static void n810_init(QEMUMachineInitArgs *args)
+{
+    return n8x0_init(args, &n810_binfo, 810);
+}
+
+static QEMUMachine n800_machine = {
+    .name = "n800",
+    .desc = "Nokia N800 tablet aka. RX-34 (OMAP2420)",
+    .init = n800_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine n810_machine = {
+    .name = "n810",
+    .desc = "Nokia N810 tablet aka. RX-44 (OMAP2420)",
+    .init = n810_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void nseries_machine_init(void)
+{
+    qemu_register_machine(&n800_machine);
+    qemu_register_machine(&n810_machine);
+}
+
+machine_init(nseries_machine_init);
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
new file mode 100644
index 0000000..8598233
--- /dev/null
+++ b/hw/arm/omap_sx1.c
@@ -0,0 +1,238 @@
+/* omap_sx1.c Support for the Siemens SX1 smartphone emulation.
+ *
+ *   Copyright (C) 2008
+ * 	Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>
+ *   Copyright (C) 2007 Vladimir Ananiev <vovan888 at gmail.com>
+ *
+ *   based on PalmOne's (TM) PDAs support (palm.c)
+ */
+
+/*
+ * PalmOne's (TM) PDAs.
+ *
+ * Copyright (C) 2006-2007 Andrzej Zaborowski <balrog at zabor.org>
+ *
+ * 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/>.
+ */
+#include "hw/hw.h"
+#include "ui/console.h"
+#include "hw/omap.h"
+#include "hw/boards.h"
+#include "hw/arm-misc.h"
+#include "hw/flash.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+/*****************************************************************************/
+/* Siemens SX1 Cellphone V1 */
+/* - ARM OMAP310 processor
+ * - SRAM                192 kB
+ * - SDRAM                32 MB at 0x10000000
+ * - Boot flash           16 MB at 0x00000000
+ * - Application flash     8 MB at 0x04000000
+ * - 3 serial ports
+ * - 1 SecureDigital
+ * - 1 LCD display
+ * - 1 RTC
+ */
+
+/*****************************************************************************/
+/* Siemens SX1 Cellphone V2 */
+/* - ARM OMAP310 processor
+ * - SRAM                192 kB
+ * - SDRAM                32 MB at 0x10000000
+ * - Boot flash           32 MB at 0x00000000
+ * - 3 serial ports
+ * - 1 SecureDigital
+ * - 1 LCD display
+ * - 1 RTC
+ */
+
+static uint64_t static_read(void *opaque, hwaddr offset,
+                            unsigned size)
+{
+    uint32_t *val = (uint32_t *) opaque;
+    uint32_t mask = (4 / size) - 1;
+
+    return *val >> ((offset & mask) << 3);
+}
+
+static void static_write(void *opaque, hwaddr offset,
+                         uint64_t value, unsigned size)
+{
+#ifdef SPY
+    printf("%s: value %" PRIx64 " %u bytes written at 0x%x\n",
+                    __func__, value, size, (int)offset);
+#endif
+}
+
+static const MemoryRegionOps static_ops = {
+    .read = static_read,
+    .write = static_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+#define sdram_size	0x02000000
+#define sector_size	(128 * 1024)
+#define flash0_size	(16 * 1024 * 1024)
+#define flash1_size	( 8 * 1024 * 1024)
+#define flash2_size	(32 * 1024 * 1024)
+#define total_ram_v1	(sdram_size + flash0_size + flash1_size + OMAP15XX_SRAM_SIZE)
+#define total_ram_v2	(sdram_size + flash2_size + OMAP15XX_SRAM_SIZE)
+
+static struct arm_boot_info sx1_binfo = {
+    .loader_start = OMAP_EMIFF_BASE,
+    .ram_size = sdram_size,
+    .board_id = 0x265,
+};
+
+static void sx1_init(QEMUMachineInitArgs *args, const int version)
+{
+    struct omap_mpu_state_s *mpu;
+    MemoryRegion *address_space = get_system_memory();
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
+    MemoryRegion *flash_1 = g_new(MemoryRegion, 1);
+    MemoryRegion *cs = g_new(MemoryRegion, 4);
+    static uint32_t cs0val = 0x00213090;
+    static uint32_t cs1val = 0x00215070;
+    static uint32_t cs2val = 0x00001139;
+    static uint32_t cs3val = 0x00001139;
+    DriveInfo *dinfo;
+    int fl_idx;
+    uint32_t flash_size = flash0_size;
+    int be;
+
+    if (version == 2) {
+        flash_size = flash2_size;
+    }
+
+    mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, args->cpu_model);
+
+    /* External Flash (EMIFS) */
+    memory_region_init_ram(flash, "omap_sx1.flash0-0", flash_size);
+    vmstate_register_ram_global(flash);
+    memory_region_set_readonly(flash, true);
+    memory_region_add_subregion(address_space, OMAP_CS0_BASE, flash);
+
+    memory_region_init_io(&cs[0], &static_ops, &cs0val,
+                          "sx1.cs0", OMAP_CS0_SIZE - flash_size);
+    memory_region_add_subregion(address_space,
+                                OMAP_CS0_BASE + flash_size, &cs[0]);
+
+
+    memory_region_init_io(&cs[2], &static_ops, &cs2val,
+                          "sx1.cs2", OMAP_CS2_SIZE);
+    memory_region_add_subregion(address_space,
+                                OMAP_CS2_BASE, &cs[2]);
+
+    memory_region_init_io(&cs[3], &static_ops, &cs3val,
+                          "sx1.cs3", OMAP_CS3_SIZE);
+    memory_region_add_subregion(address_space,
+                                OMAP_CS2_BASE, &cs[3]);
+
+    fl_idx = 0;
+#ifdef TARGET_WORDS_BIGENDIAN
+    be = 1;
+#else
+    be = 0;
+#endif
+
+    if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
+        if (!pflash_cfi01_register(OMAP_CS0_BASE, NULL,
+                                   "omap_sx1.flash0-1", flash_size,
+                                   dinfo->bdrv, sector_size,
+                                   flash_size / sector_size,
+                                   4, 0, 0, 0, 0, be)) {
+            fprintf(stderr, "qemu: Error registering flash memory %d.\n",
+                           fl_idx);
+        }
+        fl_idx++;
+    }
+
+    if ((version == 1) &&
+            (dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
+        memory_region_init_ram(flash_1, "omap_sx1.flash1-0", flash1_size);
+        vmstate_register_ram_global(flash_1);
+        memory_region_set_readonly(flash_1, true);
+        memory_region_add_subregion(address_space, OMAP_CS1_BASE, flash_1);
+
+        memory_region_init_io(&cs[1], &static_ops, &cs1val,
+                              "sx1.cs1", OMAP_CS1_SIZE - flash1_size);
+        memory_region_add_subregion(address_space,
+                                OMAP_CS1_BASE + flash1_size, &cs[1]);
+
+        if (!pflash_cfi01_register(OMAP_CS1_BASE, NULL,
+                                   "omap_sx1.flash1-1", flash1_size,
+                                   dinfo->bdrv, sector_size,
+                                   flash1_size / sector_size,
+                                   4, 0, 0, 0, 0, be)) {
+            fprintf(stderr, "qemu: Error registering flash memory %d.\n",
+                           fl_idx);
+        }
+        fl_idx++;
+    } else {
+        memory_region_init_io(&cs[1], &static_ops, &cs1val,
+                              "sx1.cs1", OMAP_CS1_SIZE);
+        memory_region_add_subregion(address_space,
+                                OMAP_CS1_BASE, &cs[1]);
+    }
+
+    if (!args->kernel_filename && !fl_idx) {
+        fprintf(stderr, "Kernel or Flash image must be specified\n");
+        exit(1);
+    }
+
+    /* Load the kernel.  */
+    if (args->kernel_filename) {
+        sx1_binfo.kernel_filename = args->kernel_filename;
+        sx1_binfo.kernel_cmdline = args->kernel_cmdline;
+        sx1_binfo.initrd_filename = args->initrd_filename;
+        arm_load_kernel(mpu->cpu, &sx1_binfo);
+    }
+
+    /* TODO: fix next line */
+    //~ qemu_console_resize(ds, 640, 480);
+}
+
+static void sx1_init_v1(QEMUMachineInitArgs *args)
+{
+    sx1_init(args, 1);
+}
+
+static void sx1_init_v2(QEMUMachineInitArgs *args)
+{
+    sx1_init(args, 2);
+}
+
+static QEMUMachine sx1_machine_v2 = {
+    .name = "sx1",
+    .desc = "Siemens SX1 (OMAP310) V2",
+    .init = sx1_init_v2,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine sx1_machine_v1 = {
+    .name = "sx1-v1",
+    .desc = "Siemens SX1 (OMAP310) V1",
+    .init = sx1_init_v1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void sx1_machine_init(void)
+{
+    qemu_register_machine(&sx1_machine_v2);
+    qemu_register_machine(&sx1_machine_v1);
+}
+
+machine_init(sx1_machine_init);
diff --git a/hw/arm/palm.c b/hw/arm/palm.c
new file mode 100644
index 0000000..91bc74a
--- /dev/null
+++ b/hw/arm/palm.c
@@ -0,0 +1,291 @@
+/*
+ * PalmOne's (TM) PDAs.
+ *
+ * Copyright (C) 2006-2007 Andrzej Zaborowski  <balrog at zabor.org>
+ *
+ * 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 or
+ * (at your option) version 3 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 "audio/audio.h"
+#include "sysemu/sysemu.h"
+#include "ui/console.h"
+#include "hw/omap.h"
+#include "hw/boards.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "hw/loader.h"
+#include "exec/address-spaces.h"
+
+static uint32_t static_readb(void *opaque, hwaddr offset)
+{
+    uint32_t *val = (uint32_t *) opaque;
+    return *val >> ((offset & 3) << 3);
+}
+
+static uint32_t static_readh(void *opaque, hwaddr offset)
+{
+    uint32_t *val = (uint32_t *) opaque;
+    return *val >> ((offset & 1) << 3);
+}
+
+static uint32_t static_readw(void *opaque, hwaddr offset)
+{
+    uint32_t *val = (uint32_t *) opaque;
+    return *val >> ((offset & 0) << 3);
+}
+
+static void static_write(void *opaque, hwaddr offset,
+                uint32_t value)
+{
+#ifdef SPY
+    printf("%s: value %08lx written at " PA_FMT "\n",
+                    __FUNCTION__, value, offset);
+#endif
+}
+
+static const MemoryRegionOps static_ops = {
+    .old_mmio = {
+        .read = { static_readb, static_readh, static_readw, },
+        .write = { static_write, static_write, static_write, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+/* Palm Tunsgten|E support */
+
+/* Shared GPIOs */
+#define PALMTE_USBDETECT_GPIO	0
+#define PALMTE_USB_OR_DC_GPIO	1
+#define PALMTE_TSC_GPIO		4
+#define PALMTE_PINTDAV_GPIO	6
+#define PALMTE_MMC_WP_GPIO	8
+#define PALMTE_MMC_POWER_GPIO	9
+#define PALMTE_HDQ_GPIO		11
+#define PALMTE_HEADPHONES_GPIO	14
+#define PALMTE_SPEAKER_GPIO	15
+/* MPU private GPIOs */
+#define PALMTE_DC_GPIO		2
+#define PALMTE_MMC_SWITCH_GPIO	4
+#define PALMTE_MMC1_GPIO	6
+#define PALMTE_MMC2_GPIO	7
+#define PALMTE_MMC3_GPIO	11
+
+static MouseTransformInfo palmte_pointercal = {
+    .x = 320,
+    .y = 320,
+    .a = { -5909, 8, 22465308, 104, 7644, -1219972, 65536 },
+};
+
+static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
+{
+    uWireSlave *tsc;
+
+    tsc = tsc2102_init(qdev_get_gpio_in(cpu->gpio, PALMTE_PINTDAV_GPIO));
+
+    omap_uwire_attach(cpu->microwire, tsc, 0);
+    omap_mcbsp_i2s_attach(cpu->mcbsp1, tsc210x_codec(tsc));
+
+    tsc210x_set_transform(tsc, &palmte_pointercal);
+}
+
+static struct {
+    int row;
+    int column;
+} palmte_keymap[0x80] = {
+    [0 ... 0x7f] = { -1, -1 },
+    [0x3b] = { 0, 0 },	/* F1	-> Calendar */
+    [0x3c] = { 1, 0 },	/* F2	-> Contacts */
+    [0x3d] = { 2, 0 },	/* F3	-> Tasks List */
+    [0x3e] = { 3, 0 },	/* F4	-> Note Pad */
+    [0x01] = { 4, 0 },	/* Esc	-> Power */
+    [0x4b] = { 0, 1 },	/* 	   Left */
+    [0x50] = { 1, 1 },	/* 	   Down */
+    [0x48] = { 2, 1 },	/*	   Up */
+    [0x4d] = { 3, 1 },	/*	   Right */
+    [0x4c] = { 4, 1 },	/* 	   Centre */
+    [0x39] = { 4, 1 },	/* Spc	-> Centre */
+};
+
+static void palmte_button_event(void *opaque, int keycode)
+{
+    struct omap_mpu_state_s *cpu = (struct omap_mpu_state_s *) opaque;
+
+    if (palmte_keymap[keycode & 0x7f].row != -1)
+        omap_mpuio_key(cpu->mpuio,
+                        palmte_keymap[keycode & 0x7f].row,
+                        palmte_keymap[keycode & 0x7f].column,
+                        !(keycode & 0x80));
+}
+
+static void palmte_onoff_gpios(void *opaque, int line, int level)
+{
+    switch (line) {
+    case 0:
+        printf("%s: current to MMC/SD card %sabled.\n",
+                        __FUNCTION__, level ? "dis" : "en");
+        break;
+    case 1:
+        printf("%s: internal speaker amplifier %s.\n",
+                        __FUNCTION__, level ? "down" : "on");
+        break;
+
+    /* These LCD & Audio output signals have not been identified yet.  */
+    case 2:
+    case 3:
+    case 4:
+        printf("%s: LCD GPIO%i %s.\n",
+                        __FUNCTION__, line - 1, level ? "high" : "low");
+        break;
+    case 5:
+    case 6:
+        printf("%s: Audio GPIO%i %s.\n",
+                        __FUNCTION__, line - 4, level ? "high" : "low");
+        break;
+    }
+}
+
+static void palmte_gpio_setup(struct omap_mpu_state_s *cpu)
+{
+    qemu_irq *misc_gpio;
+
+    omap_mmc_handlers(cpu->mmc,
+                    qdev_get_gpio_in(cpu->gpio, PALMTE_MMC_WP_GPIO),
+                    qemu_irq_invert(omap_mpuio_in_get(cpu->mpuio)
+                            [PALMTE_MMC_SWITCH_GPIO]));
+
+    misc_gpio = qemu_allocate_irqs(palmte_onoff_gpios, cpu, 7);
+    qdev_connect_gpio_out(cpu->gpio, PALMTE_MMC_POWER_GPIO,	misc_gpio[0]);
+    qdev_connect_gpio_out(cpu->gpio, PALMTE_SPEAKER_GPIO,	misc_gpio[1]);
+    qdev_connect_gpio_out(cpu->gpio, 11,			misc_gpio[2]);
+    qdev_connect_gpio_out(cpu->gpio, 12,			misc_gpio[3]);
+    qdev_connect_gpio_out(cpu->gpio, 13,			misc_gpio[4]);
+    omap_mpuio_out_set(cpu->mpuio, 1,				misc_gpio[5]);
+    omap_mpuio_out_set(cpu->mpuio, 3,				misc_gpio[6]);
+
+    /* Reset some inputs to initial state.  */
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USBDETECT_GPIO));
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USB_OR_DC_GPIO));
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, 4));
+    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_HEADPHONES_GPIO));
+    qemu_irq_lower(omap_mpuio_in_get(cpu->mpuio)[PALMTE_DC_GPIO]);
+    qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[6]);
+    qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[7]);
+    qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[11]);
+}
+
+static struct arm_boot_info palmte_binfo = {
+    .loader_start = OMAP_EMIFF_BASE,
+    .ram_size = 0x02000000,
+    .board_id = 0x331,
+};
+
+static void palmte_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    MemoryRegion *address_space_mem = get_system_memory();
+    struct omap_mpu_state_s *mpu;
+    int flash_size = 0x00800000;
+    int sdram_size = palmte_binfo.ram_size;
+    static uint32_t cs0val = 0xffffffff;
+    static uint32_t cs1val = 0x0000e1a0;
+    static uint32_t cs2val = 0x0000e1a0;
+    static uint32_t cs3val = 0xe1a0e1a0;
+    int rom_size, rom_loaded = 0;
+    DisplayState *ds = get_displaystate();
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
+    MemoryRegion *cs = g_new(MemoryRegion, 4);
+
+    mpu = omap310_mpu_init(address_space_mem, sdram_size, cpu_model);
+
+    /* External Flash (EMIFS) */
+    memory_region_init_ram(flash, "palmte.flash", flash_size);
+    vmstate_register_ram_global(flash);
+    memory_region_set_readonly(flash, true);
+    memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE, flash);
+
+    memory_region_init_io(&cs[0], &static_ops, &cs0val, "palmte-cs0",
+                          OMAP_CS0_SIZE - flash_size);
+    memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE + flash_size,
+                                &cs[0]);
+    memory_region_init_io(&cs[1], &static_ops, &cs1val, "palmte-cs1",
+                          OMAP_CS1_SIZE);
+    memory_region_add_subregion(address_space_mem, OMAP_CS1_BASE, &cs[1]);
+    memory_region_init_io(&cs[2], &static_ops, &cs2val, "palmte-cs2",
+                          OMAP_CS2_SIZE);
+    memory_region_add_subregion(address_space_mem, OMAP_CS2_BASE, &cs[2]);
+    memory_region_init_io(&cs[3], &static_ops, &cs3val, "palmte-cs3",
+                          OMAP_CS3_SIZE);
+    memory_region_add_subregion(address_space_mem, OMAP_CS3_BASE, &cs[3]);
+
+    palmte_microwire_setup(mpu);
+
+    qemu_add_kbd_event_handler(palmte_button_event, mpu);
+
+    palmte_gpio_setup(mpu);
+
+    /* Setup initial (reset) machine state */
+    if (nb_option_roms) {
+        rom_size = get_image_size(option_rom[0].name);
+        if (rom_size > flash_size) {
+            fprintf(stderr, "%s: ROM image too big (%x > %x)\n",
+                            __FUNCTION__, rom_size, flash_size);
+            rom_size = 0;
+        }
+        if (rom_size > 0) {
+            rom_size = load_image_targphys(option_rom[0].name, OMAP_CS0_BASE,
+                                           flash_size);
+            rom_loaded = 1;
+        }
+        if (rom_size < 0) {
+            fprintf(stderr, "%s: error loading '%s'\n",
+                            __FUNCTION__, option_rom[0].name);
+        }
+    }
+
+    if (!rom_loaded && !kernel_filename) {
+        fprintf(stderr, "Kernel or ROM image must be specified\n");
+        exit(1);
+    }
+
+    /* Load the kernel.  */
+    if (kernel_filename) {
+        palmte_binfo.kernel_filename = kernel_filename;
+        palmte_binfo.kernel_cmdline = kernel_cmdline;
+        palmte_binfo.initrd_filename = initrd_filename;
+        arm_load_kernel(mpu->cpu, &palmte_binfo);
+    }
+
+    /* FIXME: We shouldn't really be doing this here.  The LCD controller
+       will set the size once configured, so this just sets an initial
+       size until the guest activates the display.  */
+    ds->surface = qemu_resize_displaysurface(ds, 320, 320);
+    dpy_gfx_resize(ds);
+}
+
+static QEMUMachine palmte_machine = {
+    .name = "cheetah",
+    .desc = "Palm Tungsten|E aka. Cheetah PDA (OMAP310)",
+    .init = palmte_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void palmte_machine_init(void)
+{
+    qemu_register_machine(&palmte_machine);
+}
+
+machine_init(palmte_machine_init);
diff --git a/hw/arm/pic_cpu.c b/hw/arm/pic_cpu.c
new file mode 100644
index 0000000..a7ad893
--- /dev/null
+++ b/hw/arm/pic_cpu.c
@@ -0,0 +1,40 @@
+/*
+ * Generic ARM Programmable Interrupt Controller support.
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the LGPL
+ */
+
+#include "hw/hw.h"
+#include "hw/arm-misc.h"
+
+/* Input 0 is IRQ and input 1 is FIQ.  */
+static void arm_pic_cpu_handler(void *opaque, int irq, int level)
+{
+    ARMCPU *cpu = opaque;
+    CPUARMState *env = &cpu->env;
+
+    switch (irq) {
+    case ARM_PIC_CPU_IRQ:
+        if (level)
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        else
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        break;
+    case ARM_PIC_CPU_FIQ:
+        if (level)
+            cpu_interrupt(env, CPU_INTERRUPT_FIQ);
+        else
+            cpu_reset_interrupt(env, CPU_INTERRUPT_FIQ);
+        break;
+    default:
+        hw_error("arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
+    }
+}
+
+qemu_irq *arm_pic_init_cpu(ARMCPU *cpu)
+{
+    return qemu_allocate_irqs(arm_pic_cpu_handler, cpu, 2);
+}
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
new file mode 100644
index 0000000..5fb490c
--- /dev/null
+++ b/hw/arm/realview.c
@@ -0,0 +1,404 @@
+/*
+ * ARM RealView Baseboard System emulation.
+ *
+ * Copyright (c) 2006-2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/primecell.h"
+#include "hw/devices.h"
+#include "hw/pci/pci.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/i2c.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+#define SMP_BOOT_ADDR 0xe0000000
+#define SMP_BOOTREG_ADDR 0x10000030
+
+/* Board init.  */
+
+static struct arm_boot_info realview_binfo = {
+    .smp_loader_start = SMP_BOOT_ADDR,
+    .smp_bootreg_addr = SMP_BOOTREG_ADDR,
+};
+
+/* The following two lists must be consistent.  */
+enum realview_board_type {
+    BOARD_EB,
+    BOARD_EB_MPCORE,
+    BOARD_PB_A8,
+    BOARD_PBX_A9,
+};
+
+static const int realview_board_id[] = {
+    0x33b,
+    0x33b,
+    0x769,
+    0x76d
+};
+
+static void realview_init(QEMUMachineInitArgs *args,
+                          enum realview_board_type board_type)
+{
+    ARMCPU *cpu = NULL;
+    CPUARMState *env;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram_lo = g_new(MemoryRegion, 1);
+    MemoryRegion *ram_hi = g_new(MemoryRegion, 1);
+    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
+    MemoryRegion *ram_hack = g_new(MemoryRegion, 1);
+    DeviceState *dev, *sysctl, *gpio2, *pl041;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[64];
+    qemu_irq mmc_irq[2];
+    PCIBus *pci_bus;
+    NICInfo *nd;
+    i2c_bus *i2c;
+    int n;
+    int done_nic = 0;
+    qemu_irq cpu_irq[4];
+    int is_mpcore = 0;
+    int is_pb = 0;
+    uint32_t proc_id = 0;
+    uint32_t sys_id;
+    ram_addr_t low_ram_size;
+    ram_addr_t ram_size = args->ram_size;
+
+    switch (board_type) {
+    case BOARD_EB:
+        break;
+    case BOARD_EB_MPCORE:
+        is_mpcore = 1;
+        break;
+    case BOARD_PB_A8:
+        is_pb = 1;
+        break;
+    case BOARD_PBX_A9:
+        is_mpcore = 1;
+        is_pb = 1;
+        break;
+    }
+    for (n = 0; n < smp_cpus; n++) {
+        cpu = cpu_arm_init(args->cpu_model);
+        if (!cpu) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(cpu);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+    }
+    env = &cpu->env;
+    if (arm_feature(env, ARM_FEATURE_V7)) {
+        if (is_mpcore) {
+            proc_id = 0x0c000000;
+        } else {
+            proc_id = 0x0e000000;
+        }
+    } else if (arm_feature(env, ARM_FEATURE_V6K)) {
+        proc_id = 0x06000000;
+    } else if (arm_feature(env, ARM_FEATURE_V6)) {
+        proc_id = 0x04000000;
+    } else {
+        proc_id = 0x02000000;
+    }
+
+    if (is_pb && ram_size > 0x20000000) {
+        /* Core tile RAM.  */
+        low_ram_size = ram_size - 0x20000000;
+        ram_size = 0x20000000;
+        memory_region_init_ram(ram_lo, "realview.lowmem", low_ram_size);
+        vmstate_register_ram_global(ram_lo);
+        memory_region_add_subregion(sysmem, 0x20000000, ram_lo);
+    }
+
+    memory_region_init_ram(ram_hi, "realview.highmem", ram_size);
+    vmstate_register_ram_global(ram_hi);
+    low_ram_size = ram_size;
+    if (low_ram_size > 0x10000000)
+      low_ram_size = 0x10000000;
+    /* SDRAM at address zero.  */
+    memory_region_init_alias(ram_alias, "realview.alias",
+                             ram_hi, 0, low_ram_size);
+    memory_region_add_subregion(sysmem, 0, ram_alias);
+    if (is_pb) {
+        /* And again at a high address.  */
+        memory_region_add_subregion(sysmem, 0x70000000, ram_hi);
+    } else {
+        ram_size = low_ram_size;
+    }
+
+    sys_id = is_pb ? 0x01780500 : 0xc1400400;
+    sysctl = qdev_create(NULL, "realview_sysctl");
+    qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
+    qdev_prop_set_uint32(sysctl, "proc_id", proc_id);
+    qdev_init_nofail(sysctl);
+    sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
+
+    if (is_mpcore) {
+        hwaddr periphbase;
+        dev = qdev_create(NULL, is_pb ? "a9mpcore_priv": "realview_mpcore");
+        qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+        qdev_init_nofail(dev);
+        busdev = SYS_BUS_DEVICE(dev);
+        if (is_pb) {
+            periphbase = 0x1f000000;
+        } else {
+            periphbase = 0x10100000;
+        }
+        sysbus_mmio_map(busdev, 0, periphbase);
+        for (n = 0; n < smp_cpus; n++) {
+            sysbus_connect_irq(busdev, n, cpu_irq[n]);
+        }
+        sysbus_create_varargs("l2x0", periphbase + 0x2000, NULL);
+        /* Both A9 and 11MPCore put the GIC CPU i/f at base + 0x100 */
+        realview_binfo.gic_cpu_if_addr = periphbase + 0x100;
+    } else {
+        uint32_t gic_addr = is_pb ? 0x1e000000 : 0x10040000;
+        /* For now just create the nIRQ GIC, and ignore the others.  */
+        dev = sysbus_create_simple("realview_gic", gic_addr, cpu_irq[0]);
+    }
+    for (n = 0; n < 64; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    pl041 = qdev_create(NULL, "pl041");
+    qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
+    qdev_init_nofail(pl041);
+    sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000);
+    sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, pic[19]);
+
+    sysbus_create_simple("pl050_keyboard", 0x10006000, pic[20]);
+    sysbus_create_simple("pl050_mouse", 0x10007000, pic[21]);
+
+    sysbus_create_simple("pl011", 0x10009000, pic[12]);
+    sysbus_create_simple("pl011", 0x1000a000, pic[13]);
+    sysbus_create_simple("pl011", 0x1000b000, pic[14]);
+    sysbus_create_simple("pl011", 0x1000c000, pic[15]);
+
+    /* DMA controller is optional, apparently.  */
+    sysbus_create_simple("pl081", 0x10030000, pic[24]);
+
+    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("pl111", 0x10020000, pic[23]);
+
+    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]);
+
+    if (!is_pb) {
+        dev = qdev_create(NULL, "realview_pci");
+        busdev = SYS_BUS_DEVICE(dev);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(busdev, 0, 0x61000000); /* PCI self-config */
+        sysbus_mmio_map(busdev, 1, 0x62000000); /* PCI config */
+        sysbus_mmio_map(busdev, 2, 0x63000000); /* PCI I/O */
+        sysbus_connect_irq(busdev, 0, pic[48]);
+        sysbus_connect_irq(busdev, 1, pic[49]);
+        sysbus_connect_irq(busdev, 2, pic[50]);
+        sysbus_connect_irq(busdev, 3, pic[51]);
+        pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
+        if (usb_enabled(false)) {
+            pci_create_simple(pci_bus, -1, "pci-ohci");
+        }
+        n = drive_get_max_bus(IF_SCSI);
+        while (n >= 0) {
+            pci_create_simple(pci_bus, -1, "lsi53c895a");
+            n--;
+        }
+    }
+    for(n = 0; n < nb_nics; n++) {
+        nd = &nd_table[n];
+
+        if (!done_nic && (!nd->model ||
+                    strcmp(nd->model, is_pb ? "lan9118" : "smc91c111") == 0)) {
+            if (is_pb) {
+                lan9118_init(nd, 0x4e000000, pic[28]);
+            } else {
+                smc91c111_init(nd, 0x4e000000, pic[28]);
+            }
+            done_nic = 1;
+        } else {
+            pci_nic_init_nofail(nd, "rtl8139", NULL);
+        }
+    }
+
+    dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL);
+    i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
+    i2c_create_slave(i2c, "ds1338", 0x68);
+
+    /* Memory map for RealView Emulation Baseboard:  */
+    /* 0x10000000 System registers.  */
+    /*  0x10001000 System controller.  */
+    /* 0x10002000 Two-Wire Serial Bus.  */
+    /* 0x10003000 Reserved.  */
+    /*  0x10004000 AACI.  */
+    /*  0x10005000 MCI.  */
+    /* 0x10006000 KMI0.  */
+    /* 0x10007000 KMI1.  */
+    /*  0x10008000 Character LCD. (EB) */
+    /* 0x10009000 UART0.  */
+    /* 0x1000a000 UART1.  */
+    /* 0x1000b000 UART2.  */
+    /* 0x1000c000 UART3.  */
+    /*  0x1000d000 SSPI.  */
+    /*  0x1000e000 SCI.  */
+    /* 0x1000f000 Reserved.  */
+    /*  0x10010000 Watchdog.  */
+    /* 0x10011000 Timer 0+1.  */
+    /* 0x10012000 Timer 2+3.  */
+    /*  0x10013000 GPIO 0.  */
+    /*  0x10014000 GPIO 1.  */
+    /*  0x10015000 GPIO 2.  */
+    /*  0x10002000 Two-Wire Serial Bus - DVI. (PB) */
+    /* 0x10017000 RTC.  */
+    /*  0x10018000 DMC.  */
+    /*  0x10019000 PCI controller config.  */
+    /*  0x10020000 CLCD.  */
+    /* 0x10030000 DMA Controller.  */
+    /* 0x10040000 GIC1. (EB) */
+    /*  0x10050000 GIC2. (EB) */
+    /*  0x10060000 GIC3. (EB) */
+    /*  0x10070000 GIC4. (EB) */
+    /*  0x10080000 SMC.  */
+    /* 0x1e000000 GIC1. (PB) */
+    /*  0x1e001000 GIC2. (PB) */
+    /*  0x1e002000 GIC3. (PB) */
+    /*  0x1e003000 GIC4. (PB) */
+    /*  0x40000000 NOR flash.  */
+    /*  0x44000000 DoC flash.  */
+    /*  0x48000000 SRAM.  */
+    /*  0x4c000000 Configuration flash.  */
+    /* 0x4e000000 Ethernet.  */
+    /*  0x4f000000 USB.  */
+    /*  0x50000000 PISMO.  */
+    /*  0x54000000 PISMO.  */
+    /*  0x58000000 PISMO.  */
+    /*  0x5c000000 PISMO.  */
+    /* 0x60000000 PCI.  */
+    /* 0x61000000 PCI Self Config.  */
+    /* 0x62000000 PCI Config.  */
+    /* 0x63000000 PCI IO.  */
+    /* 0x64000000 PCI mem 0.  */
+    /* 0x68000000 PCI mem 1.  */
+    /* 0x6c000000 PCI mem 2.  */
+
+    /* ??? 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.  */
+    memory_region_init_ram(ram_hack, "realview.hack", 0x1000);
+    vmstate_register_ram_global(ram_hack);
+    memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack);
+
+    realview_binfo.ram_size = ram_size;
+    realview_binfo.kernel_filename = args->kernel_filename;
+    realview_binfo.kernel_cmdline = args->kernel_cmdline;
+    realview_binfo.initrd_filename = args->initrd_filename;
+    realview_binfo.nb_cpus = smp_cpus;
+    realview_binfo.board_id = realview_board_id[board_type];
+    realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0);
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &realview_binfo);
+}
+
+static void realview_eb_init(QEMUMachineInitArgs *args)
+{
+    if (!args->cpu_model) {
+        args->cpu_model = "arm926";
+    }
+    realview_init(args, BOARD_EB);
+}
+
+static void realview_eb_mpcore_init(QEMUMachineInitArgs *args)
+{
+    if (!args->cpu_model) {
+        args->cpu_model = "arm11mpcore";
+    }
+    realview_init(args, BOARD_EB_MPCORE);
+}
+
+static void realview_pb_a8_init(QEMUMachineInitArgs *args)
+{
+    if (!args->cpu_model) {
+        args->cpu_model = "cortex-a8";
+    }
+    realview_init(args, BOARD_PB_A8);
+}
+
+static void realview_pbx_a9_init(QEMUMachineInitArgs *args)
+{
+    if (!args->cpu_model) {
+        args->cpu_model = "cortex-a9";
+    }
+    realview_init(args, BOARD_PBX_A9);
+}
+
+static QEMUMachine realview_eb_machine = {
+    .name = "realview-eb",
+    .desc = "ARM RealView Emulation Baseboard (ARM926EJ-S)",
+    .init = realview_eb_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine realview_eb_mpcore_machine = {
+    .name = "realview-eb-mpcore",
+    .desc = "ARM RealView Emulation Baseboard (ARM11MPCore)",
+    .init = realview_eb_mpcore_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine realview_pb_a8_machine = {
+    .name = "realview-pb-a8",
+    .desc = "ARM RealView Platform Baseboard for Cortex-A8",
+    .init = realview_pb_a8_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine realview_pbx_a9_machine = {
+    .name = "realview-pbx-a9",
+    .desc = "ARM RealView Platform Baseboard Explore for Cortex-A9",
+    .init = realview_pbx_a9_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void realview_machine_init(void)
+{
+    qemu_register_machine(&realview_eb_machine);
+    qemu_register_machine(&realview_eb_mpcore_machine);
+    qemu_register_machine(&realview_pb_a8_machine);
+    qemu_register_machine(&realview_pbx_a9_machine);
+}
+
+machine_init(realview_machine_init);
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
new file mode 100644
index 0000000..f5832be
--- /dev/null
+++ b/hw/arm/spitz.c
@@ -0,0 +1,1138 @@
+/*
+ * PXA270-based Clamshell PDA platforms.
+ *
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Written by Andrzej Zaborowski <balrog at zabor.org>
+ *
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/arm-misc.h"
+#include "sysemu/sysemu.h"
+#include "hw/pcmcia.h"
+#include "hw/i2c.h"
+#include "hw/ssi.h"
+#include "hw/flash.h"
+#include "qemu/timer.h"
+#include "hw/devices.h"
+#include "hw/sharpsl.h"
+#include "ui/console.h"
+#include "block/block.h"
+#include "audio/audio.h"
+#include "hw/boards.h"
+#include "sysemu/blockdev.h"
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+
+#undef REG_FMT
+#define REG_FMT			"0x%02lx"
+
+/* Spitz Flash */
+#define FLASH_BASE		0x0c000000
+#define FLASH_ECCLPLB		0x00	/* Line parity 7 - 0 bit */
+#define FLASH_ECCLPUB		0x04	/* Line parity 15 - 8 bit */
+#define FLASH_ECCCP		0x08	/* Column parity 5 - 0 bit */
+#define FLASH_ECCCNTR		0x0c	/* ECC byte counter */
+#define FLASH_ECCCLRR		0x10	/* Clear ECC */
+#define FLASH_FLASHIO		0x14	/* Flash I/O */
+#define FLASH_FLASHCTL		0x18	/* Flash Control */
+
+#define FLASHCTL_CE0		(1 << 0)
+#define FLASHCTL_CLE		(1 << 1)
+#define FLASHCTL_ALE		(1 << 2)
+#define FLASHCTL_WP		(1 << 3)
+#define FLASHCTL_CE1		(1 << 4)
+#define FLASHCTL_RYBY		(1 << 5)
+#define FLASHCTL_NCE		(FLASHCTL_CE0 | FLASHCTL_CE1)
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    DeviceState *nand;
+    uint8_t ctl;
+    uint8_t manf_id;
+    uint8_t chip_id;
+    ECCState ecc;
+} SLNANDState;
+
+static uint64_t sl_read(void *opaque, hwaddr addr, unsigned size)
+{
+    SLNANDState *s = (SLNANDState *) opaque;
+    int ryby;
+
+    switch (addr) {
+#define BSHR(byte, from, to)	((s->ecc.lp[byte] >> (from - to)) & (1 << to))
+    case FLASH_ECCLPLB:
+        return BSHR(0, 4, 0) | BSHR(0, 5, 2) | BSHR(0, 6, 4) | BSHR(0, 7, 6) |
+                BSHR(1, 4, 1) | BSHR(1, 5, 3) | BSHR(1, 6, 5) | BSHR(1, 7, 7);
+
+#define BSHL(byte, from, to)	((s->ecc.lp[byte] << (to - from)) & (1 << to))
+    case FLASH_ECCLPUB:
+        return BSHL(0, 0, 0) | BSHL(0, 1, 2) | BSHL(0, 2, 4) | BSHL(0, 3, 6) |
+                BSHL(1, 0, 1) | BSHL(1, 1, 3) | BSHL(1, 2, 5) | BSHL(1, 3, 7);
+
+    case FLASH_ECCCP:
+        return s->ecc.cp;
+
+    case FLASH_ECCCNTR:
+        return s->ecc.count & 0xff;
+
+    case FLASH_FLASHCTL:
+        nand_getpins(s->nand, &ryby);
+        if (ryby)
+            return s->ctl | FLASHCTL_RYBY;
+        else
+            return s->ctl;
+
+    case FLASH_FLASHIO:
+        if (size == 4) {
+            return ecc_digest(&s->ecc, nand_getio(s->nand)) |
+                (ecc_digest(&s->ecc, nand_getio(s->nand)) << 16);
+        }
+        return ecc_digest(&s->ecc, nand_getio(s->nand));
+
+    default:
+        zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr);
+    }
+    return 0;
+}
+
+static void sl_write(void *opaque, hwaddr addr,
+                     uint64_t value, unsigned size)
+{
+    SLNANDState *s = (SLNANDState *) opaque;
+
+    switch (addr) {
+    case FLASH_ECCCLRR:
+        /* Value is ignored.  */
+        ecc_reset(&s->ecc);
+        break;
+
+    case FLASH_FLASHCTL:
+        s->ctl = value & 0xff & ~FLASHCTL_RYBY;
+        nand_setpins(s->nand,
+                        s->ctl & FLASHCTL_CLE,
+                        s->ctl & FLASHCTL_ALE,
+                        s->ctl & FLASHCTL_NCE,
+                        s->ctl & FLASHCTL_WP,
+                        0);
+        break;
+
+    case FLASH_FLASHIO:
+        nand_setio(s->nand, ecc_digest(&s->ecc, value & 0xff));
+        break;
+
+    default:
+        zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr);
+    }
+}
+
+enum {
+    FLASH_128M,
+    FLASH_1024M,
+};
+
+static const MemoryRegionOps sl_ops = {
+    .read = sl_read,
+    .write = sl_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void sl_flash_register(PXA2xxState *cpu, int size)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "sl-nand");
+
+    qdev_prop_set_uint8(dev, "manf_id", NAND_MFR_SAMSUNG);
+    if (size == FLASH_128M)
+        qdev_prop_set_uint8(dev, "chip_id", 0x73);
+    else if (size == FLASH_1024M)
+        qdev_prop_set_uint8(dev, "chip_id", 0xf1);
+
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, FLASH_BASE);
+}
+
+static int sl_nand_init(SysBusDevice *dev) {
+    SLNANDState *s;
+    DriveInfo *nand;
+
+    s = FROM_SYSBUS(SLNANDState, dev);
+
+    s->ctl = 0;
+    nand = drive_get(IF_MTD, 0, 0);
+    s->nand = nand_init(nand ? nand->bdrv : NULL, s->manf_id, s->chip_id);
+
+    memory_region_init_io(&s->iomem, &sl_ops, s, "sl", 0x40);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    return 0;
+}
+
+/* Spitz Keyboard */
+
+#define SPITZ_KEY_STROBE_NUM	11
+#define SPITZ_KEY_SENSE_NUM	7
+
+static const int spitz_gpio_key_sense[SPITZ_KEY_SENSE_NUM] = {
+    12, 17, 91, 34, 36, 38, 39
+};
+
+static const int spitz_gpio_key_strobe[SPITZ_KEY_STROBE_NUM] = {
+    88, 23, 24, 25, 26, 27, 52, 103, 107, 108, 114
+};
+
+/* Eighth additional row maps the special keys */
+static int spitz_keymap[SPITZ_KEY_SENSE_NUM + 1][SPITZ_KEY_STROBE_NUM] = {
+    { 0x1d, 0x02, 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0e, 0x3f, 0x40 },
+    {  -1 , 0x03, 0x05, 0x13, 0x15, 0x09, 0x17, 0x18, 0x19, 0x41, 0x42 },
+    { 0x0f, 0x10, 0x12, 0x14, 0x22, 0x16, 0x24, 0x25,  -1 ,  -1 ,  -1  },
+    { 0x3c, 0x11, 0x1f, 0x21, 0x2f, 0x23, 0x32, 0x26,  -1 , 0x36,  -1  },
+    { 0x3b, 0x1e, 0x20, 0x2e, 0x30, 0x31, 0x34,  -1 , 0x1c, 0x2a,  -1  },
+    { 0x44, 0x2c, 0x2d, 0x0c, 0x39, 0x33,  -1 , 0x48,  -1 ,  -1 , 0x38 },
+    { 0x37, 0x3d,  -1 , 0x45, 0x57, 0x58, 0x4b, 0x50, 0x4d,  -1 ,  -1  },
+    { 0x52, 0x43, 0x01, 0x47, 0x49,  -1 ,  -1 ,  -1 ,  -1 ,  -1 ,  -1  },
+};
+
+#define SPITZ_GPIO_AK_INT	13	/* Remote control */
+#define SPITZ_GPIO_SYNC		16	/* Sync button */
+#define SPITZ_GPIO_ON_KEY	95	/* Power button */
+#define SPITZ_GPIO_SWA		97	/* Lid */
+#define SPITZ_GPIO_SWB		96	/* Tablet mode */
+
+/* The special buttons are mapped to unused keys */
+static const int spitz_gpiomap[5] = {
+    SPITZ_GPIO_AK_INT, SPITZ_GPIO_SYNC, SPITZ_GPIO_ON_KEY,
+    SPITZ_GPIO_SWA, SPITZ_GPIO_SWB,
+};
+
+typedef struct {
+    SysBusDevice busdev;
+    qemu_irq sense[SPITZ_KEY_SENSE_NUM];
+    qemu_irq gpiomap[5];
+    int keymap[0x80];
+    uint16_t keyrow[SPITZ_KEY_SENSE_NUM];
+    uint16_t strobe_state;
+    uint16_t sense_state;
+
+    uint16_t pre_map[0x100];
+    uint16_t modifiers;
+    uint16_t imodifiers;
+    uint8_t fifo[16];
+    int fifopos, fifolen;
+    QEMUTimer *kbdtimer;
+} SpitzKeyboardState;
+
+static void spitz_keyboard_sense_update(SpitzKeyboardState *s)
+{
+    int i;
+    uint16_t strobe, sense = 0;
+    for (i = 0; i < SPITZ_KEY_SENSE_NUM; i ++) {
+        strobe = s->keyrow[i] & s->strobe_state;
+        if (strobe) {
+            sense |= 1 << i;
+            if (!(s->sense_state & (1 << i)))
+                qemu_irq_raise(s->sense[i]);
+        } else if (s->sense_state & (1 << i))
+            qemu_irq_lower(s->sense[i]);
+    }
+
+    s->sense_state = sense;
+}
+
+static void spitz_keyboard_strobe(void *opaque, int line, int level)
+{
+    SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
+
+    if (level)
+        s->strobe_state |= 1 << line;
+    else
+        s->strobe_state &= ~(1 << line);
+    spitz_keyboard_sense_update(s);
+}
+
+static void spitz_keyboard_keydown(SpitzKeyboardState *s, int keycode)
+{
+    int spitz_keycode = s->keymap[keycode & 0x7f];
+    if (spitz_keycode == -1)
+        return;
+
+    /* Handle the additional keys */
+    if ((spitz_keycode >> 4) == SPITZ_KEY_SENSE_NUM) {
+        qemu_set_irq(s->gpiomap[spitz_keycode & 0xf], (keycode < 0x80));
+        return;
+    }
+
+    if (keycode & 0x80)
+        s->keyrow[spitz_keycode >> 4] &= ~(1 << (spitz_keycode & 0xf));
+    else
+        s->keyrow[spitz_keycode >> 4] |= 1 << (spitz_keycode & 0xf);
+
+    spitz_keyboard_sense_update(s);
+}
+
+#define SHIFT	(1 << 7)
+#define CTRL	(1 << 8)
+#define FN	(1 << 9)
+
+#define QUEUE_KEY(c)	s->fifo[(s->fifopos + s->fifolen ++) & 0xf] = c
+
+static void spitz_keyboard_handler(void *opaque, int keycode)
+{
+    SpitzKeyboardState *s = opaque;
+    uint16_t code;
+    int mapcode;
+    switch (keycode) {
+    case 0x2a:	/* Left Shift */
+        s->modifiers |= 1;
+        break;
+    case 0xaa:
+        s->modifiers &= ~1;
+        break;
+    case 0x36:	/* Right Shift */
+        s->modifiers |= 2;
+        break;
+    case 0xb6:
+        s->modifiers &= ~2;
+        break;
+    case 0x1d:	/* Control */
+        s->modifiers |= 4;
+        break;
+    case 0x9d:
+        s->modifiers &= ~4;
+        break;
+    case 0x38:	/* Alt */
+        s->modifiers |= 8;
+        break;
+    case 0xb8:
+        s->modifiers &= ~8;
+        break;
+    }
+
+    code = s->pre_map[mapcode = ((s->modifiers & 3) ?
+            (keycode | SHIFT) :
+            (keycode & ~SHIFT))];
+
+    if (code != mapcode) {
+#if 0
+        if ((code & SHIFT) && !(s->modifiers & 1))
+            QUEUE_KEY(0x2a | (keycode & 0x80));
+        if ((code & CTRL ) && !(s->modifiers & 4))
+            QUEUE_KEY(0x1d | (keycode & 0x80));
+        if ((code & FN   ) && !(s->modifiers & 8))
+            QUEUE_KEY(0x38 | (keycode & 0x80));
+        if ((code & FN   ) && (s->modifiers & 1))
+            QUEUE_KEY(0x2a | (~keycode & 0x80));
+        if ((code & FN   ) && (s->modifiers & 2))
+            QUEUE_KEY(0x36 | (~keycode & 0x80));
+#else
+        if (keycode & 0x80) {
+            if ((s->imodifiers & 1   ) && !(s->modifiers & 1))
+                QUEUE_KEY(0x2a | 0x80);
+            if ((s->imodifiers & 4   ) && !(s->modifiers & 4))
+                QUEUE_KEY(0x1d | 0x80);
+            if ((s->imodifiers & 8   ) && !(s->modifiers & 8))
+                QUEUE_KEY(0x38 | 0x80);
+            if ((s->imodifiers & 0x10) && (s->modifiers & 1))
+                QUEUE_KEY(0x2a);
+            if ((s->imodifiers & 0x20) && (s->modifiers & 2))
+                QUEUE_KEY(0x36);
+            s->imodifiers = 0;
+        } else {
+            if ((code & SHIFT) && !((s->modifiers | s->imodifiers) & 1)) {
+                QUEUE_KEY(0x2a);
+                s->imodifiers |= 1;
+            }
+            if ((code & CTRL ) && !((s->modifiers | s->imodifiers) & 4)) {
+                QUEUE_KEY(0x1d);
+                s->imodifiers |= 4;
+            }
+            if ((code & FN   ) && !((s->modifiers | s->imodifiers) & 8)) {
+                QUEUE_KEY(0x38);
+                s->imodifiers |= 8;
+            }
+            if ((code & FN   ) && (s->modifiers & 1) &&
+                            !(s->imodifiers & 0x10)) {
+                QUEUE_KEY(0x2a | 0x80);
+                s->imodifiers |= 0x10;
+            }
+            if ((code & FN   ) && (s->modifiers & 2) &&
+                            !(s->imodifiers & 0x20)) {
+                QUEUE_KEY(0x36 | 0x80);
+                s->imodifiers |= 0x20;
+            }
+        }
+#endif
+    }
+
+    QUEUE_KEY((code & 0x7f) | (keycode & 0x80));
+}
+
+static void spitz_keyboard_tick(void *opaque)
+{
+    SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
+
+    if (s->fifolen) {
+        spitz_keyboard_keydown(s, s->fifo[s->fifopos ++]);
+        s->fifolen --;
+        if (s->fifopos >= 16)
+            s->fifopos = 0;
+    }
+
+    qemu_mod_timer(s->kbdtimer, qemu_get_clock_ns(vm_clock) +
+                   get_ticks_per_sec() / 32);
+}
+
+static void spitz_keyboard_pre_map(SpitzKeyboardState *s)
+{
+    int i;
+    for (i = 0; i < 0x100; i ++)
+        s->pre_map[i] = i;
+    s->pre_map[0x02 | SHIFT	] = 0x02 | SHIFT;	/* exclam */
+    s->pre_map[0x28 | SHIFT	] = 0x03 | SHIFT;	/* quotedbl */
+    s->pre_map[0x04 | SHIFT	] = 0x04 | SHIFT;	/* numbersign */
+    s->pre_map[0x05 | SHIFT	] = 0x05 | SHIFT;	/* dollar */
+    s->pre_map[0x06 | SHIFT	] = 0x06 | SHIFT;	/* percent */
+    s->pre_map[0x08 | SHIFT	] = 0x07 | SHIFT;	/* ampersand */
+    s->pre_map[0x28		] = 0x08 | SHIFT;	/* apostrophe */
+    s->pre_map[0x0a | SHIFT	] = 0x09 | SHIFT;	/* parenleft */
+    s->pre_map[0x0b | SHIFT	] = 0x0a | SHIFT;	/* parenright */
+    s->pre_map[0x29 | SHIFT	] = 0x0b | SHIFT;	/* asciitilde */
+    s->pre_map[0x03 | SHIFT	] = 0x0c | SHIFT;	/* at */
+    s->pre_map[0xd3		] = 0x0e | FN;		/* Delete */
+    s->pre_map[0x3a		] = 0x0f | FN;		/* Caps_Lock */
+    s->pre_map[0x07 | SHIFT	] = 0x11 | FN;		/* asciicircum */
+    s->pre_map[0x0d		] = 0x12 | FN;		/* equal */
+    s->pre_map[0x0d | SHIFT	] = 0x13 | FN;		/* plus */
+    s->pre_map[0x1a		] = 0x14 | FN;		/* bracketleft */
+    s->pre_map[0x1b		] = 0x15 | FN;		/* bracketright */
+    s->pre_map[0x1a | SHIFT	] = 0x16 | FN;		/* braceleft */
+    s->pre_map[0x1b | SHIFT	] = 0x17 | FN;		/* braceright */
+    s->pre_map[0x27		] = 0x22 | FN;		/* semicolon */
+    s->pre_map[0x27 | SHIFT	] = 0x23 | FN;		/* colon */
+    s->pre_map[0x09 | SHIFT	] = 0x24 | FN;		/* asterisk */
+    s->pre_map[0x2b		] = 0x25 | FN;		/* backslash */
+    s->pre_map[0x2b | SHIFT	] = 0x26 | FN;		/* bar */
+    s->pre_map[0x0c | SHIFT	] = 0x30 | FN;		/* underscore */
+    s->pre_map[0x33 | SHIFT	] = 0x33 | FN;		/* less */
+    s->pre_map[0x35		] = 0x33 | SHIFT;	/* slash */
+    s->pre_map[0x34 | SHIFT	] = 0x34 | FN;		/* greater */
+    s->pre_map[0x35 | SHIFT	] = 0x34 | SHIFT;	/* question */
+    s->pre_map[0x49		] = 0x48 | FN;		/* Page_Up */
+    s->pre_map[0x51		] = 0x50 | FN;		/* Page_Down */
+
+    s->modifiers = 0;
+    s->imodifiers = 0;
+    s->fifopos = 0;
+    s->fifolen = 0;
+}
+
+#undef SHIFT
+#undef CTRL
+#undef FN
+
+static int spitz_keyboard_post_load(void *opaque, int version_id)
+{
+    SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
+
+    /* Release all pressed keys */
+    memset(s->keyrow, 0, sizeof(s->keyrow));
+    spitz_keyboard_sense_update(s);
+    s->modifiers = 0;
+    s->imodifiers = 0;
+    s->fifopos = 0;
+    s->fifolen = 0;
+
+    return 0;
+}
+
+static void spitz_keyboard_register(PXA2xxState *cpu)
+{
+    int i;
+    DeviceState *dev;
+    SpitzKeyboardState *s;
+
+    dev = sysbus_create_simple("spitz-keyboard", -1, NULL);
+    s = FROM_SYSBUS(SpitzKeyboardState, SYS_BUS_DEVICE(dev));
+
+    for (i = 0; i < SPITZ_KEY_SENSE_NUM; i ++)
+        qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(cpu->gpio, spitz_gpio_key_sense[i]));
+
+    for (i = 0; i < 5; i ++)
+        s->gpiomap[i] = qdev_get_gpio_in(cpu->gpio, spitz_gpiomap[i]);
+
+    if (!graphic_rotate)
+        s->gpiomap[4] = qemu_irq_invert(s->gpiomap[4]);
+
+    for (i = 0; i < 5; i++)
+        qemu_set_irq(s->gpiomap[i], 0);
+
+    for (i = 0; i < SPITZ_KEY_STROBE_NUM; i ++)
+        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_ns(vm_clock));
+
+    qemu_add_kbd_event_handler(spitz_keyboard_handler, s);
+}
+
+static int spitz_keyboard_init(SysBusDevice *dev)
+{
+    SpitzKeyboardState *s;
+    int i, j;
+
+    s = FROM_SYSBUS(SpitzKeyboardState, dev);
+
+    for (i = 0; i < 0x80; i ++)
+        s->keymap[i] = -1;
+    for (i = 0; i < SPITZ_KEY_SENSE_NUM + 1; i ++)
+        for (j = 0; j < SPITZ_KEY_STROBE_NUM; j ++)
+            if (spitz_keymap[i][j] != -1)
+                s->keymap[spitz_keymap[i][j]] = (i << 4) | j;
+
+    spitz_keyboard_pre_map(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);
+
+    return 0;
+}
+
+/* LCD backlight controller */
+
+#define LCDTG_RESCTL	0x00
+#define LCDTG_PHACTRL	0x01
+#define LCDTG_DUTYCTRL	0x02
+#define LCDTG_POWERREG0	0x03
+#define LCDTG_POWERREG1	0x04
+#define LCDTG_GPOR3	0x05
+#define LCDTG_PICTRL	0x06
+#define LCDTG_POLCTRL	0x07
+
+typedef struct {
+    SSISlave ssidev;
+    uint32_t bl_intensity;
+    uint32_t bl_power;
+} SpitzLCDTG;
+
+static void spitz_bl_update(SpitzLCDTG *s)
+{
+    if (s->bl_power && s->bl_intensity)
+        zaurus_printf("LCD Backlight now at %i/63\n", s->bl_intensity);
+    else
+        zaurus_printf("LCD Backlight now off\n");
+}
+
+/* FIXME: Implement GPIO properly and remove this hack.  */
+static SpitzLCDTG *spitz_lcdtg;
+
+static inline void spitz_bl_bit5(void *opaque, int line, int level)
+{
+    SpitzLCDTG *s = spitz_lcdtg;
+    int prev = s->bl_intensity;
+
+    if (level)
+        s->bl_intensity &= ~0x20;
+    else
+        s->bl_intensity |= 0x20;
+
+    if (s->bl_power && prev != s->bl_intensity)
+        spitz_bl_update(s);
+}
+
+static inline void spitz_bl_power(void *opaque, int line, int level)
+{
+    SpitzLCDTG *s = spitz_lcdtg;
+    s->bl_power = !!level;
+    spitz_bl_update(s);
+}
+
+static uint32_t spitz_lcdtg_transfer(SSISlave *dev, uint32_t value)
+{
+    SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev);
+    int addr;
+    addr = value >> 5;
+    value &= 0x1f;
+
+    switch (addr) {
+    case LCDTG_RESCTL:
+        if (value)
+            zaurus_printf("LCD in QVGA mode\n");
+        else
+            zaurus_printf("LCD in VGA mode\n");
+        break;
+
+    case LCDTG_DUTYCTRL:
+        s->bl_intensity &= ~0x1f;
+        s->bl_intensity |= value;
+        if (s->bl_power)
+            spitz_bl_update(s);
+        break;
+
+    case LCDTG_POWERREG0:
+        /* Set common voltage to M62332FP */
+        break;
+    }
+    return 0;
+}
+
+static int spitz_lcdtg_init(SSISlave *dev)
+{
+    SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev);
+
+    spitz_lcdtg = s;
+    s->bl_power = 0;
+    s->bl_intensity = 0x20;
+
+    return 0;
+}
+
+/* SSP devices */
+
+#define CORGI_SSP_PORT		2
+
+#define SPITZ_GPIO_LCDCON_CS	53
+#define SPITZ_GPIO_ADS7846_CS	14
+#define SPITZ_GPIO_MAX1111_CS	20
+#define SPITZ_GPIO_TP_INT	11
+
+static DeviceState *max1111;
+
+/* "Demux" the signal based on current chipselect */
+typedef struct {
+    SSISlave ssidev;
+    SSIBus *bus[3];
+    uint32_t enable[3];
+} CorgiSSPState;
+
+static uint32_t corgi_ssp_transfer(SSISlave *dev, uint32_t value)
+{
+    CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev);
+    int i;
+
+    for (i = 0; i < 3; i++) {
+        if (s->enable[i]) {
+            return ssi_transfer(s->bus[i], value);
+        }
+    }
+    return 0;
+}
+
+static void corgi_ssp_gpio_cs(void *opaque, int line, int level)
+{
+    CorgiSSPState *s = (CorgiSSPState *)opaque;
+    assert(line >= 0 && line < 3);
+    s->enable[line] = !level;
+}
+
+#define MAX1111_BATT_VOLT	1
+#define MAX1111_BATT_TEMP	2
+#define MAX1111_ACIN_VOLT	3
+
+#define SPITZ_BATTERY_TEMP	0xe0	/* About 2.9V */
+#define SPITZ_BATTERY_VOLT	0xd0	/* About 4.0V */
+#define SPITZ_CHARGEON_ACIN	0x80	/* About 5.0V */
+
+static void spitz_adc_temp_on(void *opaque, int line, int level)
+{
+    if (!max1111)
+        return;
+
+    if (level)
+        max111x_set_input(max1111, MAX1111_BATT_TEMP, SPITZ_BATTERY_TEMP);
+    else
+        max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
+}
+
+static int corgi_ssp_init(SSISlave *dev)
+{
+    CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev);
+
+    qdev_init_gpio_in(&dev->qdev, corgi_ssp_gpio_cs, 3);
+    s->bus[0] = ssi_create_bus(&dev->qdev, "ssi0");
+    s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1");
+    s->bus[2] = ssi_create_bus(&dev->qdev, "ssi2");
+
+    return 0;
+}
+
+static void spitz_ssp_attach(PXA2xxState *cpu)
+{
+    DeviceState *mux;
+    DeviceState *dev;
+    void *bus;
+
+    mux = ssi_create_slave(cpu->ssp[CORGI_SSP_PORT - 1], "corgi-ssp");
+
+    bus = qdev_get_child_bus(mux, "ssi0");
+    ssi_create_slave(bus, "spitz-lcdtg");
+
+    bus = qdev_get_child_bus(mux, "ssi1");
+    dev = ssi_create_slave(bus, "ads7846");
+    qdev_connect_gpio_out(dev, 0,
+                          qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_TP_INT));
+
+    bus = qdev_get_child_bus(mux, "ssi2");
+    max1111 = ssi_create_slave(bus, "max1111");
+    max111x_set_input(max1111, MAX1111_BATT_VOLT, SPITZ_BATTERY_VOLT);
+    max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
+    max111x_set_input(max1111, MAX1111_ACIN_VOLT, SPITZ_CHARGEON_ACIN);
+
+    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_LCDCON_CS,
+                        qdev_get_gpio_in(mux, 0));
+    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_ADS7846_CS,
+                        qdev_get_gpio_in(mux, 1));
+    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_MAX1111_CS,
+                        qdev_get_gpio_in(mux, 2));
+}
+
+/* CF Microdrive */
+
+static void spitz_microdrive_attach(PXA2xxState *cpu, int slot)
+{
+    PCMCIACardState *md;
+    DriveInfo *dinfo;
+
+    dinfo = drive_get(IF_IDE, 0, 0);
+    if (!dinfo || dinfo->media_cd)
+        return;
+    md = dscm1xxxx_init(dinfo);
+    pxa2xx_pcmcia_attach(cpu->pcmcia[slot], md);
+}
+
+/* Wm8750 and Max7310 on I2C */
+
+#define AKITA_MAX_ADDR	0x18
+#define SPITZ_WM_ADDRL	0x1b
+#define SPITZ_WM_ADDRH	0x1a
+
+#define SPITZ_GPIO_WM	5
+
+static void spitz_wm8750_addr(void *opaque, int line, int level)
+{
+    I2CSlave *wm = (I2CSlave *) opaque;
+    if (level)
+        i2c_set_slave_address(wm, SPITZ_WM_ADDRH);
+    else
+        i2c_set_slave_address(wm, SPITZ_WM_ADDRL);
+}
+
+static void spitz_i2c_setup(PXA2xxState *cpu)
+{
+    /* Attach the CPU on one end of our I2C bus.  */
+    i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]);
+
+    DeviceState *wm;
+
+    /* Attach a WM8750 to the bus */
+    wm = i2c_create_slave(bus, "wm8750", 0);
+
+    spitz_wm8750_addr(wm, 0, 0);
+    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_WM,
+                    qemu_allocate_irqs(spitz_wm8750_addr, wm, 1)[0]);
+    /* .. and to the sound interface.  */
+    cpu->i2s->opaque = wm;
+    cpu->i2s->codec_out = wm8750_dac_dat;
+    cpu->i2s->codec_in = wm8750_adc_dat;
+    wm8750_data_req_set(wm, cpu->i2s->data_req, cpu->i2s);
+}
+
+static void spitz_akita_i2c_setup(PXA2xxState *cpu)
+{
+    /* Attach a Max7310 to Akita I2C bus.  */
+    i2c_create_slave(pxa2xx_i2c_bus(cpu->i2c[0]), "max7310",
+                     AKITA_MAX_ADDR);
+}
+
+/* Other peripherals */
+
+static void spitz_out_switch(void *opaque, int line, int level)
+{
+    switch (line) {
+    case 0:
+        zaurus_printf("Charging %s.\n", level ? "off" : "on");
+        break;
+    case 1:
+        zaurus_printf("Discharging %s.\n", level ? "on" : "off");
+        break;
+    case 2:
+        zaurus_printf("Green LED %s.\n", level ? "on" : "off");
+        break;
+    case 3:
+        zaurus_printf("Orange LED %s.\n", level ? "on" : "off");
+        break;
+    case 4:
+        spitz_bl_bit5(opaque, line, level);
+        break;
+    case 5:
+        spitz_bl_power(opaque, line, level);
+        break;
+    case 6:
+        spitz_adc_temp_on(opaque, line, level);
+        break;
+    }
+}
+
+#define SPITZ_SCP_LED_GREEN		1
+#define SPITZ_SCP_JK_B			2
+#define SPITZ_SCP_CHRG_ON		3
+#define SPITZ_SCP_MUTE_L		4
+#define SPITZ_SCP_MUTE_R		5
+#define SPITZ_SCP_CF_POWER		6
+#define SPITZ_SCP_LED_ORANGE		7
+#define SPITZ_SCP_JK_A			8
+#define SPITZ_SCP_ADC_TEMP_ON		9
+#define SPITZ_SCP2_IR_ON		1
+#define SPITZ_SCP2_AKIN_PULLUP		2
+#define SPITZ_SCP2_BACKLIGHT_CONT	7
+#define SPITZ_SCP2_BACKLIGHT_ON		8
+#define SPITZ_SCP2_MIC_BIAS		9
+
+static void spitz_scoop_gpio_setup(PXA2xxState *cpu,
+                DeviceState *scp0, DeviceState *scp1)
+{
+    qemu_irq *outsignals = qemu_allocate_irqs(spitz_out_switch, cpu, 8);
+
+    qdev_connect_gpio_out(scp0, SPITZ_SCP_CHRG_ON, outsignals[0]);
+    qdev_connect_gpio_out(scp0, SPITZ_SCP_JK_B, outsignals[1]);
+    qdev_connect_gpio_out(scp0, SPITZ_SCP_LED_GREEN, outsignals[2]);
+    qdev_connect_gpio_out(scp0, SPITZ_SCP_LED_ORANGE, outsignals[3]);
+
+    if (scp1) {
+        qdev_connect_gpio_out(scp1, SPITZ_SCP2_BACKLIGHT_CONT, outsignals[4]);
+        qdev_connect_gpio_out(scp1, SPITZ_SCP2_BACKLIGHT_ON, outsignals[5]);
+    }
+
+    qdev_connect_gpio_out(scp0, SPITZ_SCP_ADC_TEMP_ON, outsignals[6]);
+}
+
+#define SPITZ_GPIO_HSYNC		22
+#define SPITZ_GPIO_SD_DETECT		9
+#define SPITZ_GPIO_SD_WP		81
+#define SPITZ_GPIO_ON_RESET		89
+#define SPITZ_GPIO_BAT_COVER		90
+#define SPITZ_GPIO_CF1_IRQ		105
+#define SPITZ_GPIO_CF1_CD		94
+#define SPITZ_GPIO_CF2_IRQ		106
+#define SPITZ_GPIO_CF2_CD		93
+
+static int spitz_hsync;
+
+static void spitz_lcd_hsync_handler(void *opaque, int line, int level)
+{
+    PXA2xxState *cpu = (PXA2xxState *) opaque;
+    qemu_set_irq(qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_HSYNC), spitz_hsync);
+    spitz_hsync ^= 1;
+}
+
+static void spitz_gpio_setup(PXA2xxState *cpu, int slots)
+{
+    qemu_irq lcd_hsync;
+    /*
+     * Bad hack: We toggle the LCD hsync GPIO on every GPIO status
+     * read to satisfy broken guests that poll-wait for hsync.
+     * Simulating a real hsync event would be less practical and
+     * wouldn't guarantee that a guest ever exits the loop.
+     */
+    spitz_hsync = 0;
+    lcd_hsync = qemu_allocate_irqs(spitz_lcd_hsync_handler, cpu, 1)[0];
+    pxa2xx_gpio_read_notifier(cpu->gpio, lcd_hsync);
+    pxa2xx_lcd_vsync_notifier(cpu->lcd, lcd_hsync);
+
+    /* MMC/SD host */
+    pxa2xx_mmci_handlers(cpu->mmc,
+                    qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_SD_WP),
+                    qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_SD_DETECT));
+
+    /* Battery lock always closed */
+    qemu_irq_raise(qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_BAT_COVER));
+
+    /* Handle reset */
+    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_ON_RESET, cpu->reset);
+
+    /* PCMCIA signals: card's IRQ and Card-Detect */
+    if (slots >= 1)
+        pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
+                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF1_IRQ),
+                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF1_CD));
+    if (slots >= 2)
+        pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
+                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF2_IRQ),
+                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF2_CD));
+}
+
+/* Board init.  */
+enum spitz_model_e { spitz, akita, borzoi, terrier };
+
+#define SPITZ_RAM	0x04000000
+#define SPITZ_ROM	0x00800000
+
+static struct arm_boot_info spitz_binfo = {
+    .loader_start = PXA2XX_SDRAM_BASE,
+    .ram_size = 0x04000000,
+};
+
+static void spitz_common_init(QEMUMachineInitArgs *args,
+                              enum spitz_model_e model, int arm_id)
+{
+    PXA2xxState *mpu;
+    DeviceState *scp0, *scp1 = NULL;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *rom = g_new(MemoryRegion, 1);
+    const char *cpu_model = args->cpu_model;
+
+    if (!cpu_model)
+        cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0";
+
+    /* Setup CPU & memory */
+    mpu = pxa270_init(address_space_mem, spitz_binfo.ram_size, cpu_model);
+
+    sl_flash_register(mpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
+
+    memory_region_init_ram(rom, "spitz.rom", SPITZ_ROM);
+    vmstate_register_ram_global(rom);
+    memory_region_set_readonly(rom, true);
+    memory_region_add_subregion(address_space_mem, 0, rom);
+
+    /* Setup peripherals */
+    spitz_keyboard_register(mpu);
+
+    spitz_ssp_attach(mpu);
+
+    scp0 = sysbus_create_simple("scoop", 0x10800000, NULL);
+    if (model != akita) {
+        scp1 = sysbus_create_simple("scoop", 0x08800040, NULL);
+    }
+
+    spitz_scoop_gpio_setup(mpu, scp0, scp1);
+
+    spitz_gpio_setup(mpu, (model == akita) ? 1 : 2);
+
+    spitz_i2c_setup(mpu);
+
+    if (model == akita)
+        spitz_akita_i2c_setup(mpu);
+
+    if (model == terrier)
+        /* A 6.0 GB microdrive is permanently sitting in CF slot 1.  */
+        spitz_microdrive_attach(mpu, 1);
+    else if (model != akita)
+        /* A 4.0 GB microdrive is permanently sitting in CF slot 0.  */
+        spitz_microdrive_attach(mpu, 0);
+
+    spitz_binfo.kernel_filename = args->kernel_filename;
+    spitz_binfo.kernel_cmdline = args->kernel_cmdline;
+    spitz_binfo.initrd_filename = args->initrd_filename;
+    spitz_binfo.board_id = arm_id;
+    arm_load_kernel(mpu->cpu, &spitz_binfo);
+    sl_bootparam_write(SL_PXA_PARAM_BASE);
+}
+
+static void spitz_init(QEMUMachineInitArgs *args)
+{
+    spitz_common_init(args, spitz, 0x2c9);
+}
+
+static void borzoi_init(QEMUMachineInitArgs *args)
+{
+    spitz_common_init(args, borzoi, 0x33f);
+}
+
+static void akita_init(QEMUMachineInitArgs *args)
+{
+    spitz_common_init(args, akita, 0x2e8);
+}
+
+static void terrier_init(QEMUMachineInitArgs *args)
+{
+    spitz_common_init(args, terrier, 0x33f);
+}
+
+static QEMUMachine akitapda_machine = {
+    .name = "akita",
+    .desc = "Akita PDA (PXA270)",
+    .init = akita_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine spitzpda_machine = {
+    .name = "spitz",
+    .desc = "Spitz PDA (PXA270)",
+    .init = spitz_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine borzoipda_machine = {
+    .name = "borzoi",
+    .desc = "Borzoi PDA (PXA270)",
+    .init = borzoi_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine terrierpda_machine = {
+    .name = "terrier",
+    .desc = "Terrier PDA (PXA270)",
+    .init = terrier_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void spitz_machine_init(void)
+{
+    qemu_register_machine(&akitapda_machine);
+    qemu_register_machine(&spitzpda_machine);
+    qemu_register_machine(&borzoipda_machine);
+    qemu_register_machine(&terrierpda_machine);
+}
+
+machine_init(spitz_machine_init);
+
+static bool is_version_0(void *opaque, int version_id)
+{
+    return version_id == 0;
+}
+
+static VMStateDescription vmstate_sl_nand_info = {
+    .name = "sl-nand",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT8(ctl, SLNANDState),
+        VMSTATE_STRUCT(ecc, SLNANDState, 0, vmstate_ecc_state, ECCState),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static Property sl_nand_properties[] = {
+    DEFINE_PROP_UINT8("manf_id", SLNANDState, manf_id, NAND_MFR_SAMSUNG),
+    DEFINE_PROP_UINT8("chip_id", SLNANDState, chip_id, 0xf1),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void sl_nand_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = sl_nand_init;
+    dc->vmsd = &vmstate_sl_nand_info;
+    dc->props = sl_nand_properties;
+}
+
+static const TypeInfo sl_nand_info = {
+    .name          = "sl-nand",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(SLNANDState),
+    .class_init    = sl_nand_class_init,
+};
+
+static VMStateDescription vmstate_spitz_kbd = {
+    .name = "spitz-keyboard",
+    .version_id = 1,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .post_load = spitz_keyboard_post_load,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT16(sense_state, SpitzKeyboardState),
+        VMSTATE_UINT16(strobe_state, SpitzKeyboardState),
+        VMSTATE_UNUSED_TEST(is_version_0, 5),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static Property spitz_keyboard_properties[] = {
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void spitz_keyboard_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = spitz_keyboard_init;
+    dc->vmsd = &vmstate_spitz_kbd;
+    dc->props = spitz_keyboard_properties;
+}
+
+static const TypeInfo spitz_keyboard_info = {
+    .name          = "spitz-keyboard",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(SpitzKeyboardState),
+    .class_init    = spitz_keyboard_class_init,
+};
+
+static const VMStateDescription vmstate_corgi_ssp_regs = {
+    .name = "corgi-ssp",
+    .version_id = 2,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 2,
+    .fields = (VMStateField []) {
+        VMSTATE_SSI_SLAVE(ssidev, CorgiSSPState),
+        VMSTATE_UINT32_ARRAY(enable, CorgiSSPState, 3),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static void corgi_ssp_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+    k->init = corgi_ssp_init;
+    k->transfer = corgi_ssp_transfer;
+    dc->vmsd = &vmstate_corgi_ssp_regs;
+}
+
+static const TypeInfo corgi_ssp_info = {
+    .name          = "corgi-ssp",
+    .parent        = TYPE_SSI_SLAVE,
+    .instance_size = sizeof(CorgiSSPState),
+    .class_init    = corgi_ssp_class_init,
+};
+
+static const VMStateDescription vmstate_spitz_lcdtg_regs = {
+    .name = "spitz-lcdtg",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_SSI_SLAVE(ssidev, SpitzLCDTG),
+        VMSTATE_UINT32(bl_intensity, SpitzLCDTG),
+        VMSTATE_UINT32(bl_power, SpitzLCDTG),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static void spitz_lcdtg_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+    k->init = spitz_lcdtg_init;
+    k->transfer = spitz_lcdtg_transfer;
+    dc->vmsd = &vmstate_spitz_lcdtg_regs;
+}
+
+static const TypeInfo spitz_lcdtg_info = {
+    .name          = "spitz-lcdtg",
+    .parent        = TYPE_SSI_SLAVE,
+    .instance_size = sizeof(SpitzLCDTG),
+    .class_init    = spitz_lcdtg_class_init,
+};
+
+static void spitz_register_types(void)
+{
+    type_register_static(&corgi_ssp_info);
+    type_register_static(&spitz_lcdtg_info);
+    type_register_static(&spitz_keyboard_info);
+    type_register_static(&sl_nand_info);
+}
+
+type_init(spitz_register_types)
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
new file mode 100644
index 0000000..f4ce794
--- /dev/null
+++ b/hw/arm/stellaris.c
@@ -0,0 +1,1401 @@
+/*
+ * Luminary Micro Stellaris peripherals
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/ssi.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "qemu/timer.h"
+#include "hw/i2c.h"
+#include "net/net.h"
+#include "hw/boards.h"
+#include "exec/address-spaces.h"
+
+#define GPIO_A 0
+#define GPIO_B 1
+#define GPIO_C 2
+#define GPIO_D 3
+#define GPIO_E 4
+#define GPIO_F 5
+#define GPIO_G 6
+
+#define BP_OLED_I2C  0x01
+#define BP_OLED_SSI  0x02
+#define BP_GAMEPAD   0x04
+
+typedef const struct {
+    const char *name;
+    uint32_t did0;
+    uint32_t did1;
+    uint32_t dc0;
+    uint32_t dc1;
+    uint32_t dc2;
+    uint32_t dc3;
+    uint32_t dc4;
+    uint32_t peripherals;
+} stellaris_board_info;
+
+/* General purpose timer module.  */
+
+typedef struct gptm_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t config;
+    uint32_t mode[2];
+    uint32_t control;
+    uint32_t state;
+    uint32_t mask;
+    uint32_t load[2];
+    uint32_t match[2];
+    uint32_t prescale[2];
+    uint32_t match_prescale[2];
+    uint32_t rtc;
+    int64_t tick[2];
+    struct gptm_state *opaque[2];
+    QEMUTimer *timer[2];
+    /* The timers have an alternate output used to trigger the ADC.  */
+    qemu_irq trigger;
+    qemu_irq irq;
+} gptm_state;
+
+static void gptm_update_irq(gptm_state *s)
+{
+    int level;
+    level = (s->state & s->mask) != 0;
+    qemu_set_irq(s->irq, level);
+}
+
+static void gptm_stop(gptm_state *s, int n)
+{
+    qemu_del_timer(s->timer[n]);
+}
+
+static void gptm_reload(gptm_state *s, int n, int reset)
+{
+    int64_t tick;
+    if (reset)
+        tick = qemu_get_clock_ns(vm_clock);
+    else
+        tick = s->tick[n];
+
+    if (s->config == 0) {
+        /* 32-bit CountDown.  */
+        uint32_t count;
+        count = s->load[0] | (s->load[1] << 16);
+        tick += (int64_t)count * system_clock_scale;
+    } else if (s->config == 1) {
+        /* 32-bit RTC.  1Hz tick.  */
+        tick += get_ticks_per_sec();
+    } else if (s->mode[n] == 0xa) {
+        /* PWM mode.  Not implemented.  */
+    } else {
+        hw_error("TODO: 16-bit timer mode 0x%x\n", s->mode[n]);
+    }
+    s->tick[n] = tick;
+    qemu_mod_timer(s->timer[n], tick);
+}
+
+static void gptm_tick(void *opaque)
+{
+    gptm_state **p = (gptm_state **)opaque;
+    gptm_state *s;
+    int n;
+
+    s = *p;
+    n = p - s->opaque;
+    if (s->config == 0) {
+        s->state |= 1;
+        if ((s->control & 0x20)) {
+            /* Output trigger.  */
+	    qemu_irq_pulse(s->trigger);
+        }
+        if (s->mode[0] & 1) {
+            /* One-shot.  */
+            s->control &= ~1;
+        } else {
+            /* Periodic.  */
+            gptm_reload(s, 0, 0);
+        }
+    } else if (s->config == 1) {
+        /* RTC.  */
+        uint32_t match;
+        s->rtc++;
+        match = s->match[0] | (s->match[1] << 16);
+        if (s->rtc > match)
+            s->rtc = 0;
+        if (s->rtc == 0) {
+            s->state |= 8;
+        }
+        gptm_reload(s, 0, 0);
+    } else if (s->mode[n] == 0xa) {
+        /* PWM mode.  Not implemented.  */
+    } else {
+        hw_error("TODO: 16-bit timer mode 0x%x\n", s->mode[n]);
+    }
+    gptm_update_irq(s);
+}
+
+static uint64_t gptm_read(void *opaque, hwaddr offset,
+                          unsigned size)
+{
+    gptm_state *s = (gptm_state *)opaque;
+
+    switch (offset) {
+    case 0x00: /* CFG */
+        return s->config;
+    case 0x04: /* TAMR */
+        return s->mode[0];
+    case 0x08: /* TBMR */
+        return s->mode[1];
+    case 0x0c: /* CTL */
+        return s->control;
+    case 0x18: /* IMR */
+        return s->mask;
+    case 0x1c: /* RIS */
+        return s->state;
+    case 0x20: /* MIS */
+        return s->state & s->mask;
+    case 0x24: /* CR */
+        return 0;
+    case 0x28: /* TAILR */
+        return s->load[0] | ((s->config < 4) ? (s->load[1] << 16) : 0);
+    case 0x2c: /* TBILR */
+        return s->load[1];
+    case 0x30: /* TAMARCHR */
+        return s->match[0] | ((s->config < 4) ? (s->match[1] << 16) : 0);
+    case 0x34: /* TBMATCHR */
+        return s->match[1];
+    case 0x38: /* TAPR */
+        return s->prescale[0];
+    case 0x3c: /* TBPR */
+        return s->prescale[1];
+    case 0x40: /* TAPMR */
+        return s->match_prescale[0];
+    case 0x44: /* TBPMR */
+        return s->match_prescale[1];
+    case 0x48: /* TAR */
+        if (s->control == 1)
+            return s->rtc;
+    case 0x4c: /* TBR */
+        hw_error("TODO: Timer value read\n");
+    default:
+        hw_error("gptm_read: Bad offset 0x%x\n", (int)offset);
+        return 0;
+    }
+}
+
+static void gptm_write(void *opaque, hwaddr offset,
+                       uint64_t value, unsigned size)
+{
+    gptm_state *s = (gptm_state *)opaque;
+    uint32_t oldval;
+
+    /* The timers should be disabled before changing the configuration.
+       We take advantage of this and defer everything until the timer
+       is enabled.  */
+    switch (offset) {
+    case 0x00: /* CFG */
+        s->config = value;
+        break;
+    case 0x04: /* TAMR */
+        s->mode[0] = value;
+        break;
+    case 0x08: /* TBMR */
+        s->mode[1] = value;
+        break;
+    case 0x0c: /* CTL */
+        oldval = s->control;
+        s->control = value;
+        /* TODO: Implement pause.  */
+        if ((oldval ^ value) & 1) {
+            if (value & 1) {
+                gptm_reload(s, 0, 1);
+            } else {
+                gptm_stop(s, 0);
+            }
+        }
+        if (((oldval ^ value) & 0x100) && s->config >= 4) {
+            if (value & 0x100) {
+                gptm_reload(s, 1, 1);
+            } else {
+                gptm_stop(s, 1);
+            }
+        }
+        break;
+    case 0x18: /* IMR */
+        s->mask = value & 0x77;
+        gptm_update_irq(s);
+        break;
+    case 0x24: /* CR */
+        s->state &= ~value;
+        break;
+    case 0x28: /* TAILR */
+        s->load[0] = value & 0xffff;
+        if (s->config < 4) {
+            s->load[1] = value >> 16;
+        }
+        break;
+    case 0x2c: /* TBILR */
+        s->load[1] = value & 0xffff;
+        break;
+    case 0x30: /* TAMARCHR */
+        s->match[0] = value & 0xffff;
+        if (s->config < 4) {
+            s->match[1] = value >> 16;
+        }
+        break;
+    case 0x34: /* TBMATCHR */
+        s->match[1] = value >> 16;
+        break;
+    case 0x38: /* TAPR */
+        s->prescale[0] = value;
+        break;
+    case 0x3c: /* TBPR */
+        s->prescale[1] = value;
+        break;
+    case 0x40: /* TAPMR */
+        s->match_prescale[0] = value;
+        break;
+    case 0x44: /* TBPMR */
+        s->match_prescale[0] = value;
+        break;
+    default:
+        hw_error("gptm_write: Bad offset 0x%x\n", (int)offset);
+    }
+    gptm_update_irq(s);
+}
+
+static const MemoryRegionOps gptm_ops = {
+    .read = gptm_read,
+    .write = gptm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+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_UNUSED(8),
+        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)
+{
+    gptm_state *s = FROM_SYSBUS(gptm_state, dev);
+
+    sysbus_init_irq(dev, &s->irq);
+    qdev_init_gpio_out(&dev->qdev, &s->trigger, 1);
+
+    memory_region_init_io(&s->iomem, &gptm_ops, s,
+                          "gptm", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    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]);
+    vmstate_register(&dev->qdev, -1, &vmstate_stellaris_gptm, s);
+    return 0;
+}
+
+
+/* System controller.  */
+
+typedef struct {
+    MemoryRegion iomem;
+    uint32_t pborctl;
+    uint32_t ldopctl;
+    uint32_t int_status;
+    uint32_t int_mask;
+    uint32_t resc;
+    uint32_t rcc;
+    uint32_t rcc2;
+    uint32_t rcgc[3];
+    uint32_t scgc[3];
+    uint32_t dcgc[3];
+    uint32_t clkvclr;
+    uint32_t ldoarst;
+    uint32_t user0;
+    uint32_t user1;
+    qemu_irq irq;
+    stellaris_board_info *board;
+} ssys_state;
+
+static void ssys_update(ssys_state *s)
+{
+  qemu_set_irq(s->irq, (s->int_status & s->int_mask) != 0);
+}
+
+static uint32_t pllcfg_sandstorm[16] = {
+    0x31c0, /* 1 Mhz */
+    0x1ae0, /* 1.8432 Mhz */
+    0x18c0, /* 2 Mhz */
+    0xd573, /* 2.4576 Mhz */
+    0x37a6, /* 3.57954 Mhz */
+    0x1ae2, /* 3.6864 Mhz */
+    0x0c40, /* 4 Mhz */
+    0x98bc, /* 4.906 Mhz */
+    0x935b, /* 4.9152 Mhz */
+    0x09c0, /* 5 Mhz */
+    0x4dee, /* 5.12 Mhz */
+    0x0c41, /* 6 Mhz */
+    0x75db, /* 6.144 Mhz */
+    0x1ae6, /* 7.3728 Mhz */
+    0x0600, /* 8 Mhz */
+    0x585b /* 8.192 Mhz */
+};
+
+static uint32_t pllcfg_fury[16] = {
+    0x3200, /* 1 Mhz */
+    0x1b20, /* 1.8432 Mhz */
+    0x1900, /* 2 Mhz */
+    0xf42b, /* 2.4576 Mhz */
+    0x37e3, /* 3.57954 Mhz */
+    0x1b21, /* 3.6864 Mhz */
+    0x0c80, /* 4 Mhz */
+    0x98ee, /* 4.906 Mhz */
+    0xd5b4, /* 4.9152 Mhz */
+    0x0a00, /* 5 Mhz */
+    0x4e27, /* 5.12 Mhz */
+    0x1902, /* 6 Mhz */
+    0xec1c, /* 6.144 Mhz */
+    0x1b23, /* 7.3728 Mhz */
+    0x0640, /* 8 Mhz */
+    0xb11c /* 8.192 Mhz */
+};
+
+#define DID0_VER_MASK        0x70000000
+#define DID0_VER_0           0x00000000
+#define DID0_VER_1           0x10000000
+
+#define DID0_CLASS_MASK      0x00FF0000
+#define DID0_CLASS_SANDSTORM 0x00000000
+#define DID0_CLASS_FURY      0x00010000
+
+static int ssys_board_class(const ssys_state *s)
+{
+    uint32_t did0 = s->board->did0;
+    switch (did0 & DID0_VER_MASK) {
+    case DID0_VER_0:
+        return DID0_CLASS_SANDSTORM;
+    case DID0_VER_1:
+        switch (did0 & DID0_CLASS_MASK) {
+        case DID0_CLASS_SANDSTORM:
+        case DID0_CLASS_FURY:
+            return did0 & DID0_CLASS_MASK;
+        }
+        /* for unknown classes, fall through */
+    default:
+        hw_error("ssys_board_class: Unknown class 0x%08x\n", did0);
+    }
+}
+
+static uint64_t ssys_read(void *opaque, hwaddr offset,
+                          unsigned size)
+{
+    ssys_state *s = (ssys_state *)opaque;
+
+    switch (offset) {
+    case 0x000: /* DID0 */
+        return s->board->did0;
+    case 0x004: /* DID1 */
+        return s->board->did1;
+    case 0x008: /* DC0 */
+        return s->board->dc0;
+    case 0x010: /* DC1 */
+        return s->board->dc1;
+    case 0x014: /* DC2 */
+        return s->board->dc2;
+    case 0x018: /* DC3 */
+        return s->board->dc3;
+    case 0x01c: /* DC4 */
+        return s->board->dc4;
+    case 0x030: /* PBORCTL */
+        return s->pborctl;
+    case 0x034: /* LDOPCTL */
+        return s->ldopctl;
+    case 0x040: /* SRCR0 */
+        return 0;
+    case 0x044: /* SRCR1 */
+        return 0;
+    case 0x048: /* SRCR2 */
+        return 0;
+    case 0x050: /* RIS */
+        return s->int_status;
+    case 0x054: /* IMC */
+        return s->int_mask;
+    case 0x058: /* MISC */
+        return s->int_status & s->int_mask;
+    case 0x05c: /* RESC */
+        return s->resc;
+    case 0x060: /* RCC */
+        return s->rcc;
+    case 0x064: /* PLLCFG */
+        {
+            int xtal;
+            xtal = (s->rcc >> 6) & 0xf;
+            switch (ssys_board_class(s)) {
+            case DID0_CLASS_FURY:
+                return pllcfg_fury[xtal];
+            case DID0_CLASS_SANDSTORM:
+                return pllcfg_sandstorm[xtal];
+            default:
+                hw_error("ssys_read: Unhandled class for PLLCFG read.\n");
+                return 0;
+            }
+        }
+    case 0x070: /* RCC2 */
+        return s->rcc2;
+    case 0x100: /* RCGC0 */
+        return s->rcgc[0];
+    case 0x104: /* RCGC1 */
+        return s->rcgc[1];
+    case 0x108: /* RCGC2 */
+        return s->rcgc[2];
+    case 0x110: /* SCGC0 */
+        return s->scgc[0];
+    case 0x114: /* SCGC1 */
+        return s->scgc[1];
+    case 0x118: /* SCGC2 */
+        return s->scgc[2];
+    case 0x120: /* DCGC0 */
+        return s->dcgc[0];
+    case 0x124: /* DCGC1 */
+        return s->dcgc[1];
+    case 0x128: /* DCGC2 */
+        return s->dcgc[2];
+    case 0x150: /* CLKVCLR */
+        return s->clkvclr;
+    case 0x160: /* LDOARST */
+        return s->ldoarst;
+    case 0x1e0: /* USER0 */
+        return s->user0;
+    case 0x1e4: /* USER1 */
+        return s->user1;
+    default:
+        hw_error("ssys_read: Bad offset 0x%x\n", (int)offset);
+        return 0;
+    }
+}
+
+static bool ssys_use_rcc2(ssys_state *s)
+{
+    return (s->rcc2 >> 31) & 0x1;
+}
+
+/*
+ * Caculate the sys. clock period in ms.
+ */
+static void ssys_calculate_system_clock(ssys_state *s)
+{
+    if (ssys_use_rcc2(s)) {
+        system_clock_scale = 5 * (((s->rcc2 >> 23) & 0x3f) + 1);
+    } else {
+        system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
+    }
+}
+
+static void ssys_write(void *opaque, hwaddr offset,
+                       uint64_t value, unsigned size)
+{
+    ssys_state *s = (ssys_state *)opaque;
+
+    switch (offset) {
+    case 0x030: /* PBORCTL */
+        s->pborctl = value & 0xffff;
+        break;
+    case 0x034: /* LDOPCTL */
+        s->ldopctl = value & 0x1f;
+        break;
+    case 0x040: /* SRCR0 */
+    case 0x044: /* SRCR1 */
+    case 0x048: /* SRCR2 */
+        fprintf(stderr, "Peripheral reset not implemented\n");
+        break;
+    case 0x054: /* IMC */
+        s->int_mask = value & 0x7f;
+        break;
+    case 0x058: /* MISC */
+        s->int_status &= ~value;
+        break;
+    case 0x05c: /* RESC */
+        s->resc = value & 0x3f;
+        break;
+    case 0x060: /* RCC */
+        if ((s->rcc & (1 << 13)) != 0 && (value & (1 << 13)) == 0) {
+            /* PLL enable.  */
+            s->int_status |= (1 << 6);
+        }
+        s->rcc = value;
+        ssys_calculate_system_clock(s);
+        break;
+    case 0x070: /* RCC2 */
+        if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) {
+            break;
+        }
+
+        if ((s->rcc2 & (1 << 13)) != 0 && (value & (1 << 13)) == 0) {
+            /* PLL enable.  */
+            s->int_status |= (1 << 6);
+        }
+        s->rcc2 = value;
+        ssys_calculate_system_clock(s);
+        break;
+    case 0x100: /* RCGC0 */
+        s->rcgc[0] = value;
+        break;
+    case 0x104: /* RCGC1 */
+        s->rcgc[1] = value;
+        break;
+    case 0x108: /* RCGC2 */
+        s->rcgc[2] = value;
+        break;
+    case 0x110: /* SCGC0 */
+        s->scgc[0] = value;
+        break;
+    case 0x114: /* SCGC1 */
+        s->scgc[1] = value;
+        break;
+    case 0x118: /* SCGC2 */
+        s->scgc[2] = value;
+        break;
+    case 0x120: /* DCGC0 */
+        s->dcgc[0] = value;
+        break;
+    case 0x124: /* DCGC1 */
+        s->dcgc[1] = value;
+        break;
+    case 0x128: /* DCGC2 */
+        s->dcgc[2] = value;
+        break;
+    case 0x150: /* CLKVCLR */
+        s->clkvclr = value;
+        break;
+    case 0x160: /* LDOARST */
+        s->ldoarst = value;
+        break;
+    default:
+        hw_error("ssys_write: Bad offset 0x%x\n", (int)offset);
+    }
+    ssys_update(s);
+}
+
+static const MemoryRegionOps ssys_ops = {
+    .read = ssys_read,
+    .write = ssys_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void ssys_reset(void *opaque)
+{
+    ssys_state *s = (ssys_state *)opaque;
+
+    s->pborctl = 0x7ffd;
+    s->rcc = 0x078e3ac0;
+
+    if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) {
+        s->rcc2 = 0;
+    } else {
+        s->rcc2 = 0x07802810;
+    }
+    s->rcgc[0] = 1;
+    s->scgc[0] = 1;
+    s->dcgc[0] = 1;
+    ssys_calculate_system_clock(s);
+}
+
+static int stellaris_sys_post_load(void *opaque, int version_id)
+{
+    ssys_state *s = opaque;
+
+    ssys_calculate_system_clock(s);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_stellaris_sys = {
+    .name = "stellaris_sys",
+    .version_id = 2,
+    .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_V(rcc2, ssys_state, 2),
+        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)
+{
+    ssys_state *s;
+
+    s = (ssys_state *)g_malloc0(sizeof(ssys_state));
+    s->irq = irq;
+    s->board = board;
+    /* Most devices come preprogrammed with a MAC address in the user data. */
+    s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16);
+    s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16);
+
+    memory_region_init_io(&s->iomem, &ssys_ops, s, "ssys", 0x00001000);
+    memory_region_add_subregion(get_system_memory(), base, &s->iomem);
+    ssys_reset(s);
+    vmstate_register(NULL, -1, &vmstate_stellaris_sys, s);
+    return 0;
+}
+
+
+/* I2C controller.  */
+
+typedef struct {
+    SysBusDevice busdev;
+    i2c_bus *bus;
+    qemu_irq irq;
+    MemoryRegion iomem;
+    uint32_t msa;
+    uint32_t mcs;
+    uint32_t mdr;
+    uint32_t mtpr;
+    uint32_t mimr;
+    uint32_t mris;
+    uint32_t mcr;
+} stellaris_i2c_state;
+
+#define STELLARIS_I2C_MCS_BUSY    0x01
+#define STELLARIS_I2C_MCS_ERROR   0x02
+#define STELLARIS_I2C_MCS_ADRACK  0x04
+#define STELLARIS_I2C_MCS_DATACK  0x08
+#define STELLARIS_I2C_MCS_ARBLST  0x10
+#define STELLARIS_I2C_MCS_IDLE    0x20
+#define STELLARIS_I2C_MCS_BUSBSY  0x40
+
+static uint64_t stellaris_i2c_read(void *opaque, hwaddr offset,
+                                   unsigned size)
+{
+    stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
+
+    switch (offset) {
+    case 0x00: /* MSA */
+        return s->msa;
+    case 0x04: /* MCS */
+        /* We don't emulate timing, so the controller is never busy.  */
+        return s->mcs | STELLARIS_I2C_MCS_IDLE;
+    case 0x08: /* MDR */
+        return s->mdr;
+    case 0x0c: /* MTPR */
+        return s->mtpr;
+    case 0x10: /* MIMR */
+        return s->mimr;
+    case 0x14: /* MRIS */
+        return s->mris;
+    case 0x18: /* MMIS */
+        return s->mris & s->mimr;
+    case 0x20: /* MCR */
+        return s->mcr;
+    default:
+        hw_error("strllaris_i2c_read: Bad offset 0x%x\n", (int)offset);
+        return 0;
+    }
+}
+
+static void stellaris_i2c_update(stellaris_i2c_state *s)
+{
+    int level;
+
+    level = (s->mris & s->mimr) != 0;
+    qemu_set_irq(s->irq, level);
+}
+
+static void stellaris_i2c_write(void *opaque, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+    stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
+
+    switch (offset) {
+    case 0x00: /* MSA */
+        s->msa = value & 0xff;
+        break;
+    case 0x04: /* MCS */
+        if ((s->mcr & 0x10) == 0) {
+            /* Disabled.  Do nothing.  */
+            break;
+        }
+        /* Grab the bus if this is starting a transfer.  */
+        if ((value & 2) && (s->mcs & STELLARIS_I2C_MCS_BUSBSY) == 0) {
+            if (i2c_start_transfer(s->bus, s->msa >> 1, s->msa & 1)) {
+                s->mcs |= STELLARIS_I2C_MCS_ARBLST;
+            } else {
+                s->mcs &= ~STELLARIS_I2C_MCS_ARBLST;
+                s->mcs |= STELLARIS_I2C_MCS_BUSBSY;
+            }
+        }
+        /* If we don't have the bus then indicate an error.  */
+        if (!i2c_bus_busy(s->bus)
+                || (s->mcs & STELLARIS_I2C_MCS_BUSBSY) == 0) {
+            s->mcs |= STELLARIS_I2C_MCS_ERROR;
+            break;
+        }
+        s->mcs &= ~STELLARIS_I2C_MCS_ERROR;
+        if (value & 1) {
+            /* Transfer a byte.  */
+            /* TODO: Handle errors.  */
+            if (s->msa & 1) {
+                /* Recv */
+                s->mdr = i2c_recv(s->bus) & 0xff;
+            } else {
+                /* Send */
+                i2c_send(s->bus, s->mdr);
+            }
+            /* Raise an interrupt.  */
+            s->mris |= 1;
+        }
+        if (value & 4) {
+            /* Finish transfer.  */
+            i2c_end_transfer(s->bus);
+            s->mcs &= ~STELLARIS_I2C_MCS_BUSBSY;
+        }
+        break;
+    case 0x08: /* MDR */
+        s->mdr = value & 0xff;
+        break;
+    case 0x0c: /* MTPR */
+        s->mtpr = value & 0xff;
+        break;
+    case 0x10: /* MIMR */
+        s->mimr = 1;
+        break;
+    case 0x1c: /* MICR */
+        s->mris &= ~value;
+        break;
+    case 0x20: /* MCR */
+        if (value & 1)
+            hw_error(
+                      "stellaris_i2c_write: Loopback not implemented\n");
+        if (value & 0x20)
+            hw_error(
+                      "stellaris_i2c_write: Slave mode not implemented\n");
+        s->mcr = value & 0x31;
+        break;
+    default:
+        hw_error("stellaris_i2c_write: Bad offset 0x%x\n",
+                  (int)offset);
+    }
+    stellaris_i2c_update(s);
+}
+
+static void stellaris_i2c_reset(stellaris_i2c_state *s)
+{
+    if (s->mcs & STELLARIS_I2C_MCS_BUSBSY)
+        i2c_end_transfer(s->bus);
+
+    s->msa = 0;
+    s->mcs = 0;
+    s->mdr = 0;
+    s->mtpr = 1;
+    s->mimr = 0;
+    s->mris = 0;
+    s->mcr = 0;
+    stellaris_i2c_update(s);
+}
+
+static const MemoryRegionOps stellaris_i2c_ops = {
+    .read = stellaris_i2c_read,
+    .write = stellaris_i2c_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+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)
+{
+    stellaris_i2c_state *s = FROM_SYSBUS(stellaris_i2c_state, dev);
+    i2c_bus *bus;
+
+    sysbus_init_irq(dev, &s->irq);
+    bus = i2c_init_bus(&dev->qdev, "i2c");
+    s->bus = bus;
+
+    memory_region_init_io(&s->iomem, &stellaris_i2c_ops, s,
+                          "i2c", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    /* ??? For now we only implement the master interface.  */
+    stellaris_i2c_reset(s);
+    vmstate_register(&dev->qdev, -1, &vmstate_stellaris_i2c, s);
+    return 0;
+}
+
+/* Analogue to Digital Converter.  This is only partially implemented,
+   enough for applications that use a combined ADC and timer tick.  */
+
+#define STELLARIS_ADC_EM_CONTROLLER 0
+#define STELLARIS_ADC_EM_COMP       1
+#define STELLARIS_ADC_EM_EXTERNAL   4
+#define STELLARIS_ADC_EM_TIMER      5
+#define STELLARIS_ADC_EM_PWM0       6
+#define STELLARIS_ADC_EM_PWM1       7
+#define STELLARIS_ADC_EM_PWM2       8
+
+#define STELLARIS_ADC_FIFO_EMPTY    0x0100
+#define STELLARIS_ADC_FIFO_FULL     0x1000
+
+typedef struct
+{
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t actss;
+    uint32_t ris;
+    uint32_t im;
+    uint32_t emux;
+    uint32_t ostat;
+    uint32_t ustat;
+    uint32_t sspri;
+    uint32_t sac;
+    struct {
+        uint32_t state;
+        uint32_t data[16];
+    } fifo[4];
+    uint32_t ssmux[4];
+    uint32_t ssctl[4];
+    uint32_t noise;
+    qemu_irq irq[4];
+} stellaris_adc_state;
+
+static uint32_t stellaris_adc_fifo_read(stellaris_adc_state *s, int n)
+{
+    int tail;
+
+    tail = s->fifo[n].state & 0xf;
+    if (s->fifo[n].state & STELLARIS_ADC_FIFO_EMPTY) {
+        s->ustat |= 1 << n;
+    } else {
+        s->fifo[n].state = (s->fifo[n].state & ~0xf) | ((tail + 1) & 0xf);
+        s->fifo[n].state &= ~STELLARIS_ADC_FIFO_FULL;
+        if (tail + 1 == ((s->fifo[n].state >> 4) & 0xf))
+            s->fifo[n].state |= STELLARIS_ADC_FIFO_EMPTY;
+    }
+    return s->fifo[n].data[tail];
+}
+
+static void stellaris_adc_fifo_write(stellaris_adc_state *s, int n,
+                                     uint32_t value)
+{
+    int head;
+
+    /* TODO: Real hardware has limited size FIFOs.  We have a full 16 entry 
+       FIFO fir each sequencer.  */
+    head = (s->fifo[n].state >> 4) & 0xf;
+    if (s->fifo[n].state & STELLARIS_ADC_FIFO_FULL) {
+        s->ostat |= 1 << n;
+        return;
+    }
+    s->fifo[n].data[head] = value;
+    head = (head + 1) & 0xf;
+    s->fifo[n].state &= ~STELLARIS_ADC_FIFO_EMPTY;
+    s->fifo[n].state = (s->fifo[n].state & ~0xf0) | (head << 4);
+    if ((s->fifo[n].state & 0xf) == head)
+        s->fifo[n].state |= STELLARIS_ADC_FIFO_FULL;
+}
+
+static void stellaris_adc_update(stellaris_adc_state *s)
+{
+    int level;
+    int n;
+
+    for (n = 0; n < 4; n++) {
+        level = (s->ris & s->im & (1 << n)) != 0;
+        qemu_set_irq(s->irq[n], level);
+    }
+}
+
+static void stellaris_adc_trigger(void *opaque, int irq, int level)
+{
+    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
+    int n;
+
+    for (n = 0; n < 4; n++) {
+        if ((s->actss & (1 << n)) == 0) {
+            continue;
+        }
+
+        if (((s->emux >> (n * 4)) & 0xff) != 5) {
+            continue;
+        }
+
+        /* Some applications use the ADC as a random number source, so introduce
+           some variation into the signal.  */
+        s->noise = s->noise * 314159 + 1;
+        /* ??? actual inputs not implemented.  Return an arbitrary value.  */
+        stellaris_adc_fifo_write(s, n, 0x200 + ((s->noise >> 16) & 7));
+        s->ris |= (1 << n);
+        stellaris_adc_update(s);
+    }
+}
+
+static void stellaris_adc_reset(stellaris_adc_state *s)
+{
+    int n;
+
+    for (n = 0; n < 4; n++) {
+        s->ssmux[n] = 0;
+        s->ssctl[n] = 0;
+        s->fifo[n].state = STELLARIS_ADC_FIFO_EMPTY;
+    }
+}
+
+static uint64_t stellaris_adc_read(void *opaque, hwaddr offset,
+                                   unsigned size)
+{
+    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
+
+    /* TODO: Implement this.  */
+    if (offset >= 0x40 && offset < 0xc0) {
+        int n;
+        n = (offset - 0x40) >> 5;
+        switch (offset & 0x1f) {
+        case 0x00: /* SSMUX */
+            return s->ssmux[n];
+        case 0x04: /* SSCTL */
+            return s->ssctl[n];
+        case 0x08: /* SSFIFO */
+            return stellaris_adc_fifo_read(s, n);
+        case 0x0c: /* SSFSTAT */
+            return s->fifo[n].state;
+        default:
+            break;
+        }
+    }
+    switch (offset) {
+    case 0x00: /* ACTSS */
+        return s->actss;
+    case 0x04: /* RIS */
+        return s->ris;
+    case 0x08: /* IM */
+        return s->im;
+    case 0x0c: /* ISC */
+        return s->ris & s->im;
+    case 0x10: /* OSTAT */
+        return s->ostat;
+    case 0x14: /* EMUX */
+        return s->emux;
+    case 0x18: /* USTAT */
+        return s->ustat;
+    case 0x20: /* SSPRI */
+        return s->sspri;
+    case 0x30: /* SAC */
+        return s->sac;
+    default:
+        hw_error("strllaris_adc_read: Bad offset 0x%x\n",
+                  (int)offset);
+        return 0;
+    }
+}
+
+static void stellaris_adc_write(void *opaque, hwaddr offset,
+                                uint64_t value, unsigned size)
+{
+    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
+
+    /* TODO: Implement this.  */
+    if (offset >= 0x40 && offset < 0xc0) {
+        int n;
+        n = (offset - 0x40) >> 5;
+        switch (offset & 0x1f) {
+        case 0x00: /* SSMUX */
+            s->ssmux[n] = value & 0x33333333;
+            return;
+        case 0x04: /* SSCTL */
+            if (value != 6) {
+                hw_error("ADC: Unimplemented sequence %" PRIx64 "\n",
+                          value);
+            }
+            s->ssctl[n] = value;
+            return;
+        default:
+            break;
+        }
+    }
+    switch (offset) {
+    case 0x00: /* ACTSS */
+        s->actss = value & 0xf;
+        break;
+    case 0x08: /* IM */
+        s->im = value;
+        break;
+    case 0x0c: /* ISC */
+        s->ris &= ~value;
+        break;
+    case 0x10: /* OSTAT */
+        s->ostat &= ~value;
+        break;
+    case 0x14: /* EMUX */
+        s->emux = value;
+        break;
+    case 0x18: /* USTAT */
+        s->ustat &= ~value;
+        break;
+    case 0x20: /* SSPRI */
+        s->sspri = value;
+        break;
+    case 0x28: /* PSSI */
+        hw_error("Not implemented:  ADC sample initiate\n");
+        break;
+    case 0x30: /* SAC */
+        s->sac = value;
+        break;
+    default:
+        hw_error("stellaris_adc_write: Bad offset 0x%x\n", (int)offset);
+    }
+    stellaris_adc_update(s);
+}
+
+static const MemoryRegionOps stellaris_adc_ops = {
+    .read = stellaris_adc_read,
+    .write = stellaris_adc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+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()
+    }
+};
+
+static int stellaris_adc_init(SysBusDevice *dev)
+{
+    stellaris_adc_state *s = FROM_SYSBUS(stellaris_adc_state, dev);
+    int n;
+
+    for (n = 0; n < 4; n++) {
+        sysbus_init_irq(dev, &s->irq[n]);
+    }
+
+    memory_region_init_io(&s->iomem, &stellaris_adc_ops, s,
+                          "adc", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    stellaris_adc_reset(s);
+    qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1);
+    vmstate_register(&dev->qdev, -1, &vmstate_stellaris_adc, s);
+    return 0;
+}
+
+/* Board init.  */
+static stellaris_board_info stellaris_boards[] = {
+  { "LM3S811EVB",
+    0,
+    0x0032000e,
+    0x001f001f, /* dc0 */
+    0x001132bf,
+    0x01071013,
+    0x3f0f01ff,
+    0x0000001f,
+    BP_OLED_I2C
+  },
+  { "LM3S6965EVB",
+    0x10010002,
+    0x1073402e,
+    0x00ff007f, /* dc0 */
+    0x001133ff,
+    0x030f5317,
+    0x0f0f87ff,
+    0x5000007f,
+    BP_OLED_SSI | BP_GAMEPAD
+  }
+};
+
+static void stellaris_init(const char *kernel_filename, const char *cpu_model,
+                           stellaris_board_info *board)
+{
+    static const int uart_irq[] = {5, 6, 33, 34};
+    static const int timer_irq[] = {19, 21, 23, 35};
+    static const uint32_t gpio_addr[7] =
+      { 0x40004000, 0x40005000, 0x40006000, 0x40007000,
+        0x40024000, 0x40025000, 0x40026000};
+    static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31};
+
+    MemoryRegion *address_space_mem = get_system_memory();
+    qemu_irq *pic;
+    DeviceState *gpio_dev[7];
+    qemu_irq gpio_in[7][8];
+    qemu_irq gpio_out[7][8];
+    qemu_irq adc;
+    int sram_size;
+    int flash_size;
+    i2c_bus *i2c;
+    DeviceState *dev;
+    int i;
+    int j;
+
+    flash_size = ((board->dc0 & 0xffff) + 1) << 1;
+    sram_size = (board->dc0 >> 18) + 1;
+    pic = armv7m_init(address_space_mem,
+                      flash_size, sram_size, kernel_filename, cpu_model);
+
+    if (board->dc1 & (1 << 16)) {
+        dev = sysbus_create_varargs("stellaris-adc", 0x40038000,
+                                    pic[14], pic[15], pic[16], pic[17], NULL);
+        adc = qdev_get_gpio_in(dev, 0);
+    } else {
+        adc = NULL;
+    }
+    for (i = 0; i < 4; i++) {
+        if (board->dc2 & (0x10000 << i)) {
+            dev = sysbus_create_simple("stellaris-gptm",
+                                       0x40030000 + i * 0x1000,
+                                       pic[timer_irq[i]]);
+            /* TODO: This is incorrect, but we get away with it because
+               the ADC output is only ever pulsed.  */
+            qdev_connect_gpio_out(dev, 0, adc);
+        }
+    }
+
+    stellaris_sys_init(0x400fe000, pic[28], board, nd_table[0].macaddr.a);
+
+    for (i = 0; i < 7; i++) {
+        if (board->dc4 & (1 << 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);
+                gpio_out[i][j] = NULL;
+            }
+        }
+    }
+
+    if (board->dc2 & (1 << 12)) {
+        dev = sysbus_create_simple("stellaris-i2c", 0x40020000, pic[8]);
+        i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
+        if (board->peripherals & BP_OLED_I2C) {
+            i2c_create_slave(i2c, "ssd0303", 0x3d);
+        }
+    }
+
+    for (i = 0; i < 4; i++) {
+        if (board->dc2 & (1 << i)) {
+            sysbus_create_simple("pl011_luminary", 0x4000c000 + i * 0x1000,
+                                 pic[uart_irq[i]]);
+        }
+    }
+    if (board->dc2 & (1 << 4)) {
+        dev = sysbus_create_simple("pl022", 0x40008000, pic[7]);
+        if (board->peripherals & BP_OLED_SSI) {
+            void *bus;
+            DeviceState *sddev;
+            DeviceState *ssddev;
+
+            /* Some boards have both an OLED controller and SD card connected to
+             * the same SSI port, with the SD card chip select connected to a
+             * GPIO pin.  Technically the OLED chip select is connected to the
+             * SSI Fss pin.  We do not bother emulating that as both devices
+             * should never be selected simultaneously, and our OLED controller
+             * ignores stray 0xff commands that occur when deselecting the SD
+             * card.
+             */
+            bus = qdev_get_child_bus(dev, "ssi");
+
+            sddev = ssi_create_slave(bus, "ssi-sd");
+            ssddev = ssi_create_slave(bus, "ssd0323");
+            gpio_out[GPIO_D][0] = qemu_irq_split(qdev_get_gpio_in(sddev, 0),
+                                                 qdev_get_gpio_in(ssddev, 0));
+            gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 1);
+
+            /* Make sure the select pin is high.  */
+            qemu_irq_raise(gpio_out[GPIO_D][0]);
+        }
+    }
+    if (board->dc4 & (1 << 28)) {
+        DeviceState *enet;
+
+        qemu_check_nic_model(&nd_table[0], "stellaris");
+
+        enet = qdev_create(NULL, "stellaris_enet");
+        qdev_set_nic_properties(enet, &nd_table[0]);
+        qdev_init_nofail(enet);
+        sysbus_mmio_map(SYS_BUS_DEVICE(enet), 0, 0x40048000);
+        sysbus_connect_irq(SYS_BUS_DEVICE(enet), 0, pic[42]);
+    }
+    if (board->peripherals & BP_GAMEPAD) {
+        qemu_irq gpad_irq[5];
+        static const int gpad_keycode[5] = { 0xc8, 0xd0, 0xcb, 0xcd, 0x1d };
+
+        gpad_irq[0] = qemu_irq_invert(gpio_in[GPIO_E][0]); /* up */
+        gpad_irq[1] = qemu_irq_invert(gpio_in[GPIO_E][1]); /* down */
+        gpad_irq[2] = qemu_irq_invert(gpio_in[GPIO_E][2]); /* left */
+        gpad_irq[3] = qemu_irq_invert(gpio_in[GPIO_E][3]); /* right */
+        gpad_irq[4] = qemu_irq_invert(gpio_in[GPIO_F][1]); /* select */
+
+        stellaris_gamepad_init(5, gpad_irq, gpad_keycode);
+    }
+    for (i = 0; i < 7; i++) {
+        if (board->dc4 & (1 << i)) {
+            for (j = 0; j < 8; j++) {
+                if (gpio_out[i][j]) {
+                    qdev_connect_gpio_out(gpio_dev[i], j, gpio_out[i][j]);
+                }
+            }
+        }
+    }
+}
+
+/* FIXME: Figure out how to generate these from stellaris_boards.  */
+static void lm3s811evb_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    stellaris_init(kernel_filename, cpu_model, &stellaris_boards[0]);
+}
+
+static void lm3s6965evb_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    stellaris_init(kernel_filename, cpu_model, &stellaris_boards[1]);
+}
+
+static QEMUMachine lm3s811evb_machine = {
+    .name = "lm3s811evb",
+    .desc = "Stellaris LM3S811EVB",
+    .init = lm3s811evb_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine lm3s6965evb_machine = {
+    .name = "lm3s6965evb",
+    .desc = "Stellaris LM3S6965EVB",
+    .init = lm3s6965evb_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void stellaris_machine_init(void)
+{
+    qemu_register_machine(&lm3s811evb_machine);
+    qemu_register_machine(&lm3s6965evb_machine);
+}
+
+machine_init(stellaris_machine_init);
+
+static void stellaris_i2c_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = stellaris_i2c_init;
+}
+
+static const TypeInfo stellaris_i2c_info = {
+    .name          = "stellaris-i2c",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(stellaris_i2c_state),
+    .class_init    = stellaris_i2c_class_init,
+};
+
+static void stellaris_gptm_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = stellaris_gptm_init;
+}
+
+static const TypeInfo stellaris_gptm_info = {
+    .name          = "stellaris-gptm",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(gptm_state),
+    .class_init    = stellaris_gptm_class_init,
+};
+
+static void stellaris_adc_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = stellaris_adc_init;
+}
+
+static const TypeInfo stellaris_adc_info = {
+    .name          = "stellaris-adc",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(stellaris_adc_state),
+    .class_init    = stellaris_adc_class_init,
+};
+
+static void stellaris_register_types(void)
+{
+    type_register_static(&stellaris_i2c_info);
+    type_register_static(&stellaris_gptm_info);
+    type_register_static(&stellaris_adc_info);
+}
+
+type_init(stellaris_register_types)
diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
new file mode 100644
index 0000000..747888c
--- /dev/null
+++ b/hw/arm/tosa.c
@@ -0,0 +1,302 @@
+/* vim:set shiftwidth=4 ts=4 et: */
+/*
+ * PXA255 Sharp Zaurus SL-6000 PDA platform
+ *
+ * Copyright (c) 2008 Dmitry Baryshkov
+ *
+ * Code based on spitz platform by Andrzej Zaborowski <balrog at zabor.org>
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "hw/sharpsl.h"
+#include "hw/pcmcia.h"
+#include "block/block.h"
+#include "hw/boards.h"
+#include "hw/i2c.h"
+#include "hw/ssi.h"
+#include "sysemu/blockdev.h"
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+
+#define TOSA_RAM    0x04000000
+#define TOSA_ROM	0x00800000
+
+#define TOSA_GPIO_USB_IN		(5)
+#define TOSA_GPIO_nSD_DETECT	(9)
+#define TOSA_GPIO_ON_RESET		(19)
+#define TOSA_GPIO_CF_IRQ		(21)	/* CF slot0 Ready */
+#define TOSA_GPIO_CF_CD			(13)
+#define TOSA_GPIO_TC6393XB_INT  (15)
+#define TOSA_GPIO_JC_CF_IRQ		(36)	/* CF slot1 Ready */
+
+#define TOSA_SCOOP_GPIO_BASE	1
+#define TOSA_GPIO_IR_POWERDWN	(TOSA_SCOOP_GPIO_BASE + 2)
+#define TOSA_GPIO_SD_WP			(TOSA_SCOOP_GPIO_BASE + 3)
+#define TOSA_GPIO_PWR_ON		(TOSA_SCOOP_GPIO_BASE + 4)
+
+#define TOSA_SCOOP_JC_GPIO_BASE		1
+#define TOSA_GPIO_BT_LED		(TOSA_SCOOP_JC_GPIO_BASE + 0)
+#define TOSA_GPIO_NOTE_LED		(TOSA_SCOOP_JC_GPIO_BASE + 1)
+#define TOSA_GPIO_CHRG_ERR_LED		(TOSA_SCOOP_JC_GPIO_BASE + 2)
+#define TOSA_GPIO_TC6393XB_L3V_ON	(TOSA_SCOOP_JC_GPIO_BASE + 5)
+#define TOSA_GPIO_WLAN_LED		(TOSA_SCOOP_JC_GPIO_BASE + 7)
+
+#define	DAC_BASE	0x4e
+#define DAC_CH1		0
+#define DAC_CH2		1
+
+static void tosa_microdrive_attach(PXA2xxState *cpu)
+{
+    PCMCIACardState *md;
+    DriveInfo *dinfo;
+
+    dinfo = drive_get(IF_IDE, 0, 0);
+    if (!dinfo || dinfo->media_cd)
+        return;
+    md = dscm1xxxx_init(dinfo);
+    pxa2xx_pcmcia_attach(cpu->pcmcia[0], md);
+}
+
+static void tosa_out_switch(void *opaque, int line, int level)
+{
+    switch (line) {
+        case 0:
+            fprintf(stderr, "blue LED %s.\n", level ? "on" : "off");
+            break;
+        case 1:
+            fprintf(stderr, "green LED %s.\n", level ? "on" : "off");
+            break;
+        case 2:
+            fprintf(stderr, "amber LED %s.\n", level ? "on" : "off");
+            break;
+        case 3:
+            fprintf(stderr, "wlan LED %s.\n", level ? "on" : "off");
+            break;
+        default:
+            fprintf(stderr, "Uhandled out event: %d = %d\n", line, level);
+            break;
+    }
+}
+
+
+static void tosa_gpio_setup(PXA2xxState *cpu,
+                DeviceState *scp0,
+                DeviceState *scp1,
+                TC6393xbState *tmio)
+{
+    qemu_irq *outsignals = qemu_allocate_irqs(tosa_out_switch, cpu, 4);
+    /* MMC/SD host */
+    pxa2xx_mmci_handlers(cpu->mmc,
+                    qdev_get_gpio_in(scp0, TOSA_GPIO_SD_WP),
+                    qemu_irq_invert(qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_nSD_DETECT)));
+
+    /* Handle reset */
+    qdev_connect_gpio_out(cpu->gpio, TOSA_GPIO_ON_RESET, cpu->reset);
+
+    /* PCMCIA signals: card's IRQ and Card-Detect */
+    pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
+                        qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_CF_IRQ),
+                        qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_CF_CD));
+
+    pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
+                        qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_JC_CF_IRQ),
+                        NULL);
+
+    qdev_connect_gpio_out(scp1, TOSA_GPIO_BT_LED, outsignals[0]);
+    qdev_connect_gpio_out(scp1, TOSA_GPIO_NOTE_LED, outsignals[1]);
+    qdev_connect_gpio_out(scp1, TOSA_GPIO_CHRG_ERR_LED, outsignals[2]);
+    qdev_connect_gpio_out(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]);
+
+    qdev_connect_gpio_out(scp1, TOSA_GPIO_TC6393XB_L3V_ON, tc6393xb_l3v_get(tmio));
+
+    /* UDC Vbus */
+    qemu_irq_raise(qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_USB_IN));
+}
+
+static uint32_t tosa_ssp_tansfer(SSISlave *dev, uint32_t value)
+{
+    fprintf(stderr, "TG: %d %02x\n", value >> 5, value & 0x1f);
+    return 0;
+}
+
+static int tosa_ssp_init(SSISlave *dev)
+{
+    /* Nothing to do.  */
+    return 0;
+}
+
+typedef struct {
+    I2CSlave i2c;
+    int len;
+    char buf[3];
+} TosaDACState;
+
+static int tosa_dac_send(I2CSlave *i2c, uint8_t data)
+{
+    TosaDACState *s = FROM_I2C_SLAVE(TosaDACState, i2c);
+    s->buf[s->len] = data;
+    if (s->len ++ > 2) {
+#ifdef VERBOSE
+        fprintf(stderr, "%s: message too long (%i bytes)\n", __FUNCTION__, s->len);
+#endif
+        return 1;
+    }
+
+    if (s->len == 2) {
+        fprintf(stderr, "dac: channel %d value 0x%02x\n",
+                s->buf[0], s->buf[1]);
+    }
+
+    return 0;
+}
+
+static void tosa_dac_event(I2CSlave *i2c, enum i2c_event event)
+{
+    TosaDACState *s = FROM_I2C_SLAVE(TosaDACState, i2c);
+    s->len = 0;
+    switch (event) {
+    case I2C_START_SEND:
+        break;
+    case I2C_START_RECV:
+        printf("%s: recv not supported!!!\n", __FUNCTION__);
+        break;
+    case I2C_FINISH:
+#ifdef VERBOSE
+        if (s->len < 2)
+            printf("%s: message too short (%i bytes)\n", __FUNCTION__, s->len);
+        if (s->len > 2)
+            printf("%s: message too long\n", __FUNCTION__);
+#endif
+        break;
+    default:
+        break;
+    }
+}
+
+static int tosa_dac_recv(I2CSlave *s)
+{
+    printf("%s: recv not supported!!!\n", __FUNCTION__);
+    return -1;
+}
+
+static int tosa_dac_init(I2CSlave *i2c)
+{
+    /* Nothing to do.  */
+    return 0;
+}
+
+static void tosa_tg_init(PXA2xxState *cpu)
+{
+    i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]);
+    i2c_create_slave(bus, "tosa_dac", DAC_BASE);
+    ssi_create_slave(cpu->ssp[1], "tosa-ssp");
+}
+
+
+static struct arm_boot_info tosa_binfo = {
+    .loader_start = PXA2XX_SDRAM_BASE,
+    .ram_size = 0x04000000,
+};
+
+static void tosa_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *rom = g_new(MemoryRegion, 1);
+    PXA2xxState *mpu;
+    TC6393xbState *tmio;
+    DeviceState *scp0, *scp1;
+
+    if (!cpu_model)
+        cpu_model = "pxa255";
+
+    mpu = pxa255_init(address_space_mem, tosa_binfo.ram_size);
+
+    memory_region_init_ram(rom, "tosa.rom", TOSA_ROM);
+    vmstate_register_ram_global(rom);
+    memory_region_set_readonly(rom, true);
+    memory_region_add_subregion(address_space_mem, 0, rom);
+
+    tmio = tc6393xb_init(address_space_mem, 0x10000000,
+            qdev_get_gpio_in(mpu->gpio, TOSA_GPIO_TC6393XB_INT));
+
+    scp0 = sysbus_create_simple("scoop", 0x08800000, NULL);
+    scp1 = sysbus_create_simple("scoop", 0x14800040, NULL);
+
+    tosa_gpio_setup(mpu, scp0, scp1, tmio);
+
+    tosa_microdrive_attach(mpu);
+
+    tosa_tg_init(mpu);
+
+    tosa_binfo.kernel_filename = kernel_filename;
+    tosa_binfo.kernel_cmdline = kernel_cmdline;
+    tosa_binfo.initrd_filename = initrd_filename;
+    tosa_binfo.board_id = 0x208;
+    arm_load_kernel(mpu->cpu, &tosa_binfo);
+    sl_bootparam_write(SL_PXA_PARAM_BASE);
+}
+
+static QEMUMachine tosapda_machine = {
+    .name = "tosa",
+    .desc = "Tosa PDA (PXA255)",
+    .init = tosa_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void tosapda_machine_init(void)
+{
+    qemu_register_machine(&tosapda_machine);
+}
+
+machine_init(tosapda_machine_init);
+
+static void tosa_dac_class_init(ObjectClass *klass, void *data)
+{
+    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+    k->init = tosa_dac_init;
+    k->event = tosa_dac_event;
+    k->recv = tosa_dac_recv;
+    k->send = tosa_dac_send;
+}
+
+static const TypeInfo tosa_dac_info = {
+    .name          = "tosa_dac",
+    .parent        = TYPE_I2C_SLAVE,
+    .instance_size = sizeof(TosaDACState),
+    .class_init    = tosa_dac_class_init,
+};
+
+static void tosa_ssp_class_init(ObjectClass *klass, void *data)
+{
+    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+    k->init = tosa_ssp_init;
+    k->transfer = tosa_ssp_tansfer;
+}
+
+static const TypeInfo tosa_ssp_info = {
+    .name          = "tosa-ssp",
+    .parent        = TYPE_SSI_SLAVE,
+    .instance_size = sizeof(SSISlave),
+    .class_init    = tosa_ssp_class_init,
+};
+
+static void tosa_register_types(void)
+{
+    type_register_static(&tosa_dac_info);
+    type_register_static(&tosa_ssp_info);
+}
+
+type_init(tosa_register_types)
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
new file mode 100644
index 0000000..baaa265
--- /dev/null
+++ b/hw/arm/versatilepb.c
@@ -0,0 +1,403 @@
+/*
+ * ARM Versatile Platform/Application Baseboard System emulation.
+ *
+ * Copyright (c) 2005-2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/pci/pci.h"
+#include "hw/i2c.h"
+#include "hw/boards.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+#include "hw/flash.h"
+
+#define VERSATILE_FLASH_ADDR 0x34000000
+#define VERSATILE_FLASH_SIZE (64 * 1024 * 1024)
+#define VERSATILE_FLASH_SECT_SIZE (256 * 1024)
+
+/* Primary interrupt controller.  */
+
+typedef struct vpb_sic_state
+{
+  SysBusDevice busdev;
+  MemoryRegion iomem;
+  uint32_t level;
+  uint32_t mask;
+  uint32_t pic_enable;
+  qemu_irq parent[32];
+  int irq;
+} vpb_sic_state;
+
+static const VMStateDescription vmstate_vpb_sic = {
+    .name = "versatilepb_sic",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(level, vpb_sic_state),
+        VMSTATE_UINT32(mask, vpb_sic_state),
+        VMSTATE_UINT32(pic_enable, vpb_sic_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void vpb_sic_update(vpb_sic_state *s)
+{
+    uint32_t flags;
+
+    flags = s->level & s->mask;
+    qemu_set_irq(s->parent[s->irq], flags != 0);
+}
+
+static void vpb_sic_update_pic(vpb_sic_state *s)
+{
+    int i;
+    uint32_t mask;
+
+    for (i = 21; i <= 30; i++) {
+        mask = 1u << i;
+        if (!(s->pic_enable & mask))
+            continue;
+        qemu_set_irq(s->parent[i], (s->level & mask) != 0);
+    }
+}
+
+static void vpb_sic_set_irq(void *opaque, int irq, int level)
+{
+    vpb_sic_state *s = (vpb_sic_state *)opaque;
+    if (level)
+        s->level |= 1u << irq;
+    else
+        s->level &= ~(1u << irq);
+    if (s->pic_enable & (1u << irq))
+        qemu_set_irq(s->parent[irq], level);
+    vpb_sic_update(s);
+}
+
+static uint64_t vpb_sic_read(void *opaque, hwaddr offset,
+                             unsigned size)
+{
+    vpb_sic_state *s = (vpb_sic_state *)opaque;
+
+    switch (offset >> 2) {
+    case 0: /* STATUS */
+        return s->level & s->mask;
+    case 1: /* RAWSTAT */
+        return s->level;
+    case 2: /* ENABLE */
+        return s->mask;
+    case 4: /* SOFTINT */
+        return s->level & 1;
+    case 8: /* PICENABLE */
+        return s->pic_enable;
+    default:
+        printf ("vpb_sic_read: Bad register offset 0x%x\n", (int)offset);
+        return 0;
+    }
+}
+
+static void vpb_sic_write(void *opaque, hwaddr offset,
+                          uint64_t value, unsigned size)
+{
+    vpb_sic_state *s = (vpb_sic_state *)opaque;
+
+    switch (offset >> 2) {
+    case 2: /* ENSET */
+        s->mask |= value;
+        break;
+    case 3: /* ENCLR */
+        s->mask &= ~value;
+        break;
+    case 4: /* SOFTINTSET */
+        if (value)
+            s->mask |= 1;
+        break;
+    case 5: /* SOFTINTCLR */
+        if (value)
+            s->mask &= ~1u;
+        break;
+    case 8: /* PICENSET */
+        s->pic_enable |= (value & 0x7fe00000);
+        vpb_sic_update_pic(s);
+        break;
+    case 9: /* PICENCLR */
+        s->pic_enable &= ~value;
+        vpb_sic_update_pic(s);
+        break;
+    default:
+        printf ("vpb_sic_write: Bad register offset 0x%x\n", (int)offset);
+        return;
+    }
+    vpb_sic_update(s);
+}
+
+static const MemoryRegionOps vpb_sic_ops = {
+    .read = vpb_sic_read,
+    .write = vpb_sic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int vpb_sic_init(SysBusDevice *dev)
+{
+    vpb_sic_state *s = FROM_SYSBUS(vpb_sic_state, dev);
+    int i;
+
+    qdev_init_gpio_in(&dev->qdev, vpb_sic_set_irq, 32);
+    for (i = 0; i < 32; i++) {
+        sysbus_init_irq(dev, &s->parent[i]);
+    }
+    s->irq = 31;
+    memory_region_init_io(&s->iomem, &vpb_sic_ops, s, "vpb-sic", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    return 0;
+}
+
+/* Board init.  */
+
+/* The AB and PB boards both use the same core, just with different
+   peripherals and expansion busses.  For now we emulate a subset of the
+   PB peripherals and just change the board ID.  */
+
+static struct arm_boot_info versatile_binfo;
+
+static void versatile_init(QEMUMachineInitArgs *args, int board_id)
+{
+    ARMCPU *cpu;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    qemu_irq *cpu_pic;
+    qemu_irq pic[32];
+    qemu_irq sic[32];
+    DeviceState *dev, *sysctl;
+    SysBusDevice *busdev;
+    DeviceState *pl041;
+    PCIBus *pci_bus;
+    NICInfo *nd;
+    i2c_bus *i2c;
+    int n;
+    int done_smc = 0;
+    DriveInfo *dinfo;
+
+    if (!args->cpu_model) {
+        args->cpu_model = "arm926";
+    }
+    cpu = cpu_arm_init(args->cpu_model);
+    if (!cpu) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    memory_region_init_ram(ram, "versatile.ram", args->ram_size);
+    vmstate_register_ram_global(ram);
+    /* ??? RAM should repeat to fill physical memory space.  */
+    /* SDRAM at address zero.  */
+    memory_region_add_subregion(sysmem, 0, ram);
+
+    sysctl = qdev_create(NULL, "realview_sysctl");
+    qdev_prop_set_uint32(sysctl, "sys_id", 0x41007004);
+    qdev_prop_set_uint32(sysctl, "proc_id", 0x02000000);
+    qdev_init_nofail(sysctl);
+    sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
+
+    cpu_pic = arm_pic_init_cpu(cpu);
+    dev = sysbus_create_varargs("pl190", 0x10140000,
+                                cpu_pic[ARM_PIC_CPU_IRQ],
+                                cpu_pic[ARM_PIC_CPU_FIQ], NULL);
+    for (n = 0; n < 32; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+    dev = sysbus_create_simple("versatilepb_sic", 0x10003000, NULL);
+    for (n = 0; n < 32; n++) {
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), n, pic[n]);
+        sic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    sysbus_create_simple("pl050_keyboard", 0x10006000, sic[3]);
+    sysbus_create_simple("pl050_mouse", 0x10007000, sic[4]);
+
+    dev = qdev_create(NULL, "versatile_pci");
+    busdev = SYS_BUS_DEVICE(dev);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(busdev, 0, 0x41000000); /* PCI self-config */
+    sysbus_mmio_map(busdev, 1, 0x42000000); /* PCI config */
+    sysbus_connect_irq(busdev, 0, sic[27]);
+    sysbus_connect_irq(busdev, 1, sic[28]);
+    sysbus_connect_irq(busdev, 2, sic[29]);
+    sysbus_connect_irq(busdev, 3, sic[30]);
+    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
+
+    /* The Versatile PCI bridge does not provide access to PCI IO space,
+       so many of the qemu PCI devices are not useable.  */
+    for(n = 0; n < nb_nics; n++) {
+        nd = &nd_table[n];
+
+        if (!done_smc && (!nd->model || strcmp(nd->model, "smc91c111") == 0)) {
+            smc91c111_init(nd, 0x10010000, sic[25]);
+            done_smc = 1;
+        } else {
+            pci_nic_init_nofail(nd, "rtl8139", NULL);
+        }
+    }
+    if (usb_enabled(false)) {
+        pci_create_simple(pci_bus, -1, "pci-ohci");
+    }
+    n = drive_get_max_bus(IF_SCSI);
+    while (n >= 0) {
+        pci_create_simple(pci_bus, -1, "lsi53c895a");
+        n--;
+    }
+
+    sysbus_create_simple("pl011", 0x101f1000, pic[12]);
+    sysbus_create_simple("pl011", 0x101f2000, pic[13]);
+    sysbus_create_simple("pl011", 0x101f3000, pic[14]);
+    sysbus_create_simple("pl011", 0x10009000, sic[6]);
+
+    sysbus_create_simple("pl080", 0x10130000, pic[17]);
+    sysbus_create_simple("sp804", 0x101e2000, pic[4]);
+    sysbus_create_simple("sp804", 0x101e3000, pic[5]);
+
+    sysbus_create_simple("pl061", 0x101e4000, pic[6]);
+    sysbus_create_simple("pl061", 0x101e5000, pic[7]);
+    sysbus_create_simple("pl061", 0x101e6000, pic[8]);
+    sysbus_create_simple("pl061", 0x101e7000, pic[9]);
+
+    /* The versatile/PB actually has a modified Color LCD controller
+       that includes hardware cursor support from the PL111.  */
+    dev = sysbus_create_simple("pl110_versatile", 0x10120000, pic[16]);
+    /* Wire up the mux control signals from the SYS_CLCD register */
+    qdev_connect_gpio_out(sysctl, 0, qdev_get_gpio_in(dev, 0));
+
+    sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL);
+    sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL);
+
+    /* Add PL031 Real Time Clock. */
+    sysbus_create_simple("pl031", 0x101e8000, pic[10]);
+
+    dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL);
+    i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
+    i2c_create_slave(i2c, "ds1338", 0x68);
+
+    /* Add PL041 AACI Interface to the LM4549 codec */
+    pl041 = qdev_create(NULL, "pl041");
+    qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
+    qdev_init_nofail(pl041);
+    sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000);
+    sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, sic[24]);
+
+    /* Memory map for Versatile/PB:  */
+    /* 0x10000000 System registers.  */
+    /* 0x10001000 PCI controller config registers.  */
+    /* 0x10002000 Serial bus interface.  */
+    /*  0x10003000 Secondary interrupt controller.  */
+    /* 0x10004000 AACI (audio).  */
+    /*  0x10005000 MMCI0.  */
+    /*  0x10006000 KMI0 (keyboard).  */
+    /*  0x10007000 KMI1 (mouse).  */
+    /* 0x10008000 Character LCD Interface.  */
+    /*  0x10009000 UART3.  */
+    /* 0x1000a000 Smart card 1.  */
+    /*  0x1000b000 MMCI1.  */
+    /*  0x10010000 Ethernet.  */
+    /* 0x10020000 USB.  */
+    /* 0x10100000 SSMC.  */
+    /* 0x10110000 MPMC.  */
+    /*  0x10120000 CLCD Controller.  */
+    /*  0x10130000 DMA Controller.  */
+    /*  0x10140000 Vectored interrupt controller.  */
+    /* 0x101d0000 AHB Monitor Interface.  */
+    /* 0x101e0000 System Controller.  */
+    /* 0x101e1000 Watchdog Interface.  */
+    /* 0x101e2000 Timer 0/1.  */
+    /* 0x101e3000 Timer 2/3.  */
+    /* 0x101e4000 GPIO port 0.  */
+    /* 0x101e5000 GPIO port 1.  */
+    /* 0x101e6000 GPIO port 2.  */
+    /* 0x101e7000 GPIO port 3.  */
+    /* 0x101e8000 RTC.  */
+    /* 0x101f0000 Smart card 0.  */
+    /*  0x101f1000 UART0.  */
+    /*  0x101f2000 UART1.  */
+    /*  0x101f3000 UART2.  */
+    /* 0x101f4000 SSPI.  */
+    /* 0x34000000 NOR Flash */
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, NULL, "versatile.flash",
+                          VERSATILE_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL,
+                          VERSATILE_FLASH_SECT_SIZE,
+                          VERSATILE_FLASH_SIZE / VERSATILE_FLASH_SECT_SIZE,
+                          4, 0x0089, 0x0018, 0x0000, 0x0, 0)) {
+        fprintf(stderr, "qemu: Error registering flash memory.\n");
+    }
+
+    versatile_binfo.ram_size = args->ram_size;
+    versatile_binfo.kernel_filename = args->kernel_filename;
+    versatile_binfo.kernel_cmdline = args->kernel_cmdline;
+    versatile_binfo.initrd_filename = args->initrd_filename;
+    versatile_binfo.board_id = board_id;
+    arm_load_kernel(cpu, &versatile_binfo);
+}
+
+static void vpb_init(QEMUMachineInitArgs *args)
+{
+    versatile_init(args, 0x183);
+}
+
+static void vab_init(QEMUMachineInitArgs *args)
+{
+    versatile_init(args, 0x25e);
+}
+
+static QEMUMachine versatilepb_machine = {
+    .name = "versatilepb",
+    .desc = "ARM Versatile/PB (ARM926EJ-S)",
+    .init = vpb_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine versatileab_machine = {
+    .name = "versatileab",
+    .desc = "ARM Versatile/AB (ARM926EJ-S)",
+    .init = vab_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void versatile_machine_init(void)
+{
+    qemu_register_machine(&versatilepb_machine);
+    qemu_register_machine(&versatileab_machine);
+}
+
+machine_init(versatile_machine_init);
+
+static void vpb_sic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = vpb_sic_init;
+    dc->no_user = 1;
+    dc->vmsd = &vmstate_vpb_sic;
+}
+
+static const TypeInfo vpb_sic_info = {
+    .name          = "versatilepb_sic",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(vpb_sic_state),
+    .class_init    = vpb_sic_class_init,
+};
+
+static void versatilepb_register_types(void)
+{
+    type_register_static(&vpb_sic_info);
+}
+
+type_init(versatilepb_register_types)
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
new file mode 100644
index 0000000..02922c3
--- /dev/null
+++ b/hw/arm/vexpress.c
@@ -0,0 +1,500 @@
+/*
+ * 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/>.
+ *
+ *  Contributions after 2012-01-13 are licensed under the terms of the
+ *  GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/primecell.h"
+#include "hw/devices.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "exec/address-spaces.h"
+#include "sysemu/blockdev.h"
+#include "hw/flash.h"
+
+#define VEXPRESS_BOARD_ID 0x8e0
+#define VEXPRESS_FLASH_SIZE (64 * 1024 * 1024)
+#define VEXPRESS_FLASH_SECT_SIZE (256 * 1024)
+
+static struct arm_boot_info vexpress_binfo;
+
+/* Address maps for peripherals:
+ * the Versatile Express motherboard has two possible maps,
+ * the "legacy" one (used for A9) and the "Cortex-A Series"
+ * map (used for newer cores).
+ * Individual daughterboards can also have different maps for
+ * their peripherals.
+ */
+
+enum {
+    VE_SYSREGS,
+    VE_SP810,
+    VE_SERIALPCI,
+    VE_PL041,
+    VE_MMCI,
+    VE_KMI0,
+    VE_KMI1,
+    VE_UART0,
+    VE_UART1,
+    VE_UART2,
+    VE_UART3,
+    VE_WDT,
+    VE_TIMER01,
+    VE_TIMER23,
+    VE_SERIALDVI,
+    VE_RTC,
+    VE_COMPACTFLASH,
+    VE_CLCD,
+    VE_NORFLASH0,
+    VE_NORFLASH1,
+    VE_SRAM,
+    VE_VIDEORAM,
+    VE_ETHERNET,
+    VE_USB,
+    VE_DAPROM,
+};
+
+static hwaddr motherboard_legacy_map[] = {
+    /* CS7: 0x10000000 .. 0x10020000 */
+    [VE_SYSREGS] = 0x10000000,
+    [VE_SP810] = 0x10001000,
+    [VE_SERIALPCI] = 0x10002000,
+    [VE_PL041] = 0x10004000,
+    [VE_MMCI] = 0x10005000,
+    [VE_KMI0] = 0x10006000,
+    [VE_KMI1] = 0x10007000,
+    [VE_UART0] = 0x10009000,
+    [VE_UART1] = 0x1000a000,
+    [VE_UART2] = 0x1000b000,
+    [VE_UART3] = 0x1000c000,
+    [VE_WDT] = 0x1000f000,
+    [VE_TIMER01] = 0x10011000,
+    [VE_TIMER23] = 0x10012000,
+    [VE_SERIALDVI] = 0x10016000,
+    [VE_RTC] = 0x10017000,
+    [VE_COMPACTFLASH] = 0x1001a000,
+    [VE_CLCD] = 0x1001f000,
+    /* CS0: 0x40000000 .. 0x44000000 */
+    [VE_NORFLASH0] = 0x40000000,
+    /* CS1: 0x44000000 .. 0x48000000 */
+    [VE_NORFLASH1] = 0x44000000,
+    /* CS2: 0x48000000 .. 0x4a000000 */
+    [VE_SRAM] = 0x48000000,
+    /* CS3: 0x4c000000 .. 0x50000000 */
+    [VE_VIDEORAM] = 0x4c000000,
+    [VE_ETHERNET] = 0x4e000000,
+    [VE_USB] = 0x4f000000,
+};
+
+static hwaddr motherboard_aseries_map[] = {
+    /* CS0: 0x08000000 .. 0x0c000000 */
+    [VE_NORFLASH0] = 0x08000000,
+    /* CS4: 0x0c000000 .. 0x10000000 */
+    [VE_NORFLASH1] = 0x0c000000,
+    /* CS5: 0x10000000 .. 0x14000000 */
+    /* CS1: 0x14000000 .. 0x18000000 */
+    [VE_SRAM] = 0x14000000,
+    /* CS2: 0x18000000 .. 0x1c000000 */
+    [VE_VIDEORAM] = 0x18000000,
+    [VE_ETHERNET] = 0x1a000000,
+    [VE_USB] = 0x1b000000,
+    /* CS3: 0x1c000000 .. 0x20000000 */
+    [VE_DAPROM] = 0x1c000000,
+    [VE_SYSREGS] = 0x1c010000,
+    [VE_SP810] = 0x1c020000,
+    [VE_SERIALPCI] = 0x1c030000,
+    [VE_PL041] = 0x1c040000,
+    [VE_MMCI] = 0x1c050000,
+    [VE_KMI0] = 0x1c060000,
+    [VE_KMI1] = 0x1c070000,
+    [VE_UART0] = 0x1c090000,
+    [VE_UART1] = 0x1c0a0000,
+    [VE_UART2] = 0x1c0b0000,
+    [VE_UART3] = 0x1c0c0000,
+    [VE_WDT] = 0x1c0f0000,
+    [VE_TIMER01] = 0x1c110000,
+    [VE_TIMER23] = 0x1c120000,
+    [VE_SERIALDVI] = 0x1c160000,
+    [VE_RTC] = 0x1c170000,
+    [VE_COMPACTFLASH] = 0x1c1a0000,
+    [VE_CLCD] = 0x1c1f0000,
+};
+
+/* Structure defining the peculiarities of a specific daughterboard */
+
+typedef struct VEDBoardInfo VEDBoardInfo;
+
+typedef void DBoardInitFn(const VEDBoardInfo *daughterboard,
+                          ram_addr_t ram_size,
+                          const char *cpu_model,
+                          qemu_irq *pic, uint32_t *proc_id);
+
+struct VEDBoardInfo {
+    const hwaddr *motherboard_map;
+    hwaddr loader_start;
+    const hwaddr gic_cpu_if_addr;
+    DBoardInitFn *init;
+};
+
+static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
+                                  ram_addr_t ram_size,
+                                  const char *cpu_model,
+                                  qemu_irq *pic, uint32_t *proc_id)
+{
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *lowram = g_new(MemoryRegion, 1);
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    int n;
+    qemu_irq cpu_irq[4];
+    ram_addr_t low_ram_size;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    *proc_id = 0x0c000191;
+
+    for (n = 0; n < smp_cpus; n++) {
+        ARMCPU *cpu = cpu_arm_init(cpu_model);
+        if (!cpu) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(cpu);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+    }
+
+    if (ram_size > 0x40000000) {
+        /* 1GB is the maximum the address space permits */
+        fprintf(stderr, "vexpress-a9: cannot model more than 1GB RAM\n");
+        exit(1);
+    }
+
+    memory_region_init_ram(ram, "vexpress.highmem", ram_size);
+    vmstate_register_ram_global(ram);
+    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.
+     */
+    memory_region_init_alias(lowram, "vexpress.lowmem", ram, 0, low_ram_size);
+    memory_region_add_subregion(sysmem, 0x0, lowram);
+    memory_region_add_subregion(sysmem, 0x60000000, 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 = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, 0x1e000000);
+    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);
+    }
+
+    /* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
+
+    /* 0x10020000 PL111 CLCD (daughterboard) */
+    sysbus_create_simple("pl111", 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 */
+    sysbus_create_varargs("l2x0", 0x1e00a000, NULL);
+}
+
+static const VEDBoardInfo a9_daughterboard = {
+    .motherboard_map = motherboard_legacy_map,
+    .loader_start = 0x60000000,
+    .gic_cpu_if_addr = 0x1e000100,
+    .init = a9_daughterboard_init,
+};
+
+static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
+                                   ram_addr_t ram_size,
+                                   const char *cpu_model,
+                                   qemu_irq *pic, uint32_t *proc_id)
+{
+    int n;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    qemu_irq cpu_irq[4];
+    DeviceState *dev;
+    SysBusDevice *busdev;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a15";
+    }
+
+    *proc_id = 0x14000237;
+
+    for (n = 0; n < smp_cpus; n++) {
+        ARMCPU *cpu;
+        qemu_irq *irqp;
+
+        cpu = cpu_arm_init(cpu_model);
+        if (!cpu) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(cpu);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+    }
+
+    {
+        /* We have to use a separate 64 bit variable here to avoid the gcc
+         * "comparison is always false due to limited range of data type"
+         * warning if we are on a host where ram_addr_t is 32 bits.
+         */
+        uint64_t rsz = ram_size;
+        if (rsz > (30ULL * 1024 * 1024 * 1024)) {
+            fprintf(stderr, "vexpress-a15: cannot model more than 30GB RAM\n");
+            exit(1);
+        }
+    }
+
+    memory_region_init_ram(ram, "vexpress.highmem", ram_size);
+    vmstate_register_ram_global(ram);
+    /* RAM is from 0x80000000 upwards; there is no low-memory alias for it. */
+    memory_region_add_subregion(sysmem, 0x80000000, ram);
+
+    /* 0x2c000000 A15MPCore private memory region (GIC) */
+    dev = qdev_create(NULL, "a15mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, 0x2c000000);
+    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 there
+     * are internal interrupts 0..31).
+     */
+    for (n = 0; n < 64; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    /* A15 daughterboard peripherals: */
+
+    /* 0x20000000: CoreSight interfaces: not modelled */
+    /* 0x2a000000: PL301 AXI interconnect: not modelled */
+    /* 0x2a420000: SCC: not modelled */
+    /* 0x2a430000: system counter: not modelled */
+    /* 0x2b000000: HDLCD controller: not modelled */
+    /* 0x2b060000: SP805 watchdog: not modelled */
+    /* 0x2b0a0000: PL341 dynamic memory controller: not modelled */
+    /* 0x2e000000: system SRAM */
+    memory_region_init_ram(sram, "vexpress.a15sram", 0x10000);
+    vmstate_register_ram_global(sram);
+    memory_region_add_subregion(sysmem, 0x2e000000, sram);
+
+    /* 0x7ffb0000: DMA330 DMA controller: not modelled */
+    /* 0x7ffd0000: PL354 static memory controller: not modelled */
+}
+
+static const VEDBoardInfo a15_daughterboard = {
+    .motherboard_map = motherboard_aseries_map,
+    .loader_start = 0x80000000,
+    .gic_cpu_if_addr = 0x2c002000,
+    .init = a15_daughterboard_init,
+};
+
+static void vexpress_common_init(const VEDBoardInfo *daughterboard,
+                                 QEMUMachineInitArgs *args)
+{
+    DeviceState *dev, *sysctl, *pl041;
+    qemu_irq pic[64];
+    uint32_t proc_id;
+    uint32_t sys_id;
+    DriveInfo *dinfo;
+    ram_addr_t vram_size, sram_size;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *vram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    const hwaddr *map = daughterboard->motherboard_map;
+
+    daughterboard->init(daughterboard, args->ram_size, args->cpu_model,
+                        pic, &proc_id);
+
+    /* Motherboard peripherals: the wiring is the same but the
+     * addresses vary between the legacy and A-Series memory maps.
+     */
+
+    sys_id = 0x1190f500;
+
+    sysctl = qdev_create(NULL, "realview_sysctl");
+    qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
+    qdev_prop_set_uint32(sysctl, "proc_id", proc_id);
+    qdev_init_nofail(sysctl);
+    sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, map[VE_SYSREGS]);
+
+    /* VE_SP810: not modelled */
+    /* VE_SERIALPCI: not modelled */
+
+    pl041 = qdev_create(NULL, "pl041");
+    qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
+    qdev_init_nofail(pl041);
+    sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, map[VE_PL041]);
+    sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, pic[11]);
+
+    dev = sysbus_create_varargs("pl181", map[VE_MMCI], 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", map[VE_KMI0], pic[12]);
+    sysbus_create_simple("pl050_mouse", map[VE_KMI1], pic[13]);
+
+    sysbus_create_simple("pl011", map[VE_UART0], pic[5]);
+    sysbus_create_simple("pl011", map[VE_UART1], pic[6]);
+    sysbus_create_simple("pl011", map[VE_UART2], pic[7]);
+    sysbus_create_simple("pl011", map[VE_UART3], pic[8]);
+
+    sysbus_create_simple("sp804", map[VE_TIMER01], pic[2]);
+    sysbus_create_simple("sp804", map[VE_TIMER23], pic[3]);
+
+    /* VE_SERIALDVI: not modelled */
+
+    sysbus_create_simple("pl031", map[VE_RTC], pic[4]); /* RTC */
+
+    /* VE_COMPACTFLASH: not modelled */
+
+    sysbus_create_simple("pl111", map[VE_CLCD], pic[14]);
+
+    dinfo = drive_get_next(IF_PFLASH);
+    if (!pflash_cfi01_register(map[VE_NORFLASH0], NULL, "vexpress.flash0",
+            VEXPRESS_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL,
+            VEXPRESS_FLASH_SECT_SIZE,
+            VEXPRESS_FLASH_SIZE / VEXPRESS_FLASH_SECT_SIZE, 4,
+            0x00, 0x89, 0x00, 0x18, 0)) {
+        fprintf(stderr, "vexpress: error registering flash 0.\n");
+        exit(1);
+    }
+
+    dinfo = drive_get_next(IF_PFLASH);
+    if (!pflash_cfi01_register(map[VE_NORFLASH1], NULL, "vexpress.flash1",
+            VEXPRESS_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL,
+            VEXPRESS_FLASH_SECT_SIZE,
+            VEXPRESS_FLASH_SIZE / VEXPRESS_FLASH_SECT_SIZE, 4,
+            0x00, 0x89, 0x00, 0x18, 0)) {
+        fprintf(stderr, "vexpress: error registering flash 1.\n");
+        exit(1);
+    }
+
+    sram_size = 0x2000000;
+    memory_region_init_ram(sram, "vexpress.sram", sram_size);
+    vmstate_register_ram_global(sram);
+    memory_region_add_subregion(sysmem, map[VE_SRAM], sram);
+
+    vram_size = 0x800000;
+    memory_region_init_ram(vram, "vexpress.vram", vram_size);
+    vmstate_register_ram_global(vram);
+    memory_region_add_subregion(sysmem, map[VE_VIDEORAM], vram);
+
+    /* 0x4e000000 LAN9118 Ethernet */
+    if (nd_table[0].used) {
+        lan9118_init(&nd_table[0], map[VE_ETHERNET], pic[15]);
+    }
+
+    /* VE_USB: not modelled */
+
+    /* VE_DAPROM: not modelled */
+
+    vexpress_binfo.ram_size = args->ram_size;
+    vexpress_binfo.kernel_filename = args->kernel_filename;
+    vexpress_binfo.kernel_cmdline = args->kernel_cmdline;
+    vexpress_binfo.initrd_filename = args->initrd_filename;
+    vexpress_binfo.nb_cpus = smp_cpus;
+    vexpress_binfo.board_id = VEXPRESS_BOARD_ID;
+    vexpress_binfo.loader_start = daughterboard->loader_start;
+    vexpress_binfo.smp_loader_start = map[VE_SRAM];
+    vexpress_binfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30;
+    vexpress_binfo.gic_cpu_if_addr = daughterboard->gic_cpu_if_addr;
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &vexpress_binfo);
+}
+
+static void vexpress_a9_init(QEMUMachineInitArgs *args)
+{
+    vexpress_common_init(&a9_daughterboard, args);
+}
+
+static void vexpress_a15_init(QEMUMachineInitArgs *args)
+{
+    vexpress_common_init(&a15_daughterboard, args);
+}
+
+static QEMUMachine vexpress_a9_machine = {
+    .name = "vexpress-a9",
+    .desc = "ARM Versatile Express for Cortex-A9",
+    .init = vexpress_a9_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine vexpress_a15_machine = {
+    .name = "vexpress-a15",
+    .desc = "ARM Versatile Express for Cortex-A15",
+    .init = vexpress_a15_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void vexpress_machine_init(void)
+{
+    qemu_register_machine(&vexpress_a9_machine);
+    qemu_register_machine(&vexpress_a15_machine);
+}
+
+machine_init(vexpress_machine_init);
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
new file mode 100644
index 0000000..f78c47e
--- /dev/null
+++ b/hw/arm/xilinx_zynq.c
@@ -0,0 +1,224 @@
+/*
+ * Xilinx Zynq Baseboard System emulation.
+ *
+ * Copyright (c) 2010 Xilinx.
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.croshtwaite at petalogix.com)
+ * Copyright (c) 2012 Petalogix Pty Ltd.
+ * Written by Haibing Ma
+ *
+ * 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.
+ *
+ * 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/sysbus.h"
+#include "hw/arm-misc.h"
+#include "net/net.h"
+#include "exec/address-spaces.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/flash.h"
+#include "sysemu/blockdev.h"
+#include "hw/loader.h"
+#include "hw/ssi.h"
+
+#define NUM_SPI_FLASHES 4
+#define NUM_QSPI_FLASHES 2
+#define NUM_QSPI_BUSSES 2
+
+#define FLASH_SIZE (64 * 1024 * 1024)
+#define FLASH_SECTOR_SIZE (128 * 1024)
+
+#define IRQ_OFFSET 32 /* pic interrupts start from index 32 */
+
+static struct arm_boot_info zynq_binfo = {};
+
+static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    qemu_check_nic_model(nd, "cadence_gem");
+    dev = qdev_create(NULL, "cadence_gem");
+    qdev_set_nic_properties(dev, nd);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(s, 0, base);
+    sysbus_connect_irq(s, 0, irq);
+}
+
+static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
+                                         bool is_qspi)
+{
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    SSIBus *spi;
+    DeviceState *flash_dev;
+    int i, j;
+    int num_busses =  is_qspi ? NUM_QSPI_BUSSES : 1;
+    int num_ss = is_qspi ? NUM_QSPI_FLASHES : NUM_SPI_FLASHES;
+
+    dev = qdev_create(NULL, "xilinx,spips");
+    qdev_prop_set_uint8(dev, "num-txrx-bytes", is_qspi ? 4 : 1);
+    qdev_prop_set_uint8(dev, "num-ss-bits", num_ss);
+    qdev_prop_set_uint8(dev, "num-busses", num_busses);
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, base_addr);
+    if (is_qspi) {
+        sysbus_mmio_map(busdev, 1, 0xFC000000);
+    }
+    sysbus_connect_irq(busdev, 0, irq);
+
+    for (i = 0; i < num_busses; ++i) {
+        char bus_name[16];
+        qemu_irq cs_line;
+
+        snprintf(bus_name, 16, "spi%d", i);
+        spi = (SSIBus *)qdev_get_child_bus(dev, bus_name);
+
+        for (j = 0; j < num_ss; ++j) {
+            flash_dev = ssi_create_slave_no_init(spi, "n25q128");
+            qdev_init_nofail(flash_dev);
+
+            cs_line = qdev_get_gpio_in(flash_dev, 0);
+            sysbus_connect_irq(busdev, i * num_ss + j + 1, cs_line);
+        }
+    }
+
+}
+
+static void zynq_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    ARMCPU *cpu;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ext_ram = g_new(MemoryRegion, 1);
+    MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[64];
+    NICInfo *nd;
+    int n;
+    qemu_irq cpu_irq;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    cpu = cpu_arm_init(cpu_model);
+    if (!cpu) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    irqp = arm_pic_init_cpu(cpu);
+    cpu_irq = irqp[ARM_PIC_CPU_IRQ];
+
+    /* max 2GB ram */
+    if (ram_size > 0x80000000) {
+        ram_size = 0x80000000;
+    }
+
+    /* DDR remapped to address zero.  */
+    memory_region_init_ram(ext_ram, "zynq.ext_ram", ram_size);
+    vmstate_register_ram_global(ext_ram);
+    memory_region_add_subregion(address_space_mem, 0, ext_ram);
+
+    /* 256K of on-chip memory */
+    memory_region_init_ram(ocm_ram, "zynq.ocm_ram", 256 << 10);
+    vmstate_register_ram_global(ocm_ram);
+    memory_region_add_subregion(address_space_mem, 0xFFFC0000, ocm_ram);
+
+    DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
+
+    /* AMD */
+    pflash_cfi02_register(0xe2000000, NULL, "zynq.pflash", FLASH_SIZE,
+                          dinfo ? dinfo->bdrv : NULL, FLASH_SECTOR_SIZE,
+                          FLASH_SIZE/FLASH_SECTOR_SIZE, 1,
+                          1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa,
+                              0);
+
+    dev = qdev_create(NULL, "xilinx,zynq_slcr");
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xF8000000);
+
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", 1);
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, 0xF8F00000);
+    sysbus_connect_irq(busdev, 0, cpu_irq);
+
+    for (n = 0; n < 64; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    zynq_init_spi_flashes(0xE0006000, pic[58-IRQ_OFFSET], false);
+    zynq_init_spi_flashes(0xE0007000, pic[81-IRQ_OFFSET], false);
+    zynq_init_spi_flashes(0xE000D000, pic[51-IRQ_OFFSET], true);
+
+    sysbus_create_simple("xlnx,ps7-usb", 0xE0002000, pic[53-IRQ_OFFSET]);
+    sysbus_create_simple("xlnx,ps7-usb", 0xE0003000, pic[76-IRQ_OFFSET]);
+
+    sysbus_create_simple("cadence_uart", 0xE0000000, pic[59-IRQ_OFFSET]);
+    sysbus_create_simple("cadence_uart", 0xE0001000, pic[82-IRQ_OFFSET]);
+
+    sysbus_create_varargs("cadence_ttc", 0xF8001000,
+            pic[42-IRQ_OFFSET], pic[43-IRQ_OFFSET], pic[44-IRQ_OFFSET], NULL);
+    sysbus_create_varargs("cadence_ttc", 0xF8002000,
+            pic[69-IRQ_OFFSET], pic[70-IRQ_OFFSET], pic[71-IRQ_OFFSET], NULL);
+
+    for (n = 0; n < nb_nics; n++) {
+        nd = &nd_table[n];
+        if (n == 0) {
+            gem_init(nd, 0xE000B000, pic[54-IRQ_OFFSET]);
+        } else if (n == 1) {
+            gem_init(nd, 0xE000C000, pic[77-IRQ_OFFSET]);
+        }
+    }
+
+    dev = qdev_create(NULL, "generic-sdhci");
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0100000);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[56-IRQ_OFFSET]);
+
+    dev = qdev_create(NULL, "generic-sdhci");
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]);
+
+    zynq_binfo.ram_size = ram_size;
+    zynq_binfo.kernel_filename = kernel_filename;
+    zynq_binfo.kernel_cmdline = kernel_cmdline;
+    zynq_binfo.initrd_filename = initrd_filename;
+    zynq_binfo.nb_cpus = 1;
+    zynq_binfo.board_id = 0xd32;
+    zynq_binfo.loader_start = 0;
+    arm_load_kernel(arm_env_get_cpu(first_cpu), &zynq_binfo);
+}
+
+static QEMUMachine zynq_machine = {
+    .name = "xilinx-zynq-a9",
+    .desc = "Xilinx Zynq Platform Baseboard for Cortex-A9",
+    .init = zynq_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 1,
+    .no_sdcard = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void zynq_machine_init(void)
+{
+    qemu_register_machine(&zynq_machine);
+}
+
+machine_init(zynq_machine_init);
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
new file mode 100644
index 0000000..cbb6d80
--- /dev/null
+++ b/hw/arm/z2.c
@@ -0,0 +1,384 @@
+/*
+ * PXA270-based Zipit Z2 device
+ *
+ * Copyright (c) 2011 by Vasily Khoruzhick <anarsoul at gmail.com>
+ *
+ * Code is based on mainstone platform.
+ *
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "hw/i2c.h"
+#include "hw/ssi.h"
+#include "hw/boards.h"
+#include "sysemu/sysemu.h"
+#include "hw/flash.h"
+#include "sysemu/blockdev.h"
+#include "ui/console.h"
+#include "audio/audio.h"
+#include "exec/address-spaces.h"
+
+#ifdef DEBUG_Z2
+#define DPRINTF(fmt, ...) \
+        printf(fmt, ## __VA_ARGS__)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+static struct keymap map[0x100] = {
+    [0 ... 0xff] = { -1, -1 },
+    [0x3b] = {0, 0}, /* Option = F1 */
+    [0xc8] = {0, 1}, /* Up */
+    [0xd0] = {0, 2}, /* Down */
+    [0xcb] = {0, 3}, /* Left */
+    [0xcd] = {0, 4}, /* Right */
+    [0xcf] = {0, 5}, /* End */
+    [0x0d] = {0, 6}, /* KPPLUS */
+    [0xc7] = {1, 0}, /* Home */
+    [0x10] = {1, 1}, /* Q */
+    [0x17] = {1, 2}, /* I */
+    [0x22] = {1, 3}, /* G */
+    [0x2d] = {1, 4}, /* X */
+    [0x1c] = {1, 5}, /* Enter */
+    [0x0c] = {1, 6}, /* KPMINUS */
+    [0xc9] = {2, 0}, /* PageUp */
+    [0x11] = {2, 1}, /* W */
+    [0x18] = {2, 2}, /* O */
+    [0x23] = {2, 3}, /* H */
+    [0x2e] = {2, 4}, /* C */
+    [0x38] = {2, 5}, /* LeftAlt */
+    [0xd1] = {3, 0}, /* PageDown */
+    [0x12] = {3, 1}, /* E */
+    [0x19] = {3, 2}, /* P */
+    [0x24] = {3, 3}, /* J */
+    [0x2f] = {3, 4}, /* V */
+    [0x2a] = {3, 5}, /* LeftShift */
+    [0x01] = {4, 0}, /* Esc */
+    [0x13] = {4, 1}, /* R */
+    [0x1e] = {4, 2}, /* A */
+    [0x25] = {4, 3}, /* K */
+    [0x30] = {4, 4}, /* B */
+    [0x1d] = {4, 5}, /* LeftCtrl */
+    [0x0f] = {5, 0}, /* Tab */
+    [0x14] = {5, 1}, /* T */
+    [0x1f] = {5, 2}, /* S */
+    [0x26] = {5, 3}, /* L */
+    [0x31] = {5, 4}, /* N */
+    [0x39] = {5, 5}, /* Space */
+    [0x3c] = {6, 0}, /* Stop = F2 */
+    [0x15] = {6, 1}, /* Y */
+    [0x20] = {6, 2}, /* D */
+    [0x0e] = {6, 3}, /* Backspace */
+    [0x32] = {6, 4}, /* M */
+    [0x33] = {6, 5}, /* Comma */
+    [0x3d] = {7, 0}, /* Play = F3 */
+    [0x16] = {7, 1}, /* U */
+    [0x21] = {7, 2}, /* F */
+    [0x2c] = {7, 3}, /* Z */
+    [0x27] = {7, 4}, /* Semicolon */
+    [0x34] = {7, 5}, /* Dot */
+};
+
+#define Z2_RAM_SIZE     0x02000000
+#define Z2_FLASH_BASE   0x00000000
+#define Z2_FLASH_SIZE   0x00800000
+
+static struct arm_boot_info z2_binfo = {
+    .loader_start   = PXA2XX_SDRAM_BASE,
+    .ram_size       = Z2_RAM_SIZE,
+};
+
+#define Z2_GPIO_SD_DETECT   96
+#define Z2_GPIO_AC_IN       0
+#define Z2_GPIO_KEY_ON      1
+#define Z2_GPIO_LCD_CS      88
+
+typedef struct {
+    SSISlave ssidev;
+    int32_t selected;
+    int32_t enabled;
+    uint8_t buf[3];
+    uint32_t cur_reg;
+    int pos;
+} ZipitLCD;
+
+static uint32_t zipit_lcd_transfer(SSISlave *dev, uint32_t value)
+{
+    ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev);
+    uint16_t val;
+    if (z->selected) {
+        z->buf[z->pos] = value & 0xff;
+        z->pos++;
+    }
+    if (z->pos == 3) {
+        switch (z->buf[0]) {
+        case 0x74:
+            DPRINTF("%s: reg: 0x%.2x\n", __func__, z->buf[2]);
+            z->cur_reg = z->buf[2];
+            break;
+        case 0x76:
+            val = z->buf[1] << 8 | z->buf[2];
+            DPRINTF("%s: value: 0x%.4x\n", __func__, val);
+            if (z->cur_reg == 0x22 && val == 0x0000) {
+                z->enabled = 1;
+                printf("%s: LCD enabled\n", __func__);
+            } else if (z->cur_reg == 0x10 && val == 0x0000) {
+                z->enabled = 0;
+                printf("%s: LCD disabled\n", __func__);
+            }
+            break;
+        default:
+            DPRINTF("%s: unknown command!\n", __func__);
+            break;
+        }
+        z->pos = 0;
+    }
+    return 0;
+}
+
+static void z2_lcd_cs(void *opaque, int line, int level)
+{
+    ZipitLCD *z2_lcd = opaque;
+    z2_lcd->selected = !level;
+}
+
+static int zipit_lcd_init(SSISlave *dev)
+{
+    ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev);
+    z->selected = 0;
+    z->enabled = 0;
+    z->pos = 0;
+
+    return 0;
+}
+
+static VMStateDescription vmstate_zipit_lcd_state = {
+    .name = "zipit-lcd",
+    .version_id = 2,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 2,
+    .fields = (VMStateField[]) {
+        VMSTATE_SSI_SLAVE(ssidev, ZipitLCD),
+        VMSTATE_INT32(selected, ZipitLCD),
+        VMSTATE_INT32(enabled, ZipitLCD),
+        VMSTATE_BUFFER(buf, ZipitLCD),
+        VMSTATE_UINT32(cur_reg, ZipitLCD),
+        VMSTATE_INT32(pos, ZipitLCD),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static void zipit_lcd_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+
+    k->init = zipit_lcd_init;
+    k->transfer = zipit_lcd_transfer;
+    dc->vmsd = &vmstate_zipit_lcd_state;
+}
+
+static const TypeInfo zipit_lcd_info = {
+    .name          = "zipit-lcd",
+    .parent        = TYPE_SSI_SLAVE,
+    .instance_size = sizeof(ZipitLCD),
+    .class_init    = zipit_lcd_class_init,
+};
+
+typedef struct {
+    I2CSlave i2c;
+    int len;
+    uint8_t buf[3];
+} AER915State;
+
+static int aer915_send(I2CSlave *i2c, uint8_t data)
+{
+    AER915State *s = FROM_I2C_SLAVE(AER915State, i2c);
+    s->buf[s->len] = data;
+    if (s->len++ > 2) {
+        DPRINTF("%s: message too long (%i bytes)\n",
+            __func__, s->len);
+        return 1;
+    }
+
+    if (s->len == 2) {
+        DPRINTF("%s: reg %d value 0x%02x\n", __func__,
+                s->buf[0], s->buf[1]);
+    }
+
+    return 0;
+}
+
+static void aer915_event(I2CSlave *i2c, enum i2c_event event)
+{
+    AER915State *s = FROM_I2C_SLAVE(AER915State, i2c);
+    switch (event) {
+    case I2C_START_SEND:
+        s->len = 0;
+        break;
+    case I2C_START_RECV:
+        if (s->len != 1) {
+            DPRINTF("%s: short message!?\n", __func__);
+        }
+        break;
+    case I2C_FINISH:
+        break;
+    default:
+        break;
+    }
+}
+
+static int aer915_recv(I2CSlave *slave)
+{
+    int retval = 0x00;
+    AER915State *s = FROM_I2C_SLAVE(AER915State, slave);
+
+    switch (s->buf[0]) {
+    /* Return hardcoded battery voltage,
+     * 0xf0 means ~4.1V
+     */
+    case 0x02:
+        retval = 0xf0;
+        break;
+    /* Return 0x00 for other regs,
+     * we don't know what they are for,
+     * anyway they return 0x00 on real hardware.
+     */
+    default:
+        break;
+    }
+
+    return retval;
+}
+
+static int aer915_init(I2CSlave *i2c)
+{
+    /* Nothing to do.  */
+    return 0;
+}
+
+static VMStateDescription vmstate_aer915_state = {
+    .name = "aer915",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_INT32(len, AER915State),
+        VMSTATE_BUFFER(buf, AER915State),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static void aer915_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+    k->init = aer915_init;
+    k->event = aer915_event;
+    k->recv = aer915_recv;
+    k->send = aer915_send;
+    dc->vmsd = &vmstate_aer915_state;
+}
+
+static const TypeInfo aer915_info = {
+    .name          = "aer915",
+    .parent        = TYPE_I2C_SLAVE,
+    .instance_size = sizeof(AER915State),
+    .class_init    = aer915_class_init,
+};
+
+static void z2_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    MemoryRegion *address_space_mem = get_system_memory();
+    uint32_t sector_len = 0x10000;
+    PXA2xxState *mpu;
+    DriveInfo *dinfo;
+    int be;
+    void *z2_lcd;
+    i2c_bus *bus;
+    DeviceState *wm;
+
+    if (!cpu_model) {
+        cpu_model = "pxa270-c5";
+    }
+
+    /* Setup CPU & memory */
+    mpu = pxa270_init(address_space_mem, z2_binfo.ram_size, cpu_model);
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    be = 1;
+#else
+    be = 0;
+#endif
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (!dinfo) {
+        fprintf(stderr, "Flash image must be given with the "
+                "'pflash' parameter\n");
+        exit(1);
+    }
+
+    if (!pflash_cfi01_register(Z2_FLASH_BASE,
+                               NULL, "z2.flash0", Z2_FLASH_SIZE,
+                               dinfo->bdrv, sector_len,
+                               Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0,
+                               be)) {
+        fprintf(stderr, "qemu: Error registering flash memory.\n");
+        exit(1);
+    }
+
+    /* setup keypad */
+    pxa27x_register_keypad(mpu->kp, map, 0x100);
+
+    /* MMC/SD host */
+    pxa2xx_mmci_handlers(mpu->mmc,
+        NULL,
+        qdev_get_gpio_in(mpu->gpio, Z2_GPIO_SD_DETECT));
+
+    type_register_static(&zipit_lcd_info);
+    type_register_static(&aer915_info);
+    z2_lcd = ssi_create_slave(mpu->ssp[1], "zipit-lcd");
+    bus = pxa2xx_i2c_bus(mpu->i2c[0]);
+    i2c_create_slave(bus, "aer915", 0x55);
+    wm = i2c_create_slave(bus, "wm8750", 0x1b);
+    mpu->i2s->opaque = wm;
+    mpu->i2s->codec_out = wm8750_dac_dat;
+    mpu->i2s->codec_in = wm8750_adc_dat;
+    wm8750_data_req_set(wm, mpu->i2s->data_req, mpu->i2s);
+
+    qdev_connect_gpio_out(mpu->gpio, Z2_GPIO_LCD_CS,
+        qemu_allocate_irqs(z2_lcd_cs, z2_lcd, 1)[0]);
+
+    if (kernel_filename) {
+        z2_binfo.kernel_filename = kernel_filename;
+        z2_binfo.kernel_cmdline = kernel_cmdline;
+        z2_binfo.initrd_filename = initrd_filename;
+        z2_binfo.board_id = 0x6dd;
+        arm_load_kernel(mpu->cpu, &z2_binfo);
+    }
+}
+
+static QEMUMachine z2_machine = {
+    .name = "z2",
+    .desc = "Zipit Z2 (PXA27x)",
+    .init = z2_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void z2_machine_init(void)
+{
+    qemu_register_machine(&z2_machine);
+}
+
+machine_init(z2_machine_init);
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
deleted file mode 100644
index 43253fd..0000000
--- a/hw/arm_boot.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * ARM kernel loader.
- *
- * Copyright (c) 2006-2007 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GPL.
- */
-
-#include "config.h"
-#include "hw/hw.h"
-#include "hw/arm-misc.h"
-#include "sysemu/sysemu.h"
-#include "hw/boards.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "sysemu/device_tree.h"
-#include "qemu/config-file.h"
-
-#define KERNEL_ARGS_ADDR 0x100
-#define KERNEL_LOAD_ADDR 0x00010000
-
-/* The worlds second smallest bootloader.  Set r0-r2, then jump to kernel.  */
-static uint32_t bootloader[] = {
-  0xe3a00000, /* mov     r0, #0 */
-  0xe59f1004, /* ldr     r1, [pc, #4] */
-  0xe59f2004, /* ldr     r2, [pc, #4] */
-  0xe59ff004, /* ldr     pc, [pc, #4] */
-  0, /* Board ID */
-  0, /* Address of kernel args.  Set by integratorcp_init.  */
-  0  /* Kernel entry point.  Set by integratorcp_init.  */
-};
-
-/* Handling for secondary CPU boot in a multicore system.
- * Unlike the uniprocessor/primary CPU boot, this is platform
- * dependent. The default code here is based on the secondary
- * CPU boot protocol used on realview/vexpress boards, with
- * some parameterisation to increase its flexibility.
- * QEMU platform models for which this code is not appropriate
- * should override write_secondary_boot and secondary_cpu_reset_hook
- * instead.
- *
- * This code enables the interrupt controllers for the secondary
- * CPUs and then puts all the secondary CPUs into a loop waiting
- * for an interprocessor interrupt and polling a configurable
- * location for the kernel secondary CPU entry point.
- */
-#define DSB_INSN 0xf57ff04f
-#define CP15_DSB_INSN 0xee070f9a /* mcr cp15, 0, r0, c7, c10, 4 */
-
-static uint32_t smpboot[] = {
-  0xe59f2028, /* ldr r2, gic_cpu_if */
-  0xe59f0028, /* ldr r0, startaddr */
-  0xe3a01001, /* mov r1, #1 */
-  0xe5821000, /* str r1, [r2] - set GICC_CTLR.Enable */
-  0xe3a010ff, /* mov r1, #0xff */
-  0xe5821004, /* str r1, [r2, 4] - set GIC_PMR.Priority to 0xff */
-  DSB_INSN,   /* dsb */
-  0xe320f003, /* wfi */
-  0xe5901000, /* ldr     r1, [r0] */
-  0xe1110001, /* tst     r1, r1 */
-  0x0afffffb, /* beq     <wfi> */
-  0xe12fff11, /* bx      r1 */
-  0,          /* gic_cpu_if: base address of GIC CPU interface */
-  0           /* bootreg: Boot register address is held here */
-};
-
-static void default_write_secondary(ARMCPU *cpu,
-                                    const struct arm_boot_info *info)
-{
-    int n;
-    smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
-    smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr;
-    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
-        /* Replace DSB with the pre-v7 DSB if necessary. */
-        if (!arm_feature(&cpu->env, ARM_FEATURE_V7) &&
-            smpboot[n] == DSB_INSN) {
-            smpboot[n] = CP15_DSB_INSN;
-        }
-        smpboot[n] = tswap32(smpboot[n]);
-    }
-    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
-                       info->smp_loader_start);
-}
-
-static void default_reset_secondary(ARMCPU *cpu,
-                                    const struct arm_boot_info *info)
-{
-    CPUARMState *env = &cpu->env;
-
-    stl_phys_notdirty(info->smp_bootreg_addr, 0);
-    env->regs[15] = info->smp_loader_start;
-}
-
-#define WRITE_WORD(p, value) do { \
-    stl_phys_notdirty(p, value);  \
-    p += 4;                       \
-} while (0)
-
-static void set_kernel_args(const struct arm_boot_info *info)
-{
-    int initrd_size = info->initrd_size;
-    hwaddr base = info->loader_start;
-    hwaddr p;
-
-    p = base + KERNEL_ARGS_ADDR;
-    /* ATAG_CORE */
-    WRITE_WORD(p, 5);
-    WRITE_WORD(p, 0x54410001);
-    WRITE_WORD(p, 1);
-    WRITE_WORD(p, 0x1000);
-    WRITE_WORD(p, 0);
-    /* ATAG_MEM */
-    /* TODO: handle multiple chips on one ATAG list */
-    WRITE_WORD(p, 4);
-    WRITE_WORD(p, 0x54410002);
-    WRITE_WORD(p, info->ram_size);
-    WRITE_WORD(p, info->loader_start);
-    if (initrd_size) {
-        /* ATAG_INITRD2 */
-        WRITE_WORD(p, 4);
-        WRITE_WORD(p, 0x54420005);
-        WRITE_WORD(p, info->initrd_start);
-        WRITE_WORD(p, initrd_size);
-    }
-    if (info->kernel_cmdline && *info->kernel_cmdline) {
-        /* ATAG_CMDLINE */
-        int cmdline_size;
-
-        cmdline_size = strlen(info->kernel_cmdline);
-        cpu_physical_memory_write(p + 8, (void *)info->kernel_cmdline,
-                                  cmdline_size + 1);
-        cmdline_size = (cmdline_size >> 2) + 1;
-        WRITE_WORD(p, cmdline_size + 2);
-        WRITE_WORD(p, 0x54410009);
-        p += cmdline_size * 4;
-    }
-    if (info->atag_board) {
-        /* ATAG_BOARD */
-        int atag_board_len;
-        uint8_t atag_board_buf[0x1000];
-
-        atag_board_len = (info->atag_board(info, atag_board_buf) + 3) & ~3;
-        WRITE_WORD(p, (atag_board_len + 8) >> 2);
-        WRITE_WORD(p, 0x414f4d50);
-        cpu_physical_memory_write(p, atag_board_buf, atag_board_len);
-        p += atag_board_len;
-    }
-    /* ATAG_END */
-    WRITE_WORD(p, 0);
-    WRITE_WORD(p, 0);
-}
-
-static void set_kernel_args_old(const struct arm_boot_info *info)
-{
-    hwaddr p;
-    const char *s;
-    int initrd_size = info->initrd_size;
-    hwaddr base = info->loader_start;
-
-    /* see linux/include/asm-arm/setup.h */
-    p = base + KERNEL_ARGS_ADDR;
-    /* page_size */
-    WRITE_WORD(p, 4096);
-    /* nr_pages */
-    WRITE_WORD(p, info->ram_size / 4096);
-    /* ramdisk_size */
-    WRITE_WORD(p, 0);
-#define FLAG_READONLY	1
-#define FLAG_RDLOAD	4
-#define FLAG_RDPROMPT	8
-    /* flags */
-    WRITE_WORD(p, FLAG_READONLY | FLAG_RDLOAD | FLAG_RDPROMPT);
-    /* rootdev */
-    WRITE_WORD(p, (31 << 8) | 0);	/* /dev/mtdblock0 */
-    /* video_num_cols */
-    WRITE_WORD(p, 0);
-    /* video_num_rows */
-    WRITE_WORD(p, 0);
-    /* video_x */
-    WRITE_WORD(p, 0);
-    /* video_y */
-    WRITE_WORD(p, 0);
-    /* memc_control_reg */
-    WRITE_WORD(p, 0);
-    /* unsigned char sounddefault */
-    /* unsigned char adfsdrives */
-    /* unsigned char bytes_per_char_h */
-    /* unsigned char bytes_per_char_v */
-    WRITE_WORD(p, 0);
-    /* pages_in_bank[4] */
-    WRITE_WORD(p, 0);
-    WRITE_WORD(p, 0);
-    WRITE_WORD(p, 0);
-    WRITE_WORD(p, 0);
-    /* pages_in_vram */
-    WRITE_WORD(p, 0);
-    /* initrd_start */
-    if (initrd_size) {
-        WRITE_WORD(p, info->initrd_start);
-    } else {
-        WRITE_WORD(p, 0);
-    }
-    /* initrd_size */
-    WRITE_WORD(p, initrd_size);
-    /* rd_start */
-    WRITE_WORD(p, 0);
-    /* system_rev */
-    WRITE_WORD(p, 0);
-    /* system_serial_low */
-    WRITE_WORD(p, 0);
-    /* system_serial_high */
-    WRITE_WORD(p, 0);
-    /* mem_fclk_21285 */
-    WRITE_WORD(p, 0);
-    /* zero unused fields */
-    while (p < base + KERNEL_ARGS_ADDR + 256 + 1024) {
-        WRITE_WORD(p, 0);
-    }
-    s = info->kernel_cmdline;
-    if (s) {
-        cpu_physical_memory_write(p, (void *)s, strlen(s) + 1);
-    } else {
-        WRITE_WORD(p, 0);
-    }
-}
-
-static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo)
-{
-#ifdef CONFIG_FDT
-    uint32_t *mem_reg_property;
-    uint32_t mem_reg_propsize;
-    void *fdt = NULL;
-    char *filename;
-    int size, rc;
-    uint32_t acells, scells, hival;
-
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, binfo->dtb_filename);
-    if (!filename) {
-        fprintf(stderr, "Couldn't open dtb file %s\n", binfo->dtb_filename);
-        return -1;
-    }
-
-    fdt = load_device_tree(filename, &size);
-    if (!fdt) {
-        fprintf(stderr, "Couldn't open dtb file %s\n", filename);
-        g_free(filename);
-        return -1;
-    }
-    g_free(filename);
-
-    acells = qemu_devtree_getprop_cell(fdt, "/", "#address-cells");
-    scells = qemu_devtree_getprop_cell(fdt, "/", "#size-cells");
-    if (acells == 0 || scells == 0) {
-        fprintf(stderr, "dtb file invalid (#address-cells or #size-cells 0)\n");
-        return -1;
-    }
-
-    mem_reg_propsize = acells + scells;
-    mem_reg_property = g_new0(uint32_t, mem_reg_propsize);
-    mem_reg_property[acells - 1] = cpu_to_be32(binfo->loader_start);
-    hival = cpu_to_be32(binfo->loader_start >> 32);
-    if (acells > 1) {
-        mem_reg_property[acells - 2] = hival;
-    } else if (hival != 0) {
-        fprintf(stderr, "qemu: dtb file not compatible with "
-                "RAM start address > 4GB\n");
-        exit(1);
-    }
-    mem_reg_property[acells + scells - 1] = cpu_to_be32(binfo->ram_size);
-    hival = cpu_to_be32(binfo->ram_size >> 32);
-    if (scells > 1) {
-        mem_reg_property[acells + scells - 2] = hival;
-    } else if (hival != 0) {
-        fprintf(stderr, "qemu: dtb file not compatible with "
-                "RAM size > 4GB\n");
-        exit(1);
-    }
-
-    rc = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
-                              mem_reg_propsize * sizeof(uint32_t));
-    if (rc < 0) {
-        fprintf(stderr, "couldn't set /memory/reg\n");
-    }
-
-    if (binfo->kernel_cmdline && *binfo->kernel_cmdline) {
-        rc = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
-                                          binfo->kernel_cmdline);
-        if (rc < 0) {
-            fprintf(stderr, "couldn't set /chosen/bootargs\n");
-        }
-    }
-
-    if (binfo->initrd_size) {
-        rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
-                binfo->initrd_start);
-        if (rc < 0) {
-            fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
-        }
-
-        rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
-                    binfo->initrd_start + binfo->initrd_size);
-        if (rc < 0) {
-            fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
-        }
-    }
-
-    cpu_physical_memory_write(addr, fdt, size);
-
-    return 0;
-
-#else
-    fprintf(stderr, "Device tree requested, "
-                "but qemu was compiled without fdt support\n");
-    return -1;
-#endif
-}
-
-static void do_cpu_reset(void *opaque)
-{
-    ARMCPU *cpu = opaque;
-    CPUARMState *env = &cpu->env;
-    const struct arm_boot_info *info = env->boot_info;
-
-    cpu_reset(CPU(cpu));
-    if (info) {
-        if (!info->is_linux) {
-            /* Jump to the entry point.  */
-            env->regs[15] = info->entry & 0xfffffffe;
-            env->thumb = info->entry & 1;
-        } else {
-            if (env == first_cpu) {
-                env->regs[15] = info->loader_start;
-                if (!info->dtb_filename) {
-                    if (old_param) {
-                        set_kernel_args_old(info);
-                    } else {
-                        set_kernel_args(info);
-                    }
-                }
-            } else {
-                info->secondary_cpu_reset_hook(cpu, info);
-            }
-        }
-    }
-}
-
-void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
-{
-    CPUARMState *env = &cpu->env;
-    int kernel_size;
-    int initrd_size;
-    int n;
-    int is_linux = 0;
-    uint64_t elf_entry;
-    hwaddr entry;
-    int big_endian;
-    QemuOpts *machine_opts;
-
-    /* Load the kernel.  */
-    if (!info->kernel_filename) {
-        fprintf(stderr, "Kernel image must be specified\n");
-        exit(1);
-    }
-
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        info->dtb_filename = qemu_opt_get(machine_opts, "dtb");
-    } else {
-        info->dtb_filename = NULL;
-    }
-
-    if (!info->secondary_cpu_reset_hook) {
-        info->secondary_cpu_reset_hook = default_reset_secondary;
-    }
-    if (!info->write_secondary_boot) {
-        info->write_secondary_boot = default_write_secondary;
-    }
-
-    if (info->nb_cpus == 0)
-        info->nb_cpus = 1;
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    big_endian = 1;
-#else
-    big_endian = 0;
-#endif
-
-    /* We want to put the initrd far enough into RAM that when the
-     * kernel is uncompressed it will not clobber the initrd. However
-     * on boards without much RAM we must ensure that we still leave
-     * enough room for a decent sized initrd, and on boards with large
-     * amounts of RAM we must avoid the initrd being so far up in RAM
-     * that it is outside lowmem and inaccessible to the kernel.
-     * So for boards with less  than 256MB of RAM we put the initrd
-     * halfway into RAM, and for boards with 256MB of RAM or more we put
-     * the initrd at 128MB.
-     */
-    info->initrd_start = info->loader_start +
-        MIN(info->ram_size / 2, 128 * 1024 * 1024);
-
-    /* Assume that raw images are linux kernels, and ELF images are not.  */
-    kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
-                           NULL, NULL, big_endian, ELF_MACHINE, 1);
-    entry = elf_entry;
-    if (kernel_size < 0) {
-        kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
-                                  &is_linux);
-    }
-    if (kernel_size < 0) {
-        entry = info->loader_start + KERNEL_LOAD_ADDR;
-        kernel_size = load_image_targphys(info->kernel_filename, entry,
-                                          info->ram_size - KERNEL_LOAD_ADDR);
-        is_linux = 1;
-    }
-    if (kernel_size < 0) {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                info->kernel_filename);
-        exit(1);
-    }
-    info->entry = entry;
-    if (is_linux) {
-        if (info->initrd_filename) {
-            initrd_size = load_image_targphys(info->initrd_filename,
-                                              info->initrd_start,
-                                              info->ram_size -
-                                              info->initrd_start);
-            if (initrd_size < 0) {
-                fprintf(stderr, "qemu: could not load initrd '%s'\n",
-                        info->initrd_filename);
-                exit(1);
-            }
-        } else {
-            initrd_size = 0;
-        }
-        info->initrd_size = initrd_size;
-
-        bootloader[4] = info->board_id;
-
-        /* for device tree boot, we pass the DTB directly in r2. Otherwise
-         * we point to the kernel args.
-         */
-        if (info->dtb_filename) {
-            /* Place the DTB after the initrd in memory. Note that some
-             * kernels will trash anything in the 4K page the initrd
-             * ends in, so make sure the DTB isn't caught up in that.
-             */
-            hwaddr dtb_start = QEMU_ALIGN_UP(info->initrd_start + initrd_size,
-                                             4096);
-            if (load_dtb(dtb_start, info)) {
-                exit(1);
-            }
-            bootloader[5] = dtb_start;
-        } else {
-            bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR;
-            if (info->ram_size >= (1ULL << 32)) {
-                fprintf(stderr, "qemu: RAM size must be less than 4GB to boot"
-                        " Linux kernel using ATAGS (try passing a device tree"
-                        " using -dtb)\n");
-                exit(1);
-            }
-        }
-        bootloader[6] = entry;
-        for (n = 0; n < sizeof(bootloader) / 4; n++) {
-            bootloader[n] = tswap32(bootloader[n]);
-        }
-        rom_add_blob_fixed("bootloader", bootloader, sizeof(bootloader),
-                           info->loader_start);
-        if (info->nb_cpus > 1) {
-            info->write_secondary_boot(cpu, info);
-        }
-    }
-    info->is_linux = is_linux;
-
-    for (; env; env = env->next_cpu) {
-        cpu = arm_env_get_cpu(env);
-        env->boot_info = info;
-        qemu_register_reset(do_cpu_reset, cpu);
-    }
-}
diff --git a/hw/arm_pic.c b/hw/arm_pic.c
deleted file mode 100644
index a7ad893..0000000
--- a/hw/arm_pic.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Generic ARM Programmable Interrupt Controller support.
- *
- * Copyright (c) 2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the LGPL
- */
-
-#include "hw/hw.h"
-#include "hw/arm-misc.h"
-
-/* Input 0 is IRQ and input 1 is FIQ.  */
-static void arm_pic_cpu_handler(void *opaque, int irq, int level)
-{
-    ARMCPU *cpu = opaque;
-    CPUARMState *env = &cpu->env;
-
-    switch (irq) {
-    case ARM_PIC_CPU_IRQ:
-        if (level)
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
-        else
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-        break;
-    case ARM_PIC_CPU_FIQ:
-        if (level)
-            cpu_interrupt(env, CPU_INTERRUPT_FIQ);
-        else
-            cpu_reset_interrupt(env, CPU_INTERRUPT_FIQ);
-        break;
-    default:
-        hw_error("arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
-    }
-}
-
-qemu_irq *arm_pic_init_cpu(ARMCPU *cpu)
-{
-    return qemu_allocate_irqs(arm_pic_cpu_handler, cpu, 2);
-}
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
deleted file mode 100644
index eccd423..0000000
--- a/hw/axis_dev88.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * QEMU model for the AXIS devboard 88.
- *
- * Copyright (c) 2009 Edgar E. Iglesias, Axis Communications AB.
- *
- * 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/sysbus.h"
-#include "net/net.h"
-#include "hw/flash.h"
-#include "hw/boards.h"
-#include "hw/etraxfs.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "hw/cris-boot.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-#define D(x)
-#define DNAND(x)
-
-struct nand_state_t
-{
-    DeviceState *nand;
-    MemoryRegion iomem;
-    unsigned int rdy:1;
-    unsigned int ale:1;
-    unsigned int cle:1;
-    unsigned int ce:1;
-};
-
-static struct nand_state_t nand_state;
-static uint64_t nand_read(void *opaque, hwaddr addr, unsigned size)
-{
-    struct nand_state_t *s = opaque;
-    uint32_t r;
-    int rdy;
-
-    r = nand_getio(s->nand);
-    nand_getpins(s->nand, &rdy);
-    s->rdy = rdy;
-
-    DNAND(printf("%s addr=%x r=%x\n", __func__, addr, r));
-    return r;
-}
-
-static void
-nand_write(void *opaque, hwaddr addr, uint64_t value,
-           unsigned size)
-{
-    struct nand_state_t *s = opaque;
-    int rdy;
-
-    DNAND(printf("%s addr=%x v=%x\n", __func__, addr, (unsigned)value));
-    nand_setpins(s->nand, s->cle, s->ale, s->ce, 1, 0);
-    nand_setio(s->nand, value);
-    nand_getpins(s->nand, &rdy);
-    s->rdy = rdy;
-}
-
-static const MemoryRegionOps nand_ops = {
-    .read = nand_read,
-    .write = nand_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-struct tempsensor_t
-{
-    unsigned int shiftreg;
-    unsigned int count;
-    enum {
-        ST_OUT, ST_IN, ST_Z
-    } state;
-
-    uint16_t regs[3];
-};
-
-static void tempsensor_clkedge(struct tempsensor_t *s,
-                               unsigned int clk, unsigned int data_in)
-{
-    D(printf("%s clk=%d state=%d sr=%x\n", __func__,
-             clk, s->state, s->shiftreg));
-    if (s->count == 0) {
-        s->count = 16;
-        s->state = ST_OUT;
-    }
-    switch (s->state) {
-        case ST_OUT:
-            /* Output reg is clocked at negedge.  */
-            if (!clk) {
-                s->count--;
-                s->shiftreg <<= 1;
-                if (s->count == 0) {
-                    s->shiftreg = 0;
-                    s->state = ST_IN;
-                    s->count = 16;
-                }
-            }
-            break;
-        case ST_Z:
-            if (clk) {
-                s->count--;
-                if (s->count == 0) {
-                    s->shiftreg = 0;
-                    s->state = ST_OUT;
-                    s->count = 16;
-                }
-            }
-            break;
-        case ST_IN:
-            /* Indata is sampled at posedge.  */
-            if (clk) {
-                s->count--;
-                s->shiftreg <<= 1;
-                s->shiftreg |= data_in & 1;
-                if (s->count == 0) {
-                    D(printf("%s cfgreg=%x\n", __func__, s->shiftreg));
-                    s->regs[0] = s->shiftreg;
-                    s->state = ST_OUT;
-                    s->count = 16;
-
-                    if ((s->regs[0] & 0xff) == 0) {
-                        /* 25 degrees celcius.  */
-                        s->shiftreg = 0x0b9f;
-                    } else if ((s->regs[0] & 0xff) == 0xff) {
-                        /* Sensor ID, 0x8100 LM70.  */
-                        s->shiftreg = 0x8100;
-                    } else
-                        printf("Invalid tempsens state %x\n", s->regs[0]);
-                }
-            }
-            break;
-    }
-}
-
-
-#define RW_PA_DOUT    0x00
-#define R_PA_DIN      0x01
-#define RW_PA_OE      0x02
-#define RW_PD_DOUT    0x10
-#define R_PD_DIN      0x11
-#define RW_PD_OE      0x12
-
-static struct gpio_state_t
-{
-    MemoryRegion iomem;
-    struct nand_state_t *nand;
-    struct tempsensor_t tempsensor;
-    uint32_t regs[0x5c / 4];
-} gpio_state;
-
-static uint64_t gpio_read(void *opaque, hwaddr addr, unsigned size)
-{
-    struct gpio_state_t *s = opaque;
-    uint32_t r = 0;
-
-    addr >>= 2;
-    switch (addr)
-    {
-        case R_PA_DIN:
-            r = s->regs[RW_PA_DOUT] & s->regs[RW_PA_OE];
-
-            /* Encode pins from the nand.  */
-            r |= s->nand->rdy << 7;
-            break;
-        case R_PD_DIN:
-            r = s->regs[RW_PD_DOUT] & s->regs[RW_PD_OE];
-
-            /* Encode temp sensor pins.  */
-            r |= (!!(s->tempsensor.shiftreg & 0x10000)) << 4;
-            break;
-
-        default:
-            r = s->regs[addr];
-            break;
-    }
-    return r;
-    D(printf("%s %x=%x\n", __func__, addr, r));
-}
-
-static void gpio_write(void *opaque, hwaddr addr, uint64_t value,
-                       unsigned size)
-{
-    struct gpio_state_t *s = opaque;
-    D(printf("%s %x=%x\n", __func__, addr, (unsigned)value));
-
-    addr >>= 2;
-    switch (addr)
-    {
-        case RW_PA_DOUT:
-            /* Decode nand pins.  */
-            s->nand->ale = !!(value & (1 << 6));
-            s->nand->cle = !!(value & (1 << 5));
-            s->nand->ce  = !!(value & (1 << 4));
-
-            s->regs[addr] = value;
-            break;
-
-        case RW_PD_DOUT:
-            /* Temp sensor clk.  */
-            if ((s->regs[addr] ^ value) & 2)
-                tempsensor_clkedge(&s->tempsensor, !!(value & 2),
-                                   !!(value & 16));
-            s->regs[addr] = value;
-            break;
-
-        default:
-            s->regs[addr] = value;
-            break;
-    }
-}
-
-static const MemoryRegionOps gpio_ops = {
-    .read = gpio_read,
-    .write = gpio_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-    .valid = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-};
-
-#define INTMEM_SIZE (128 * 1024)
-
-static struct cris_load_info li;
-
-static
-void axisdev88_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    CRISCPU *cpu;
-    CPUCRISState *env;
-    DeviceState *dev;
-    SysBusDevice *s;
-    DriveInfo *nand;
-    qemu_irq irq[30], nmi[2], *cpu_irq;
-    void *etraxfs_dmac;
-    struct etraxfs_dma_client *dma_eth;
-    int i;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
-    MemoryRegion *phys_intmem = g_new(MemoryRegion, 1);
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-        cpu_model = "crisv32";
-    }
-    cpu = cpu_cris_init(cpu_model);
-    env = &cpu->env;
-
-    /* allocate RAM */
-    memory_region_init_ram(phys_ram, "axisdev88.ram", ram_size);
-    vmstate_register_ram_global(phys_ram);
-    memory_region_add_subregion(address_space_mem, 0x40000000, phys_ram);
-
-    /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the 
-       internal memory.  */
-    memory_region_init_ram(phys_intmem, "axisdev88.chipram", INTMEM_SIZE);
-    vmstate_register_ram_global(phys_intmem);
-    memory_region_add_subregion(address_space_mem, 0x38000000, phys_intmem);
-
-      /* Attach a NAND flash to CS1.  */
-    nand = drive_get(IF_MTD, 0, 0);
-    nand_state.nand = nand_init(nand ? nand->bdrv : NULL,
-                                NAND_MFR_STMICRO, 0x39);
-    memory_region_init_io(&nand_state.iomem, &nand_ops, &nand_state,
-                          "nand", 0x05000000);
-    memory_region_add_subregion(address_space_mem, 0x10000000,
-                                &nand_state.iomem);
-
-    gpio_state.nand = &nand_state;
-    memory_region_init_io(&gpio_state.iomem, &gpio_ops, &gpio_state,
-                          "gpio", 0x5c);
-    memory_region_add_subregion(address_space_mem, 0x3001a000,
-                                &gpio_state.iomem);
-
-
-    cpu_irq = cris_pic_init_cpu(env);
-    dev = qdev_create(NULL, "etraxfs,pic");
-    /* FIXME: Is there a proper way to signal vectors to the CPU core?  */
-    qdev_prop_set_ptr(dev, "interrupt_vector", &env->interrupt_vector);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(s, 0, 0x3001c000);
-    sysbus_connect_irq(s, 0, cpu_irq[0]);
-    sysbus_connect_irq(s, 1, cpu_irq[1]);
-    for (i = 0; i < 30; i++) {
-        irq[i] = qdev_get_gpio_in(dev, i);
-    }
-    nmi[0] = qdev_get_gpio_in(dev, 30);
-    nmi[1] = qdev_get_gpio_in(dev, 31);
-
-    etraxfs_dmac = etraxfs_dmac_init(0x30000000, 10);
-    for (i = 0; i < 10; i++) {
-        /* On ETRAX, odd numbered channels are inputs.  */
-        etraxfs_dmac_connect(etraxfs_dmac, i, irq + 7 + i, i & 1);
-    }
-
-    /* Add the two ethernet blocks.  */
-    dma_eth = g_malloc0(sizeof dma_eth[0] * 4); /* Allocate 4 channels.  */
-    etraxfs_eth_init(&nd_table[0], 0x30034000, 1, &dma_eth[0], &dma_eth[1]);
-    if (nb_nics > 1) {
-        etraxfs_eth_init(&nd_table[1], 0x30036000, 2, &dma_eth[2], &dma_eth[3]);
-    }
-
-    /* The DMA Connector block is missing, hardwire things for now.  */
-    etraxfs_dmac_connect_client(etraxfs_dmac, 0, &dma_eth[0]);
-    etraxfs_dmac_connect_client(etraxfs_dmac, 1, &dma_eth[1]);
-    if (nb_nics > 1) {
-        etraxfs_dmac_connect_client(etraxfs_dmac, 6, &dma_eth[2]);
-        etraxfs_dmac_connect_client(etraxfs_dmac, 7, &dma_eth[3]);
-    }
-
-    /* 2 timers.  */
-    sysbus_create_varargs("etraxfs,timer", 0x3001e000, irq[0x1b], nmi[1], NULL);
-    sysbus_create_varargs("etraxfs,timer", 0x3005e000, irq[0x1b], nmi[1], NULL);
-
-    for (i = 0; i < 4; i++) {
-        sysbus_create_simple("etraxfs,serial", 0x30026000 + i * 0x2000,
-                             irq[0x14 + i]);
-    }
-
-    if (!kernel_filename) {
-        fprintf(stderr, "Kernel image must be specified\n");
-        exit(1);
-    }
-
-    li.image_filename = kernel_filename;
-    li.cmdline = kernel_cmdline;
-    cris_load_image(cpu, &li);
-}
-
-static QEMUMachine axisdev88_machine = {
-    .name = "axis-dev88",
-    .desc = "AXIS devboard 88",
-    .init = axisdev88_init,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void axisdev88_machine_init(void)
-{
-    qemu_register_machine(&axisdev88_machine);
-}
-
-machine_init(axisdev88_machine_init);
diff --git a/hw/collie.c b/hw/collie.c
deleted file mode 100644
index 17fddc8..0000000
--- a/hw/collie.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * SA-1110-based Sharp Zaurus SL-5500 platform.
- *
- * Copyright (C) 2011 Dmitry Eremin-Solenikov
- *
- * This code is licensed under GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-#include "hw/hw.h"
-#include "hw/sysbus.h"
-#include "hw/boards.h"
-#include "hw/devices.h"
-#include "hw/strongarm.h"
-#include "hw/arm-misc.h"
-#include "hw/flash.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-static struct arm_boot_info collie_binfo = {
-    .loader_start = SA_SDCS0,
-    .ram_size = 0x20000000,
-};
-
-static void collie_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    StrongARMState *s;
-    DriveInfo *dinfo;
-    MemoryRegion *sysmem = get_system_memory();
-
-    if (!cpu_model) {
-        cpu_model = "sa1110";
-    }
-
-    s = sa1110_init(sysmem, collie_binfo.ram_size, cpu_model);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi01_register(SA_CS0, NULL, "collie.fl1", 0x02000000,
-                    dinfo ? dinfo->bdrv : NULL, (64 * 1024),
-                    512, 4, 0x00, 0x00, 0x00, 0x00, 0);
-
-    dinfo = drive_get(IF_PFLASH, 0, 1);
-    pflash_cfi01_register(SA_CS1, NULL, "collie.fl2", 0x02000000,
-                    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->cpu, &collie_binfo);
-}
-
-static QEMUMachine collie_machine = {
-    .name = "collie",
-    .desc = "Collie PDA (SA-1110)",
-    .init = collie_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void collie_machine_init(void)
-{
-    qemu_register_machine(&collie_machine);
-}
-
-machine_init(collie_machine_init)
diff --git a/hw/cris-boot.c b/hw/cris-boot.c
deleted file mode 100644
index c330e22..0000000
--- a/hw/cris-boot.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * CRIS image loading.
- *
- * Copyright (c) 2010 Edgar E. Iglesias, Axis Communications AB.
- *
- * 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/hw.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "hw/cris-boot.h"
-
-static void main_cpu_reset(void *opaque)
-{
-    CRISCPU *cpu = opaque;
-    CPUCRISState *env = &cpu->env;
-    struct cris_load_info *li;
-
-    li = env->load_info;
-
-    cpu_reset(CPU(cpu));
-
-    if (!li) {
-        /* nothing more to do.  */
-        return;
-    }
-
-    env->pc = li->entry;
-
-    if (li->image_filename) {
-        env->regs[8] = 0x56902387; /* RAM boot magic.  */
-        env->regs[9] = 0x40004000 + li->image_size;
-    }
-
-    if (li->cmdline) {
-        /* Let the kernel know we are modifying the cmdline.  */
-        env->regs[10] = 0x87109563;
-        env->regs[11] = 0x40000000;
-    }
-}
-
-static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
-{
-    return addr - 0x80000000LL;
-}
-
-void cris_load_image(CRISCPU *cpu, struct cris_load_info *li)
-{
-    CPUCRISState *env = &cpu->env;
-    uint64_t entry, high;
-    int kcmdline_len;
-    int image_size;
-
-    env->load_info = li;
-    /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis 
-       devboard SDK.  */
-    image_size = load_elf(li->image_filename, translate_kernel_address, NULL,
-                          &entry, NULL, &high, 0, ELF_MACHINE, 0);
-    li->entry = entry;
-    if (image_size < 0) {
-        /* Takes a kimage from the axis devboard SDK.  */
-        image_size = load_image_targphys(li->image_filename, 0x40004000,
-                                         ram_size);
-        li->entry = 0x40004000;
-    }
-
-    if (image_size < 0) {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                li->image_filename);
-        exit(1);
-    }
-
-    if (li->cmdline && (kcmdline_len = strlen(li->cmdline))) {
-        if (kcmdline_len > 256) {
-            fprintf(stderr, "Too long CRIS kernel cmdline (max 256)\n");
-            exit(1);
-        }
-        pstrcpy_targphys("cmdline", 0x40000000, 256, li->cmdline);
-    }
-    qemu_register_reset(main_cpu_reset, cpu);
-}
diff --git a/hw/cris/Makefile.objs b/hw/cris/Makefile.objs
index aa9298a..a94c624 100644
--- a/hw/cris/Makefile.objs
+++ b/hw/cris/Makefile.objs
@@ -1,8 +1,3 @@
-# Boards
-obj-y = cris_pic_cpu.o
-obj-y += cris-boot.o
-obj-y += axis_dev88.o
-
 # IO blocks
 obj-y += etraxfs_dma.o
 obj-y += etraxfs_pic.o
@@ -11,3 +6,8 @@ obj-y += etraxfs_timer.o
 obj-y += etraxfs_ser.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+# Boards
+obj-y += pic_cpu.o
+obj-y += boot.o
+obj-y += axis_dev88.o
diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c
new file mode 100644
index 0000000..eccd423
--- /dev/null
+++ b/hw/cris/axis_dev88.c
@@ -0,0 +1,366 @@
+/*
+ * QEMU model for the AXIS devboard 88.
+ *
+ * Copyright (c) 2009 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * 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/sysbus.h"
+#include "net/net.h"
+#include "hw/flash.h"
+#include "hw/boards.h"
+#include "hw/etraxfs.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "hw/cris-boot.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+#define D(x)
+#define DNAND(x)
+
+struct nand_state_t
+{
+    DeviceState *nand;
+    MemoryRegion iomem;
+    unsigned int rdy:1;
+    unsigned int ale:1;
+    unsigned int cle:1;
+    unsigned int ce:1;
+};
+
+static struct nand_state_t nand_state;
+static uint64_t nand_read(void *opaque, hwaddr addr, unsigned size)
+{
+    struct nand_state_t *s = opaque;
+    uint32_t r;
+    int rdy;
+
+    r = nand_getio(s->nand);
+    nand_getpins(s->nand, &rdy);
+    s->rdy = rdy;
+
+    DNAND(printf("%s addr=%x r=%x\n", __func__, addr, r));
+    return r;
+}
+
+static void
+nand_write(void *opaque, hwaddr addr, uint64_t value,
+           unsigned size)
+{
+    struct nand_state_t *s = opaque;
+    int rdy;
+
+    DNAND(printf("%s addr=%x v=%x\n", __func__, addr, (unsigned)value));
+    nand_setpins(s->nand, s->cle, s->ale, s->ce, 1, 0);
+    nand_setio(s->nand, value);
+    nand_getpins(s->nand, &rdy);
+    s->rdy = rdy;
+}
+
+static const MemoryRegionOps nand_ops = {
+    .read = nand_read,
+    .write = nand_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+struct tempsensor_t
+{
+    unsigned int shiftreg;
+    unsigned int count;
+    enum {
+        ST_OUT, ST_IN, ST_Z
+    } state;
+
+    uint16_t regs[3];
+};
+
+static void tempsensor_clkedge(struct tempsensor_t *s,
+                               unsigned int clk, unsigned int data_in)
+{
+    D(printf("%s clk=%d state=%d sr=%x\n", __func__,
+             clk, s->state, s->shiftreg));
+    if (s->count == 0) {
+        s->count = 16;
+        s->state = ST_OUT;
+    }
+    switch (s->state) {
+        case ST_OUT:
+            /* Output reg is clocked at negedge.  */
+            if (!clk) {
+                s->count--;
+                s->shiftreg <<= 1;
+                if (s->count == 0) {
+                    s->shiftreg = 0;
+                    s->state = ST_IN;
+                    s->count = 16;
+                }
+            }
+            break;
+        case ST_Z:
+            if (clk) {
+                s->count--;
+                if (s->count == 0) {
+                    s->shiftreg = 0;
+                    s->state = ST_OUT;
+                    s->count = 16;
+                }
+            }
+            break;
+        case ST_IN:
+            /* Indata is sampled at posedge.  */
+            if (clk) {
+                s->count--;
+                s->shiftreg <<= 1;
+                s->shiftreg |= data_in & 1;
+                if (s->count == 0) {
+                    D(printf("%s cfgreg=%x\n", __func__, s->shiftreg));
+                    s->regs[0] = s->shiftreg;
+                    s->state = ST_OUT;
+                    s->count = 16;
+
+                    if ((s->regs[0] & 0xff) == 0) {
+                        /* 25 degrees celcius.  */
+                        s->shiftreg = 0x0b9f;
+                    } else if ((s->regs[0] & 0xff) == 0xff) {
+                        /* Sensor ID, 0x8100 LM70.  */
+                        s->shiftreg = 0x8100;
+                    } else
+                        printf("Invalid tempsens state %x\n", s->regs[0]);
+                }
+            }
+            break;
+    }
+}
+
+
+#define RW_PA_DOUT    0x00
+#define R_PA_DIN      0x01
+#define RW_PA_OE      0x02
+#define RW_PD_DOUT    0x10
+#define R_PD_DIN      0x11
+#define RW_PD_OE      0x12
+
+static struct gpio_state_t
+{
+    MemoryRegion iomem;
+    struct nand_state_t *nand;
+    struct tempsensor_t tempsensor;
+    uint32_t regs[0x5c / 4];
+} gpio_state;
+
+static uint64_t gpio_read(void *opaque, hwaddr addr, unsigned size)
+{
+    struct gpio_state_t *s = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    switch (addr)
+    {
+        case R_PA_DIN:
+            r = s->regs[RW_PA_DOUT] & s->regs[RW_PA_OE];
+
+            /* Encode pins from the nand.  */
+            r |= s->nand->rdy << 7;
+            break;
+        case R_PD_DIN:
+            r = s->regs[RW_PD_DOUT] & s->regs[RW_PD_OE];
+
+            /* Encode temp sensor pins.  */
+            r |= (!!(s->tempsensor.shiftreg & 0x10000)) << 4;
+            break;
+
+        default:
+            r = s->regs[addr];
+            break;
+    }
+    return r;
+    D(printf("%s %x=%x\n", __func__, addr, r));
+}
+
+static void gpio_write(void *opaque, hwaddr addr, uint64_t value,
+                       unsigned size)
+{
+    struct gpio_state_t *s = opaque;
+    D(printf("%s %x=%x\n", __func__, addr, (unsigned)value));
+
+    addr >>= 2;
+    switch (addr)
+    {
+        case RW_PA_DOUT:
+            /* Decode nand pins.  */
+            s->nand->ale = !!(value & (1 << 6));
+            s->nand->cle = !!(value & (1 << 5));
+            s->nand->ce  = !!(value & (1 << 4));
+
+            s->regs[addr] = value;
+            break;
+
+        case RW_PD_DOUT:
+            /* Temp sensor clk.  */
+            if ((s->regs[addr] ^ value) & 2)
+                tempsensor_clkedge(&s->tempsensor, !!(value & 2),
+                                   !!(value & 16));
+            s->regs[addr] = value;
+            break;
+
+        default:
+            s->regs[addr] = value;
+            break;
+    }
+}
+
+static const MemoryRegionOps gpio_ops = {
+    .read = gpio_read,
+    .write = gpio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+#define INTMEM_SIZE (128 * 1024)
+
+static struct cris_load_info li;
+
+static
+void axisdev88_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    CRISCPU *cpu;
+    CPUCRISState *env;
+    DeviceState *dev;
+    SysBusDevice *s;
+    DriveInfo *nand;
+    qemu_irq irq[30], nmi[2], *cpu_irq;
+    void *etraxfs_dmac;
+    struct etraxfs_dma_client *dma_eth;
+    int i;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
+    MemoryRegion *phys_intmem = g_new(MemoryRegion, 1);
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+        cpu_model = "crisv32";
+    }
+    cpu = cpu_cris_init(cpu_model);
+    env = &cpu->env;
+
+    /* allocate RAM */
+    memory_region_init_ram(phys_ram, "axisdev88.ram", ram_size);
+    vmstate_register_ram_global(phys_ram);
+    memory_region_add_subregion(address_space_mem, 0x40000000, phys_ram);
+
+    /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the 
+       internal memory.  */
+    memory_region_init_ram(phys_intmem, "axisdev88.chipram", INTMEM_SIZE);
+    vmstate_register_ram_global(phys_intmem);
+    memory_region_add_subregion(address_space_mem, 0x38000000, phys_intmem);
+
+      /* Attach a NAND flash to CS1.  */
+    nand = drive_get(IF_MTD, 0, 0);
+    nand_state.nand = nand_init(nand ? nand->bdrv : NULL,
+                                NAND_MFR_STMICRO, 0x39);
+    memory_region_init_io(&nand_state.iomem, &nand_ops, &nand_state,
+                          "nand", 0x05000000);
+    memory_region_add_subregion(address_space_mem, 0x10000000,
+                                &nand_state.iomem);
+
+    gpio_state.nand = &nand_state;
+    memory_region_init_io(&gpio_state.iomem, &gpio_ops, &gpio_state,
+                          "gpio", 0x5c);
+    memory_region_add_subregion(address_space_mem, 0x3001a000,
+                                &gpio_state.iomem);
+
+
+    cpu_irq = cris_pic_init_cpu(env);
+    dev = qdev_create(NULL, "etraxfs,pic");
+    /* FIXME: Is there a proper way to signal vectors to the CPU core?  */
+    qdev_prop_set_ptr(dev, "interrupt_vector", &env->interrupt_vector);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(s, 0, 0x3001c000);
+    sysbus_connect_irq(s, 0, cpu_irq[0]);
+    sysbus_connect_irq(s, 1, cpu_irq[1]);
+    for (i = 0; i < 30; i++) {
+        irq[i] = qdev_get_gpio_in(dev, i);
+    }
+    nmi[0] = qdev_get_gpio_in(dev, 30);
+    nmi[1] = qdev_get_gpio_in(dev, 31);
+
+    etraxfs_dmac = etraxfs_dmac_init(0x30000000, 10);
+    for (i = 0; i < 10; i++) {
+        /* On ETRAX, odd numbered channels are inputs.  */
+        etraxfs_dmac_connect(etraxfs_dmac, i, irq + 7 + i, i & 1);
+    }
+
+    /* Add the two ethernet blocks.  */
+    dma_eth = g_malloc0(sizeof dma_eth[0] * 4); /* Allocate 4 channels.  */
+    etraxfs_eth_init(&nd_table[0], 0x30034000, 1, &dma_eth[0], &dma_eth[1]);
+    if (nb_nics > 1) {
+        etraxfs_eth_init(&nd_table[1], 0x30036000, 2, &dma_eth[2], &dma_eth[3]);
+    }
+
+    /* The DMA Connector block is missing, hardwire things for now.  */
+    etraxfs_dmac_connect_client(etraxfs_dmac, 0, &dma_eth[0]);
+    etraxfs_dmac_connect_client(etraxfs_dmac, 1, &dma_eth[1]);
+    if (nb_nics > 1) {
+        etraxfs_dmac_connect_client(etraxfs_dmac, 6, &dma_eth[2]);
+        etraxfs_dmac_connect_client(etraxfs_dmac, 7, &dma_eth[3]);
+    }
+
+    /* 2 timers.  */
+    sysbus_create_varargs("etraxfs,timer", 0x3001e000, irq[0x1b], nmi[1], NULL);
+    sysbus_create_varargs("etraxfs,timer", 0x3005e000, irq[0x1b], nmi[1], NULL);
+
+    for (i = 0; i < 4; i++) {
+        sysbus_create_simple("etraxfs,serial", 0x30026000 + i * 0x2000,
+                             irq[0x14 + i]);
+    }
+
+    if (!kernel_filename) {
+        fprintf(stderr, "Kernel image must be specified\n");
+        exit(1);
+    }
+
+    li.image_filename = kernel_filename;
+    li.cmdline = kernel_cmdline;
+    cris_load_image(cpu, &li);
+}
+
+static QEMUMachine axisdev88_machine = {
+    .name = "axis-dev88",
+    .desc = "AXIS devboard 88",
+    .init = axisdev88_init,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void axisdev88_machine_init(void)
+{
+    qemu_register_machine(&axisdev88_machine);
+}
+
+machine_init(axisdev88_machine_init);
diff --git a/hw/cris/boot.c b/hw/cris/boot.c
new file mode 100644
index 0000000..c330e22
--- /dev/null
+++ b/hw/cris/boot.c
@@ -0,0 +1,98 @@
+/*
+ * CRIS image loading.
+ *
+ * Copyright (c) 2010 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * 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/hw.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "hw/cris-boot.h"
+
+static void main_cpu_reset(void *opaque)
+{
+    CRISCPU *cpu = opaque;
+    CPUCRISState *env = &cpu->env;
+    struct cris_load_info *li;
+
+    li = env->load_info;
+
+    cpu_reset(CPU(cpu));
+
+    if (!li) {
+        /* nothing more to do.  */
+        return;
+    }
+
+    env->pc = li->entry;
+
+    if (li->image_filename) {
+        env->regs[8] = 0x56902387; /* RAM boot magic.  */
+        env->regs[9] = 0x40004000 + li->image_size;
+    }
+
+    if (li->cmdline) {
+        /* Let the kernel know we are modifying the cmdline.  */
+        env->regs[10] = 0x87109563;
+        env->regs[11] = 0x40000000;
+    }
+}
+
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+    return addr - 0x80000000LL;
+}
+
+void cris_load_image(CRISCPU *cpu, struct cris_load_info *li)
+{
+    CPUCRISState *env = &cpu->env;
+    uint64_t entry, high;
+    int kcmdline_len;
+    int image_size;
+
+    env->load_info = li;
+    /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis 
+       devboard SDK.  */
+    image_size = load_elf(li->image_filename, translate_kernel_address, NULL,
+                          &entry, NULL, &high, 0, ELF_MACHINE, 0);
+    li->entry = entry;
+    if (image_size < 0) {
+        /* Takes a kimage from the axis devboard SDK.  */
+        image_size = load_image_targphys(li->image_filename, 0x40004000,
+                                         ram_size);
+        li->entry = 0x40004000;
+    }
+
+    if (image_size < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                li->image_filename);
+        exit(1);
+    }
+
+    if (li->cmdline && (kcmdline_len = strlen(li->cmdline))) {
+        if (kcmdline_len > 256) {
+            fprintf(stderr, "Too long CRIS kernel cmdline (max 256)\n");
+            exit(1);
+        }
+        pstrcpy_targphys("cmdline", 0x40000000, 256, li->cmdline);
+    }
+    qemu_register_reset(main_cpu_reset, cpu);
+}
diff --git a/hw/cris/pic_cpu.c b/hw/cris/pic_cpu.c
new file mode 100644
index 0000000..7f50471
--- /dev/null
+++ b/hw/cris/pic_cpu.c
@@ -0,0 +1,45 @@
+/*
+ * QEMU CRIS CPU interrupt wrapper logic.
+ *
+ * Copyright (c) 2009 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * 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/sysbus.h"
+#include "hw/hw.h"
+#include "hw/etraxfs.h"
+
+#define D(x)
+
+static void cris_pic_cpu_handler(void *opaque, int irq, int level)
+{
+    CPUCRISState *env = (CPUCRISState *)opaque;
+    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
+
+    if (level)
+        cpu_interrupt(env, type);
+    else
+        cpu_reset_interrupt(env, type);
+}
+
+qemu_irq *cris_pic_init_cpu(CPUCRISState *env)
+{
+    return qemu_allocate_irqs(cris_pic_cpu_handler, env, 2);
+}
diff --git a/hw/cris_pic_cpu.c b/hw/cris_pic_cpu.c
deleted file mode 100644
index 7f50471..0000000
--- a/hw/cris_pic_cpu.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * QEMU CRIS CPU interrupt wrapper logic.
- *
- * Copyright (c) 2009 Edgar E. Iglesias, Axis Communications AB.
- *
- * 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/sysbus.h"
-#include "hw/hw.h"
-#include "hw/etraxfs.h"
-
-#define D(x)
-
-static void cris_pic_cpu_handler(void *opaque, int irq, int level)
-{
-    CPUCRISState *env = (CPUCRISState *)opaque;
-    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
-
-    if (level)
-        cpu_interrupt(env, type);
-    else
-        cpu_reset_interrupt(env, type);
-}
-
-qemu_irq *cris_pic_init_cpu(CPUCRISState *env)
-{
-    return qemu_allocate_irqs(cris_pic_cpu_handler, env, 2);
-}
diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c
deleted file mode 100644
index 544d56b..0000000
--- a/hw/dummy_m68k.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Dummy board with just RAM and CPU for use as an ISS.
- *
- * Copyright (c) 2007 CodeSourcery.
- *
- * This code is licensed under the GPL
- */
-
-#include "hw/hw.h"
-#include "hw/boards.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "exec/address-spaces.h"
-
-#define KERNEL_LOAD_ADDR 0x10000
-
-/* Board init.  */
-
-static void dummy_m68k_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    CPUM68KState *env;
-    MemoryRegion *address_space_mem =  get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    int kernel_size;
-    uint64_t elf_entry;
-    hwaddr entry;
-
-    if (!cpu_model)
-        cpu_model = "cfv4e";
-    env = cpu_init(cpu_model);
-    if (!env) {
-        fprintf(stderr, "Unable to find m68k CPU definition\n");
-        exit(1);
-    }
-
-    /* Initialize CPU registers.  */
-    env->vbr = 0;
-
-    /* RAM at address zero */
-    memory_region_init_ram(ram, "dummy_m68k.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(address_space_mem, 0, ram);
-
-    /* Load kernel.  */
-    if (kernel_filename) {
-        kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                               NULL, NULL, 1, ELF_MACHINE, 0);
-        entry = elf_entry;
-        if (kernel_size < 0) {
-            kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
-        }
-        if (kernel_size < 0) {
-            kernel_size = load_image_targphys(kernel_filename,
-                                              KERNEL_LOAD_ADDR,
-                                              ram_size - KERNEL_LOAD_ADDR);
-            entry = KERNEL_LOAD_ADDR;
-        }
-        if (kernel_size < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                    kernel_filename);
-            exit(1);
-        }
-    } else {
-        entry = 0;
-    }
-    env->pc = entry;
-}
-
-static QEMUMachine dummy_m68k_machine = {
-    .name = "dummy",
-    .desc = "Dummy board",
-    .init = dummy_m68k_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void dummy_m68k_machine_init(void)
-{
-    qemu_register_machine(&dummy_m68k_machine);
-}
-
-machine_init(dummy_m68k_machine_init);
diff --git a/hw/exynos4_boards.c b/hw/exynos4_boards.c
deleted file mode 100644
index 473da34..0000000
--- a/hw/exynos4_boards.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- *  Samsung exynos4 SoC based boards emulation
- *
- *  Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *    Maksim Kozlov <m.kozlov at samsung.com>
- *    Evgeny Voevodin <e.voevodin at samsung.com>
- *    Igor Mitsyanko  <i.mitsyanko at samsung.com>
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the
- *  Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "sysemu/sysemu.h"
-#include "hw/sysbus.h"
-#include "net/net.h"
-#include "hw/arm-misc.h"
-#include "exec/address-spaces.h"
-#include "hw/exynos4210.h"
-#include "hw/boards.h"
-
-#undef DEBUG
-
-//#define DEBUG
-
-#ifdef DEBUG
-    #undef PRINT_DEBUG
-    #define  PRINT_DEBUG(fmt, args...) \
-        do { \
-            fprintf(stderr, "  [%s:%d]   "fmt, __func__, __LINE__, ##args); \
-        } while (0)
-#else
-    #define  PRINT_DEBUG(fmt, args...)  do {} while (0)
-#endif
-
-#define SMDK_LAN9118_BASE_ADDR      0x05000000
-
-typedef enum Exynos4BoardType {
-    EXYNOS4_BOARD_NURI,
-    EXYNOS4_BOARD_SMDKC210,
-    EXYNOS4_NUM_OF_BOARDS
-} Exynos4BoardType;
-
-static int exynos4_board_id[EXYNOS4_NUM_OF_BOARDS] = {
-    [EXYNOS4_BOARD_NURI]     = 0xD33,
-    [EXYNOS4_BOARD_SMDKC210] = 0xB16,
-};
-
-static int exynos4_board_smp_bootreg_addr[EXYNOS4_NUM_OF_BOARDS] = {
-    [EXYNOS4_BOARD_NURI]     = EXYNOS4210_SECOND_CPU_BOOTREG,
-    [EXYNOS4_BOARD_SMDKC210] = EXYNOS4210_SECOND_CPU_BOOTREG,
-};
-
-static unsigned long exynos4_board_ram_size[EXYNOS4_NUM_OF_BOARDS] = {
-    [EXYNOS4_BOARD_NURI]     = 0x40000000,
-    [EXYNOS4_BOARD_SMDKC210] = 0x40000000,
-};
-
-static struct arm_boot_info exynos4_board_binfo = {
-    .loader_start     = EXYNOS4210_BASE_BOOT_ADDR,
-    .smp_loader_start = EXYNOS4210_SMP_BOOT_ADDR,
-    .nb_cpus          = EXYNOS4210_NCPUS,
-    .write_secondary_boot = exynos4210_write_secondary,
-};
-
-static QEMUMachine exynos4_machines[EXYNOS4_NUM_OF_BOARDS];
-
-static void lan9215_init(uint32_t base, qemu_irq irq)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    /* This should be a 9215 but the 9118 is close enough */
-    if (nd_table[0].used) {
-        qemu_check_nic_model(&nd_table[0], "lan9118");
-        dev = qdev_create(NULL, "lan9118");
-        qdev_set_nic_properties(dev, &nd_table[0]);
-        qdev_prop_set_uint32(dev, "mode_16bit", 1);
-        qdev_init_nofail(dev);
-        s = SYS_BUS_DEVICE(dev);
-        sysbus_mmio_map(s, 0, base);
-        sysbus_connect_irq(s, 0, irq);
-    }
-}
-
-static Exynos4210State *exynos4_boards_init_common(QEMUMachineInitArgs *args,
-                                                   Exynos4BoardType board_type)
-{
-    if (smp_cpus != EXYNOS4210_NCPUS) {
-        fprintf(stderr, "%s board supports only %d CPU cores. Ignoring smp_cpus"
-                " value.\n",
-                exynos4_machines[board_type].name,
-                exynos4_machines[board_type].max_cpus);
-    }
-
-    exynos4_board_binfo.ram_size = exynos4_board_ram_size[board_type];
-    exynos4_board_binfo.board_id = exynos4_board_id[board_type];
-    exynos4_board_binfo.smp_bootreg_addr =
-            exynos4_board_smp_bootreg_addr[board_type];
-    exynos4_board_binfo.kernel_filename = args->kernel_filename;
-    exynos4_board_binfo.initrd_filename = args->initrd_filename;
-    exynos4_board_binfo.kernel_cmdline = args->kernel_cmdline;
-    exynos4_board_binfo.gic_cpu_if_addr =
-            EXYNOS4210_SMP_PRIVATE_BASE_ADDR + 0x100;
-
-    PRINT_DEBUG("\n ram_size: %luMiB [0x%08lx]\n"
-            " kernel_filename: %s\n"
-            " kernel_cmdline: %s\n"
-            " initrd_filename: %s\n",
-            exynos4_board_ram_size[board_type] / 1048576,
-            exynos4_board_ram_size[board_type],
-            args->kernel_filename,
-            args->kernel_cmdline,
-            args->initrd_filename);
-
-    return exynos4210_init(get_system_memory(),
-            exynos4_board_ram_size[board_type]);
-}
-
-static void nuri_init(QEMUMachineInitArgs *args)
-{
-    exynos4_boards_init_common(args, EXYNOS4_BOARD_NURI);
-
-    arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
-}
-
-static void smdkc210_init(QEMUMachineInitArgs *args)
-{
-    Exynos4210State *s = exynos4_boards_init_common(args,
-                                                    EXYNOS4_BOARD_SMDKC210);
-
-    lan9215_init(SMDK_LAN9118_BASE_ADDR,
-            qemu_irq_invert(s->irq_table[exynos4210_get_irq(37, 1)]));
-    arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo);
-}
-
-static QEMUMachine exynos4_machines[EXYNOS4_NUM_OF_BOARDS] = {
-    [EXYNOS4_BOARD_NURI] = {
-        .name = "nuri",
-        .desc = "Samsung NURI board (Exynos4210)",
-        .init = nuri_init,
-        .max_cpus = EXYNOS4210_NCPUS,
-        DEFAULT_MACHINE_OPTIONS,
-    },
-    [EXYNOS4_BOARD_SMDKC210] = {
-        .name = "smdkc210",
-        .desc = "Samsung SMDKC210 board (Exynos4210)",
-        .init = smdkc210_init,
-        .max_cpus = EXYNOS4210_NCPUS,
-        DEFAULT_MACHINE_OPTIONS,
-    },
-};
-
-static void exynos4_machine_init(void)
-{
-    qemu_register_machine(&exynos4_machines[EXYNOS4_BOARD_NURI]);
-    qemu_register_machine(&exynos4_machines[EXYNOS4_BOARD_SMDKC210]);
-}
-
-machine_init(exynos4_machine_init);
diff --git a/hw/gumstix.c b/hw/gumstix.c
deleted file mode 100644
index 8859b73..0000000
--- a/hw/gumstix.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Gumstix Platforms
- *
- * Copyright (c) 2007 by Thorsten Zitterell <info at bitmux.org>
- *
- * Code based on spitz platform by Andrzej Zaborowski <balrog at zabor.org>
- *
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
- 
-/* 
- * Example usage:
- * 
- * connex:
- * =======
- * create image:
- * # dd of=flash bs=1k count=16k if=/dev/zero
- * # dd of=flash bs=1k conv=notrunc if=u-boot.bin
- * # dd of=flash bs=1k conv=notrunc seek=256 if=rootfs.arm_nofpu.jffs2
- * start it:
- * # qemu-system-arm -M connex -pflash flash -monitor null -nographic
- *
- * verdex:
- * =======
- * create image:
- * # dd of=flash bs=1k count=32k if=/dev/zero
- * # dd of=flash bs=1k conv=notrunc if=u-boot.bin
- * # dd of=flash bs=1k conv=notrunc seek=256 if=rootfs.arm_nofpu.jffs2
- * # dd of=flash bs=1k conv=notrunc seek=31744 if=uImage
- * start it:
- * # qemu-system-arm -M verdex -pflash flash -monitor null -nographic -m 289
- */
-
-#include "hw/hw.h"
-#include "hw/pxa.h"
-#include "net/net.h"
-#include "hw/flash.h"
-#include "hw/devices.h"
-#include "hw/boards.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-static const int sector_len = 128 * 1024;
-
-static void connex_init(QEMUMachineInitArgs *args)
-{
-    PXA2xxState *cpu;
-    DriveInfo *dinfo;
-    int be;
-    MemoryRegion *address_space_mem = get_system_memory();
-
-    uint32_t connex_rom = 0x01000000;
-    uint32_t connex_ram = 0x04000000;
-
-    cpu = pxa255_init(address_space_mem, connex_ram);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (!dinfo) {
-        fprintf(stderr, "A flash image must be given with the "
-                "'pflash' parameter\n");
-        exit(1);
-    }
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
-#else
-    be = 0;
-#endif
-    if (!pflash_cfi01_register(0x00000000, NULL, "connext.rom", connex_rom,
-                               dinfo->bdrv, sector_len, connex_rom / sector_len,
-                               2, 0, 0, 0, 0, be)) {
-        fprintf(stderr, "qemu: Error registering flash memory.\n");
-        exit(1);
-    }
-
-    /* Interrupt line of NIC is connected to GPIO line 36 */
-    smc91c111_init(&nd_table[0], 0x04000300,
-                    qdev_get_gpio_in(cpu->gpio, 36));
-}
-
-static void verdex_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    PXA2xxState *cpu;
-    DriveInfo *dinfo;
-    int be;
-    MemoryRegion *address_space_mem = get_system_memory();
-
-    uint32_t verdex_rom = 0x02000000;
-    uint32_t verdex_ram = 0x10000000;
-
-    cpu = pxa270_init(address_space_mem, verdex_ram, cpu_model ?: "pxa270-c0");
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (!dinfo) {
-        fprintf(stderr, "A flash image must be given with the "
-                "'pflash' parameter\n");
-        exit(1);
-    }
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
-#else
-    be = 0;
-#endif
-    if (!pflash_cfi01_register(0x00000000, NULL, "verdex.rom", verdex_rom,
-                               dinfo->bdrv, sector_len, verdex_rom / sector_len,
-                               2, 0, 0, 0, 0, be)) {
-        fprintf(stderr, "qemu: Error registering flash memory.\n");
-        exit(1);
-    }
-
-    /* Interrupt line of NIC is connected to GPIO line 99 */
-    smc91c111_init(&nd_table[0], 0x04000300,
-                    qdev_get_gpio_in(cpu->gpio, 99));
-}
-
-static QEMUMachine connex_machine = {
-    .name = "connex",
-    .desc = "Gumstix Connex (PXA255)",
-    .init = connex_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine verdex_machine = {
-    .name = "verdex",
-    .desc = "Gumstix Verdex (PXA270)",
-    .init = verdex_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void gumstix_machine_init(void)
-{
-    qemu_register_machine(&connex_machine);
-    qemu_register_machine(&verdex_machine);
-}
-
-machine_init(gumstix_machine_init);
diff --git a/hw/highbank.c b/hw/highbank.c
deleted file mode 100644
index a622224..0000000
--- a/hw/highbank.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * Calxeda Highbank SoC emulation
- *
- * Copyright (c) 2010-2012 Calxeda
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2 or later, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "hw/sysbus.h"
-#include "hw/arm-misc.h"
-#include "hw/devices.h"
-#include "hw/loader.h"
-#include "net/net.h"
-#include "sysemu/sysemu.h"
-#include "hw/boards.h"
-#include "hw/sysbus.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-#define SMP_BOOT_ADDR 0x100
-#define SMP_BOOT_REG  0x40
-#define GIC_BASE_ADDR 0xfff10000
-
-#define NIRQ_GIC      160
-
-/* Board init.  */
-
-static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
-{
-    int n;
-    uint32_t smpboot[] = {
-        0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 - read current core id */
-        0xe210000f, /* ands r0, r0, #0x0f */
-        0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */
-        0xe0830200, /* add r0, r3, r0, lsl #4 */
-        0xe59f2024, /* ldr r2, privbase */
-        0xe3a01001, /* mov r1, #1 */
-        0xe5821100, /* str r1, [r2, #256] - set GICC_CTLR.Enable */
-        0xe3a010ff, /* mov r1, #0xff */
-        0xe5821104, /* str r1, [r2, #260] - set GICC_PMR.Priority to 0xff */
-        0xf57ff04f, /* dsb */
-        0xe320f003, /* wfi */
-        0xe5901000, /* ldr     r1, [r0] */
-        0xe1110001, /* tst     r1, r1 */
-        0x0afffffb, /* beq     <wfi> */
-        0xe12fff11, /* bx      r1 */
-        GIC_BASE_ADDR      /* privbase: gic address.  */
-    };
-    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
-        smpboot[n] = tswap32(smpboot[n]);
-    }
-    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR);
-}
-
-static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
-{
-    CPUARMState *env = &cpu->env;
-
-    switch (info->nb_cpus) {
-    case 4:
-        stl_phys_notdirty(SMP_BOOT_REG + 0x30, 0);
-    case 3:
-        stl_phys_notdirty(SMP_BOOT_REG + 0x20, 0);
-    case 2:
-        stl_phys_notdirty(SMP_BOOT_REG + 0x10, 0);
-        env->regs[15] = SMP_BOOT_ADDR;
-        break;
-    default:
-        break;
-    }
-}
-
-#define NUM_REGS      0x200
-static void hb_regs_write(void *opaque, hwaddr offset,
-                          uint64_t value, unsigned size)
-{
-    uint32_t *regs = opaque;
-
-    if (offset == 0xf00) {
-        if (value == 1 || value == 2) {
-            qemu_system_reset_request();
-        } else if (value == 3) {
-            qemu_system_shutdown_request();
-        }
-    }
-
-    regs[offset/4] = value;
-}
-
-static uint64_t hb_regs_read(void *opaque, hwaddr offset,
-                             unsigned size)
-{
-    uint32_t *regs = opaque;
-    uint32_t value = regs[offset/4];
-
-    if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) {
-        value |= 0x30000000;
-    }
-
-    return value;
-}
-
-static const MemoryRegionOps hb_mem_ops = {
-    .read = hb_regs_read,
-    .write = hb_regs_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion *iomem;
-    uint32_t regs[NUM_REGS];
-} HighbankRegsState;
-
-static VMStateDescription vmstate_highbank_regs = {
-    .name = "highbank-regs",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32_ARRAY(regs, HighbankRegsState, NUM_REGS),
-        VMSTATE_END_OF_LIST(),
-    },
-};
-
-static void highbank_regs_reset(DeviceState *dev)
-{
-    SysBusDevice *sys_dev = SYS_BUS_DEVICE(dev);
-    HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, sys_dev);
-
-    s->regs[0x40] = 0x05F20121;
-    s->regs[0x41] = 0x2;
-    s->regs[0x42] = 0x05F30121;
-    s->regs[0x43] = 0x05F40121;
-}
-
-static int highbank_regs_init(SysBusDevice *dev)
-{
-    HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, dev);
-
-    s->iomem = g_new(MemoryRegion, 1);
-    memory_region_init_io(s->iomem, &hb_mem_ops, s->regs, "highbank_regs",
-                          0x1000);
-    sysbus_init_mmio(dev, s->iomem);
-
-    return 0;
-}
-
-static void highbank_regs_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    sbc->init = highbank_regs_init;
-    dc->desc = "Calxeda Highbank registers";
-    dc->vmsd = &vmstate_highbank_regs;
-    dc->reset = highbank_regs_reset;
-}
-
-static const TypeInfo highbank_regs_info = {
-    .name          = "highbank-regs",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(HighbankRegsState),
-    .class_init    = highbank_regs_class_init,
-};
-
-static void highbank_regs_register_types(void)
-{
-    type_register_static(&highbank_regs_info);
-}
-
-type_init(highbank_regs_register_types)
-
-static struct arm_boot_info highbank_binfo;
-
-/* ram_size must be set to match the upper bound of memory in the
- * device tree (linux/arch/arm/boot/dts/highbank.dts), which is
- * normally 0xff900000 or -m 4089. When running this board on a
- * 32-bit host, set the reg value of memory to 0xf7ff00000 in the
- * device tree and pass -m 2047 to QEMU.
- */
-static void highbank_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    DeviceState *dev;
-    SysBusDevice *busdev;
-    qemu_irq *irqp;
-    qemu_irq pic[128];
-    int n;
-    qemu_irq cpu_irq[4];
-    MemoryRegion *sysram;
-    MemoryRegion *dram;
-    MemoryRegion *sysmem;
-    char *sysboot_filename;
-
-    if (!cpu_model) {
-        cpu_model = "cortex-a9";
-    }
-
-    for (n = 0; n < smp_cpus; n++) {
-        ARMCPU *cpu;
-        cpu = cpu_arm_init(cpu_model);
-        if (cpu == NULL) {
-            fprintf(stderr, "Unable to find CPU definition\n");
-            exit(1);
-        }
-
-        /* This will become a QOM property eventually */
-        cpu->reset_cbar = GIC_BASE_ADDR;
-        irqp = arm_pic_init_cpu(cpu);
-        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
-    }
-
-    sysmem = get_system_memory();
-    dram = g_new(MemoryRegion, 1);
-    memory_region_init_ram(dram, "highbank.dram", ram_size);
-    /* SDRAM at address zero.  */
-    memory_region_add_subregion(sysmem, 0, dram);
-
-    sysram = g_new(MemoryRegion, 1);
-    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
-    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
-    if (bios_name != NULL) {
-        sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-        if (sysboot_filename != NULL) {
-            uint32_t filesize = get_image_size(sysboot_filename);
-            if (load_image_targphys("sysram.bin", 0xfff88000, filesize) < 0) {
-                hw_error("Unable to load %s\n", bios_name);
-            }
-        } else {
-           hw_error("Unable to find %s\n", bios_name);
-        }
-    }
-
-    dev = qdev_create(NULL, "a9mpcore_priv");
-    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
-    qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(busdev, 0, GIC_BASE_ADDR);
-    for (n = 0; n < smp_cpus; n++) {
-        sysbus_connect_irq(busdev, n, cpu_irq[n]);
-    }
-
-    for (n = 0; n < 128; n++) {
-        pic[n] = qdev_get_gpio_in(dev, n);
-    }
-
-    dev = qdev_create(NULL, "l2x0");
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(busdev, 0, 0xfff12000);
-
-    dev = qdev_create(NULL, "sp804");
-    qdev_prop_set_uint32(dev, "freq0", 150000000);
-    qdev_prop_set_uint32(dev, "freq1", 150000000);
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(busdev, 0, 0xfff34000);
-    sysbus_connect_irq(busdev, 0, pic[18]);
-    sysbus_create_simple("pl011", 0xfff36000, pic[20]);
-
-    dev = qdev_create(NULL, "highbank-regs");
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(busdev, 0, 0xfff3c000);
-
-    sysbus_create_simple("pl061", 0xfff30000, pic[14]);
-    sysbus_create_simple("pl061", 0xfff31000, pic[15]);
-    sysbus_create_simple("pl061", 0xfff32000, pic[16]);
-    sysbus_create_simple("pl061", 0xfff33000, pic[17]);
-    sysbus_create_simple("pl031", 0xfff35000, pic[19]);
-    sysbus_create_simple("pl022", 0xfff39000, pic[23]);
-
-    sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]);
-
-    if (nd_table[0].used) {
-        qemu_check_nic_model(&nd_table[0], "xgmac");
-        dev = qdev_create(NULL, "xgmac");
-        qdev_set_nic_properties(dev, &nd_table[0]);
-        qdev_init_nofail(dev);
-        sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff50000);
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[77]);
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[78]);
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[79]);
-
-        qemu_check_nic_model(&nd_table[1], "xgmac");
-        dev = qdev_create(NULL, "xgmac");
-        qdev_set_nic_properties(dev, &nd_table[1]);
-        qdev_init_nofail(dev);
-        sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff51000);
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[80]);
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[81]);
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[82]);
-    }
-
-    highbank_binfo.ram_size = ram_size;
-    highbank_binfo.kernel_filename = kernel_filename;
-    highbank_binfo.kernel_cmdline = kernel_cmdline;
-    highbank_binfo.initrd_filename = initrd_filename;
-    /* highbank requires a dtb in order to boot, and the dtb will override
-     * the board ID. The following value is ignored, so set it to -1 to be
-     * clear that the value is meaningless.
-     */
-    highbank_binfo.board_id = -1;
-    highbank_binfo.nb_cpus = smp_cpus;
-    highbank_binfo.loader_start = 0;
-    highbank_binfo.write_secondary_boot = hb_write_secondary;
-    highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
-    arm_load_kernel(arm_env_get_cpu(first_cpu), &highbank_binfo);
-}
-
-static QEMUMachine highbank_machine = {
-    .name = "highbank",
-    .desc = "Calxeda Highbank (ECX-1000)",
-    .init = highbank_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void highbank_machine_init(void)
-{
-    qemu_register_machine(&highbank_machine);
-}
-
-machine_init(highbank_machine_init);
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 025803a..5d071f4 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -1,12 +1,11 @@
-obj-y += mc146818rtc.o pc.o
+obj-y += mc146818rtc.o
 obj-y += apic_common.o apic.o kvmvapic.o
 obj-y += sga.o ioapic_common.o ioapic.o piix_pci.o
 obj-y += vmport.o
-obj-y += pci/pci-hotplug.o smbios.o wdt_ib700.o
-obj-y += debugcon.o debugexit.o multiboot.o
-obj-y += pc_piix.o
+obj-y += pci/pci-hotplug.o wdt_ib700.o
+obj-y += debugcon.o debugexit.o
 obj-y += pc_sysfw.o
-obj-y += lpc_ich9.o q35.o pc_q35.o
+obj-y += lpc_ich9.o q35.o
 obj-$(CONFIG_XEN) += xen_platform.o xen_apic.o
 obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o
 obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o
@@ -15,3 +14,7 @@ obj-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
 obj-y += pc-testdev.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += multiboot.o smbios.o
+obj-y += pc.o pc_piix.o pc_q35.o
+obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c
new file mode 100644
index 0000000..3cb228f
--- /dev/null
+++ b/hw/i386/multiboot.c
@@ -0,0 +1,349 @@
+/*
+ * QEMU PC System Emulator
+ *
+ * Copyright (c) 2003-2004 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 "hw/hw.h"
+#include "hw/fw_cfg.h"
+#include "hw/multiboot.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "sysemu/sysemu.h"
+
+/* Show multiboot debug output */
+//#define DEBUG_MULTIBOOT
+
+#ifdef DEBUG_MULTIBOOT
+#define mb_debug(a...) fprintf(stderr, ## a)
+#else
+#define mb_debug(a...)
+#endif
+
+#define MULTIBOOT_STRUCT_ADDR 0x9000
+
+#if MULTIBOOT_STRUCT_ADDR > 0xf0000
+#error multiboot struct needs to fit in 16 bit real mode
+#endif
+
+enum {
+    /* Multiboot info */
+    MBI_FLAGS       = 0,
+    MBI_MEM_LOWER   = 4,
+    MBI_MEM_UPPER   = 8,
+    MBI_BOOT_DEVICE = 12,
+    MBI_CMDLINE     = 16,
+    MBI_MODS_COUNT  = 20,
+    MBI_MODS_ADDR   = 24,
+    MBI_MMAP_ADDR   = 48,
+
+    MBI_SIZE        = 88,
+
+    /* Multiboot modules */
+    MB_MOD_START    = 0,
+    MB_MOD_END      = 4,
+    MB_MOD_CMDLINE  = 8,
+
+    MB_MOD_SIZE     = 16,
+
+    /* Region offsets */
+    ADDR_E820_MAP = MULTIBOOT_STRUCT_ADDR + 0,
+    ADDR_MBI      = ADDR_E820_MAP + 0x500,
+
+    /* Multiboot flags */
+    MULTIBOOT_FLAGS_MEMORY      = 1 << 0,
+    MULTIBOOT_FLAGS_BOOT_DEVICE = 1 << 1,
+    MULTIBOOT_FLAGS_CMDLINE     = 1 << 2,
+    MULTIBOOT_FLAGS_MODULES     = 1 << 3,
+    MULTIBOOT_FLAGS_MMAP        = 1 << 6,
+};
+
+typedef struct {
+    /* buffer holding kernel, cmdlines and mb_infos */
+    void *mb_buf;
+    /* address in target */
+    hwaddr mb_buf_phys;
+    /* size of mb_buf in bytes */
+    unsigned mb_buf_size;
+    /* offset of mb-info's in bytes */
+    hwaddr offset_mbinfo;
+    /* offset in buffer for cmdlines in bytes */
+    hwaddr offset_cmdlines;
+    /* offset of modules in bytes */
+    hwaddr offset_mods;
+    /* available slots for mb modules infos */
+    int mb_mods_avail;
+    /* currently used slots of mb modules */
+    int mb_mods_count;
+} MultibootState;
+
+static uint32_t mb_add_cmdline(MultibootState *s, const char *cmdline)
+{
+    hwaddr p = s->offset_cmdlines;
+    char *b = (char *)s->mb_buf + p;
+
+    get_opt_value(b, strlen(cmdline) + 1, cmdline);
+    s->offset_cmdlines += strlen(b) + 1;
+    return s->mb_buf_phys + p;
+}
+
+static void mb_add_mod(MultibootState *s,
+                       hwaddr start, hwaddr end,
+                       hwaddr cmdline_phys)
+{
+    char *p;
+    assert(s->mb_mods_count < s->mb_mods_avail);
+
+    p = (char *)s->mb_buf + s->offset_mbinfo + MB_MOD_SIZE * s->mb_mods_count;
+
+    stl_p(p + MB_MOD_START,   start);
+    stl_p(p + MB_MOD_END,     end);
+    stl_p(p + MB_MOD_CMDLINE, cmdline_phys);
+
+    mb_debug("mod%02d: "TARGET_FMT_plx" - "TARGET_FMT_plx"\n",
+             s->mb_mods_count, start, end);
+
+    s->mb_mods_count++;
+}
+
+int load_multiboot(void *fw_cfg,
+                   FILE *f,
+                   const char *kernel_filename,
+                   const char *initrd_filename,
+                   const char *kernel_cmdline,
+                   int kernel_file_size,
+                   uint8_t *header)
+{
+    int i, is_multiboot = 0;
+    uint32_t flags = 0;
+    uint32_t mh_entry_addr;
+    uint32_t mh_load_addr;
+    uint32_t mb_kernel_size;
+    MultibootState mbs;
+    uint8_t bootinfo[MBI_SIZE];
+    uint8_t *mb_bootinfo_data;
+
+    /* Ok, let's see if it is a multiboot image.
+       The header is 12x32bit long, so the latest entry may be 8192 - 48. */
+    for (i = 0; i < (8192 - 48); i += 4) {
+        if (ldl_p(header+i) == 0x1BADB002) {
+            uint32_t checksum = ldl_p(header+i+8);
+            flags = ldl_p(header+i+4);
+            checksum += flags;
+            checksum += (uint32_t)0x1BADB002;
+            if (!checksum) {
+                is_multiboot = 1;
+                break;
+            }
+        }
+    }
+
+    if (!is_multiboot)
+        return 0; /* no multiboot */
+
+    mb_debug("qemu: I believe we found a multiboot image!\n");
+    memset(bootinfo, 0, sizeof(bootinfo));
+    memset(&mbs, 0, sizeof(mbs));
+
+    if (flags & 0x00000004) { /* MULTIBOOT_HEADER_HAS_VBE */
+        fprintf(stderr, "qemu: multiboot knows VBE. we don't.\n");
+    }
+    if (!(flags & 0x00010000)) { /* MULTIBOOT_HEADER_HAS_ADDR */
+        uint64_t elf_entry;
+        uint64_t elf_low, elf_high;
+        int kernel_size;
+        fclose(f);
+
+        if (((struct elf64_hdr*)header)->e_machine == EM_X86_64) {
+            fprintf(stderr, "Cannot load x86-64 image, give a 32bit one.\n");
+            exit(1);
+        }
+
+        kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+                               &elf_low, &elf_high, 0, ELF_MACHINE, 0);
+        if (kernel_size < 0) {
+            fprintf(stderr, "Error while loading elf kernel\n");
+            exit(1);
+        }
+        mh_load_addr = elf_low;
+        mb_kernel_size = elf_high - elf_low;
+        mh_entry_addr = elf_entry;
+
+        mbs.mb_buf = g_malloc(mb_kernel_size);
+        if (rom_copy(mbs.mb_buf, mh_load_addr, mb_kernel_size) != mb_kernel_size) {
+            fprintf(stderr, "Error while fetching elf kernel from rom\n");
+            exit(1);
+        }
+
+        mb_debug("qemu: loading multiboot-elf kernel (%#x bytes) with entry %#zx\n",
+                  mb_kernel_size, (size_t)mh_entry_addr);
+    } else {
+        /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_ADDR. */
+        uint32_t mh_header_addr = ldl_p(header+i+12);
+        uint32_t mh_load_end_addr = ldl_p(header+i+20);
+        uint32_t mh_bss_end_addr = ldl_p(header+i+24);
+        mh_load_addr = ldl_p(header+i+16);
+        uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr);
+        uint32_t mb_load_size = 0;
+        mh_entry_addr = ldl_p(header+i+28);
+
+        if (mh_load_end_addr) {
+            mb_kernel_size = mh_bss_end_addr - mh_load_addr;
+            mb_load_size = mh_load_end_addr - mh_load_addr;
+        } else {
+            mb_kernel_size = kernel_file_size - mb_kernel_text_offset;
+            mb_load_size = mb_kernel_size;
+        }
+
+        /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_VBE.
+        uint32_t mh_mode_type = ldl_p(header+i+32);
+        uint32_t mh_width = ldl_p(header+i+36);
+        uint32_t mh_height = ldl_p(header+i+40);
+        uint32_t mh_depth = ldl_p(header+i+44); */
+
+        mb_debug("multiboot: mh_header_addr = %#x\n", mh_header_addr);
+        mb_debug("multiboot: mh_load_addr = %#x\n", mh_load_addr);
+        mb_debug("multiboot: mh_load_end_addr = %#x\n", mh_load_end_addr);
+        mb_debug("multiboot: mh_bss_end_addr = %#x\n", mh_bss_end_addr);
+        mb_debug("qemu: loading multiboot kernel (%#x bytes) at %#x\n",
+                 mb_load_size, mh_load_addr);
+
+        mbs.mb_buf = g_malloc(mb_kernel_size);
+        fseek(f, mb_kernel_text_offset, SEEK_SET);
+        if (fread(mbs.mb_buf, 1, mb_load_size, f) != mb_load_size) {
+            fprintf(stderr, "fread() failed\n");
+            exit(1);
+        }
+        memset(mbs.mb_buf + mb_load_size, 0, mb_kernel_size - mb_load_size);
+        fclose(f);
+    }
+
+    mbs.mb_buf_phys = mh_load_addr;
+
+    mbs.mb_buf_size = TARGET_PAGE_ALIGN(mb_kernel_size);
+    mbs.offset_mbinfo = mbs.mb_buf_size;
+
+    /* Calculate space for cmdlines and mb_mods */
+    mbs.mb_buf_size += strlen(kernel_filename) + 1;
+    mbs.mb_buf_size += strlen(kernel_cmdline) + 1;
+    if (initrd_filename) {
+        const char *r = initrd_filename;
+        mbs.mb_buf_size += strlen(r) + 1;
+        mbs.mb_mods_avail = 1;
+        while (*(r = get_opt_value(NULL, 0, r))) {
+           mbs.mb_mods_avail++;
+           r++;
+        }
+        mbs.mb_buf_size += MB_MOD_SIZE * mbs.mb_mods_avail;
+    }
+
+    mbs.mb_buf_size = TARGET_PAGE_ALIGN(mbs.mb_buf_size);
+
+    /* enlarge mb_buf to hold cmdlines and mb-info structs */
+    mbs.mb_buf          = g_realloc(mbs.mb_buf, mbs.mb_buf_size);
+    mbs.offset_cmdlines = mbs.offset_mbinfo + mbs.mb_mods_avail * MB_MOD_SIZE;
+
+    if (initrd_filename) {
+        char *next_initrd, not_last;
+
+        mbs.offset_mods = mbs.mb_buf_size;
+
+        do {
+            char *next_space;
+            int mb_mod_length;
+            uint32_t offs = mbs.mb_buf_size;
+
+            next_initrd = (char *)get_opt_value(NULL, 0, initrd_filename);
+            not_last = *next_initrd;
+            *next_initrd = '\0';
+            /* if a space comes after the module filename, treat everything
+               after that as parameters */
+            hwaddr c = mb_add_cmdline(&mbs, initrd_filename);
+            if ((next_space = strchr(initrd_filename, ' ')))
+                *next_space = '\0';
+            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 open file '%s'\n", initrd_filename);
+                exit(1);
+            }
+
+            mbs.mb_buf_size = TARGET_PAGE_ALIGN(mb_mod_length + mbs.mb_buf_size);
+            mbs.mb_buf = g_realloc(mbs.mb_buf, mbs.mb_buf_size);
+
+            load_image(initrd_filename, (unsigned char *)mbs.mb_buf + offs);
+            mb_add_mod(&mbs, mbs.mb_buf_phys + offs,
+                       mbs.mb_buf_phys + offs + mb_mod_length, c);
+
+            mb_debug("mod_start: %p\nmod_end:   %p\n  cmdline: "TARGET_FMT_plx"\n",
+                     (char *)mbs.mb_buf + offs,
+                     (char *)mbs.mb_buf + offs + mb_mod_length, c);
+            initrd_filename = next_initrd+1;
+        } while (not_last);
+    }
+
+    /* Commandline support */
+    char kcmdline[strlen(kernel_filename) + strlen(kernel_cmdline) + 2];
+    snprintf(kcmdline, sizeof(kcmdline), "%s %s",
+             kernel_filename, kernel_cmdline);
+    stl_p(bootinfo + MBI_CMDLINE, mb_add_cmdline(&mbs, kcmdline));
+
+    stl_p(bootinfo + MBI_MODS_ADDR,  mbs.mb_buf_phys + mbs.offset_mbinfo);
+    stl_p(bootinfo + MBI_MODS_COUNT, mbs.mb_mods_count); /* mods_count */
+
+    /* the kernel is where we want it to be now */
+    stl_p(bootinfo + MBI_FLAGS, MULTIBOOT_FLAGS_MEMORY
+                                | MULTIBOOT_FLAGS_BOOT_DEVICE
+                                | MULTIBOOT_FLAGS_CMDLINE
+                                | MULTIBOOT_FLAGS_MODULES
+                                | MULTIBOOT_FLAGS_MMAP);
+    stl_p(bootinfo + MBI_MEM_LOWER,   640);
+    stl_p(bootinfo + MBI_MEM_UPPER,   (ram_size / 1024) - 1024);
+    stl_p(bootinfo + MBI_BOOT_DEVICE, 0x8000ffff); /* XXX: use the -boot switch? */
+    stl_p(bootinfo + MBI_MMAP_ADDR,   ADDR_E820_MAP);
+
+    mb_debug("multiboot: mh_entry_addr = %#x\n", mh_entry_addr);
+    mb_debug("           mb_buf_phys   = "TARGET_FMT_plx"\n", mbs.mb_buf_phys);
+    mb_debug("           mod_start     = "TARGET_FMT_plx"\n", mbs.mb_buf_phys + mbs.offset_mods);
+    mb_debug("           mb_mods_count = %d\n", mbs.mb_mods_count);
+
+    /* save bootinfo off the stack */
+    mb_bootinfo_data = g_malloc(sizeof(bootinfo));
+    memcpy(mb_bootinfo_data, bootinfo, sizeof(bootinfo));
+
+    /* Pass variables to option rom */
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ENTRY, mh_entry_addr);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, mh_load_addr);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, mbs.mb_buf_size);
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA,
+                     mbs.mb_buf, mbs.mb_buf_size);
+
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, ADDR_MBI);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, sizeof(bootinfo));
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, mb_bootinfo_data,
+                     sizeof(bootinfo));
+
+    option_rom[nb_option_roms].name = "multiboot.bin";
+    option_rom[nb_option_roms].bootindex = 0;
+    nb_option_roms++;
+
+    return 1; /* yes, we are multiboot */
+}
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
new file mode 100644
index 0000000..309bb83
--- /dev/null
+++ b/hw/i386/pc.c
@@ -0,0 +1,1161 @@
+/*
+ * QEMU PC System Emulator
+ *
+ * Copyright (c) 2003-2004 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 "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/apic.h"
+#include "hw/fdc.h"
+#include "hw/ide.h"
+#include "hw/pci/pci.h"
+#include "monitor/monitor.h"
+#include "hw/fw_cfg.h"
+#include "hw/hpet_emul.h"
+#include "hw/smbios.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "hw/multiboot.h"
+#include "hw/mc146818rtc.h"
+#include "hw/i8254.h"
+#include "hw/pcspk.h"
+#include "hw/pci/msi.h"
+#include "hw/sysbus.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
+#include "kvm_i386.h"
+#include "hw/xen.h"
+#include "sysemu/blockdev.h"
+#include "hw/block-common.h"
+#include "ui/qemu-spice.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "sysemu/arch_init.h"
+#include "qemu/bitmap.h"
+
+/* debug PC/ISA interrupts */
+//#define DEBUG_IRQ
+
+#ifdef DEBUG_IRQ
+#define DPRINTF(fmt, ...)                                       \
+    do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables.  */
+#define ACPI_DATA_SIZE       0x10000
+#define BIOS_CFG_IOPORT 0x510
+#define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0)
+#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1)
+#define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2)
+#define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3)
+#define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4)
+
+#define E820_NR_ENTRIES		16
+
+struct e820_entry {
+    uint64_t address;
+    uint64_t length;
+    uint32_t type;
+} QEMU_PACKED __attribute((__aligned__(4)));
+
+struct e820_table {
+    uint32_t count;
+    struct e820_entry entry[E820_NR_ENTRIES];
+} QEMU_PACKED __attribute((__aligned__(4)));
+
+static struct e820_table e820_table;
+struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
+
+void gsi_handler(void *opaque, int n, int level)
+{
+    GSIState *s = opaque;
+
+    DPRINTF("pc: %s GSI %d\n", level ? "raising" : "lowering", n);
+    if (n < ISA_NUM_IRQS) {
+        qemu_set_irq(s->i8259_irq[n], level);
+    }
+    qemu_set_irq(s->ioapic_irq[n], level);
+}
+
+static void ioport80_write(void *opaque, hwaddr addr, uint64_t data,
+                           unsigned size)
+{
+}
+
+static uint64_t ioport80_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return 0xffffffffffffffffULL;
+}
+
+/* MSDOS compatibility mode FPU exception support */
+static qemu_irq ferr_irq;
+
+void pc_register_ferr_irq(qemu_irq irq)
+{
+    ferr_irq = irq;
+}
+
+/* XXX: add IGNNE support */
+void cpu_set_ferr(CPUX86State *s)
+{
+    qemu_irq_raise(ferr_irq);
+}
+
+static void ioportF0_write(void *opaque, hwaddr addr, uint64_t data,
+                           unsigned size)
+{
+    qemu_irq_lower(ferr_irq);
+}
+
+static uint64_t ioportF0_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return 0xffffffffffffffffULL;
+}
+
+/* TSC handling */
+uint64_t cpu_get_tsc(CPUX86State *env)
+{
+    return cpu_get_ticks();
+}
+
+/* SMM support */
+
+static cpu_set_smm_t smm_set;
+static void *smm_arg;
+
+void cpu_smm_register(cpu_set_smm_t callback, void *arg)
+{
+    assert(smm_set == NULL);
+    assert(smm_arg == NULL);
+    smm_set = callback;
+    smm_arg = arg;
+}
+
+void cpu_smm_update(CPUX86State *env)
+{
+    if (smm_set && smm_arg && env == first_cpu)
+        smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg);
+}
+
+
+/* IRQ handling */
+int cpu_get_pic_interrupt(CPUX86State *env)
+{
+    int intno;
+
+    intno = apic_get_interrupt(env->apic_state);
+    if (intno >= 0) {
+        return intno;
+    }
+    /* read the irq from the PIC */
+    if (!apic_accept_pic_intr(env->apic_state)) {
+        return -1;
+    }
+
+    intno = pic_read_irq(isa_pic);
+    return intno;
+}
+
+static void pic_irq_request(void *opaque, int irq, int level)
+{
+    CPUX86State *env = first_cpu;
+
+    DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
+    if (env->apic_state) {
+        while (env) {
+            if (apic_accept_pic_intr(env->apic_state)) {
+                apic_deliver_pic_intr(env->apic_state, level);
+            }
+            env = env->next_cpu;
+        }
+    } else {
+        if (level)
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        else
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+/* PC cmos mappings */
+
+#define REG_EQUIPMENT_BYTE          0x14
+
+static int cmos_get_fd_drive_type(FDriveType fd0)
+{
+    int val;
+
+    switch (fd0) {
+    case FDRIVE_DRV_144:
+        /* 1.44 Mb 3"5 drive */
+        val = 4;
+        break;
+    case FDRIVE_DRV_288:
+        /* 2.88 Mb 3"5 drive */
+        val = 5;
+        break;
+    case FDRIVE_DRV_120:
+        /* 1.2 Mb 5"5 drive */
+        val = 2;
+        break;
+    case FDRIVE_DRV_NONE:
+    default:
+        val = 0;
+        break;
+    }
+    return val;
+}
+
+static void cmos_init_hd(ISADevice *s, int type_ofs, int info_ofs,
+                         int16_t cylinders, int8_t heads, int8_t sectors)
+{
+    rtc_set_memory(s, type_ofs, 47);
+    rtc_set_memory(s, info_ofs, cylinders);
+    rtc_set_memory(s, info_ofs + 1, cylinders >> 8);
+    rtc_set_memory(s, info_ofs + 2, heads);
+    rtc_set_memory(s, info_ofs + 3, 0xff);
+    rtc_set_memory(s, info_ofs + 4, 0xff);
+    rtc_set_memory(s, info_ofs + 5, 0xc0 | ((heads > 8) << 3));
+    rtc_set_memory(s, info_ofs + 6, cylinders);
+    rtc_set_memory(s, info_ofs + 7, cylinders >> 8);
+    rtc_set_memory(s, info_ofs + 8, sectors);
+}
+
+/* convert boot_device letter to something recognizable by the bios */
+static int boot_device2nibble(char boot_device)
+{
+    switch(boot_device) {
+    case 'a':
+    case 'b':
+        return 0x01; /* floppy boot */
+    case 'c':
+        return 0x02; /* hard drive boot */
+    case 'd':
+        return 0x03; /* CD-ROM boot */
+    case 'n':
+        return 0x04; /* Network boot */
+    }
+    return 0;
+}
+
+static int set_boot_dev(ISADevice *s, const char *boot_device, int fd_bootchk)
+{
+#define PC_MAX_BOOT_DEVICES 3
+    int nbds, bds[3] = { 0, };
+    int i;
+
+    nbds = strlen(boot_device);
+    if (nbds > PC_MAX_BOOT_DEVICES) {
+        error_report("Too many boot devices for PC");
+        return(1);
+    }
+    for (i = 0; i < nbds; i++) {
+        bds[i] = boot_device2nibble(boot_device[i]);
+        if (bds[i] == 0) {
+            error_report("Invalid boot device for PC: '%c'",
+                         boot_device[i]);
+            return(1);
+        }
+    }
+    rtc_set_memory(s, 0x3d, (bds[1] << 4) | bds[0]);
+    rtc_set_memory(s, 0x38, (bds[2] << 4) | (fd_bootchk ? 0x0 : 0x1));
+    return(0);
+}
+
+static int pc_boot_set(void *opaque, const char *boot_device)
+{
+    return set_boot_dev(opaque, boot_device, 0);
+}
+
+typedef struct pc_cmos_init_late_arg {
+    ISADevice *rtc_state;
+    BusState *idebus[2];
+} pc_cmos_init_late_arg;
+
+static void pc_cmos_init_late(void *opaque)
+{
+    pc_cmos_init_late_arg *arg = opaque;
+    ISADevice *s = arg->rtc_state;
+    int16_t cylinders;
+    int8_t heads, sectors;
+    int val;
+    int i, trans;
+
+    val = 0;
+    if (ide_get_geometry(arg->idebus[0], 0,
+                         &cylinders, &heads, &sectors) >= 0) {
+        cmos_init_hd(s, 0x19, 0x1b, cylinders, heads, sectors);
+        val |= 0xf0;
+    }
+    if (ide_get_geometry(arg->idebus[0], 1,
+                         &cylinders, &heads, &sectors) >= 0) {
+        cmos_init_hd(s, 0x1a, 0x24, cylinders, heads, sectors);
+        val |= 0x0f;
+    }
+    rtc_set_memory(s, 0x12, val);
+
+    val = 0;
+    for (i = 0; i < 4; i++) {
+        /* NOTE: ide_get_geometry() returns the physical
+           geometry.  It is always such that: 1 <= sects <= 63, 1
+           <= heads <= 16, 1 <= cylinders <= 16383. The BIOS
+           geometry can be different if a translation is done. */
+        if (ide_get_geometry(arg->idebus[i / 2], i % 2,
+                             &cylinders, &heads, &sectors) >= 0) {
+            trans = ide_get_bios_chs_trans(arg->idebus[i / 2], i % 2) - 1;
+            assert((trans & ~3) == 0);
+            val |= trans << (i * 2);
+        }
+    }
+    rtc_set_memory(s, 0x39, val);
+
+    qemu_unregister_reset(pc_cmos_init_late, opaque);
+}
+
+void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
+                  const char *boot_device,
+                  ISADevice *floppy, BusState *idebus0, BusState *idebus1,
+                  ISADevice *s)
+{
+    int val, nb, i;
+    FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
+    static pc_cmos_init_late_arg arg;
+
+    /* various important CMOS locations needed by PC/Bochs bios */
+
+    /* memory size */
+    /* base memory (first MiB) */
+    val = MIN(ram_size / 1024, 640);
+    rtc_set_memory(s, 0x15, val);
+    rtc_set_memory(s, 0x16, val >> 8);
+    /* extended memory (next 64MiB) */
+    if (ram_size > 1024 * 1024) {
+        val = (ram_size - 1024 * 1024) / 1024;
+    } else {
+        val = 0;
+    }
+    if (val > 65535)
+        val = 65535;
+    rtc_set_memory(s, 0x17, val);
+    rtc_set_memory(s, 0x18, val >> 8);
+    rtc_set_memory(s, 0x30, val);
+    rtc_set_memory(s, 0x31, val >> 8);
+    /* memory between 16MiB and 4GiB */
+    if (ram_size > 16 * 1024 * 1024) {
+        val = (ram_size - 16 * 1024 * 1024) / 65536;
+    } else {
+        val = 0;
+    }
+    if (val > 65535)
+        val = 65535;
+    rtc_set_memory(s, 0x34, val);
+    rtc_set_memory(s, 0x35, val >> 8);
+    /* memory above 4GiB */
+    val = above_4g_mem_size / 65536;
+    rtc_set_memory(s, 0x5b, val);
+    rtc_set_memory(s, 0x5c, val >> 8);
+    rtc_set_memory(s, 0x5d, val >> 16);
+
+    /* set the number of CPU */
+    rtc_set_memory(s, 0x5f, smp_cpus - 1);
+
+    /* set boot devices, and disable floppy signature check if requested */
+    if (set_boot_dev(s, boot_device, fd_bootchk)) {
+        exit(1);
+    }
+
+    /* floppy type */
+    if (floppy) {
+        for (i = 0; i < 2; i++) {
+            fd_type[i] = isa_fdc_get_drive_type(floppy, i);
+        }
+    }
+    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 (fd_type[0] < FDRIVE_DRV_NONE) {
+        nb++;
+    }
+    if (fd_type[1] < FDRIVE_DRV_NONE) {
+        nb++;
+    }
+    switch (nb) {
+    case 0:
+        break;
+    case 1:
+        val |= 0x01; /* 1 drive, ready for boot */
+        break;
+    case 2:
+        val |= 0x41; /* 2 drives, ready for boot */
+        break;
+    }
+    val |= 0x02; /* FPU is there */
+    val |= 0x04; /* PS/2 mouse installed */
+    rtc_set_memory(s, REG_EQUIPMENT_BYTE, val);
+
+    /* hard drives */
+    arg.rtc_state = s;
+    arg.idebus[0] = idebus0;
+    arg.idebus[1] = idebus1;
+    qemu_register_reset(pc_cmos_init_late, &arg);
+}
+
+/* port 92 stuff: could be split off */
+typedef struct Port92State {
+    ISADevice dev;
+    MemoryRegion io;
+    uint8_t outport;
+    qemu_irq *a20_out;
+} Port92State;
+
+static void port92_write(void *opaque, hwaddr addr, uint64_t val,
+                         unsigned size)
+{
+    Port92State *s = opaque;
+
+    DPRINTF("port92: write 0x%02x\n", val);
+    s->outport = val;
+    qemu_set_irq(*s->a20_out, (val >> 1) & 1);
+    if (val & 1) {
+        qemu_system_reset_request();
+    }
+}
+
+static uint64_t port92_read(void *opaque, hwaddr addr,
+                            unsigned size)
+{
+    Port92State *s = opaque;
+    uint32_t ret;
+
+    ret = s->outport;
+    DPRINTF("port92: read 0x%02x\n", ret);
+    return ret;
+}
+
+static void port92_init(ISADevice *dev, qemu_irq *a20_out)
+{
+    Port92State *s = DO_UPCAST(Port92State, dev, dev);
+
+    s->a20_out = a20_out;
+}
+
+static const VMStateDescription vmstate_port92_isa = {
+    .name = "port92",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_UINT8(outport, Port92State),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void port92_reset(DeviceState *d)
+{
+    Port92State *s = container_of(d, Port92State, dev.qdev);
+
+    s->outport &= ~1;
+}
+
+static const MemoryRegionOps port92_ops = {
+    .read = port92_read,
+    .write = port92_write,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int port92_initfn(ISADevice *dev)
+{
+    Port92State *s = DO_UPCAST(Port92State, dev, dev);
+
+    memory_region_init_io(&s->io, &port92_ops, s, "port92", 1);
+    isa_register_ioport(dev, &s->io, 0x92);
+
+    s->outport = 0;
+    return 0;
+}
+
+static void port92_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+    ic->init = port92_initfn;
+    dc->no_user = 1;
+    dc->reset = port92_reset;
+    dc->vmsd = &vmstate_port92_isa;
+}
+
+static const TypeInfo port92_info = {
+    .name          = "port92",
+    .parent        = TYPE_ISA_DEVICE,
+    .instance_size = sizeof(Port92State),
+    .class_init    = port92_class_initfn,
+};
+
+static void port92_register_types(void)
+{
+    type_register_static(&port92_info);
+}
+
+type_init(port92_register_types)
+
+static void handle_a20_line_change(void *opaque, int irq, int level)
+{
+    X86CPU *cpu = opaque;
+
+    /* XXX: send to all CPUs ? */
+    /* XXX: add logic to handle multiple A20 line sources */
+    x86_cpu_set_a20(cpu, level);
+}
+
+int e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
+{
+    int index = le32_to_cpu(e820_table.count);
+    struct e820_entry *entry;
+
+    if (index >= E820_NR_ENTRIES)
+        return -EBUSY;
+    entry = &e820_table.entry[index++];
+
+    entry->address = cpu_to_le64(address);
+    entry->length = cpu_to_le64(length);
+    entry->type = cpu_to_le32(type);
+
+    e820_table.count = cpu_to_le32(index);
+    return index;
+}
+
+/* Calculates the limit to CPU APIC ID values
+ *
+ * This function returns the limit for the APIC ID value, so that all
+ * CPU APIC IDs are < pc_apic_id_limit().
+ *
+ * This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init().
+ */
+static unsigned int pc_apic_id_limit(unsigned int max_cpus)
+{
+    return x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
+}
+
+static void *bochs_bios_init(void)
+{
+    void *fw_cfg;
+    uint8_t *smbios_table;
+    size_t smbios_len;
+    uint64_t *numa_fw_cfg;
+    int i, j;
+    unsigned int apic_id_limit = pc_apic_id_limit(max_cpus);
+
+    fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
+    /* FW_CFG_MAX_CPUS is a bit confusing/problematic on x86:
+     *
+     * SeaBIOS needs FW_CFG_MAX_CPUS for CPU hotplug, but the CPU hotplug
+     * QEMU<->SeaBIOS interface is not based on the "CPU index", but on the APIC
+     * ID of hotplugged CPUs[1]. This means that FW_CFG_MAX_CPUS is not the
+     * "maximum number of CPUs", but the "limit to the APIC ID values SeaBIOS
+     * may see".
+     *
+     * So, this means we must not use max_cpus, here, but the maximum possible
+     * APIC ID value, plus one.
+     *
+     * [1] The only kind of "CPU identifier" used between SeaBIOS and QEMU is
+     *     the APIC ID, not the "CPU index"
+     */
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)apic_id_limit);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES,
+                     acpi_tables, acpi_tables_len);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
+
+    smbios_table = smbios_get_table(&smbios_len);
+    if (smbios_table)
+        fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES,
+                         smbios_table, smbios_len);
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE,
+                     &e820_table, sizeof(e820_table));
+
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_HPET, &hpet_cfg, sizeof(hpet_cfg));
+    /* allocate memory for the NUMA channel: one (64bit) word for the number
+     * of nodes, one word for each VCPU->node and one word for each node to
+     * hold the amount of memory.
+     */
+    numa_fw_cfg = g_new0(uint64_t, 1 + apic_id_limit + nb_numa_nodes);
+    numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes);
+    for (i = 0; i < max_cpus; i++) {
+        unsigned int apic_id = x86_cpu_apic_id_from_index(i);
+        assert(apic_id < apic_id_limit);
+        for (j = 0; j < nb_numa_nodes; j++) {
+            if (test_bit(i, node_cpumask[j])) {
+                numa_fw_cfg[apic_id + 1] = cpu_to_le64(j);
+                break;
+            }
+        }
+    }
+    for (i = 0; i < nb_numa_nodes; i++) {
+        numa_fw_cfg[apic_id_limit + 1 + i] = cpu_to_le64(node_mem[i]);
+    }
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, numa_fw_cfg,
+                     (1 + apic_id_limit + nb_numa_nodes) *
+                     sizeof(*numa_fw_cfg));
+
+    return fw_cfg;
+}
+
+static long get_file_size(FILE *f)
+{
+    long where, size;
+
+    /* XXX: on Unix systems, using fstat() probably makes more sense */
+
+    where = ftell(f);
+    fseek(f, 0, SEEK_END);
+    size = ftell(f);
+    fseek(f, where, SEEK_SET);
+
+    return size;
+}
+
+static void load_linux(void *fw_cfg,
+                       const char *kernel_filename,
+		       const char *initrd_filename,
+		       const char *kernel_cmdline,
+                       hwaddr max_ram_size)
+{
+    uint16_t protocol;
+    int setup_size, kernel_size, initrd_size = 0, cmdline_size;
+    uint32_t initrd_max;
+    uint8_t header[8192], *setup, *kernel, *initrd_data;
+    hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0;
+    FILE *f;
+    char *vmode;
+
+    /* Align to 16 bytes as a paranoia measure */
+    cmdline_size = (strlen(kernel_cmdline)+16) & ~15;
+
+    /* load the kernel header */
+    f = fopen(kernel_filename, "rb");
+    if (!f || !(kernel_size = get_file_size(f)) ||
+	fread(header, 1, MIN(ARRAY_SIZE(header), kernel_size), f) !=
+	MIN(ARRAY_SIZE(header), kernel_size)) {
+	fprintf(stderr, "qemu: could not load kernel '%s': %s\n",
+		kernel_filename, strerror(errno));
+	exit(1);
+    }
+
+    /* kernel protocol version */
+#if 0
+    fprintf(stderr, "header magic: %#x\n", ldl_p(header+0x202));
+#endif
+    if (ldl_p(header+0x202) == 0x53726448)
+	protocol = lduw_p(header+0x206);
+    else {
+	/* This looks like a multiboot kernel. If it is, let's stop
+	   treating it like a Linux kernel. */
+        if (load_multiboot(fw_cfg, f, kernel_filename, initrd_filename,
+                           kernel_cmdline, kernel_size, header))
+            return;
+	protocol = 0;
+    }
+
+    if (protocol < 0x200 || !(header[0x211] & 0x01)) {
+	/* Low kernel */
+	real_addr    = 0x90000;
+	cmdline_addr = 0x9a000 - cmdline_size;
+	prot_addr    = 0x10000;
+    } else if (protocol < 0x202) {
+	/* High but ancient kernel */
+	real_addr    = 0x90000;
+	cmdline_addr = 0x9a000 - cmdline_size;
+	prot_addr    = 0x100000;
+    } else {
+	/* High and recent kernel */
+	real_addr    = 0x10000;
+	cmdline_addr = 0x20000;
+	prot_addr    = 0x100000;
+    }
+
+#if 0
+    fprintf(stderr,
+	    "qemu: real_addr     = 0x" TARGET_FMT_plx "\n"
+	    "qemu: cmdline_addr  = 0x" TARGET_FMT_plx "\n"
+	    "qemu: prot_addr     = 0x" TARGET_FMT_plx "\n",
+	    real_addr,
+	    cmdline_addr,
+	    prot_addr);
+#endif
+
+    /* highest address for loading the initrd */
+    if (protocol >= 0x203)
+	initrd_max = ldl_p(header+0x22c);
+    else
+	initrd_max = 0x37ffffff;
+
+    if (initrd_max >= max_ram_size-ACPI_DATA_SIZE)
+    	initrd_max = max_ram_size-ACPI_DATA_SIZE-1;
+
+    fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, strlen(kernel_cmdline)+1);
+    fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
+
+    if (protocol >= 0x202) {
+	stl_p(header+0x228, cmdline_addr);
+    } else {
+	stw_p(header+0x20, 0xA33F);
+	stw_p(header+0x22, cmdline_addr-real_addr);
+    }
+
+    /* handle vga= parameter */
+    vmode = strstr(kernel_cmdline, "vga=");
+    if (vmode) {
+        unsigned int video_mode;
+        /* skip "vga=" */
+        vmode += 4;
+        if (!strncmp(vmode, "normal", 6)) {
+            video_mode = 0xffff;
+        } else if (!strncmp(vmode, "ext", 3)) {
+            video_mode = 0xfffe;
+        } else if (!strncmp(vmode, "ask", 3)) {
+            video_mode = 0xfffd;
+        } else {
+            video_mode = strtol(vmode, NULL, 0);
+        }
+        stw_p(header+0x1fa, video_mode);
+    }
+
+    /* loader type */
+    /* High nybble = B reserved for QEMU; low nybble is revision number.
+       If this code is substantially changed, you may want to consider
+       incrementing the revision. */
+    if (protocol >= 0x200)
+	header[0x210] = 0xB0;
+
+    /* heap */
+    if (protocol >= 0x201) {
+	header[0x211] |= 0x80;	/* CAN_USE_HEAP */
+	stw_p(header+0x224, cmdline_addr-real_addr-0x200);
+    }
+
+    /* load initrd */
+    if (initrd_filename) {
+	if (protocol < 0x200) {
+	    fprintf(stderr, "qemu: linux kernel too old to load a ram disk\n");
+	    exit(1);
+	}
+
+	initrd_size = get_image_size(initrd_filename);
+        if (initrd_size < 0) {
+            fprintf(stderr, "qemu: error reading initrd %s\n",
+                    initrd_filename);
+            exit(1);
+        }
+
+        initrd_addr = (initrd_max-initrd_size) & ~4095;
+
+        initrd_data = g_malloc(initrd_size);
+        load_image(initrd_filename, initrd_data);
+
+        fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
+        fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
+        fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data, initrd_size);
+
+	stl_p(header+0x218, initrd_addr);
+	stl_p(header+0x21c, initrd_size);
+    }
+
+    /* load kernel and setup */
+    setup_size = header[0x1f1];
+    if (setup_size == 0)
+	setup_size = 4;
+    setup_size = (setup_size+1)*512;
+    kernel_size -= setup_size;
+
+    setup  = g_malloc(setup_size);
+    kernel = g_malloc(kernel_size);
+    fseek(f, 0, SEEK_SET);
+    if (fread(setup, 1, setup_size, f) != setup_size) {
+        fprintf(stderr, "fread() failed\n");
+        exit(1);
+    }
+    if (fread(kernel, 1, kernel_size, f) != kernel_size) {
+        fprintf(stderr, "fread() failed\n");
+        exit(1);
+    }
+    fclose(f);
+    memcpy(setup, header, MIN(sizeof(header), setup_size));
+
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
+
+    fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size);
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size);
+
+    option_rom[nb_option_roms].name = "linuxboot.bin";
+    option_rom[nb_option_roms].bootindex = 0;
+    nb_option_roms++;
+}
+
+#define NE2000_NB_MAX 6
+
+static const int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360,
+                                              0x280, 0x380 };
+static const int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
+
+static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
+static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
+
+void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd)
+{
+    static int nb_ne2k = 0;
+
+    if (nb_ne2k == NE2000_NB_MAX)
+        return;
+    isa_ne2000_init(bus, ne2000_io[nb_ne2k],
+                    ne2000_irq[nb_ne2k], nd);
+    nb_ne2k++;
+}
+
+DeviceState *cpu_get_current_apic(void)
+{
+    if (cpu_single_env) {
+        return cpu_single_env->apic_state;
+    } else {
+        return NULL;
+    }
+}
+
+void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
+{
+    CPUX86State *s = opaque;
+
+    if (level) {
+        cpu_interrupt(s, CPU_INTERRUPT_SMI);
+    }
+}
+
+void pc_cpus_init(const char *cpu_model)
+{
+    int i;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+#ifdef TARGET_X86_64
+        cpu_model = "qemu64";
+#else
+        cpu_model = "qemu32";
+#endif
+    }
+
+    for (i = 0; i < smp_cpus; i++) {
+        if (!cpu_x86_init(cpu_model)) {
+            exit(1);
+        }
+    }
+}
+
+void pc_acpi_init(const char *default_dsdt)
+{
+    char *filename = NULL, *arg = NULL;
+
+    if (acpi_tables != NULL) {
+        /* manually set via -acpitable, leave it alone */
+        return;
+    }
+
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, default_dsdt);
+    if (filename == NULL) {
+        fprintf(stderr, "WARNING: failed to find %s\n", default_dsdt);
+        return;
+    }
+
+    arg = g_strdup_printf("file=%s", filename);
+    if (acpi_table_add(arg) != 0) {
+        fprintf(stderr, "WARNING: failed to load %s\n", filename);
+    }
+    g_free(arg);
+    g_free(filename);
+}
+
+void *pc_memory_init(MemoryRegion *system_memory,
+                    const char *kernel_filename,
+                    const char *kernel_cmdline,
+                    const char *initrd_filename,
+                    ram_addr_t below_4g_mem_size,
+                    ram_addr_t above_4g_mem_size,
+                    MemoryRegion *rom_memory,
+                    MemoryRegion **ram_memory)
+{
+    int linux_boot, i;
+    MemoryRegion *ram, *option_rom_mr;
+    MemoryRegion *ram_below_4g, *ram_above_4g;
+    void *fw_cfg;
+
+    linux_boot = (kernel_filename != NULL);
+
+    /* Allocate RAM.  We allocate it as a single memory region and use
+     * aliases to address portions of it, mostly for backwards compatibility
+     * with older qemus that used qemu_ram_alloc().
+     */
+    ram = g_malloc(sizeof(*ram));
+    memory_region_init_ram(ram, "pc.ram",
+                           below_4g_mem_size + above_4g_mem_size);
+    vmstate_register_ram_global(ram);
+    *ram_memory = ram;
+    ram_below_4g = g_malloc(sizeof(*ram_below_4g));
+    memory_region_init_alias(ram_below_4g, "ram-below-4g", ram,
+                             0, below_4g_mem_size);
+    memory_region_add_subregion(system_memory, 0, ram_below_4g);
+    if (above_4g_mem_size > 0) {
+        ram_above_4g = g_malloc(sizeof(*ram_above_4g));
+        memory_region_init_alias(ram_above_4g, "ram-above-4g", ram,
+                                 below_4g_mem_size, above_4g_mem_size);
+        memory_region_add_subregion(system_memory, 0x100000000ULL,
+                                    ram_above_4g);
+    }
+
+
+    /* Initialize PC system firmware */
+    pc_system_firmware_init(rom_memory);
+
+    option_rom_mr = g_malloc(sizeof(*option_rom_mr));
+    memory_region_init_ram(option_rom_mr, "pc.rom", PC_ROM_SIZE);
+    vmstate_register_ram_global(option_rom_mr);
+    memory_region_add_subregion_overlap(rom_memory,
+                                        PC_ROM_MIN_VGA,
+                                        option_rom_mr,
+                                        1);
+
+    fw_cfg = bochs_bios_init();
+    rom_set_fw(fw_cfg);
+
+    if (linux_boot) {
+        load_linux(fw_cfg, kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size);
+    }
+
+    for (i = 0; i < nb_option_roms; i++) {
+        rom_add_option(option_rom[i].name, option_rom[i].bootindex);
+    }
+    return fw_cfg;
+}
+
+qemu_irq *pc_allocate_cpu_irq(void)
+{
+    return qemu_allocate_irqs(pic_irq_request, NULL, 1);
+}
+
+DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
+{
+    DeviceState *dev = NULL;
+
+    if (pci_bus) {
+        PCIDevice *pcidev = pci_vga_init(pci_bus);
+        dev = pcidev ? &pcidev->qdev : NULL;
+    } else if (isa_bus) {
+        ISADevice *isadev = isa_vga_init(isa_bus);
+        dev = isadev ? &isadev->qdev : NULL;
+    }
+    return dev;
+}
+
+static void cpu_request_exit(void *opaque, int irq, int level)
+{
+    CPUX86State *env = cpu_single_env;
+
+    if (env && level) {
+        cpu_exit(env);
+    }
+}
+
+static const MemoryRegionOps ioport80_io_ops = {
+    .write = ioport80_write,
+    .read = ioport80_read,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
+static const MemoryRegionOps ioportF0_io_ops = {
+    .write = ioportF0_write,
+    .read = ioportF0_read,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
+void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
+                          ISADevice **rtc_state,
+                          ISADevice **floppy,
+                          bool no_vmport)
+{
+    int i;
+    DriveInfo *fd[MAX_FD];
+    DeviceState *hpet = NULL;
+    int pit_isa_irq = 0;
+    qemu_irq pit_alt_irq = NULL;
+    qemu_irq rtc_irq = NULL;
+    qemu_irq *a20_line;
+    ISADevice *i8042, *port92, *vmmouse, *pit = NULL;
+    qemu_irq *cpu_exit_irq;
+    MemoryRegion *ioport80_io = g_new(MemoryRegion, 1);
+    MemoryRegion *ioportF0_io = g_new(MemoryRegion, 1);
+
+    memory_region_init_io(ioport80_io, &ioport80_io_ops, NULL, "ioport80", 1);
+    memory_region_add_subregion(isa_bus->address_space_io, 0x80, ioport80_io);
+
+    memory_region_init_io(ioportF0_io, &ioportF0_io_ops, NULL, "ioportF0", 1);
+    memory_region_add_subregion(isa_bus->address_space_io, 0xf0, ioportF0_io);
+
+    /*
+     * Check if an HPET shall be created.
+     *
+     * Without KVM_CAP_PIT_STATE2, we cannot switch off the in-kernel PIT
+     * when the HPET wants to take over. Thus we have to disable the latter.
+     */
+    if (!no_hpet && (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) {
+        hpet = sysbus_try_create_simple("hpet", HPET_BASE, NULL);
+
+        if (hpet) {
+            for (i = 0; i < GSI_NUM_PINS; i++) {
+                sysbus_connect_irq(SYS_BUS_DEVICE(hpet), i, gsi[i]);
+            }
+            pit_isa_irq = -1;
+            pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT);
+            rtc_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_RTC_INT);
+        }
+    }
+    *rtc_state = rtc_init(isa_bus, 2000, rtc_irq);
+
+    qemu_register_boot_set(pc_boot_set, *rtc_state);
+
+    if (!xen_enabled()) {
+        if (kvm_irqchip_in_kernel()) {
+            pit = kvm_pit_init(isa_bus, 0x40);
+        } else {
+            pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
+        }
+        if (hpet) {
+            /* connect PIT to output control line of the HPET */
+            qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0));
+        }
+        pcspk_init(isa_bus, pit);
+    }
+
+    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
+        if (serial_hds[i]) {
+            serial_isa_init(isa_bus, i, serial_hds[i]);
+        }
+    }
+
+    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
+        if (parallel_hds[i]) {
+            parallel_init(isa_bus, i, parallel_hds[i]);
+        }
+    }
+
+    a20_line = qemu_allocate_irqs(handle_a20_line_change,
+                                  x86_env_get_cpu(first_cpu), 2);
+    i8042 = isa_create_simple(isa_bus, "i8042");
+    i8042_setup_a20_line(i8042, &a20_line[0]);
+    if (!no_vmport) {
+        vmport_init(isa_bus);
+        vmmouse = isa_try_create(isa_bus, "vmmouse");
+    } else {
+        vmmouse = NULL;
+    }
+    if (vmmouse) {
+        qdev_prop_set_ptr(&vmmouse->qdev, "ps2_mouse", i8042);
+        qdev_init_nofail(&vmmouse->qdev);
+    }
+    port92 = isa_create_simple(isa_bus, "port92");
+    port92_init(port92, &a20_line[1]);
+
+    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
+    DMA_init(0, cpu_exit_irq);
+
+    for(i = 0; i < MAX_FD; i++) {
+        fd[i] = drive_get(IF_FLOPPY, 0, i);
+    }
+    *floppy = fdctrl_init_isa(isa_bus, fd);
+}
+
+void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus)
+{
+    int i;
+
+    for (i = 0; i < nb_nics; i++) {
+        NICInfo *nd = &nd_table[i];
+
+        if (!pci_bus || (nd->model && strcmp(nd->model, "ne2k_isa") == 0)) {
+            pc_init_ne2k_isa(isa_bus, nd);
+        } else {
+            pci_nic_init_nofail(nd, "e1000", NULL);
+        }
+    }
+}
+
+void pc_pci_device_init(PCIBus *pci_bus)
+{
+    int max_bus;
+    int bus;
+
+    max_bus = drive_get_max_bus(IF_SCSI);
+    for (bus = 0; bus <= max_bus; bus++) {
+        pci_create_simple(pci_bus, -1, "lsi53c895a");
+    }
+}
+
+void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name)
+{
+    DeviceState *dev;
+    SysBusDevice *d;
+    unsigned int i;
+
+    if (kvm_irqchip_in_kernel()) {
+        dev = qdev_create(NULL, "kvm-ioapic");
+    } else {
+        dev = qdev_create(NULL, "ioapic");
+    }
+    if (parent_name) {
+        object_property_add_child(object_resolve_path(parent_name, NULL),
+                                  "ioapic", OBJECT(dev), NULL);
+    }
+    qdev_init_nofail(dev);
+    d = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(d, 0, 0xfec00000);
+
+    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+        gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i);
+    }
+}
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
new file mode 100644
index 0000000..73a8656
--- /dev/null
+++ b/hw/i386/pc_piix.c
@@ -0,0 +1,713 @@
+/*
+ * QEMU PC System Emulator
+ *
+ * Copyright (c) 2003-2004 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 <glib.h>
+
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/apic.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_ids.h"
+#include "hw/usb.h"
+#include "net/net.h"
+#include "hw/boards.h"
+#include "hw/ide.h"
+#include "sysemu/kvm.h"
+#include "hw/kvm/clock.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+#include "sysemu/arch_init.h"
+#include "sysemu/blockdev.h"
+#include "hw/smbus.h"
+#include "hw/xen.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "cpu.h"
+#ifdef CONFIG_XEN
+#  include <xen/hvm/hvm_info_table.h>
+#endif
+
+#define MAX_IDE_BUS 2
+
+static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
+static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
+static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
+
+/* PC hardware initialisation */
+static void pc_init1(MemoryRegion *system_memory,
+                     MemoryRegion *system_io,
+                     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,
+                     int pci_enabled,
+                     int kvmclock_enabled)
+{
+    int i;
+    ram_addr_t below_4g_mem_size, above_4g_mem_size;
+    PCIBus *pci_bus;
+    ISABus *isa_bus;
+    PCII440FXState *i440fx_state;
+    int piix3_devfn = -1;
+    qemu_irq *cpu_irq;
+    qemu_irq *gsi;
+    qemu_irq *i8259;
+    qemu_irq *smi_irq;
+    GSIState *gsi_state;
+    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    BusState *idebus[MAX_IDE_BUS];
+    ISADevice *rtc_state;
+    ISADevice *floppy;
+    MemoryRegion *ram_memory;
+    MemoryRegion *pci_memory;
+    MemoryRegion *rom_memory;
+    void *fw_cfg = NULL;
+
+    pc_cpus_init(cpu_model);
+    pc_acpi_init("acpi-dsdt.aml");
+
+    if (kvmclock_enabled) {
+        kvmclock_create();
+    }
+
+    if (ram_size >= 0xe0000000 ) {
+        above_4g_mem_size = ram_size - 0xe0000000;
+        below_4g_mem_size = 0xe0000000;
+    } else {
+        above_4g_mem_size = 0;
+        below_4g_mem_size = ram_size;
+    }
+
+    if (pci_enabled) {
+        pci_memory = g_new(MemoryRegion, 1);
+        memory_region_init(pci_memory, "pci", INT64_MAX);
+        rom_memory = pci_memory;
+    } else {
+        pci_memory = NULL;
+        rom_memory = system_memory;
+    }
+
+    /* allocate ram and load rom/bios */
+    if (!xen_enabled()) {
+        fw_cfg = pc_memory_init(system_memory,
+                       kernel_filename, kernel_cmdline, initrd_filename,
+                       below_4g_mem_size, above_4g_mem_size,
+                       rom_memory, &ram_memory);
+    }
+
+    gsi_state = g_malloc0(sizeof(*gsi_state));
+    if (kvm_irqchip_in_kernel()) {
+        kvm_pc_setup_irq_routing(pci_enabled);
+        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
+                                 GSI_NUM_PINS);
+    } else {
+        gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
+    }
+
+    if (pci_enabled) {
+        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
+                              system_memory, system_io, ram_size,
+                              below_4g_mem_size,
+                              0x100000000ULL - below_4g_mem_size,
+                              0x100000000ULL + above_4g_mem_size,
+                              (sizeof(hwaddr) == 4
+                               ? 0
+                               : ((uint64_t)1 << 62)),
+                              pci_memory, ram_memory);
+    } else {
+        pci_bus = NULL;
+        i440fx_state = NULL;
+        isa_bus = isa_bus_new(NULL, system_io);
+        no_hpet = 1;
+    }
+    isa_bus_irqs(isa_bus, gsi);
+
+    if (kvm_irqchip_in_kernel()) {
+        i8259 = kvm_i8259_init(isa_bus);
+    } else if (xen_enabled()) {
+        i8259 = xen_interrupt_controller_init();
+    } else {
+        cpu_irq = pc_allocate_cpu_irq();
+        i8259 = i8259_init(isa_bus, cpu_irq[0]);
+    }
+
+    for (i = 0; i < ISA_NUM_IRQS; i++) {
+        gsi_state->i8259_irq[i] = i8259[i];
+    }
+    if (pci_enabled) {
+        ioapic_init_gsi(gsi_state, "i440fx");
+    }
+
+    pc_register_ferr_irq(gsi[13]);
+
+    pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
+    if (xen_enabled()) {
+        pci_create_simple(pci_bus, -1, "xen-platform");
+    }
+
+    /* init basic PC hardware */
+    pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled());
+
+    pc_nic_init(isa_bus, pci_bus);
+
+    ide_drive_get(hd, MAX_IDE_BUS);
+    if (pci_enabled) {
+        PCIDevice *dev;
+        if (xen_enabled()) {
+            dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
+        } else {
+            dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
+        }
+        idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
+        idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
+    } else {
+        for(i = 0; i < MAX_IDE_BUS; i++) {
+            ISADevice *dev;
+            dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
+                               ide_irq[i],
+                               hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
+            idebus[i] = qdev_get_child_bus(&dev->qdev, "ide.0");
+        }
+    }
+
+    audio_init(isa_bus, pci_enabled ? pci_bus : NULL);
+
+    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
+                 floppy, idebus[0], idebus[1], rtc_state);
+
+    if (pci_enabled && usb_enabled(false)) {
+        pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
+    }
+
+    if (pci_enabled && acpi_enabled) {
+        i2c_bus *smbus;
+
+        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,
+                              gsi[9], *smi_irq,
+                              kvm_enabled(), fw_cfg);
+        smbus_eeprom_init(smbus, 8, NULL, 0);
+    }
+
+    if (pci_enabled) {
+        pc_pci_device_init(pci_bus);
+    }
+}
+
+static void pc_init_pci(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    pc_init1(get_system_memory(),
+             get_system_io(),
+             ram_size, boot_device,
+             kernel_filename, kernel_cmdline,
+             initrd_filename, cpu_model, 1, 1);
+}
+
+static void pc_init_pci_1_3(QEMUMachineInitArgs *args)
+{
+    enable_compat_apic_id_mode();
+    pc_init_pci(args);
+}
+
+/* PC machine init function for pc-0.14 to pc-1.2 */
+static void pc_init_pci_1_2(QEMUMachineInitArgs *args)
+{
+    disable_kvm_pv_eoi();
+    pc_init_pci_1_3(args);
+}
+
+/* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */
+static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    disable_kvm_pv_eoi();
+    enable_compat_apic_id_mode();
+    pc_init1(get_system_memory(),
+             get_system_io(),
+             ram_size, boot_device,
+             kernel_filename, kernel_cmdline,
+             initrd_filename, cpu_model, 1, 0);
+}
+
+static void pc_init_isa(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    if (cpu_model == NULL)
+        cpu_model = "486";
+    disable_kvm_pv_eoi();
+    enable_compat_apic_id_mode();
+    pc_init1(get_system_memory(),
+             get_system_io(),
+             ram_size, boot_device,
+             kernel_filename, kernel_cmdline,
+             initrd_filename, cpu_model, 0, 1);
+}
+
+#ifdef CONFIG_XEN
+static void pc_xen_hvm_init(QEMUMachineInitArgs *args)
+{
+    if (xen_hvm_init() != 0) {
+        hw_error("xen hardware virtual machine initialisation failed");
+    }
+    pc_init_pci_no_kvmclock(args);
+    xen_vcpu_init();
+}
+#endif
+
+static QEMUMachine pc_i440fx_machine_v1_5 = {
+    .name = "pc-i440fx-1.5",
+    .alias = "pc",
+    .desc = "Standard PC (i440FX + PIIX, 1996)",
+    .init = pc_init_pci,
+    .max_cpus = 255,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine pc_i440fx_machine_v1_4 = {
+    .name = "pc-i440fx-1.4",
+    .desc = "Standard PC (i440FX + PIIX, 1996)",
+    .init = pc_init_pci,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_1_4,
+        { /* end of list */ }
+    },
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_1_3 \
+	PC_COMPAT_1_4, \
+        {\
+            .driver   = "usb-tablet",\
+            .property = "usb_version",\
+            .value    = stringify(1),\
+        },{\
+            .driver   = "virtio-net-pci",\
+            .property = "ctrl_mac_addr",\
+            .value    = "off",      \
+        },{ \
+            .driver   = "virtio-net-pci", \
+            .property = "mq", \
+            .value    = "off", \
+        }
+
+static QEMUMachine pc_machine_v1_3 = {
+    .name = "pc-1.3",
+    .desc = "Standard PC",
+    .init = pc_init_pci_1_3,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_1_3,
+        { /* end of list */ }
+    },
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_1_2 \
+        PC_COMPAT_1_3,\
+        {\
+            .driver   = "nec-usb-xhci",\
+            .property = "msi",\
+            .value    = "off",\
+        },{\
+            .driver   = "nec-usb-xhci",\
+            .property = "msix",\
+            .value    = "off",\
+        },{\
+            .driver   = "ivshmem",\
+            .property = "use64",\
+            .value    = "0",\
+        },{\
+            .driver   = "qxl",\
+            .property = "revision",\
+            .value    = stringify(3),\
+        },{\
+            .driver   = "qxl-vga",\
+            .property = "revision",\
+            .value    = stringify(3),\
+        },{\
+            .driver   = "VGA",\
+            .property = "mmio",\
+            .value    = "off",\
+        }
+
+static QEMUMachine pc_machine_v1_2 = {
+    .name = "pc-1.2",
+    .desc = "Standard PC",
+    .init = pc_init_pci_1_2,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_1_2,
+        { /* end of list */ }
+    },
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_1_1 \
+        PC_COMPAT_1_2,\
+        {\
+            .driver   = "virtio-scsi-pci",\
+            .property = "hotplug",\
+            .value    = "off",\
+        },{\
+            .driver   = "virtio-scsi-pci",\
+            .property = "param_change",\
+            .value    = "off",\
+        },{\
+            .driver   = "VGA",\
+            .property = "vgamem_mb",\
+            .value    = stringify(8),\
+        },{\
+            .driver   = "vmware-svga",\
+            .property = "vgamem_mb",\
+            .value    = stringify(8),\
+        },{\
+            .driver   = "qxl-vga",\
+            .property = "vgamem_mb",\
+            .value    = stringify(8),\
+        },{\
+            .driver   = "qxl",\
+            .property = "vgamem_mb",\
+            .value    = stringify(8),\
+        },{\
+            .driver   = "virtio-blk-pci",\
+            .property = "config-wce",\
+            .value    = "off",\
+        }
+
+static QEMUMachine pc_machine_v1_1 = {
+    .name = "pc-1.1",
+    .desc = "Standard PC",
+    .init = pc_init_pci_1_2,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_1_1,
+        { /* end of list */ }
+    },
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_1_0 \
+        PC_COMPAT_1_1,\
+        {\
+            .driver   = "pc-sysfw",\
+            .property = "rom_only",\
+            .value    = stringify(1),\
+        }, {\
+            .driver   = "isa-fdc",\
+            .property = "check_media_rate",\
+            .value    = "off",\
+        }, {\
+            .driver   = "virtio-balloon-pci",\
+            .property = "class",\
+            .value    = stringify(PCI_CLASS_MEMORY_RAM),\
+        },{\
+            .driver   = "apic",\
+            .property = "vapic",\
+            .value    = "off",\
+        },{\
+            .driver   = TYPE_USB_DEVICE,\
+            .property = "full-path",\
+            .value    = "no",\
+        }
+
+static QEMUMachine pc_machine_v1_0 = {
+    .name = "pc-1.0",
+    .desc = "Standard PC",
+    .init = pc_init_pci_1_2,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_1_0,
+        { /* end of list */ }
+    },
+    .hw_version = "1.0",
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_0_15 \
+        PC_COMPAT_1_0
+
+static QEMUMachine pc_machine_v0_15 = {
+    .name = "pc-0.15",
+    .desc = "Standard PC",
+    .init = pc_init_pci_1_2,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_0_15,
+        { /* end of list */ }
+    },
+    .hw_version = "0.15",
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_0_14 \
+        PC_COMPAT_0_15,\
+        {\
+            .driver   = "virtio-blk-pci",\
+            .property = "event_idx",\
+            .value    = "off",\
+        },{\
+            .driver   = "virtio-serial-pci",\
+            .property = "event_idx",\
+            .value    = "off",\
+        },{\
+            .driver   = "virtio-net-pci",\
+            .property = "event_idx",\
+            .value    = "off",\
+        },{\
+            .driver   = "virtio-balloon-pci",\
+            .property = "event_idx",\
+            .value    = "off",\
+        }
+
+static QEMUMachine pc_machine_v0_14 = {
+    .name = "pc-0.14",
+    .desc = "Standard PC",
+    .init = pc_init_pci_1_2,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_0_14, 
+        {
+            .driver   = "qxl",
+            .property = "revision",
+            .value    = stringify(2),
+        },{
+            .driver   = "qxl-vga",
+            .property = "revision",
+            .value    = stringify(2),
+        },
+        { /* end of list */ }
+    },
+    .hw_version = "0.14",
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_0_13 \
+        PC_COMPAT_0_14,\
+        {\
+            .driver   = TYPE_PCI_DEVICE,\
+            .property = "command_serr_enable",\
+            .value    = "off",\
+        },{\
+            .driver   = "AC97",\
+            .property = "use_broken_id",\
+            .value    = stringify(1),\
+        }
+
+static QEMUMachine pc_machine_v0_13 = {
+    .name = "pc-0.13",
+    .desc = "Standard PC",
+    .init = pc_init_pci_no_kvmclock,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_0_13,
+        {
+            .driver   = "virtio-9p-pci",
+            .property = "vectors",
+            .value    = stringify(0),
+        },{
+            .driver   = "VGA",
+            .property = "rombar",
+            .value    = stringify(0),
+        },{
+            .driver   = "vmware-svga",
+            .property = "rombar",
+            .value    = stringify(0),
+        },
+        { /* end of list */ }
+    },
+    .hw_version = "0.13",
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_0_12 \
+        PC_COMPAT_0_13,\
+        {\
+            .driver   = "virtio-serial-pci",\
+            .property = "max_ports",\
+            .value    = stringify(1),\
+        },{\
+            .driver   = "virtio-serial-pci",\
+            .property = "vectors",\
+            .value    = stringify(0),\
+        }
+
+static QEMUMachine pc_machine_v0_12 = {
+    .name = "pc-0.12",
+    .desc = "Standard PC",
+    .init = pc_init_pci_no_kvmclock,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_0_12,
+        {
+            .driver   = "VGA",
+            .property = "rombar",
+            .value    = stringify(0),
+        },{
+            .driver   = "vmware-svga",
+            .property = "rombar",
+            .value    = stringify(0),
+        },
+        { /* end of list */ }
+    },
+    .hw_version = "0.12",
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#define PC_COMPAT_0_11 \
+        PC_COMPAT_0_12,\
+        {\
+            .driver   = "virtio-blk-pci",\
+            .property = "vectors",\
+            .value    = stringify(0),\
+        },{\
+            .driver   = TYPE_PCI_DEVICE,\
+            .property = "rombar",\
+            .value    = stringify(0),\
+        }
+
+static QEMUMachine pc_machine_v0_11 = {
+    .name = "pc-0.11",
+    .desc = "Standard PC, qemu 0.11",
+    .init = pc_init_pci_no_kvmclock,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_0_11,
+        {
+            .driver   = "ide-drive",
+            .property = "ver",
+            .value    = "0.11",
+        },{
+            .driver   = "scsi-disk",
+            .property = "ver",
+            .value    = "0.11",
+        },
+        { /* end of list */ }
+    },
+    .hw_version = "0.11",
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine pc_machine_v0_10 = {
+    .name = "pc-0.10",
+    .desc = "Standard PC, qemu 0.10",
+    .init = pc_init_pci_no_kvmclock,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_0_11,
+        {
+            .driver   = "virtio-blk-pci",
+            .property = "class",
+            .value    = stringify(PCI_CLASS_STORAGE_OTHER),
+        },{
+            .driver   = "virtio-serial-pci",
+            .property = "class",
+            .value    = stringify(PCI_CLASS_DISPLAY_OTHER),
+        },{
+            .driver   = "virtio-net-pci",
+            .property = "vectors",
+            .value    = stringify(0),
+        },{
+            .driver   = "ide-drive",
+            .property = "ver",
+            .value    = "0.10",
+        },{
+            .driver   = "scsi-disk",
+            .property = "ver",
+            .value    = "0.10",
+        },
+        { /* end of list */ }
+    },
+    .hw_version = "0.10",
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine isapc_machine = {
+    .name = "isapc",
+    .desc = "ISA-only PC",
+    .init = pc_init_isa,
+    .max_cpus = 1,
+    .compat_props = (GlobalProperty[]) {
+        {
+            .driver   = "pc-sysfw",
+            .property = "rom_only",
+            .value    = stringify(1),
+        },
+        { /* end of list */ }
+    },
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+#ifdef CONFIG_XEN
+static QEMUMachine xenfv_machine = {
+    .name = "xenfv",
+    .desc = "Xen Fully-virtualized PC",
+    .init = pc_xen_hvm_init,
+    .max_cpus = HVM_MAX_VCPUS,
+    .default_machine_opts = "accel=xen",
+    DEFAULT_MACHINE_OPTIONS,
+};
+#endif
+
+static void pc_machine_init(void)
+{
+    qemu_register_machine(&pc_i440fx_machine_v1_5);
+    qemu_register_machine(&pc_i440fx_machine_v1_4);
+    qemu_register_machine(&pc_machine_v1_3);
+    qemu_register_machine(&pc_machine_v1_2);
+    qemu_register_machine(&pc_machine_v1_1);
+    qemu_register_machine(&pc_machine_v1_0);
+    qemu_register_machine(&pc_machine_v0_15);
+    qemu_register_machine(&pc_machine_v0_14);
+    qemu_register_machine(&pc_machine_v0_13);
+    qemu_register_machine(&pc_machine_v0_12);
+    qemu_register_machine(&pc_machine_v0_11);
+    qemu_register_machine(&pc_machine_v0_10);
+    qemu_register_machine(&isapc_machine);
+#ifdef CONFIG_XEN
+    qemu_register_machine(&xenfv_machine);
+#endif
+}
+
+machine_init(pc_machine_init);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
new file mode 100644
index 0000000..4f5f347
--- /dev/null
+++ b/hw/i386/pc_q35.c
@@ -0,0 +1,239 @@
+/*
+ * Q35 chipset based pc system emulator
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2009, 2010
+ *               Isaku Yamahata <yamahata at valinux co jp>
+ *               VA Linux Systems Japan K.K.
+ * Copyright (C) 2012 Jason Baron <jbaron at redhat.com>
+ *
+ * This is based on pc.c, but heavily modified.
+ *
+ * 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/hw.h"
+#include "sysemu/arch_init.h"
+#include "hw/smbus.h"
+#include "hw/boards.h"
+#include "hw/mc146818rtc.h"
+#include "hw/xen.h"
+#include "sysemu/kvm.h"
+#include "hw/kvm/clock.h"
+#include "hw/q35.h"
+#include "exec/address-spaces.h"
+#include "hw/ich9.h"
+#include "hw/ide/pci.h"
+#include "hw/ide/ahci.h"
+#include "hw/usb.h"
+
+/* ICH9 AHCI has 6 ports */
+#define MAX_SATA_PORTS     6
+
+/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
+ *    BIOS will read it and start S3 resume at POST Entry */
+static void pc_cmos_set_s3_resume(void *opaque, int irq, int level)
+{
+    ISADevice *s = opaque;
+
+    if (level) {
+        rtc_set_memory(s, 0xF, 0xFE);
+    }
+}
+
+/* PC hardware initialisation */
+static void pc_q35_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    ram_addr_t below_4g_mem_size, above_4g_mem_size;
+    Q35PCIHost *q35_host;
+    PCIBus *host_bus;
+    PCIDevice *lpc;
+    BusState *idebus[MAX_SATA_PORTS];
+    ISADevice *rtc_state;
+    ISADevice *floppy;
+    MemoryRegion *pci_memory;
+    MemoryRegion *rom_memory;
+    MemoryRegion *ram_memory;
+    GSIState *gsi_state;
+    ISABus *isa_bus;
+    int pci_enabled = 1;
+    qemu_irq *cpu_irq;
+    qemu_irq *gsi;
+    qemu_irq *i8259;
+    int i;
+    ICH9LPCState *ich9_lpc;
+    PCIDevice *ahci;
+    qemu_irq *cmos_s3;
+
+    pc_cpus_init(cpu_model);
+    pc_acpi_init("q35-acpi-dsdt.aml");
+
+    kvmclock_create();
+
+    if (ram_size >= 0xb0000000) {
+        above_4g_mem_size = ram_size - 0xb0000000;
+        below_4g_mem_size = 0xb0000000;
+    } else {
+        above_4g_mem_size = 0;
+        below_4g_mem_size = ram_size;
+    }
+
+    /* pci enabled */
+    if (pci_enabled) {
+        pci_memory = g_new(MemoryRegion, 1);
+        memory_region_init(pci_memory, "pci", INT64_MAX);
+        rom_memory = pci_memory;
+    } else {
+        pci_memory = NULL;
+        rom_memory = get_system_memory();
+    }
+
+    /* allocate ram and load rom/bios */
+    if (!xen_enabled()) {
+        pc_memory_init(get_system_memory(), kernel_filename, kernel_cmdline,
+                       initrd_filename, below_4g_mem_size, above_4g_mem_size,
+                       rom_memory, &ram_memory);
+    }
+
+    /* irq lines */
+    gsi_state = g_malloc0(sizeof(*gsi_state));
+    if (kvm_irqchip_in_kernel()) {
+        kvm_pc_setup_irq_routing(pci_enabled);
+        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
+                                 GSI_NUM_PINS);
+    } else {
+        gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
+    }
+
+    /* create pci host bus */
+    q35_host = Q35_HOST_DEVICE(qdev_create(NULL, TYPE_Q35_HOST_DEVICE));
+
+    q35_host->mch.ram_memory = ram_memory;
+    q35_host->mch.pci_address_space = pci_memory;
+    q35_host->mch.system_memory = get_system_memory();
+    q35_host->mch.address_space_io = get_system_io();;
+    q35_host->mch.below_4g_mem_size = below_4g_mem_size;
+    q35_host->mch.above_4g_mem_size = above_4g_mem_size;
+    /* pci */
+    qdev_init_nofail(DEVICE(q35_host));
+    host_bus = q35_host->host.pci.bus;
+    /* create ISA bus */
+    lpc = pci_create_simple_multifunction(host_bus, PCI_DEVFN(ICH9_LPC_DEV,
+                                          ICH9_LPC_FUNC), true,
+                                          TYPE_ICH9_LPC_DEVICE);
+    ich9_lpc = ICH9_LPC_DEVICE(lpc);
+    ich9_lpc->pic = gsi;
+    ich9_lpc->ioapic = gsi_state->ioapic_irq;
+    pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc,
+                 ICH9_LPC_NB_PIRQS);
+    pci_bus_set_route_irq_fn(host_bus, ich9_route_intx_pin_to_irq);
+    isa_bus = ich9_lpc->isa_bus;
+
+    /*end early*/
+    isa_bus_irqs(isa_bus, gsi);
+
+    if (kvm_irqchip_in_kernel()) {
+        i8259 = kvm_i8259_init(isa_bus);
+    } else if (xen_enabled()) {
+        i8259 = xen_interrupt_controller_init();
+    } else {
+        cpu_irq = pc_allocate_cpu_irq();
+        i8259 = i8259_init(isa_bus, cpu_irq[0]);
+    }
+
+    for (i = 0; i < ISA_NUM_IRQS; i++) {
+        gsi_state->i8259_irq[i] = i8259[i];
+    }
+    if (pci_enabled) {
+        ioapic_init_gsi(gsi_state, NULL);
+    }
+
+    pc_register_ferr_irq(gsi[13]);
+
+    /* init basic PC hardware */
+    pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, false);
+
+    /* connect pm stuff to lpc */
+    cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
+    ich9_lpc_pm_init(lpc, *cmos_s3);
+
+    /* ahci and SATA device, for q35 1 ahci controller is built-in */
+    ahci = pci_create_simple_multifunction(host_bus,
+                                           PCI_DEVFN(ICH9_SATA1_DEV,
+                                                     ICH9_SATA1_FUNC),
+                                           true, "ich9-ahci");
+    idebus[0] = qdev_get_child_bus(&ahci->qdev, "ide.0");
+    idebus[1] = qdev_get_child_bus(&ahci->qdev, "ide.1");
+
+    if (usb_enabled(false)) {
+        /* Should we create 6 UHCI according to ich9 spec? */
+        ehci_create_ich9_with_companions(host_bus, 0x1d);
+    }
+
+    /* TODO: Populate SPD eeprom data.  */
+    smbus_eeprom_init(ich9_smb_init(host_bus,
+                                    PCI_DEVFN(ICH9_SMB_DEV, ICH9_SMB_FUNC),
+                                    0xb100),
+                      8, NULL, 0);
+
+    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
+                 floppy, idebus[0], idebus[1], rtc_state);
+
+    /* the rest devices to which pci devfn is automatically assigned */
+    pc_vga_init(isa_bus, host_bus);
+    audio_init(isa_bus, host_bus);
+    pc_nic_init(isa_bus, host_bus);
+    if (pci_enabled) {
+        pc_pci_device_init(host_bus);
+    }
+}
+
+static QEMUMachine pc_q35_machine_v1_5 = {
+    .name = "pc-q35-1.5",
+    .alias = "q35",
+    .desc = "Standard PC (Q35 + ICH9, 2009)",
+    .init = pc_q35_init,
+    .max_cpus = 255,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine pc_q35_machine_v1_4 = {
+    .name = "pc-q35-1.4",
+    .desc = "Standard PC (Q35 + ICH9, 2009)",
+    .init = pc_q35_init,
+    .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_COMPAT_1_4,
+        { /* end of list */ }
+    },
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void pc_q35_machine_init(void)
+{
+    qemu_register_machine(&pc_q35_machine_v1_5);
+    qemu_register_machine(&pc_q35_machine_v1_4);
+}
+
+machine_init(pc_q35_machine_init);
diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c
new file mode 100644
index 0000000..672ee9b
--- /dev/null
+++ b/hw/i386/smbios.c
@@ -0,0 +1,241 @@
+/*
+ * SMBIOS Support
+ *
+ * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * Authors:
+ *  Alex Williamson <alex.williamson at hp.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "sysemu/sysemu.h"
+#include "hw/smbios.h"
+#include "hw/loader.h"
+
+/*
+ * Structures shared with the BIOS
+ */
+struct smbios_header {
+    uint16_t length;
+    uint8_t type;
+} QEMU_PACKED;
+
+struct smbios_field {
+    struct smbios_header header;
+    uint8_t type;
+    uint16_t offset;
+    uint8_t data[];
+} QEMU_PACKED;
+
+struct smbios_table {
+    struct smbios_header header;
+    uint8_t data[];
+} QEMU_PACKED;
+
+#define SMBIOS_FIELD_ENTRY 0
+#define SMBIOS_TABLE_ENTRY 1
+
+
+static uint8_t *smbios_entries;
+static size_t smbios_entries_len;
+static int smbios_type4_count = 0;
+
+static void smbios_validate_table(void)
+{
+    if (smbios_type4_count && smbios_type4_count != smp_cpus) {
+         fprintf(stderr,
+                 "Number of SMBIOS Type 4 tables must match cpu count.\n");
+        exit(1);
+    }
+}
+
+uint8_t *smbios_get_table(size_t *length)
+{
+    smbios_validate_table();
+    *length = smbios_entries_len;
+    return smbios_entries;
+}
+
+/*
+ * To avoid unresolvable overlaps in data, don't allow both
+ * tables and fields for the same smbios type.
+ */
+static void smbios_check_collision(int type, int entry)
+{
+    uint16_t *num_entries = (uint16_t *)smbios_entries;
+    struct smbios_header *header;
+    char *p;
+    int i;
+
+    if (!num_entries)
+        return;
+
+    p = (char *)(num_entries + 1);
+
+    for (i = 0; i < *num_entries; i++) {
+        header = (struct smbios_header *)p;
+        if (entry == SMBIOS_TABLE_ENTRY && header->type == SMBIOS_FIELD_ENTRY) {
+            struct smbios_field *field = (void *)header;
+            if (type == field->type) {
+                fprintf(stderr, "SMBIOS type %d field already defined, "
+                                "cannot add table\n", type);
+                exit(1);
+            }
+        } else if (entry == SMBIOS_FIELD_ENTRY &&
+                   header->type == SMBIOS_TABLE_ENTRY) {
+            struct smbios_structure_header *table = (void *)(header + 1);
+            if (type == table->type) {
+                fprintf(stderr, "SMBIOS type %d table already defined, "
+                                "cannot add field\n", type);
+                exit(1);
+            }
+        }
+        p += le16_to_cpu(header->length);
+    }
+}
+
+void smbios_add_field(int type, int offset, int len, void *data)
+{
+    struct smbios_field *field;
+
+    smbios_check_collision(type, SMBIOS_FIELD_ENTRY);
+
+    if (!smbios_entries) {
+        smbios_entries_len = sizeof(uint16_t);
+        smbios_entries = g_malloc0(smbios_entries_len);
+    }
+    smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
+                                                  sizeof(*field) + len);
+    field = (struct smbios_field *)(smbios_entries + smbios_entries_len);
+    field->header.type = SMBIOS_FIELD_ENTRY;
+    field->header.length = cpu_to_le16(sizeof(*field) + len);
+
+    field->type = type;
+    field->offset = cpu_to_le16(offset);
+    memcpy(field->data, data, len);
+
+    smbios_entries_len += sizeof(*field) + len;
+    (*(uint16_t *)smbios_entries) =
+            cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
+}
+
+static void smbios_build_type_0_fields(const char *t)
+{
+    char buf[1024];
+
+    if (get_param_value(buf, sizeof(buf), "vendor", t))
+        smbios_add_field(0, offsetof(struct smbios_type_0, vendor_str),
+                         strlen(buf) + 1, buf);
+    if (get_param_value(buf, sizeof(buf), "version", t))
+        smbios_add_field(0, offsetof(struct smbios_type_0, bios_version_str),
+                         strlen(buf) + 1, buf);
+    if (get_param_value(buf, sizeof(buf), "date", t))
+        smbios_add_field(0, offsetof(struct smbios_type_0,
+                                     bios_release_date_str),
+                                     strlen(buf) + 1, buf);
+    if (get_param_value(buf, sizeof(buf), "release", t)) {
+        int major, minor;
+        sscanf(buf, "%d.%d", &major, &minor);
+        smbios_add_field(0, offsetof(struct smbios_type_0,
+                                     system_bios_major_release), 1, &major);
+        smbios_add_field(0, offsetof(struct smbios_type_0,
+                                     system_bios_minor_release), 1, &minor);
+    }
+}
+
+static void smbios_build_type_1_fields(const char *t)
+{
+    char buf[1024];
+
+    if (get_param_value(buf, sizeof(buf), "manufacturer", t))
+        smbios_add_field(1, offsetof(struct smbios_type_1, manufacturer_str),
+                         strlen(buf) + 1, buf);
+    if (get_param_value(buf, sizeof(buf), "product", t))
+        smbios_add_field(1, offsetof(struct smbios_type_1, product_name_str),
+                         strlen(buf) + 1, buf);
+    if (get_param_value(buf, sizeof(buf), "version", t))
+        smbios_add_field(1, offsetof(struct smbios_type_1, version_str),
+                         strlen(buf) + 1, buf);
+    if (get_param_value(buf, sizeof(buf), "serial", t))
+        smbios_add_field(1, offsetof(struct smbios_type_1, serial_number_str),
+                         strlen(buf) + 1, buf);
+    if (get_param_value(buf, sizeof(buf), "uuid", t)) {
+        if (qemu_uuid_parse(buf, qemu_uuid) != 0) {
+            fprintf(stderr, "Invalid SMBIOS UUID string\n");
+            exit(1);
+        }
+    }
+    if (get_param_value(buf, sizeof(buf), "sku", t))
+        smbios_add_field(1, offsetof(struct smbios_type_1, sku_number_str),
+                         strlen(buf) + 1, buf);
+    if (get_param_value(buf, sizeof(buf), "family", t))
+        smbios_add_field(1, offsetof(struct smbios_type_1, family_str),
+                         strlen(buf) + 1, buf);
+}
+
+int smbios_entry_add(const char *t)
+{
+    char buf[1024];
+
+    if (get_param_value(buf, sizeof(buf), "file", t)) {
+        struct smbios_structure_header *header;
+        struct smbios_table *table;
+        int size = get_image_size(buf);
+
+        if (size == -1 || size < sizeof(struct smbios_structure_header)) {
+            fprintf(stderr, "Cannot read smbios file %s\n", buf);
+            exit(1);
+        }
+
+        if (!smbios_entries) {
+            smbios_entries_len = sizeof(uint16_t);
+            smbios_entries = g_malloc0(smbios_entries_len);
+        }
+
+        smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
+                                                      sizeof(*table) + size);
+        table = (struct smbios_table *)(smbios_entries + smbios_entries_len);
+        table->header.type = SMBIOS_TABLE_ENTRY;
+        table->header.length = cpu_to_le16(sizeof(*table) + size);
+
+        if (load_image(buf, table->data) != size) {
+            fprintf(stderr, "Failed to load smbios file %s", buf);
+            exit(1);
+        }
+
+        header = (struct smbios_structure_header *)(table->data);
+        smbios_check_collision(header->type, SMBIOS_TABLE_ENTRY);
+        if (header->type == 4) {
+            smbios_type4_count++;
+        }
+
+        smbios_entries_len += sizeof(*table) + size;
+        (*(uint16_t *)smbios_entries) =
+                cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
+        return 0;
+    }
+
+    if (get_param_value(buf, sizeof(buf), "type", t)) {
+        unsigned long type = strtoul(buf, NULL, 0);
+        switch (type) {
+        case 0:
+            smbios_build_type_0_fields(t);
+            return 0;
+        case 1:
+            smbios_build_type_1_fields(t);
+            return 0;
+        default:
+            fprintf(stderr, "Don't know how to build fields for SMBIOS type "
+                    "%ld\n", type);
+            exit(1);
+        }
+    }
+
+    fprintf(stderr, "smbios: must specify type= or file=\n");
+    return -1;
+}
diff --git a/hw/i386/xen_domainbuild.c b/hw/i386/xen_domainbuild.c
new file mode 100644
index 0000000..d477061
--- /dev/null
+++ b/hw/i386/xen_domainbuild.c
@@ -0,0 +1,299 @@
+#include <signal.h>
+#include "hw/xen_backend.h"
+#include "hw/xen_domainbuild.h"
+#include "qemu/timer.h"
+#include "qemu/log.h"
+
+#include <xenguest.h>
+
+static int xenstore_domain_mkdir(char *path)
+{
+    struct xs_permissions perms_ro[] = {{
+            .id    = 0, /* set owner: dom0 */
+        },{
+            .id    = xen_domid,
+            .perms = XS_PERM_READ,
+        }};
+    struct xs_permissions perms_rw[] = {{
+            .id    = 0, /* set owner: dom0 */
+        },{
+            .id    = xen_domid,
+            .perms = XS_PERM_READ | XS_PERM_WRITE,
+        }};
+    const char *writable[] = { "device", "control", "error", NULL };
+    char subpath[256];
+    int i;
+
+    if (!xs_mkdir(xenstore, 0, path)) {
+        fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, path);
+	return -1;
+    }
+    if (!xs_set_permissions(xenstore, 0, path, perms_ro, 2)) {
+        fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
+	return -1;
+    }
+
+    for (i = 0; writable[i]; i++) {
+        snprintf(subpath, sizeof(subpath), "%s/%s", path, writable[i]);
+        if (!xs_mkdir(xenstore, 0, subpath)) {
+            fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, subpath);
+            return -1;
+        }
+        if (!xs_set_permissions(xenstore, 0, subpath, perms_rw, 2)) {
+            fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+int xenstore_domain_init1(const char *kernel, const char *ramdisk,
+                          const char *cmdline)
+{
+    char *dom, uuid_string[42], vm[256], path[256];
+    int i;
+
+    snprintf(uuid_string, sizeof(uuid_string), UUID_FMT,
+             qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], qemu_uuid[3],
+             qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
+             qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], qemu_uuid[11],
+             qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], qemu_uuid[15]);
+    dom = xs_get_domain_path(xenstore, xen_domid);
+    snprintf(vm,  sizeof(vm),  "/vm/%s", uuid_string);
+
+    xenstore_domain_mkdir(dom);
+
+    xenstore_write_str(vm, "image/ostype",  "linux");
+    if (kernel)
+        xenstore_write_str(vm, "image/kernel",  kernel);
+    if (ramdisk)
+        xenstore_write_str(vm, "image/ramdisk", ramdisk);
+    if (cmdline)
+        xenstore_write_str(vm, "image/cmdline", cmdline);
+
+    /* name + id */
+    xenstore_write_str(vm,  "name",   qemu_name ? qemu_name : "no-name");
+    xenstore_write_str(vm,  "uuid",   uuid_string);
+    xenstore_write_str(dom, "name",   qemu_name ? qemu_name : "no-name");
+    xenstore_write_int(dom, "domid",  xen_domid);
+    xenstore_write_str(dom, "vm",     vm);
+
+    /* memory */
+    xenstore_write_int(dom, "memory/target", ram_size >> 10);  // kB
+    xenstore_write_int(vm, "memory",         ram_size >> 20);  // MB
+    xenstore_write_int(vm, "maxmem",         ram_size >> 20);  // MB
+
+    /* cpus */
+    for (i = 0; i < smp_cpus; i++) {
+	snprintf(path, sizeof(path), "cpu/%d/availability",i);
+	xenstore_write_str(dom, path, "online");
+    }
+    xenstore_write_int(vm, "vcpu_avail",  smp_cpus);
+    xenstore_write_int(vm, "vcpus",       smp_cpus);
+
+    /* vnc password */
+    xenstore_write_str(vm, "vncpassword", "" /* FIXME */);
+
+    free(dom);
+    return 0;
+}
+
+int xenstore_domain_init2(int xenstore_port, int xenstore_mfn,
+                          int console_port, int console_mfn)
+{
+    char *dom;
+
+    dom = xs_get_domain_path(xenstore, xen_domid);
+
+    /* signal new domain */
+    xs_introduce_domain(xenstore,
+                        xen_domid,
+                        xenstore_mfn,
+                        xenstore_port);
+
+    /* xenstore */
+    xenstore_write_int(dom, "store/ring-ref",   xenstore_mfn);
+    xenstore_write_int(dom, "store/port",       xenstore_port);
+
+    /* console */
+    xenstore_write_str(dom, "console/type",     "ioemu");
+    xenstore_write_int(dom, "console/limit",    128 * 1024);
+    xenstore_write_int(dom, "console/ring-ref", console_mfn);
+    xenstore_write_int(dom, "console/port",     console_port);
+    xen_config_dev_console(0);
+
+    free(dom);
+    return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static QEMUTimer *xen_poll;
+
+/* check domain state once per second */
+static void xen_domain_poll(void *opaque)
+{
+    struct xc_dominfo info;
+    int rc;
+
+    rc = xc_domain_getinfo(xen_xc, xen_domid, 1, &info);
+    if ((rc != 1) || (info.domid != xen_domid)) {
+        qemu_log("xen: domain %d is gone\n", xen_domid);
+        goto quit;
+    }
+    if (info.dying) {
+        qemu_log("xen: domain %d is dying (%s%s)\n", xen_domid,
+                 info.crashed  ? "crashed"  : "",
+                 info.shutdown ? "shutdown" : "");
+        goto quit;
+    }
+
+    qemu_mod_timer(xen_poll, qemu_get_clock_ms(rt_clock) + 1000);
+    return;
+
+quit:
+    qemu_system_shutdown_request();
+}
+
+static int xen_domain_watcher(void)
+{
+    int qemu_running = 1;
+    int fd[2], i, n, rc;
+    char byte;
+
+    if (pipe(fd) != 0) {
+        qemu_log("%s: Huh? pipe error: %s\n", __FUNCTION__, strerror(errno));
+        return -1;
+    }
+    if (fork() != 0)
+        return 0; /* not child */
+
+    /* close all file handles, except stdio/out/err,
+     * our watch pipe and the xen interface handle */
+    n = getdtablesize();
+    for (i = 3; i < n; i++) {
+        if (i == fd[0])
+            continue;
+        if (i == xc_fd(xen_xc)) {
+            continue;
+        }
+        close(i);
+    }
+
+    /* ignore term signals */
+    signal(SIGINT,  SIG_IGN);
+    signal(SIGTERM, SIG_IGN);
+
+    /* wait for qemu exiting */
+    while (qemu_running) {
+        rc = read(fd[0], &byte, 1);
+        switch (rc) {
+        case -1:
+            if (errno == EINTR)
+                continue;
+            qemu_log("%s: Huh? read error: %s\n", __FUNCTION__, strerror(errno));
+            qemu_running = 0;
+            break;
+        case 0:
+            /* EOF -> qemu exited */
+            qemu_running = 0;
+            break;
+        default:
+            qemu_log("%s: Huh? data on the watch pipe?\n", __FUNCTION__);
+            break;
+        }
+    }
+
+    /* cleanup */
+    qemu_log("%s: destroy domain %d\n", __FUNCTION__, xen_domid);
+    xc_domain_destroy(xen_xc, xen_domid);
+    _exit(0);
+}
+
+/* normal cleanup */
+static void xen_domain_cleanup(void)
+{
+    char *dom;
+
+    dom = xs_get_domain_path(xenstore, xen_domid);
+    if (dom) {
+        xs_rm(xenstore, 0, dom);
+        free(dom);
+    }
+    xs_release_domain(xenstore, xen_domid);
+}
+
+int xen_domain_build_pv(const char *kernel, const char *ramdisk,
+                        const char *cmdline)
+{
+    uint32_t ssidref = 0;
+    uint32_t flags = 0;
+    xen_domain_handle_t uuid;
+    unsigned int xenstore_port = 0, console_port = 0;
+    unsigned long xenstore_mfn = 0, console_mfn = 0;
+    int rc;
+
+    memcpy(uuid, qemu_uuid, sizeof(uuid));
+    rc = xc_domain_create(xen_xc, ssidref, uuid, flags, &xen_domid);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_create() failed\n");
+        goto err;
+    }
+    qemu_log("xen: created domain %d\n", xen_domid);
+    atexit(xen_domain_cleanup);
+    if (xen_domain_watcher() == -1) {
+        goto err;
+    }
+
+    xenstore_domain_init1(kernel, ramdisk, cmdline);
+
+    rc = xc_domain_max_vcpus(xen_xc, xen_domid, smp_cpus);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_max_vcpus() failed\n");
+        goto err;
+    }
+
+#if 0
+    rc = xc_domain_setcpuweight(xen_xc, xen_domid, 256);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_setcpuweight() failed\n");
+        goto err;
+    }
+#endif
+
+    rc = xc_domain_setmaxmem(xen_xc, xen_domid, ram_size >> 10);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_setmaxmem() failed\n");
+        goto err;
+    }
+
+    xenstore_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
+    console_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
+
+    rc = xc_linux_build(xen_xc, xen_domid, ram_size >> 20,
+                        kernel, ramdisk, cmdline,
+                        0, flags,
+                        xenstore_port, &xenstore_mfn,
+                        console_port, &console_mfn);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_linux_build() failed\n");
+        goto err;
+    }
+
+    xenstore_domain_init2(xenstore_port, xenstore_mfn,
+                          console_port, console_mfn);
+
+    qemu_log("xen: unpausing domain %d\n", xen_domid);
+    rc = xc_domain_unpause(xen_xc, xen_domid);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_unpause() failed\n");
+        goto err;
+    }
+
+    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:
+    return -1;
+}
diff --git a/hw/i386/xen_machine_pv.c b/hw/i386/xen_machine_pv.c
new file mode 100644
index 0000000..a8177b6
--- /dev/null
+++ b/hw/i386/xen_machine_pv.c
@@ -0,0 +1,126 @@
+/*
+ * QEMU Xen PV Machine
+ *
+ * Copyright (c) 2007 Red Hat
+ *
+ * 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/hw.h"
+#include "hw/pc.h"
+#include "hw/boards.h"
+#include "hw/xen_backend.h"
+#include "hw/xen_domainbuild.h"
+#include "sysemu/blockdev.h"
+
+static void xen_init_pv(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    X86CPU *cpu;
+    CPUX86State *env;
+    DriveInfo *dinfo;
+    int i;
+
+    /* Initialize a dummy CPU */
+    if (cpu_model == NULL) {
+#ifdef TARGET_X86_64
+        cpu_model = "qemu64";
+#else
+        cpu_model = "qemu32";
+#endif
+    }
+    cpu = cpu_x86_init(cpu_model);
+    env = &cpu->env;
+    env->halted = 1;
+
+    /* Initialize backend core & drivers */
+    if (xen_be_init() != 0) {
+        fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__);
+        exit(1);
+    }
+
+    switch (xen_mode) {
+    case XEN_ATTACH:
+        /* nothing to do, xend handles everything */
+        break;
+    case XEN_CREATE:
+        if (xen_domain_build_pv(kernel_filename, initrd_filename,
+                                kernel_cmdline) < 0) {
+            fprintf(stderr, "xen pv domain creation failed\n");
+            exit(1);
+        }
+        break;
+    case XEN_EMULATE:
+        fprintf(stderr, "xen emulation not implemented (yet)\n");
+        exit(1);
+        break;
+    }
+
+    xen_be_register("console", &xen_console_ops);
+    xen_be_register("vkbd", &xen_kbdmouse_ops);
+    xen_be_register("vfb", &xen_framebuffer_ops);
+    xen_be_register("qdisk", &xen_blkdev_ops);
+    xen_be_register("qnic", &xen_netdev_ops);
+
+    /* configure framebuffer */
+    if (xenfb_enabled) {
+        xen_config_dev_vfb(0, "vnc");
+        xen_config_dev_vkbd(0);
+    }
+
+    /* configure disks */
+    for (i = 0; i < 16; i++) {
+        dinfo = drive_get(IF_XEN, 0, i);
+        if (!dinfo)
+            continue;
+        xen_config_dev_blk(dinfo);
+    }
+
+    /* configure nics */
+    for (i = 0; i < nb_nics; i++) {
+        if (!nd_table[i].model || 0 != strcmp(nd_table[i].model, "xen"))
+            continue;
+        xen_config_dev_nic(nd_table + i);
+    }
+
+    /* config cleanup hook */
+    atexit(xen_config_cleanup);
+
+    /* setup framebuffer */
+    xen_init_display(xen_domid);
+}
+
+static QEMUMachine xenpv_machine = {
+    .name = "xenpv",
+    .desc = "Xen Para-virtualized PC",
+    .init = xen_init_pv,
+    .max_cpus = 1,
+    .default_machine_opts = "accel=xen",
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void xenpv_machine_init(void)
+{
+    qemu_register_machine(&xenpv_machine);
+}
+
+machine_init(xenpv_machine_init);
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
deleted file mode 100644
index e0ba327..0000000
--- a/hw/integratorcp.c
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * ARM Integrator CP System emulation.
- *
- * Copyright (c) 2005-2007 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GPL
- */
-
-#include "hw/sysbus.h"
-#include "hw/devices.h"
-#include "hw/boards.h"
-#include "hw/arm-misc.h"
-#include "net/net.h"
-#include "exec/address-spaces.h"
-#include "sysemu/sysemu.h"
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t memsz;
-    MemoryRegion flash;
-    uint32_t cm_osc;
-    uint32_t cm_ctrl;
-    uint32_t cm_lock;
-    uint32_t cm_auxosc;
-    uint32_t cm_sdram;
-    uint32_t cm_init;
-    uint32_t cm_flags;
-    uint32_t cm_nvflags;
-    uint32_t int_level;
-    uint32_t irq_enabled;
-    uint32_t fiq_enabled;
-} integratorcm_state;
-
-static uint8_t integrator_spd[128] = {
-   128, 8, 4, 11, 9, 1, 64, 0,  2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
-   0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
-};
-
-static uint64_t integratorcm_read(void *opaque, hwaddr offset,
-                                  unsigned size)
-{
-    integratorcm_state *s = (integratorcm_state *)opaque;
-    if (offset >= 0x100 && offset < 0x200) {
-        /* CM_SPD */
-        if (offset >= 0x180)
-            return 0;
-        return integrator_spd[offset >> 2];
-    }
-    switch (offset >> 2) {
-    case 0: /* CM_ID */
-        return 0x411a3001;
-    case 1: /* CM_PROC */
-        return 0;
-    case 2: /* CM_OSC */
-        return s->cm_osc;
-    case 3: /* CM_CTRL */
-        return s->cm_ctrl;
-    case 4: /* CM_STAT */
-        return 0x00100000;
-    case 5: /* CM_LOCK */
-        if (s->cm_lock == 0xa05f) {
-            return 0x1a05f;
-        } else {
-            return s->cm_lock;
-        }
-    case 6: /* CM_LMBUSCNT */
-        /* ??? High frequency timer.  */
-        hw_error("integratorcm_read: CM_LMBUSCNT");
-    case 7: /* CM_AUXOSC */
-        return s->cm_auxosc;
-    case 8: /* CM_SDRAM */
-        return s->cm_sdram;
-    case 9: /* CM_INIT */
-        return s->cm_init;
-    case 10: /* CM_REFCT */
-        /* ??? High frequency timer.  */
-        hw_error("integratorcm_read: CM_REFCT");
-    case 12: /* CM_FLAGS */
-        return s->cm_flags;
-    case 14: /* CM_NVFLAGS */
-        return s->cm_nvflags;
-    case 16: /* CM_IRQ_STAT */
-        return s->int_level & s->irq_enabled;
-    case 17: /* CM_IRQ_RSTAT */
-        return s->int_level;
-    case 18: /* CM_IRQ_ENSET */
-        return s->irq_enabled;
-    case 20: /* CM_SOFT_INTSET */
-        return s->int_level & 1;
-    case 24: /* CM_FIQ_STAT */
-        return s->int_level & s->fiq_enabled;
-    case 25: /* CM_FIQ_RSTAT */
-        return s->int_level;
-    case 26: /* CM_FIQ_ENSET */
-        return s->fiq_enabled;
-    case 32: /* CM_VOLTAGE_CTL0 */
-    case 33: /* CM_VOLTAGE_CTL1 */
-    case 34: /* CM_VOLTAGE_CTL2 */
-    case 35: /* CM_VOLTAGE_CTL3 */
-        /* ??? Voltage control unimplemented.  */
-        return 0;
-    default:
-        hw_error("integratorcm_read: Unimplemented offset 0x%x\n",
-                 (int)offset);
-        return 0;
-    }
-}
-
-static void integratorcm_do_remap(integratorcm_state *s)
-{
-    /* Sync memory region state with CM_CTRL REMAP bit:
-     * bit 0 => flash at address 0; bit 1 => RAM
-     */
-    memory_region_set_enabled(&s->flash, !(s->cm_ctrl & 4));
-}
-
-static void integratorcm_set_ctrl(integratorcm_state *s, uint32_t value)
-{
-    if (value & 8) {
-        qemu_system_reset_request();
-    }
-    if ((s->cm_ctrl ^ value) & 1) {
-        /* (value & 1) != 0 means the green "MISC LED" is lit.
-         * We don't have any nice place to display LEDs. printf is a bad
-         * idea because Linux uses the LED as a heartbeat and the output
-         * will swamp anything else on the terminal.
-         */
-    }
-    /* Note that the RESET bit [3] always reads as zero */
-    s->cm_ctrl = (s->cm_ctrl & ~5) | (value & 5);
-    integratorcm_do_remap(s);
-}
-
-static void integratorcm_update(integratorcm_state *s)
-{
-    /* ??? The CPU irq/fiq is raised when either the core module or base PIC
-       are active.  */
-    if (s->int_level & (s->irq_enabled | s->fiq_enabled))
-        hw_error("Core module interrupt\n");
-}
-
-static void integratorcm_write(void *opaque, hwaddr offset,
-                               uint64_t value, unsigned size)
-{
-    integratorcm_state *s = (integratorcm_state *)opaque;
-    switch (offset >> 2) {
-    case 2: /* CM_OSC */
-        if (s->cm_lock == 0xa05f)
-            s->cm_osc = value;
-        break;
-    case 3: /* CM_CTRL */
-        integratorcm_set_ctrl(s, value);
-        break;
-    case 5: /* CM_LOCK */
-        s->cm_lock = value & 0xffff;
-        break;
-    case 7: /* CM_AUXOSC */
-        if (s->cm_lock == 0xa05f)
-            s->cm_auxosc = value;
-        break;
-    case 8: /* CM_SDRAM */
-        s->cm_sdram = value;
-        break;
-    case 9: /* CM_INIT */
-        /* ??? This can change the memory bus frequency.  */
-        s->cm_init = value;
-        break;
-    case 12: /* CM_FLAGSS */
-        s->cm_flags |= value;
-        break;
-    case 13: /* CM_FLAGSC */
-        s->cm_flags &= ~value;
-        break;
-    case 14: /* CM_NVFLAGSS */
-        s->cm_nvflags |= value;
-        break;
-    case 15: /* CM_NVFLAGSS */
-        s->cm_nvflags &= ~value;
-        break;
-    case 18: /* CM_IRQ_ENSET */
-        s->irq_enabled |= value;
-        integratorcm_update(s);
-        break;
-    case 19: /* CM_IRQ_ENCLR */
-        s->irq_enabled &= ~value;
-        integratorcm_update(s);
-        break;
-    case 20: /* CM_SOFT_INTSET */
-        s->int_level |= (value & 1);
-        integratorcm_update(s);
-        break;
-    case 21: /* CM_SOFT_INTCLR */
-        s->int_level &= ~(value & 1);
-        integratorcm_update(s);
-        break;
-    case 26: /* CM_FIQ_ENSET */
-        s->fiq_enabled |= value;
-        integratorcm_update(s);
-        break;
-    case 27: /* CM_FIQ_ENCLR */
-        s->fiq_enabled &= ~value;
-        integratorcm_update(s);
-        break;
-    case 32: /* CM_VOLTAGE_CTL0 */
-    case 33: /* CM_VOLTAGE_CTL1 */
-    case 34: /* CM_VOLTAGE_CTL2 */
-    case 35: /* CM_VOLTAGE_CTL3 */
-        /* ??? Voltage control unimplemented.  */
-        break;
-    default:
-        hw_error("integratorcm_write: Unimplemented offset 0x%x\n",
-                 (int)offset);
-        break;
-    }
-}
-
-/* Integrator/CM control registers.  */
-
-static const MemoryRegionOps integratorcm_ops = {
-    .read = integratorcm_read,
-    .write = integratorcm_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int integratorcm_init(SysBusDevice *dev)
-{
-    integratorcm_state *s = FROM_SYSBUS(integratorcm_state, dev);
-
-    s->cm_osc = 0x01000048;
-    /* ??? What should the high bits of this value be?  */
-    s->cm_auxosc = 0x0007feff;
-    s->cm_sdram = 0x00011122;
-    if (s->memsz >= 256) {
-        integrator_spd[31] = 64;
-        s->cm_sdram |= 0x10;
-    } else if (s->memsz >= 128) {
-        integrator_spd[31] = 32;
-        s->cm_sdram |= 0x0c;
-    } else if (s->memsz >= 64) {
-        integrator_spd[31] = 16;
-        s->cm_sdram |= 0x08;
-    } else if (s->memsz >= 32) {
-        integrator_spd[31] = 4;
-        s->cm_sdram |= 0x04;
-    } else {
-        integrator_spd[31] = 2;
-    }
-    memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
-    s->cm_init = 0x00000112;
-    memory_region_init_ram(&s->flash, "integrator.flash", 0x100000);
-    vmstate_register_ram_global(&s->flash);
-
-    memory_region_init_io(&s->iomem, &integratorcm_ops, s,
-                          "integratorcm", 0x00800000);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    integratorcm_do_remap(s);
-    /* ??? Save/restore.  */
-    return 0;
-}
-
-/* Integrator/CP hardware emulation.  */
-/* Primary interrupt controller.  */
-
-typedef struct icp_pic_state
-{
-  SysBusDevice busdev;
-  MemoryRegion iomem;
-  uint32_t level;
-  uint32_t irq_enabled;
-  uint32_t fiq_enabled;
-  qemu_irq parent_irq;
-  qemu_irq parent_fiq;
-} icp_pic_state;
-
-static void icp_pic_update(icp_pic_state *s)
-{
-    uint32_t flags;
-
-    flags = (s->level & s->irq_enabled);
-    qemu_set_irq(s->parent_irq, flags != 0);
-    flags = (s->level & s->fiq_enabled);
-    qemu_set_irq(s->parent_fiq, flags != 0);
-}
-
-static void icp_pic_set_irq(void *opaque, int irq, int level)
-{
-    icp_pic_state *s = (icp_pic_state *)opaque;
-    if (level)
-        s->level |= 1 << irq;
-    else
-        s->level &= ~(1 << irq);
-    icp_pic_update(s);
-}
-
-static uint64_t icp_pic_read(void *opaque, hwaddr offset,
-                             unsigned size)
-{
-    icp_pic_state *s = (icp_pic_state *)opaque;
-
-    switch (offset >> 2) {
-    case 0: /* IRQ_STATUS */
-        return s->level & s->irq_enabled;
-    case 1: /* IRQ_RAWSTAT */
-        return s->level;
-    case 2: /* IRQ_ENABLESET */
-        return s->irq_enabled;
-    case 4: /* INT_SOFTSET */
-        return s->level & 1;
-    case 8: /* FRQ_STATUS */
-        return s->level & s->fiq_enabled;
-    case 9: /* FRQ_RAWSTAT */
-        return s->level;
-    case 10: /* FRQ_ENABLESET */
-        return s->fiq_enabled;
-    case 3: /* IRQ_ENABLECLR */
-    case 5: /* INT_SOFTCLR */
-    case 11: /* FRQ_ENABLECLR */
-    default:
-        printf ("icp_pic_read: Bad register offset 0x%x\n", (int)offset);
-        return 0;
-    }
-}
-
-static void icp_pic_write(void *opaque, hwaddr offset,
-                          uint64_t value, unsigned size)
-{
-    icp_pic_state *s = (icp_pic_state *)opaque;
-
-    switch (offset >> 2) {
-    case 2: /* IRQ_ENABLESET */
-        s->irq_enabled |= value;
-        break;
-    case 3: /* IRQ_ENABLECLR */
-        s->irq_enabled &= ~value;
-        break;
-    case 4: /* INT_SOFTSET */
-        if (value & 1)
-            icp_pic_set_irq(s, 0, 1);
-        break;
-    case 5: /* INT_SOFTCLR */
-        if (value & 1)
-            icp_pic_set_irq(s, 0, 0);
-        break;
-    case 10: /* FRQ_ENABLESET */
-        s->fiq_enabled |= value;
-        break;
-    case 11: /* FRQ_ENABLECLR */
-        s->fiq_enabled &= ~value;
-        break;
-    case 0: /* IRQ_STATUS */
-    case 1: /* IRQ_RAWSTAT */
-    case 8: /* FRQ_STATUS */
-    case 9: /* FRQ_RAWSTAT */
-    default:
-        printf ("icp_pic_write: Bad register offset 0x%x\n", (int)offset);
-        return;
-    }
-    icp_pic_update(s);
-}
-
-static const MemoryRegionOps icp_pic_ops = {
-    .read = icp_pic_read,
-    .write = icp_pic_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int icp_pic_init(SysBusDevice *dev)
-{
-    icp_pic_state *s = FROM_SYSBUS(icp_pic_state, dev);
-
-    qdev_init_gpio_in(&dev->qdev, icp_pic_set_irq, 32);
-    sysbus_init_irq(dev, &s->parent_irq);
-    sysbus_init_irq(dev, &s->parent_fiq);
-    memory_region_init_io(&s->iomem, &icp_pic_ops, s, "icp-pic", 0x00800000);
-    sysbus_init_mmio(dev, &s->iomem);
-    return 0;
-}
-
-/* CP control registers.  */
-
-static uint64_t icp_control_read(void *opaque, hwaddr offset,
-                                 unsigned size)
-{
-    switch (offset >> 2) {
-    case 0: /* CP_IDFIELD */
-        return 0x41034003;
-    case 1: /* CP_FLASHPROG */
-        return 0;
-    case 2: /* CP_INTREG */
-        return 0;
-    case 3: /* CP_DECODE */
-        return 0x11;
-    default:
-        hw_error("icp_control_read: Bad offset %x\n", (int)offset);
-        return 0;
-    }
-}
-
-static void icp_control_write(void *opaque, hwaddr offset,
-                          uint64_t value, unsigned size)
-{
-    switch (offset >> 2) {
-    case 1: /* CP_FLASHPROG */
-    case 2: /* CP_INTREG */
-    case 3: /* CP_DECODE */
-        /* Nothing interesting implemented yet.  */
-        break;
-    default:
-        hw_error("icp_control_write: Bad offset %x\n", (int)offset);
-    }
-}
-
-static const MemoryRegionOps icp_control_ops = {
-    .read = icp_control_read,
-    .write = icp_control_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void icp_control_init(hwaddr base)
-{
-    MemoryRegion *io;
-
-    io = (MemoryRegion *)g_malloc0(sizeof(MemoryRegion));
-    memory_region_init_io(io, &icp_control_ops, NULL,
-                          "control", 0x00800000);
-    memory_region_add_subregion(get_system_memory(), base, io);
-    /* ??? Save/restore.  */
-}
-
-
-/* Board init.  */
-
-static struct arm_boot_info integrator_binfo = {
-    .loader_start = 0x0,
-    .board_id = 0x113,
-};
-
-static void integratorcp_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    ARMCPU *cpu;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
-    qemu_irq pic[32];
-    qemu_irq *cpu_pic;
-    DeviceState *dev;
-    int i;
-
-    if (!cpu_model) {
-        cpu_model = "arm926";
-    }
-    cpu = cpu_arm_init(cpu_model);
-    if (!cpu) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-
-    memory_region_init_ram(ram, "integrator.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
-    /* ??? RAM should repeat to fill physical memory space.  */
-    /* SDRAM at address zero*/
-    memory_region_add_subregion(address_space_mem, 0, ram);
-    /* And again at address 0x80000000 */
-    memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size);
-    memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
-
-    dev = qdev_create(NULL, "integrator_core");
-    qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
-
-    cpu_pic = arm_pic_init_cpu(cpu);
-    dev = sysbus_create_varargs("integrator_pic", 0x14000000,
-                                cpu_pic[ARM_PIC_CPU_IRQ],
-                                cpu_pic[ARM_PIC_CPU_FIQ], NULL);
-    for (i = 0; i < 32; i++) {
-        pic[i] = qdev_get_gpio_in(dev, i);
-    }
-    sysbus_create_simple("integrator_pic", 0xca000000, pic[26]);
-    sysbus_create_varargs("integrator_pit", 0x13000000,
-                          pic[5], pic[6], pic[7], NULL);
-    sysbus_create_simple("pl031", 0x15000000, pic[8]);
-    sysbus_create_simple("pl011", 0x16000000, pic[1]);
-    sysbus_create_simple("pl011", 0x17000000, pic[2]);
-    icp_control_init(0xcb000000);
-    sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
-    sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]);
-    sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL);
-    if (nd_table[0].used)
-        smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
-
-    sysbus_create_simple("pl110", 0xc0000000, pic[22]);
-
-    integrator_binfo.ram_size = ram_size;
-    integrator_binfo.kernel_filename = kernel_filename;
-    integrator_binfo.kernel_cmdline = kernel_cmdline;
-    integrator_binfo.initrd_filename = initrd_filename;
-    arm_load_kernel(cpu, &integrator_binfo);
-}
-
-static QEMUMachine integratorcp_machine = {
-    .name = "integratorcp",
-    .desc = "ARM Integrator/CP (ARM926EJ-S)",
-    .init = integratorcp_init,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void integratorcp_machine_init(void)
-{
-    qemu_register_machine(&integratorcp_machine);
-}
-
-machine_init(integratorcp_machine_init);
-
-static Property core_properties[] = {
-    DEFINE_PROP_UINT32("memsz", integratorcm_state, memsz, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void core_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = integratorcm_init;
-    dc->props = core_properties;
-}
-
-static const TypeInfo core_info = {
-    .name          = "integrator_core",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(integratorcm_state),
-    .class_init    = core_class_init,
-};
-
-static void icp_pic_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = icp_pic_init;
-}
-
-static const TypeInfo icp_pic_info = {
-    .name          = "integrator_pic",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(icp_pic_state),
-    .class_init    = icp_pic_class_init,
-};
-
-static void integratorcp_register_types(void)
-{
-    type_register_static(&icp_pic_info);
-    type_register_static(&core_info);
-}
-
-type_init(integratorcp_register_types)
diff --git a/hw/kzm.c b/hw/kzm.c
deleted file mode 100644
index ec50a31..0000000
--- a/hw/kzm.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * KZM Board System emulation.
- *
- * Copyright (c) 2008 OKL and 2011 NICTA
- * Written by Hans at OK-Labs
- * Updated by Peter Chubb.
- *
- * This code is licensed under the GPL, version 2 or later.
- * See the file `COPYING' in the top level directory.
- *
- * It (partially) emulates a Kyoto Microcomputer
- * KZM-ARM11-01 evaluation board, with a Freescale
- * i.MX31 SoC
- */
-
-#include "hw/sysbus.h"
-#include "exec/address-spaces.h"
-#include "hw/hw.h"
-#include "hw/arm-misc.h"
-#include "hw/devices.h"
-#include "net/net.h"
-#include "sysemu/sysemu.h"
-#include "hw/boards.h"
-#include "hw/serial.h"
-#include "hw/imx.h"
-
-    /* Memory map for Kzm Emulation Baseboard:
-     * 0x00000000-0x00003fff 16k secure ROM       IGNORED
-     * 0x00004000-0x00407fff Reserved             IGNORED
-     * 0x00404000-0x00407fff ROM                  IGNORED
-     * 0x00408000-0x0fffffff Reserved             IGNORED
-     * 0x10000000-0x1fffbfff RAM aliasing         IGNORED
-     * 0x1fffc000-0x1fffffff RAM                  EMULATED
-     * 0x20000000-0x2fffffff Reserved             IGNORED
-     * 0x30000000-0x7fffffff I.MX31 Internal Register Space
-     *   0x43f00000 IO_AREA0
-     *   0x43f90000 UART1                         EMULATED
-     *   0x43f94000 UART2                         EMULATED
-     *   0x68000000 AVIC                          EMULATED
-     *   0x53f80000 CCM                           EMULATED
-     *   0x53f94000 PIT 1                         EMULATED
-     *   0x53f98000 PIT 2                         EMULATED
-     *   0x53f90000 GPT                           EMULATED
-     * 0x80000000-0x87ffffff RAM                  EMULATED
-     * 0x88000000-0x8fffffff RAM Aliasing         EMULATED
-     * 0xa0000000-0xafffffff NAND Flash           IGNORED
-     * 0xb0000000-0xb3ffffff Unavailable          IGNORED
-     * 0xb4000000-0xb4000fff 8-bit free space     IGNORED
-     * 0xb4001000-0xb400100f Board control        IGNORED
-     *  0xb4001003           DIP switch
-     * 0xb4001010-0xb400101f 7-segment LED        IGNORED
-     * 0xb4001020-0xb400102f LED                  IGNORED
-     * 0xb4001030-0xb400103f LED                  IGNORED
-     * 0xb4001040-0xb400104f FPGA, UART           EMULATED
-     * 0xb4001050-0xb400105f FPGA, UART           EMULATED
-     * 0xb4001060-0xb40fffff FPGA                 IGNORED
-     * 0xb6000000-0xb61fffff LAN controller       EMULATED
-     * 0xb6200000-0xb62fffff FPGA NAND Controller IGNORED
-     * 0xb6300000-0xb7ffffff Free                 IGNORED
-     * 0xb8000000-0xb8004fff Memory control registers IGNORED
-     * 0xc0000000-0xc3ffffff PCMCIA/CF            IGNORED
-     * 0xc4000000-0xffffffff Reserved             IGNORED
-     */
-
-#define KZM_RAMADDRESS (0x80000000)
-#define KZM_FPGA       (0xb4001040)
-
-static struct arm_boot_info kzm_binfo = {
-    .loader_start = KZM_RAMADDRESS,
-    .board_id = 1722,
-};
-
-static void kzm_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    ARMCPU *cpu;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
-    qemu_irq *cpu_pic;
-    DeviceState *dev;
-    DeviceState *ccm;
-
-    if (!cpu_model) {
-        cpu_model = "arm1136";
-    }
-
-    cpu = cpu_arm_init(cpu_model);
-    if (!cpu) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-
-    /* On a real system, the first 16k is a `secure boot rom' */
-
-    memory_region_init_ram(ram, "kzm.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(address_space_mem, KZM_RAMADDRESS, ram);
-
-    memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size);
-    memory_region_add_subregion(address_space_mem, 0x88000000, ram_alias);
-
-    memory_region_init_ram(sram, "kzm.sram", 0x4000);
-    memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram);
-
-    cpu_pic = arm_pic_init_cpu(cpu);
-    dev = sysbus_create_varargs("imx_avic", 0x68000000,
-                                cpu_pic[ARM_PIC_CPU_IRQ],
-                                cpu_pic[ARM_PIC_CPU_FIQ], NULL);
-
-
-    imx_serial_create(0, 0x43f90000, qdev_get_gpio_in(dev, 45));
-    imx_serial_create(1, 0x43f94000, qdev_get_gpio_in(dev, 32));
-
-    ccm = sysbus_create_simple("imx_ccm", 0x53f80000, NULL);
-
-    imx_timerp_create(0x53f94000, qdev_get_gpio_in(dev, 28), ccm);
-    imx_timerp_create(0x53f98000, qdev_get_gpio_in(dev, 27), ccm);
-    imx_timerg_create(0x53f90000, qdev_get_gpio_in(dev, 29), ccm);
-
-    if (nd_table[0].used) {
-        lan9118_init(&nd_table[0], 0xb6000000, qdev_get_gpio_in(dev, 52));
-    }
-
-    if (serial_hds[2]) { /* touchscreen */
-        serial_mm_init(address_space_mem, KZM_FPGA+0x10, 0,
-                       qdev_get_gpio_in(dev, 52),
-                       14745600, serial_hds[2],
-                       DEVICE_NATIVE_ENDIAN);
-    }
-
-    kzm_binfo.ram_size = ram_size;
-    kzm_binfo.kernel_filename = kernel_filename;
-    kzm_binfo.kernel_cmdline = kernel_cmdline;
-    kzm_binfo.initrd_filename = initrd_filename;
-    kzm_binfo.nb_cpus = 1;
-    arm_load_kernel(cpu, &kzm_binfo);
-}
-
-static QEMUMachine kzm_machine = {
-    .name = "kzm",
-    .desc = "ARM KZM Emulation Baseboard (ARM1136)",
-    .init = kzm_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void kzm_machine_init(void)
-{
-    qemu_register_machine(&kzm_machine);
-}
-
-machine_init(kzm_machine_init)
diff --git a/hw/leon3.c b/hw/leon3.c
deleted file mode 100644
index f58061f..0000000
--- a/hw/leon3.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * QEMU Leon3 System Emulator
- *
- * Copyright (c) 2010-2011 AdaCore
- *
- * 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/hw.h"
-#include "qemu/timer.h"
-#include "hw/ptimer.h"
-#include "char/char.h"
-#include "sysemu/sysemu.h"
-#include "hw/boards.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "trace.h"
-#include "exec/address-spaces.h"
-
-#include "hw/grlib.h"
-
-/* Default system clock.  */
-#define CPU_CLK (40 * 1000 * 1000)
-
-#define PROM_FILENAME        "u-boot.bin"
-
-#define MAX_PILS 16
-
-typedef struct ResetData {
-    SPARCCPU *cpu;
-    uint32_t  entry;            /* save kernel entry in case of reset */
-} ResetData;
-
-static void main_cpu_reset(void *opaque)
-{
-    ResetData *s   = (ResetData *)opaque;
-    CPUSPARCState  *env = &s->cpu->env;
-
-    cpu_reset(CPU(s->cpu));
-
-    env->halted = 0;
-    env->pc     = s->entry;
-    env->npc    = s->entry + 4;
-}
-
-void leon3_irq_ack(void *irq_manager, int intno)
-{
-    grlib_irqmp_ack((DeviceState *)irq_manager, intno);
-}
-
-static void leon3_set_pil_in(void *opaque, uint32_t pil_in)
-{
-    CPUSPARCState *env = (CPUSPARCState *)opaque;
-
-    assert(env != NULL);
-
-    env->pil_in = pil_in;
-
-    if (env->pil_in && (env->interrupt_index == 0 ||
-                        (env->interrupt_index & ~15) == TT_EXTINT)) {
-        unsigned int i;
-
-        for (i = 15; i > 0; i--) {
-            if (env->pil_in & (1 << i)) {
-                int old_interrupt = env->interrupt_index;
-
-                env->interrupt_index = TT_EXTINT | i;
-                if (old_interrupt != env->interrupt_index) {
-                    trace_leon3_set_irq(i);
-                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
-                }
-                break;
-            }
-        }
-    } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
-        trace_leon3_reset_irq(env->interrupt_index & 15);
-        env->interrupt_index = 0;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-}
-
-static void leon3_generic_hw_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    SPARCCPU *cpu;
-    CPUSPARCState   *env;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *prom = g_new(MemoryRegion, 1);
-    int         ret;
-    char       *filename;
-    qemu_irq   *cpu_irqs = NULL;
-    int         bios_size;
-    int         prom_size;
-    ResetData  *reset_info;
-
-    /* Init CPU */
-    if (!cpu_model) {
-        cpu_model = "LEON3";
-    }
-
-    cpu = cpu_sparc_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    cpu_sparc_set_id(env, 0);
-
-    /* Reset data */
-    reset_info        = g_malloc0(sizeof(ResetData));
-    reset_info->cpu   = cpu;
-    qemu_register_reset(main_cpu_reset, reset_info);
-
-    /* Allocate IRQ manager */
-    grlib_irqmp_create(0x80000200, env, &cpu_irqs, MAX_PILS, &leon3_set_pil_in);
-
-    env->qemu_irq_ack = leon3_irq_manager;
-
-    /* Allocate RAM */
-    if ((uint64_t)ram_size > (1UL << 30)) {
-        fprintf(stderr,
-                "qemu: Too much memory for this machine: %d, maximum 1G\n",
-                (unsigned int)(ram_size / (1024 * 1024)));
-        exit(1);
-    }
-
-    memory_region_init_ram(ram, "leon3.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(address_space_mem, 0x40000000, ram);
-
-    /* Allocate BIOS */
-    prom_size = 8 * 1024 * 1024; /* 8Mb */
-    memory_region_init_ram(prom, "Leon3.bios", prom_size);
-    vmstate_register_ram_global(prom);
-    memory_region_set_readonly(prom, true);
-    memory_region_add_subregion(address_space_mem, 0x00000000, prom);
-
-    /* Load boot prom */
-    if (bios_name == NULL) {
-        bios_name = PROM_FILENAME;
-    }
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-
-    bios_size = get_image_size(filename);
-
-    if (bios_size > prom_size) {
-        fprintf(stderr, "qemu: could not load prom '%s': file too big\n",
-                filename);
-        exit(1);
-    }
-
-    if (bios_size > 0) {
-        ret = load_image_targphys(filename, 0x00000000, bios_size);
-        if (ret < 0 || ret > prom_size) {
-            fprintf(stderr, "qemu: could not load prom '%s'\n", filename);
-            exit(1);
-        }
-    } else if (kernel_filename == NULL) {
-        fprintf(stderr, "Can't read bios image %s\n", filename);
-        exit(1);
-    }
-
-    /* Can directly load an application. */
-    if (kernel_filename != NULL) {
-        long     kernel_size;
-        uint64_t entry;
-
-        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
-                               1 /* big endian */, ELF_MACHINE, 0);
-        if (kernel_size < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                    kernel_filename);
-            exit(1);
-        }
-        if (bios_size <= 0) {
-            /* If there is no bios/monitor, start the application.  */
-            env->pc = entry;
-            env->npc = entry + 4;
-            reset_info->entry = entry;
-        }
-    }
-
-    /* Allocate timers */
-    grlib_gptimer_create(0x80000300, 2, CPU_CLK, cpu_irqs, 6);
-
-    /* Allocate uart */
-    if (serial_hds[0]) {
-        grlib_apbuart_create(0x80000100, serial_hds[0], cpu_irqs[3]);
-    }
-}
-
-static QEMUMachine leon3_generic_machine = {
-    .name     = "leon3_generic",
-    .desc     = "Leon-3 generic",
-    .init     = leon3_generic_hw_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void leon3_machine_init(void)
-{
-    qemu_register_machine(&leon3_generic_machine);
-}
-
-machine_init(leon3_machine_init);
diff --git a/hw/lm32/Makefile.objs b/hw/lm32/Makefile.objs
index 4e1843c..4592fe5 100644
--- a/hw/lm32/Makefile.objs
+++ b/hw/lm32/Makefile.objs
@@ -1,7 +1,3 @@
-# LM32 boards
-obj-y += lm32_boards.o
-obj-y += milkymist.o
-
 # LM32 peripherals
 obj-y += lm32_pic.o
 obj-y += lm32_juart.o
@@ -21,3 +17,7 @@ obj-y += milkymist-vgafb.o
 obj-y += framebuffer.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+# LM32 boards
+obj-y += lm32_boards.o
+obj-y += milkymist.o
diff --git a/hw/lm32/lm32_boards.c b/hw/lm32/lm32_boards.c
new file mode 100644
index 0000000..1ce466a
--- /dev/null
+++ b/hw/lm32/lm32_boards.c
@@ -0,0 +1,308 @@
+/*
+ *  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 "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/flash.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "sysemu/blockdev.h"
+#include "elf.h"
+#include "hw/lm32_hwsetup.h"
+#include "hw/lm32.h"
+#include "exec/address-spaces.h"
+
+typedef struct {
+    LM32CPU *cpu;
+    hwaddr bootstrap_pc;
+    hwaddr flash_base;
+    hwaddr hwsetup_base;
+    hwaddr initrd_base;
+    size_t initrd_size;
+    hwaddr cmdline_base;
+} ResetInfo;
+
+static void cpu_irq_handler(void *opaque, int irq, int level)
+{
+    CPULM32State *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;
+    CPULM32State *env = &reset_info->cpu->env;
+
+    cpu_reset(CPU(reset_info->cpu));
+
+    /* 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(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    LM32CPU *cpu;
+    CPULM32State *env;
+    DriveInfo *dinfo;
+    MemoryRegion *address_space_mem =  get_system_memory();
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
+    qemu_irq *cpu_irq, irq[32];
+    ResetInfo *reset_info;
+    int i;
+
+    /* memory map */
+    hwaddr flash_base  = 0x04000000;
+    size_t flash_sector_size       = 256 * 1024;
+    size_t flash_size              = 32 * 1024 * 1024;
+    hwaddr ram_base    = 0x08000000;
+    size_t ram_size                = 64 * 1024 * 1024;
+    hwaddr timer0_base = 0x80002000;
+    hwaddr uart0_base  = 0x80006000;
+    hwaddr timer1_base = 0x8000a000;
+    int uart0_irq                  = 0;
+    int timer0_irq                 = 1;
+    int timer1_irq                 = 3;
+
+    reset_info = g_malloc0(sizeof(ResetInfo));
+
+    if (cpu_model == NULL) {
+        cpu_model = "lm32-full";
+    }
+    cpu = cpu_lm32_init(cpu_model);
+    env = &cpu->env;
+    reset_info->cpu = cpu;
+
+    reset_info->flash_base = flash_base;
+
+    memory_region_init_ram(phys_ram, "lm32_evr.sdram", ram_size);
+    vmstate_register_ram_global(phys_ram);
+    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    /* Spansion S29NS128P */
+    pflash_cfi02_register(flash_base, NULL, "lm32_evr.flash", flash_size,
+                          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(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    LM32CPU *cpu;
+    CPULM32State *env;
+    DriveInfo *dinfo;
+    MemoryRegion *address_space_mem =  get_system_memory();
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
+    qemu_irq *cpu_irq, irq[32];
+    HWSetup *hw;
+    ResetInfo *reset_info;
+    int i;
+
+    /* memory map */
+    hwaddr flash_base   = 0x04000000;
+    size_t flash_sector_size        = 256 * 1024;
+    size_t flash_size               = 32 * 1024 * 1024;
+    hwaddr ram_base     = 0x08000000;
+    size_t ram_size                 = 64 * 1024 * 1024;
+    hwaddr uart0_base   = 0x80000000;
+    hwaddr timer0_base  = 0x80002000;
+    hwaddr timer1_base  = 0x80010000;
+    hwaddr timer2_base  = 0x80012000;
+    int uart0_irq                   = 0;
+    int timer0_irq                  = 1;
+    int timer1_irq                  = 20;
+    int timer2_irq                  = 21;
+    hwaddr hwsetup_base = 0x0bffe000;
+    hwaddr cmdline_base = 0x0bfff000;
+    hwaddr initrd_base  = 0x08400000;
+    size_t initrd_max               = 0x01000000;
+
+    reset_info = g_malloc0(sizeof(ResetInfo));
+
+    if (cpu_model == NULL) {
+        cpu_model = "lm32-full";
+    }
+    cpu = cpu_lm32_init(cpu_model);
+    env = &cpu->env;
+    reset_info->cpu = cpu;
+
+    reset_info->flash_base = flash_base;
+
+    memory_region_init_ram(phys_ram, "lm32_uclinux.sdram", ram_size);
+    vmstate_register_ram_global(phys_ram);
+    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    /* Spansion S29NS128P */
+    pflash_cfi02_register(flash_base, NULL, "lm32_uclinux.flash", flash_size,
+                          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,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+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,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void lm32_machine_init(void)
+{
+    qemu_register_machine(&lm32_uclinux_machine);
+    qemu_register_machine(&lm32_evr_machine);
+}
+
+machine_init(lm32_machine_init);
diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
new file mode 100644
index 0000000..fd36de5
--- /dev/null
+++ b/hw/lm32/milkymist.c
@@ -0,0 +1,218 @@
+/*
+ *  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 "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/flash.h"
+#include "sysemu/sysemu.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "sysemu/blockdev.h"
+#include "hw/milkymist-hw.h"
+#include "hw/lm32.h"
+#include "exec/address-spaces.h"
+
+#define BIOS_FILENAME    "mmone-bios.bin"
+#define BIOS_OFFSET      0x00860000
+#define BIOS_SIZE        (512*1024)
+#define KERNEL_LOAD_ADDR 0x40000000
+
+typedef struct {
+    LM32CPU *cpu;
+    hwaddr bootstrap_pc;
+    hwaddr flash_base;
+    hwaddr initrd_base;
+    size_t initrd_size;
+    hwaddr cmdline_base;
+} ResetInfo;
+
+static void cpu_irq_handler(void *opaque, int irq, int level)
+{
+    CPULM32State *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;
+    CPULM32State *env = &reset_info->cpu->env;
+
+    cpu_reset(CPU(reset_info->cpu));
+
+    /* 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(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    LM32CPU *cpu;
+    CPULM32State *env;
+    int kernel_size;
+    DriveInfo *dinfo;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *phys_sdram = g_new(MemoryRegion, 1);
+    qemu_irq irq[32], *cpu_irq;
+    int i;
+    char *bios_filename;
+    ResetInfo *reset_info;
+
+    /* memory map */
+    hwaddr flash_base   = 0x00000000;
+    size_t flash_sector_size        = 128 * 1024;
+    size_t flash_size               = 32 * 1024 * 1024;
+    hwaddr sdram_base   = 0x40000000;
+    size_t sdram_size               = 128 * 1024 * 1024;
+
+    hwaddr initrd_base  = sdram_base + 0x1002000;
+    hwaddr cmdline_base = sdram_base + 0x1000000;
+    size_t initrd_max = sdram_size - 0x1002000;
+
+    reset_info = g_malloc0(sizeof(ResetInfo));
+
+    if (cpu_model == NULL) {
+        cpu_model = "lm32-full";
+    }
+    cpu = cpu_lm32_init(cpu_model);
+    env = &cpu->env;
+    reset_info->cpu = cpu;
+
+    cpu_lm32_set_phys_msb_ignore(env, 1);
+
+    memory_region_init_ram(phys_sdram, "milkymist.sdram", sdram_size);
+    vmstate_register_ram_global(phys_sdram);
+    memory_region_add_subregion(address_space_mem, sdram_base, phys_sdram);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    /* Numonyx JS28F256J3F105 */
+    pflash_cfi01_register(flash_base, NULL, "milkymist.flash", flash_size,
+                          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]);
+    milkymist_sysctl_create(0x60001000, irq[1], irq[2], irq[3],
+            80000000, 0x10014d31, 0x0000041f, 0x00000001);
+    milkymist_hpdmc_create(0x60002000);
+    milkymist_vgafb_create(0x60003000, 0x40000000, 0x0fffffff);
+    milkymist_memcard_create(0x60004000);
+    milkymist_ac97_create(0x60005000, irq[4], irq[5], irq[6], irq[7]);
+    milkymist_pfpu_create(0x60006000, irq[8]);
+    milkymist_tmu2_create(0x60007000, irq[9]);
+    milkymist_minimac2_create(0x60008000, 0x30000000, irq[10], irq[11]);
+    milkymist_softusb_create(0x6000f000, irq[15],
+            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,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void milkymist_machine_init(void)
+{
+    qemu_register_machine(&milkymist_machine);
+}
+
+machine_init(milkymist_machine_init);
diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c
deleted file mode 100644
index 1ce466a..0000000
--- a/hw/lm32_boards.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- *  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 "hw/sysbus.h"
-#include "hw/hw.h"
-#include "hw/flash.h"
-#include "hw/devices.h"
-#include "hw/boards.h"
-#include "hw/loader.h"
-#include "sysemu/blockdev.h"
-#include "elf.h"
-#include "hw/lm32_hwsetup.h"
-#include "hw/lm32.h"
-#include "exec/address-spaces.h"
-
-typedef struct {
-    LM32CPU *cpu;
-    hwaddr bootstrap_pc;
-    hwaddr flash_base;
-    hwaddr hwsetup_base;
-    hwaddr initrd_base;
-    size_t initrd_size;
-    hwaddr cmdline_base;
-} ResetInfo;
-
-static void cpu_irq_handler(void *opaque, int irq, int level)
-{
-    CPULM32State *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;
-    CPULM32State *env = &reset_info->cpu->env;
-
-    cpu_reset(CPU(reset_info->cpu));
-
-    /* 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(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    LM32CPU *cpu;
-    CPULM32State *env;
-    DriveInfo *dinfo;
-    MemoryRegion *address_space_mem =  get_system_memory();
-    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
-    qemu_irq *cpu_irq, irq[32];
-    ResetInfo *reset_info;
-    int i;
-
-    /* memory map */
-    hwaddr flash_base  = 0x04000000;
-    size_t flash_sector_size       = 256 * 1024;
-    size_t flash_size              = 32 * 1024 * 1024;
-    hwaddr ram_base    = 0x08000000;
-    size_t ram_size                = 64 * 1024 * 1024;
-    hwaddr timer0_base = 0x80002000;
-    hwaddr uart0_base  = 0x80006000;
-    hwaddr timer1_base = 0x8000a000;
-    int uart0_irq                  = 0;
-    int timer0_irq                 = 1;
-    int timer1_irq                 = 3;
-
-    reset_info = g_malloc0(sizeof(ResetInfo));
-
-    if (cpu_model == NULL) {
-        cpu_model = "lm32-full";
-    }
-    cpu = cpu_lm32_init(cpu_model);
-    env = &cpu->env;
-    reset_info->cpu = cpu;
-
-    reset_info->flash_base = flash_base;
-
-    memory_region_init_ram(phys_ram, "lm32_evr.sdram", ram_size);
-    vmstate_register_ram_global(phys_ram);
-    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    /* Spansion S29NS128P */
-    pflash_cfi02_register(flash_base, NULL, "lm32_evr.flash", flash_size,
-                          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(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    LM32CPU *cpu;
-    CPULM32State *env;
-    DriveInfo *dinfo;
-    MemoryRegion *address_space_mem =  get_system_memory();
-    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
-    qemu_irq *cpu_irq, irq[32];
-    HWSetup *hw;
-    ResetInfo *reset_info;
-    int i;
-
-    /* memory map */
-    hwaddr flash_base   = 0x04000000;
-    size_t flash_sector_size        = 256 * 1024;
-    size_t flash_size               = 32 * 1024 * 1024;
-    hwaddr ram_base     = 0x08000000;
-    size_t ram_size                 = 64 * 1024 * 1024;
-    hwaddr uart0_base   = 0x80000000;
-    hwaddr timer0_base  = 0x80002000;
-    hwaddr timer1_base  = 0x80010000;
-    hwaddr timer2_base  = 0x80012000;
-    int uart0_irq                   = 0;
-    int timer0_irq                  = 1;
-    int timer1_irq                  = 20;
-    int timer2_irq                  = 21;
-    hwaddr hwsetup_base = 0x0bffe000;
-    hwaddr cmdline_base = 0x0bfff000;
-    hwaddr initrd_base  = 0x08400000;
-    size_t initrd_max               = 0x01000000;
-
-    reset_info = g_malloc0(sizeof(ResetInfo));
-
-    if (cpu_model == NULL) {
-        cpu_model = "lm32-full";
-    }
-    cpu = cpu_lm32_init(cpu_model);
-    env = &cpu->env;
-    reset_info->cpu = cpu;
-
-    reset_info->flash_base = flash_base;
-
-    memory_region_init_ram(phys_ram, "lm32_uclinux.sdram", ram_size);
-    vmstate_register_ram_global(phys_ram);
-    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    /* Spansion S29NS128P */
-    pflash_cfi02_register(flash_base, NULL, "lm32_uclinux.flash", flash_size,
-                          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,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-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,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void lm32_machine_init(void)
-{
-    qemu_register_machine(&lm32_uclinux_machine);
-    qemu_register_machine(&lm32_evr_machine);
-}
-
-machine_init(lm32_machine_init);
diff --git a/hw/m68k/Makefile.objs b/hw/m68k/Makefile.objs
index 93b6d25..7c033a8 100644
--- a/hw/m68k/Makefile.objs
+++ b/hw/m68k/Makefile.objs
@@ -1,4 +1,7 @@
-obj-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
-obj-y += dummy_m68k.o
+obj-y = mcf5206.o mcf_uart.o mcf_intc.o mcf_fec.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += an5206.o mcf5208.o
+obj-y += dummy_m68k.o
+
diff --git a/hw/m68k/an5206.c b/hw/m68k/an5206.c
new file mode 100644
index 0000000..7c21c66
--- /dev/null
+++ b/hw/m68k/an5206.c
@@ -0,0 +1,100 @@
+/*
+ * Arnewsh 5206 ColdFire system emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licensed under the GPL
+ */
+
+#include "hw/hw.h"
+#include "hw/mcf.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "exec/address-spaces.h"
+
+#define KERNEL_LOAD_ADDR 0x10000
+#define AN5206_MBAR_ADDR 0x10000000
+#define AN5206_RAMBAR_ADDR 0x20000000
+
+/* Board init.  */
+
+static void an5206_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    M68kCPU *cpu;
+    CPUM68KState *env;
+    int kernel_size;
+    uint64_t elf_entry;
+    hwaddr entry;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+
+    if (!cpu_model) {
+        cpu_model = "m5206";
+    }
+    cpu = cpu_m68k_init(cpu_model);
+    if (!cpu) {
+        hw_error("Unable to find m68k CPU definition\n");
+    }
+    env = &cpu->env;
+
+    /* Initialize CPU registers.  */
+    env->vbr = 0;
+    /* TODO: allow changing MBAR and RAMBAR.  */
+    env->mbar = AN5206_MBAR_ADDR | 1;
+    env->rambar0 = AN5206_RAMBAR_ADDR | 1;
+
+    /* DRAM at address zero */
+    memory_region_init_ram(ram, "an5206.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(address_space_mem, 0, ram);
+
+    /* Internal SRAM.  */
+    memory_region_init_ram(sram, "an5206.sram", 512);
+    vmstate_register_ram_global(sram);
+    memory_region_add_subregion(address_space_mem, AN5206_RAMBAR_ADDR, sram);
+
+    mcf5206_init(address_space_mem, AN5206_MBAR_ADDR, cpu);
+
+    /* Load kernel.  */
+    if (!kernel_filename) {
+        fprintf(stderr, "Kernel image must be specified\n");
+        exit(1);
+    }
+
+    kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+                           NULL, NULL, 1, ELF_MACHINE, 0);
+    entry = elf_entry;
+    if (kernel_size < 0) {
+        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
+    }
+    if (kernel_size < 0) {
+        kernel_size = load_image_targphys(kernel_filename, KERNEL_LOAD_ADDR,
+                                          ram_size - KERNEL_LOAD_ADDR);
+        entry = KERNEL_LOAD_ADDR;
+    }
+    if (kernel_size < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
+        exit(1);
+    }
+
+    env->pc = entry;
+}
+
+static QEMUMachine an5206_machine = {
+    .name = "an5206",
+    .desc = "Arnewsh 5206",
+    .init = an5206_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void an5206_machine_init(void)
+{
+    qemu_register_machine(&an5206_machine);
+}
+
+machine_init(an5206_machine_init);
diff --git a/hw/m68k/dummy_m68k.c b/hw/m68k/dummy_m68k.c
new file mode 100644
index 0000000..544d56b
--- /dev/null
+++ b/hw/m68k/dummy_m68k.c
@@ -0,0 +1,84 @@
+/*
+ * Dummy board with just RAM and CPU for use as an ISS.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licensed under the GPL
+ */
+
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "exec/address-spaces.h"
+
+#define KERNEL_LOAD_ADDR 0x10000
+
+/* Board init.  */
+
+static void dummy_m68k_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    CPUM68KState *env;
+    MemoryRegion *address_space_mem =  get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    int kernel_size;
+    uint64_t elf_entry;
+    hwaddr entry;
+
+    if (!cpu_model)
+        cpu_model = "cfv4e";
+    env = cpu_init(cpu_model);
+    if (!env) {
+        fprintf(stderr, "Unable to find m68k CPU definition\n");
+        exit(1);
+    }
+
+    /* Initialize CPU registers.  */
+    env->vbr = 0;
+
+    /* RAM at address zero */
+    memory_region_init_ram(ram, "dummy_m68k.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(address_space_mem, 0, ram);
+
+    /* Load kernel.  */
+    if (kernel_filename) {
+        kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+                               NULL, NULL, 1, ELF_MACHINE, 0);
+        entry = elf_entry;
+        if (kernel_size < 0) {
+            kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
+        }
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(kernel_filename,
+                                              KERNEL_LOAD_ADDR,
+                                              ram_size - KERNEL_LOAD_ADDR);
+            entry = KERNEL_LOAD_ADDR;
+        }
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+    } else {
+        entry = 0;
+    }
+    env->pc = entry;
+}
+
+static QEMUMachine dummy_m68k_machine = {
+    .name = "dummy",
+    .desc = "Dummy board",
+    .init = dummy_m68k_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void dummy_m68k_machine_init(void)
+{
+    qemu_register_machine(&dummy_m68k_machine);
+}
+
+machine_init(dummy_m68k_machine_init);
diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
new file mode 100644
index 0000000..748bf56
--- /dev/null
+++ b/hw/m68k/mcf5208.c
@@ -0,0 +1,306 @@
+/*
+ * Motorola ColdFire MCF5208 SoC emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licensed under the GPL
+ */
+#include "hw/hw.h"
+#include "hw/mcf.h"
+#include "qemu/timer.h"
+#include "hw/ptimer.h"
+#include "sysemu/sysemu.h"
+#include "net/net.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "exec/address-spaces.h"
+
+#define SYS_FREQ 66000000
+
+#define PCSR_EN         0x0001
+#define PCSR_RLD        0x0002
+#define PCSR_PIF        0x0004
+#define PCSR_PIE        0x0008
+#define PCSR_OVW        0x0010
+#define PCSR_DBG        0x0020
+#define PCSR_DOZE       0x0040
+#define PCSR_PRE_SHIFT  8
+#define PCSR_PRE_MASK   0x0f00
+
+typedef struct {
+    MemoryRegion iomem;
+    qemu_irq irq;
+    ptimer_state *timer;
+    uint16_t pcsr;
+    uint16_t pmr;
+    uint16_t pcntr;
+} m5208_timer_state;
+
+static void m5208_timer_update(m5208_timer_state *s)
+{
+    if ((s->pcsr & (PCSR_PIE | PCSR_PIF)) == (PCSR_PIE | PCSR_PIF))
+        qemu_irq_raise(s->irq);
+    else
+        qemu_irq_lower(s->irq);
+}
+
+static void m5208_timer_write(void *opaque, hwaddr offset,
+                              uint64_t value, unsigned size)
+{
+    m5208_timer_state *s = (m5208_timer_state *)opaque;
+    int prescale;
+    int limit;
+    switch (offset) {
+    case 0:
+        /* The PIF bit is set-to-clear.  */
+        if (value & PCSR_PIF) {
+            s->pcsr &= ~PCSR_PIF;
+            value &= ~PCSR_PIF;
+        }
+        /* Avoid frobbing the timer if we're just twiddling IRQ bits. */
+        if (((s->pcsr ^ value) & ~PCSR_PIE) == 0) {
+            s->pcsr = value;
+            m5208_timer_update(s);
+            return;
+        }
+
+        if (s->pcsr & PCSR_EN)
+            ptimer_stop(s->timer);
+
+        s->pcsr = value;
+
+        prescale = 1 << ((s->pcsr & PCSR_PRE_MASK) >> PCSR_PRE_SHIFT);
+        ptimer_set_freq(s->timer, (SYS_FREQ / 2) / prescale);
+        if (s->pcsr & PCSR_RLD)
+            limit = s->pmr;
+        else
+            limit = 0xffff;
+        ptimer_set_limit(s->timer, limit, 0);
+
+        if (s->pcsr & PCSR_EN)
+            ptimer_run(s->timer, 0);
+        break;
+    case 2:
+        s->pmr = value;
+        s->pcsr &= ~PCSR_PIF;
+        if ((s->pcsr & PCSR_RLD) == 0) {
+            if (s->pcsr & PCSR_OVW)
+                ptimer_set_count(s->timer, value);
+        } else {
+            ptimer_set_limit(s->timer, value, s->pcsr & PCSR_OVW);
+        }
+        break;
+    case 4:
+        break;
+    default:
+        hw_error("m5208_timer_write: Bad offset 0x%x\n", (int)offset);
+        break;
+    }
+    m5208_timer_update(s);
+}
+
+static void m5208_timer_trigger(void *opaque)
+{
+    m5208_timer_state *s = (m5208_timer_state *)opaque;
+    s->pcsr |= PCSR_PIF;
+    m5208_timer_update(s);
+}
+
+static uint64_t m5208_timer_read(void *opaque, hwaddr addr,
+                                 unsigned size)
+{
+    m5208_timer_state *s = (m5208_timer_state *)opaque;
+    switch (addr) {
+    case 0:
+        return s->pcsr;
+    case 2:
+        return s->pmr;
+    case 4:
+        return ptimer_get_count(s->timer);
+    default:
+        hw_error("m5208_timer_read: Bad offset 0x%x\n", (int)addr);
+        return 0;
+    }
+}
+
+static const MemoryRegionOps m5208_timer_ops = {
+    .read = m5208_timer_read,
+    .write = m5208_timer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static uint64_t m5208_sys_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    switch (addr) {
+    case 0x110: /* SDCS0 */
+        {
+            int n;
+            for (n = 0; n < 32; n++) {
+                if (ram_size < (2u << n))
+                    break;
+            }
+            return (n - 1)  | 0x40000000;
+        }
+    case 0x114: /* SDCS1 */
+        return 0;
+
+    default:
+        hw_error("m5208_sys_read: Bad offset 0x%x\n", (int)addr);
+        return 0;
+    }
+}
+
+static void m5208_sys_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    hw_error("m5208_sys_write: Bad offset 0x%x\n", (int)addr);
+}
+
+static const MemoryRegionOps m5208_sys_ops = {
+    .read = m5208_sys_read,
+    .write = m5208_sys_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic)
+{
+    MemoryRegion *iomem = g_new(MemoryRegion, 1);
+    m5208_timer_state *s;
+    QEMUBH *bh;
+    int i;
+
+    /* SDRAMC.  */
+    memory_region_init_io(iomem, &m5208_sys_ops, NULL, "m5208-sys", 0x00004000);
+    memory_region_add_subregion(address_space, 0xfc0a8000, iomem);
+    /* Timers.  */
+    for (i = 0; i < 2; i++) {
+        s = (m5208_timer_state *)g_malloc0(sizeof(m5208_timer_state));
+        bh = qemu_bh_new(m5208_timer_trigger, s);
+        s->timer = ptimer_init(bh);
+        memory_region_init_io(&s->iomem, &m5208_timer_ops, s,
+                              "m5208-timer", 0x00004000);
+        memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i,
+                                    &s->iomem);
+        s->irq = pic[4 + i];
+    }
+}
+
+static void mcf5208evb_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    M68kCPU *cpu;
+    CPUM68KState *env;
+    int kernel_size;
+    uint64_t elf_entry;
+    hwaddr entry;
+    qemu_irq *pic;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+
+    if (!cpu_model) {
+        cpu_model = "m5208";
+    }
+    cpu = cpu_m68k_init(cpu_model);
+    if (!cpu) {
+        fprintf(stderr, "Unable to find m68k CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    /* Initialize CPU registers.  */
+    env->vbr = 0;
+    /* TODO: Configure BARs.  */
+
+    /* DRAM at 0x40000000 */
+    memory_region_init_ram(ram, "mcf5208.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(address_space_mem, 0x40000000, ram);
+
+    /* Internal SRAM.  */
+    memory_region_init_ram(sram, "mcf5208.sram", 16384);
+    vmstate_register_ram_global(sram);
+    memory_region_add_subregion(address_space_mem, 0x80000000, sram);
+
+    /* Internal peripherals.  */
+    pic = mcf_intc_init(address_space_mem, 0xfc048000, cpu);
+
+    mcf_uart_mm_init(address_space_mem, 0xfc060000, pic[26], serial_hds[0]);
+    mcf_uart_mm_init(address_space_mem, 0xfc064000, pic[27], serial_hds[1]);
+    mcf_uart_mm_init(address_space_mem, 0xfc068000, pic[28], serial_hds[2]);
+
+    mcf5208_sys_init(address_space_mem, pic);
+
+    if (nb_nics > 1) {
+        fprintf(stderr, "Too many NICs\n");
+        exit(1);
+    }
+    if (nd_table[0].used)
+        mcf_fec_init(address_space_mem, &nd_table[0],
+                     0xfc030000, pic + 36);
+
+    /*  0xfc000000 SCM.  */
+    /*  0xfc004000 XBS.  */
+    /*  0xfc008000 FlexBus CS.  */
+    /* 0xfc030000 FEC.  */
+    /*  0xfc040000 SCM + Power management.  */
+    /*  0xfc044000 eDMA.  */
+    /* 0xfc048000 INTC.  */
+    /*  0xfc058000 I2C.  */
+    /*  0xfc05c000 QSPI.  */
+    /* 0xfc060000 UART0.  */
+    /* 0xfc064000 UART0.  */
+    /* 0xfc068000 UART0.  */
+    /*  0xfc070000 DMA timers.  */
+    /* 0xfc080000 PIT0.  */
+    /* 0xfc084000 PIT1.  */
+    /*  0xfc088000 EPORT.  */
+    /*  0xfc08c000 Watchdog.  */
+    /*  0xfc090000 clock module.  */
+    /*  0xfc0a0000 CCM + reset.  */
+    /*  0xfc0a4000 GPIO.  */
+    /* 0xfc0a8000 SDRAM controller.  */
+
+    /* Load kernel.  */
+    if (!kernel_filename) {
+        fprintf(stderr, "Kernel image must be specified\n");
+        exit(1);
+    }
+
+    kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+                           NULL, NULL, 1, ELF_MACHINE, 0);
+    entry = elf_entry;
+    if (kernel_size < 0) {
+        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
+    }
+    if (kernel_size < 0) {
+        kernel_size = load_image_targphys(kernel_filename, 0x40000000,
+                                          ram_size);
+        entry = 0x40000000;
+    }
+    if (kernel_size < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
+        exit(1);
+    }
+
+    env->pc = entry;
+}
+
+static QEMUMachine mcf5208evb_machine = {
+    .name = "mcf5208evb",
+    .desc = "MCF5206EVB",
+    .init = mcf5208evb_init,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void mcf5208evb_machine_init(void)
+{
+    qemu_register_machine(&mcf5208evb_machine);
+}
+
+machine_init(mcf5208evb_machine_init);
diff --git a/hw/mainstone.c b/hw/mainstone.c
deleted file mode 100644
index aea908f..0000000
--- a/hw/mainstone.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * PXA270-based Intel Mainstone platforms.
- *
- * Copyright (c) 2007 by Armin Kuster <akuster at kama-aina.net> or
- *                                    <akuster at mvista.com>
- *
- * Code based on spitz platform by Andrzej Zaborowski <balrog at zabor.org>
- *
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-#include "hw/hw.h"
-#include "hw/pxa.h"
-#include "hw/arm-misc.h"
-#include "net/net.h"
-#include "hw/devices.h"
-#include "hw/boards.h"
-#include "hw/flash.h"
-#include "sysemu/blockdev.h"
-#include "hw/sysbus.h"
-#include "exec/address-spaces.h"
-
-/* Device addresses */
-#define MST_FPGA_PHYS	0x08000000
-#define MST_ETH_PHYS	0x10000300
-#define MST_FLASH_0		0x00000000
-#define MST_FLASH_1		0x04000000
-
-/* IRQ definitions */
-#define MMC_IRQ       0
-#define USIM_IRQ      1
-#define USBC_IRQ      2
-#define ETHERNET_IRQ  3
-#define AC97_IRQ      4
-#define PEN_IRQ       5
-#define MSINS_IRQ     6
-#define EXBRD_IRQ     7
-#define S0_CD_IRQ     9
-#define S0_STSCHG_IRQ 10
-#define S0_IRQ        11
-#define S1_CD_IRQ     13
-#define S1_STSCHG_IRQ 14
-#define S1_IRQ        15
-
-static struct keymap map[0xE0] = {
-    [0 ... 0xDF] = { -1, -1 },
-    [0x1e] = {0,0}, /* a */
-    [0x30] = {0,1}, /* b */
-    [0x2e] = {0,2}, /* c */
-    [0x20] = {0,3}, /* d */
-    [0x12] = {0,4}, /* e */
-    [0x21] = {0,5}, /* f */
-    [0x22] = {1,0}, /* g */
-    [0x23] = {1,1}, /* h */
-    [0x17] = {1,2}, /* i */
-    [0x24] = {1,3}, /* j */
-    [0x25] = {1,4}, /* k */
-    [0x26] = {1,5}, /* l */
-    [0x32] = {2,0}, /* m */
-    [0x31] = {2,1}, /* n */
-    [0x18] = {2,2}, /* o */
-    [0x19] = {2,3}, /* p */
-    [0x10] = {2,4}, /* q */
-    [0x13] = {2,5}, /* r */
-    [0x1f] = {3,0}, /* s */
-    [0x14] = {3,1}, /* t */
-    [0x16] = {3,2}, /* u */
-    [0x2f] = {3,3}, /* v */
-    [0x11] = {3,4}, /* w */
-    [0x2d] = {3,5}, /* x */
-    [0x15] = {4,2}, /* y */
-    [0x2c] = {4,3}, /* z */
-    [0xc7] = {5,0}, /* Home */
-    [0x2a] = {5,1}, /* shift */
-    [0x39] = {5,2}, /* space */
-    [0x39] = {5,3}, /* space */
-    [0x1c] = {5,5}, /*  enter */
-    [0xc8] = {6,0}, /* up */
-    [0xd0] = {6,1}, /* down */
-    [0xcb] = {6,2}, /* left */
-    [0xcd] = {6,3}, /* right */
-};
-
-enum mainstone_model_e { mainstone };
-
-#define MAINSTONE_RAM	0x04000000
-#define MAINSTONE_ROM	0x00800000
-#define MAINSTONE_FLASH	0x02000000
-
-static struct arm_boot_info mainstone_binfo = {
-    .loader_start = PXA2XX_SDRAM_BASE,
-    .ram_size = 0x04000000,
-};
-
-static void mainstone_common_init(MemoryRegion *address_space_mem,
-                                  QEMUMachineInitArgs *args,
-                                  enum mainstone_model_e model, int arm_id)
-{
-    uint32_t sector_len = 256 * 1024;
-    hwaddr mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 };
-    PXA2xxState *mpu;
-    DeviceState *mst_irq;
-    DriveInfo *dinfo;
-    int i;
-    int be;
-    MemoryRegion *rom = g_new(MemoryRegion, 1);
-    const char *cpu_model = args->cpu_model;
-
-    if (!cpu_model)
-        cpu_model = "pxa270-c5";
-
-    /* Setup CPU & memory */
-    mpu = pxa270_init(address_space_mem, mainstone_binfo.ram_size, cpu_model);
-    memory_region_init_ram(rom, "mainstone.rom", MAINSTONE_ROM);
-    vmstate_register_ram_global(rom);
-    memory_region_set_readonly(rom, true);
-    memory_region_add_subregion(address_space_mem, 0, rom);
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
-#else
-    be = 0;
-#endif
-    /* There are two 32MiB flash devices on the board */
-    for (i = 0; i < 2; i ++) {
-        dinfo = drive_get(IF_PFLASH, 0, i);
-        if (!dinfo) {
-            fprintf(stderr, "Two flash images must be given with the "
-                    "'pflash' parameter\n");
-            exit(1);
-        }
-
-        if (!pflash_cfi01_register(mainstone_flash_base[i], NULL,
-                                   i ? "mainstone.flash1" : "mainstone.flash0",
-                                   MAINSTONE_FLASH,
-                                   dinfo->bdrv, sector_len,
-                                   MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0,
-                                   be)) {
-            fprintf(stderr, "qemu: Error registering flash memory.\n");
-            exit(1);
-        }
-    }
-
-    mst_irq = sysbus_create_simple("mainstone-fpga", MST_FPGA_PHYS,
-                    qdev_get_gpio_in(mpu->gpio, 0));
-
-    /* setup keypad */
-    printf("map addr %p\n", &map);
-    pxa27x_register_keypad(mpu->kp, map, 0xe0);
-
-    /* MMC/SD host */
-    pxa2xx_mmci_handlers(mpu->mmc, NULL, qdev_get_gpio_in(mst_irq, MMC_IRQ));
-
-    pxa2xx_pcmcia_set_irq_cb(mpu->pcmcia[0],
-            qdev_get_gpio_in(mst_irq, S0_IRQ),
-            qdev_get_gpio_in(mst_irq, S0_CD_IRQ));
-    pxa2xx_pcmcia_set_irq_cb(mpu->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));
-
-    mainstone_binfo.kernel_filename = args->kernel_filename;
-    mainstone_binfo.kernel_cmdline = args->kernel_cmdline;
-    mainstone_binfo.initrd_filename = args->initrd_filename;
-    mainstone_binfo.board_id = arm_id;
-    arm_load_kernel(mpu->cpu, &mainstone_binfo);
-}
-
-static void mainstone_init(QEMUMachineInitArgs *args)
-{
-    mainstone_common_init(get_system_memory(), args, mainstone, 0x196);
-}
-
-static QEMUMachine mainstone2_machine = {
-    .name = "mainstone",
-    .desc = "Mainstone II (PXA27x)",
-    .init = mainstone_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void mainstone_machine_init(void)
-{
-    qemu_register_machine(&mainstone2_machine);
-}
-
-machine_init(mainstone_machine_init);
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
deleted file mode 100644
index 748bf56..0000000
--- a/hw/mcf5208.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Motorola ColdFire MCF5208 SoC emulation.
- *
- * Copyright (c) 2007 CodeSourcery.
- *
- * This code is licensed under the GPL
- */
-#include "hw/hw.h"
-#include "hw/mcf.h"
-#include "qemu/timer.h"
-#include "hw/ptimer.h"
-#include "sysemu/sysemu.h"
-#include "net/net.h"
-#include "hw/boards.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "exec/address-spaces.h"
-
-#define SYS_FREQ 66000000
-
-#define PCSR_EN         0x0001
-#define PCSR_RLD        0x0002
-#define PCSR_PIF        0x0004
-#define PCSR_PIE        0x0008
-#define PCSR_OVW        0x0010
-#define PCSR_DBG        0x0020
-#define PCSR_DOZE       0x0040
-#define PCSR_PRE_SHIFT  8
-#define PCSR_PRE_MASK   0x0f00
-
-typedef struct {
-    MemoryRegion iomem;
-    qemu_irq irq;
-    ptimer_state *timer;
-    uint16_t pcsr;
-    uint16_t pmr;
-    uint16_t pcntr;
-} m5208_timer_state;
-
-static void m5208_timer_update(m5208_timer_state *s)
-{
-    if ((s->pcsr & (PCSR_PIE | PCSR_PIF)) == (PCSR_PIE | PCSR_PIF))
-        qemu_irq_raise(s->irq);
-    else
-        qemu_irq_lower(s->irq);
-}
-
-static void m5208_timer_write(void *opaque, hwaddr offset,
-                              uint64_t value, unsigned size)
-{
-    m5208_timer_state *s = (m5208_timer_state *)opaque;
-    int prescale;
-    int limit;
-    switch (offset) {
-    case 0:
-        /* The PIF bit is set-to-clear.  */
-        if (value & PCSR_PIF) {
-            s->pcsr &= ~PCSR_PIF;
-            value &= ~PCSR_PIF;
-        }
-        /* Avoid frobbing the timer if we're just twiddling IRQ bits. */
-        if (((s->pcsr ^ value) & ~PCSR_PIE) == 0) {
-            s->pcsr = value;
-            m5208_timer_update(s);
-            return;
-        }
-
-        if (s->pcsr & PCSR_EN)
-            ptimer_stop(s->timer);
-
-        s->pcsr = value;
-
-        prescale = 1 << ((s->pcsr & PCSR_PRE_MASK) >> PCSR_PRE_SHIFT);
-        ptimer_set_freq(s->timer, (SYS_FREQ / 2) / prescale);
-        if (s->pcsr & PCSR_RLD)
-            limit = s->pmr;
-        else
-            limit = 0xffff;
-        ptimer_set_limit(s->timer, limit, 0);
-
-        if (s->pcsr & PCSR_EN)
-            ptimer_run(s->timer, 0);
-        break;
-    case 2:
-        s->pmr = value;
-        s->pcsr &= ~PCSR_PIF;
-        if ((s->pcsr & PCSR_RLD) == 0) {
-            if (s->pcsr & PCSR_OVW)
-                ptimer_set_count(s->timer, value);
-        } else {
-            ptimer_set_limit(s->timer, value, s->pcsr & PCSR_OVW);
-        }
-        break;
-    case 4:
-        break;
-    default:
-        hw_error("m5208_timer_write: Bad offset 0x%x\n", (int)offset);
-        break;
-    }
-    m5208_timer_update(s);
-}
-
-static void m5208_timer_trigger(void *opaque)
-{
-    m5208_timer_state *s = (m5208_timer_state *)opaque;
-    s->pcsr |= PCSR_PIF;
-    m5208_timer_update(s);
-}
-
-static uint64_t m5208_timer_read(void *opaque, hwaddr addr,
-                                 unsigned size)
-{
-    m5208_timer_state *s = (m5208_timer_state *)opaque;
-    switch (addr) {
-    case 0:
-        return s->pcsr;
-    case 2:
-        return s->pmr;
-    case 4:
-        return ptimer_get_count(s->timer);
-    default:
-        hw_error("m5208_timer_read: Bad offset 0x%x\n", (int)addr);
-        return 0;
-    }
-}
-
-static const MemoryRegionOps m5208_timer_ops = {
-    .read = m5208_timer_read,
-    .write = m5208_timer_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static uint64_t m5208_sys_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    switch (addr) {
-    case 0x110: /* SDCS0 */
-        {
-            int n;
-            for (n = 0; n < 32; n++) {
-                if (ram_size < (2u << n))
-                    break;
-            }
-            return (n - 1)  | 0x40000000;
-        }
-    case 0x114: /* SDCS1 */
-        return 0;
-
-    default:
-        hw_error("m5208_sys_read: Bad offset 0x%x\n", (int)addr);
-        return 0;
-    }
-}
-
-static void m5208_sys_write(void *opaque, hwaddr addr,
-                            uint64_t value, unsigned size)
-{
-    hw_error("m5208_sys_write: Bad offset 0x%x\n", (int)addr);
-}
-
-static const MemoryRegionOps m5208_sys_ops = {
-    .read = m5208_sys_read,
-    .write = m5208_sys_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic)
-{
-    MemoryRegion *iomem = g_new(MemoryRegion, 1);
-    m5208_timer_state *s;
-    QEMUBH *bh;
-    int i;
-
-    /* SDRAMC.  */
-    memory_region_init_io(iomem, &m5208_sys_ops, NULL, "m5208-sys", 0x00004000);
-    memory_region_add_subregion(address_space, 0xfc0a8000, iomem);
-    /* Timers.  */
-    for (i = 0; i < 2; i++) {
-        s = (m5208_timer_state *)g_malloc0(sizeof(m5208_timer_state));
-        bh = qemu_bh_new(m5208_timer_trigger, s);
-        s->timer = ptimer_init(bh);
-        memory_region_init_io(&s->iomem, &m5208_timer_ops, s,
-                              "m5208-timer", 0x00004000);
-        memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i,
-                                    &s->iomem);
-        s->irq = pic[4 + i];
-    }
-}
-
-static void mcf5208evb_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    M68kCPU *cpu;
-    CPUM68KState *env;
-    int kernel_size;
-    uint64_t elf_entry;
-    hwaddr entry;
-    qemu_irq *pic;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-
-    if (!cpu_model) {
-        cpu_model = "m5208";
-    }
-    cpu = cpu_m68k_init(cpu_model);
-    if (!cpu) {
-        fprintf(stderr, "Unable to find m68k CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    /* Initialize CPU registers.  */
-    env->vbr = 0;
-    /* TODO: Configure BARs.  */
-
-    /* DRAM at 0x40000000 */
-    memory_region_init_ram(ram, "mcf5208.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(address_space_mem, 0x40000000, ram);
-
-    /* Internal SRAM.  */
-    memory_region_init_ram(sram, "mcf5208.sram", 16384);
-    vmstate_register_ram_global(sram);
-    memory_region_add_subregion(address_space_mem, 0x80000000, sram);
-
-    /* Internal peripherals.  */
-    pic = mcf_intc_init(address_space_mem, 0xfc048000, cpu);
-
-    mcf_uart_mm_init(address_space_mem, 0xfc060000, pic[26], serial_hds[0]);
-    mcf_uart_mm_init(address_space_mem, 0xfc064000, pic[27], serial_hds[1]);
-    mcf_uart_mm_init(address_space_mem, 0xfc068000, pic[28], serial_hds[2]);
-
-    mcf5208_sys_init(address_space_mem, pic);
-
-    if (nb_nics > 1) {
-        fprintf(stderr, "Too many NICs\n");
-        exit(1);
-    }
-    if (nd_table[0].used)
-        mcf_fec_init(address_space_mem, &nd_table[0],
-                     0xfc030000, pic + 36);
-
-    /*  0xfc000000 SCM.  */
-    /*  0xfc004000 XBS.  */
-    /*  0xfc008000 FlexBus CS.  */
-    /* 0xfc030000 FEC.  */
-    /*  0xfc040000 SCM + Power management.  */
-    /*  0xfc044000 eDMA.  */
-    /* 0xfc048000 INTC.  */
-    /*  0xfc058000 I2C.  */
-    /*  0xfc05c000 QSPI.  */
-    /* 0xfc060000 UART0.  */
-    /* 0xfc064000 UART0.  */
-    /* 0xfc068000 UART0.  */
-    /*  0xfc070000 DMA timers.  */
-    /* 0xfc080000 PIT0.  */
-    /* 0xfc084000 PIT1.  */
-    /*  0xfc088000 EPORT.  */
-    /*  0xfc08c000 Watchdog.  */
-    /*  0xfc090000 clock module.  */
-    /*  0xfc0a0000 CCM + reset.  */
-    /*  0xfc0a4000 GPIO.  */
-    /* 0xfc0a8000 SDRAM controller.  */
-
-    /* Load kernel.  */
-    if (!kernel_filename) {
-        fprintf(stderr, "Kernel image must be specified\n");
-        exit(1);
-    }
-
-    kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                           NULL, NULL, 1, ELF_MACHINE, 0);
-    entry = elf_entry;
-    if (kernel_size < 0) {
-        kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
-    }
-    if (kernel_size < 0) {
-        kernel_size = load_image_targphys(kernel_filename, 0x40000000,
-                                          ram_size);
-        entry = 0x40000000;
-    }
-    if (kernel_size < 0) {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
-        exit(1);
-    }
-
-    env->pc = entry;
-}
-
-static QEMUMachine mcf5208evb_machine = {
-    .name = "mcf5208evb",
-    .desc = "MCF5206EVB",
-    .init = mcf5208evb_init,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void mcf5208evb_machine_init(void)
-{
-    qemu_register_machine(&mcf5208evb_machine);
-}
-
-machine_init(mcf5208evb_machine_init);
diff --git a/hw/microblaze/Makefile.objs b/hw/microblaze/Makefile.objs
index 2ff8048..9e7f249 100644
--- a/hw/microblaze/Makefile.objs
+++ b/hw/microblaze/Makefile.objs
@@ -1,9 +1,9 @@
-obj-y = petalogix_s3adsp1800_mmu.o
-obj-y += petalogix_ml605_mmu.o
-obj-y += microblaze_boot.o
 obj-y += xilinx_spi.o
-
-obj-y += microblaze_pic_cpu.o
 obj-y += xilinx_ethlite.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += petalogix_s3adsp1800_mmu.o
+obj-y += petalogix_ml605_mmu.o
+obj-y += boot.o
+obj-y += pic_cpu.o
diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
new file mode 100644
index 0000000..e13b3e1
--- /dev/null
+++ b/hw/microblaze/boot.c
@@ -0,0 +1,177 @@
+/*
+ * Microblaze kernel loader
+ *
+ * Copyright (c) 2012 Peter Crosthwaite <peter.crosthwaite at petalogix.com>
+ * Copyright (c) 2012 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 "qemu/option.h"
+#include "qemu/config-file.h"
+#include "qemu-common.h"
+#include "sysemu/device_tree.h"
+#include "hw/loader.h"
+#include "elf.h"
+
+#include "hw/microblaze_boot.h"
+
+static struct
+{
+    void (*machine_cpu_reset)(MicroBlazeCPU *);
+    uint32_t bootstrap_pc;
+    uint32_t cmdline;
+    uint32_t fdt;
+} boot_info;
+
+static void main_cpu_reset(void *opaque)
+{
+    MicroBlazeCPU *cpu = opaque;
+    CPUMBState *env = &cpu->env;
+
+    cpu_reset(CPU(cpu));
+    env->regs[5] = boot_info.cmdline;
+    env->regs[7] = boot_info.fdt;
+    env->sregs[SR_PC] = boot_info.bootstrap_pc;
+    if (boot_info.machine_cpu_reset) {
+        boot_info.machine_cpu_reset(cpu);
+    }
+}
+
+static int microblaze_load_dtb(hwaddr addr,
+                                      uint32_t ramsize,
+                                      const char *kernel_cmdline,
+                                      const char *dtb_filename)
+{
+    int fdt_size;
+#ifdef CONFIG_FDT
+    void *fdt = NULL;
+    int r;
+
+    if (dtb_filename) {
+        fdt = load_device_tree(dtb_filename, &fdt_size);
+    }
+    if (!fdt) {
+        return 0;
+    }
+
+    if (kernel_cmdline) {
+        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.  */
+    if (dtb_filename) {
+        fdt_size = load_image_targphys(dtb_filename, addr, 0x10000);
+    }
+    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;
+}
+
+void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
+                            uint32_t ramsize, const char *dtb_filename,
+                            void (*machine_cpu_reset)(MicroBlazeCPU *))
+{
+    QemuOpts *machine_opts;
+    const char *kernel_filename = NULL;
+    const char *kernel_cmdline = NULL;
+
+    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
+    if (machine_opts) {
+        const char *dtb_arg;
+        kernel_filename = qemu_opt_get(machine_opts, "kernel");
+        kernel_cmdline = qemu_opt_get(machine_opts, "append");
+        dtb_arg = qemu_opt_get(machine_opts, "dtb");
+        if (dtb_arg) { /* Preference a -dtb argument */
+            dtb_filename = dtb_arg;
+        } else { /* default to pcbios dtb as passed by machine_init */
+            dtb_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
+        }
+    }
+
+    boot_info.machine_cpu_reset = machine_cpu_reset;
+    qemu_register_reset(main_cpu_reset, cpu);
+
+    if (kernel_filename) {
+        int kernel_size;
+        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) {
+            hwaddr 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;
+        microblaze_load_dtb(boot_info.fdt, ram_size, kernel_cmdline,
+                                                     dtb_filename);
+    }
+
+}
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
new file mode 100644
index 0000000..cfc0220
--- /dev/null
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -0,0 +1,186 @@
+/*
+ * 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 "hw/sysbus.h"
+#include "hw/hw.h"
+#include "net/net.h"
+#include "hw/flash.h"
+#include "sysemu/sysemu.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/xilinx.h"
+#include "sysemu/blockdev.h"
+#include "hw/serial.h"
+#include "exec/address-spaces.h"
+#include "hw/ssi.h"
+
+#include "hw/microblaze_boot.h"
+#include "hw/microblaze_pic_cpu.h"
+
+#include "hw/stream.h"
+
+#define LMB_BRAM_SIZE  (128 * 1024)
+#define FLASH_SIZE     (32 * 1024 * 1024)
+
+#define BINARY_DEVICE_TREE_FILE "petalogix-ml605.dtb"
+
+#define NUM_SPI_FLASHES 4
+
+#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 machine_cpu_reset(MicroBlazeCPU *cpu)
+{
+    CPUMBState *env = &cpu->env;
+
+    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;
+}
+
+static void
+petalogix_ml605_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    MemoryRegion *address_space_mem = get_system_memory();
+    DeviceState *dev, *dma, *eth0;
+    MicroBlazeCPU *cpu;
+    SysBusDevice *busdev;
+    CPUMBState *env;
+    DriveInfo *dinfo;
+    int i;
+    hwaddr ddr_base = MEMORY_BASEADDR;
+    MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1);
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
+    qemu_irq irq[32], *cpu_irq;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+        cpu_model = "microblaze";
+    }
+    cpu = cpu_mb_init(cpu_model);
+    env = &cpu->env;
+
+    /* Attach emulated BRAM through the LMB.  */
+    memory_region_init_ram(phys_lmb_bram, "petalogix_ml605.lmb_bram",
+                           LMB_BRAM_SIZE);
+    vmstate_register_ram_global(phys_lmb_bram);
+    memory_region_add_subregion(address_space_mem, 0x00000000, phys_lmb_bram);
+
+    memory_region_init_ram(phys_ram, "petalogix_ml605.ram", ram_size);
+    vmstate_register_ram_global(phys_ram);
+    memory_region_add_subregion(address_space_mem, ddr_base, phys_ram);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    /* 5th parameter 2 means bank-width
+     * 10th paremeter 0 means little-endian */
+    pflash_cfi01_register(FLASH_BASEADDR,
+                          NULL, "petalogix_ml605.flash", FLASH_SIZE,
+                          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_mm_init(address_space_mem, UART16550_BASEADDR + 0x1000, 2,
+                   irq[5], 115200, serial_hds[0], DEVICE_LITTLE_ENDIAN);
+
+    /* 2 timers at irq 2 @ 100 Mhz.  */
+    xilinx_timer_create(TIMER_BASEADDR, irq[2], 0, 100 * 1000000);
+
+    /* axi ethernet and dma initialization. */
+    qemu_check_nic_model(&nd_table[0], "xlnx.axi-ethernet");
+    eth0 = qdev_create(NULL, "xlnx.axi-ethernet");
+    dma = qdev_create(NULL, "xlnx.axi-dma");
+
+    /* FIXME: attach to the sysbus instead */
+    object_property_add_child(container_get(qdev_get_machine(), "/unattached"),
+                                  "xilinx-dma", OBJECT(dma), NULL);
+
+    xilinx_axiethernet_init(eth0, &nd_table[0], STREAM_SLAVE(dma),
+                                   0x82780000, irq[3], 0x1000, 0x1000);
+
+    xilinx_axidma_init(dma, STREAM_SLAVE(eth0), 0x84600000, irq[1], irq[0],
+                       100 * 1000000);
+
+    {
+        SSIBus *spi;
+
+        dev = qdev_create(NULL, "xlnx.xps-spi");
+        qdev_prop_set_uint8(dev, "num-ss-bits", NUM_SPI_FLASHES);
+        qdev_init_nofail(dev);
+        busdev = SYS_BUS_DEVICE(dev);
+        sysbus_mmio_map(busdev, 0, 0x40a00000);
+        sysbus_connect_irq(busdev, 0, irq[4]);
+
+        spi = (SSIBus *)qdev_get_child_bus(dev, "spi");
+
+        for (i = 0; i < NUM_SPI_FLASHES; i++) {
+            qemu_irq cs_line;
+
+            dev = ssi_create_slave_no_init(spi, "n25q128");
+            qdev_init_nofail(dev);
+            cs_line = qdev_get_gpio_in(dev, 0);
+            sysbus_connect_irq(busdev, i+1, cs_line);
+        }
+    }
+
+    microblaze_load_kernel(cpu, ddr_base, ram_size, BINARY_DEVICE_TREE_FILE,
+                                                            machine_cpu_reset);
+
+}
+
+static QEMUMachine petalogix_ml605_machine = {
+    .name = "petalogix-ml605",
+    .desc = "PetaLogix linux refdesign for xilinx ml605 little endian",
+    .init = petalogix_ml605_init,
+    .is_default = 0,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void petalogix_ml605_machine_init(void)
+{
+    qemu_register_machine(&petalogix_ml605_machine);
+}
+
+machine_init(petalogix_ml605_machine_init);
diff --git a/hw/microblaze/petalogix_s3adsp1800_mmu.c b/hw/microblaze/petalogix_s3adsp1800_mmu.c
new file mode 100644
index 0000000..2498362
--- /dev/null
+++ b/hw/microblaze/petalogix_s3adsp1800_mmu.c
@@ -0,0 +1,127 @@
+/*
+ * Model of Petalogix linux reference design targeting Xilinx Spartan 3ADSP-1800
+ * boards.
+ *
+ * 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 "hw/sysbus.h"
+#include "hw/hw.h"
+#include "net/net.h"
+#include "hw/flash.h"
+#include "sysemu/sysemu.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/xilinx.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+#include "hw/microblaze_boot.h"
+#include "hw/microblaze_pic_cpu.h"
+
+#define LMB_BRAM_SIZE  (128 * 1024)
+#define FLASH_SIZE     (16 * 1024 * 1024)
+
+#define BINARY_DEVICE_TREE_FILE "petalogix-s3adsp1800.dtb"
+
+#define MEMORY_BASEADDR 0x90000000
+#define FLASH_BASEADDR 0xa0000000
+#define INTC_BASEADDR 0x81800000
+#define TIMER_BASEADDR 0x83c00000
+#define UARTLITE_BASEADDR 0x84000000
+#define ETHLITE_BASEADDR 0x81000000
+
+static void machine_cpu_reset(MicroBlazeCPU *cpu)
+{
+    CPUMBState *env = &cpu->env;
+
+    env->pvr.regs[10] = 0x0c000000; /* spartan 3a dsp family.  */
+}
+
+static void
+petalogix_s3adsp1800_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    DeviceState *dev;
+    MicroBlazeCPU *cpu;
+    CPUMBState *env;
+    DriveInfo *dinfo;
+    int i;
+    hwaddr ddr_base = MEMORY_BASEADDR;
+    MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1);
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
+    qemu_irq irq[32], *cpu_irq;
+    MemoryRegion *sysmem = get_system_memory();
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+        cpu_model = "microblaze";
+    }
+    cpu = cpu_mb_init(cpu_model);
+    env = &cpu->env;
+
+    /* Attach emulated BRAM through the LMB.  */
+    memory_region_init_ram(phys_lmb_bram,
+                           "petalogix_s3adsp1800.lmb_bram", LMB_BRAM_SIZE);
+    vmstate_register_ram_global(phys_lmb_bram);
+    memory_region_add_subregion(sysmem, 0x00000000, phys_lmb_bram);
+
+    memory_region_init_ram(phys_ram, "petalogix_s3adsp1800.ram", ram_size);
+    vmstate_register_ram_global(phys_ram);
+    memory_region_add_subregion(sysmem, ddr_base, phys_ram);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    pflash_cfi01_register(FLASH_BASEADDR,
+                          NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE,
+                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
+                          FLASH_SIZE >> 16,
+                          1, 0x89, 0x18, 0x0000, 0x0, 1);
+
+    cpu_irq = microblaze_pic_init_cpu(env);
+    dev = xilinx_intc_create(INTC_BASEADDR, cpu_irq[0], 2);
+    for (i = 0; i < 32; i++) {
+        irq[i] = qdev_get_gpio_in(dev, i);
+    }
+
+    sysbus_create_simple("xlnx.xps-uartlite", UARTLITE_BASEADDR, irq[3]);
+    /* 2 timers at irq 2 @ 62 Mhz.  */
+    xilinx_timer_create(TIMER_BASEADDR, irq[0], 0, 62 * 1000000);
+    xilinx_ethlite_create(&nd_table[0], ETHLITE_BASEADDR, irq[1], 0, 0);
+
+    microblaze_load_kernel(cpu, ddr_base, ram_size,
+                    BINARY_DEVICE_TREE_FILE, machine_cpu_reset);
+}
+
+static QEMUMachine petalogix_s3adsp1800_machine = {
+    .name = "petalogix-s3adsp1800",
+    .desc = "PetaLogix linux refdesign for xilinx Spartan 3ADSP1800",
+    .init = petalogix_s3adsp1800_init,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void petalogix_s3adsp1800_machine_init(void)
+{
+    qemu_register_machine(&petalogix_s3adsp1800_machine);
+}
+
+machine_init(petalogix_s3adsp1800_machine_init);
diff --git a/hw/microblaze/pic_cpu.c b/hw/microblaze/pic_cpu.c
new file mode 100644
index 0000000..d4743ab
--- /dev/null
+++ b/hw/microblaze/pic_cpu.c
@@ -0,0 +1,44 @@
+/*
+ * QEMU MicroBlaze CPU interrupt wrapper logic.
+ *
+ * Copyright (c) 2009 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * 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/hw.h"
+#include "hw/microblaze_pic_cpu.h"
+
+#define D(x)
+
+static void microblaze_pic_cpu_handler(void *opaque, int irq, int level)
+{
+    CPUMBState *env = (CPUMBState *)opaque;
+    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
+
+    if (level)
+        cpu_interrupt(env, type);
+    else
+        cpu_reset_interrupt(env, type);
+}
+
+qemu_irq *microblaze_pic_init_cpu(CPUMBState *env)
+{
+    return qemu_allocate_irqs(microblaze_pic_cpu_handler, env, 2);
+}
diff --git a/hw/microblaze_boot.c b/hw/microblaze_boot.c
deleted file mode 100644
index e13b3e1..0000000
--- a/hw/microblaze_boot.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Microblaze kernel loader
- *
- * Copyright (c) 2012 Peter Crosthwaite <peter.crosthwaite at petalogix.com>
- * Copyright (c) 2012 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 "qemu/option.h"
-#include "qemu/config-file.h"
-#include "qemu-common.h"
-#include "sysemu/device_tree.h"
-#include "hw/loader.h"
-#include "elf.h"
-
-#include "hw/microblaze_boot.h"
-
-static struct
-{
-    void (*machine_cpu_reset)(MicroBlazeCPU *);
-    uint32_t bootstrap_pc;
-    uint32_t cmdline;
-    uint32_t fdt;
-} boot_info;
-
-static void main_cpu_reset(void *opaque)
-{
-    MicroBlazeCPU *cpu = opaque;
-    CPUMBState *env = &cpu->env;
-
-    cpu_reset(CPU(cpu));
-    env->regs[5] = boot_info.cmdline;
-    env->regs[7] = boot_info.fdt;
-    env->sregs[SR_PC] = boot_info.bootstrap_pc;
-    if (boot_info.machine_cpu_reset) {
-        boot_info.machine_cpu_reset(cpu);
-    }
-}
-
-static int microblaze_load_dtb(hwaddr addr,
-                                      uint32_t ramsize,
-                                      const char *kernel_cmdline,
-                                      const char *dtb_filename)
-{
-    int fdt_size;
-#ifdef CONFIG_FDT
-    void *fdt = NULL;
-    int r;
-
-    if (dtb_filename) {
-        fdt = load_device_tree(dtb_filename, &fdt_size);
-    }
-    if (!fdt) {
-        return 0;
-    }
-
-    if (kernel_cmdline) {
-        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.  */
-    if (dtb_filename) {
-        fdt_size = load_image_targphys(dtb_filename, addr, 0x10000);
-    }
-    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;
-}
-
-void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
-                            uint32_t ramsize, const char *dtb_filename,
-                            void (*machine_cpu_reset)(MicroBlazeCPU *))
-{
-    QemuOpts *machine_opts;
-    const char *kernel_filename = NULL;
-    const char *kernel_cmdline = NULL;
-
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        const char *dtb_arg;
-        kernel_filename = qemu_opt_get(machine_opts, "kernel");
-        kernel_cmdline = qemu_opt_get(machine_opts, "append");
-        dtb_arg = qemu_opt_get(machine_opts, "dtb");
-        if (dtb_arg) { /* Preference a -dtb argument */
-            dtb_filename = dtb_arg;
-        } else { /* default to pcbios dtb as passed by machine_init */
-            dtb_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
-        }
-    }
-
-    boot_info.machine_cpu_reset = machine_cpu_reset;
-    qemu_register_reset(main_cpu_reset, cpu);
-
-    if (kernel_filename) {
-        int kernel_size;
-        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) {
-            hwaddr 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;
-        microblaze_load_dtb(boot_info.fdt, ram_size, kernel_cmdline,
-                                                     dtb_filename);
-    }
-
-}
diff --git a/hw/microblaze_pic_cpu.c b/hw/microblaze_pic_cpu.c
deleted file mode 100644
index d4743ab..0000000
--- a/hw/microblaze_pic_cpu.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * QEMU MicroBlaze CPU interrupt wrapper logic.
- *
- * Copyright (c) 2009 Edgar E. Iglesias, Axis Communications AB.
- *
- * 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/hw.h"
-#include "hw/microblaze_pic_cpu.h"
-
-#define D(x)
-
-static void microblaze_pic_cpu_handler(void *opaque, int irq, int level)
-{
-    CPUMBState *env = (CPUMBState *)opaque;
-    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
-
-    if (level)
-        cpu_interrupt(env, type);
-    else
-        cpu_reset_interrupt(env, type);
-}
-
-qemu_irq *microblaze_pic_init_cpu(CPUMBState *env)
-{
-    return qemu_allocate_irqs(microblaze_pic_cpu_handler, env, 2);
-}
diff --git a/hw/milkymist.c b/hw/milkymist.c
deleted file mode 100644
index fd36de5..0000000
--- a/hw/milkymist.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- *  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 "hw/sysbus.h"
-#include "hw/hw.h"
-#include "hw/flash.h"
-#include "sysemu/sysemu.h"
-#include "hw/devices.h"
-#include "hw/boards.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "sysemu/blockdev.h"
-#include "hw/milkymist-hw.h"
-#include "hw/lm32.h"
-#include "exec/address-spaces.h"
-
-#define BIOS_FILENAME    "mmone-bios.bin"
-#define BIOS_OFFSET      0x00860000
-#define BIOS_SIZE        (512*1024)
-#define KERNEL_LOAD_ADDR 0x40000000
-
-typedef struct {
-    LM32CPU *cpu;
-    hwaddr bootstrap_pc;
-    hwaddr flash_base;
-    hwaddr initrd_base;
-    size_t initrd_size;
-    hwaddr cmdline_base;
-} ResetInfo;
-
-static void cpu_irq_handler(void *opaque, int irq, int level)
-{
-    CPULM32State *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;
-    CPULM32State *env = &reset_info->cpu->env;
-
-    cpu_reset(CPU(reset_info->cpu));
-
-    /* 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(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    LM32CPU *cpu;
-    CPULM32State *env;
-    int kernel_size;
-    DriveInfo *dinfo;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *phys_sdram = g_new(MemoryRegion, 1);
-    qemu_irq irq[32], *cpu_irq;
-    int i;
-    char *bios_filename;
-    ResetInfo *reset_info;
-
-    /* memory map */
-    hwaddr flash_base   = 0x00000000;
-    size_t flash_sector_size        = 128 * 1024;
-    size_t flash_size               = 32 * 1024 * 1024;
-    hwaddr sdram_base   = 0x40000000;
-    size_t sdram_size               = 128 * 1024 * 1024;
-
-    hwaddr initrd_base  = sdram_base + 0x1002000;
-    hwaddr cmdline_base = sdram_base + 0x1000000;
-    size_t initrd_max = sdram_size - 0x1002000;
-
-    reset_info = g_malloc0(sizeof(ResetInfo));
-
-    if (cpu_model == NULL) {
-        cpu_model = "lm32-full";
-    }
-    cpu = cpu_lm32_init(cpu_model);
-    env = &cpu->env;
-    reset_info->cpu = cpu;
-
-    cpu_lm32_set_phys_msb_ignore(env, 1);
-
-    memory_region_init_ram(phys_sdram, "milkymist.sdram", sdram_size);
-    vmstate_register_ram_global(phys_sdram);
-    memory_region_add_subregion(address_space_mem, sdram_base, phys_sdram);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    /* Numonyx JS28F256J3F105 */
-    pflash_cfi01_register(flash_base, NULL, "milkymist.flash", flash_size,
-                          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]);
-    milkymist_sysctl_create(0x60001000, irq[1], irq[2], irq[3],
-            80000000, 0x10014d31, 0x0000041f, 0x00000001);
-    milkymist_hpdmc_create(0x60002000);
-    milkymist_vgafb_create(0x60003000, 0x40000000, 0x0fffffff);
-    milkymist_memcard_create(0x60004000);
-    milkymist_ac97_create(0x60005000, irq[4], irq[5], irq[6], irq[7]);
-    milkymist_pfpu_create(0x60006000, irq[8]);
-    milkymist_tmu2_create(0x60007000, irq[9]);
-    milkymist_minimac2_create(0x60008000, 0x30000000, irq[10], irq[11]);
-    milkymist_softusb_create(0x6000f000, irq[15],
-            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,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void milkymist_machine_init(void)
-{
-    qemu_register_machine(&milkymist_machine);
-}
-
-machine_init(milkymist_machine_init);
diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs
index 29a5d0d..1e3bca1 100644
--- a/hw/mips/Makefile.objs
+++ b/hw/mips/Makefile.objs
@@ -1,6 +1,8 @@
-obj-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
-obj-y += mips_addr.o mips_timer.o mips_int.o
 obj-y += gt64xxx.o mc146818rtc.o
-obj-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o
+obj-$(CONFIG_FULONG) += bonito.o vt82c686.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
+obj-y += addr.o cputimer.o mips_int.o
+obj-$(CONFIG_FULONG) += mips_fulong2e.o
diff --git a/hw/mips/addr.c b/hw/mips/addr.c
new file mode 100644
index 0000000..cddc25c
--- /dev/null
+++ b/hw/mips/addr.c
@@ -0,0 +1,34 @@
+/*
+ * QEMU MIPS address translation support
+ *
+ * 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/hw.h"
+#include "hw/mips_cpudevs.h"
+
+uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr)
+{
+    return addr & 0x7fffffffll;
+}
+
+uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr)
+{
+    return addr | ~0x7fffffffll;
+}
diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c
new file mode 100644
index 0000000..9ad13f3
--- /dev/null
+++ b/hw/mips/cputimer.c
@@ -0,0 +1,147 @@
+/*
+ * QEMU MIPS timer support
+ *
+ * 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/hw.h"
+#include "hw/mips_cpudevs.h"
+#include "qemu/timer.h"
+
+#define TIMER_FREQ	100 * 1000 * 1000
+
+/* XXX: do not use a global */
+uint32_t cpu_mips_get_random (CPUMIPSState *env)
+{
+    static uint32_t lfsr = 1;
+    static uint32_t prev_idx = 0;
+    uint32_t idx;
+    /* Don't return same value twice, so get another value */
+    do {
+        lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u);
+        idx = lfsr % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
+    } while (idx == prev_idx);
+    prev_idx = idx;
+    return idx;
+}
+
+/* MIPS R4K timer */
+static void cpu_mips_timer_update(CPUMIPSState *env)
+{
+    uint64_t now, next;
+    uint32_t wait;
+
+    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);
+    qemu_mod_timer(env->timer, next);
+}
+
+/* Expire the timer.  */
+static void cpu_mips_timer_expire(CPUMIPSState *env)
+{
+    cpu_mips_timer_update(env);
+    if (env->insn_flags & ISA_MIPS32R2) {
+        env->CP0_Cause |= 1 << CP0Ca_TI;
+    }
+    qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
+}
+
+uint32_t cpu_mips_get_count (CPUMIPSState *env)
+{
+    if (env->CP0_Cause & (1 << CP0Ca_DC)) {
+        return env->CP0_Count;
+    } else {
+        uint64_t now;
+
+        now = qemu_get_clock_ns(vm_clock);
+        if (qemu_timer_pending(env->timer)
+            && qemu_timer_expired(env->timer, now)) {
+            /* The timer has already expired.  */
+            cpu_mips_timer_expire(env);
+        }
+
+        return env->CP0_Count +
+            (uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec());
+    }
+}
+
+void cpu_mips_store_count (CPUMIPSState *env, uint32_t count)
+{
+    if (env->CP0_Cause & (1 << CP0Ca_DC))
+        env->CP0_Count = count;
+    else {
+        /* Store new count register */
+        env->CP0_Count =
+            count - (uint32_t)muldiv64(qemu_get_clock_ns(vm_clock),
+                                       TIMER_FREQ, get_ticks_per_sec());
+        /* Update timer timer */
+        cpu_mips_timer_update(env);
+    }
+}
+
+void cpu_mips_store_compare (CPUMIPSState *env, uint32_t value)
+{
+    env->CP0_Compare = value;
+    if (!(env->CP0_Cause & (1 << CP0Ca_DC)))
+        cpu_mips_timer_update(env);
+    if (env->insn_flags & ISA_MIPS32R2)
+        env->CP0_Cause &= ~(1 << CP0Ca_TI);
+    qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
+}
+
+void cpu_mips_start_count(CPUMIPSState *env)
+{
+    cpu_mips_store_count(env, env->CP0_Count);
+}
+
+void cpu_mips_stop_count(CPUMIPSState *env)
+{
+    /* Store the current value */
+    env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock_ns(vm_clock),
+                                         TIMER_FREQ, get_ticks_per_sec());
+}
+
+static void mips_timer_cb (void *opaque)
+{
+    CPUMIPSState *env;
+
+    env = opaque;
+#if 0
+    qemu_log("%s\n", __func__);
+#endif
+
+    if (env->CP0_Cause & (1 << CP0Ca_DC))
+        return;
+
+    /* ??? This callback should occur when the counter is exactly equal to
+       the comparator value.  Offset the count by one to avoid immediately
+       retriggering the callback before any virtual time has passed.  */
+    env->CP0_Count++;
+    cpu_mips_timer_expire(env);
+    env->CP0_Count--;
+}
+
+void cpu_mips_clock_init (CPUMIPSState *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/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c
new file mode 100644
index 0000000..766aa9d
--- /dev/null
+++ b/hw/mips/mips_fulong2e.c
@@ -0,0 +1,411 @@
+/*
+ * QEMU fulong 2e mini pc support
+ *
+ * Copyright (c) 2008 yajin (yajin at vm-kernel.org)
+ * Copyright (c) 2009 chenming (chenming at rdc.faw.com.cn)
+ * Copyright (c) 2010 Huacai Chen (zltjiangshi at gmail.com)
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+/*
+ * Fulong 2e mini pc is based on ICT/ST Loongson 2e CPU (MIPS III like, 800MHz)
+ * http://www.linux-mips.org/wiki/Fulong
+ *
+ * Loongson 2e user manual:
+ * http://www.loongsondeveloper.com/doc/Loongson2EUserGuide.pdf
+ */
+
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/fdc.h"
+#include "net/net.h"
+#include "hw/boards.h"
+#include "hw/smbus.h"
+#include "block/block.h"
+#include "hw/flash.h"
+#include "hw/mips.h"
+#include "hw/mips_cpudevs.h"
+#include "hw/pci/pci.h"
+#include "char/char.h"
+#include "sysemu/sysemu.h"
+#include "audio/audio.h"
+#include "qemu/log.h"
+#include "hw/loader.h"
+#include "hw/mips-bios.h"
+#include "hw/ide.h"
+#include "elf.h"
+#include "hw/vt82c686.h"
+#include "hw/mc146818rtc.h"
+#include "hw/i8254.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+#define DEBUG_FULONG2E_INIT
+
+#define ENVP_ADDR       0x80002000l
+#define ENVP_NB_ENTRIES	 	16
+#define ENVP_ENTRY_SIZE	 	256
+
+#define MAX_IDE_BUS 2
+
+/*
+ * PMON is not part of qemu and released with BSD license, anyone
+ * who want to build a pmon binary please first git-clone the source
+ * from the git repository at:
+ * http://www.loongson.cn/support/git/pmon
+ * Then follow the "Compile Guide" available at:
+ * http://dev.lemote.com/code/pmon
+ *
+ * Notes:
+ * 1, don't use the source at http://dev.lemote.com/http_git/pmon.git
+ * 2, use "Bonito2edev" to replace "dir_corresponding_to_your_target_hardware"
+ * in the "Compile Guide".
+ */
+#define FULONG_BIOSNAME "pmon_fulong2e.bin"
+
+/* PCI SLOT in fulong 2e */
+#define FULONG2E_VIA_SLOT        5
+#define FULONG2E_ATI_SLOT        6
+#define FULONG2E_RTL8139_SLOT    7
+
+static ISADevice *pit;
+
+static struct _loaderparams {
+    int ram_size;
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *initrd_filename;
+} loaderparams;
+
+static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index,
+                                        const char *string, ...)
+{
+    va_list ap;
+    int32_t table_addr;
+
+    if (index >= ENVP_NB_ENTRIES)
+        return;
+
+    if (string == NULL) {
+        prom_buf[index] = 0;
+        return;
+    }
+
+    table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
+    prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
+
+    va_start(ap, string);
+    vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
+    va_end(ap);
+}
+
+static int64_t load_kernel (CPUMIPSState *env)
+{
+    int64_t kernel_entry, kernel_low, kernel_high;
+    int index = 0;
+    long initrd_size;
+    ram_addr_t initrd_offset;
+    uint32_t *prom_buf;
+    long prom_size;
+
+    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
+                 (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
+                 (uint64_t *)&kernel_high, 0, ELF_MACHINE, 1) < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                loaderparams.kernel_filename);
+        exit(1);
+    }
+
+    /* load initrd */
+    initrd_size = 0;
+    initrd_offset = 0;
+    if (loaderparams.initrd_filename) {
+        initrd_size = get_image_size (loaderparams.initrd_filename);
+        if (initrd_size > 0) {
+            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
+            if (initrd_offset + initrd_size > ram_size) {
+                fprintf(stderr,
+                        "qemu: memory too small for initial ram disk '%s'\n",
+                        loaderparams.initrd_filename);
+                exit(1);
+            }
+            initrd_size = load_image_targphys(loaderparams.initrd_filename,
+                                     initrd_offset, ram_size - initrd_offset);
+        }
+        if (initrd_size == (target_ulong) -1) {
+            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                    loaderparams.initrd_filename);
+            exit(1);
+        }
+    }
+
+    /* Setup prom parameters. */
+    prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
+    prom_buf = g_malloc(prom_size);
+
+    prom_set(prom_buf, index++, "%s", loaderparams.kernel_filename);
+    if (initrd_size > 0) {
+        prom_set(prom_buf, index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
+                 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
+                 loaderparams.kernel_cmdline);
+    } else {
+        prom_set(prom_buf, index++, "%s", loaderparams.kernel_cmdline);
+    }
+
+    /* Setup minimum environment variables */
+    prom_set(prom_buf, index++, "busclock=33000000");
+    prom_set(prom_buf, index++, "cpuclock=100000000");
+    prom_set(prom_buf, index++, "memsize=%i", loaderparams.ram_size/1024/1024);
+    prom_set(prom_buf, index++, "modetty0=38400n8r");
+    prom_set(prom_buf, index++, NULL);
+
+    rom_add_blob_fixed("prom", prom_buf, prom_size,
+                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
+
+    return kernel_entry;
+}
+
+static void write_bootloader (CPUMIPSState *env, uint8_t *base, int64_t kernel_addr)
+{
+    uint32_t *p;
+
+    /* Small bootloader */
+    p = (uint32_t *) base;
+
+    stl_raw(p++, 0x0bf00010);                                      /* j 0x1fc00040 */
+    stl_raw(p++, 0x00000000);                                      /* nop */
+
+    /* Second part of the bootloader */
+    p = (uint32_t *) (base + 0x040);
+
+    stl_raw(p++, 0x3c040000);                                      /* lui a0, 0 */
+    stl_raw(p++, 0x34840002);                                      /* ori a0, a0, 2 */
+    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
+    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
+    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
+    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
+    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));      /* lui a3, high(env->ram_size) */
+    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));   /* ori a3, a3, low(env->ram_size) */
+    stl_raw(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff));     /* lui ra, high(kernel_addr) */;
+    stl_raw(p++, 0x37ff0000 | (kernel_addr & 0xffff));             /* ori ra, ra, low(kernel_addr) */
+    stl_raw(p++, 0x03e00008);                                      /* jr ra */
+    stl_raw(p++, 0x00000000);                                      /* nop */
+}
+
+
+static void main_cpu_reset(void *opaque)
+{
+    MIPSCPU *cpu = opaque;
+    CPUMIPSState *env = &cpu->env;
+
+    cpu_reset(CPU(cpu));
+    /* TODO: 2E reset stuff */
+    if (loaderparams.kernel_filename) {
+        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
+    }
+}
+
+uint8_t eeprom_spd[0x80] = {
+    0x80,0x08,0x07,0x0d,0x09,0x02,0x40,0x00,0x04,0x70,
+    0x70,0x00,0x82,0x10,0x00,0x01,0x0e,0x04,0x0c,0x01,
+    0x02,0x20,0x80,0x75,0x70,0x00,0x00,0x50,0x3c,0x50,
+    0x2d,0x20,0xb0,0xb0,0x50,0x50,0x00,0x00,0x00,0x00,
+    0x00,0x41,0x48,0x3c,0x32,0x75,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x9c,0x7b,0x07,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x48,0x42,0x35,0x34,0x41,0x32,
+    0x35,0x36,0x38,0x4b,0x4e,0x2d,0x41,0x37,0x35,0x42,
+    0x20,0x30,0x20
+};
+
+/* Audio support */
+static void audio_init (PCIBus *pci_bus)
+{
+    vt82c686b_ac97_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 5));
+    vt82c686b_mc97_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 6));
+}
+
+/* Network support */
+static void network_init (void)
+{
+    int i;
+
+    for(i = 0; i < nb_nics; i++) {
+        NICInfo *nd = &nd_table[i];
+        const char *default_devaddr = NULL;
+
+        if (i == 0 && (!nd->model || strcmp(nd->model, "rtl8139") == 0)) {
+            /* The fulong board has a RTL8139 card using PCI SLOT 7 */
+            default_devaddr = "07";
+        }
+
+        pci_nic_init_nofail(nd, "rtl8139", default_devaddr);
+    }
+}
+
+static void cpu_request_exit(void *opaque, int irq, int level)
+{
+    CPUMIPSState *env = cpu_single_env;
+
+    if (env && level) {
+        cpu_exit(env);
+    }
+}
+
+static void mips_fulong2e_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    char *filename;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *bios = g_new(MemoryRegion, 1);
+    long bios_size;
+    int64_t kernel_entry;
+    qemu_irq *i8259;
+    qemu_irq *cpu_exit_irq;
+    PCIBus *pci_bus;
+    ISABus *isa_bus;
+    i2c_bus *smbus;
+    int i;
+    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    MIPSCPU *cpu;
+    CPUMIPSState *env;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+        cpu_model = "Loongson-2E";
+    }
+    cpu = cpu_mips_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    qemu_register_reset(main_cpu_reset, cpu);
+
+    /* fulong 2e has 256M ram. */
+    ram_size = 256 * 1024 * 1024;
+
+    /* fulong 2e has a 1M flash.Winbond W39L040AP70Z */
+    bios_size = 1024 * 1024;
+
+    /* allocate RAM */
+    memory_region_init_ram(ram, "fulong2e.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_init_ram(bios, "fulong2e.bios", bios_size);
+    vmstate_register_ram_global(bios);
+    memory_region_set_readonly(bios, true);
+
+    memory_region_add_subregion(address_space_mem, 0, ram);
+    memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
+
+    /* We do not support flash operation, just loading pmon.bin as raw BIOS.
+     * Please use -L to set the BIOS path and -bios to set bios name. */
+
+    if (kernel_filename) {
+        loaderparams.ram_size = ram_size;
+        loaderparams.kernel_filename = kernel_filename;
+        loaderparams.kernel_cmdline = kernel_cmdline;
+        loaderparams.initrd_filename = initrd_filename;
+        kernel_entry = load_kernel (env);
+        write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
+    } else {
+        if (bios_name == NULL) {
+                bios_name = FULONG_BIOSNAME;
+        }
+        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (filename) {
+            bios_size = load_image_targphys(filename, 0x1fc00000LL,
+                                            BIOS_SIZE);
+            g_free(filename);
+        } else {
+            bios_size = -1;
+        }
+
+        if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
+            fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n", bios_name);
+            exit(1);
+        }
+    }
+
+    /* Init internal devices */
+    cpu_mips_irq_init_cpu(env);
+    cpu_mips_clock_init(env);
+
+    /* North bridge, Bonito --> IP2 */
+    pci_bus = bonito_init((qemu_irq *)&(env->irq[2]));
+
+    /* South bridge */
+    ide_drive_get(hd, MAX_IDE_BUS);
+
+    isa_bus = vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 0));
+    if (!isa_bus) {
+        fprintf(stderr, "vt82c686b_init error\n");
+        exit(1);
+    }
+
+    /* Interrupt controller */
+    /* The 8259 -> IP5  */
+    i8259 = i8259_init(isa_bus, env->irq[5]);
+    isa_bus_irqs(isa_bus, i8259);
+
+    vt82c686b_ide_init(pci_bus, hd, PCI_DEVFN(FULONG2E_VIA_SLOT, 1));
+    pci_create_simple(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 2),
+                      "vt82c686b-usb-uhci");
+    pci_create_simple(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 3),
+                      "vt82c686b-usb-uhci");
+
+    smbus = vt82c686b_pm_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 4),
+                              0xeee1, NULL);
+    /* TODO: Populate SPD eeprom data.  */
+    smbus_eeprom_init(smbus, 1, eeprom_spd, sizeof(eeprom_spd));
+
+    /* init other devices */
+    pit = pit_init(isa_bus, 0x40, 0, NULL);
+    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
+    DMA_init(0, cpu_exit_irq);
+
+    /* Super I/O */
+    isa_create_simple(isa_bus, "i8042");
+
+    rtc_init(isa_bus, 2000, NULL);
+
+    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
+        if (serial_hds[i]) {
+            serial_isa_init(isa_bus, i, serial_hds[i]);
+        }
+    }
+
+    if (parallel_hds[0]) {
+        parallel_init(isa_bus, 0, parallel_hds[0]);
+    }
+
+    /* Sound card */
+    audio_init(pci_bus);
+    /* Network card */
+    network_init();
+}
+
+static QEMUMachine mips_fulong2e_machine = {
+    .name = "fulong2e",
+    .desc = "Fulong 2e mini pc",
+    .init = mips_fulong2e_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void mips_fulong2e_machine_init(void)
+{
+    qemu_register_machine(&mips_fulong2e_machine);
+}
+
+machine_init(mips_fulong2e_machine_init);
diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
new file mode 100644
index 0000000..ddd3b1b
--- /dev/null
+++ b/hw/mips/mips_int.c
@@ -0,0 +1,65 @@
+/*
+ * QEMU MIPS interrupt support
+ *
+ * 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/hw.h"
+#include "hw/mips_cpudevs.h"
+#include "cpu.h"
+
+static void cpu_mips_irq_request(void *opaque, int irq, int level)
+{
+    CPUMIPSState *env = (CPUMIPSState *)opaque;
+
+    if (irq < 0 || irq > 7)
+        return;
+
+    if (level) {
+        env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
+    } else {
+        env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
+    }
+
+    if (env->CP0_Cause & CP0Ca_IP_mask) {
+        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+void cpu_mips_irq_init_cpu(CPUMIPSState *env)
+{
+    qemu_irq *qi;
+    int i;
+
+    qi = qemu_allocate_irqs(cpu_mips_irq_request, env, 8);
+    for (i = 0; i < 8; i++) {
+        env->irq[i] = qi[i];
+    }
+}
+
+void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level)
+{
+    if (irq < 0 || irq > 2) {
+        return;
+    }
+
+    qemu_set_irq(env->irq[irq], level);
+}
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
new file mode 100644
index 0000000..daeb985
--- /dev/null
+++ b/hw/mips/mips_jazz.c
@@ -0,0 +1,345 @@
+/*
+ * QEMU MIPS Jazz support
+ *
+ * Copyright (c) 2007-2008 Hervé Poussineau
+ *
+ * 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/hw.h"
+#include "hw/mips.h"
+#include "hw/mips_cpudevs.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/isa.h"
+#include "hw/fdc.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/arch_init.h"
+#include "hw/boards.h"
+#include "net/net.h"
+#include "hw/esp.h"
+#include "hw/mips-bios.h"
+#include "hw/loader.h"
+#include "hw/mc146818rtc.h"
+#include "hw/i8254.h"
+#include "hw/pcspk.h"
+#include "sysemu/blockdev.h"
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+
+enum jazz_model_e
+{
+    JAZZ_MAGNUM,
+    JAZZ_PICA61,
+};
+
+static void main_cpu_reset(void *opaque)
+{
+    MIPSCPU *cpu = opaque;
+
+    cpu_reset(CPU(cpu));
+}
+
+static uint64_t rtc_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return cpu_inw(0x71);
+}
+
+static void rtc_write(void *opaque, hwaddr addr,
+                      uint64_t val, unsigned size)
+{
+    cpu_outw(0x71, val & 0xff);
+}
+
+static const MemoryRegionOps rtc_ops = {
+    .read = rtc_read,
+    .write = rtc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static uint64_t dma_dummy_read(void *opaque, hwaddr addr,
+                               unsigned size)
+{
+    /* Nothing to do. That is only to ensure that
+     * the current DMA acknowledge cycle is completed. */
+    return 0xff;
+}
+
+static void dma_dummy_write(void *opaque, hwaddr addr,
+                            uint64_t val, unsigned size)
+{
+    /* Nothing to do. That is only to ensure that
+     * the current DMA acknowledge cycle is completed. */
+}
+
+static const MemoryRegionOps dma_dummy_ops = {
+    .read = dma_dummy_read,
+    .write = dma_dummy_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+#define MAGNUM_BIOS_SIZE_MAX 0x7e000
+#define MAGNUM_BIOS_SIZE (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX)
+
+static void cpu_request_exit(void *opaque, int irq, int level)
+{
+    CPUMIPSState *env = cpu_single_env;
+
+    if (env && level) {
+        cpu_exit(env);
+    }
+}
+
+static void mips_jazz_init(MemoryRegion *address_space,
+                           MemoryRegion *address_space_io,
+                           ram_addr_t ram_size,
+                           const char *cpu_model,
+                           enum jazz_model_e jazz_model)
+{
+    char *filename;
+    int bios_size, n;
+    MIPSCPU *cpu;
+    CPUMIPSState *env;
+    qemu_irq *rc4030, *i8259;
+    rc4030_dma *dmas;
+    void* rc4030_opaque;
+    MemoryRegion *rtc = g_new(MemoryRegion, 1);
+    MemoryRegion *i8042 = g_new(MemoryRegion, 1);
+    MemoryRegion *dma_dummy = g_new(MemoryRegion, 1);
+    NICInfo *nd;
+    DeviceState *dev;
+    SysBusDevice *sysbus;
+    ISABus *isa_bus;
+    ISADevice *pit;
+    DriveInfo *fds[MAX_FD];
+    qemu_irq esp_reset, dma_enable;
+    qemu_irq *cpu_exit_irq;
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *bios = g_new(MemoryRegion, 1);
+    MemoryRegion *bios2 = g_new(MemoryRegion, 1);
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+#ifdef TARGET_MIPS64
+        cpu_model = "R4000";
+#else
+        /* FIXME: All wrong, this maybe should be R3000 for the older JAZZs. */
+        cpu_model = "24Kf";
+#endif
+    }
+    cpu = cpu_mips_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+    qemu_register_reset(main_cpu_reset, cpu);
+
+    /* allocate RAM */
+    memory_region_init_ram(ram, "mips_jazz.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(address_space, 0, ram);
+
+    memory_region_init_ram(bios, "mips_jazz.bios", MAGNUM_BIOS_SIZE);
+    vmstate_register_ram_global(bios);
+    memory_region_set_readonly(bios, true);
+    memory_region_init_alias(bios2, "mips_jazz.bios", bios,
+                             0, MAGNUM_BIOS_SIZE);
+    memory_region_add_subregion(address_space, 0x1fc00000LL, bios);
+    memory_region_add_subregion(address_space, 0xfff00000LL, bios2);
+
+    /* load the BIOS image. */
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+    if (filename) {
+        bios_size = load_image_targphys(filename, 0xfff00000LL,
+                                        MAGNUM_BIOS_SIZE);
+        g_free(filename);
+    } else {
+        bios_size = -1;
+    }
+    if (bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) {
+        fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n",
+                bios_name);
+        exit(1);
+    }
+
+    /* Init CPU internal devices */
+    cpu_mips_irq_init_cpu(env);
+    cpu_mips_clock_init(env);
+
+    /* Chipset */
+    rc4030_opaque = rc4030_init(env->irq[6], env->irq[3], &rc4030, &dmas,
+                                address_space);
+    memory_region_init_io(dma_dummy, &dma_dummy_ops, NULL, "dummy_dma", 0x1000);
+    memory_region_add_subregion(address_space, 0x8000d000, dma_dummy);
+
+    /* ISA devices */
+    isa_bus = isa_bus_new(NULL, address_space_io);
+    i8259 = i8259_init(isa_bus, env->irq[4]);
+    isa_bus_irqs(isa_bus, i8259);
+    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
+    DMA_init(0, cpu_exit_irq);
+    pit = pit_init(isa_bus, 0x40, 0, NULL);
+    pcspk_init(isa_bus, pit);
+
+    /* ISA IO space at 0x90000000 */
+    isa_mmio_init(0x90000000, 0x01000000);
+    isa_mem_base = 0x11000000;
+
+    /* Video card */
+    switch (jazz_model) {
+    case JAZZ_MAGNUM:
+        dev = qdev_create(NULL, "sysbus-g364");
+        qdev_init_nofail(dev);
+        sysbus = SYS_BUS_DEVICE(dev);
+        sysbus_mmio_map(sysbus, 0, 0x60080000);
+        sysbus_mmio_map(sysbus, 1, 0x40000000);
+        sysbus_connect_irq(sysbus, 0, rc4030[3]);
+        {
+            /* Simple ROM, so user doesn't have to provide one */
+            MemoryRegion *rom_mr = g_new(MemoryRegion, 1);
+            memory_region_init_ram(rom_mr, "g364fb.rom", 0x80000);
+            vmstate_register_ram_global(rom_mr);
+            memory_region_set_readonly(rom_mr, true);
+            uint8_t *rom = memory_region_get_ram_ptr(rom_mr);
+            memory_region_add_subregion(address_space, 0x60000000, rom_mr);
+            rom[0] = 0x10; /* Mips G364 */
+        }
+        break;
+    case JAZZ_PICA61:
+        isa_vga_mm_init(0x40000000, 0x60000000, 0, get_system_memory());
+        break;
+    default:
+        break;
+    }
+
+    /* Network controller */
+    for (n = 0; n < nb_nics; n++) {
+        nd = &nd_table[n];
+        if (!nd->model)
+            nd->model = g_strdup("dp83932");
+        if (strcmp(nd->model, "dp83932") == 0) {
+            dp83932_init(nd, 0x80001000, 2, get_system_memory(), rc4030[4],
+                         rc4030_opaque, rc4030_dma_memory_rw);
+            break;
+        } else if (is_help_option(nd->model)) {
+            fprintf(stderr, "qemu: Supported NICs: dp83932\n");
+            exit(1);
+        } else {
+            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
+            exit(1);
+        }
+    }
+
+    /* SCSI adapter */
+    esp_init(0x80002000, 0,
+             rc4030_dma_read, rc4030_dma_write, dmas[0],
+             rc4030[5], &esp_reset, &dma_enable);
+
+    /* Floppy */
+    if (drive_get_max_bus(IF_FLOPPY) >= MAX_FD) {
+        fprintf(stderr, "qemu: too many floppy drives\n");
+        exit(1);
+    }
+    for (n = 0; n < MAX_FD; n++) {
+        fds[n] = drive_get(IF_FLOPPY, 0, n);
+    }
+    fdctrl_init_sysbus(rc4030[1], 0, 0x80003000, fds);
+
+    /* Real time clock */
+    rtc_init(isa_bus, 1980, NULL);
+    memory_region_init_io(rtc, &rtc_ops, NULL, "rtc", 0x1000);
+    memory_region_add_subregion(address_space, 0x80004000, rtc);
+
+    /* Keyboard (i8042) */
+    i8042_mm_init(rc4030[6], rc4030[7], i8042, 0x1000, 0x1);
+    memory_region_add_subregion(address_space, 0x80005000, i8042);
+
+    /* Serial ports */
+    if (serial_hds[0]) {
+        serial_mm_init(address_space, 0x80006000, 0, rc4030[8], 8000000/16,
+                       serial_hds[0], DEVICE_NATIVE_ENDIAN);
+    }
+    if (serial_hds[1]) {
+        serial_mm_init(address_space, 0x80007000, 0, rc4030[9], 8000000/16,
+                       serial_hds[1], DEVICE_NATIVE_ENDIAN);
+    }
+
+    /* Parallel port */
+    if (parallel_hds[0])
+        parallel_mm_init(address_space, 0x80008000, 0, rc4030[0],
+                         parallel_hds[0]);
+
+    /* Sound card */
+    /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */
+    audio_init(isa_bus, NULL);
+
+    /* NVRAM */
+    dev = qdev_create(NULL, "ds1225y");
+    qdev_init_nofail(dev);
+    sysbus = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(sysbus, 0, 0x80009000);
+
+    /* LED indicator */
+    sysbus_create_simple("jazz-led", 0x8000f000, NULL);
+}
+
+static
+void mips_magnum_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+        mips_jazz_init(get_system_memory(), get_system_io(),
+                       ram_size, cpu_model, JAZZ_MAGNUM);
+}
+
+static
+void mips_pica61_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    mips_jazz_init(get_system_memory(), get_system_io(),
+                   ram_size, cpu_model, JAZZ_PICA61);
+}
+
+static QEMUMachine mips_magnum_machine = {
+    .name = "magnum",
+    .desc = "MIPS Magnum",
+    .init = mips_magnum_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine mips_pica61_machine = {
+    .name = "pica61",
+    .desc = "Acer Pica 61",
+    .init = mips_pica61_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void mips_jazz_machine_init(void)
+{
+    qemu_register_machine(&mips_magnum_machine);
+    qemu_register_machine(&mips_pica61_machine);
+}
+
+machine_init(mips_jazz_machine_init);
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
new file mode 100644
index 0000000..9a67dce
--- /dev/null
+++ b/hw/mips/mips_malta.c
@@ -0,0 +1,1037 @@
+/*
+ * QEMU Malta board support
+ *
+ * Copyright (c) 2006 Aurelien Jarno
+ *
+ * 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/hw.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/fdc.h"
+#include "net/net.h"
+#include "hw/boards.h"
+#include "hw/smbus.h"
+#include "block/block.h"
+#include "hw/flash.h"
+#include "hw/mips.h"
+#include "hw/mips_cpudevs.h"
+#include "hw/pci/pci.h"
+#include "char/char.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/arch_init.h"
+#include "hw/boards.h"
+#include "qemu/log.h"
+#include "hw/mips-bios.h"
+#include "hw/ide.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "hw/mc146818rtc.h"
+#include "hw/i8254.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+#include "hw/sysbus.h"             /* SysBusDevice */
+
+//#define DEBUG_BOARD_INIT
+
+#define ENVP_ADDR		0x80002000l
+#define ENVP_NB_ENTRIES	 	16
+#define ENVP_ENTRY_SIZE	 	256
+
+/* Hardware addresses */
+#define FLASH_ADDRESS 0x1e000000ULL
+#define FPGA_ADDRESS  0x1f000000ULL
+#define RESET_ADDRESS 0x1fc00000ULL
+
+#define FLASH_SIZE    0x400000
+
+#define MAX_IDE_BUS 2
+
+typedef struct {
+    MemoryRegion iomem;
+    MemoryRegion iomem_lo; /* 0 - 0x900 */
+    MemoryRegion iomem_hi; /* 0xa00 - 0x100000 */
+    uint32_t leds;
+    uint32_t brk;
+    uint32_t gpout;
+    uint32_t i2cin;
+    uint32_t i2coe;
+    uint32_t i2cout;
+    uint32_t i2csel;
+    CharDriverState *display;
+    char display_text[9];
+    SerialState *uart;
+} MaltaFPGAState;
+
+typedef struct {
+    SysBusDevice busdev;
+    qemu_irq *i8259;
+} MaltaState;
+
+static ISADevice *pit;
+
+static struct _loaderparams {
+    int ram_size;
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *initrd_filename;
+} loaderparams;
+
+/* Malta FPGA */
+static void malta_fpga_update_display(void *opaque)
+{
+    char leds_text[9];
+    int i;
+    MaltaFPGAState *s = opaque;
+
+    for (i = 7 ; i >= 0 ; i--) {
+        if (s->leds & (1 << i))
+            leds_text[i] = '#';
+        else
+            leds_text[i] = ' ';
+    }
+    leds_text[8] = '\0';
+
+    qemu_chr_fe_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
+    qemu_chr_fe_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
+}
+
+/*
+ * EEPROM 24C01 / 24C02 emulation.
+ *
+ * Emulation for serial EEPROMs:
+ * 24C01 - 1024 bit (128 x 8)
+ * 24C02 - 2048 bit (256 x 8)
+ *
+ * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
+ */
+
+//~ #define DEBUG
+
+#if defined(DEBUG)
+#  define logout(fmt, ...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ## __VA_ARGS__)
+#else
+#  define logout(fmt, ...) ((void)0)
+#endif
+
+struct _eeprom24c0x_t {
+  uint8_t tick;
+  uint8_t address;
+  uint8_t command;
+  uint8_t ack;
+  uint8_t scl;
+  uint8_t sda;
+  uint8_t data;
+  //~ uint16_t size;
+  uint8_t contents[256];
+};
+
+typedef struct _eeprom24c0x_t eeprom24c0x_t;
+
+static eeprom24c0x_t eeprom = {
+    .contents = {
+        /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
+        /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
+        /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
+        /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
+        /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
+        /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
+        /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
+    },
+};
+
+static uint8_t eeprom24c0x_read(void)
+{
+    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
+        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
+    return eeprom.sda;
+}
+
+static void eeprom24c0x_write(int scl, int sda)
+{
+    if (eeprom.scl && scl && (eeprom.sda != sda)) {
+        logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
+                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
+        if (!sda) {
+            eeprom.tick = 1;
+            eeprom.command = 0;
+        }
+    } else if (eeprom.tick == 0 && !eeprom.ack) {
+        /* Waiting for start. */
+        logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
+                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
+    } else if (!eeprom.scl && scl) {
+        logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
+                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
+        if (eeprom.ack) {
+            logout("\ti2c ack bit = 0\n");
+            sda = 0;
+            eeprom.ack = 0;
+        } else if (eeprom.sda == sda) {
+            uint8_t bit = (sda != 0);
+            logout("\ti2c bit = %d\n", bit);
+            if (eeprom.tick < 9) {
+                eeprom.command <<= 1;
+                eeprom.command += bit;
+                eeprom.tick++;
+                if (eeprom.tick == 9) {
+                    logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
+                    eeprom.ack = 1;
+                }
+            } else if (eeprom.tick < 17) {
+                if (eeprom.command & 1) {
+                    sda = ((eeprom.data & 0x80) != 0);
+                }
+                eeprom.address <<= 1;
+                eeprom.address += bit;
+                eeprom.tick++;
+                eeprom.data <<= 1;
+                if (eeprom.tick == 17) {
+                    eeprom.data = eeprom.contents[eeprom.address];
+                    logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
+                    eeprom.ack = 1;
+                    eeprom.tick = 0;
+                }
+            } else if (eeprom.tick >= 17) {
+                sda = 0;
+            }
+        } else {
+            logout("\tsda changed with raising scl\n");
+        }
+    } else {
+        logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
+    }
+    eeprom.scl = scl;
+    eeprom.sda = sda;
+}
+
+static uint64_t malta_fpga_read(void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    MaltaFPGAState *s = opaque;
+    uint32_t val = 0;
+    uint32_t saddr;
+
+    saddr = (addr & 0xfffff);
+
+    switch (saddr) {
+
+    /* SWITCH Register */
+    case 0x00200:
+        val = 0x00000000;		/* All switches closed */
+        break;
+
+    /* STATUS Register */
+    case 0x00208:
+#ifdef TARGET_WORDS_BIGENDIAN
+        val = 0x00000012;
+#else
+        val = 0x00000010;
+#endif
+        break;
+
+    /* JMPRS Register */
+    case 0x00210:
+        val = 0x00;
+        break;
+
+    /* LEDBAR Register */
+    case 0x00408:
+        val = s->leds;
+        break;
+
+    /* BRKRES Register */
+    case 0x00508:
+        val = s->brk;
+        break;
+
+    /* UART Registers are handled directly by the serial device */
+
+    /* GPOUT Register */
+    case 0x00a00:
+        val = s->gpout;
+        break;
+
+    /* XXX: implement a real I2C controller */
+
+    /* GPINP Register */
+    case 0x00a08:
+        /* IN = OUT until a real I2C control is implemented */
+        if (s->i2csel)
+            val = s->i2cout;
+        else
+            val = 0x00;
+        break;
+
+    /* I2CINP Register */
+    case 0x00b00:
+        val = ((s->i2cin & ~1) | eeprom24c0x_read());
+        break;
+
+    /* I2COE Register */
+    case 0x00b08:
+        val = s->i2coe;
+        break;
+
+    /* I2COUT Register */
+    case 0x00b10:
+        val = s->i2cout;
+        break;
+
+    /* I2CSEL Register */
+    case 0x00b18:
+        val = s->i2csel;
+        break;
+
+    default:
+#if 0
+        printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
+                addr);
+#endif
+        break;
+    }
+    return val;
+}
+
+static void malta_fpga_write(void *opaque, hwaddr addr,
+                             uint64_t val, unsigned size)
+{
+    MaltaFPGAState *s = opaque;
+    uint32_t saddr;
+
+    saddr = (addr & 0xfffff);
+
+    switch (saddr) {
+
+    /* SWITCH Register */
+    case 0x00200:
+        break;
+
+    /* JMPRS Register */
+    case 0x00210:
+        break;
+
+    /* LEDBAR Register */
+    case 0x00408:
+        s->leds = val & 0xff;
+        malta_fpga_update_display(s);
+        break;
+
+    /* ASCIIWORD Register */
+    case 0x00410:
+        snprintf(s->display_text, 9, "%08X", (uint32_t)val);
+        malta_fpga_update_display(s);
+        break;
+
+    /* ASCIIPOS0 to ASCIIPOS7 Registers */
+    case 0x00418:
+    case 0x00420:
+    case 0x00428:
+    case 0x00430:
+    case 0x00438:
+    case 0x00440:
+    case 0x00448:
+    case 0x00450:
+        s->display_text[(saddr - 0x00418) >> 3] = (char) val;
+        malta_fpga_update_display(s);
+        break;
+
+    /* SOFTRES Register */
+    case 0x00500:
+        if (val == 0x42)
+            qemu_system_reset_request ();
+        break;
+
+    /* BRKRES Register */
+    case 0x00508:
+        s->brk = val & 0xff;
+        break;
+
+    /* UART Registers are handled directly by the serial device */
+
+    /* GPOUT Register */
+    case 0x00a00:
+        s->gpout = val & 0xff;
+        break;
+
+    /* I2COE Register */
+    case 0x00b08:
+        s->i2coe = val & 0x03;
+        break;
+
+    /* I2COUT Register */
+    case 0x00b10:
+        eeprom24c0x_write(val & 0x02, val & 0x01);
+        s->i2cout = val;
+        break;
+
+    /* I2CSEL Register */
+    case 0x00b18:
+        s->i2csel = val & 0x01;
+        break;
+
+    default:
+#if 0
+        printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
+                addr);
+#endif
+        break;
+    }
+}
+
+static const MemoryRegionOps malta_fpga_ops = {
+    .read = malta_fpga_read,
+    .write = malta_fpga_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void malta_fpga_reset(void *opaque)
+{
+    MaltaFPGAState *s = opaque;
+
+    s->leds   = 0x00;
+    s->brk    = 0x0a;
+    s->gpout  = 0x00;
+    s->i2cin  = 0x3;
+    s->i2coe  = 0x0;
+    s->i2cout = 0x3;
+    s->i2csel = 0x1;
+
+    s->display_text[8] = '\0';
+    snprintf(s->display_text, 9, "        ");
+}
+
+static void malta_fpga_led_init(CharDriverState *chr)
+{
+    qemu_chr_fe_printf(chr, "\e[HMalta LEDBAR\r\n");
+    qemu_chr_fe_printf(chr, "+--------+\r\n");
+    qemu_chr_fe_printf(chr, "+        +\r\n");
+    qemu_chr_fe_printf(chr, "+--------+\r\n");
+    qemu_chr_fe_printf(chr, "\n");
+    qemu_chr_fe_printf(chr, "Malta ASCII\r\n");
+    qemu_chr_fe_printf(chr, "+--------+\r\n");
+    qemu_chr_fe_printf(chr, "+        +\r\n");
+    qemu_chr_fe_printf(chr, "+--------+\r\n");
+}
+
+static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
+         hwaddr base, qemu_irq uart_irq, CharDriverState *uart_chr)
+{
+    MaltaFPGAState *s;
+
+    s = (MaltaFPGAState *)g_malloc0(sizeof(MaltaFPGAState));
+
+    memory_region_init_io(&s->iomem, &malta_fpga_ops, s,
+                          "malta-fpga", 0x100000);
+    memory_region_init_alias(&s->iomem_lo, "malta-fpga",
+                             &s->iomem, 0, 0x900);
+    memory_region_init_alias(&s->iomem_hi, "malta-fpga",
+                             &s->iomem, 0xa00, 0x10000-0xa00);
+
+    memory_region_add_subregion(address_space, base, &s->iomem_lo);
+    memory_region_add_subregion(address_space, base + 0xa00, &s->iomem_hi);
+
+    s->display = qemu_chr_new("fpga", "vc:320x200", malta_fpga_led_init);
+
+    s->uart = serial_mm_init(address_space, base + 0x900, 3, uart_irq,
+                             230400, uart_chr, DEVICE_NATIVE_ENDIAN);
+
+    malta_fpga_reset(s);
+    qemu_register_reset(malta_fpga_reset, s);
+
+    return s;
+}
+
+/* Network support */
+static void network_init(void)
+{
+    int i;
+
+    for(i = 0; i < nb_nics; i++) {
+        NICInfo *nd = &nd_table[i];
+        const char *default_devaddr = NULL;
+
+        if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
+            /* The malta board has a PCNet card using PCI SLOT 11 */
+            default_devaddr = "0b";
+
+        pci_nic_init_nofail(nd, "pcnet", default_devaddr);
+    }
+}
+
+/* ROM and pseudo bootloader
+
+   The following code implements a very very simple bootloader. It first
+   loads the registers a0 to a3 to the values expected by the OS, and
+   then jump at the kernel address.
+
+   The bootloader should pass the locations of the kernel arguments and
+   environment variables tables. Those tables contain the 32-bit address
+   of NULL terminated strings. The environment variables table should be
+   terminated by a NULL address.
+
+   For a simpler implementation, the number of kernel arguments is fixed
+   to two (the name of the kernel and the command line), and the two
+   tables are actually the same one.
+
+   The registers a0 to a3 should contain the following values:
+     a0 - number of kernel arguments
+     a1 - 32-bit address of the kernel arguments table
+     a2 - 32-bit address of the environment variables table
+     a3 - RAM size in bytes
+*/
+
+static void write_bootloader (CPUMIPSState *env, uint8_t *base,
+                              int64_t kernel_entry)
+{
+    uint32_t *p;
+
+    /* Small bootloader */
+    p = (uint32_t *)base;
+    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
+    stl_raw(p++, 0x00000000);                                      /* nop */
+
+    /* YAMON service vector */
+    stl_raw(base + 0x500, 0xbfc00580);      /* start: */
+    stl_raw(base + 0x504, 0xbfc0083c);      /* print_count: */
+    stl_raw(base + 0x520, 0xbfc00580);      /* start: */
+    stl_raw(base + 0x52c, 0xbfc00800);      /* flush_cache: */
+    stl_raw(base + 0x534, 0xbfc00808);      /* print: */
+    stl_raw(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
+    stl_raw(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
+    stl_raw(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
+    stl_raw(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
+    stl_raw(base + 0x548, 0xbfc00800);      /* reg_esr: */
+    stl_raw(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
+    stl_raw(base + 0x550, 0xbfc00800);      /* getchar: */
+    stl_raw(base + 0x554, 0xbfc00800);      /* syscon_read: */
+
+
+    /* Second part of the bootloader */
+    p = (uint32_t *) (base + 0x580);
+    stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
+    stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
+    stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
+    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
+    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
+    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
+    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
+    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
+    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
+
+    /* Load BAR registers as done by YAMON */
+    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
+#else
+    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
+#endif
+    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
+
+    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
+#else
+    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
+#endif
+    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
+#else
+    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
+#endif
+    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
+#else
+    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
+#endif
+    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
+#else
+    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
+#endif
+    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
+#else
+    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
+#endif
+    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
+#else
+    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
+#endif
+    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
+
+    /* Jump to kernel code */
+    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
+    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
+    stl_raw(p++, 0x03e00008);                                      /* jr ra */
+    stl_raw(p++, 0x00000000);                                      /* nop */
+
+    /* YAMON subroutines */
+    p = (uint32_t *) (base + 0x800);
+    stl_raw(p++, 0x03e00008);                                     /* jr ra */
+    stl_raw(p++, 0x24020000);                                     /* li v0,0 */
+   /* 808 YAMON print */
+    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
+    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
+    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
+    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
+    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
+    stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x08000205);                                     /* j 814 */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
+    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
+    /* 0x83c YAMON print_count */
+    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
+    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
+    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
+    stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
+    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
+    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
+    stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
+    stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
+    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
+    /* 0x870 */
+    stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
+    stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
+    stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
+    stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x03e00008);                                     /* jr ra */
+    stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
+
+}
+
+static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index,
+                                        const char *string, ...)
+{
+    va_list ap;
+    int32_t table_addr;
+
+    if (index >= ENVP_NB_ENTRIES)
+        return;
+
+    if (string == NULL) {
+        prom_buf[index] = 0;
+        return;
+    }
+
+    table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
+    prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
+
+    va_start(ap, string);
+    vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
+    va_end(ap);
+}
+
+/* Kernel */
+static int64_t load_kernel (void)
+{
+    int64_t kernel_entry, kernel_high;
+    long initrd_size;
+    ram_addr_t initrd_offset;
+    int big_endian;
+    uint32_t *prom_buf;
+    long prom_size;
+    int prom_index = 0;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    big_endian = 1;
+#else
+    big_endian = 0;
+#endif
+
+    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
+                 (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
+                 big_endian, ELF_MACHINE, 1) < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                loaderparams.kernel_filename);
+        exit(1);
+    }
+
+    /* load initrd */
+    initrd_size = 0;
+    initrd_offset = 0;
+    if (loaderparams.initrd_filename) {
+        initrd_size = get_image_size (loaderparams.initrd_filename);
+        if (initrd_size > 0) {
+            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
+            if (initrd_offset + initrd_size > ram_size) {
+                fprintf(stderr,
+                        "qemu: memory too small for initial ram disk '%s'\n",
+                        loaderparams.initrd_filename);
+                exit(1);
+            }
+            initrd_size = load_image_targphys(loaderparams.initrd_filename,
+                                              initrd_offset,
+                                              ram_size - initrd_offset);
+        }
+        if (initrd_size == (target_ulong) -1) {
+            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                    loaderparams.initrd_filename);
+            exit(1);
+        }
+    }
+
+    /* Setup prom parameters. */
+    prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
+    prom_buf = g_malloc(prom_size);
+
+    prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_filename);
+    if (initrd_size > 0) {
+        prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
+                 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
+                 loaderparams.kernel_cmdline);
+    } else {
+        prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_cmdline);
+    }
+
+    prom_set(prom_buf, prom_index++, "memsize");
+    prom_set(prom_buf, prom_index++, "%i", loaderparams.ram_size);
+    prom_set(prom_buf, prom_index++, "modetty0");
+    prom_set(prom_buf, prom_index++, "38400n8r");
+    prom_set(prom_buf, prom_index++, NULL);
+
+    rom_add_blob_fixed("prom", prom_buf, prom_size,
+                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
+
+    return kernel_entry;
+}
+
+static void malta_mips_config(MIPSCPU *cpu)
+{
+    CPUMIPSState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
+
+    env->mvp->CP0_MVPConf0 |= ((smp_cpus - 1) << CP0MVPC0_PVPE) |
+                         ((smp_cpus * cs->nr_threads - 1) << CP0MVPC0_PTC);
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    MIPSCPU *cpu = opaque;
+    CPUMIPSState *env = &cpu->env;
+
+    cpu_reset(CPU(cpu));
+
+    /* The bootloader does not need to be rewritten as it is located in a
+       read only location. The kernel location and the arguments table
+       location does not change. */
+    if (loaderparams.kernel_filename) {
+        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
+    }
+
+    malta_mips_config(cpu);
+}
+
+static void cpu_request_exit(void *opaque, int irq, int level)
+{
+    CPUMIPSState *env = cpu_single_env;
+
+    if (env && level) {
+        cpu_exit(env);
+    }
+}
+
+static
+void mips_malta_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    char *filename;
+    pflash_t *fl;
+    MemoryRegion *system_memory = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1);
+    target_long bios_size = FLASH_SIZE;
+    int64_t kernel_entry;
+    PCIBus *pci_bus;
+    ISABus *isa_bus;
+    MIPSCPU *cpu;
+    CPUMIPSState *env;
+    qemu_irq *isa_irq;
+    qemu_irq *cpu_exit_irq;
+    int piix4_devfn;
+    i2c_bus *smbus;
+    int i;
+    DriveInfo *dinfo;
+    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    DriveInfo *fd[MAX_FD];
+    int fl_idx = 0;
+    int fl_sectors = bios_size >> 16;
+    int be;
+
+    DeviceState *dev = qdev_create(NULL, "mips-malta");
+    MaltaState *s = DO_UPCAST(MaltaState, busdev.qdev, dev);
+
+    qdev_init_nofail(dev);
+
+    /* Make sure the first 3 serial ports are associated with a device. */
+    for(i = 0; i < 3; i++) {
+        if (!serial_hds[i]) {
+            char label[32];
+            snprintf(label, sizeof(label), "serial%d", i);
+            serial_hds[i] = qemu_chr_new(label, "null", NULL);
+        }
+    }
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+#ifdef TARGET_MIPS64
+        cpu_model = "20Kc";
+#else
+        cpu_model = "24Kf";
+#endif
+    }
+
+    for (i = 0; i < smp_cpus; i++) {
+        cpu = cpu_mips_init(cpu_model);
+        if (cpu == NULL) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        env = &cpu->env;
+
+        /* Init internal devices */
+        cpu_mips_irq_init_cpu(env);
+        cpu_mips_clock_init(env);
+        qemu_register_reset(main_cpu_reset, cpu);
+    }
+    env = first_cpu;
+
+    /* allocate RAM */
+    if (ram_size > (256 << 20)) {
+        fprintf(stderr,
+                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
+                ((unsigned int)ram_size / (1 << 20)));
+        exit(1);
+    }
+    memory_region_init_ram(ram, "mips_malta.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(system_memory, 0, ram);
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    be = 1;
+#else
+    be = 0;
+#endif
+    /* FPGA */
+    /* The CBUS UART is attached to the MIPS CPU INT2 pin, ie interrupt 4 */
+    malta_fpga_init(system_memory, FPGA_ADDRESS, env->irq[4], serial_hds[2]);
+
+    /* Load firmware in flash / BIOS. */
+    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
+#ifdef DEBUG_BOARD_INIT
+    if (dinfo) {
+        printf("Register parallel flash %d size " TARGET_FMT_lx " at "
+               "addr %08llx '%s' %x\n",
+               fl_idx, bios_size, FLASH_ADDRESS,
+               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
+    }
+#endif
+    fl = pflash_cfi01_register(FLASH_ADDRESS, NULL, "mips_malta.bios",
+                               BIOS_SIZE, dinfo ? dinfo->bdrv : NULL,
+                               65536, fl_sectors,
+                               4, 0x0000, 0x0000, 0x0000, 0x0000, be);
+    bios = pflash_cfi01_get_memory(fl);
+    fl_idx++;
+    if (kernel_filename) {
+        /* Write a small bootloader to the flash location. */
+        loaderparams.ram_size = ram_size;
+        loaderparams.kernel_filename = kernel_filename;
+        loaderparams.kernel_cmdline = kernel_cmdline;
+        loaderparams.initrd_filename = initrd_filename;
+        kernel_entry = load_kernel();
+        write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
+    } else {
+        /* Load firmware from flash. */
+        if (!dinfo) {
+            /* Load a BIOS image. */
+            if (bios_name == NULL) {
+                bios_name = BIOS_FILENAME;
+            }
+            filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+            if (filename) {
+                bios_size = load_image_targphys(filename, FLASH_ADDRESS,
+                                                BIOS_SIZE);
+                g_free(filename);
+            } else {
+                bios_size = -1;
+            }
+            if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
+                fprintf(stderr,
+                        "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
+                        bios_name);
+                exit(1);
+            }
+        }
+        /* In little endian mode the 32bit words in the bios are swapped,
+           a neat trick which allows bi-endian firmware. */
+#ifndef TARGET_WORDS_BIGENDIAN
+        {
+            uint32_t *addr = memory_region_get_ram_ptr(bios);
+            uint32_t *end = addr + bios_size;
+            while (addr < end) {
+                bswap32s(addr);
+                addr++;
+            }
+        }
+#endif
+    }
+
+    /* Map the BIOS at a 2nd physical location, as on the real board. */
+    memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
+    memory_region_add_subregion(system_memory, RESET_ADDRESS, bios_alias);
+
+    /* Board ID = 0x420 (Malta Board with CoreLV)
+       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
+       map to the board ID. */
+    stl_p(memory_region_get_ram_ptr(bios) + 0x10, 0x00000420);
+
+    /* Init internal devices */
+    cpu_mips_irq_init_cpu(env);
+    cpu_mips_clock_init(env);
+
+    /*
+     * We have a circular dependency problem: pci_bus depends on isa_irq,
+     * isa_irq is provided by i8259, i8259 depends on ISA, ISA depends
+     * on piix4, and piix4 depends on pci_bus.  To stop the cycle we have
+     * qemu_irq_proxy() adds an extra bit of indirection, allowing us
+     * to resolve the isa_irq -> i8259 dependency after i8259 is initialized.
+     */
+    isa_irq = qemu_irq_proxy(&s->i8259, 16);
+
+    /* Northbridge */
+    pci_bus = gt64120_register(isa_irq);
+
+    /* Southbridge */
+    ide_drive_get(hd, MAX_IDE_BUS);
+
+    piix4_devfn = piix4_init(pci_bus, &isa_bus, 80);
+
+    /* Interrupt controller */
+    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
+    s->i8259 = i8259_init(isa_bus, env->irq[2]);
+
+    isa_bus_irqs(isa_bus, s->i8259);
+    pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
+    pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci");
+    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
+                          isa_get_irq(NULL, 9), NULL, 0, NULL);
+    /* TODO: Populate SPD eeprom data.  */
+    smbus_eeprom_init(smbus, 8, NULL, 0);
+    pit = pit_init(isa_bus, 0x40, 0, NULL);
+    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
+    DMA_init(0, cpu_exit_irq);
+
+    /* Super I/O */
+    isa_create_simple(isa_bus, "i8042");
+
+    rtc_init(isa_bus, 2000, NULL);
+    serial_isa_init(isa_bus, 0, serial_hds[0]);
+    serial_isa_init(isa_bus, 1, serial_hds[1]);
+    if (parallel_hds[0])
+        parallel_init(isa_bus, 0, parallel_hds[0]);
+    for(i = 0; i < MAX_FD; i++) {
+        fd[i] = drive_get(IF_FLOPPY, 0, i);
+    }
+    fdctrl_init_isa(isa_bus, fd);
+
+    /* Sound card */
+    audio_init(isa_bus, pci_bus);
+
+    /* Network card */
+    network_init();
+
+    /* Optional PCI video card */
+    pci_vga_init(pci_bus);
+}
+
+static int mips_malta_sysbus_device_init(SysBusDevice *sysbusdev)
+{
+    return 0;
+}
+
+static void mips_malta_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = mips_malta_sysbus_device_init;
+}
+
+static const TypeInfo mips_malta_device = {
+    .name          = "mips-malta",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(MaltaState),
+    .class_init    = mips_malta_class_init,
+};
+
+static QEMUMachine mips_malta_machine = {
+    .name = "malta",
+    .desc = "MIPS Malta Core LV",
+    .init = mips_malta_init,
+    .max_cpus = 16,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void mips_malta_register_types(void)
+{
+    type_register_static(&mips_malta_device);
+}
+
+static void mips_malta_machine_init(void)
+{
+    qemu_register_machine(&mips_malta_machine);
+}
+
+type_init(mips_malta_register_types)
+machine_init(mips_malta_machine_init);
diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c
new file mode 100644
index 0000000..4935c78
--- /dev/null
+++ b/hw/mips/mips_mipssim.c
@@ -0,0 +1,240 @@
+/*
+ * QEMU/mipssim emulation
+ *
+ * Emulates a very simple machine model similar to the one used by the
+ * proprietary MIPS emulator.
+ * 
+ * Copyright (c) 2007 Thiemo Seufer
+ *
+ * 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/hw.h"
+#include "hw/mips.h"
+#include "hw/mips_cpudevs.h"
+#include "hw/serial.h"
+#include "hw/isa.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/mips-bios.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+
+static struct _loaderparams {
+    int ram_size;
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *initrd_filename;
+} loaderparams;
+
+typedef struct ResetData {
+    MIPSCPU *cpu;
+    uint64_t vector;
+} ResetData;
+
+static int64_t load_kernel(void)
+{
+    int64_t entry, kernel_high;
+    long kernel_size;
+    long initrd_size;
+    ram_addr_t initrd_offset;
+    int big_endian;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    big_endian = 1;
+#else
+    big_endian = 0;
+#endif
+
+    kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
+                           NULL, (uint64_t *)&entry, NULL,
+                           (uint64_t *)&kernel_high, big_endian,
+                           ELF_MACHINE, 1);
+    if (kernel_size >= 0) {
+        if ((entry & ~0x7fffffffULL) == 0x80000000)
+            entry = (int32_t)entry;
+    } else {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                loaderparams.kernel_filename);
+        exit(1);
+    }
+
+    /* load initrd */
+    initrd_size = 0;
+    initrd_offset = 0;
+    if (loaderparams.initrd_filename) {
+        initrd_size = get_image_size (loaderparams.initrd_filename);
+        if (initrd_size > 0) {
+            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
+            if (initrd_offset + initrd_size > loaderparams.ram_size) {
+                fprintf(stderr,
+                        "qemu: memory too small for initial ram disk '%s'\n",
+                        loaderparams.initrd_filename);
+                exit(1);
+            }
+            initrd_size = load_image_targphys(loaderparams.initrd_filename,
+                initrd_offset, loaderparams.ram_size - initrd_offset);
+        }
+        if (initrd_size == (target_ulong) -1) {
+            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                    loaderparams.initrd_filename);
+            exit(1);
+        }
+    }
+    return entry;
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    ResetData *s = (ResetData *)opaque;
+    CPUMIPSState *env = &s->cpu->env;
+
+    cpu_reset(CPU(s->cpu));
+    env->active_tc.PC = s->vector & ~(target_ulong)1;
+    if (s->vector & 1) {
+        env->hflags |= MIPS_HFLAG_M16;
+    }
+}
+
+static void mipsnet_init(int base, qemu_irq irq, NICInfo *nd)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "mipsnet");
+    qdev_set_nic_properties(dev, nd);
+    qdev_init_nofail(dev);
+
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(s, 0, irq);
+    memory_region_add_subregion(get_system_io(),
+                                base,
+                                sysbus_mmio_get_region(s, 0));
+}
+
+static void
+mips_mipssim_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    char *filename;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *bios = g_new(MemoryRegion, 1);
+    MIPSCPU *cpu;
+    CPUMIPSState *env;
+    ResetData *reset_info;
+    int bios_size;
+
+    /* Init CPUs. */
+    if (cpu_model == NULL) {
+#ifdef TARGET_MIPS64
+        cpu_model = "5Kf";
+#else
+        cpu_model = "24Kf";
+#endif
+    }
+    cpu = cpu_mips_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    reset_info = g_malloc0(sizeof(ResetData));
+    reset_info->cpu = cpu;
+    reset_info->vector = env->active_tc.PC;
+    qemu_register_reset(main_cpu_reset, reset_info);
+
+    /* Allocate RAM. */
+    memory_region_init_ram(ram, "mips_mipssim.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_init_ram(bios, "mips_mipssim.bios", BIOS_SIZE);
+    vmstate_register_ram_global(bios);
+    memory_region_set_readonly(bios, true);
+
+    memory_region_add_subregion(address_space_mem, 0, ram);
+
+    /* Map the BIOS / boot exception handler. */
+    memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
+    /* Load a BIOS / boot exception handler image. */
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+    if (filename) {
+        bios_size = load_image_targphys(filename, 0x1fc00000LL, BIOS_SIZE);
+        g_free(filename);
+    } else {
+        bios_size = -1;
+    }
+    if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
+        /* Bail out if we have neither a kernel image nor boot vector code. */
+        fprintf(stderr,
+                "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
+                filename);
+        exit(1);
+    } else {
+        /* We have a boot vector start address. */
+        env->active_tc.PC = (target_long)(int32_t)0xbfc00000;
+    }
+
+    if (kernel_filename) {
+        loaderparams.ram_size = ram_size;
+        loaderparams.kernel_filename = kernel_filename;
+        loaderparams.kernel_cmdline = kernel_cmdline;
+        loaderparams.initrd_filename = initrd_filename;
+        reset_info->vector = load_kernel();
+    }
+
+    /* Init CPU internal devices. */
+    cpu_mips_irq_init_cpu(env);
+    cpu_mips_clock_init(env);
+
+    /* Register 64 KB of ISA IO space at 0x1fd00000. */
+    isa_mmio_init(0x1fd00000, 0x00010000);
+
+    /* A single 16450 sits at offset 0x3f8. It is attached to
+       MIPS CPU INT2, which is interrupt 4. */
+    if (serial_hds[0])
+        serial_init(0x3f8, env->irq[4], 115200, serial_hds[0],
+                    get_system_io());
+
+    if (nd_table[0].used)
+        /* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */
+        mipsnet_init(0x4200, env->irq[2], &nd_table[0]);
+}
+
+static QEMUMachine mips_mipssim_machine = {
+    .name = "mipssim",
+    .desc = "MIPS MIPSsim platform",
+    .init = mips_mipssim_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void mips_mipssim_machine_init(void)
+{
+    qemu_register_machine(&mips_mipssim_machine);
+}
+
+machine_init(mips_mipssim_machine_init);
diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c
new file mode 100644
index 0000000..539a562
--- /dev/null
+++ b/hw/mips/mips_r4k.c
@@ -0,0 +1,313 @@
+/*
+ * QEMU/MIPS pseudo-board
+ *
+ * emulates a simple machine with ISA-like bus.
+ * ISA IO space mapped to the 0x14000000 (PHYS) and
+ * ISA memory at the 0x10000000 (PHYS, 16Mb in size).
+ * All peripherial devices are attached to this "bus" with
+ * the standard PC ISA addresses.
+*/
+#include "hw/hw.h"
+#include "hw/mips.h"
+#include "hw/mips_cpudevs.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/isa.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/flash.h"
+#include "qemu/log.h"
+#include "hw/mips-bios.h"
+#include "hw/ide.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "hw/mc146818rtc.h"
+#include "hw/i8254.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+#define MAX_IDE_BUS 2
+
+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 ISADevice *pit; /* PIT i8254 */
+
+/* i8254 PIT is attached to the IRQ0 at PIC i8259 */
+
+static struct _loaderparams {
+    int ram_size;
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *initrd_filename;
+} loaderparams;
+
+static void mips_qemu_write (void *opaque, hwaddr addr,
+                             uint64_t val, unsigned size)
+{
+    if ((addr & 0xffff) == 0 && val == 42)
+        qemu_system_reset_request ();
+    else if ((addr & 0xffff) == 4 && val == 42)
+        qemu_system_shutdown_request ();
+}
+
+static uint64_t mips_qemu_read (void *opaque, hwaddr addr,
+                                unsigned size)
+{
+    return 0;
+}
+
+static const MemoryRegionOps mips_qemu_ops = {
+    .read = mips_qemu_read,
+    .write = mips_qemu_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+typedef struct ResetData {
+    MIPSCPU *cpu;
+    uint64_t vector;
+} ResetData;
+
+static int64_t load_kernel(void)
+{
+    int64_t entry, kernel_high;
+    long kernel_size, initrd_size, params_size;
+    ram_addr_t initrd_offset;
+    uint32_t *params_buf;
+    int big_endian;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    big_endian = 1;
+#else
+    big_endian = 0;
+#endif
+    kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
+                           NULL, (uint64_t *)&entry, NULL,
+                           (uint64_t *)&kernel_high, big_endian,
+                           ELF_MACHINE, 1);
+    if (kernel_size >= 0) {
+        if ((entry & ~0x7fffffffULL) == 0x80000000)
+            entry = (int32_t)entry;
+    } else {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                loaderparams.kernel_filename);
+        exit(1);
+    }
+
+    /* load initrd */
+    initrd_size = 0;
+    initrd_offset = 0;
+    if (loaderparams.initrd_filename) {
+        initrd_size = get_image_size (loaderparams.initrd_filename);
+        if (initrd_size > 0) {
+            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
+            if (initrd_offset + initrd_size > ram_size) {
+                fprintf(stderr,
+                        "qemu: memory too small for initial ram disk '%s'\n",
+                        loaderparams.initrd_filename);
+                exit(1);
+            }
+            initrd_size = load_image_targphys(loaderparams.initrd_filename,
+                                              initrd_offset,
+                                              ram_size - initrd_offset);
+        }
+        if (initrd_size == (target_ulong) -1) {
+            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                    loaderparams.initrd_filename);
+            exit(1);
+        }
+    }
+
+    /* Store command line.  */
+    params_size = 264;
+    params_buf = g_malloc(params_size);
+
+    params_buf[0] = tswap32(ram_size);
+    params_buf[1] = tswap32(0x12345678);
+
+    if (initrd_size > 0) {
+        snprintf((char *)params_buf + 8, 256, "rd_start=0x%" PRIx64 " rd_size=%li %s",
+                 cpu_mips_phys_to_kseg0(NULL, initrd_offset),
+                 initrd_size, loaderparams.kernel_cmdline);
+    } else {
+        snprintf((char *)params_buf + 8, 256, "%s", loaderparams.kernel_cmdline);
+    }
+
+    rom_add_blob_fixed("params", params_buf, params_size,
+                       (16 << 20) - 264);
+
+    return entry;
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    ResetData *s = (ResetData *)opaque;
+    CPUMIPSState *env = &s->cpu->env;
+
+    cpu_reset(CPU(s->cpu));
+    env->active_tc.PC = s->vector;
+}
+
+static const int sector_len = 32 * 1024;
+static
+void mips_r4k_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    char *filename;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *bios;
+    MemoryRegion *iomem = g_new(MemoryRegion, 1);
+    int bios_size;
+    MIPSCPU *cpu;
+    CPUMIPSState *env;
+    ResetData *reset_info;
+    int i;
+    qemu_irq *i8259;
+    ISABus *isa_bus;
+    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    DriveInfo *dinfo;
+    int be;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+#ifdef TARGET_MIPS64
+        cpu_model = "R4000";
+#else
+        cpu_model = "24Kf";
+#endif
+    }
+    cpu = cpu_mips_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    reset_info = g_malloc0(sizeof(ResetData));
+    reset_info->cpu = cpu;
+    reset_info->vector = env->active_tc.PC;
+    qemu_register_reset(main_cpu_reset, reset_info);
+
+    /* allocate RAM */
+    if (ram_size > (256 << 20)) {
+        fprintf(stderr,
+                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
+                ((unsigned int)ram_size / (1 << 20)));
+        exit(1);
+    }
+    memory_region_init_ram(ram, "mips_r4k.ram", ram_size);
+    vmstate_register_ram_global(ram);
+
+    memory_region_add_subregion(address_space_mem, 0, ram);
+
+    memory_region_init_io(iomem, &mips_qemu_ops, NULL, "mips-qemu", 0x10000);
+    memory_region_add_subregion(address_space_mem, 0x1fbf0000, iomem);
+
+    /* Try to load a BIOS image. If this fails, we continue regardless,
+       but initialize the hardware ourselves. When a kernel gets
+       preloaded we also initialize the hardware, since the BIOS wasn't
+       run. */
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+    if (filename) {
+        bios_size = get_image_size(filename);
+    } else {
+        bios_size = -1;
+    }
+#ifdef TARGET_WORDS_BIGENDIAN
+    be = 1;
+#else
+    be = 0;
+#endif
+    if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
+        bios = g_new(MemoryRegion, 1);
+        memory_region_init_ram(bios, "mips_r4k.bios", BIOS_SIZE);
+        vmstate_register_ram_global(bios);
+        memory_region_set_readonly(bios, true);
+        memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios);
+
+        load_image_targphys(filename, 0x1fc00000, BIOS_SIZE);
+    } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
+        uint32_t mips_rom = 0x00400000;
+        if (!pflash_cfi01_register(0x1fc00000, NULL, "mips_r4k.bios", mips_rom,
+                                   dinfo->bdrv, sector_len,
+                                   mips_rom / sector_len,
+                                   4, 0, 0, 0, 0, be)) {
+            fprintf(stderr, "qemu: Error registering flash memory.\n");
+	}
+    }
+    else {
+	/* not fatal */
+        fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
+		bios_name);
+    }
+    if (filename) {
+        g_free(filename);
+    }
+
+    if (kernel_filename) {
+        loaderparams.ram_size = ram_size;
+        loaderparams.kernel_filename = kernel_filename;
+        loaderparams.kernel_cmdline = kernel_cmdline;
+        loaderparams.initrd_filename = initrd_filename;
+        reset_info->vector = load_kernel();
+    }
+
+    /* Init CPU internal devices */
+    cpu_mips_irq_init_cpu(env);
+    cpu_mips_clock_init(env);
+
+    /* The PIC is attached to the MIPS CPU INT0 pin */
+    isa_bus = isa_bus_new(NULL, get_system_io());
+    i8259 = i8259_init(isa_bus, env->irq[2]);
+    isa_bus_irqs(isa_bus, i8259);
+
+    rtc_init(isa_bus, 2000, NULL);
+
+    /* Register 64 KB of ISA IO space at 0x14000000 */
+    isa_mmio_init(0x14000000, 0x00010000);
+    isa_mem_base = 0x10000000;
+
+    pit = pit_init(isa_bus, 0x40, 0, NULL);
+
+    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
+        if (serial_hds[i]) {
+            serial_isa_init(isa_bus, i, serial_hds[i]);
+        }
+    }
+
+    isa_vga_init(isa_bus);
+
+    if (nd_table[0].used)
+        isa_ne2000_init(isa_bus, 0x300, 9, &nd_table[0]);
+
+    ide_drive_get(hd, MAX_IDE_BUS);
+    for(i = 0; i < MAX_IDE_BUS; i++)
+        isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i],
+                     hd[MAX_IDE_DEVS * i],
+		     hd[MAX_IDE_DEVS * i + 1]);
+
+    isa_create_simple(isa_bus, "i8042");
+}
+
+static QEMUMachine mips_machine = {
+    .name = "mips",
+    .desc = "mips r4k platform",
+    .init = mips_r4k_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void mips_machine_init(void)
+{
+    qemu_register_machine(&mips_machine);
+}
+
+machine_init(mips_machine_init);
diff --git a/hw/mips_addr.c b/hw/mips_addr.c
deleted file mode 100644
index cddc25c..0000000
--- a/hw/mips_addr.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * QEMU MIPS address translation support
- *
- * 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/hw.h"
-#include "hw/mips_cpudevs.h"
-
-uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr)
-{
-    return addr & 0x7fffffffll;
-}
-
-uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr)
-{
-    return addr | ~0x7fffffffll;
-}
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
deleted file mode 100644
index 766aa9d..0000000
--- a/hw/mips_fulong2e.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * QEMU fulong 2e mini pc support
- *
- * Copyright (c) 2008 yajin (yajin at vm-kernel.org)
- * Copyright (c) 2009 chenming (chenming at rdc.faw.com.cn)
- * Copyright (c) 2010 Huacai Chen (zltjiangshi at gmail.com)
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-/*
- * Fulong 2e mini pc is based on ICT/ST Loongson 2e CPU (MIPS III like, 800MHz)
- * http://www.linux-mips.org/wiki/Fulong
- *
- * Loongson 2e user manual:
- * http://www.loongsondeveloper.com/doc/Loongson2EUserGuide.pdf
- */
-
-#include "hw/hw.h"
-#include "hw/pc.h"
-#include "hw/serial.h"
-#include "hw/fdc.h"
-#include "net/net.h"
-#include "hw/boards.h"
-#include "hw/smbus.h"
-#include "block/block.h"
-#include "hw/flash.h"
-#include "hw/mips.h"
-#include "hw/mips_cpudevs.h"
-#include "hw/pci/pci.h"
-#include "char/char.h"
-#include "sysemu/sysemu.h"
-#include "audio/audio.h"
-#include "qemu/log.h"
-#include "hw/loader.h"
-#include "hw/mips-bios.h"
-#include "hw/ide.h"
-#include "elf.h"
-#include "hw/vt82c686.h"
-#include "hw/mc146818rtc.h"
-#include "hw/i8254.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-#define DEBUG_FULONG2E_INIT
-
-#define ENVP_ADDR       0x80002000l
-#define ENVP_NB_ENTRIES	 	16
-#define ENVP_ENTRY_SIZE	 	256
-
-#define MAX_IDE_BUS 2
-
-/*
- * PMON is not part of qemu and released with BSD license, anyone
- * who want to build a pmon binary please first git-clone the source
- * from the git repository at:
- * http://www.loongson.cn/support/git/pmon
- * Then follow the "Compile Guide" available at:
- * http://dev.lemote.com/code/pmon
- *
- * Notes:
- * 1, don't use the source at http://dev.lemote.com/http_git/pmon.git
- * 2, use "Bonito2edev" to replace "dir_corresponding_to_your_target_hardware"
- * in the "Compile Guide".
- */
-#define FULONG_BIOSNAME "pmon_fulong2e.bin"
-
-/* PCI SLOT in fulong 2e */
-#define FULONG2E_VIA_SLOT        5
-#define FULONG2E_ATI_SLOT        6
-#define FULONG2E_RTL8139_SLOT    7
-
-static ISADevice *pit;
-
-static struct _loaderparams {
-    int ram_size;
-    const char *kernel_filename;
-    const char *kernel_cmdline;
-    const char *initrd_filename;
-} loaderparams;
-
-static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index,
-                                        const char *string, ...)
-{
-    va_list ap;
-    int32_t table_addr;
-
-    if (index >= ENVP_NB_ENTRIES)
-        return;
-
-    if (string == NULL) {
-        prom_buf[index] = 0;
-        return;
-    }
-
-    table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
-    prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
-
-    va_start(ap, string);
-    vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
-    va_end(ap);
-}
-
-static int64_t load_kernel (CPUMIPSState *env)
-{
-    int64_t kernel_entry, kernel_low, kernel_high;
-    int index = 0;
-    long initrd_size;
-    ram_addr_t initrd_offset;
-    uint32_t *prom_buf;
-    long prom_size;
-
-    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
-                 (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
-                 (uint64_t *)&kernel_high, 0, ELF_MACHINE, 1) < 0) {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                loaderparams.kernel_filename);
-        exit(1);
-    }
-
-    /* load initrd */
-    initrd_size = 0;
-    initrd_offset = 0;
-    if (loaderparams.initrd_filename) {
-        initrd_size = get_image_size (loaderparams.initrd_filename);
-        if (initrd_size > 0) {
-            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
-            if (initrd_offset + initrd_size > ram_size) {
-                fprintf(stderr,
-                        "qemu: memory too small for initial ram disk '%s'\n",
-                        loaderparams.initrd_filename);
-                exit(1);
-            }
-            initrd_size = load_image_targphys(loaderparams.initrd_filename,
-                                     initrd_offset, ram_size - initrd_offset);
-        }
-        if (initrd_size == (target_ulong) -1) {
-            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
-                    loaderparams.initrd_filename);
-            exit(1);
-        }
-    }
-
-    /* Setup prom parameters. */
-    prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
-    prom_buf = g_malloc(prom_size);
-
-    prom_set(prom_buf, index++, "%s", loaderparams.kernel_filename);
-    if (initrd_size > 0) {
-        prom_set(prom_buf, index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
-                 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
-                 loaderparams.kernel_cmdline);
-    } else {
-        prom_set(prom_buf, index++, "%s", loaderparams.kernel_cmdline);
-    }
-
-    /* Setup minimum environment variables */
-    prom_set(prom_buf, index++, "busclock=33000000");
-    prom_set(prom_buf, index++, "cpuclock=100000000");
-    prom_set(prom_buf, index++, "memsize=%i", loaderparams.ram_size/1024/1024);
-    prom_set(prom_buf, index++, "modetty0=38400n8r");
-    prom_set(prom_buf, index++, NULL);
-
-    rom_add_blob_fixed("prom", prom_buf, prom_size,
-                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
-
-    return kernel_entry;
-}
-
-static void write_bootloader (CPUMIPSState *env, uint8_t *base, int64_t kernel_addr)
-{
-    uint32_t *p;
-
-    /* Small bootloader */
-    p = (uint32_t *) base;
-
-    stl_raw(p++, 0x0bf00010);                                      /* j 0x1fc00040 */
-    stl_raw(p++, 0x00000000);                                      /* nop */
-
-    /* Second part of the bootloader */
-    p = (uint32_t *) (base + 0x040);
-
-    stl_raw(p++, 0x3c040000);                                      /* lui a0, 0 */
-    stl_raw(p++, 0x34840002);                                      /* ori a0, a0, 2 */
-    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
-    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
-    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
-    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
-    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));      /* lui a3, high(env->ram_size) */
-    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));   /* ori a3, a3, low(env->ram_size) */
-    stl_raw(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff));     /* lui ra, high(kernel_addr) */;
-    stl_raw(p++, 0x37ff0000 | (kernel_addr & 0xffff));             /* ori ra, ra, low(kernel_addr) */
-    stl_raw(p++, 0x03e00008);                                      /* jr ra */
-    stl_raw(p++, 0x00000000);                                      /* nop */
-}
-
-
-static void main_cpu_reset(void *opaque)
-{
-    MIPSCPU *cpu = opaque;
-    CPUMIPSState *env = &cpu->env;
-
-    cpu_reset(CPU(cpu));
-    /* TODO: 2E reset stuff */
-    if (loaderparams.kernel_filename) {
-        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
-    }
-}
-
-uint8_t eeprom_spd[0x80] = {
-    0x80,0x08,0x07,0x0d,0x09,0x02,0x40,0x00,0x04,0x70,
-    0x70,0x00,0x82,0x10,0x00,0x01,0x0e,0x04,0x0c,0x01,
-    0x02,0x20,0x80,0x75,0x70,0x00,0x00,0x50,0x3c,0x50,
-    0x2d,0x20,0xb0,0xb0,0x50,0x50,0x00,0x00,0x00,0x00,
-    0x00,0x41,0x48,0x3c,0x32,0x75,0x00,0x00,0x00,0x00,
-    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-    0x00,0x00,0x00,0x9c,0x7b,0x07,0x00,0x00,0x00,0x00,
-    0x00,0x00,0x00,0x00,0x48,0x42,0x35,0x34,0x41,0x32,
-    0x35,0x36,0x38,0x4b,0x4e,0x2d,0x41,0x37,0x35,0x42,
-    0x20,0x30,0x20
-};
-
-/* Audio support */
-static void audio_init (PCIBus *pci_bus)
-{
-    vt82c686b_ac97_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 5));
-    vt82c686b_mc97_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 6));
-}
-
-/* Network support */
-static void network_init (void)
-{
-    int i;
-
-    for(i = 0; i < nb_nics; i++) {
-        NICInfo *nd = &nd_table[i];
-        const char *default_devaddr = NULL;
-
-        if (i == 0 && (!nd->model || strcmp(nd->model, "rtl8139") == 0)) {
-            /* The fulong board has a RTL8139 card using PCI SLOT 7 */
-            default_devaddr = "07";
-        }
-
-        pci_nic_init_nofail(nd, "rtl8139", default_devaddr);
-    }
-}
-
-static void cpu_request_exit(void *opaque, int irq, int level)
-{
-    CPUMIPSState *env = cpu_single_env;
-
-    if (env && level) {
-        cpu_exit(env);
-    }
-}
-
-static void mips_fulong2e_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    char *filename;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *bios = g_new(MemoryRegion, 1);
-    long bios_size;
-    int64_t kernel_entry;
-    qemu_irq *i8259;
-    qemu_irq *cpu_exit_irq;
-    PCIBus *pci_bus;
-    ISABus *isa_bus;
-    i2c_bus *smbus;
-    int i;
-    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    MIPSCPU *cpu;
-    CPUMIPSState *env;
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-        cpu_model = "Loongson-2E";
-    }
-    cpu = cpu_mips_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    qemu_register_reset(main_cpu_reset, cpu);
-
-    /* fulong 2e has 256M ram. */
-    ram_size = 256 * 1024 * 1024;
-
-    /* fulong 2e has a 1M flash.Winbond W39L040AP70Z */
-    bios_size = 1024 * 1024;
-
-    /* allocate RAM */
-    memory_region_init_ram(ram, "fulong2e.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_init_ram(bios, "fulong2e.bios", bios_size);
-    vmstate_register_ram_global(bios);
-    memory_region_set_readonly(bios, true);
-
-    memory_region_add_subregion(address_space_mem, 0, ram);
-    memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
-
-    /* We do not support flash operation, just loading pmon.bin as raw BIOS.
-     * Please use -L to set the BIOS path and -bios to set bios name. */
-
-    if (kernel_filename) {
-        loaderparams.ram_size = ram_size;
-        loaderparams.kernel_filename = kernel_filename;
-        loaderparams.kernel_cmdline = kernel_cmdline;
-        loaderparams.initrd_filename = initrd_filename;
-        kernel_entry = load_kernel (env);
-        write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
-    } else {
-        if (bios_name == NULL) {
-                bios_name = FULONG_BIOSNAME;
-        }
-        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-        if (filename) {
-            bios_size = load_image_targphys(filename, 0x1fc00000LL,
-                                            BIOS_SIZE);
-            g_free(filename);
-        } else {
-            bios_size = -1;
-        }
-
-        if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
-            fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n", bios_name);
-            exit(1);
-        }
-    }
-
-    /* Init internal devices */
-    cpu_mips_irq_init_cpu(env);
-    cpu_mips_clock_init(env);
-
-    /* North bridge, Bonito --> IP2 */
-    pci_bus = bonito_init((qemu_irq *)&(env->irq[2]));
-
-    /* South bridge */
-    ide_drive_get(hd, MAX_IDE_BUS);
-
-    isa_bus = vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 0));
-    if (!isa_bus) {
-        fprintf(stderr, "vt82c686b_init error\n");
-        exit(1);
-    }
-
-    /* Interrupt controller */
-    /* The 8259 -> IP5  */
-    i8259 = i8259_init(isa_bus, env->irq[5]);
-    isa_bus_irqs(isa_bus, i8259);
-
-    vt82c686b_ide_init(pci_bus, hd, PCI_DEVFN(FULONG2E_VIA_SLOT, 1));
-    pci_create_simple(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 2),
-                      "vt82c686b-usb-uhci");
-    pci_create_simple(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 3),
-                      "vt82c686b-usb-uhci");
-
-    smbus = vt82c686b_pm_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 4),
-                              0xeee1, NULL);
-    /* TODO: Populate SPD eeprom data.  */
-    smbus_eeprom_init(smbus, 1, eeprom_spd, sizeof(eeprom_spd));
-
-    /* init other devices */
-    pit = pit_init(isa_bus, 0x40, 0, NULL);
-    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
-    DMA_init(0, cpu_exit_irq);
-
-    /* Super I/O */
-    isa_create_simple(isa_bus, "i8042");
-
-    rtc_init(isa_bus, 2000, NULL);
-
-    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
-        if (serial_hds[i]) {
-            serial_isa_init(isa_bus, i, serial_hds[i]);
-        }
-    }
-
-    if (parallel_hds[0]) {
-        parallel_init(isa_bus, 0, parallel_hds[0]);
-    }
-
-    /* Sound card */
-    audio_init(pci_bus);
-    /* Network card */
-    network_init();
-}
-
-static QEMUMachine mips_fulong2e_machine = {
-    .name = "fulong2e",
-    .desc = "Fulong 2e mini pc",
-    .init = mips_fulong2e_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void mips_fulong2e_machine_init(void)
-{
-    qemu_register_machine(&mips_fulong2e_machine);
-}
-
-machine_init(mips_fulong2e_machine_init);
diff --git a/hw/mips_int.c b/hw/mips_int.c
deleted file mode 100644
index ddd3b1b..0000000
--- a/hw/mips_int.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * QEMU MIPS interrupt support
- *
- * 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/hw.h"
-#include "hw/mips_cpudevs.h"
-#include "cpu.h"
-
-static void cpu_mips_irq_request(void *opaque, int irq, int level)
-{
-    CPUMIPSState *env = (CPUMIPSState *)opaque;
-
-    if (irq < 0 || irq > 7)
-        return;
-
-    if (level) {
-        env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
-    } else {
-        env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
-    }
-
-    if (env->CP0_Cause & CP0Ca_IP_mask) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    } else {
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-}
-
-void cpu_mips_irq_init_cpu(CPUMIPSState *env)
-{
-    qemu_irq *qi;
-    int i;
-
-    qi = qemu_allocate_irqs(cpu_mips_irq_request, env, 8);
-    for (i = 0; i < 8; i++) {
-        env->irq[i] = qi[i];
-    }
-}
-
-void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level)
-{
-    if (irq < 0 || irq > 2) {
-        return;
-    }
-
-    qemu_set_irq(env->irq[irq], level);
-}
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
deleted file mode 100644
index daeb985..0000000
--- a/hw/mips_jazz.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * QEMU MIPS Jazz support
- *
- * Copyright (c) 2007-2008 Hervé Poussineau
- *
- * 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/hw.h"
-#include "hw/mips.h"
-#include "hw/mips_cpudevs.h"
-#include "hw/pc.h"
-#include "hw/serial.h"
-#include "hw/isa.h"
-#include "hw/fdc.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/arch_init.h"
-#include "hw/boards.h"
-#include "net/net.h"
-#include "hw/esp.h"
-#include "hw/mips-bios.h"
-#include "hw/loader.h"
-#include "hw/mc146818rtc.h"
-#include "hw/i8254.h"
-#include "hw/pcspk.h"
-#include "sysemu/blockdev.h"
-#include "hw/sysbus.h"
-#include "exec/address-spaces.h"
-
-enum jazz_model_e
-{
-    JAZZ_MAGNUM,
-    JAZZ_PICA61,
-};
-
-static void main_cpu_reset(void *opaque)
-{
-    MIPSCPU *cpu = opaque;
-
-    cpu_reset(CPU(cpu));
-}
-
-static uint64_t rtc_read(void *opaque, hwaddr addr, unsigned size)
-{
-    return cpu_inw(0x71);
-}
-
-static void rtc_write(void *opaque, hwaddr addr,
-                      uint64_t val, unsigned size)
-{
-    cpu_outw(0x71, val & 0xff);
-}
-
-static const MemoryRegionOps rtc_ops = {
-    .read = rtc_read,
-    .write = rtc_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static uint64_t dma_dummy_read(void *opaque, hwaddr addr,
-                               unsigned size)
-{
-    /* Nothing to do. That is only to ensure that
-     * the current DMA acknowledge cycle is completed. */
-    return 0xff;
-}
-
-static void dma_dummy_write(void *opaque, hwaddr addr,
-                            uint64_t val, unsigned size)
-{
-    /* Nothing to do. That is only to ensure that
-     * the current DMA acknowledge cycle is completed. */
-}
-
-static const MemoryRegionOps dma_dummy_ops = {
-    .read = dma_dummy_read,
-    .write = dma_dummy_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-#define MAGNUM_BIOS_SIZE_MAX 0x7e000
-#define MAGNUM_BIOS_SIZE (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX)
-
-static void cpu_request_exit(void *opaque, int irq, int level)
-{
-    CPUMIPSState *env = cpu_single_env;
-
-    if (env && level) {
-        cpu_exit(env);
-    }
-}
-
-static void mips_jazz_init(MemoryRegion *address_space,
-                           MemoryRegion *address_space_io,
-                           ram_addr_t ram_size,
-                           const char *cpu_model,
-                           enum jazz_model_e jazz_model)
-{
-    char *filename;
-    int bios_size, n;
-    MIPSCPU *cpu;
-    CPUMIPSState *env;
-    qemu_irq *rc4030, *i8259;
-    rc4030_dma *dmas;
-    void* rc4030_opaque;
-    MemoryRegion *rtc = g_new(MemoryRegion, 1);
-    MemoryRegion *i8042 = g_new(MemoryRegion, 1);
-    MemoryRegion *dma_dummy = g_new(MemoryRegion, 1);
-    NICInfo *nd;
-    DeviceState *dev;
-    SysBusDevice *sysbus;
-    ISABus *isa_bus;
-    ISADevice *pit;
-    DriveInfo *fds[MAX_FD];
-    qemu_irq esp_reset, dma_enable;
-    qemu_irq *cpu_exit_irq;
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *bios = g_new(MemoryRegion, 1);
-    MemoryRegion *bios2 = g_new(MemoryRegion, 1);
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-#ifdef TARGET_MIPS64
-        cpu_model = "R4000";
-#else
-        /* FIXME: All wrong, this maybe should be R3000 for the older JAZZs. */
-        cpu_model = "24Kf";
-#endif
-    }
-    cpu = cpu_mips_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-    qemu_register_reset(main_cpu_reset, cpu);
-
-    /* allocate RAM */
-    memory_region_init_ram(ram, "mips_jazz.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(address_space, 0, ram);
-
-    memory_region_init_ram(bios, "mips_jazz.bios", MAGNUM_BIOS_SIZE);
-    vmstate_register_ram_global(bios);
-    memory_region_set_readonly(bios, true);
-    memory_region_init_alias(bios2, "mips_jazz.bios", bios,
-                             0, MAGNUM_BIOS_SIZE);
-    memory_region_add_subregion(address_space, 0x1fc00000LL, bios);
-    memory_region_add_subregion(address_space, 0xfff00000LL, bios2);
-
-    /* load the BIOS image. */
-    if (bios_name == NULL)
-        bios_name = BIOS_FILENAME;
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-    if (filename) {
-        bios_size = load_image_targphys(filename, 0xfff00000LL,
-                                        MAGNUM_BIOS_SIZE);
-        g_free(filename);
-    } else {
-        bios_size = -1;
-    }
-    if (bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) {
-        fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n",
-                bios_name);
-        exit(1);
-    }
-
-    /* Init CPU internal devices */
-    cpu_mips_irq_init_cpu(env);
-    cpu_mips_clock_init(env);
-
-    /* Chipset */
-    rc4030_opaque = rc4030_init(env->irq[6], env->irq[3], &rc4030, &dmas,
-                                address_space);
-    memory_region_init_io(dma_dummy, &dma_dummy_ops, NULL, "dummy_dma", 0x1000);
-    memory_region_add_subregion(address_space, 0x8000d000, dma_dummy);
-
-    /* ISA devices */
-    isa_bus = isa_bus_new(NULL, address_space_io);
-    i8259 = i8259_init(isa_bus, env->irq[4]);
-    isa_bus_irqs(isa_bus, i8259);
-    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
-    DMA_init(0, cpu_exit_irq);
-    pit = pit_init(isa_bus, 0x40, 0, NULL);
-    pcspk_init(isa_bus, pit);
-
-    /* ISA IO space at 0x90000000 */
-    isa_mmio_init(0x90000000, 0x01000000);
-    isa_mem_base = 0x11000000;
-
-    /* Video card */
-    switch (jazz_model) {
-    case JAZZ_MAGNUM:
-        dev = qdev_create(NULL, "sysbus-g364");
-        qdev_init_nofail(dev);
-        sysbus = SYS_BUS_DEVICE(dev);
-        sysbus_mmio_map(sysbus, 0, 0x60080000);
-        sysbus_mmio_map(sysbus, 1, 0x40000000);
-        sysbus_connect_irq(sysbus, 0, rc4030[3]);
-        {
-            /* Simple ROM, so user doesn't have to provide one */
-            MemoryRegion *rom_mr = g_new(MemoryRegion, 1);
-            memory_region_init_ram(rom_mr, "g364fb.rom", 0x80000);
-            vmstate_register_ram_global(rom_mr);
-            memory_region_set_readonly(rom_mr, true);
-            uint8_t *rom = memory_region_get_ram_ptr(rom_mr);
-            memory_region_add_subregion(address_space, 0x60000000, rom_mr);
-            rom[0] = 0x10; /* Mips G364 */
-        }
-        break;
-    case JAZZ_PICA61:
-        isa_vga_mm_init(0x40000000, 0x60000000, 0, get_system_memory());
-        break;
-    default:
-        break;
-    }
-
-    /* Network controller */
-    for (n = 0; n < nb_nics; n++) {
-        nd = &nd_table[n];
-        if (!nd->model)
-            nd->model = g_strdup("dp83932");
-        if (strcmp(nd->model, "dp83932") == 0) {
-            dp83932_init(nd, 0x80001000, 2, get_system_memory(), rc4030[4],
-                         rc4030_opaque, rc4030_dma_memory_rw);
-            break;
-        } else if (is_help_option(nd->model)) {
-            fprintf(stderr, "qemu: Supported NICs: dp83932\n");
-            exit(1);
-        } else {
-            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
-            exit(1);
-        }
-    }
-
-    /* SCSI adapter */
-    esp_init(0x80002000, 0,
-             rc4030_dma_read, rc4030_dma_write, dmas[0],
-             rc4030[5], &esp_reset, &dma_enable);
-
-    /* Floppy */
-    if (drive_get_max_bus(IF_FLOPPY) >= MAX_FD) {
-        fprintf(stderr, "qemu: too many floppy drives\n");
-        exit(1);
-    }
-    for (n = 0; n < MAX_FD; n++) {
-        fds[n] = drive_get(IF_FLOPPY, 0, n);
-    }
-    fdctrl_init_sysbus(rc4030[1], 0, 0x80003000, fds);
-
-    /* Real time clock */
-    rtc_init(isa_bus, 1980, NULL);
-    memory_region_init_io(rtc, &rtc_ops, NULL, "rtc", 0x1000);
-    memory_region_add_subregion(address_space, 0x80004000, rtc);
-
-    /* Keyboard (i8042) */
-    i8042_mm_init(rc4030[6], rc4030[7], i8042, 0x1000, 0x1);
-    memory_region_add_subregion(address_space, 0x80005000, i8042);
-
-    /* Serial ports */
-    if (serial_hds[0]) {
-        serial_mm_init(address_space, 0x80006000, 0, rc4030[8], 8000000/16,
-                       serial_hds[0], DEVICE_NATIVE_ENDIAN);
-    }
-    if (serial_hds[1]) {
-        serial_mm_init(address_space, 0x80007000, 0, rc4030[9], 8000000/16,
-                       serial_hds[1], DEVICE_NATIVE_ENDIAN);
-    }
-
-    /* Parallel port */
-    if (parallel_hds[0])
-        parallel_mm_init(address_space, 0x80008000, 0, rc4030[0],
-                         parallel_hds[0]);
-
-    /* Sound card */
-    /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */
-    audio_init(isa_bus, NULL);
-
-    /* NVRAM */
-    dev = qdev_create(NULL, "ds1225y");
-    qdev_init_nofail(dev);
-    sysbus = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(sysbus, 0, 0x80009000);
-
-    /* LED indicator */
-    sysbus_create_simple("jazz-led", 0x8000f000, NULL);
-}
-
-static
-void mips_magnum_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-        mips_jazz_init(get_system_memory(), get_system_io(),
-                       ram_size, cpu_model, JAZZ_MAGNUM);
-}
-
-static
-void mips_pica61_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    mips_jazz_init(get_system_memory(), get_system_io(),
-                   ram_size, cpu_model, JAZZ_PICA61);
-}
-
-static QEMUMachine mips_magnum_machine = {
-    .name = "magnum",
-    .desc = "MIPS Magnum",
-    .init = mips_magnum_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine mips_pica61_machine = {
-    .name = "pica61",
-    .desc = "Acer Pica 61",
-    .init = mips_pica61_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void mips_jazz_machine_init(void)
-{
-    qemu_register_machine(&mips_magnum_machine);
-    qemu_register_machine(&mips_pica61_machine);
-}
-
-machine_init(mips_jazz_machine_init);
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
deleted file mode 100644
index 9a67dce..0000000
--- a/hw/mips_malta.c
+++ /dev/null
@@ -1,1037 +0,0 @@
-/*
- * QEMU Malta board support
- *
- * Copyright (c) 2006 Aurelien Jarno
- *
- * 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/hw.h"
-#include "hw/pc.h"
-#include "hw/serial.h"
-#include "hw/fdc.h"
-#include "net/net.h"
-#include "hw/boards.h"
-#include "hw/smbus.h"
-#include "block/block.h"
-#include "hw/flash.h"
-#include "hw/mips.h"
-#include "hw/mips_cpudevs.h"
-#include "hw/pci/pci.h"
-#include "char/char.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/arch_init.h"
-#include "hw/boards.h"
-#include "qemu/log.h"
-#include "hw/mips-bios.h"
-#include "hw/ide.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "hw/mc146818rtc.h"
-#include "hw/i8254.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-#include "hw/sysbus.h"             /* SysBusDevice */
-
-//#define DEBUG_BOARD_INIT
-
-#define ENVP_ADDR		0x80002000l
-#define ENVP_NB_ENTRIES	 	16
-#define ENVP_ENTRY_SIZE	 	256
-
-/* Hardware addresses */
-#define FLASH_ADDRESS 0x1e000000ULL
-#define FPGA_ADDRESS  0x1f000000ULL
-#define RESET_ADDRESS 0x1fc00000ULL
-
-#define FLASH_SIZE    0x400000
-
-#define MAX_IDE_BUS 2
-
-typedef struct {
-    MemoryRegion iomem;
-    MemoryRegion iomem_lo; /* 0 - 0x900 */
-    MemoryRegion iomem_hi; /* 0xa00 - 0x100000 */
-    uint32_t leds;
-    uint32_t brk;
-    uint32_t gpout;
-    uint32_t i2cin;
-    uint32_t i2coe;
-    uint32_t i2cout;
-    uint32_t i2csel;
-    CharDriverState *display;
-    char display_text[9];
-    SerialState *uart;
-} MaltaFPGAState;
-
-typedef struct {
-    SysBusDevice busdev;
-    qemu_irq *i8259;
-} MaltaState;
-
-static ISADevice *pit;
-
-static struct _loaderparams {
-    int ram_size;
-    const char *kernel_filename;
-    const char *kernel_cmdline;
-    const char *initrd_filename;
-} loaderparams;
-
-/* Malta FPGA */
-static void malta_fpga_update_display(void *opaque)
-{
-    char leds_text[9];
-    int i;
-    MaltaFPGAState *s = opaque;
-
-    for (i = 7 ; i >= 0 ; i--) {
-        if (s->leds & (1 << i))
-            leds_text[i] = '#';
-        else
-            leds_text[i] = ' ';
-    }
-    leds_text[8] = '\0';
-
-    qemu_chr_fe_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
-    qemu_chr_fe_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
-}
-
-/*
- * EEPROM 24C01 / 24C02 emulation.
- *
- * Emulation for serial EEPROMs:
- * 24C01 - 1024 bit (128 x 8)
- * 24C02 - 2048 bit (256 x 8)
- *
- * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
- */
-
-//~ #define DEBUG
-
-#if defined(DEBUG)
-#  define logout(fmt, ...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ## __VA_ARGS__)
-#else
-#  define logout(fmt, ...) ((void)0)
-#endif
-
-struct _eeprom24c0x_t {
-  uint8_t tick;
-  uint8_t address;
-  uint8_t command;
-  uint8_t ack;
-  uint8_t scl;
-  uint8_t sda;
-  uint8_t data;
-  //~ uint16_t size;
-  uint8_t contents[256];
-};
-
-typedef struct _eeprom24c0x_t eeprom24c0x_t;
-
-static eeprom24c0x_t eeprom = {
-    .contents = {
-        /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
-        /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
-        /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
-        /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
-        /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
-        /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
-        /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-        /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
-    },
-};
-
-static uint8_t eeprom24c0x_read(void)
-{
-    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
-        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
-    return eeprom.sda;
-}
-
-static void eeprom24c0x_write(int scl, int sda)
-{
-    if (eeprom.scl && scl && (eeprom.sda != sda)) {
-        logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
-                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
-        if (!sda) {
-            eeprom.tick = 1;
-            eeprom.command = 0;
-        }
-    } else if (eeprom.tick == 0 && !eeprom.ack) {
-        /* Waiting for start. */
-        logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
-                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
-    } else if (!eeprom.scl && scl) {
-        logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
-                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
-        if (eeprom.ack) {
-            logout("\ti2c ack bit = 0\n");
-            sda = 0;
-            eeprom.ack = 0;
-        } else if (eeprom.sda == sda) {
-            uint8_t bit = (sda != 0);
-            logout("\ti2c bit = %d\n", bit);
-            if (eeprom.tick < 9) {
-                eeprom.command <<= 1;
-                eeprom.command += bit;
-                eeprom.tick++;
-                if (eeprom.tick == 9) {
-                    logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
-                    eeprom.ack = 1;
-                }
-            } else if (eeprom.tick < 17) {
-                if (eeprom.command & 1) {
-                    sda = ((eeprom.data & 0x80) != 0);
-                }
-                eeprom.address <<= 1;
-                eeprom.address += bit;
-                eeprom.tick++;
-                eeprom.data <<= 1;
-                if (eeprom.tick == 17) {
-                    eeprom.data = eeprom.contents[eeprom.address];
-                    logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
-                    eeprom.ack = 1;
-                    eeprom.tick = 0;
-                }
-            } else if (eeprom.tick >= 17) {
-                sda = 0;
-            }
-        } else {
-            logout("\tsda changed with raising scl\n");
-        }
-    } else {
-        logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
-    }
-    eeprom.scl = scl;
-    eeprom.sda = sda;
-}
-
-static uint64_t malta_fpga_read(void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    MaltaFPGAState *s = opaque;
-    uint32_t val = 0;
-    uint32_t saddr;
-
-    saddr = (addr & 0xfffff);
-
-    switch (saddr) {
-
-    /* SWITCH Register */
-    case 0x00200:
-        val = 0x00000000;		/* All switches closed */
-        break;
-
-    /* STATUS Register */
-    case 0x00208:
-#ifdef TARGET_WORDS_BIGENDIAN
-        val = 0x00000012;
-#else
-        val = 0x00000010;
-#endif
-        break;
-
-    /* JMPRS Register */
-    case 0x00210:
-        val = 0x00;
-        break;
-
-    /* LEDBAR Register */
-    case 0x00408:
-        val = s->leds;
-        break;
-
-    /* BRKRES Register */
-    case 0x00508:
-        val = s->brk;
-        break;
-
-    /* UART Registers are handled directly by the serial device */
-
-    /* GPOUT Register */
-    case 0x00a00:
-        val = s->gpout;
-        break;
-
-    /* XXX: implement a real I2C controller */
-
-    /* GPINP Register */
-    case 0x00a08:
-        /* IN = OUT until a real I2C control is implemented */
-        if (s->i2csel)
-            val = s->i2cout;
-        else
-            val = 0x00;
-        break;
-
-    /* I2CINP Register */
-    case 0x00b00:
-        val = ((s->i2cin & ~1) | eeprom24c0x_read());
-        break;
-
-    /* I2COE Register */
-    case 0x00b08:
-        val = s->i2coe;
-        break;
-
-    /* I2COUT Register */
-    case 0x00b10:
-        val = s->i2cout;
-        break;
-
-    /* I2CSEL Register */
-    case 0x00b18:
-        val = s->i2csel;
-        break;
-
-    default:
-#if 0
-        printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
-                addr);
-#endif
-        break;
-    }
-    return val;
-}
-
-static void malta_fpga_write(void *opaque, hwaddr addr,
-                             uint64_t val, unsigned size)
-{
-    MaltaFPGAState *s = opaque;
-    uint32_t saddr;
-
-    saddr = (addr & 0xfffff);
-
-    switch (saddr) {
-
-    /* SWITCH Register */
-    case 0x00200:
-        break;
-
-    /* JMPRS Register */
-    case 0x00210:
-        break;
-
-    /* LEDBAR Register */
-    case 0x00408:
-        s->leds = val & 0xff;
-        malta_fpga_update_display(s);
-        break;
-
-    /* ASCIIWORD Register */
-    case 0x00410:
-        snprintf(s->display_text, 9, "%08X", (uint32_t)val);
-        malta_fpga_update_display(s);
-        break;
-
-    /* ASCIIPOS0 to ASCIIPOS7 Registers */
-    case 0x00418:
-    case 0x00420:
-    case 0x00428:
-    case 0x00430:
-    case 0x00438:
-    case 0x00440:
-    case 0x00448:
-    case 0x00450:
-        s->display_text[(saddr - 0x00418) >> 3] = (char) val;
-        malta_fpga_update_display(s);
-        break;
-
-    /* SOFTRES Register */
-    case 0x00500:
-        if (val == 0x42)
-            qemu_system_reset_request ();
-        break;
-
-    /* BRKRES Register */
-    case 0x00508:
-        s->brk = val & 0xff;
-        break;
-
-    /* UART Registers are handled directly by the serial device */
-
-    /* GPOUT Register */
-    case 0x00a00:
-        s->gpout = val & 0xff;
-        break;
-
-    /* I2COE Register */
-    case 0x00b08:
-        s->i2coe = val & 0x03;
-        break;
-
-    /* I2COUT Register */
-    case 0x00b10:
-        eeprom24c0x_write(val & 0x02, val & 0x01);
-        s->i2cout = val;
-        break;
-
-    /* I2CSEL Register */
-    case 0x00b18:
-        s->i2csel = val & 0x01;
-        break;
-
-    default:
-#if 0
-        printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
-                addr);
-#endif
-        break;
-    }
-}
-
-static const MemoryRegionOps malta_fpga_ops = {
-    .read = malta_fpga_read,
-    .write = malta_fpga_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void malta_fpga_reset(void *opaque)
-{
-    MaltaFPGAState *s = opaque;
-
-    s->leds   = 0x00;
-    s->brk    = 0x0a;
-    s->gpout  = 0x00;
-    s->i2cin  = 0x3;
-    s->i2coe  = 0x0;
-    s->i2cout = 0x3;
-    s->i2csel = 0x1;
-
-    s->display_text[8] = '\0';
-    snprintf(s->display_text, 9, "        ");
-}
-
-static void malta_fpga_led_init(CharDriverState *chr)
-{
-    qemu_chr_fe_printf(chr, "\e[HMalta LEDBAR\r\n");
-    qemu_chr_fe_printf(chr, "+--------+\r\n");
-    qemu_chr_fe_printf(chr, "+        +\r\n");
-    qemu_chr_fe_printf(chr, "+--------+\r\n");
-    qemu_chr_fe_printf(chr, "\n");
-    qemu_chr_fe_printf(chr, "Malta ASCII\r\n");
-    qemu_chr_fe_printf(chr, "+--------+\r\n");
-    qemu_chr_fe_printf(chr, "+        +\r\n");
-    qemu_chr_fe_printf(chr, "+--------+\r\n");
-}
-
-static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
-         hwaddr base, qemu_irq uart_irq, CharDriverState *uart_chr)
-{
-    MaltaFPGAState *s;
-
-    s = (MaltaFPGAState *)g_malloc0(sizeof(MaltaFPGAState));
-
-    memory_region_init_io(&s->iomem, &malta_fpga_ops, s,
-                          "malta-fpga", 0x100000);
-    memory_region_init_alias(&s->iomem_lo, "malta-fpga",
-                             &s->iomem, 0, 0x900);
-    memory_region_init_alias(&s->iomem_hi, "malta-fpga",
-                             &s->iomem, 0xa00, 0x10000-0xa00);
-
-    memory_region_add_subregion(address_space, base, &s->iomem_lo);
-    memory_region_add_subregion(address_space, base + 0xa00, &s->iomem_hi);
-
-    s->display = qemu_chr_new("fpga", "vc:320x200", malta_fpga_led_init);
-
-    s->uart = serial_mm_init(address_space, base + 0x900, 3, uart_irq,
-                             230400, uart_chr, DEVICE_NATIVE_ENDIAN);
-
-    malta_fpga_reset(s);
-    qemu_register_reset(malta_fpga_reset, s);
-
-    return s;
-}
-
-/* Network support */
-static void network_init(void)
-{
-    int i;
-
-    for(i = 0; i < nb_nics; i++) {
-        NICInfo *nd = &nd_table[i];
-        const char *default_devaddr = NULL;
-
-        if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
-            /* The malta board has a PCNet card using PCI SLOT 11 */
-            default_devaddr = "0b";
-
-        pci_nic_init_nofail(nd, "pcnet", default_devaddr);
-    }
-}
-
-/* ROM and pseudo bootloader
-
-   The following code implements a very very simple bootloader. It first
-   loads the registers a0 to a3 to the values expected by the OS, and
-   then jump at the kernel address.
-
-   The bootloader should pass the locations of the kernel arguments and
-   environment variables tables. Those tables contain the 32-bit address
-   of NULL terminated strings. The environment variables table should be
-   terminated by a NULL address.
-
-   For a simpler implementation, the number of kernel arguments is fixed
-   to two (the name of the kernel and the command line), and the two
-   tables are actually the same one.
-
-   The registers a0 to a3 should contain the following values:
-     a0 - number of kernel arguments
-     a1 - 32-bit address of the kernel arguments table
-     a2 - 32-bit address of the environment variables table
-     a3 - RAM size in bytes
-*/
-
-static void write_bootloader (CPUMIPSState *env, uint8_t *base,
-                              int64_t kernel_entry)
-{
-    uint32_t *p;
-
-    /* Small bootloader */
-    p = (uint32_t *)base;
-    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
-    stl_raw(p++, 0x00000000);                                      /* nop */
-
-    /* YAMON service vector */
-    stl_raw(base + 0x500, 0xbfc00580);      /* start: */
-    stl_raw(base + 0x504, 0xbfc0083c);      /* print_count: */
-    stl_raw(base + 0x520, 0xbfc00580);      /* start: */
-    stl_raw(base + 0x52c, 0xbfc00800);      /* flush_cache: */
-    stl_raw(base + 0x534, 0xbfc00808);      /* print: */
-    stl_raw(base + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
-    stl_raw(base + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
-    stl_raw(base + 0x540, 0xbfc00800);      /* reg_ic_isr: */
-    stl_raw(base + 0x544, 0xbfc00800);      /* unred_ic_isr: */
-    stl_raw(base + 0x548, 0xbfc00800);      /* reg_esr: */
-    stl_raw(base + 0x54c, 0xbfc00800);      /* unreg_esr: */
-    stl_raw(base + 0x550, 0xbfc00800);      /* getchar: */
-    stl_raw(base + 0x554, 0xbfc00800);      /* syscon_read: */
-
-
-    /* Second part of the bootloader */
-    p = (uint32_t *) (base + 0x580);
-    stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
-    stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
-    stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
-    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
-    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
-    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
-    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
-    stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
-    stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff));  /* ori a3, a3, low(ram_size) */
-
-    /* Load BAR registers as done by YAMON */
-    stl_raw(p++, 0x3c09b400);                                      /* lui t1, 0xb400 */
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c08df00);                                      /* lui t0, 0xdf00 */
-#else
-    stl_raw(p++, 0x340800df);                                      /* ori t0, r0, 0x00df */
-#endif
-    stl_raw(p++, 0xad280068);                                      /* sw t0, 0x0068(t1) */
-
-    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
-#else
-    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
-#endif
-    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
-#ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
-#else
-    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
-#endif
-    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
-#else
-    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
-#endif
-    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
-#ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
-#else
-    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
-#endif
-    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
-#else
-    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
-#endif
-    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
-#ifdef TARGET_WORDS_BIGENDIAN
-    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
-#else
-    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
-#endif
-    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
-
-    /* Jump to kernel code */
-    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
-    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
-    stl_raw(p++, 0x03e00008);                                      /* jr ra */
-    stl_raw(p++, 0x00000000);                                      /* nop */
-
-    /* YAMON subroutines */
-    p = (uint32_t *) (base + 0x800);
-    stl_raw(p++, 0x03e00008);                                     /* jr ra */
-    stl_raw(p++, 0x24020000);                                     /* li v0,0 */
-   /* 808 YAMON print */
-    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
-    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
-    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
-    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
-    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
-    stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x08000205);                                     /* j 814 */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
-    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
-    /* 0x83c YAMON print_count */
-    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
-    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
-    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
-    stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
-    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
-    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
-    stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
-    stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
-    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
-    /* 0x870 */
-    stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
-    stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
-    stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
-    stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
-    stl_raw(p++, 0x00000000);                                     /* nop */
-    stl_raw(p++, 0x03e00008);                                     /* jr ra */
-    stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
-
-}
-
-static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t* prom_buf, int index,
-                                        const char *string, ...)
-{
-    va_list ap;
-    int32_t table_addr;
-
-    if (index >= ENVP_NB_ENTRIES)
-        return;
-
-    if (string == NULL) {
-        prom_buf[index] = 0;
-        return;
-    }
-
-    table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
-    prom_buf[index] = tswap32(ENVP_ADDR + table_addr);
-
-    va_start(ap, string);
-    vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap);
-    va_end(ap);
-}
-
-/* Kernel */
-static int64_t load_kernel (void)
-{
-    int64_t kernel_entry, kernel_high;
-    long initrd_size;
-    ram_addr_t initrd_offset;
-    int big_endian;
-    uint32_t *prom_buf;
-    long prom_size;
-    int prom_index = 0;
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    big_endian = 1;
-#else
-    big_endian = 0;
-#endif
-
-    if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
-                 (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
-                 big_endian, ELF_MACHINE, 1) < 0) {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                loaderparams.kernel_filename);
-        exit(1);
-    }
-
-    /* load initrd */
-    initrd_size = 0;
-    initrd_offset = 0;
-    if (loaderparams.initrd_filename) {
-        initrd_size = get_image_size (loaderparams.initrd_filename);
-        if (initrd_size > 0) {
-            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
-            if (initrd_offset + initrd_size > ram_size) {
-                fprintf(stderr,
-                        "qemu: memory too small for initial ram disk '%s'\n",
-                        loaderparams.initrd_filename);
-                exit(1);
-            }
-            initrd_size = load_image_targphys(loaderparams.initrd_filename,
-                                              initrd_offset,
-                                              ram_size - initrd_offset);
-        }
-        if (initrd_size == (target_ulong) -1) {
-            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
-                    loaderparams.initrd_filename);
-            exit(1);
-        }
-    }
-
-    /* Setup prom parameters. */
-    prom_size = ENVP_NB_ENTRIES * (sizeof(int32_t) + ENVP_ENTRY_SIZE);
-    prom_buf = g_malloc(prom_size);
-
-    prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_filename);
-    if (initrd_size > 0) {
-        prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
-                 cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
-                 loaderparams.kernel_cmdline);
-    } else {
-        prom_set(prom_buf, prom_index++, "%s", loaderparams.kernel_cmdline);
-    }
-
-    prom_set(prom_buf, prom_index++, "memsize");
-    prom_set(prom_buf, prom_index++, "%i", loaderparams.ram_size);
-    prom_set(prom_buf, prom_index++, "modetty0");
-    prom_set(prom_buf, prom_index++, "38400n8r");
-    prom_set(prom_buf, prom_index++, NULL);
-
-    rom_add_blob_fixed("prom", prom_buf, prom_size,
-                       cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
-
-    return kernel_entry;
-}
-
-static void malta_mips_config(MIPSCPU *cpu)
-{
-    CPUMIPSState *env = &cpu->env;
-    CPUState *cs = CPU(cpu);
-
-    env->mvp->CP0_MVPConf0 |= ((smp_cpus - 1) << CP0MVPC0_PVPE) |
-                         ((smp_cpus * cs->nr_threads - 1) << CP0MVPC0_PTC);
-}
-
-static void main_cpu_reset(void *opaque)
-{
-    MIPSCPU *cpu = opaque;
-    CPUMIPSState *env = &cpu->env;
-
-    cpu_reset(CPU(cpu));
-
-    /* The bootloader does not need to be rewritten as it is located in a
-       read only location. The kernel location and the arguments table
-       location does not change. */
-    if (loaderparams.kernel_filename) {
-        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
-    }
-
-    malta_mips_config(cpu);
-}
-
-static void cpu_request_exit(void *opaque, int irq, int level)
-{
-    CPUMIPSState *env = cpu_single_env;
-
-    if (env && level) {
-        cpu_exit(env);
-    }
-}
-
-static
-void mips_malta_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    char *filename;
-    pflash_t *fl;
-    MemoryRegion *system_memory = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1);
-    target_long bios_size = FLASH_SIZE;
-    int64_t kernel_entry;
-    PCIBus *pci_bus;
-    ISABus *isa_bus;
-    MIPSCPU *cpu;
-    CPUMIPSState *env;
-    qemu_irq *isa_irq;
-    qemu_irq *cpu_exit_irq;
-    int piix4_devfn;
-    i2c_bus *smbus;
-    int i;
-    DriveInfo *dinfo;
-    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    DriveInfo *fd[MAX_FD];
-    int fl_idx = 0;
-    int fl_sectors = bios_size >> 16;
-    int be;
-
-    DeviceState *dev = qdev_create(NULL, "mips-malta");
-    MaltaState *s = DO_UPCAST(MaltaState, busdev.qdev, dev);
-
-    qdev_init_nofail(dev);
-
-    /* Make sure the first 3 serial ports are associated with a device. */
-    for(i = 0; i < 3; i++) {
-        if (!serial_hds[i]) {
-            char label[32];
-            snprintf(label, sizeof(label), "serial%d", i);
-            serial_hds[i] = qemu_chr_new(label, "null", NULL);
-        }
-    }
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-#ifdef TARGET_MIPS64
-        cpu_model = "20Kc";
-#else
-        cpu_model = "24Kf";
-#endif
-    }
-
-    for (i = 0; i < smp_cpus; i++) {
-        cpu = cpu_mips_init(cpu_model);
-        if (cpu == NULL) {
-            fprintf(stderr, "Unable to find CPU definition\n");
-            exit(1);
-        }
-        env = &cpu->env;
-
-        /* Init internal devices */
-        cpu_mips_irq_init_cpu(env);
-        cpu_mips_clock_init(env);
-        qemu_register_reset(main_cpu_reset, cpu);
-    }
-    env = first_cpu;
-
-    /* allocate RAM */
-    if (ram_size > (256 << 20)) {
-        fprintf(stderr,
-                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
-                ((unsigned int)ram_size / (1 << 20)));
-        exit(1);
-    }
-    memory_region_init_ram(ram, "mips_malta.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(system_memory, 0, ram);
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
-#else
-    be = 0;
-#endif
-    /* FPGA */
-    /* The CBUS UART is attached to the MIPS CPU INT2 pin, ie interrupt 4 */
-    malta_fpga_init(system_memory, FPGA_ADDRESS, env->irq[4], serial_hds[2]);
-
-    /* Load firmware in flash / BIOS. */
-    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
-#ifdef DEBUG_BOARD_INIT
-    if (dinfo) {
-        printf("Register parallel flash %d size " TARGET_FMT_lx " at "
-               "addr %08llx '%s' %x\n",
-               fl_idx, bios_size, FLASH_ADDRESS,
-               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
-    }
-#endif
-    fl = pflash_cfi01_register(FLASH_ADDRESS, NULL, "mips_malta.bios",
-                               BIOS_SIZE, dinfo ? dinfo->bdrv : NULL,
-                               65536, fl_sectors,
-                               4, 0x0000, 0x0000, 0x0000, 0x0000, be);
-    bios = pflash_cfi01_get_memory(fl);
-    fl_idx++;
-    if (kernel_filename) {
-        /* Write a small bootloader to the flash location. */
-        loaderparams.ram_size = ram_size;
-        loaderparams.kernel_filename = kernel_filename;
-        loaderparams.kernel_cmdline = kernel_cmdline;
-        loaderparams.initrd_filename = initrd_filename;
-        kernel_entry = load_kernel();
-        write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
-    } else {
-        /* Load firmware from flash. */
-        if (!dinfo) {
-            /* Load a BIOS image. */
-            if (bios_name == NULL) {
-                bios_name = BIOS_FILENAME;
-            }
-            filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-            if (filename) {
-                bios_size = load_image_targphys(filename, FLASH_ADDRESS,
-                                                BIOS_SIZE);
-                g_free(filename);
-            } else {
-                bios_size = -1;
-            }
-            if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
-                fprintf(stderr,
-                        "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
-                        bios_name);
-                exit(1);
-            }
-        }
-        /* In little endian mode the 32bit words in the bios are swapped,
-           a neat trick which allows bi-endian firmware. */
-#ifndef TARGET_WORDS_BIGENDIAN
-        {
-            uint32_t *addr = memory_region_get_ram_ptr(bios);
-            uint32_t *end = addr + bios_size;
-            while (addr < end) {
-                bswap32s(addr);
-                addr++;
-            }
-        }
-#endif
-    }
-
-    /* Map the BIOS at a 2nd physical location, as on the real board. */
-    memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
-    memory_region_add_subregion(system_memory, RESET_ADDRESS, bios_alias);
-
-    /* Board ID = 0x420 (Malta Board with CoreLV)
-       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
-       map to the board ID. */
-    stl_p(memory_region_get_ram_ptr(bios) + 0x10, 0x00000420);
-
-    /* Init internal devices */
-    cpu_mips_irq_init_cpu(env);
-    cpu_mips_clock_init(env);
-
-    /*
-     * We have a circular dependency problem: pci_bus depends on isa_irq,
-     * isa_irq is provided by i8259, i8259 depends on ISA, ISA depends
-     * on piix4, and piix4 depends on pci_bus.  To stop the cycle we have
-     * qemu_irq_proxy() adds an extra bit of indirection, allowing us
-     * to resolve the isa_irq -> i8259 dependency after i8259 is initialized.
-     */
-    isa_irq = qemu_irq_proxy(&s->i8259, 16);
-
-    /* Northbridge */
-    pci_bus = gt64120_register(isa_irq);
-
-    /* Southbridge */
-    ide_drive_get(hd, MAX_IDE_BUS);
-
-    piix4_devfn = piix4_init(pci_bus, &isa_bus, 80);
-
-    /* Interrupt controller */
-    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
-    s->i8259 = i8259_init(isa_bus, env->irq[2]);
-
-    isa_bus_irqs(isa_bus, s->i8259);
-    pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
-    pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci");
-    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
-                          isa_get_irq(NULL, 9), NULL, 0, NULL);
-    /* TODO: Populate SPD eeprom data.  */
-    smbus_eeprom_init(smbus, 8, NULL, 0);
-    pit = pit_init(isa_bus, 0x40, 0, NULL);
-    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
-    DMA_init(0, cpu_exit_irq);
-
-    /* Super I/O */
-    isa_create_simple(isa_bus, "i8042");
-
-    rtc_init(isa_bus, 2000, NULL);
-    serial_isa_init(isa_bus, 0, serial_hds[0]);
-    serial_isa_init(isa_bus, 1, serial_hds[1]);
-    if (parallel_hds[0])
-        parallel_init(isa_bus, 0, parallel_hds[0]);
-    for(i = 0; i < MAX_FD; i++) {
-        fd[i] = drive_get(IF_FLOPPY, 0, i);
-    }
-    fdctrl_init_isa(isa_bus, fd);
-
-    /* Sound card */
-    audio_init(isa_bus, pci_bus);
-
-    /* Network card */
-    network_init();
-
-    /* Optional PCI video card */
-    pci_vga_init(pci_bus);
-}
-
-static int mips_malta_sysbus_device_init(SysBusDevice *sysbusdev)
-{
-    return 0;
-}
-
-static void mips_malta_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = mips_malta_sysbus_device_init;
-}
-
-static const TypeInfo mips_malta_device = {
-    .name          = "mips-malta",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(MaltaState),
-    .class_init    = mips_malta_class_init,
-};
-
-static QEMUMachine mips_malta_machine = {
-    .name = "malta",
-    .desc = "MIPS Malta Core LV",
-    .init = mips_malta_init,
-    .max_cpus = 16,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void mips_malta_register_types(void)
-{
-    type_register_static(&mips_malta_device);
-}
-
-static void mips_malta_machine_init(void)
-{
-    qemu_register_machine(&mips_malta_machine);
-}
-
-type_init(mips_malta_register_types)
-machine_init(mips_malta_machine_init);
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
deleted file mode 100644
index 4935c78..0000000
--- a/hw/mips_mipssim.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * QEMU/mipssim emulation
- *
- * Emulates a very simple machine model similar to the one used by the
- * proprietary MIPS emulator.
- * 
- * Copyright (c) 2007 Thiemo Seufer
- *
- * 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/hw.h"
-#include "hw/mips.h"
-#include "hw/mips_cpudevs.h"
-#include "hw/serial.h"
-#include "hw/isa.h"
-#include "net/net.h"
-#include "sysemu/sysemu.h"
-#include "hw/boards.h"
-#include "hw/mips-bios.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "hw/sysbus.h"
-#include "exec/address-spaces.h"
-
-static struct _loaderparams {
-    int ram_size;
-    const char *kernel_filename;
-    const char *kernel_cmdline;
-    const char *initrd_filename;
-} loaderparams;
-
-typedef struct ResetData {
-    MIPSCPU *cpu;
-    uint64_t vector;
-} ResetData;
-
-static int64_t load_kernel(void)
-{
-    int64_t entry, kernel_high;
-    long kernel_size;
-    long initrd_size;
-    ram_addr_t initrd_offset;
-    int big_endian;
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    big_endian = 1;
-#else
-    big_endian = 0;
-#endif
-
-    kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
-                           NULL, (uint64_t *)&entry, NULL,
-                           (uint64_t *)&kernel_high, big_endian,
-                           ELF_MACHINE, 1);
-    if (kernel_size >= 0) {
-        if ((entry & ~0x7fffffffULL) == 0x80000000)
-            entry = (int32_t)entry;
-    } else {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                loaderparams.kernel_filename);
-        exit(1);
-    }
-
-    /* load initrd */
-    initrd_size = 0;
-    initrd_offset = 0;
-    if (loaderparams.initrd_filename) {
-        initrd_size = get_image_size (loaderparams.initrd_filename);
-        if (initrd_size > 0) {
-            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
-            if (initrd_offset + initrd_size > loaderparams.ram_size) {
-                fprintf(stderr,
-                        "qemu: memory too small for initial ram disk '%s'\n",
-                        loaderparams.initrd_filename);
-                exit(1);
-            }
-            initrd_size = load_image_targphys(loaderparams.initrd_filename,
-                initrd_offset, loaderparams.ram_size - initrd_offset);
-        }
-        if (initrd_size == (target_ulong) -1) {
-            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
-                    loaderparams.initrd_filename);
-            exit(1);
-        }
-    }
-    return entry;
-}
-
-static void main_cpu_reset(void *opaque)
-{
-    ResetData *s = (ResetData *)opaque;
-    CPUMIPSState *env = &s->cpu->env;
-
-    cpu_reset(CPU(s->cpu));
-    env->active_tc.PC = s->vector & ~(target_ulong)1;
-    if (s->vector & 1) {
-        env->hflags |= MIPS_HFLAG_M16;
-    }
-}
-
-static void mipsnet_init(int base, qemu_irq irq, NICInfo *nd)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "mipsnet");
-    qdev_set_nic_properties(dev, nd);
-    qdev_init_nofail(dev);
-
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_connect_irq(s, 0, irq);
-    memory_region_add_subregion(get_system_io(),
-                                base,
-                                sysbus_mmio_get_region(s, 0));
-}
-
-static void
-mips_mipssim_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    char *filename;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *bios = g_new(MemoryRegion, 1);
-    MIPSCPU *cpu;
-    CPUMIPSState *env;
-    ResetData *reset_info;
-    int bios_size;
-
-    /* Init CPUs. */
-    if (cpu_model == NULL) {
-#ifdef TARGET_MIPS64
-        cpu_model = "5Kf";
-#else
-        cpu_model = "24Kf";
-#endif
-    }
-    cpu = cpu_mips_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    reset_info = g_malloc0(sizeof(ResetData));
-    reset_info->cpu = cpu;
-    reset_info->vector = env->active_tc.PC;
-    qemu_register_reset(main_cpu_reset, reset_info);
-
-    /* Allocate RAM. */
-    memory_region_init_ram(ram, "mips_mipssim.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_init_ram(bios, "mips_mipssim.bios", BIOS_SIZE);
-    vmstate_register_ram_global(bios);
-    memory_region_set_readonly(bios, true);
-
-    memory_region_add_subregion(address_space_mem, 0, ram);
-
-    /* Map the BIOS / boot exception handler. */
-    memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
-    /* Load a BIOS / boot exception handler image. */
-    if (bios_name == NULL)
-        bios_name = BIOS_FILENAME;
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-    if (filename) {
-        bios_size = load_image_targphys(filename, 0x1fc00000LL, BIOS_SIZE);
-        g_free(filename);
-    } else {
-        bios_size = -1;
-    }
-    if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
-        /* Bail out if we have neither a kernel image nor boot vector code. */
-        fprintf(stderr,
-                "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
-                filename);
-        exit(1);
-    } else {
-        /* We have a boot vector start address. */
-        env->active_tc.PC = (target_long)(int32_t)0xbfc00000;
-    }
-
-    if (kernel_filename) {
-        loaderparams.ram_size = ram_size;
-        loaderparams.kernel_filename = kernel_filename;
-        loaderparams.kernel_cmdline = kernel_cmdline;
-        loaderparams.initrd_filename = initrd_filename;
-        reset_info->vector = load_kernel();
-    }
-
-    /* Init CPU internal devices. */
-    cpu_mips_irq_init_cpu(env);
-    cpu_mips_clock_init(env);
-
-    /* Register 64 KB of ISA IO space at 0x1fd00000. */
-    isa_mmio_init(0x1fd00000, 0x00010000);
-
-    /* A single 16450 sits at offset 0x3f8. It is attached to
-       MIPS CPU INT2, which is interrupt 4. */
-    if (serial_hds[0])
-        serial_init(0x3f8, env->irq[4], 115200, serial_hds[0],
-                    get_system_io());
-
-    if (nd_table[0].used)
-        /* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */
-        mipsnet_init(0x4200, env->irq[2], &nd_table[0]);
-}
-
-static QEMUMachine mips_mipssim_machine = {
-    .name = "mipssim",
-    .desc = "MIPS MIPSsim platform",
-    .init = mips_mipssim_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void mips_mipssim_machine_init(void)
-{
-    qemu_register_machine(&mips_mipssim_machine);
-}
-
-machine_init(mips_mipssim_machine_init);
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
deleted file mode 100644
index 539a562..0000000
--- a/hw/mips_r4k.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * QEMU/MIPS pseudo-board
- *
- * emulates a simple machine with ISA-like bus.
- * ISA IO space mapped to the 0x14000000 (PHYS) and
- * ISA memory at the 0x10000000 (PHYS, 16Mb in size).
- * All peripherial devices are attached to this "bus" with
- * the standard PC ISA addresses.
-*/
-#include "hw/hw.h"
-#include "hw/mips.h"
-#include "hw/mips_cpudevs.h"
-#include "hw/pc.h"
-#include "hw/serial.h"
-#include "hw/isa.h"
-#include "net/net.h"
-#include "sysemu/sysemu.h"
-#include "hw/boards.h"
-#include "hw/flash.h"
-#include "qemu/log.h"
-#include "hw/mips-bios.h"
-#include "hw/ide.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "hw/mc146818rtc.h"
-#include "hw/i8254.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-#define MAX_IDE_BUS 2
-
-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 ISADevice *pit; /* PIT i8254 */
-
-/* i8254 PIT is attached to the IRQ0 at PIC i8259 */
-
-static struct _loaderparams {
-    int ram_size;
-    const char *kernel_filename;
-    const char *kernel_cmdline;
-    const char *initrd_filename;
-} loaderparams;
-
-static void mips_qemu_write (void *opaque, hwaddr addr,
-                             uint64_t val, unsigned size)
-{
-    if ((addr & 0xffff) == 0 && val == 42)
-        qemu_system_reset_request ();
-    else if ((addr & 0xffff) == 4 && val == 42)
-        qemu_system_shutdown_request ();
-}
-
-static uint64_t mips_qemu_read (void *opaque, hwaddr addr,
-                                unsigned size)
-{
-    return 0;
-}
-
-static const MemoryRegionOps mips_qemu_ops = {
-    .read = mips_qemu_read,
-    .write = mips_qemu_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-typedef struct ResetData {
-    MIPSCPU *cpu;
-    uint64_t vector;
-} ResetData;
-
-static int64_t load_kernel(void)
-{
-    int64_t entry, kernel_high;
-    long kernel_size, initrd_size, params_size;
-    ram_addr_t initrd_offset;
-    uint32_t *params_buf;
-    int big_endian;
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    big_endian = 1;
-#else
-    big_endian = 0;
-#endif
-    kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
-                           NULL, (uint64_t *)&entry, NULL,
-                           (uint64_t *)&kernel_high, big_endian,
-                           ELF_MACHINE, 1);
-    if (kernel_size >= 0) {
-        if ((entry & ~0x7fffffffULL) == 0x80000000)
-            entry = (int32_t)entry;
-    } else {
-        fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                loaderparams.kernel_filename);
-        exit(1);
-    }
-
-    /* load initrd */
-    initrd_size = 0;
-    initrd_offset = 0;
-    if (loaderparams.initrd_filename) {
-        initrd_size = get_image_size (loaderparams.initrd_filename);
-        if (initrd_size > 0) {
-            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
-            if (initrd_offset + initrd_size > ram_size) {
-                fprintf(stderr,
-                        "qemu: memory too small for initial ram disk '%s'\n",
-                        loaderparams.initrd_filename);
-                exit(1);
-            }
-            initrd_size = load_image_targphys(loaderparams.initrd_filename,
-                                              initrd_offset,
-                                              ram_size - initrd_offset);
-        }
-        if (initrd_size == (target_ulong) -1) {
-            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
-                    loaderparams.initrd_filename);
-            exit(1);
-        }
-    }
-
-    /* Store command line.  */
-    params_size = 264;
-    params_buf = g_malloc(params_size);
-
-    params_buf[0] = tswap32(ram_size);
-    params_buf[1] = tswap32(0x12345678);
-
-    if (initrd_size > 0) {
-        snprintf((char *)params_buf + 8, 256, "rd_start=0x%" PRIx64 " rd_size=%li %s",
-                 cpu_mips_phys_to_kseg0(NULL, initrd_offset),
-                 initrd_size, loaderparams.kernel_cmdline);
-    } else {
-        snprintf((char *)params_buf + 8, 256, "%s", loaderparams.kernel_cmdline);
-    }
-
-    rom_add_blob_fixed("params", params_buf, params_size,
-                       (16 << 20) - 264);
-
-    return entry;
-}
-
-static void main_cpu_reset(void *opaque)
-{
-    ResetData *s = (ResetData *)opaque;
-    CPUMIPSState *env = &s->cpu->env;
-
-    cpu_reset(CPU(s->cpu));
-    env->active_tc.PC = s->vector;
-}
-
-static const int sector_len = 32 * 1024;
-static
-void mips_r4k_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    char *filename;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *bios;
-    MemoryRegion *iomem = g_new(MemoryRegion, 1);
-    int bios_size;
-    MIPSCPU *cpu;
-    CPUMIPSState *env;
-    ResetData *reset_info;
-    int i;
-    qemu_irq *i8259;
-    ISABus *isa_bus;
-    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    DriveInfo *dinfo;
-    int be;
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-#ifdef TARGET_MIPS64
-        cpu_model = "R4000";
-#else
-        cpu_model = "24Kf";
-#endif
-    }
-    cpu = cpu_mips_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    reset_info = g_malloc0(sizeof(ResetData));
-    reset_info->cpu = cpu;
-    reset_info->vector = env->active_tc.PC;
-    qemu_register_reset(main_cpu_reset, reset_info);
-
-    /* allocate RAM */
-    if (ram_size > (256 << 20)) {
-        fprintf(stderr,
-                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
-                ((unsigned int)ram_size / (1 << 20)));
-        exit(1);
-    }
-    memory_region_init_ram(ram, "mips_r4k.ram", ram_size);
-    vmstate_register_ram_global(ram);
-
-    memory_region_add_subregion(address_space_mem, 0, ram);
-
-    memory_region_init_io(iomem, &mips_qemu_ops, NULL, "mips-qemu", 0x10000);
-    memory_region_add_subregion(address_space_mem, 0x1fbf0000, iomem);
-
-    /* Try to load a BIOS image. If this fails, we continue regardless,
-       but initialize the hardware ourselves. When a kernel gets
-       preloaded we also initialize the hardware, since the BIOS wasn't
-       run. */
-    if (bios_name == NULL)
-        bios_name = BIOS_FILENAME;
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-    if (filename) {
-        bios_size = get_image_size(filename);
-    } else {
-        bios_size = -1;
-    }
-#ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
-#else
-    be = 0;
-#endif
-    if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
-        bios = g_new(MemoryRegion, 1);
-        memory_region_init_ram(bios, "mips_r4k.bios", BIOS_SIZE);
-        vmstate_register_ram_global(bios);
-        memory_region_set_readonly(bios, true);
-        memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios);
-
-        load_image_targphys(filename, 0x1fc00000, BIOS_SIZE);
-    } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
-        uint32_t mips_rom = 0x00400000;
-        if (!pflash_cfi01_register(0x1fc00000, NULL, "mips_r4k.bios", mips_rom,
-                                   dinfo->bdrv, sector_len,
-                                   mips_rom / sector_len,
-                                   4, 0, 0, 0, 0, be)) {
-            fprintf(stderr, "qemu: Error registering flash memory.\n");
-	}
-    }
-    else {
-	/* not fatal */
-        fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
-		bios_name);
-    }
-    if (filename) {
-        g_free(filename);
-    }
-
-    if (kernel_filename) {
-        loaderparams.ram_size = ram_size;
-        loaderparams.kernel_filename = kernel_filename;
-        loaderparams.kernel_cmdline = kernel_cmdline;
-        loaderparams.initrd_filename = initrd_filename;
-        reset_info->vector = load_kernel();
-    }
-
-    /* Init CPU internal devices */
-    cpu_mips_irq_init_cpu(env);
-    cpu_mips_clock_init(env);
-
-    /* The PIC is attached to the MIPS CPU INT0 pin */
-    isa_bus = isa_bus_new(NULL, get_system_io());
-    i8259 = i8259_init(isa_bus, env->irq[2]);
-    isa_bus_irqs(isa_bus, i8259);
-
-    rtc_init(isa_bus, 2000, NULL);
-
-    /* Register 64 KB of ISA IO space at 0x14000000 */
-    isa_mmio_init(0x14000000, 0x00010000);
-    isa_mem_base = 0x10000000;
-
-    pit = pit_init(isa_bus, 0x40, 0, NULL);
-
-    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
-        if (serial_hds[i]) {
-            serial_isa_init(isa_bus, i, serial_hds[i]);
-        }
-    }
-
-    isa_vga_init(isa_bus);
-
-    if (nd_table[0].used)
-        isa_ne2000_init(isa_bus, 0x300, 9, &nd_table[0]);
-
-    ide_drive_get(hd, MAX_IDE_BUS);
-    for(i = 0; i < MAX_IDE_BUS; i++)
-        isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i],
-                     hd[MAX_IDE_DEVS * i],
-		     hd[MAX_IDE_DEVS * i + 1]);
-
-    isa_create_simple(isa_bus, "i8042");
-}
-
-static QEMUMachine mips_machine = {
-    .name = "mips",
-    .desc = "mips r4k platform",
-    .init = mips_r4k_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void mips_machine_init(void)
-{
-    qemu_register_machine(&mips_machine);
-}
-
-machine_init(mips_machine_init);
diff --git a/hw/mips_timer.c b/hw/mips_timer.c
deleted file mode 100644
index 9ad13f3..0000000
--- a/hw/mips_timer.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * QEMU MIPS timer support
- *
- * 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/hw.h"
-#include "hw/mips_cpudevs.h"
-#include "qemu/timer.h"
-
-#define TIMER_FREQ	100 * 1000 * 1000
-
-/* XXX: do not use a global */
-uint32_t cpu_mips_get_random (CPUMIPSState *env)
-{
-    static uint32_t lfsr = 1;
-    static uint32_t prev_idx = 0;
-    uint32_t idx;
-    /* Don't return same value twice, so get another value */
-    do {
-        lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u);
-        idx = lfsr % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
-    } while (idx == prev_idx);
-    prev_idx = idx;
-    return idx;
-}
-
-/* MIPS R4K timer */
-static void cpu_mips_timer_update(CPUMIPSState *env)
-{
-    uint64_t now, next;
-    uint32_t wait;
-
-    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);
-    qemu_mod_timer(env->timer, next);
-}
-
-/* Expire the timer.  */
-static void cpu_mips_timer_expire(CPUMIPSState *env)
-{
-    cpu_mips_timer_update(env);
-    if (env->insn_flags & ISA_MIPS32R2) {
-        env->CP0_Cause |= 1 << CP0Ca_TI;
-    }
-    qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
-}
-
-uint32_t cpu_mips_get_count (CPUMIPSState *env)
-{
-    if (env->CP0_Cause & (1 << CP0Ca_DC)) {
-        return env->CP0_Count;
-    } else {
-        uint64_t now;
-
-        now = qemu_get_clock_ns(vm_clock);
-        if (qemu_timer_pending(env->timer)
-            && qemu_timer_expired(env->timer, now)) {
-            /* The timer has already expired.  */
-            cpu_mips_timer_expire(env);
-        }
-
-        return env->CP0_Count +
-            (uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec());
-    }
-}
-
-void cpu_mips_store_count (CPUMIPSState *env, uint32_t count)
-{
-    if (env->CP0_Cause & (1 << CP0Ca_DC))
-        env->CP0_Count = count;
-    else {
-        /* Store new count register */
-        env->CP0_Count =
-            count - (uint32_t)muldiv64(qemu_get_clock_ns(vm_clock),
-                                       TIMER_FREQ, get_ticks_per_sec());
-        /* Update timer timer */
-        cpu_mips_timer_update(env);
-    }
-}
-
-void cpu_mips_store_compare (CPUMIPSState *env, uint32_t value)
-{
-    env->CP0_Compare = value;
-    if (!(env->CP0_Cause & (1 << CP0Ca_DC)))
-        cpu_mips_timer_update(env);
-    if (env->insn_flags & ISA_MIPS32R2)
-        env->CP0_Cause &= ~(1 << CP0Ca_TI);
-    qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
-}
-
-void cpu_mips_start_count(CPUMIPSState *env)
-{
-    cpu_mips_store_count(env, env->CP0_Count);
-}
-
-void cpu_mips_stop_count(CPUMIPSState *env)
-{
-    /* Store the current value */
-    env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock_ns(vm_clock),
-                                         TIMER_FREQ, get_ticks_per_sec());
-}
-
-static void mips_timer_cb (void *opaque)
-{
-    CPUMIPSState *env;
-
-    env = opaque;
-#if 0
-    qemu_log("%s\n", __func__);
-#endif
-
-    if (env->CP0_Cause & (1 << CP0Ca_DC))
-        return;
-
-    /* ??? This callback should occur when the counter is exactly equal to
-       the comparator value.  Offset the count by one to avoid immediately
-       retriggering the callback before any virtual time has passed.  */
-    env->CP0_Count++;
-    cpu_mips_timer_expire(env);
-    env->CP0_Count--;
-}
-
-void cpu_mips_clock_init (CPUMIPSState *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/multiboot.c b/hw/multiboot.c
deleted file mode 100644
index 3cb228f..0000000
--- a/hw/multiboot.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * QEMU PC System Emulator
- *
- * Copyright (c) 2003-2004 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 "hw/hw.h"
-#include "hw/fw_cfg.h"
-#include "hw/multiboot.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "sysemu/sysemu.h"
-
-/* Show multiboot debug output */
-//#define DEBUG_MULTIBOOT
-
-#ifdef DEBUG_MULTIBOOT
-#define mb_debug(a...) fprintf(stderr, ## a)
-#else
-#define mb_debug(a...)
-#endif
-
-#define MULTIBOOT_STRUCT_ADDR 0x9000
-
-#if MULTIBOOT_STRUCT_ADDR > 0xf0000
-#error multiboot struct needs to fit in 16 bit real mode
-#endif
-
-enum {
-    /* Multiboot info */
-    MBI_FLAGS       = 0,
-    MBI_MEM_LOWER   = 4,
-    MBI_MEM_UPPER   = 8,
-    MBI_BOOT_DEVICE = 12,
-    MBI_CMDLINE     = 16,
-    MBI_MODS_COUNT  = 20,
-    MBI_MODS_ADDR   = 24,
-    MBI_MMAP_ADDR   = 48,
-
-    MBI_SIZE        = 88,
-
-    /* Multiboot modules */
-    MB_MOD_START    = 0,
-    MB_MOD_END      = 4,
-    MB_MOD_CMDLINE  = 8,
-
-    MB_MOD_SIZE     = 16,
-
-    /* Region offsets */
-    ADDR_E820_MAP = MULTIBOOT_STRUCT_ADDR + 0,
-    ADDR_MBI      = ADDR_E820_MAP + 0x500,
-
-    /* Multiboot flags */
-    MULTIBOOT_FLAGS_MEMORY      = 1 << 0,
-    MULTIBOOT_FLAGS_BOOT_DEVICE = 1 << 1,
-    MULTIBOOT_FLAGS_CMDLINE     = 1 << 2,
-    MULTIBOOT_FLAGS_MODULES     = 1 << 3,
-    MULTIBOOT_FLAGS_MMAP        = 1 << 6,
-};
-
-typedef struct {
-    /* buffer holding kernel, cmdlines and mb_infos */
-    void *mb_buf;
-    /* address in target */
-    hwaddr mb_buf_phys;
-    /* size of mb_buf in bytes */
-    unsigned mb_buf_size;
-    /* offset of mb-info's in bytes */
-    hwaddr offset_mbinfo;
-    /* offset in buffer for cmdlines in bytes */
-    hwaddr offset_cmdlines;
-    /* offset of modules in bytes */
-    hwaddr offset_mods;
-    /* available slots for mb modules infos */
-    int mb_mods_avail;
-    /* currently used slots of mb modules */
-    int mb_mods_count;
-} MultibootState;
-
-static uint32_t mb_add_cmdline(MultibootState *s, const char *cmdline)
-{
-    hwaddr p = s->offset_cmdlines;
-    char *b = (char *)s->mb_buf + p;
-
-    get_opt_value(b, strlen(cmdline) + 1, cmdline);
-    s->offset_cmdlines += strlen(b) + 1;
-    return s->mb_buf_phys + p;
-}
-
-static void mb_add_mod(MultibootState *s,
-                       hwaddr start, hwaddr end,
-                       hwaddr cmdline_phys)
-{
-    char *p;
-    assert(s->mb_mods_count < s->mb_mods_avail);
-
-    p = (char *)s->mb_buf + s->offset_mbinfo + MB_MOD_SIZE * s->mb_mods_count;
-
-    stl_p(p + MB_MOD_START,   start);
-    stl_p(p + MB_MOD_END,     end);
-    stl_p(p + MB_MOD_CMDLINE, cmdline_phys);
-
-    mb_debug("mod%02d: "TARGET_FMT_plx" - "TARGET_FMT_plx"\n",
-             s->mb_mods_count, start, end);
-
-    s->mb_mods_count++;
-}
-
-int load_multiboot(void *fw_cfg,
-                   FILE *f,
-                   const char *kernel_filename,
-                   const char *initrd_filename,
-                   const char *kernel_cmdline,
-                   int kernel_file_size,
-                   uint8_t *header)
-{
-    int i, is_multiboot = 0;
-    uint32_t flags = 0;
-    uint32_t mh_entry_addr;
-    uint32_t mh_load_addr;
-    uint32_t mb_kernel_size;
-    MultibootState mbs;
-    uint8_t bootinfo[MBI_SIZE];
-    uint8_t *mb_bootinfo_data;
-
-    /* Ok, let's see if it is a multiboot image.
-       The header is 12x32bit long, so the latest entry may be 8192 - 48. */
-    for (i = 0; i < (8192 - 48); i += 4) {
-        if (ldl_p(header+i) == 0x1BADB002) {
-            uint32_t checksum = ldl_p(header+i+8);
-            flags = ldl_p(header+i+4);
-            checksum += flags;
-            checksum += (uint32_t)0x1BADB002;
-            if (!checksum) {
-                is_multiboot = 1;
-                break;
-            }
-        }
-    }
-
-    if (!is_multiboot)
-        return 0; /* no multiboot */
-
-    mb_debug("qemu: I believe we found a multiboot image!\n");
-    memset(bootinfo, 0, sizeof(bootinfo));
-    memset(&mbs, 0, sizeof(mbs));
-
-    if (flags & 0x00000004) { /* MULTIBOOT_HEADER_HAS_VBE */
-        fprintf(stderr, "qemu: multiboot knows VBE. we don't.\n");
-    }
-    if (!(flags & 0x00010000)) { /* MULTIBOOT_HEADER_HAS_ADDR */
-        uint64_t elf_entry;
-        uint64_t elf_low, elf_high;
-        int kernel_size;
-        fclose(f);
-
-        if (((struct elf64_hdr*)header)->e_machine == EM_X86_64) {
-            fprintf(stderr, "Cannot load x86-64 image, give a 32bit one.\n");
-            exit(1);
-        }
-
-        kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                               &elf_low, &elf_high, 0, ELF_MACHINE, 0);
-        if (kernel_size < 0) {
-            fprintf(stderr, "Error while loading elf kernel\n");
-            exit(1);
-        }
-        mh_load_addr = elf_low;
-        mb_kernel_size = elf_high - elf_low;
-        mh_entry_addr = elf_entry;
-
-        mbs.mb_buf = g_malloc(mb_kernel_size);
-        if (rom_copy(mbs.mb_buf, mh_load_addr, mb_kernel_size) != mb_kernel_size) {
-            fprintf(stderr, "Error while fetching elf kernel from rom\n");
-            exit(1);
-        }
-
-        mb_debug("qemu: loading multiboot-elf kernel (%#x bytes) with entry %#zx\n",
-                  mb_kernel_size, (size_t)mh_entry_addr);
-    } else {
-        /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_ADDR. */
-        uint32_t mh_header_addr = ldl_p(header+i+12);
-        uint32_t mh_load_end_addr = ldl_p(header+i+20);
-        uint32_t mh_bss_end_addr = ldl_p(header+i+24);
-        mh_load_addr = ldl_p(header+i+16);
-        uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr);
-        uint32_t mb_load_size = 0;
-        mh_entry_addr = ldl_p(header+i+28);
-
-        if (mh_load_end_addr) {
-            mb_kernel_size = mh_bss_end_addr - mh_load_addr;
-            mb_load_size = mh_load_end_addr - mh_load_addr;
-        } else {
-            mb_kernel_size = kernel_file_size - mb_kernel_text_offset;
-            mb_load_size = mb_kernel_size;
-        }
-
-        /* Valid if mh_flags sets MULTIBOOT_HEADER_HAS_VBE.
-        uint32_t mh_mode_type = ldl_p(header+i+32);
-        uint32_t mh_width = ldl_p(header+i+36);
-        uint32_t mh_height = ldl_p(header+i+40);
-        uint32_t mh_depth = ldl_p(header+i+44); */
-
-        mb_debug("multiboot: mh_header_addr = %#x\n", mh_header_addr);
-        mb_debug("multiboot: mh_load_addr = %#x\n", mh_load_addr);
-        mb_debug("multiboot: mh_load_end_addr = %#x\n", mh_load_end_addr);
-        mb_debug("multiboot: mh_bss_end_addr = %#x\n", mh_bss_end_addr);
-        mb_debug("qemu: loading multiboot kernel (%#x bytes) at %#x\n",
-                 mb_load_size, mh_load_addr);
-
-        mbs.mb_buf = g_malloc(mb_kernel_size);
-        fseek(f, mb_kernel_text_offset, SEEK_SET);
-        if (fread(mbs.mb_buf, 1, mb_load_size, f) != mb_load_size) {
-            fprintf(stderr, "fread() failed\n");
-            exit(1);
-        }
-        memset(mbs.mb_buf + mb_load_size, 0, mb_kernel_size - mb_load_size);
-        fclose(f);
-    }
-
-    mbs.mb_buf_phys = mh_load_addr;
-
-    mbs.mb_buf_size = TARGET_PAGE_ALIGN(mb_kernel_size);
-    mbs.offset_mbinfo = mbs.mb_buf_size;
-
-    /* Calculate space for cmdlines and mb_mods */
-    mbs.mb_buf_size += strlen(kernel_filename) + 1;
-    mbs.mb_buf_size += strlen(kernel_cmdline) + 1;
-    if (initrd_filename) {
-        const char *r = initrd_filename;
-        mbs.mb_buf_size += strlen(r) + 1;
-        mbs.mb_mods_avail = 1;
-        while (*(r = get_opt_value(NULL, 0, r))) {
-           mbs.mb_mods_avail++;
-           r++;
-        }
-        mbs.mb_buf_size += MB_MOD_SIZE * mbs.mb_mods_avail;
-    }
-
-    mbs.mb_buf_size = TARGET_PAGE_ALIGN(mbs.mb_buf_size);
-
-    /* enlarge mb_buf to hold cmdlines and mb-info structs */
-    mbs.mb_buf          = g_realloc(mbs.mb_buf, mbs.mb_buf_size);
-    mbs.offset_cmdlines = mbs.offset_mbinfo + mbs.mb_mods_avail * MB_MOD_SIZE;
-
-    if (initrd_filename) {
-        char *next_initrd, not_last;
-
-        mbs.offset_mods = mbs.mb_buf_size;
-
-        do {
-            char *next_space;
-            int mb_mod_length;
-            uint32_t offs = mbs.mb_buf_size;
-
-            next_initrd = (char *)get_opt_value(NULL, 0, initrd_filename);
-            not_last = *next_initrd;
-            *next_initrd = '\0';
-            /* if a space comes after the module filename, treat everything
-               after that as parameters */
-            hwaddr c = mb_add_cmdline(&mbs, initrd_filename);
-            if ((next_space = strchr(initrd_filename, ' ')))
-                *next_space = '\0';
-            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 open file '%s'\n", initrd_filename);
-                exit(1);
-            }
-
-            mbs.mb_buf_size = TARGET_PAGE_ALIGN(mb_mod_length + mbs.mb_buf_size);
-            mbs.mb_buf = g_realloc(mbs.mb_buf, mbs.mb_buf_size);
-
-            load_image(initrd_filename, (unsigned char *)mbs.mb_buf + offs);
-            mb_add_mod(&mbs, mbs.mb_buf_phys + offs,
-                       mbs.mb_buf_phys + offs + mb_mod_length, c);
-
-            mb_debug("mod_start: %p\nmod_end:   %p\n  cmdline: "TARGET_FMT_plx"\n",
-                     (char *)mbs.mb_buf + offs,
-                     (char *)mbs.mb_buf + offs + mb_mod_length, c);
-            initrd_filename = next_initrd+1;
-        } while (not_last);
-    }
-
-    /* Commandline support */
-    char kcmdline[strlen(kernel_filename) + strlen(kernel_cmdline) + 2];
-    snprintf(kcmdline, sizeof(kcmdline), "%s %s",
-             kernel_filename, kernel_cmdline);
-    stl_p(bootinfo + MBI_CMDLINE, mb_add_cmdline(&mbs, kcmdline));
-
-    stl_p(bootinfo + MBI_MODS_ADDR,  mbs.mb_buf_phys + mbs.offset_mbinfo);
-    stl_p(bootinfo + MBI_MODS_COUNT, mbs.mb_mods_count); /* mods_count */
-
-    /* the kernel is where we want it to be now */
-    stl_p(bootinfo + MBI_FLAGS, MULTIBOOT_FLAGS_MEMORY
-                                | MULTIBOOT_FLAGS_BOOT_DEVICE
-                                | MULTIBOOT_FLAGS_CMDLINE
-                                | MULTIBOOT_FLAGS_MODULES
-                                | MULTIBOOT_FLAGS_MMAP);
-    stl_p(bootinfo + MBI_MEM_LOWER,   640);
-    stl_p(bootinfo + MBI_MEM_UPPER,   (ram_size / 1024) - 1024);
-    stl_p(bootinfo + MBI_BOOT_DEVICE, 0x8000ffff); /* XXX: use the -boot switch? */
-    stl_p(bootinfo + MBI_MMAP_ADDR,   ADDR_E820_MAP);
-
-    mb_debug("multiboot: mh_entry_addr = %#x\n", mh_entry_addr);
-    mb_debug("           mb_buf_phys   = "TARGET_FMT_plx"\n", mbs.mb_buf_phys);
-    mb_debug("           mod_start     = "TARGET_FMT_plx"\n", mbs.mb_buf_phys + mbs.offset_mods);
-    mb_debug("           mb_mods_count = %d\n", mbs.mb_mods_count);
-
-    /* save bootinfo off the stack */
-    mb_bootinfo_data = g_malloc(sizeof(bootinfo));
-    memcpy(mb_bootinfo_data, bootinfo, sizeof(bootinfo));
-
-    /* Pass variables to option rom */
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ENTRY, mh_entry_addr);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, mh_load_addr);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, mbs.mb_buf_size);
-    fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA,
-                     mbs.mb_buf, mbs.mb_buf_size);
-
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, ADDR_MBI);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, sizeof(bootinfo));
-    fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, mb_bootinfo_data,
-                     sizeof(bootinfo));
-
-    option_rom[nb_option_roms].name = "multiboot.bin";
-    option_rom[nb_option_roms].bootindex = 0;
-    nb_option_roms++;
-
-    return 1; /* yes, we are multiboot */
-}
diff --git a/hw/musicpal.c b/hw/musicpal.c
deleted file mode 100644
index a37dbd7..0000000
--- a/hw/musicpal.c
+++ /dev/null
@@ -1,1697 +0,0 @@
-/*
- * Marvell MV88W8618 / Freecom MusicPal emulation.
- *
- * Copyright (c) 2008 Jan Kiszka
- *
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "hw/sysbus.h"
-#include "hw/arm-misc.h"
-#include "hw/devices.h"
-#include "net/net.h"
-#include "sysemu/sysemu.h"
-#include "hw/boards.h"
-#include "hw/serial.h"
-#include "qemu/timer.h"
-#include "hw/ptimer.h"
-#include "block/block.h"
-#include "hw/flash.h"
-#include "ui/console.h"
-#include "hw/i2c.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-#include "ui/pixel_ops.h"
-
-#define MP_MISC_BASE            0x80002000
-#define MP_MISC_SIZE            0x00001000
-
-#define MP_ETH_BASE             0x80008000
-#define MP_ETH_SIZE             0x00001000
-
-#define MP_WLAN_BASE            0x8000C000
-#define MP_WLAN_SIZE            0x00000800
-
-#define MP_UART1_BASE           0x8000C840
-#define MP_UART2_BASE           0x8000C940
-
-#define MP_GPIO_BASE            0x8000D000
-#define MP_GPIO_SIZE            0x00001000
-
-#define MP_FLASHCFG_BASE        0x90006000
-#define MP_FLASHCFG_SIZE        0x00001000
-
-#define MP_AUDIO_BASE           0x90007000
-
-#define MP_PIC_BASE             0x90008000
-#define MP_PIC_SIZE             0x00001000
-
-#define MP_PIT_BASE             0x90009000
-#define MP_PIT_SIZE             0x00001000
-
-#define MP_LCD_BASE             0x9000c000
-#define MP_LCD_SIZE             0x00001000
-
-#define MP_SRAM_BASE            0xC0000000
-#define MP_SRAM_SIZE            0x00020000
-
-#define MP_RAM_DEFAULT_SIZE     32*1024*1024
-#define MP_FLASH_SIZE_MAX       32*1024*1024
-
-#define MP_TIMER1_IRQ           4
-#define MP_TIMER2_IRQ           5
-#define MP_TIMER3_IRQ           6
-#define MP_TIMER4_IRQ           7
-#define MP_EHCI_IRQ             8
-#define MP_ETH_IRQ              9
-#define MP_UART1_IRQ            11
-#define MP_UART2_IRQ            11
-#define MP_GPIO_IRQ             12
-#define MP_RTC_IRQ              28
-#define MP_AUDIO_IRQ            30
-
-/* Wolfson 8750 I2C address */
-#define MP_WM_ADDR              0x1A
-
-/* Ethernet register offsets */
-#define MP_ETH_SMIR             0x010
-#define MP_ETH_PCXR             0x408
-#define MP_ETH_SDCMR            0x448
-#define MP_ETH_ICR              0x450
-#define MP_ETH_IMR              0x458
-#define MP_ETH_FRDP0            0x480
-#define MP_ETH_FRDP1            0x484
-#define MP_ETH_FRDP2            0x488
-#define MP_ETH_FRDP3            0x48C
-#define MP_ETH_CRDP0            0x4A0
-#define MP_ETH_CRDP1            0x4A4
-#define MP_ETH_CRDP2            0x4A8
-#define MP_ETH_CRDP3            0x4AC
-#define MP_ETH_CTDP0            0x4E0
-#define MP_ETH_CTDP1            0x4E4
-#define MP_ETH_CTDP2            0x4E8
-#define MP_ETH_CTDP3            0x4EC
-
-/* MII PHY access */
-#define MP_ETH_SMIR_DATA        0x0000FFFF
-#define MP_ETH_SMIR_ADDR        0x03FF0000
-#define MP_ETH_SMIR_OPCODE      (1 << 26) /* Read value */
-#define MP_ETH_SMIR_RDVALID     (1 << 27)
-
-/* PHY registers */
-#define MP_ETH_PHY1_BMSR        0x00210000
-#define MP_ETH_PHY1_PHYSID1     0x00410000
-#define MP_ETH_PHY1_PHYSID2     0x00610000
-
-#define MP_PHY_BMSR_LINK        0x0004
-#define MP_PHY_BMSR_AUTONEG     0x0008
-
-#define MP_PHY_88E3015          0x01410E20
-
-/* TX descriptor status */
-#define MP_ETH_TX_OWN           (1 << 31)
-
-/* RX descriptor status */
-#define MP_ETH_RX_OWN           (1 << 31)
-
-/* Interrupt cause/mask bits */
-#define MP_ETH_IRQ_RX_BIT       0
-#define MP_ETH_IRQ_RX           (1 << MP_ETH_IRQ_RX_BIT)
-#define MP_ETH_IRQ_TXHI_BIT     2
-#define MP_ETH_IRQ_TXLO_BIT     3
-
-/* Port config bits */
-#define MP_ETH_PCXR_2BSM_BIT    28 /* 2-byte incoming suffix */
-
-/* SDMA command bits */
-#define MP_ETH_CMD_TXHI         (1 << 23)
-#define MP_ETH_CMD_TXLO         (1 << 22)
-
-typedef struct mv88w8618_tx_desc {
-    uint32_t cmdstat;
-    uint16_t res;
-    uint16_t bytes;
-    uint32_t buffer;
-    uint32_t next;
-} mv88w8618_tx_desc;
-
-typedef struct mv88w8618_rx_desc {
-    uint32_t cmdstat;
-    uint16_t bytes;
-    uint16_t buffer_size;
-    uint32_t buffer;
-    uint32_t next;
-} mv88w8618_rx_desc;
-
-typedef struct mv88w8618_eth_state {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    qemu_irq irq;
-    uint32_t smir;
-    uint32_t icr;
-    uint32_t imr;
-    int mmio_index;
-    uint32_t vlan_header;
-    uint32_t tx_queue[2];
-    uint32_t rx_queue[4];
-    uint32_t frx_queue[4];
-    uint32_t cur_rx[4];
-    NICState *nic;
-    NICConf conf;
-} mv88w8618_eth_state;
-
-static void eth_rx_desc_put(uint32_t addr, mv88w8618_rx_desc *desc)
-{
-    cpu_to_le32s(&desc->cmdstat);
-    cpu_to_le16s(&desc->bytes);
-    cpu_to_le16s(&desc->buffer_size);
-    cpu_to_le32s(&desc->buffer);
-    cpu_to_le32s(&desc->next);
-    cpu_physical_memory_write(addr, (void *)desc, sizeof(*desc));
-}
-
-static void eth_rx_desc_get(uint32_t addr, mv88w8618_rx_desc *desc)
-{
-    cpu_physical_memory_read(addr, (void *)desc, sizeof(*desc));
-    le32_to_cpus(&desc->cmdstat);
-    le16_to_cpus(&desc->bytes);
-    le16_to_cpus(&desc->buffer_size);
-    le32_to_cpus(&desc->buffer);
-    le32_to_cpus(&desc->next);
-}
-
-static int eth_can_receive(NetClientState *nc)
-{
-    return 1;
-}
-
-static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size)
-{
-    mv88w8618_eth_state *s = qemu_get_nic_opaque(nc);
-    uint32_t desc_addr;
-    mv88w8618_rx_desc desc;
-    int i;
-
-    for (i = 0; i < 4; i++) {
-        desc_addr = s->cur_rx[i];
-        if (!desc_addr) {
-            continue;
-        }
-        do {
-            eth_rx_desc_get(desc_addr, &desc);
-            if ((desc.cmdstat & MP_ETH_RX_OWN) && desc.buffer_size >= size) {
-                cpu_physical_memory_write(desc.buffer + s->vlan_header,
-                                          buf, size);
-                desc.bytes = size + s->vlan_header;
-                desc.cmdstat &= ~MP_ETH_RX_OWN;
-                s->cur_rx[i] = desc.next;
-
-                s->icr |= MP_ETH_IRQ_RX;
-                if (s->icr & s->imr) {
-                    qemu_irq_raise(s->irq);
-                }
-                eth_rx_desc_put(desc_addr, &desc);
-                return size;
-            }
-            desc_addr = desc.next;
-        } while (desc_addr != s->rx_queue[i]);
-    }
-    return size;
-}
-
-static void eth_tx_desc_put(uint32_t addr, mv88w8618_tx_desc *desc)
-{
-    cpu_to_le32s(&desc->cmdstat);
-    cpu_to_le16s(&desc->res);
-    cpu_to_le16s(&desc->bytes);
-    cpu_to_le32s(&desc->buffer);
-    cpu_to_le32s(&desc->next);
-    cpu_physical_memory_write(addr, (void *)desc, sizeof(*desc));
-}
-
-static void eth_tx_desc_get(uint32_t addr, mv88w8618_tx_desc *desc)
-{
-    cpu_physical_memory_read(addr, (void *)desc, sizeof(*desc));
-    le32_to_cpus(&desc->cmdstat);
-    le16_to_cpus(&desc->res);
-    le16_to_cpus(&desc->bytes);
-    le32_to_cpus(&desc->buffer);
-    le32_to_cpus(&desc->next);
-}
-
-static void eth_send(mv88w8618_eth_state *s, int queue_index)
-{
-    uint32_t desc_addr = s->tx_queue[queue_index];
-    mv88w8618_tx_desc desc;
-    uint32_t next_desc;
-    uint8_t buf[2048];
-    int len;
-
-    do {
-        eth_tx_desc_get(desc_addr, &desc);
-        next_desc = desc.next;
-        if (desc.cmdstat & MP_ETH_TX_OWN) {
-            len = desc.bytes;
-            if (len < 2048) {
-                cpu_physical_memory_read(desc.buffer, buf, len);
-                qemu_send_packet(qemu_get_queue(s->nic), buf, len);
-            }
-            desc.cmdstat &= ~MP_ETH_TX_OWN;
-            s->icr |= 1 << (MP_ETH_IRQ_TXLO_BIT - queue_index);
-            eth_tx_desc_put(desc_addr, &desc);
-        }
-        desc_addr = next_desc;
-    } while (desc_addr != s->tx_queue[queue_index]);
-}
-
-static uint64_t mv88w8618_eth_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    mv88w8618_eth_state *s = opaque;
-
-    switch (offset) {
-    case MP_ETH_SMIR:
-        if (s->smir & MP_ETH_SMIR_OPCODE) {
-            switch (s->smir & MP_ETH_SMIR_ADDR) {
-            case MP_ETH_PHY1_BMSR:
-                return MP_PHY_BMSR_LINK | MP_PHY_BMSR_AUTONEG |
-                       MP_ETH_SMIR_RDVALID;
-            case MP_ETH_PHY1_PHYSID1:
-                return (MP_PHY_88E3015 >> 16) | MP_ETH_SMIR_RDVALID;
-            case MP_ETH_PHY1_PHYSID2:
-                return (MP_PHY_88E3015 & 0xFFFF) | MP_ETH_SMIR_RDVALID;
-            default:
-                return MP_ETH_SMIR_RDVALID;
-            }
-        }
-        return 0;
-
-    case MP_ETH_ICR:
-        return s->icr;
-
-    case MP_ETH_IMR:
-        return s->imr;
-
-    case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
-        return s->frx_queue[(offset - MP_ETH_FRDP0)/4];
-
-    case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
-        return s->rx_queue[(offset - MP_ETH_CRDP0)/4];
-
-    case MP_ETH_CTDP0 ... MP_ETH_CTDP3:
-        return s->tx_queue[(offset - MP_ETH_CTDP0)/4];
-
-    default:
-        return 0;
-    }
-}
-
-static void mv88w8618_eth_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-    mv88w8618_eth_state *s = opaque;
-
-    switch (offset) {
-    case MP_ETH_SMIR:
-        s->smir = value;
-        break;
-
-    case MP_ETH_PCXR:
-        s->vlan_header = ((value >> MP_ETH_PCXR_2BSM_BIT) & 1) * 2;
-        break;
-
-    case MP_ETH_SDCMR:
-        if (value & MP_ETH_CMD_TXHI) {
-            eth_send(s, 1);
-        }
-        if (value & MP_ETH_CMD_TXLO) {
-            eth_send(s, 0);
-        }
-        if (value & (MP_ETH_CMD_TXHI | MP_ETH_CMD_TXLO) && s->icr & s->imr) {
-            qemu_irq_raise(s->irq);
-        }
-        break;
-
-    case MP_ETH_ICR:
-        s->icr &= value;
-        break;
-
-    case MP_ETH_IMR:
-        s->imr = value;
-        if (s->icr & s->imr) {
-            qemu_irq_raise(s->irq);
-        }
-        break;
-
-    case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
-        s->frx_queue[(offset - MP_ETH_FRDP0)/4] = value;
-        break;
-
-    case MP_ETH_CRDP0 ... MP_ETH_CRDP3:
-        s->rx_queue[(offset - MP_ETH_CRDP0)/4] =
-            s->cur_rx[(offset - MP_ETH_CRDP0)/4] = value;
-        break;
-
-    case MP_ETH_CTDP0 ... MP_ETH_CTDP3:
-        s->tx_queue[(offset - MP_ETH_CTDP0)/4] = value;
-        break;
-    }
-}
-
-static const MemoryRegionOps mv88w8618_eth_ops = {
-    .read = mv88w8618_eth_read,
-    .write = mv88w8618_eth_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void eth_cleanup(NetClientState *nc)
-{
-    mv88w8618_eth_state *s = qemu_get_nic_opaque(nc);
-
-    s->nic = NULL;
-}
-
-static NetClientInfo net_mv88w8618_info = {
-    .type = NET_CLIENT_OPTIONS_KIND_NIC,
-    .size = sizeof(NICState),
-    .can_receive = eth_can_receive,
-    .receive = eth_receive,
-    .cleanup = eth_cleanup,
-};
-
-static int mv88w8618_eth_init(SysBusDevice *dev)
-{
-    mv88w8618_eth_state *s = FROM_SYSBUS(mv88w8618_eth_state, dev);
-
-    sysbus_init_irq(dev, &s->irq);
-    s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf,
-                          object_get_typename(OBJECT(dev)), dev->qdev.id, s);
-    memory_region_init_io(&s->iomem, &mv88w8618_eth_ops, s, "mv88w8618-eth",
-                          MP_ETH_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-    return 0;
-}
-
-static const VMStateDescription mv88w8618_eth_vmsd = {
-    .name = "mv88w8618_eth",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(smir, mv88w8618_eth_state),
-        VMSTATE_UINT32(icr, mv88w8618_eth_state),
-        VMSTATE_UINT32(imr, mv88w8618_eth_state),
-        VMSTATE_UINT32(vlan_header, mv88w8618_eth_state),
-        VMSTATE_UINT32_ARRAY(tx_queue, mv88w8618_eth_state, 2),
-        VMSTATE_UINT32_ARRAY(rx_queue, mv88w8618_eth_state, 4),
-        VMSTATE_UINT32_ARRAY(frx_queue, mv88w8618_eth_state, 4),
-        VMSTATE_UINT32_ARRAY(cur_rx, mv88w8618_eth_state, 4),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static Property mv88w8618_eth_properties[] = {
-    DEFINE_NIC_PROPERTIES(mv88w8618_eth_state, conf),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void mv88w8618_eth_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = mv88w8618_eth_init;
-    dc->vmsd = &mv88w8618_eth_vmsd;
-    dc->props = mv88w8618_eth_properties;
-}
-
-static const TypeInfo mv88w8618_eth_info = {
-    .name          = "mv88w8618_eth",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(mv88w8618_eth_state),
-    .class_init    = mv88w8618_eth_class_init,
-};
-
-/* LCD register offsets */
-#define MP_LCD_IRQCTRL          0x180
-#define MP_LCD_IRQSTAT          0x184
-#define MP_LCD_SPICTRL          0x1ac
-#define MP_LCD_INST             0x1bc
-#define MP_LCD_DATA             0x1c0
-
-/* Mode magics */
-#define MP_LCD_SPI_DATA         0x00100011
-#define MP_LCD_SPI_CMD          0x00104011
-#define MP_LCD_SPI_INVALID      0x00000000
-
-/* Commmands */
-#define MP_LCD_INST_SETPAGE0    0xB0
-/* ... */
-#define MP_LCD_INST_SETPAGE7    0xB7
-
-#define MP_LCD_TEXTCOLOR        0xe0e0ff /* RRGGBB */
-
-typedef struct musicpal_lcd_state {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t brightness;
-    uint32_t mode;
-    uint32_t irqctrl;
-    uint32_t page;
-    uint32_t page_off;
-    DisplayState *ds;
-    uint8_t video_ram[128*64/8];
-} musicpal_lcd_state;
-
-static uint8_t scale_lcd_color(musicpal_lcd_state *s, uint8_t col)
-{
-    switch (s->brightness) {
-    case 7:
-        return col;
-    case 0:
-        return 0;
-    default:
-        return (col * s->brightness) / 7;
-    }
-}
-
-#define SET_LCD_PIXEL(depth, type) \
-static inline void glue(set_lcd_pixel, depth) \
-        (musicpal_lcd_state *s, int x, int y, type col) \
-{ \
-    int dx, dy; \
-    type *pixel = &((type *) ds_get_data(s->ds))[(y * 128 * 3 + x) * 3]; \
-\
-    for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
-        for (dx = 0; dx < 3; dx++, pixel++) \
-            *pixel = col; \
-}
-SET_LCD_PIXEL(8, uint8_t)
-SET_LCD_PIXEL(16, uint16_t)
-SET_LCD_PIXEL(32, uint32_t)
-
-static void lcd_refresh(void *opaque)
-{
-    musicpal_lcd_state *s = opaque;
-    int x, y, col;
-
-    switch (ds_get_bits_per_pixel(s->ds)) {
-    case 0:
-        return;
-#define LCD_REFRESH(depth, func) \
-    case depth: \
-        col = func(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff), \
-                   scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff), \
-                   scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff)); \
-        for (x = 0; x < 128; x++) { \
-            for (y = 0; y < 64; y++) { \
-                if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) { \
-                    glue(set_lcd_pixel, depth)(s, x, y, col); \
-                } else { \
-                    glue(set_lcd_pixel, depth)(s, x, y, 0); \
-                } \
-            } \
-        } \
-        break;
-    LCD_REFRESH(8, rgb_to_pixel8)
-    LCD_REFRESH(16, rgb_to_pixel16)
-    LCD_REFRESH(32, (is_surface_bgr(s->ds->surface) ?
-                     rgb_to_pixel32bgr : rgb_to_pixel32))
-    default:
-        hw_error("unsupported colour depth %i\n",
-                  ds_get_bits_per_pixel(s->ds));
-    }
-
-    dpy_gfx_update(s->ds, 0, 0, 128*3, 64*3);
-}
-
-static void lcd_invalidate(void *opaque)
-{
-}
-
-static void musicpal_lcd_gpio_brigthness_in(void *opaque, int irq, int level)
-{
-    musicpal_lcd_state *s = opaque;
-    s->brightness &= ~(1 << irq);
-    s->brightness |= level << irq;
-}
-
-static uint64_t musicpal_lcd_read(void *opaque, hwaddr offset,
-                                  unsigned size)
-{
-    musicpal_lcd_state *s = opaque;
-
-    switch (offset) {
-    case MP_LCD_IRQCTRL:
-        return s->irqctrl;
-
-    default:
-        return 0;
-    }
-}
-
-static void musicpal_lcd_write(void *opaque, hwaddr offset,
-                               uint64_t value, unsigned size)
-{
-    musicpal_lcd_state *s = opaque;
-
-    switch (offset) {
-    case MP_LCD_IRQCTRL:
-        s->irqctrl = value;
-        break;
-
-    case MP_LCD_SPICTRL:
-        if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD) {
-            s->mode = value;
-        } else {
-            s->mode = MP_LCD_SPI_INVALID;
-        }
-        break;
-
-    case MP_LCD_INST:
-        if (value >= MP_LCD_INST_SETPAGE0 && value <= MP_LCD_INST_SETPAGE7) {
-            s->page = value - MP_LCD_INST_SETPAGE0;
-            s->page_off = 0;
-        }
-        break;
-
-    case MP_LCD_DATA:
-        if (s->mode == MP_LCD_SPI_CMD) {
-            if (value >= MP_LCD_INST_SETPAGE0 &&
-                value <= MP_LCD_INST_SETPAGE7) {
-                s->page = value - MP_LCD_INST_SETPAGE0;
-                s->page_off = 0;
-            }
-        } else if (s->mode == MP_LCD_SPI_DATA) {
-            s->video_ram[s->page*128 + s->page_off] = value;
-            s->page_off = (s->page_off + 1) & 127;
-        }
-        break;
-    }
-}
-
-static const MemoryRegionOps musicpal_lcd_ops = {
-    .read = musicpal_lcd_read,
-    .write = musicpal_lcd_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int musicpal_lcd_init(SysBusDevice *dev)
-{
-    musicpal_lcd_state *s = FROM_SYSBUS(musicpal_lcd_state, dev);
-
-    s->brightness = 7;
-
-    memory_region_init_io(&s->iomem, &musicpal_lcd_ops, s,
-                          "musicpal-lcd", MP_LCD_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    s->ds = graphic_console_init(lcd_refresh, lcd_invalidate,
-                                 NULL, NULL, s);
-    qemu_console_resize(s->ds, 128*3, 64*3);
-
-    qdev_init_gpio_in(&dev->qdev, musicpal_lcd_gpio_brigthness_in, 3);
-
-    return 0;
-}
-
-static const VMStateDescription musicpal_lcd_vmsd = {
-    .name = "musicpal_lcd",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(brightness, musicpal_lcd_state),
-        VMSTATE_UINT32(mode, musicpal_lcd_state),
-        VMSTATE_UINT32(irqctrl, musicpal_lcd_state),
-        VMSTATE_UINT32(page, musicpal_lcd_state),
-        VMSTATE_UINT32(page_off, musicpal_lcd_state),
-        VMSTATE_BUFFER(video_ram, musicpal_lcd_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void musicpal_lcd_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = musicpal_lcd_init;
-    dc->vmsd = &musicpal_lcd_vmsd;
-}
-
-static const TypeInfo musicpal_lcd_info = {
-    .name          = "musicpal_lcd",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(musicpal_lcd_state),
-    .class_init    = musicpal_lcd_class_init,
-};
-
-/* PIC register offsets */
-#define MP_PIC_STATUS           0x00
-#define MP_PIC_ENABLE_SET       0x08
-#define MP_PIC_ENABLE_CLR       0x0C
-
-typedef struct mv88w8618_pic_state
-{
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t level;
-    uint32_t enabled;
-    qemu_irq parent_irq;
-} mv88w8618_pic_state;
-
-static void mv88w8618_pic_update(mv88w8618_pic_state *s)
-{
-    qemu_set_irq(s->parent_irq, (s->level & s->enabled));
-}
-
-static void mv88w8618_pic_set_irq(void *opaque, int irq, int level)
-{
-    mv88w8618_pic_state *s = opaque;
-
-    if (level) {
-        s->level |= 1 << irq;
-    } else {
-        s->level &= ~(1 << irq);
-    }
-    mv88w8618_pic_update(s);
-}
-
-static uint64_t mv88w8618_pic_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    mv88w8618_pic_state *s = opaque;
-
-    switch (offset) {
-    case MP_PIC_STATUS:
-        return s->level & s->enabled;
-
-    default:
-        return 0;
-    }
-}
-
-static void mv88w8618_pic_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-    mv88w8618_pic_state *s = opaque;
-
-    switch (offset) {
-    case MP_PIC_ENABLE_SET:
-        s->enabled |= value;
-        break;
-
-    case MP_PIC_ENABLE_CLR:
-        s->enabled &= ~value;
-        s->level &= ~value;
-        break;
-    }
-    mv88w8618_pic_update(s);
-}
-
-static void mv88w8618_pic_reset(DeviceState *d)
-{
-    mv88w8618_pic_state *s = FROM_SYSBUS(mv88w8618_pic_state,
-                                         SYS_BUS_DEVICE(d));
-
-    s->level = 0;
-    s->enabled = 0;
-}
-
-static const MemoryRegionOps mv88w8618_pic_ops = {
-    .read = mv88w8618_pic_read,
-    .write = mv88w8618_pic_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int mv88w8618_pic_init(SysBusDevice *dev)
-{
-    mv88w8618_pic_state *s = FROM_SYSBUS(mv88w8618_pic_state, dev);
-
-    qdev_init_gpio_in(&dev->qdev, mv88w8618_pic_set_irq, 32);
-    sysbus_init_irq(dev, &s->parent_irq);
-    memory_region_init_io(&s->iomem, &mv88w8618_pic_ops, s,
-                          "musicpal-pic", MP_PIC_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-    return 0;
-}
-
-static const VMStateDescription mv88w8618_pic_vmsd = {
-    .name = "mv88w8618_pic",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(level, mv88w8618_pic_state),
-        VMSTATE_UINT32(enabled, mv88w8618_pic_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void mv88w8618_pic_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = mv88w8618_pic_init;
-    dc->reset = mv88w8618_pic_reset;
-    dc->vmsd = &mv88w8618_pic_vmsd;
-}
-
-static const TypeInfo mv88w8618_pic_info = {
-    .name          = "mv88w8618_pic",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(mv88w8618_pic_state),
-    .class_init    = mv88w8618_pic_class_init,
-};
-
-/* PIT register offsets */
-#define MP_PIT_TIMER1_LENGTH    0x00
-/* ... */
-#define MP_PIT_TIMER4_LENGTH    0x0C
-#define MP_PIT_CONTROL          0x10
-#define MP_PIT_TIMER1_VALUE     0x14
-/* ... */
-#define MP_PIT_TIMER4_VALUE     0x20
-#define MP_BOARD_RESET          0x34
-
-/* Magic board reset value (probably some watchdog behind it) */
-#define MP_BOARD_RESET_MAGIC    0x10000
-
-typedef struct mv88w8618_timer_state {
-    ptimer_state *ptimer;
-    uint32_t limit;
-    int freq;
-    qemu_irq irq;
-} mv88w8618_timer_state;
-
-typedef struct mv88w8618_pit_state {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    mv88w8618_timer_state timer[4];
-} mv88w8618_pit_state;
-
-static void mv88w8618_timer_tick(void *opaque)
-{
-    mv88w8618_timer_state *s = opaque;
-
-    qemu_irq_raise(s->irq);
-}
-
-static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s,
-                                 uint32_t freq)
-{
-    QEMUBH *bh;
-
-    sysbus_init_irq(dev, &s->irq);
-    s->freq = freq;
-
-    bh = qemu_bh_new(mv88w8618_timer_tick, s);
-    s->ptimer = ptimer_init(bh);
-}
-
-static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    mv88w8618_pit_state *s = opaque;
-    mv88w8618_timer_state *t;
-
-    switch (offset) {
-    case MP_PIT_TIMER1_VALUE ... MP_PIT_TIMER4_VALUE:
-        t = &s->timer[(offset-MP_PIT_TIMER1_VALUE) >> 2];
-        return ptimer_get_count(t->ptimer);
-
-    default:
-        return 0;
-    }
-}
-
-static void mv88w8618_pit_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-    mv88w8618_pit_state *s = opaque;
-    mv88w8618_timer_state *t;
-    int i;
-
-    switch (offset) {
-    case MP_PIT_TIMER1_LENGTH ... MP_PIT_TIMER4_LENGTH:
-        t = &s->timer[offset >> 2];
-        t->limit = value;
-        if (t->limit > 0) {
-            ptimer_set_limit(t->ptimer, t->limit, 1);
-        } else {
-            ptimer_stop(t->ptimer);
-        }
-        break;
-
-    case MP_PIT_CONTROL:
-        for (i = 0; i < 4; i++) {
-            t = &s->timer[i];
-            if (value & 0xf && t->limit > 0) {
-                ptimer_set_limit(t->ptimer, t->limit, 0);
-                ptimer_set_freq(t->ptimer, t->freq);
-                ptimer_run(t->ptimer, 0);
-            } else {
-                ptimer_stop(t->ptimer);
-            }
-            value >>= 4;
-        }
-        break;
-
-    case MP_BOARD_RESET:
-        if (value == MP_BOARD_RESET_MAGIC) {
-            qemu_system_reset_request();
-        }
-        break;
-    }
-}
-
-static void mv88w8618_pit_reset(DeviceState *d)
-{
-    mv88w8618_pit_state *s = FROM_SYSBUS(mv88w8618_pit_state,
-                                         SYS_BUS_DEVICE(d));
-    int i;
-
-    for (i = 0; i < 4; i++) {
-        ptimer_stop(s->timer[i].ptimer);
-        s->timer[i].limit = 0;
-    }
-}
-
-static const MemoryRegionOps mv88w8618_pit_ops = {
-    .read = mv88w8618_pit_read,
-    .write = mv88w8618_pit_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int mv88w8618_pit_init(SysBusDevice *dev)
-{
-    mv88w8618_pit_state *s = FROM_SYSBUS(mv88w8618_pit_state, dev);
-    int i;
-
-    /* Letting them all run at 1 MHz is likely just a pragmatic
-     * simplification. */
-    for (i = 0; i < 4; i++) {
-        mv88w8618_timer_init(dev, &s->timer[i], 1000000);
-    }
-
-    memory_region_init_io(&s->iomem, &mv88w8618_pit_ops, s,
-                          "musicpal-pit", MP_PIT_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-    return 0;
-}
-
-static const VMStateDescription mv88w8618_timer_vmsd = {
-    .name = "timer",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_PTIMER(ptimer, mv88w8618_timer_state),
-        VMSTATE_UINT32(limit, mv88w8618_timer_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription mv88w8618_pit_vmsd = {
-    .name = "mv88w8618_pit",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_STRUCT_ARRAY(timer, mv88w8618_pit_state, 4, 1,
-                             mv88w8618_timer_vmsd, mv88w8618_timer_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void mv88w8618_pit_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = mv88w8618_pit_init;
-    dc->reset = mv88w8618_pit_reset;
-    dc->vmsd = &mv88w8618_pit_vmsd;
-}
-
-static const TypeInfo mv88w8618_pit_info = {
-    .name          = "mv88w8618_pit",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(mv88w8618_pit_state),
-    .class_init    = mv88w8618_pit_class_init,
-};
-
-/* Flash config register offsets */
-#define MP_FLASHCFG_CFGR0    0x04
-
-typedef struct mv88w8618_flashcfg_state {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t cfgr0;
-} mv88w8618_flashcfg_state;
-
-static uint64_t mv88w8618_flashcfg_read(void *opaque,
-                                        hwaddr offset,
-                                        unsigned size)
-{
-    mv88w8618_flashcfg_state *s = opaque;
-
-    switch (offset) {
-    case MP_FLASHCFG_CFGR0:
-        return s->cfgr0;
-
-    default:
-        return 0;
-    }
-}
-
-static void mv88w8618_flashcfg_write(void *opaque, hwaddr offset,
-                                     uint64_t value, unsigned size)
-{
-    mv88w8618_flashcfg_state *s = opaque;
-
-    switch (offset) {
-    case MP_FLASHCFG_CFGR0:
-        s->cfgr0 = value;
-        break;
-    }
-}
-
-static const MemoryRegionOps mv88w8618_flashcfg_ops = {
-    .read = mv88w8618_flashcfg_read,
-    .write = mv88w8618_flashcfg_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int mv88w8618_flashcfg_init(SysBusDevice *dev)
-{
-    mv88w8618_flashcfg_state *s = FROM_SYSBUS(mv88w8618_flashcfg_state, dev);
-
-    s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
-    memory_region_init_io(&s->iomem, &mv88w8618_flashcfg_ops, s,
-                          "musicpal-flashcfg", MP_FLASHCFG_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-    return 0;
-}
-
-static const VMStateDescription mv88w8618_flashcfg_vmsd = {
-    .name = "mv88w8618_flashcfg",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(cfgr0, mv88w8618_flashcfg_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void mv88w8618_flashcfg_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = mv88w8618_flashcfg_init;
-    dc->vmsd = &mv88w8618_flashcfg_vmsd;
-}
-
-static const TypeInfo mv88w8618_flashcfg_info = {
-    .name          = "mv88w8618_flashcfg",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(mv88w8618_flashcfg_state),
-    .class_init    = mv88w8618_flashcfg_class_init,
-};
-
-/* Misc register offsets */
-#define MP_MISC_BOARD_REVISION  0x18
-
-#define MP_BOARD_REVISION       0x31
-
-static uint64_t musicpal_misc_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    switch (offset) {
-    case MP_MISC_BOARD_REVISION:
-        return MP_BOARD_REVISION;
-
-    default:
-        return 0;
-    }
-}
-
-static void musicpal_misc_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-}
-
-static const MemoryRegionOps musicpal_misc_ops = {
-    .read = musicpal_misc_read,
-    .write = musicpal_misc_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void musicpal_misc_init(SysBusDevice *dev)
-{
-    MemoryRegion *iomem = g_new(MemoryRegion, 1);
-
-    memory_region_init_io(iomem, &musicpal_misc_ops, NULL,
-                          "musicpal-misc", MP_MISC_SIZE);
-    sysbus_add_memory(dev, MP_MISC_BASE, iomem);
-}
-
-/* WLAN register offsets */
-#define MP_WLAN_MAGIC1          0x11c
-#define MP_WLAN_MAGIC2          0x124
-
-static uint64_t mv88w8618_wlan_read(void *opaque, hwaddr offset,
-                                    unsigned size)
-{
-    switch (offset) {
-    /* Workaround to allow loading the binary-only wlandrv.ko crap
-     * from the original Freecom firmware. */
-    case MP_WLAN_MAGIC1:
-        return ~3;
-    case MP_WLAN_MAGIC2:
-        return -1;
-
-    default:
-        return 0;
-    }
-}
-
-static void mv88w8618_wlan_write(void *opaque, hwaddr offset,
-                                 uint64_t value, unsigned size)
-{
-}
-
-static const MemoryRegionOps mv88w8618_wlan_ops = {
-    .read = mv88w8618_wlan_read,
-    .write =mv88w8618_wlan_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int mv88w8618_wlan_init(SysBusDevice *dev)
-{
-    MemoryRegion *iomem = g_new(MemoryRegion, 1);
-
-    memory_region_init_io(iomem, &mv88w8618_wlan_ops, NULL,
-                          "musicpal-wlan", MP_WLAN_SIZE);
-    sysbus_init_mmio(dev, iomem);
-    return 0;
-}
-
-/* GPIO register offsets */
-#define MP_GPIO_OE_LO           0x008
-#define MP_GPIO_OUT_LO          0x00c
-#define MP_GPIO_IN_LO           0x010
-#define MP_GPIO_IER_LO          0x014
-#define MP_GPIO_IMR_LO          0x018
-#define MP_GPIO_ISR_LO          0x020
-#define MP_GPIO_OE_HI           0x508
-#define MP_GPIO_OUT_HI          0x50c
-#define MP_GPIO_IN_HI           0x510
-#define MP_GPIO_IER_HI          0x514
-#define MP_GPIO_IMR_HI          0x518
-#define MP_GPIO_ISR_HI          0x520
-
-/* GPIO bits & masks */
-#define MP_GPIO_LCD_BRIGHTNESS  0x00070000
-#define MP_GPIO_I2C_DATA_BIT    29
-#define MP_GPIO_I2C_CLOCK_BIT   30
-
-/* LCD brightness bits in GPIO_OE_HI */
-#define MP_OE_LCD_BRIGHTNESS    0x0007
-
-typedef struct musicpal_gpio_state {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t lcd_brightness;
-    uint32_t out_state;
-    uint32_t in_state;
-    uint32_t ier;
-    uint32_t imr;
-    uint32_t isr;
-    qemu_irq irq;
-    qemu_irq out[5]; /* 3 brightness out + 2 lcd (data and clock ) */
-} musicpal_gpio_state;
-
-static void musicpal_gpio_brightness_update(musicpal_gpio_state *s) {
-    int i;
-    uint32_t brightness;
-
-    /* compute brightness ratio */
-    switch (s->lcd_brightness) {
-    case 0x00000007:
-        brightness = 0;
-        break;
-
-    case 0x00020000:
-        brightness = 1;
-        break;
-
-    case 0x00020001:
-        brightness = 2;
-        break;
-
-    case 0x00040000:
-        brightness = 3;
-        break;
-
-    case 0x00010006:
-        brightness = 4;
-        break;
-
-    case 0x00020005:
-        brightness = 5;
-        break;
-
-    case 0x00040003:
-        brightness = 6;
-        break;
-
-    case 0x00030004:
-    default:
-        brightness = 7;
-    }
-
-    /* set lcd brightness GPIOs  */
-    for (i = 0; i <= 2; i++) {
-        qemu_set_irq(s->out[i], (brightness >> i) & 1);
-    }
-}
-
-static void musicpal_gpio_pin_event(void *opaque, int pin, int level)
-{
-    musicpal_gpio_state *s = opaque;
-    uint32_t mask = 1 << pin;
-    uint32_t delta = level << pin;
-    uint32_t old = s->in_state & mask;
-
-    s->in_state &= ~mask;
-    s->in_state |= delta;
-
-    if ((old ^ delta) &&
-        ((level && (s->imr & mask)) || (!level && (s->ier & mask)))) {
-        s->isr = mask;
-        qemu_irq_raise(s->irq);
-    }
-}
-
-static uint64_t musicpal_gpio_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    musicpal_gpio_state *s = opaque;
-
-    switch (offset) {
-    case MP_GPIO_OE_HI: /* used for LCD brightness control */
-        return s->lcd_brightness & MP_OE_LCD_BRIGHTNESS;
-
-    case MP_GPIO_OUT_LO:
-        return s->out_state & 0xFFFF;
-    case MP_GPIO_OUT_HI:
-        return s->out_state >> 16;
-
-    case MP_GPIO_IN_LO:
-        return s->in_state & 0xFFFF;
-    case MP_GPIO_IN_HI:
-        return s->in_state >> 16;
-
-    case MP_GPIO_IER_LO:
-        return s->ier & 0xFFFF;
-    case MP_GPIO_IER_HI:
-        return s->ier >> 16;
-
-    case MP_GPIO_IMR_LO:
-        return s->imr & 0xFFFF;
-    case MP_GPIO_IMR_HI:
-        return s->imr >> 16;
-
-    case MP_GPIO_ISR_LO:
-        return s->isr & 0xFFFF;
-    case MP_GPIO_ISR_HI:
-        return s->isr >> 16;
-
-    default:
-        return 0;
-    }
-}
-
-static void musicpal_gpio_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-    musicpal_gpio_state *s = opaque;
-    switch (offset) {
-    case MP_GPIO_OE_HI: /* used for LCD brightness control */
-        s->lcd_brightness = (s->lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
-                         (value & MP_OE_LCD_BRIGHTNESS);
-        musicpal_gpio_brightness_update(s);
-        break;
-
-    case MP_GPIO_OUT_LO:
-        s->out_state = (s->out_state & 0xFFFF0000) | (value & 0xFFFF);
-        break;
-    case MP_GPIO_OUT_HI:
-        s->out_state = (s->out_state & 0xFFFF) | (value << 16);
-        s->lcd_brightness = (s->lcd_brightness & 0xFFFF) |
-                            (s->out_state & MP_GPIO_LCD_BRIGHTNESS);
-        musicpal_gpio_brightness_update(s);
-        qemu_set_irq(s->out[3], (s->out_state >> MP_GPIO_I2C_DATA_BIT) & 1);
-        qemu_set_irq(s->out[4], (s->out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
-        break;
-
-    case MP_GPIO_IER_LO:
-        s->ier = (s->ier & 0xFFFF0000) | (value & 0xFFFF);
-        break;
-    case MP_GPIO_IER_HI:
-        s->ier = (s->ier & 0xFFFF) | (value << 16);
-        break;
-
-    case MP_GPIO_IMR_LO:
-        s->imr = (s->imr & 0xFFFF0000) | (value & 0xFFFF);
-        break;
-    case MP_GPIO_IMR_HI:
-        s->imr = (s->imr & 0xFFFF) | (value << 16);
-        break;
-    }
-}
-
-static const MemoryRegionOps musicpal_gpio_ops = {
-    .read = musicpal_gpio_read,
-    .write = musicpal_gpio_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void musicpal_gpio_reset(DeviceState *d)
-{
-    musicpal_gpio_state *s = FROM_SYSBUS(musicpal_gpio_state,
-                                         SYS_BUS_DEVICE(d));
-
-    s->lcd_brightness = 0;
-    s->out_state = 0;
-    s->in_state = 0xffffffff;
-    s->ier = 0;
-    s->imr = 0;
-    s->isr = 0;
-}
-
-static int musicpal_gpio_init(SysBusDevice *dev)
-{
-    musicpal_gpio_state *s = FROM_SYSBUS(musicpal_gpio_state, dev);
-
-    sysbus_init_irq(dev, &s->irq);
-
-    memory_region_init_io(&s->iomem, &musicpal_gpio_ops, s,
-                          "musicpal-gpio", MP_GPIO_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
-
-    qdev_init_gpio_in(&dev->qdev, musicpal_gpio_pin_event, 32);
-
-    return 0;
-}
-
-static const VMStateDescription musicpal_gpio_vmsd = {
-    .name = "musicpal_gpio",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(lcd_brightness, musicpal_gpio_state),
-        VMSTATE_UINT32(out_state, musicpal_gpio_state),
-        VMSTATE_UINT32(in_state, musicpal_gpio_state),
-        VMSTATE_UINT32(ier, musicpal_gpio_state),
-        VMSTATE_UINT32(imr, musicpal_gpio_state),
-        VMSTATE_UINT32(isr, musicpal_gpio_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void musicpal_gpio_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = musicpal_gpio_init;
-    dc->reset = musicpal_gpio_reset;
-    dc->vmsd = &musicpal_gpio_vmsd;
-}
-
-static const TypeInfo musicpal_gpio_info = {
-    .name          = "musicpal_gpio",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(musicpal_gpio_state),
-    .class_init    = musicpal_gpio_class_init,
-};
-
-/* Keyboard codes & masks */
-#define KEY_RELEASED            0x80
-#define KEY_CODE                0x7f
-
-#define KEYCODE_TAB             0x0f
-#define KEYCODE_ENTER           0x1c
-#define KEYCODE_F               0x21
-#define KEYCODE_M               0x32
-
-#define KEYCODE_EXTENDED        0xe0
-#define KEYCODE_UP              0x48
-#define KEYCODE_DOWN            0x50
-#define KEYCODE_LEFT            0x4b
-#define KEYCODE_RIGHT           0x4d
-
-#define MP_KEY_WHEEL_VOL       (1 << 0)
-#define MP_KEY_WHEEL_VOL_INV   (1 << 1)
-#define MP_KEY_WHEEL_NAV       (1 << 2)
-#define MP_KEY_WHEEL_NAV_INV   (1 << 3)
-#define MP_KEY_BTN_FAVORITS    (1 << 4)
-#define MP_KEY_BTN_MENU        (1 << 5)
-#define MP_KEY_BTN_VOLUME      (1 << 6)
-#define MP_KEY_BTN_NAVIGATION  (1 << 7)
-
-typedef struct musicpal_key_state {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t kbd_extended;
-    uint32_t pressed_keys;
-    qemu_irq out[8];
-} musicpal_key_state;
-
-static void musicpal_key_event(void *opaque, int keycode)
-{
-    musicpal_key_state *s = opaque;
-    uint32_t event = 0;
-    int i;
-
-    if (keycode == KEYCODE_EXTENDED) {
-        s->kbd_extended = 1;
-        return;
-    }
-
-    if (s->kbd_extended) {
-        switch (keycode & KEY_CODE) {
-        case KEYCODE_UP:
-            event = MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_NAV_INV;
-            break;
-
-        case KEYCODE_DOWN:
-            event = MP_KEY_WHEEL_NAV;
-            break;
-
-        case KEYCODE_LEFT:
-            event = MP_KEY_WHEEL_VOL | MP_KEY_WHEEL_VOL_INV;
-            break;
-
-        case KEYCODE_RIGHT:
-            event = MP_KEY_WHEEL_VOL;
-            break;
-        }
-    } else {
-        switch (keycode & KEY_CODE) {
-        case KEYCODE_F:
-            event = MP_KEY_BTN_FAVORITS;
-            break;
-
-        case KEYCODE_TAB:
-            event = MP_KEY_BTN_VOLUME;
-            break;
-
-        case KEYCODE_ENTER:
-            event = MP_KEY_BTN_NAVIGATION;
-            break;
-
-        case KEYCODE_M:
-            event = MP_KEY_BTN_MENU;
-            break;
-        }
-        /* Do not repeat already pressed buttons */
-        if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
-            event = 0;
-        }
-    }
-
-    if (event) {
-        /* Raise GPIO pin first if repeating a key */
-        if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
-            for (i = 0; i <= 7; i++) {
-                if (event & (1 << i)) {
-                    qemu_set_irq(s->out[i], 1);
-                }
-            }
-        }
-        for (i = 0; i <= 7; i++) {
-            if (event & (1 << i)) {
-                qemu_set_irq(s->out[i], !!(keycode & KEY_RELEASED));
-            }
-        }
-        if (keycode & KEY_RELEASED) {
-            s->pressed_keys &= ~event;
-        } else {
-            s->pressed_keys |= event;
-        }
-    }
-
-    s->kbd_extended = 0;
-}
-
-static int musicpal_key_init(SysBusDevice *dev)
-{
-    musicpal_key_state *s = FROM_SYSBUS(musicpal_key_state, dev);
-
-    memory_region_init(&s->iomem, "dummy", 0);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    s->kbd_extended = 0;
-    s->pressed_keys = 0;
-
-    qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
-
-    qemu_add_kbd_event_handler(musicpal_key_event, s);
-
-    return 0;
-}
-
-static const VMStateDescription musicpal_key_vmsd = {
-    .name = "musicpal_key",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(kbd_extended, musicpal_key_state),
-        VMSTATE_UINT32(pressed_keys, musicpal_key_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void musicpal_key_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = musicpal_key_init;
-    dc->vmsd = &musicpal_key_vmsd;
-}
-
-static const TypeInfo musicpal_key_info = {
-    .name          = "musicpal_key",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(musicpal_key_state),
-    .class_init    = musicpal_key_class_init,
-};
-
-static struct arm_boot_info musicpal_binfo = {
-    .loader_start = 0x0,
-    .board_id = 0x20e,
-};
-
-static void musicpal_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    ARMCPU *cpu;
-    qemu_irq *cpu_pic;
-    qemu_irq pic[32];
-    DeviceState *dev;
-    DeviceState *i2c_dev;
-    DeviceState *lcd_dev;
-    DeviceState *key_dev;
-    DeviceState *wm8750_dev;
-    SysBusDevice *s;
-    i2c_bus *i2c;
-    int i;
-    unsigned long flash_size;
-    DriveInfo *dinfo;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-
-    if (!cpu_model) {
-        cpu_model = "arm926";
-    }
-    cpu = cpu_arm_init(cpu_model);
-    if (!cpu) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    cpu_pic = arm_pic_init_cpu(cpu);
-
-    /* For now we use a fixed - the original - RAM size */
-    memory_region_init_ram(ram, "musicpal.ram", MP_RAM_DEFAULT_SIZE);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(address_space_mem, 0, ram);
-
-    memory_region_init_ram(sram, "musicpal.sram", MP_SRAM_SIZE);
-    vmstate_register_ram_global(sram);
-    memory_region_add_subregion(address_space_mem, MP_SRAM_BASE, sram);
-
-    dev = sysbus_create_simple("mv88w8618_pic", MP_PIC_BASE,
-                               cpu_pic[ARM_PIC_CPU_IRQ]);
-    for (i = 0; i < 32; i++) {
-        pic[i] = qdev_get_gpio_in(dev, i);
-    }
-    sysbus_create_varargs("mv88w8618_pit", MP_PIT_BASE, pic[MP_TIMER1_IRQ],
-                          pic[MP_TIMER2_IRQ], pic[MP_TIMER3_IRQ],
-                          pic[MP_TIMER4_IRQ], NULL);
-
-    if (serial_hds[0]) {
-        serial_mm_init(address_space_mem, MP_UART1_BASE, 2, pic[MP_UART1_IRQ],
-                       1825000, serial_hds[0], DEVICE_NATIVE_ENDIAN);
-    }
-    if (serial_hds[1]) {
-        serial_mm_init(address_space_mem, MP_UART2_BASE, 2, pic[MP_UART2_IRQ],
-                       1825000, serial_hds[1], DEVICE_NATIVE_ENDIAN);
-    }
-
-    /* Register flash */
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (dinfo) {
-        flash_size = bdrv_getlength(dinfo->bdrv);
-        if (flash_size != 8*1024*1024 && flash_size != 16*1024*1024 &&
-            flash_size != 32*1024*1024) {
-            fprintf(stderr, "Invalid flash image size\n");
-            exit(1);
-        }
-
-        /*
-         * The original U-Boot accesses the flash at 0xFE000000 instead of
-         * 0xFF800000 (if there is 8 MB flash). So remap flash access if the
-         * image is smaller than 32 MB.
-         */
-#ifdef TARGET_WORDS_BIGENDIAN
-        pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
-                              "musicpal.flash", flash_size,
-                              dinfo->bdrv, 0x10000,
-                              (flash_size + 0xffff) >> 16,
-                              MP_FLASH_SIZE_MAX / flash_size,
-                              2, 0x00BF, 0x236D, 0x0000, 0x0000,
-                              0x5555, 0x2AAA, 1);
-#else
-        pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
-                              "musicpal.flash", flash_size,
-                              dinfo->bdrv, 0x10000,
-                              (flash_size + 0xffff) >> 16,
-                              MP_FLASH_SIZE_MAX / flash_size,
-                              2, 0x00BF, 0x236D, 0x0000, 0x0000,
-                              0x5555, 0x2AAA, 0);
-#endif
-
-    }
-    sysbus_create_simple("mv88w8618_flashcfg", MP_FLASHCFG_BASE, NULL);
-
-    qemu_check_nic_model(&nd_table[0], "mv88w8618");
-    dev = qdev_create(NULL, "mv88w8618_eth");
-    qdev_set_nic_properties(dev, &nd_table[0]);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, MP_ETH_BASE);
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[MP_ETH_IRQ]);
-
-    sysbus_create_simple("mv88w8618_wlan", MP_WLAN_BASE, NULL);
-
-    musicpal_misc_init(SYS_BUS_DEVICE(dev));
-
-    dev = sysbus_create_simple("musicpal_gpio", MP_GPIO_BASE, pic[MP_GPIO_IRQ]);
-    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", -1, NULL);
-
-    /* I2C read data */
-    qdev_connect_gpio_out(i2c_dev, 0,
-                          qdev_get_gpio_in(dev, MP_GPIO_I2C_DATA_BIT));
-    /* I2C data */
-    qdev_connect_gpio_out(dev, 3, qdev_get_gpio_in(i2c_dev, 0));
-    /* I2C clock */
-    qdev_connect_gpio_out(dev, 4, qdev_get_gpio_in(i2c_dev, 1));
-
-    for (i = 0; i < 3; i++) {
-        qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(lcd_dev, i));
-    }
-    for (i = 0; i < 4; i++) {
-        qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 8));
-    }
-    for (i = 4; i < 8; i++) {
-        qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15));
-    }
-
-    wm8750_dev = i2c_create_slave(i2c, "wm8750", MP_WM_ADDR);
-    dev = qdev_create(NULL, "mv88w8618_audio");
-    s = SYS_BUS_DEVICE(dev);
-    qdev_prop_set_ptr(dev, "wm8750", wm8750_dev);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(s, 0, MP_AUDIO_BASE);
-    sysbus_connect_irq(s, 0, pic[MP_AUDIO_IRQ]);
-
-    musicpal_binfo.ram_size = MP_RAM_DEFAULT_SIZE;
-    musicpal_binfo.kernel_filename = kernel_filename;
-    musicpal_binfo.kernel_cmdline = kernel_cmdline;
-    musicpal_binfo.initrd_filename = initrd_filename;
-    arm_load_kernel(cpu, &musicpal_binfo);
-}
-
-static QEMUMachine musicpal_machine = {
-    .name = "musicpal",
-    .desc = "Marvell 88w8618 / MusicPal (ARM926EJ-S)",
-    .init = musicpal_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void musicpal_machine_init(void)
-{
-    qemu_register_machine(&musicpal_machine);
-}
-
-machine_init(musicpal_machine_init);
-
-static void mv88w8618_wlan_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = mv88w8618_wlan_init;
-}
-
-static const TypeInfo mv88w8618_wlan_info = {
-    .name          = "mv88w8618_wlan",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(SysBusDevice),
-    .class_init    = mv88w8618_wlan_class_init,
-};
-
-static void musicpal_register_types(void)
-{
-    type_register_static(&mv88w8618_pic_info);
-    type_register_static(&mv88w8618_pit_info);
-    type_register_static(&mv88w8618_flashcfg_info);
-    type_register_static(&mv88w8618_eth_info);
-    type_register_static(&mv88w8618_wlan_info);
-    type_register_static(&musicpal_lcd_info);
-    type_register_static(&musicpal_gpio_info);
-    type_register_static(&musicpal_key_info);
-}
-
-type_init(musicpal_register_types)
diff --git a/hw/nseries.c b/hw/nseries.c
deleted file mode 100644
index c5bf9f9..0000000
--- a/hw/nseries.c
+++ /dev/null
@@ -1,1430 +0,0 @@
-/*
- * Nokia N-series internet tablets.
- *
- * Copyright (C) 2007 Nokia Corporation
- * Written by Andrzej Zaborowski <andrew at openedhand.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 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 "qemu-common.h"
-#include "sysemu/sysemu.h"
-#include "hw/omap.h"
-#include "hw/arm-misc.h"
-#include "hw/irq.h"
-#include "ui/console.h"
-#include "hw/boards.h"
-#include "hw/i2c.h"
-#include "hw/devices.h"
-#include "hw/flash.h"
-#include "hw/hw.h"
-#include "hw/bt.h"
-#include "hw/loader.h"
-#include "sysemu/blockdev.h"
-#include "hw/sysbus.h"
-#include "exec/address-spaces.h"
-
-/* Nokia N8x0 support */
-struct n800_s {
-    struct omap_mpu_state_s *mpu;
-
-    struct rfbi_chip_s blizzard;
-    struct {
-        void *opaque;
-        uint32_t (*txrx)(void *opaque, uint32_t value, int len);
-        uWireSlave *chip;
-    } ts;
-
-    int keymap[0x80];
-    DeviceState *kbd;
-
-    DeviceState *usb;
-    void *retu;
-    void *tahvo;
-    DeviceState *nand;
-};
-
-/* GPIO pins */
-#define N8X0_TUSB_ENABLE_GPIO		0
-#define N800_MMC2_WP_GPIO		8
-#define N800_UNKNOWN_GPIO0		9	/* out */
-#define N810_MMC2_VIOSD_GPIO		9
-#define N810_HEADSET_AMP_GPIO		10
-#define N800_CAM_TURN_GPIO		12
-#define N810_GPS_RESET_GPIO		12
-#define N800_BLIZZARD_POWERDOWN_GPIO	15
-#define N800_MMC1_WP_GPIO		23
-#define N810_MMC2_VSD_GPIO		23
-#define N8X0_ONENAND_GPIO		26
-#define N810_BLIZZARD_RESET_GPIO	30
-#define N800_UNKNOWN_GPIO2		53	/* out */
-#define N8X0_TUSB_INT_GPIO		58
-#define N8X0_BT_WKUP_GPIO		61
-#define N8X0_STI_GPIO			62
-#define N8X0_CBUS_SEL_GPIO		64
-#define N8X0_CBUS_DAT_GPIO		65
-#define N8X0_CBUS_CLK_GPIO		66
-#define N8X0_WLAN_IRQ_GPIO		87
-#define N8X0_BT_RESET_GPIO		92
-#define N8X0_TEA5761_CS_GPIO		93
-#define N800_UNKNOWN_GPIO		94
-#define N810_TSC_RESET_GPIO		94
-#define N800_CAM_ACT_GPIO		95
-#define N810_GPS_WAKEUP_GPIO		95
-#define N8X0_MMC_CS_GPIO		96
-#define N8X0_WLAN_PWR_GPIO		97
-#define N8X0_BT_HOST_WKUP_GPIO		98
-#define N810_SPEAKER_AMP_GPIO		101
-#define N810_KB_LOCK_GPIO		102
-#define N800_TSC_TS_GPIO		103
-#define N810_TSC_TS_GPIO		106
-#define N8X0_HEADPHONE_GPIO		107
-#define N8X0_RETU_GPIO			108
-#define N800_TSC_KP_IRQ_GPIO		109
-#define N810_KEYBOARD_GPIO		109
-#define N800_BAT_COVER_GPIO		110
-#define N810_SLIDE_GPIO			110
-#define N8X0_TAHVO_GPIO			111
-#define N800_UNKNOWN_GPIO4		112	/* out */
-#define N810_SLEEPX_LED_GPIO		112
-#define N800_TSC_RESET_GPIO		118	/* ? */
-#define N810_AIC33_RESET_GPIO		118
-#define N800_TSC_UNKNOWN_GPIO		119	/* out */
-#define N8X0_TMP105_GPIO		125
-
-/* Config */
-#define BT_UART				0
-#define XLDR_LL_UART			1
-
-/* Addresses on the I2C bus 0 */
-#define N810_TLV320AIC33_ADDR		0x18	/* Audio CODEC */
-#define N8X0_TCM825x_ADDR		0x29	/* Camera */
-#define N810_LP5521_ADDR		0x32	/* LEDs */
-#define N810_TSL2563_ADDR		0x3d	/* Light sensor */
-#define N810_LM8323_ADDR		0x45	/* Keyboard */
-/* Addresses on the I2C bus 1 */
-#define N8X0_TMP105_ADDR		0x48	/* Temperature sensor */
-#define N8X0_MENELAUS_ADDR		0x72	/* Power management */
-
-/* Chipselects on GPMC NOR interface */
-#define N8X0_ONENAND_CS			0
-#define N8X0_USB_ASYNC_CS		1
-#define N8X0_USB_SYNC_CS		4
-
-#define N8X0_BD_ADDR			0x00, 0x1a, 0x89, 0x9e, 0x3e, 0x81
-
-static void n800_mmc_cs_cb(void *opaque, int line, int level)
-{
-    /* TODO: this seems to actually be connected to the menelaus, to
-     * which also both MMC slots connect.  */
-    omap_mmc_enable((struct omap_mmc_s *) opaque, !level);
-
-    printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);
-}
-
-static void n8x0_gpio_setup(struct n800_s *s)
-{
-    qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->mpu->mmc, 1);
-    qdev_connect_gpio_out(s->mpu->gpio, N8X0_MMC_CS_GPIO, mmc_cs[0]);
-
-    qemu_irq_lower(qdev_get_gpio_in(s->mpu->gpio, N800_BAT_COVER_GPIO));
-}
-
-#define MAEMO_CAL_HEADER(...)				\
-    'C',  'o',  'n',  'F',  0x02, 0x00, 0x04, 0x00,	\
-    __VA_ARGS__,					\
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-static const uint8_t n8x0_cal_wlan_mac[] = {
-    MAEMO_CAL_HEADER('w', 'l', 'a', 'n', '-', 'm', 'a', 'c')
-    0x1c, 0x00, 0x00, 0x00, 0x47, 0xd6, 0x69, 0xb3,
-    0x30, 0x08, 0xa0, 0x83, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
-    0x89, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
-    0x5d, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00,
-};
-
-static const uint8_t n8x0_cal_bt_id[] = {
-    MAEMO_CAL_HEADER('b', 't', '-', 'i', 'd', 0, 0, 0)
-    0x0a, 0x00, 0x00, 0x00, 0xa3, 0x4b, 0xf6, 0x96,
-    0xa8, 0xeb, 0xb2, 0x41, 0x00, 0x00, 0x00, 0x00,
-    N8X0_BD_ADDR,
-};
-
-static void n8x0_nand_setup(struct n800_s *s)
-{
-    char *otp_region;
-    DriveInfo *dinfo;
-
-    s->nand = qdev_create(NULL, "onenand");
-    qdev_prop_set_uint16(s->nand, "manufacturer_id", NAND_MFR_SAMSUNG);
-    /* Either 0x40 or 0x48 are OK for the device ID */
-    qdev_prop_set_uint16(s->nand, "device_id", 0x48);
-    qdev_prop_set_uint16(s->nand, "version_id", 0);
-    qdev_prop_set_int32(s->nand, "shift", 1);
-    dinfo = drive_get(IF_MTD, 0, 0);
-    if (dinfo && dinfo->bdrv) {
-        qdev_prop_set_drive_nofail(s->nand, "drive", dinfo->bdrv);
-    }
-    qdev_init_nofail(s->nand);
-    sysbus_connect_irq(SYS_BUS_DEVICE(s->nand), 0,
-                       qdev_get_gpio_in(s->mpu->gpio, N8X0_ONENAND_GPIO));
-    omap_gpmc_attach(s->mpu->gpmc, N8X0_ONENAND_CS,
-                     sysbus_mmio_get_region(SYS_BUS_DEVICE(s->nand), 0));
-    otp_region = onenand_raw_otp(s->nand);
-
-    memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac));
-    memcpy(otp_region + 0x800, n8x0_cal_bt_id, sizeof(n8x0_cal_bt_id));
-    /* XXX: in theory should also update the OOB for both pages */
-}
-
-static qemu_irq n8x0_system_powerdown;
-
-static void n8x0_powerdown_req(Notifier *n, void *opaque)
-{
-    qemu_irq_raise(n8x0_system_powerdown);
-}
-
-static Notifier n8x0_system_powerdown_notifier = {
-    .notify = n8x0_powerdown_req
-};
-
-static void n8x0_i2c_setup(struct n800_s *s)
-{
-    DeviceState *dev;
-    qemu_irq tmp_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TMP105_GPIO);
-    i2c_bus *i2c = omap_i2c_bus(s->mpu->i2c[0]);
-
-    /* Attach a menelaus PM chip */
-    dev = i2c_create_slave(i2c, "twl92230", N8X0_MENELAUS_ADDR);
-    qdev_connect_gpio_out(dev, 3,
-                          qdev_get_gpio_in(s->mpu->ih[0],
-                                           OMAP_INT_24XX_SYS_NIRQ));
-
-    n8x0_system_powerdown = qdev_get_gpio_in(dev, 3);
-    qemu_register_powerdown_notifier(&n8x0_system_powerdown_notifier);
-
-    /* Attach a TMP105 PM chip (A0 wired to ground) */
-    dev = i2c_create_slave(i2c, "tmp105", N8X0_TMP105_ADDR);
-    qdev_connect_gpio_out(dev, 0, tmp_irq);
-}
-
-/* Touchscreen and keypad controller */
-static MouseTransformInfo n800_pointercal = {
-    .x = 800,
-    .y = 480,
-    .a = { 14560, -68, -3455208, -39, -9621, 35152972, 65536 },
-};
-
-static MouseTransformInfo n810_pointercal = {
-    .x = 800,
-    .y = 480,
-    .a = { 15041, 148, -4731056, 171, -10238, 35933380, 65536 },
-};
-
-#define RETU_KEYCODE	61	/* F3 */
-
-static void n800_key_event(void *opaque, int keycode)
-{
-    struct n800_s *s = (struct n800_s *) opaque;
-    int code = s->keymap[keycode & 0x7f];
-
-    if (code == -1) {
-        if ((keycode & 0x7f) == RETU_KEYCODE)
-            retu_key_event(s->retu, !(keycode & 0x80));
-        return;
-    }
-
-    tsc210x_key_event(s->ts.chip, code, !(keycode & 0x80));
-}
-
-static const int n800_keys[16] = {
-    -1,
-    72,	/* Up */
-    63,	/* Home (F5) */
-    -1,
-    75,	/* Left */
-    28,	/* Enter */
-    77,	/* Right */
-    -1,
-     1,	/* Cycle (ESC) */
-    80,	/* Down */
-    62,	/* Menu (F4) */
-    -1,
-    66,	/* Zoom- (F8) */
-    64,	/* FullScreen (F6) */
-    65,	/* Zoom+ (F7) */
-    -1,
-};
-
-static void n800_tsc_kbd_setup(struct n800_s *s)
-{
-    int i;
-
-    /* XXX: are the three pins inverted inside the chip between the
-     * tsc and the cpu (N4111)?  */
-    qemu_irq penirq = NULL;	/* NC */
-    qemu_irq kbirq = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_KP_IRQ_GPIO);
-    qemu_irq dav = qdev_get_gpio_in(s->mpu->gpio, N800_TSC_TS_GPIO);
-
-    s->ts.chip = tsc2301_init(penirq, kbirq, dav);
-    s->ts.opaque = s->ts.chip->opaque;
-    s->ts.txrx = tsc210x_txrx;
-
-    for (i = 0; i < 0x80; i ++)
-        s->keymap[i] = -1;
-    for (i = 0; i < 0x10; i ++)
-        if (n800_keys[i] >= 0)
-            s->keymap[n800_keys[i]] = i;
-
-    qemu_add_kbd_event_handler(n800_key_event, s);
-
-    tsc210x_set_transform(s->ts.chip, &n800_pointercal);
-}
-
-static void n810_tsc_setup(struct n800_s *s)
-{
-    qemu_irq pintdav = qdev_get_gpio_in(s->mpu->gpio, N810_TSC_TS_GPIO);
-
-    s->ts.opaque = tsc2005_init(pintdav);
-    s->ts.txrx = tsc2005_txrx;
-
-    tsc2005_set_transform(s->ts.opaque, &n810_pointercal);
-}
-
-/* N810 Keyboard controller */
-static void n810_key_event(void *opaque, int keycode)
-{
-    struct n800_s *s = (struct n800_s *) opaque;
-    int code = s->keymap[keycode & 0x7f];
-
-    if (code == -1) {
-        if ((keycode & 0x7f) == RETU_KEYCODE)
-            retu_key_event(s->retu, !(keycode & 0x80));
-        return;
-    }
-
-    lm832x_key_event(s->kbd, code, !(keycode & 0x80));
-}
-
-#define M	0
-
-static int n810_keys[0x80] = {
-    [0x01] = 16,	/* Q */
-    [0x02] = 37,	/* K */
-    [0x03] = 24,	/* O */
-    [0x04] = 25,	/* P */
-    [0x05] = 14,	/* Backspace */
-    [0x06] = 30,	/* A */
-    [0x07] = 31,	/* S */
-    [0x08] = 32,	/* D */
-    [0x09] = 33,	/* F */
-    [0x0a] = 34,	/* G */
-    [0x0b] = 35,	/* H */
-    [0x0c] = 36,	/* J */
-
-    [0x11] = 17,	/* W */
-    [0x12] = 62,	/* Menu (F4) */
-    [0x13] = 38,	/* L */
-    [0x14] = 40,	/* ' (Apostrophe) */
-    [0x16] = 44,	/* Z */
-    [0x17] = 45,	/* X */
-    [0x18] = 46,	/* C */
-    [0x19] = 47,	/* V */
-    [0x1a] = 48,	/* B */
-    [0x1b] = 49,	/* N */
-    [0x1c] = 42,	/* Shift (Left shift) */
-    [0x1f] = 65,	/* Zoom+ (F7) */
-
-    [0x21] = 18,	/* E */
-    [0x22] = 39,	/* ; (Semicolon) */
-    [0x23] = 12,	/* - (Minus) */
-    [0x24] = 13,	/* = (Equal) */
-    [0x2b] = 56,	/* Fn (Left Alt) */
-    [0x2c] = 50,	/* M */
-    [0x2f] = 66,	/* Zoom- (F8) */
-
-    [0x31] = 19,	/* R */
-    [0x32] = 29 | M,	/* Right Ctrl */
-    [0x34] = 57,	/* Space */
-    [0x35] = 51,	/* , (Comma) */
-    [0x37] = 72 | M,	/* Up */
-    [0x3c] = 82 | M,	/* Compose (Insert) */
-    [0x3f] = 64,	/* FullScreen (F6) */
-
-    [0x41] = 20,	/* T */
-    [0x44] = 52,	/* . (Dot) */
-    [0x46] = 77 | M,	/* Right */
-    [0x4f] = 63,	/* Home (F5) */
-    [0x51] = 21,	/* Y */
-    [0x53] = 80 | M,	/* Down */
-    [0x55] = 28,	/* Enter */
-    [0x5f] =  1,	/* Cycle (ESC) */
-
-    [0x61] = 22,	/* U */
-    [0x64] = 75 | M,	/* Left */
-
-    [0x71] = 23,	/* I */
-#if 0
-    [0x75] = 28 | M,	/* KP Enter (KP Enter) */
-#else
-    [0x75] = 15,	/* KP Enter (Tab) */
-#endif
-};
-
-#undef M
-
-static void n810_kbd_setup(struct n800_s *s)
-{
-    qemu_irq kbd_irq = qdev_get_gpio_in(s->mpu->gpio, N810_KEYBOARD_GPIO);
-    int i;
-
-    for (i = 0; i < 0x80; i ++)
-        s->keymap[i] = -1;
-    for (i = 0; i < 0x80; i ++)
-        if (n810_keys[i] > 0)
-            s->keymap[n810_keys[i]] = i;
-
-    qemu_add_kbd_event_handler(n810_key_event, s);
-
-    /* Attach the LM8322 keyboard to the I2C bus,
-     * should happen in n8x0_i2c_setup and s->kbd be initialised here.  */
-    s->kbd = i2c_create_slave(omap_i2c_bus(s->mpu->i2c[0]),
-                           "lm8323", N810_LM8323_ADDR);
-    qdev_connect_gpio_out(s->kbd, 0, kbd_irq);
-}
-
-/* LCD MIPI DBI-C controller (URAL) */
-struct mipid_s {
-    int resp[4];
-    int param[4];
-    int p;
-    int pm;
-    int cmd;
-
-    int sleep;
-    int booster;
-    int te;
-    int selfcheck;
-    int partial;
-    int normal;
-    int vscr;
-    int invert;
-    int onoff;
-    int gamma;
-    uint32_t id;
-};
-
-static void mipid_reset(struct mipid_s *s)
-{
-    if (!s->sleep)
-        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
-
-    s->pm = 0;
-    s->cmd = 0;
-
-    s->sleep = 1;
-    s->booster = 0;
-    s->selfcheck =
-            (1 << 7) |	/* Register loading OK.  */
-            (1 << 5) |	/* The chip is attached.  */
-            (1 << 4);	/* Display glass still in one piece.  */
-    s->te = 0;
-    s->partial = 0;
-    s->normal = 1;
-    s->vscr = 0;
-    s->invert = 0;
-    s->onoff = 1;
-    s->gamma = 0;
-}
-
-static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
-{
-    struct mipid_s *s = (struct mipid_s *) opaque;
-    uint8_t ret;
-
-    if (len > 9)
-        hw_error("%s: FIXME: bad SPI word width %i\n", __FUNCTION__, len);
-
-    if (s->p >= ARRAY_SIZE(s->resp))
-        ret = 0;
-    else
-        ret = s->resp[s->p ++];
-    if (s->pm --> 0)
-        s->param[s->pm] = cmd;
-    else
-        s->cmd = cmd;
-
-    switch (s->cmd) {
-    case 0x00:	/* NOP */
-        break;
-
-    case 0x01:	/* SWRESET */
-        mipid_reset(s);
-        break;
-
-    case 0x02:	/* BSTROFF */
-        s->booster = 0;
-        break;
-    case 0x03:	/* BSTRON */
-        s->booster = 1;
-        break;
-
-    case 0x04:	/* RDDID */
-        s->p = 0;
-        s->resp[0] = (s->id >> 16) & 0xff;
-        s->resp[1] = (s->id >>  8) & 0xff;
-        s->resp[2] = (s->id >>  0) & 0xff;
-        break;
-
-    case 0x06:	/* RD_RED */
-    case 0x07:	/* RD_GREEN */
-        /* XXX the bootloader sometimes issues RD_BLUE meaning RDDID so
-         * for the bootloader one needs to change this.  */
-    case 0x08:	/* RD_BLUE */
-        s->p = 0;
-        /* TODO: return first pixel components */
-        s->resp[0] = 0x01;
-        break;
-
-    case 0x09:	/* RDDST */
-        s->p = 0;
-        s->resp[0] = s->booster << 7;
-        s->resp[1] = (5 << 4) | (s->partial << 2) |
-                (s->sleep << 1) | s->normal;
-        s->resp[2] = (s->vscr << 7) | (s->invert << 5) |
-                (s->onoff << 2) | (s->te << 1) | (s->gamma >> 2);
-        s->resp[3] = s->gamma << 6;
-        break;
-
-    case 0x0a:	/* RDDPM */
-        s->p = 0;
-        s->resp[0] = (s->onoff << 2) | (s->normal << 3) | (s->sleep << 4) |
-                (s->partial << 5) | (s->sleep << 6) | (s->booster << 7);
-        break;
-    case 0x0b:	/* RDDMADCTR */
-        s->p = 0;
-        s->resp[0] = 0;
-        break;
-    case 0x0c:	/* RDDCOLMOD */
-        s->p = 0;
-        s->resp[0] = 5;	/* 65K colours */
-        break;
-    case 0x0d:	/* RDDIM */
-        s->p = 0;
-        s->resp[0] = (s->invert << 5) | (s->vscr << 7) | s->gamma;
-        break;
-    case 0x0e:	/* RDDSM */
-        s->p = 0;
-        s->resp[0] = s->te << 7;
-        break;
-    case 0x0f:	/* RDDSDR */
-        s->p = 0;
-        s->resp[0] = s->selfcheck;
-        break;
-
-    case 0x10:	/* SLPIN */
-        s->sleep = 1;
-        break;
-    case 0x11:	/* SLPOUT */
-        s->sleep = 0;
-        s->selfcheck ^= 1 << 6;	/* POFF self-diagnosis Ok */
-        break;
-
-    case 0x12:	/* PTLON */
-        s->partial = 1;
-        s->normal = 0;
-        s->vscr = 0;
-        break;
-    case 0x13:	/* NORON */
-        s->partial = 0;
-        s->normal = 1;
-        s->vscr = 0;
-        break;
-
-    case 0x20:	/* INVOFF */
-        s->invert = 0;
-        break;
-    case 0x21:	/* INVON */
-        s->invert = 1;
-        break;
-
-    case 0x22:	/* APOFF */
-    case 0x23:	/* APON */
-        goto bad_cmd;
-
-    case 0x25:	/* WRCNTR */
-        if (s->pm < 0)
-            s->pm = 1;
-        goto bad_cmd;
-
-    case 0x26:	/* GAMSET */
-        if (!s->pm)
-            s->gamma = ffs(s->param[0] & 0xf) - 1;
-        else if (s->pm < 0)
-            s->pm = 1;
-        break;
-
-    case 0x28:	/* DISPOFF */
-        s->onoff = 0;
-        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
-        break;
-    case 0x29:	/* DISPON */
-        s->onoff = 1;
-        fprintf(stderr, "%s: Display on\n", __FUNCTION__);
-        break;
-
-    case 0x2a:	/* CASET */
-    case 0x2b:	/* RASET */
-    case 0x2c:	/* RAMWR */
-    case 0x2d:	/* RGBSET */
-    case 0x2e:	/* RAMRD */
-    case 0x30:	/* PTLAR */
-    case 0x33:	/* SCRLAR */
-        goto bad_cmd;
-
-    case 0x34:	/* TEOFF */
-        s->te = 0;
-        break;
-    case 0x35:	/* TEON */
-        if (!s->pm)
-            s->te = 1;
-        else if (s->pm < 0)
-            s->pm = 1;
-        break;
-
-    case 0x36:	/* MADCTR */
-        goto bad_cmd;
-
-    case 0x37:	/* VSCSAD */
-        s->partial = 0;
-        s->normal = 0;
-        s->vscr = 1;
-        break;
-
-    case 0x38:	/* IDMOFF */
-    case 0x39:	/* IDMON */
-    case 0x3a:	/* COLMOD */
-        goto bad_cmd;
-
-    case 0xb0:	/* CLKINT / DISCTL */
-    case 0xb1:	/* CLKEXT */
-        if (s->pm < 0)
-            s->pm = 2;
-        break;
-
-    case 0xb4:	/* FRMSEL */
-        break;
-
-    case 0xb5:	/* FRM8SEL */
-    case 0xb6:	/* TMPRNG / INIESC */
-    case 0xb7:	/* TMPHIS / NOP2 */
-    case 0xb8:	/* TMPREAD / MADCTL */
-    case 0xba:	/* DISTCTR */
-    case 0xbb:	/* EPVOL */
-        goto bad_cmd;
-
-    case 0xbd:	/* Unknown */
-        s->p = 0;
-        s->resp[0] = 0;
-        s->resp[1] = 1;
-        break;
-
-    case 0xc2:	/* IFMOD */
-        if (s->pm < 0)
-            s->pm = 2;
-        break;
-
-    case 0xc6:	/* PWRCTL */
-    case 0xc7:	/* PPWRCTL */
-    case 0xd0:	/* EPWROUT */
-    case 0xd1:	/* EPWRIN */
-    case 0xd4:	/* RDEV */
-    case 0xd5:	/* RDRR */
-        goto bad_cmd;
-
-    case 0xda:	/* RDID1 */
-        s->p = 0;
-        s->resp[0] = (s->id >> 16) & 0xff;
-        break;
-    case 0xdb:	/* RDID2 */
-        s->p = 0;
-        s->resp[0] = (s->id >>  8) & 0xff;
-        break;
-    case 0xdc:	/* RDID3 */
-        s->p = 0;
-        s->resp[0] = (s->id >>  0) & 0xff;
-        break;
-
-    default:
-    bad_cmd:
-        fprintf(stderr, "%s: unknown command %02x\n", __FUNCTION__, s->cmd);
-        break;
-    }
-
-    return ret;
-}
-
-static void *mipid_init(void)
-{
-    struct mipid_s *s = (struct mipid_s *) g_malloc0(sizeof(*s));
-
-    s->id = 0x838f03;
-    mipid_reset(s);
-
-    return s;
-}
-
-static void n8x0_spi_setup(struct n800_s *s)
-{
-    void *tsc = s->ts.opaque;
-    void *mipid = mipid_init();
-
-    omap_mcspi_attach(s->mpu->mcspi[0], s->ts.txrx, tsc, 0);
-    omap_mcspi_attach(s->mpu->mcspi[0], mipid_txrx, mipid, 1);
-}
-
-/* This task is normally performed by the bootloader.  If we're loading
- * a kernel directly, we need to enable the Blizzard ourselves.  */
-static void n800_dss_init(struct rfbi_chip_s *chip)
-{
-    uint8_t *fb_blank;
-
-    chip->write(chip->opaque, 0, 0x2a);		/* LCD Width register */
-    chip->write(chip->opaque, 1, 0x64);
-    chip->write(chip->opaque, 0, 0x2c);		/* LCD HNDP register */
-    chip->write(chip->opaque, 1, 0x1e);
-    chip->write(chip->opaque, 0, 0x2e);		/* LCD Height 0 register */
-    chip->write(chip->opaque, 1, 0xe0);
-    chip->write(chip->opaque, 0, 0x30);		/* LCD Height 1 register */
-    chip->write(chip->opaque, 1, 0x01);
-    chip->write(chip->opaque, 0, 0x32);		/* LCD VNDP register */
-    chip->write(chip->opaque, 1, 0x06);
-    chip->write(chip->opaque, 0, 0x68);		/* Display Mode register */
-    chip->write(chip->opaque, 1, 1);		/* Enable bit */
-
-    chip->write(chip->opaque, 0, 0x6c);	
-    chip->write(chip->opaque, 1, 0x00);		/* Input X Start Position */
-    chip->write(chip->opaque, 1, 0x00);		/* Input X Start Position */
-    chip->write(chip->opaque, 1, 0x00);		/* Input Y Start Position */
-    chip->write(chip->opaque, 1, 0x00);		/* Input Y Start Position */
-    chip->write(chip->opaque, 1, 0x1f);		/* Input X End Position */
-    chip->write(chip->opaque, 1, 0x03);		/* Input X End Position */
-    chip->write(chip->opaque, 1, 0xdf);		/* Input Y End Position */
-    chip->write(chip->opaque, 1, 0x01);		/* Input Y End Position */
-    chip->write(chip->opaque, 1, 0x00);		/* Output X Start Position */
-    chip->write(chip->opaque, 1, 0x00);		/* Output X Start Position */
-    chip->write(chip->opaque, 1, 0x00);		/* Output Y Start Position */
-    chip->write(chip->opaque, 1, 0x00);		/* Output Y Start Position */
-    chip->write(chip->opaque, 1, 0x1f);		/* Output X End Position */
-    chip->write(chip->opaque, 1, 0x03);		/* Output X End Position */
-    chip->write(chip->opaque, 1, 0xdf);		/* Output Y End Position */
-    chip->write(chip->opaque, 1, 0x01);		/* Output Y End Position */
-    chip->write(chip->opaque, 1, 0x01);		/* Input Data Format */
-    chip->write(chip->opaque, 1, 0x01);		/* Data Source Select */
-
-    fb_blank = memset(g_malloc(800 * 480 * 2), 0xff, 800 * 480 * 2);
-    /* Display Memory Data Port */
-    chip->block(chip->opaque, 1, fb_blank, 800 * 480 * 2, 800);
-    g_free(fb_blank);
-}
-
-static void n8x0_dss_setup(struct n800_s *s)
-{
-    s->blizzard.opaque = s1d13745_init(NULL);
-    s->blizzard.block = s1d13745_write_block;
-    s->blizzard.write = s1d13745_write;
-    s->blizzard.read = s1d13745_read;
-
-    omap_rfbi_attach(s->mpu->dss, 0, &s->blizzard);
-}
-
-static void n8x0_cbus_setup(struct n800_s *s)
-{
-    qemu_irq dat_out = qdev_get_gpio_in(s->mpu->gpio, N8X0_CBUS_DAT_GPIO);
-    qemu_irq retu_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_RETU_GPIO);
-    qemu_irq tahvo_irq = qdev_get_gpio_in(s->mpu->gpio, N8X0_TAHVO_GPIO);
-
-    CBus *cbus = cbus_init(dat_out);
-
-    qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_CLK_GPIO, cbus->clk);
-    qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_DAT_GPIO, cbus->dat);
-    qdev_connect_gpio_out(s->mpu->gpio, N8X0_CBUS_SEL_GPIO, cbus->sel);
-
-    cbus_attach(cbus, s->retu = retu_init(retu_irq, 1));
-    cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1));
-}
-
-static void n8x0_uart_setup(struct n800_s *s)
-{
-    CharDriverState *radio = uart_hci_init(
-                    qdev_get_gpio_in(s->mpu->gpio, N8X0_BT_HOST_WKUP_GPIO));
-
-    qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_RESET_GPIO,
-                    csrhci_pins_get(radio)[csrhci_pin_reset]);
-    qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_WKUP_GPIO,
-                    csrhci_pins_get(radio)[csrhci_pin_wakeup]);
-
-    omap_uart_attach(s->mpu->uart[BT_UART], radio);
-}
-
-static void n8x0_usb_setup(struct n800_s *s)
-{
-    SysBusDevice *dev;
-    s->usb = qdev_create(NULL, "tusb6010");
-    dev = SYS_BUS_DEVICE(s->usb);
-    qdev_init_nofail(s->usb);
-    sysbus_connect_irq(dev, 0,
-                       qdev_get_gpio_in(s->mpu->gpio, N8X0_TUSB_INT_GPIO));
-    /* Using the NOR interface */
-    omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_ASYNC_CS,
-                     sysbus_mmio_get_region(dev, 0));
-    omap_gpmc_attach(s->mpu->gpmc, N8X0_USB_SYNC_CS,
-                     sysbus_mmio_get_region(dev, 1));
-    qdev_connect_gpio_out(s->mpu->gpio, N8X0_TUSB_ENABLE_GPIO,
-                          qdev_get_gpio_in(s->usb, 0)); /* tusb_pwr */
-}
-
-/* Setup done before the main bootloader starts by some early setup code
- * - used when we want to run the main bootloader in emulation.  This
- * isn't documented.  */
-static uint32_t n800_pinout[104] = {
-    0x080f00d8, 0x00d40808, 0x03080808, 0x080800d0,
-    0x00dc0808, 0x0b0f0f00, 0x080800b4, 0x00c00808,
-    0x08080808, 0x180800c4, 0x00b80000, 0x08080808,
-    0x080800bc, 0x00cc0808, 0x08081818, 0x18180128,
-    0x01241800, 0x18181818, 0x000000f0, 0x01300000,
-    0x00001b0b, 0x1b0f0138, 0x00e0181b, 0x1b031b0b,
-    0x180f0078, 0x00740018, 0x0f0f0f1a, 0x00000080,
-    0x007c0000, 0x00000000, 0x00000088, 0x00840000,
-    0x00000000, 0x00000094, 0x00980300, 0x0f180003,
-    0x0000008c, 0x00900f0f, 0x0f0f1b00, 0x0f00009c,
-    0x01140000, 0x1b1b0f18, 0x0818013c, 0x01400008,
-    0x00001818, 0x000b0110, 0x010c1800, 0x0b030b0f,
-    0x181800f4, 0x00f81818, 0x00000018, 0x000000fc,
-    0x00401808, 0x00000000, 0x0f1b0030, 0x003c0008,
-    0x00000000, 0x00000038, 0x00340000, 0x00000000,
-    0x1a080070, 0x00641a1a, 0x08080808, 0x08080060,
-    0x005c0808, 0x08080808, 0x08080058, 0x00540808,
-    0x08080808, 0x0808006c, 0x00680808, 0x08080808,
-    0x000000a8, 0x00b00000, 0x08080808, 0x000000a0,
-    0x00a40000, 0x00000000, 0x08ff0050, 0x004c0808,
-    0xffffffff, 0xffff0048, 0x0044ffff, 0xffffffff,
-    0x000000ac, 0x01040800, 0x08080b0f, 0x18180100,
-    0x01081818, 0x0b0b1808, 0x1a0300e4, 0x012c0b1a,
-    0x02020018, 0x0b000134, 0x011c0800, 0x0b1b1b00,
-    0x0f0000c8, 0x00ec181b, 0x000f0f02, 0x00180118,
-    0x01200000, 0x0f0b1b1b, 0x0f0200e8, 0x0000020b,
-};
-
-static void n800_setup_nolo_tags(void *sram_base)
-{
-    int i;
-    uint32_t *p = sram_base + 0x8000;
-    uint32_t *v = sram_base + 0xa000;
-
-    memset(p, 0, 0x3000);
-
-    strcpy((void *) (p + 0), "QEMU N800");
-
-    strcpy((void *) (p + 8), "F5");
-
-    stl_raw(p + 10, 0x04f70000);
-    strcpy((void *) (p + 9), "RX-34");
-
-    /* RAM size in MB? */
-    stl_raw(p + 12, 0x80);
-
-    /* Pointer to the list of tags */
-    stl_raw(p + 13, OMAP2_SRAM_BASE + 0x9000);
-
-    /* The NOLO tags start here */
-    p = sram_base + 0x9000;
-#define ADD_TAG(tag, len)				\
-    stw_raw((uint16_t *) p + 0, tag);			\
-    stw_raw((uint16_t *) p + 1, len); p ++;		\
-    stl_raw(p ++, OMAP2_SRAM_BASE | (((void *) v - sram_base) & 0xffff));
-
-    /* OMAP STI console? Pin out settings? */
-    ADD_TAG(0x6e01, 414);
-    for (i = 0; i < ARRAY_SIZE(n800_pinout); i ++)
-        stl_raw(v ++, n800_pinout[i]);
-
-    /* Kernel memsize? */
-    ADD_TAG(0x6e05, 1);
-    stl_raw(v ++, 2);
-
-    /* NOLO serial console */
-    ADD_TAG(0x6e02, 4);
-    stl_raw(v ++, XLDR_LL_UART);	/* UART number (1 - 3) */
-
-#if 0
-    /* CBUS settings (Retu/AVilma) */
-    ADD_TAG(0x6e03, 6);
-    stw_raw((uint16_t *) v + 0, 65);	/* CBUS GPIO0 */
-    stw_raw((uint16_t *) v + 1, 66);	/* CBUS GPIO1 */
-    stw_raw((uint16_t *) v + 2, 64);	/* CBUS GPIO2 */
-    v += 2;
-#endif
-
-    /* Nokia ASIC BB5 (Retu/Tahvo) */
-    ADD_TAG(0x6e0a, 4);
-    stw_raw((uint16_t *) v + 0, 111);	/* "Retu" interrupt GPIO */
-    stw_raw((uint16_t *) v + 1, 108);	/* "Tahvo" interrupt GPIO */
-    v ++;
-
-    /* LCD console? */
-    ADD_TAG(0x6e04, 4);
-    stw_raw((uint16_t *) v + 0, 30);	/* ??? */
-    stw_raw((uint16_t *) v + 1, 24);	/* ??? */
-    v ++;
-
-#if 0
-    /* LCD settings */
-    ADD_TAG(0x6e06, 2);
-    stw_raw((uint16_t *) (v ++), 15);	/* ??? */
-#endif
-
-    /* I^2C (Menelaus) */
-    ADD_TAG(0x6e07, 4);
-    stl_raw(v ++, 0x00720000);		/* ??? */
-
-    /* Unknown */
-    ADD_TAG(0x6e0b, 6);
-    stw_raw((uint16_t *) v + 0, 94);	/* ??? */
-    stw_raw((uint16_t *) v + 1, 23);	/* ??? */
-    stw_raw((uint16_t *) v + 2, 0);	/* ??? */
-    v += 2;
-
-    /* OMAP gpio switch info */
-    ADD_TAG(0x6e0c, 80);
-    strcpy((void *) v, "bat_cover");	v += 3;
-    stw_raw((uint16_t *) v + 0, 110);	/* GPIO num ??? */
-    stw_raw((uint16_t *) v + 1, 1);	/* GPIO num ??? */
-    v += 2;
-    strcpy((void *) v, "cam_act");	v += 3;
-    stw_raw((uint16_t *) v + 0, 95);	/* GPIO num ??? */
-    stw_raw((uint16_t *) v + 1, 32);	/* GPIO num ??? */
-    v += 2;
-    strcpy((void *) v, "cam_turn");	v += 3;
-    stw_raw((uint16_t *) v + 0, 12);	/* GPIO num ??? */
-    stw_raw((uint16_t *) v + 1, 33);	/* GPIO num ??? */
-    v += 2;
-    strcpy((void *) v, "headphone");	v += 3;
-    stw_raw((uint16_t *) v + 0, 107);	/* GPIO num ??? */
-    stw_raw((uint16_t *) v + 1, 17);	/* GPIO num ??? */
-    v += 2;
-
-    /* Bluetooth */
-    ADD_TAG(0x6e0e, 12);
-    stl_raw(v ++, 0x5c623d01);		/* ??? */
-    stl_raw(v ++, 0x00000201);		/* ??? */
-    stl_raw(v ++, 0x00000000);		/* ??? */
-
-    /* CX3110x WLAN settings */
-    ADD_TAG(0x6e0f, 8);
-    stl_raw(v ++, 0x00610025);		/* ??? */
-    stl_raw(v ++, 0xffff0057);		/* ??? */
-
-    /* MMC host settings */
-    ADD_TAG(0x6e10, 12);
-    stl_raw(v ++, 0xffff000f);		/* ??? */
-    stl_raw(v ++, 0xffffffff);		/* ??? */
-    stl_raw(v ++, 0x00000060);		/* ??? */
-
-    /* OneNAND chip select */
-    ADD_TAG(0x6e11, 10);
-    stl_raw(v ++, 0x00000401);		/* ??? */
-    stl_raw(v ++, 0x0002003a);		/* ??? */
-    stl_raw(v ++, 0x00000002);		/* ??? */
-
-    /* TEA5761 sensor settings */
-    ADD_TAG(0x6e12, 2);
-    stl_raw(v ++, 93);			/* GPIO num ??? */
-
-#if 0
-    /* Unknown tag */
-    ADD_TAG(6e09, 0);
-
-    /* Kernel UART / console */
-    ADD_TAG(6e12, 0);
-#endif
-
-    /* End of the list */
-    stl_raw(p ++, 0x00000000);
-    stl_raw(p ++, 0x00000000);
-}
-
-/* This task is normally performed by the bootloader.  If we're loading
- * a kernel directly, we need to set up GPMC mappings ourselves.  */
-static void n800_gpmc_init(struct n800_s *s)
-{
-    uint32_t config7 =
-            (0xf << 8) |	/* MASKADDRESS */
-            (1 << 6) |		/* CSVALID */
-            (4 << 0);		/* BASEADDRESS */
-
-    cpu_physical_memory_write(0x6800a078,		/* GPMC_CONFIG7_0 */
-                    (void *) &config7, sizeof(config7));
-}
-
-/* Setup sequence done by the bootloader */
-static void n8x0_boot_init(void *opaque)
-{
-    struct n800_s *s = (struct n800_s *) opaque;
-    uint32_t buf;
-
-    /* PRCM setup */
-#define omap_writel(addr, val)	\
-    buf = (val);			\
-    cpu_physical_memory_write(addr, (void *) &buf, sizeof(buf))
-
-    omap_writel(0x48008060, 0x41);		/* PRCM_CLKSRC_CTRL */
-    omap_writel(0x48008070, 1);			/* PRCM_CLKOUT_CTRL */
-    omap_writel(0x48008078, 0);			/* PRCM_CLKEMUL_CTRL */
-    omap_writel(0x48008090, 0);			/* PRCM_VOLTSETUP */
-    omap_writel(0x48008094, 0);			/* PRCM_CLKSSETUP */
-    omap_writel(0x48008098, 0);			/* PRCM_POLCTRL */
-    omap_writel(0x48008140, 2);			/* CM_CLKSEL_MPU */
-    omap_writel(0x48008148, 0);			/* CM_CLKSTCTRL_MPU */
-    omap_writel(0x48008158, 1);			/* RM_RSTST_MPU */
-    omap_writel(0x480081c8, 0x15);		/* PM_WKDEP_MPU */
-    omap_writel(0x480081d4, 0x1d4);		/* PM_EVGENCTRL_MPU */
-    omap_writel(0x480081d8, 0);			/* PM_EVEGENONTIM_MPU */
-    omap_writel(0x480081dc, 0);			/* PM_EVEGENOFFTIM_MPU */
-    omap_writel(0x480081e0, 0xc);		/* PM_PWSTCTRL_MPU */
-    omap_writel(0x48008200, 0x047e7ff7);	/* CM_FCLKEN1_CORE */
-    omap_writel(0x48008204, 0x00000004);	/* CM_FCLKEN2_CORE */
-    omap_writel(0x48008210, 0x047e7ff1);	/* CM_ICLKEN1_CORE */
-    omap_writel(0x48008214, 0x00000004);	/* CM_ICLKEN2_CORE */
-    omap_writel(0x4800821c, 0x00000000);	/* CM_ICLKEN4_CORE */
-    omap_writel(0x48008230, 0);			/* CM_AUTOIDLE1_CORE */
-    omap_writel(0x48008234, 0);			/* CM_AUTOIDLE2_CORE */
-    omap_writel(0x48008238, 7);			/* CM_AUTOIDLE3_CORE */
-    omap_writel(0x4800823c, 0);			/* CM_AUTOIDLE4_CORE */
-    omap_writel(0x48008240, 0x04360626);	/* CM_CLKSEL1_CORE */
-    omap_writel(0x48008244, 0x00000014);	/* CM_CLKSEL2_CORE */
-    omap_writel(0x48008248, 0);			/* CM_CLKSTCTRL_CORE */
-    omap_writel(0x48008300, 0x00000000);	/* CM_FCLKEN_GFX */
-    omap_writel(0x48008310, 0x00000000);	/* CM_ICLKEN_GFX */
-    omap_writel(0x48008340, 0x00000001);	/* CM_CLKSEL_GFX */
-    omap_writel(0x48008400, 0x00000004);	/* CM_FCLKEN_WKUP */
-    omap_writel(0x48008410, 0x00000004);	/* CM_ICLKEN_WKUP */
-    omap_writel(0x48008440, 0x00000000);	/* CM_CLKSEL_WKUP */
-    omap_writel(0x48008500, 0x000000cf);	/* CM_CLKEN_PLL */
-    omap_writel(0x48008530, 0x0000000c);	/* CM_AUTOIDLE_PLL */
-    omap_writel(0x48008540,			/* CM_CLKSEL1_PLL */
-                    (0x78 << 12) | (6 << 8));
-    omap_writel(0x48008544, 2);			/* CM_CLKSEL2_PLL */
-
-    /* GPMC setup */
-    n800_gpmc_init(s);
-
-    /* Video setup */
-    n800_dss_init(&s->blizzard);
-
-    /* CPU setup */
-    s->mpu->cpu->env.GE = 0x5;
-
-    /* If the machine has a slided keyboard, open it */
-    if (s->kbd)
-        qemu_irq_raise(qdev_get_gpio_in(s->mpu->gpio, N810_SLIDE_GPIO));
-}
-
-#define OMAP_TAG_NOKIA_BT	0x4e01
-#define OMAP_TAG_WLAN_CX3110X	0x4e02
-#define OMAP_TAG_CBUS		0x4e03
-#define OMAP_TAG_EM_ASIC_BB5	0x4e04
-
-static struct omap_gpiosw_info_s {
-    const char *name;
-    int line;
-    int type;
-} n800_gpiosw_info[] = {
-    {
-        "bat_cover", N800_BAT_COVER_GPIO,
-        OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
-    }, {
-        "cam_act", N800_CAM_ACT_GPIO,
-        OMAP_GPIOSW_TYPE_ACTIVITY,
-    }, {
-        "cam_turn", N800_CAM_TURN_GPIO,
-        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED,
-    }, {
-        "headphone", N8X0_HEADPHONE_GPIO,
-        OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED,
-    },
-    { NULL }
-}, n810_gpiosw_info[] = {
-    {
-        "gps_reset", N810_GPS_RESET_GPIO,
-        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT,
-    }, {
-        "gps_wakeup", N810_GPS_WAKEUP_GPIO,
-        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_OUTPUT,
-    }, {
-        "headphone", N8X0_HEADPHONE_GPIO,
-        OMAP_GPIOSW_TYPE_CONNECTION | OMAP_GPIOSW_INVERTED,
-    }, {
-        "kb_lock", N810_KB_LOCK_GPIO,
-        OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
-    }, {
-        "sleepx_led", N810_SLEEPX_LED_GPIO,
-        OMAP_GPIOSW_TYPE_ACTIVITY | OMAP_GPIOSW_INVERTED | OMAP_GPIOSW_OUTPUT,
-    }, {
-        "slide", N810_SLIDE_GPIO,
-        OMAP_GPIOSW_TYPE_COVER | OMAP_GPIOSW_INVERTED,
-    },
-    { NULL }
-};
-
-static struct omap_partition_info_s {
-    uint32_t offset;
-    uint32_t size;
-    int mask;
-    const char *name;
-} n800_part_info[] = {
-    { 0x00000000, 0x00020000, 0x3, "bootloader" },
-    { 0x00020000, 0x00060000, 0x0, "config" },
-    { 0x00080000, 0x00200000, 0x0, "kernel" },
-    { 0x00280000, 0x00200000, 0x3, "initfs" },
-    { 0x00480000, 0x0fb80000, 0x3, "rootfs" },
-
-    { 0, 0, 0, NULL }
-}, n810_part_info[] = {
-    { 0x00000000, 0x00020000, 0x3, "bootloader" },
-    { 0x00020000, 0x00060000, 0x0, "config" },
-    { 0x00080000, 0x00220000, 0x0, "kernel" },
-    { 0x002a0000, 0x00400000, 0x0, "initfs" },
-    { 0x006a0000, 0x0f960000, 0x0, "rootfs" },
-
-    { 0, 0, 0, NULL }
-};
-
-static bdaddr_t n8x0_bd_addr = {{ N8X0_BD_ADDR }};
-
-static int n8x0_atag_setup(void *p, int model)
-{
-    uint8_t *b;
-    uint16_t *w;
-    uint32_t *l;
-    struct omap_gpiosw_info_s *gpiosw;
-    struct omap_partition_info_s *partition;
-    const char *tag;
-
-    w = p;
-
-    stw_raw(w ++, OMAP_TAG_UART);		/* u16 tag */
-    stw_raw(w ++, 4);				/* u16 len */
-    stw_raw(w ++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
-    w ++;
-
-#if 0
-    stw_raw(w ++, OMAP_TAG_SERIAL_CONSOLE);	/* u16 tag */
-    stw_raw(w ++, 4);				/* u16 len */
-    stw_raw(w ++, XLDR_LL_UART + 1);		/* u8 console_uart */
-    stw_raw(w ++, 115200);			/* u32 console_speed */
-#endif
-
-    stw_raw(w ++, OMAP_TAG_LCD);		/* u16 tag */
-    stw_raw(w ++, 36);				/* u16 len */
-    strcpy((void *) w, "QEMU LCD panel");	/* char panel_name[16] */
-    w += 8;
-    strcpy((void *) w, "blizzard");		/* char ctrl_name[16] */
-    w += 8;
-    stw_raw(w ++, N810_BLIZZARD_RESET_GPIO);	/* TODO: n800 s16 nreset_gpio */
-    stw_raw(w ++, 24);				/* u8 data_lines */
-
-    stw_raw(w ++, OMAP_TAG_CBUS);		/* u16 tag */
-    stw_raw(w ++, 8);				/* u16 len */
-    stw_raw(w ++, N8X0_CBUS_CLK_GPIO);		/* s16 clk_gpio */
-    stw_raw(w ++, N8X0_CBUS_DAT_GPIO);		/* s16 dat_gpio */
-    stw_raw(w ++, N8X0_CBUS_SEL_GPIO);		/* s16 sel_gpio */
-    w ++;
-
-    stw_raw(w ++, OMAP_TAG_EM_ASIC_BB5);	/* u16 tag */
-    stw_raw(w ++, 4);				/* u16 len */
-    stw_raw(w ++, N8X0_RETU_GPIO);		/* s16 retu_irq_gpio */
-    stw_raw(w ++, N8X0_TAHVO_GPIO);		/* s16 tahvo_irq_gpio */
-
-    gpiosw = (model == 810) ? n810_gpiosw_info : n800_gpiosw_info;
-    for (; gpiosw->name; gpiosw ++) {
-        stw_raw(w ++, OMAP_TAG_GPIO_SWITCH);	/* u16 tag */
-        stw_raw(w ++, 20);			/* u16 len */
-        strcpy((void *) w, gpiosw->name);	/* char name[12] */
-        w += 6;
-        stw_raw(w ++, gpiosw->line);		/* u16 gpio */
-        stw_raw(w ++, gpiosw->type);
-        stw_raw(w ++, 0);
-        stw_raw(w ++, 0);
-    }
-
-    stw_raw(w ++, OMAP_TAG_NOKIA_BT);		/* u16 tag */
-    stw_raw(w ++, 12);				/* u16 len */
-    b = (void *) w;
-    stb_raw(b ++, 0x01);			/* u8 chip_type	(CSR) */
-    stb_raw(b ++, N8X0_BT_WKUP_GPIO);		/* u8 bt_wakeup_gpio */
-    stb_raw(b ++, N8X0_BT_HOST_WKUP_GPIO);	/* u8 host_wakeup_gpio */
-    stb_raw(b ++, N8X0_BT_RESET_GPIO);		/* u8 reset_gpio */
-    stb_raw(b ++, BT_UART + 1);			/* u8 bt_uart */
-    memcpy(b, &n8x0_bd_addr, 6);		/* u8 bd_addr[6] */
-    b += 6;
-    stb_raw(b ++, 0x02);			/* u8 bt_sysclk (38.4) */
-    w = (void *) b;
-
-    stw_raw(w ++, OMAP_TAG_WLAN_CX3110X);	/* u16 tag */
-    stw_raw(w ++, 8);				/* u16 len */
-    stw_raw(w ++, 0x25);			/* u8 chip_type */
-    stw_raw(w ++, N8X0_WLAN_PWR_GPIO);		/* s16 power_gpio */
-    stw_raw(w ++, N8X0_WLAN_IRQ_GPIO);		/* s16 irq_gpio */
-    stw_raw(w ++, -1);				/* s16 spi_cs_gpio */
-
-    stw_raw(w ++, OMAP_TAG_MMC);		/* u16 tag */
-    stw_raw(w ++, 16);				/* u16 len */
-    if (model == 810) {
-        stw_raw(w ++, 0x23f);			/* unsigned flags */
-        stw_raw(w ++, -1);			/* s16 power_pin */
-        stw_raw(w ++, -1);			/* s16 switch_pin */
-        stw_raw(w ++, -1);			/* s16 wp_pin */
-        stw_raw(w ++, 0x240);			/* unsigned flags */
-        stw_raw(w ++, 0xc000);			/* s16 power_pin */
-        stw_raw(w ++, 0x0248);			/* s16 switch_pin */
-        stw_raw(w ++, 0xc000);			/* s16 wp_pin */
-    } else {
-        stw_raw(w ++, 0xf);			/* unsigned flags */
-        stw_raw(w ++, -1);			/* s16 power_pin */
-        stw_raw(w ++, -1);			/* s16 switch_pin */
-        stw_raw(w ++, -1);			/* s16 wp_pin */
-        stw_raw(w ++, 0);			/* unsigned flags */
-        stw_raw(w ++, 0);			/* s16 power_pin */
-        stw_raw(w ++, 0);			/* s16 switch_pin */
-        stw_raw(w ++, 0);			/* s16 wp_pin */
-    }
-
-    stw_raw(w ++, OMAP_TAG_TEA5761);		/* u16 tag */
-    stw_raw(w ++, 4);				/* u16 len */
-    stw_raw(w ++, N8X0_TEA5761_CS_GPIO);	/* u16 enable_gpio */
-    w ++;
-
-    partition = (model == 810) ? n810_part_info : n800_part_info;
-    for (; partition->name; partition ++) {
-        stw_raw(w ++, OMAP_TAG_PARTITION);	/* u16 tag */
-        stw_raw(w ++, 28);			/* u16 len */
-        strcpy((void *) w, partition->name);	/* char name[16] */
-        l = (void *) (w + 8);
-        stl_raw(l ++, partition->size);		/* unsigned int size */
-        stl_raw(l ++, partition->offset);	/* unsigned int offset */
-        stl_raw(l ++, partition->mask);		/* unsigned int mask_flags */
-        w = (void *) l;
-    }
-
-    stw_raw(w ++, OMAP_TAG_BOOT_REASON);	/* u16 tag */
-    stw_raw(w ++, 12);				/* u16 len */
-#if 0
-    strcpy((void *) w, "por");			/* char reason_str[12] */
-    strcpy((void *) w, "charger");		/* char reason_str[12] */
-    strcpy((void *) w, "32wd_to");		/* char reason_str[12] */
-    strcpy((void *) w, "sw_rst");		/* char reason_str[12] */
-    strcpy((void *) w, "mbus");			/* char reason_str[12] */
-    strcpy((void *) w, "unknown");		/* char reason_str[12] */
-    strcpy((void *) w, "swdg_to");		/* char reason_str[12] */
-    strcpy((void *) w, "sec_vio");		/* char reason_str[12] */
-    strcpy((void *) w, "pwr_key");		/* char reason_str[12] */
-    strcpy((void *) w, "rtc_alarm");		/* char reason_str[12] */
-#else
-    strcpy((void *) w, "pwr_key");		/* char reason_str[12] */
-#endif
-    w += 6;
-
-    tag = (model == 810) ? "RX-44" : "RX-34";
-    stw_raw(w ++, OMAP_TAG_VERSION_STR);	/* u16 tag */
-    stw_raw(w ++, 24);				/* u16 len */
-    strcpy((void *) w, "product");		/* char component[12] */
-    w += 6;
-    strcpy((void *) w, tag);			/* char version[12] */
-    w += 6;
-
-    stw_raw(w ++, OMAP_TAG_VERSION_STR);	/* u16 tag */
-    stw_raw(w ++, 24);				/* u16 len */
-    strcpy((void *) w, "hw-build");		/* char component[12] */
-    w += 6;
-    strcpy((void *) w, "QEMU ");
-    pstrcat((void *) w, 12, qemu_get_version()); /* char version[12] */
-    w += 6;
-
-    tag = (model == 810) ? "1.1.10-qemu" : "1.1.6-qemu";
-    stw_raw(w ++, OMAP_TAG_VERSION_STR);	/* u16 tag */
-    stw_raw(w ++, 24);				/* u16 len */
-    strcpy((void *) w, "nolo");			/* char component[12] */
-    w += 6;
-    strcpy((void *) w, tag);			/* char version[12] */
-    w += 6;
-
-    return (void *) w - p;
-}
-
-static int n800_atag_setup(const struct arm_boot_info *info, void *p)
-{
-    return n8x0_atag_setup(p, 800);
-}
-
-static int n810_atag_setup(const struct arm_boot_info *info, void *p)
-{
-    return n8x0_atag_setup(p, 810);
-}
-
-static void n8x0_init(QEMUMachineInitArgs *args,
-                      struct arm_boot_info *binfo, int model)
-{
-    MemoryRegion *sysmem = get_system_memory();
-    struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s));
-    int sdram_size = binfo->ram_size;
-    DisplayState *ds;
-
-    s->mpu = omap2420_mpu_init(sysmem, sdram_size, args->cpu_model);
-
-    /* Setup peripherals
-     *
-     * Believed external peripherals layout in the N810:
-     * (spi bus 1)
-     *   tsc2005
-     *   lcd_mipid
-     * (spi bus 2)
-     *   Conexant cx3110x (WLAN)
-     *   optional: pc2400m (WiMAX)
-     * (i2c bus 0)
-     *   TLV320AIC33 (audio codec)
-     *   TCM825x (camera by Toshiba)
-     *   lp5521 (clever LEDs)
-     *   tsl2563 (light sensor, hwmon, model 7, rev. 0)
-     *   lm8323 (keypad, manf 00, rev 04)
-     * (i2c bus 1)
-     *   tmp105 (temperature sensor, hwmon)
-     *   menelaus (pm)
-     * (somewhere on i2c - maybe N800-only)
-     *   tea5761 (FM tuner)
-     * (serial 0)
-     *   GPS
-     * (some serial port)
-     *   csr41814 (Bluetooth)
-     */
-    n8x0_gpio_setup(s);
-    n8x0_nand_setup(s);
-    n8x0_i2c_setup(s);
-    if (model == 800)
-        n800_tsc_kbd_setup(s);
-    else if (model == 810) {
-        n810_tsc_setup(s);
-        n810_kbd_setup(s);
-    }
-    n8x0_spi_setup(s);
-    n8x0_dss_setup(s);
-    n8x0_cbus_setup(s);
-    n8x0_uart_setup(s);
-    if (usb_enabled(false)) {
-        n8x0_usb_setup(s);
-    }
-
-    if (args->kernel_filename) {
-        /* Or at the linux loader.  */
-        binfo->kernel_filename = args->kernel_filename;
-        binfo->kernel_cmdline = args->kernel_cmdline;
-        binfo->initrd_filename = args->initrd_filename;
-        arm_load_kernel(s->mpu->cpu, binfo);
-
-        qemu_register_reset(n8x0_boot_init, s);
-    }
-
-    if (option_rom[0].name &&
-        (args->boot_device[0] == 'n' || !args->kernel_filename)) {
-        int rom_size;
-        uint8_t nolo_tags[0x10000];
-        /* No, wait, better start at the ROM.  */
-        s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
-
-        /* This is intended for loading the `secondary.bin' program from
-         * Nokia images (the NOLO bootloader).  The entry point seems
-         * to be at OMAP2_Q2_BASE + 0x400000.
-         *
-         * The `2nd.bin' files contain some kind of earlier boot code and
-         * for them the entry point needs to be set to OMAP2_SRAM_BASE.
-         *
-         * The code above is for loading the `zImage' file from Nokia
-         * images.  */
-        rom_size = load_image_targphys(option_rom[0].name,
-                                       OMAP2_Q2_BASE + 0x400000,
-                                       sdram_size - 0x400000);
-        printf("%i bytes of image loaded\n", rom_size);
-
-        n800_setup_nolo_tags(nolo_tags);
-        cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000);
-    }
-    /* FIXME: We shouldn't really be doing this here.  The LCD controller
-       will set the size once configured, so this just sets an initial
-       size until the guest activates the display.  */
-    ds = get_displaystate();
-    ds->surface = qemu_resize_displaysurface(ds, 800, 480);
-    dpy_gfx_resize(ds);
-}
-
-static struct arm_boot_info n800_binfo = {
-    .loader_start = OMAP2_Q2_BASE,
-    /* Actually two chips of 0x4000000 bytes each */
-    .ram_size = 0x08000000,
-    .board_id = 0x4f7,
-    .atag_board = n800_atag_setup,
-};
-
-static struct arm_boot_info n810_binfo = {
-    .loader_start = OMAP2_Q2_BASE,
-    /* Actually two chips of 0x4000000 bytes each */
-    .ram_size = 0x08000000,
-    /* 0x60c and 0x6bf (WiMAX Edition) have been assigned but are not
-     * used by some older versions of the bootloader and 5555 is used
-     * instead (including versions that shipped with many devices).  */
-    .board_id = 0x60c,
-    .atag_board = n810_atag_setup,
-};
-
-static void n800_init(QEMUMachineInitArgs *args)
-{
-    return n8x0_init(args, &n800_binfo, 800);
-}
-
-static void n810_init(QEMUMachineInitArgs *args)
-{
-    return n8x0_init(args, &n810_binfo, 810);
-}
-
-static QEMUMachine n800_machine = {
-    .name = "n800",
-    .desc = "Nokia N800 tablet aka. RX-34 (OMAP2420)",
-    .init = n800_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine n810_machine = {
-    .name = "n810",
-    .desc = "Nokia N810 tablet aka. RX-44 (OMAP2420)",
-    .init = n810_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void nseries_machine_init(void)
-{
-    qemu_register_machine(&n800_machine);
-    qemu_register_machine(&n810_machine);
-}
-
-machine_init(nseries_machine_init);
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
deleted file mode 100644
index 8598233..0000000
--- a/hw/omap_sx1.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/* omap_sx1.c Support for the Siemens SX1 smartphone emulation.
- *
- *   Copyright (C) 2008
- * 	Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>
- *   Copyright (C) 2007 Vladimir Ananiev <vovan888 at gmail.com>
- *
- *   based on PalmOne's (TM) PDAs support (palm.c)
- */
-
-/*
- * PalmOne's (TM) PDAs.
- *
- * Copyright (C) 2006-2007 Andrzej Zaborowski <balrog at zabor.org>
- *
- * 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/>.
- */
-#include "hw/hw.h"
-#include "ui/console.h"
-#include "hw/omap.h"
-#include "hw/boards.h"
-#include "hw/arm-misc.h"
-#include "hw/flash.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-/*****************************************************************************/
-/* Siemens SX1 Cellphone V1 */
-/* - ARM OMAP310 processor
- * - SRAM                192 kB
- * - SDRAM                32 MB at 0x10000000
- * - Boot flash           16 MB at 0x00000000
- * - Application flash     8 MB at 0x04000000
- * - 3 serial ports
- * - 1 SecureDigital
- * - 1 LCD display
- * - 1 RTC
- */
-
-/*****************************************************************************/
-/* Siemens SX1 Cellphone V2 */
-/* - ARM OMAP310 processor
- * - SRAM                192 kB
- * - SDRAM                32 MB at 0x10000000
- * - Boot flash           32 MB at 0x00000000
- * - 3 serial ports
- * - 1 SecureDigital
- * - 1 LCD display
- * - 1 RTC
- */
-
-static uint64_t static_read(void *opaque, hwaddr offset,
-                            unsigned size)
-{
-    uint32_t *val = (uint32_t *) opaque;
-    uint32_t mask = (4 / size) - 1;
-
-    return *val >> ((offset & mask) << 3);
-}
-
-static void static_write(void *opaque, hwaddr offset,
-                         uint64_t value, unsigned size)
-{
-#ifdef SPY
-    printf("%s: value %" PRIx64 " %u bytes written at 0x%x\n",
-                    __func__, value, size, (int)offset);
-#endif
-}
-
-static const MemoryRegionOps static_ops = {
-    .read = static_read,
-    .write = static_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-#define sdram_size	0x02000000
-#define sector_size	(128 * 1024)
-#define flash0_size	(16 * 1024 * 1024)
-#define flash1_size	( 8 * 1024 * 1024)
-#define flash2_size	(32 * 1024 * 1024)
-#define total_ram_v1	(sdram_size + flash0_size + flash1_size + OMAP15XX_SRAM_SIZE)
-#define total_ram_v2	(sdram_size + flash2_size + OMAP15XX_SRAM_SIZE)
-
-static struct arm_boot_info sx1_binfo = {
-    .loader_start = OMAP_EMIFF_BASE,
-    .ram_size = sdram_size,
-    .board_id = 0x265,
-};
-
-static void sx1_init(QEMUMachineInitArgs *args, const int version)
-{
-    struct omap_mpu_state_s *mpu;
-    MemoryRegion *address_space = get_system_memory();
-    MemoryRegion *flash = g_new(MemoryRegion, 1);
-    MemoryRegion *flash_1 = g_new(MemoryRegion, 1);
-    MemoryRegion *cs = g_new(MemoryRegion, 4);
-    static uint32_t cs0val = 0x00213090;
-    static uint32_t cs1val = 0x00215070;
-    static uint32_t cs2val = 0x00001139;
-    static uint32_t cs3val = 0x00001139;
-    DriveInfo *dinfo;
-    int fl_idx;
-    uint32_t flash_size = flash0_size;
-    int be;
-
-    if (version == 2) {
-        flash_size = flash2_size;
-    }
-
-    mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, args->cpu_model);
-
-    /* External Flash (EMIFS) */
-    memory_region_init_ram(flash, "omap_sx1.flash0-0", flash_size);
-    vmstate_register_ram_global(flash);
-    memory_region_set_readonly(flash, true);
-    memory_region_add_subregion(address_space, OMAP_CS0_BASE, flash);
-
-    memory_region_init_io(&cs[0], &static_ops, &cs0val,
-                          "sx1.cs0", OMAP_CS0_SIZE - flash_size);
-    memory_region_add_subregion(address_space,
-                                OMAP_CS0_BASE + flash_size, &cs[0]);
-
-
-    memory_region_init_io(&cs[2], &static_ops, &cs2val,
-                          "sx1.cs2", OMAP_CS2_SIZE);
-    memory_region_add_subregion(address_space,
-                                OMAP_CS2_BASE, &cs[2]);
-
-    memory_region_init_io(&cs[3], &static_ops, &cs3val,
-                          "sx1.cs3", OMAP_CS3_SIZE);
-    memory_region_add_subregion(address_space,
-                                OMAP_CS2_BASE, &cs[3]);
-
-    fl_idx = 0;
-#ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
-#else
-    be = 0;
-#endif
-
-    if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
-        if (!pflash_cfi01_register(OMAP_CS0_BASE, NULL,
-                                   "omap_sx1.flash0-1", flash_size,
-                                   dinfo->bdrv, sector_size,
-                                   flash_size / sector_size,
-                                   4, 0, 0, 0, 0, be)) {
-            fprintf(stderr, "qemu: Error registering flash memory %d.\n",
-                           fl_idx);
-        }
-        fl_idx++;
-    }
-
-    if ((version == 1) &&
-            (dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
-        memory_region_init_ram(flash_1, "omap_sx1.flash1-0", flash1_size);
-        vmstate_register_ram_global(flash_1);
-        memory_region_set_readonly(flash_1, true);
-        memory_region_add_subregion(address_space, OMAP_CS1_BASE, flash_1);
-
-        memory_region_init_io(&cs[1], &static_ops, &cs1val,
-                              "sx1.cs1", OMAP_CS1_SIZE - flash1_size);
-        memory_region_add_subregion(address_space,
-                                OMAP_CS1_BASE + flash1_size, &cs[1]);
-
-        if (!pflash_cfi01_register(OMAP_CS1_BASE, NULL,
-                                   "omap_sx1.flash1-1", flash1_size,
-                                   dinfo->bdrv, sector_size,
-                                   flash1_size / sector_size,
-                                   4, 0, 0, 0, 0, be)) {
-            fprintf(stderr, "qemu: Error registering flash memory %d.\n",
-                           fl_idx);
-        }
-        fl_idx++;
-    } else {
-        memory_region_init_io(&cs[1], &static_ops, &cs1val,
-                              "sx1.cs1", OMAP_CS1_SIZE);
-        memory_region_add_subregion(address_space,
-                                OMAP_CS1_BASE, &cs[1]);
-    }
-
-    if (!args->kernel_filename && !fl_idx) {
-        fprintf(stderr, "Kernel or Flash image must be specified\n");
-        exit(1);
-    }
-
-    /* Load the kernel.  */
-    if (args->kernel_filename) {
-        sx1_binfo.kernel_filename = args->kernel_filename;
-        sx1_binfo.kernel_cmdline = args->kernel_cmdline;
-        sx1_binfo.initrd_filename = args->initrd_filename;
-        arm_load_kernel(mpu->cpu, &sx1_binfo);
-    }
-
-    /* TODO: fix next line */
-    //~ qemu_console_resize(ds, 640, 480);
-}
-
-static void sx1_init_v1(QEMUMachineInitArgs *args)
-{
-    sx1_init(args, 1);
-}
-
-static void sx1_init_v2(QEMUMachineInitArgs *args)
-{
-    sx1_init(args, 2);
-}
-
-static QEMUMachine sx1_machine_v2 = {
-    .name = "sx1",
-    .desc = "Siemens SX1 (OMAP310) V2",
-    .init = sx1_init_v2,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine sx1_machine_v1 = {
-    .name = "sx1-v1",
-    .desc = "Siemens SX1 (OMAP310) V1",
-    .init = sx1_init_v1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void sx1_machine_init(void)
-{
-    qemu_register_machine(&sx1_machine_v2);
-    qemu_register_machine(&sx1_machine_v1);
-}
-
-machine_init(sx1_machine_init);
diff --git a/hw/openrisc/Makefile.objs b/hw/openrisc/Makefile.objs
index 38ff8f5..61246b1 100644
--- a/hw/openrisc/Makefile.objs
+++ b/hw/openrisc/Makefile.objs
@@ -1,3 +1,2 @@
-obj-y = openrisc_pic.o openrisc_sim.o openrisc_timer.o
-
-obj-y := $(addprefix ../,$(obj-y))
+obj-y = pic_cpu.o cputimer.o
+obj-y += openrisc_sim.o 
diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c
new file mode 100644
index 0000000..f6c877f
--- /dev/null
+++ b/hw/openrisc/cputimer.c
@@ -0,0 +1,101 @@
+/*
+ * QEMU OpenRISC timer support
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc at gmail.com>
+ *                         Zhizhou Zhang <etouzh at gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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 "cpu.h"
+#include "hw/hw.h"
+#include "qemu/timer.h"
+
+#define TIMER_FREQ    (20 * 1000 * 1000)    /* 20MHz */
+
+/* The time when TTCR changes */
+static uint64_t last_clk;
+static int is_counting;
+
+void cpu_openrisc_count_update(OpenRISCCPU *cpu)
+{
+    uint64_t now, next;
+    uint32_t wait;
+
+    now = qemu_get_clock_ns(vm_clock);
+    if (!is_counting) {
+        qemu_del_timer(cpu->env.timer);
+        last_clk = now;
+        return;
+    }
+
+    cpu->env.ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ,
+                                        get_ticks_per_sec());
+    last_clk = now;
+
+    if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) {
+        wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1;
+        wait += cpu->env.ttmr & TTMR_TP;
+    } else {
+        wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP);
+    }
+
+    next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
+    qemu_mod_timer(cpu->env.timer, next);
+}
+
+void cpu_openrisc_count_start(OpenRISCCPU *cpu)
+{
+    is_counting = 1;
+    cpu_openrisc_count_update(cpu);
+}
+
+void cpu_openrisc_count_stop(OpenRISCCPU *cpu)
+{
+    is_counting = 0;
+    cpu_openrisc_count_update(cpu);
+}
+
+static void openrisc_timer_cb(void *opaque)
+{
+    OpenRISCCPU *cpu = opaque;
+
+    if ((cpu->env.ttmr & TTMR_IE) &&
+         qemu_timer_expired(cpu->env.timer, qemu_get_clock_ns(vm_clock))) {
+        cpu->env.ttmr |= TTMR_IP;
+        cpu->env.interrupt_request |= CPU_INTERRUPT_TIMER;
+    }
+
+    switch (cpu->env.ttmr & TTMR_M) {
+    case TIMER_NONE:
+        break;
+    case TIMER_INTR:
+        cpu->env.ttcr = 0;
+        cpu_openrisc_count_start(cpu);
+        break;
+    case TIMER_SHOT:
+        cpu_openrisc_count_stop(cpu);
+        break;
+    case TIMER_CONT:
+        cpu_openrisc_count_start(cpu);
+        break;
+    }
+}
+
+void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
+{
+    cpu->env.timer = qemu_new_timer_ns(vm_clock, &openrisc_timer_cb, cpu);
+    cpu->env.ttmr = 0x00000000;
+    cpu->env.ttcr = 0x00000000;
+}
diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
new file mode 100644
index 0000000..db2aac8
--- /dev/null
+++ b/hw/openrisc/openrisc_sim.c
@@ -0,0 +1,150 @@
+/*
+ * OpenRISC simulator for use as an IIS.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc at gmail.com>
+ *                         Feng Gao <gf91597 at gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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/hw.h"
+#include "hw/boards.h"
+#include "elf.h"
+#include "hw/serial.h"
+#include "net/net.h"
+#include "hw/loader.h"
+#include "exec/address-spaces.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+#include "sysemu/qtest.h"
+
+#define KERNEL_LOAD_ADDR 0x100
+
+static void main_cpu_reset(void *opaque)
+{
+    OpenRISCCPU *cpu = opaque;
+
+    cpu_reset(CPU(cpu));
+}
+
+static void openrisc_sim_net_init(MemoryRegion *address_space,
+                                  hwaddr base,
+                                  hwaddr descriptors,
+                                  qemu_irq irq, NICInfo *nd)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "open_eth");
+    qdev_set_nic_properties(dev, nd);
+    qdev_init_nofail(dev);
+
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(s, 0, irq);
+    memory_region_add_subregion(address_space, base,
+                                sysbus_mmio_get_region(s, 0));
+    memory_region_add_subregion(address_space, descriptors,
+                                sysbus_mmio_get_region(s, 1));
+}
+
+static void cpu_openrisc_load_kernel(ram_addr_t ram_size,
+                                     const char *kernel_filename,
+                                     OpenRISCCPU *cpu)
+{
+    long kernel_size;
+    uint64_t elf_entry;
+    hwaddr entry;
+
+    if (kernel_filename && !qtest_enabled()) {
+        kernel_size = load_elf(kernel_filename, NULL, NULL,
+                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
+        entry = elf_entry;
+        if (kernel_size < 0) {
+            kernel_size = load_uimage(kernel_filename,
+                                      &entry, NULL, NULL);
+        }
+        if (kernel_size < 0) {
+            kernel_size = load_image_targphys(kernel_filename,
+                                              KERNEL_LOAD_ADDR,
+                                              ram_size - KERNEL_LOAD_ADDR);
+            entry = KERNEL_LOAD_ADDR;
+        }
+
+        if (kernel_size < 0) {
+            qemu_log("QEMU: couldn't load the kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+    }
+
+    cpu->env.pc = entry;
+}
+
+static void openrisc_sim_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+   OpenRISCCPU *cpu = NULL;
+    MemoryRegion *ram;
+    int n;
+
+    if (!cpu_model) {
+        cpu_model = "or1200";
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        cpu = cpu_openrisc_init(cpu_model);
+        if (cpu == NULL) {
+            qemu_log("Unable to find CPU definition!\n");
+            exit(1);
+        }
+        qemu_register_reset(main_cpu_reset, cpu);
+        main_cpu_reset(cpu);
+    }
+
+    ram = g_malloc(sizeof(*ram));
+    memory_region_init_ram(ram, "openrisc.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(get_system_memory(), 0, ram);
+
+    cpu_openrisc_pic_init(cpu);
+    cpu_openrisc_clock_init(cpu);
+
+    serial_mm_init(get_system_memory(), 0x90000000, 0, cpu->env.irq[2],
+                   115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
+
+    if (nd_table[0].used) {
+        openrisc_sim_net_init(get_system_memory(), 0x92000000,
+                              0x92000400, cpu->env.irq[4], nd_table);
+    }
+
+    cpu_openrisc_load_kernel(ram_size, kernel_filename, cpu);
+}
+
+static QEMUMachine openrisc_sim_machine = {
+    .name = "or32-sim",
+    .desc = "or32 simulation",
+    .init = openrisc_sim_init,
+    .max_cpus = 1,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void openrisc_sim_machine_init(void)
+{
+    qemu_register_machine(&openrisc_sim_machine);
+}
+
+machine_init(openrisc_sim_machine_init);
diff --git a/hw/openrisc/pic_cpu.c b/hw/openrisc/pic_cpu.c
new file mode 100644
index 0000000..931511e
--- /dev/null
+++ b/hw/openrisc/pic_cpu.c
@@ -0,0 +1,60 @@
+/*
+ * OpenRISC Programmable Interrupt Controller support.
+ *
+ * Copyright (c) 2011-2012 Jia Liu <proljc at gmail.com>
+ *                         Feng Gao <gf91597 at gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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/hw.h"
+#include "cpu.h"
+
+/* OpenRISC pic handler */
+static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
+{
+    OpenRISCCPU *cpu = (OpenRISCCPU *)opaque;
+    int i;
+    uint32_t irq_bit = 1 << irq;
+
+    if (irq > 31 || irq < 0) {
+        return;
+    }
+
+    if (level) {
+        cpu->env.picsr |= irq_bit;
+    } else {
+        cpu->env.picsr &= ~irq_bit;
+    }
+
+    for (i = 0; i < 32; i++) {
+        if ((cpu->env.picsr && (1 << i)) && (cpu->env.picmr && (1 << i))) {
+            cpu_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
+        } else {
+            cpu_reset_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
+            cpu->env.picsr &= ~(1 << i);
+        }
+    }
+}
+
+void cpu_openrisc_pic_init(OpenRISCCPU *cpu)
+{
+    int i;
+    qemu_irq *qi;
+    qi = qemu_allocate_irqs(openrisc_pic_cpu_handler, cpu, NR_IRQS);
+
+    for (i = 0; i < NR_IRQS; i++) {
+        cpu->env.irq[i] = qi[i];
+    }
+}
diff --git a/hw/openrisc_pic.c b/hw/openrisc_pic.c
deleted file mode 100644
index 931511e..0000000
--- a/hw/openrisc_pic.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * OpenRISC Programmable Interrupt Controller support.
- *
- * Copyright (c) 2011-2012 Jia Liu <proljc at gmail.com>
- *                         Feng Gao <gf91597 at gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 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/hw.h"
-#include "cpu.h"
-
-/* OpenRISC pic handler */
-static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
-{
-    OpenRISCCPU *cpu = (OpenRISCCPU *)opaque;
-    int i;
-    uint32_t irq_bit = 1 << irq;
-
-    if (irq > 31 || irq < 0) {
-        return;
-    }
-
-    if (level) {
-        cpu->env.picsr |= irq_bit;
-    } else {
-        cpu->env.picsr &= ~irq_bit;
-    }
-
-    for (i = 0; i < 32; i++) {
-        if ((cpu->env.picsr && (1 << i)) && (cpu->env.picmr && (1 << i))) {
-            cpu_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
-        } else {
-            cpu_reset_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
-            cpu->env.picsr &= ~(1 << i);
-        }
-    }
-}
-
-void cpu_openrisc_pic_init(OpenRISCCPU *cpu)
-{
-    int i;
-    qemu_irq *qi;
-    qi = qemu_allocate_irqs(openrisc_pic_cpu_handler, cpu, NR_IRQS);
-
-    for (i = 0; i < NR_IRQS; i++) {
-        cpu->env.irq[i] = qi[i];
-    }
-}
diff --git a/hw/openrisc_sim.c b/hw/openrisc_sim.c
deleted file mode 100644
index db2aac8..0000000
--- a/hw/openrisc_sim.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * OpenRISC simulator for use as an IIS.
- *
- * Copyright (c) 2011-2012 Jia Liu <proljc at gmail.com>
- *                         Feng Gao <gf91597 at gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 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/hw.h"
-#include "hw/boards.h"
-#include "elf.h"
-#include "hw/serial.h"
-#include "net/net.h"
-#include "hw/loader.h"
-#include "exec/address-spaces.h"
-#include "sysemu/sysemu.h"
-#include "hw/sysbus.h"
-#include "sysemu/qtest.h"
-
-#define KERNEL_LOAD_ADDR 0x100
-
-static void main_cpu_reset(void *opaque)
-{
-    OpenRISCCPU *cpu = opaque;
-
-    cpu_reset(CPU(cpu));
-}
-
-static void openrisc_sim_net_init(MemoryRegion *address_space,
-                                  hwaddr base,
-                                  hwaddr descriptors,
-                                  qemu_irq irq, NICInfo *nd)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "open_eth");
-    qdev_set_nic_properties(dev, nd);
-    qdev_init_nofail(dev);
-
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_connect_irq(s, 0, irq);
-    memory_region_add_subregion(address_space, base,
-                                sysbus_mmio_get_region(s, 0));
-    memory_region_add_subregion(address_space, descriptors,
-                                sysbus_mmio_get_region(s, 1));
-}
-
-static void cpu_openrisc_load_kernel(ram_addr_t ram_size,
-                                     const char *kernel_filename,
-                                     OpenRISCCPU *cpu)
-{
-    long kernel_size;
-    uint64_t elf_entry;
-    hwaddr entry;
-
-    if (kernel_filename && !qtest_enabled()) {
-        kernel_size = load_elf(kernel_filename, NULL, NULL,
-                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
-        entry = elf_entry;
-        if (kernel_size < 0) {
-            kernel_size = load_uimage(kernel_filename,
-                                      &entry, NULL, NULL);
-        }
-        if (kernel_size < 0) {
-            kernel_size = load_image_targphys(kernel_filename,
-                                              KERNEL_LOAD_ADDR,
-                                              ram_size - KERNEL_LOAD_ADDR);
-            entry = KERNEL_LOAD_ADDR;
-        }
-
-        if (kernel_size < 0) {
-            qemu_log("QEMU: couldn't load the kernel '%s'\n",
-                    kernel_filename);
-            exit(1);
-        }
-    }
-
-    cpu->env.pc = entry;
-}
-
-static void openrisc_sim_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-   OpenRISCCPU *cpu = NULL;
-    MemoryRegion *ram;
-    int n;
-
-    if (!cpu_model) {
-        cpu_model = "or1200";
-    }
-
-    for (n = 0; n < smp_cpus; n++) {
-        cpu = cpu_openrisc_init(cpu_model);
-        if (cpu == NULL) {
-            qemu_log("Unable to find CPU definition!\n");
-            exit(1);
-        }
-        qemu_register_reset(main_cpu_reset, cpu);
-        main_cpu_reset(cpu);
-    }
-
-    ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, "openrisc.ram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(get_system_memory(), 0, ram);
-
-    cpu_openrisc_pic_init(cpu);
-    cpu_openrisc_clock_init(cpu);
-
-    serial_mm_init(get_system_memory(), 0x90000000, 0, cpu->env.irq[2],
-                   115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
-
-    if (nd_table[0].used) {
-        openrisc_sim_net_init(get_system_memory(), 0x92000000,
-                              0x92000400, cpu->env.irq[4], nd_table);
-    }
-
-    cpu_openrisc_load_kernel(ram_size, kernel_filename, cpu);
-}
-
-static QEMUMachine openrisc_sim_machine = {
-    .name = "or32-sim",
-    .desc = "or32 simulation",
-    .init = openrisc_sim_init,
-    .max_cpus = 1,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void openrisc_sim_machine_init(void)
-{
-    qemu_register_machine(&openrisc_sim_machine);
-}
-
-machine_init(openrisc_sim_machine_init);
diff --git a/hw/openrisc_timer.c b/hw/openrisc_timer.c
deleted file mode 100644
index f6c877f..0000000
--- a/hw/openrisc_timer.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * QEMU OpenRISC timer support
- *
- * Copyright (c) 2011-2012 Jia Liu <proljc at gmail.com>
- *                         Zhizhou Zhang <etouzh at gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 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 "cpu.h"
-#include "hw/hw.h"
-#include "qemu/timer.h"
-
-#define TIMER_FREQ    (20 * 1000 * 1000)    /* 20MHz */
-
-/* The time when TTCR changes */
-static uint64_t last_clk;
-static int is_counting;
-
-void cpu_openrisc_count_update(OpenRISCCPU *cpu)
-{
-    uint64_t now, next;
-    uint32_t wait;
-
-    now = qemu_get_clock_ns(vm_clock);
-    if (!is_counting) {
-        qemu_del_timer(cpu->env.timer);
-        last_clk = now;
-        return;
-    }
-
-    cpu->env.ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ,
-                                        get_ticks_per_sec());
-    last_clk = now;
-
-    if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) {
-        wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1;
-        wait += cpu->env.ttmr & TTMR_TP;
-    } else {
-        wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP);
-    }
-
-    next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
-    qemu_mod_timer(cpu->env.timer, next);
-}
-
-void cpu_openrisc_count_start(OpenRISCCPU *cpu)
-{
-    is_counting = 1;
-    cpu_openrisc_count_update(cpu);
-}
-
-void cpu_openrisc_count_stop(OpenRISCCPU *cpu)
-{
-    is_counting = 0;
-    cpu_openrisc_count_update(cpu);
-}
-
-static void openrisc_timer_cb(void *opaque)
-{
-    OpenRISCCPU *cpu = opaque;
-
-    if ((cpu->env.ttmr & TTMR_IE) &&
-         qemu_timer_expired(cpu->env.timer, qemu_get_clock_ns(vm_clock))) {
-        cpu->env.ttmr |= TTMR_IP;
-        cpu->env.interrupt_request |= CPU_INTERRUPT_TIMER;
-    }
-
-    switch (cpu->env.ttmr & TTMR_M) {
-    case TIMER_NONE:
-        break;
-    case TIMER_INTR:
-        cpu->env.ttcr = 0;
-        cpu_openrisc_count_start(cpu);
-        break;
-    case TIMER_SHOT:
-        cpu_openrisc_count_stop(cpu);
-        break;
-    case TIMER_CONT:
-        cpu_openrisc_count_start(cpu);
-        break;
-    }
-}
-
-void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
-{
-    cpu->env.timer = qemu_new_timer_ns(vm_clock, &openrisc_timer_cb, cpu);
-    cpu->env.ttmr = 0x00000000;
-    cpu->env.ttcr = 0x00000000;
-}
diff --git a/hw/palm.c b/hw/palm.c
deleted file mode 100644
index 91bc74a..0000000
--- a/hw/palm.c
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * PalmOne's (TM) PDAs.
- *
- * Copyright (C) 2006-2007 Andrzej Zaborowski  <balrog at zabor.org>
- *
- * 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 or
- * (at your option) version 3 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 "audio/audio.h"
-#include "sysemu/sysemu.h"
-#include "ui/console.h"
-#include "hw/omap.h"
-#include "hw/boards.h"
-#include "hw/arm-misc.h"
-#include "hw/devices.h"
-#include "hw/loader.h"
-#include "exec/address-spaces.h"
-
-static uint32_t static_readb(void *opaque, hwaddr offset)
-{
-    uint32_t *val = (uint32_t *) opaque;
-    return *val >> ((offset & 3) << 3);
-}
-
-static uint32_t static_readh(void *opaque, hwaddr offset)
-{
-    uint32_t *val = (uint32_t *) opaque;
-    return *val >> ((offset & 1) << 3);
-}
-
-static uint32_t static_readw(void *opaque, hwaddr offset)
-{
-    uint32_t *val = (uint32_t *) opaque;
-    return *val >> ((offset & 0) << 3);
-}
-
-static void static_write(void *opaque, hwaddr offset,
-                uint32_t value)
-{
-#ifdef SPY
-    printf("%s: value %08lx written at " PA_FMT "\n",
-                    __FUNCTION__, value, offset);
-#endif
-}
-
-static const MemoryRegionOps static_ops = {
-    .old_mmio = {
-        .read = { static_readb, static_readh, static_readw, },
-        .write = { static_write, static_write, static_write, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-/* Palm Tunsgten|E support */
-
-/* Shared GPIOs */
-#define PALMTE_USBDETECT_GPIO	0
-#define PALMTE_USB_OR_DC_GPIO	1
-#define PALMTE_TSC_GPIO		4
-#define PALMTE_PINTDAV_GPIO	6
-#define PALMTE_MMC_WP_GPIO	8
-#define PALMTE_MMC_POWER_GPIO	9
-#define PALMTE_HDQ_GPIO		11
-#define PALMTE_HEADPHONES_GPIO	14
-#define PALMTE_SPEAKER_GPIO	15
-/* MPU private GPIOs */
-#define PALMTE_DC_GPIO		2
-#define PALMTE_MMC_SWITCH_GPIO	4
-#define PALMTE_MMC1_GPIO	6
-#define PALMTE_MMC2_GPIO	7
-#define PALMTE_MMC3_GPIO	11
-
-static MouseTransformInfo palmte_pointercal = {
-    .x = 320,
-    .y = 320,
-    .a = { -5909, 8, 22465308, 104, 7644, -1219972, 65536 },
-};
-
-static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
-{
-    uWireSlave *tsc;
-
-    tsc = tsc2102_init(qdev_get_gpio_in(cpu->gpio, PALMTE_PINTDAV_GPIO));
-
-    omap_uwire_attach(cpu->microwire, tsc, 0);
-    omap_mcbsp_i2s_attach(cpu->mcbsp1, tsc210x_codec(tsc));
-
-    tsc210x_set_transform(tsc, &palmte_pointercal);
-}
-
-static struct {
-    int row;
-    int column;
-} palmte_keymap[0x80] = {
-    [0 ... 0x7f] = { -1, -1 },
-    [0x3b] = { 0, 0 },	/* F1	-> Calendar */
-    [0x3c] = { 1, 0 },	/* F2	-> Contacts */
-    [0x3d] = { 2, 0 },	/* F3	-> Tasks List */
-    [0x3e] = { 3, 0 },	/* F4	-> Note Pad */
-    [0x01] = { 4, 0 },	/* Esc	-> Power */
-    [0x4b] = { 0, 1 },	/* 	   Left */
-    [0x50] = { 1, 1 },	/* 	   Down */
-    [0x48] = { 2, 1 },	/*	   Up */
-    [0x4d] = { 3, 1 },	/*	   Right */
-    [0x4c] = { 4, 1 },	/* 	   Centre */
-    [0x39] = { 4, 1 },	/* Spc	-> Centre */
-};
-
-static void palmte_button_event(void *opaque, int keycode)
-{
-    struct omap_mpu_state_s *cpu = (struct omap_mpu_state_s *) opaque;
-
-    if (palmte_keymap[keycode & 0x7f].row != -1)
-        omap_mpuio_key(cpu->mpuio,
-                        palmte_keymap[keycode & 0x7f].row,
-                        palmte_keymap[keycode & 0x7f].column,
-                        !(keycode & 0x80));
-}
-
-static void palmte_onoff_gpios(void *opaque, int line, int level)
-{
-    switch (line) {
-    case 0:
-        printf("%s: current to MMC/SD card %sabled.\n",
-                        __FUNCTION__, level ? "dis" : "en");
-        break;
-    case 1:
-        printf("%s: internal speaker amplifier %s.\n",
-                        __FUNCTION__, level ? "down" : "on");
-        break;
-
-    /* These LCD & Audio output signals have not been identified yet.  */
-    case 2:
-    case 3:
-    case 4:
-        printf("%s: LCD GPIO%i %s.\n",
-                        __FUNCTION__, line - 1, level ? "high" : "low");
-        break;
-    case 5:
-    case 6:
-        printf("%s: Audio GPIO%i %s.\n",
-                        __FUNCTION__, line - 4, level ? "high" : "low");
-        break;
-    }
-}
-
-static void palmte_gpio_setup(struct omap_mpu_state_s *cpu)
-{
-    qemu_irq *misc_gpio;
-
-    omap_mmc_handlers(cpu->mmc,
-                    qdev_get_gpio_in(cpu->gpio, PALMTE_MMC_WP_GPIO),
-                    qemu_irq_invert(omap_mpuio_in_get(cpu->mpuio)
-                            [PALMTE_MMC_SWITCH_GPIO]));
-
-    misc_gpio = qemu_allocate_irqs(palmte_onoff_gpios, cpu, 7);
-    qdev_connect_gpio_out(cpu->gpio, PALMTE_MMC_POWER_GPIO,	misc_gpio[0]);
-    qdev_connect_gpio_out(cpu->gpio, PALMTE_SPEAKER_GPIO,	misc_gpio[1]);
-    qdev_connect_gpio_out(cpu->gpio, 11,			misc_gpio[2]);
-    qdev_connect_gpio_out(cpu->gpio, 12,			misc_gpio[3]);
-    qdev_connect_gpio_out(cpu->gpio, 13,			misc_gpio[4]);
-    omap_mpuio_out_set(cpu->mpuio, 1,				misc_gpio[5]);
-    omap_mpuio_out_set(cpu->mpuio, 3,				misc_gpio[6]);
-
-    /* Reset some inputs to initial state.  */
-    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USBDETECT_GPIO));
-    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USB_OR_DC_GPIO));
-    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, 4));
-    qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_HEADPHONES_GPIO));
-    qemu_irq_lower(omap_mpuio_in_get(cpu->mpuio)[PALMTE_DC_GPIO]);
-    qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[6]);
-    qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[7]);
-    qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[11]);
-}
-
-static struct arm_boot_info palmte_binfo = {
-    .loader_start = OMAP_EMIFF_BASE,
-    .ram_size = 0x02000000,
-    .board_id = 0x331,
-};
-
-static void palmte_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    MemoryRegion *address_space_mem = get_system_memory();
-    struct omap_mpu_state_s *mpu;
-    int flash_size = 0x00800000;
-    int sdram_size = palmte_binfo.ram_size;
-    static uint32_t cs0val = 0xffffffff;
-    static uint32_t cs1val = 0x0000e1a0;
-    static uint32_t cs2val = 0x0000e1a0;
-    static uint32_t cs3val = 0xe1a0e1a0;
-    int rom_size, rom_loaded = 0;
-    DisplayState *ds = get_displaystate();
-    MemoryRegion *flash = g_new(MemoryRegion, 1);
-    MemoryRegion *cs = g_new(MemoryRegion, 4);
-
-    mpu = omap310_mpu_init(address_space_mem, sdram_size, cpu_model);
-
-    /* External Flash (EMIFS) */
-    memory_region_init_ram(flash, "palmte.flash", flash_size);
-    vmstate_register_ram_global(flash);
-    memory_region_set_readonly(flash, true);
-    memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE, flash);
-
-    memory_region_init_io(&cs[0], &static_ops, &cs0val, "palmte-cs0",
-                          OMAP_CS0_SIZE - flash_size);
-    memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE + flash_size,
-                                &cs[0]);
-    memory_region_init_io(&cs[1], &static_ops, &cs1val, "palmte-cs1",
-                          OMAP_CS1_SIZE);
-    memory_region_add_subregion(address_space_mem, OMAP_CS1_BASE, &cs[1]);
-    memory_region_init_io(&cs[2], &static_ops, &cs2val, "palmte-cs2",
-                          OMAP_CS2_SIZE);
-    memory_region_add_subregion(address_space_mem, OMAP_CS2_BASE, &cs[2]);
-    memory_region_init_io(&cs[3], &static_ops, &cs3val, "palmte-cs3",
-                          OMAP_CS3_SIZE);
-    memory_region_add_subregion(address_space_mem, OMAP_CS3_BASE, &cs[3]);
-
-    palmte_microwire_setup(mpu);
-
-    qemu_add_kbd_event_handler(palmte_button_event, mpu);
-
-    palmte_gpio_setup(mpu);
-
-    /* Setup initial (reset) machine state */
-    if (nb_option_roms) {
-        rom_size = get_image_size(option_rom[0].name);
-        if (rom_size > flash_size) {
-            fprintf(stderr, "%s: ROM image too big (%x > %x)\n",
-                            __FUNCTION__, rom_size, flash_size);
-            rom_size = 0;
-        }
-        if (rom_size > 0) {
-            rom_size = load_image_targphys(option_rom[0].name, OMAP_CS0_BASE,
-                                           flash_size);
-            rom_loaded = 1;
-        }
-        if (rom_size < 0) {
-            fprintf(stderr, "%s: error loading '%s'\n",
-                            __FUNCTION__, option_rom[0].name);
-        }
-    }
-
-    if (!rom_loaded && !kernel_filename) {
-        fprintf(stderr, "Kernel or ROM image must be specified\n");
-        exit(1);
-    }
-
-    /* Load the kernel.  */
-    if (kernel_filename) {
-        palmte_binfo.kernel_filename = kernel_filename;
-        palmte_binfo.kernel_cmdline = kernel_cmdline;
-        palmte_binfo.initrd_filename = initrd_filename;
-        arm_load_kernel(mpu->cpu, &palmte_binfo);
-    }
-
-    /* FIXME: We shouldn't really be doing this here.  The LCD controller
-       will set the size once configured, so this just sets an initial
-       size until the guest activates the display.  */
-    ds->surface = qemu_resize_displaysurface(ds, 320, 320);
-    dpy_gfx_resize(ds);
-}
-
-static QEMUMachine palmte_machine = {
-    .name = "cheetah",
-    .desc = "Palm Tungsten|E aka. Cheetah PDA (OMAP310)",
-    .init = palmte_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void palmte_machine_init(void)
-{
-    qemu_register_machine(&palmte_machine);
-}
-
-machine_init(palmte_machine_init);
diff --git a/hw/pc.c b/hw/pc.c
deleted file mode 100644
index 309bb83..0000000
--- a/hw/pc.c
+++ /dev/null
@@ -1,1161 +0,0 @@
-/*
- * QEMU PC System Emulator
- *
- * Copyright (c) 2003-2004 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 "hw/hw.h"
-#include "hw/pc.h"
-#include "hw/serial.h"
-#include "hw/apic.h"
-#include "hw/fdc.h"
-#include "hw/ide.h"
-#include "hw/pci/pci.h"
-#include "monitor/monitor.h"
-#include "hw/fw_cfg.h"
-#include "hw/hpet_emul.h"
-#include "hw/smbios.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "hw/multiboot.h"
-#include "hw/mc146818rtc.h"
-#include "hw/i8254.h"
-#include "hw/pcspk.h"
-#include "hw/pci/msi.h"
-#include "hw/sysbus.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/kvm.h"
-#include "kvm_i386.h"
-#include "hw/xen.h"
-#include "sysemu/blockdev.h"
-#include "hw/block-common.h"
-#include "ui/qemu-spice.h"
-#include "exec/memory.h"
-#include "exec/address-spaces.h"
-#include "sysemu/arch_init.h"
-#include "qemu/bitmap.h"
-
-/* debug PC/ISA interrupts */
-//#define DEBUG_IRQ
-
-#ifdef DEBUG_IRQ
-#define DPRINTF(fmt, ...)                                       \
-    do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...)
-#endif
-
-/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables.  */
-#define ACPI_DATA_SIZE       0x10000
-#define BIOS_CFG_IOPORT 0x510
-#define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0)
-#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1)
-#define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2)
-#define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3)
-#define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4)
-
-#define E820_NR_ENTRIES		16
-
-struct e820_entry {
-    uint64_t address;
-    uint64_t length;
-    uint32_t type;
-} QEMU_PACKED __attribute((__aligned__(4)));
-
-struct e820_table {
-    uint32_t count;
-    struct e820_entry entry[E820_NR_ENTRIES];
-} QEMU_PACKED __attribute((__aligned__(4)));
-
-static struct e820_table e820_table;
-struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
-
-void gsi_handler(void *opaque, int n, int level)
-{
-    GSIState *s = opaque;
-
-    DPRINTF("pc: %s GSI %d\n", level ? "raising" : "lowering", n);
-    if (n < ISA_NUM_IRQS) {
-        qemu_set_irq(s->i8259_irq[n], level);
-    }
-    qemu_set_irq(s->ioapic_irq[n], level);
-}
-
-static void ioport80_write(void *opaque, hwaddr addr, uint64_t data,
-                           unsigned size)
-{
-}
-
-static uint64_t ioport80_read(void *opaque, hwaddr addr, unsigned size)
-{
-    return 0xffffffffffffffffULL;
-}
-
-/* MSDOS compatibility mode FPU exception support */
-static qemu_irq ferr_irq;
-
-void pc_register_ferr_irq(qemu_irq irq)
-{
-    ferr_irq = irq;
-}
-
-/* XXX: add IGNNE support */
-void cpu_set_ferr(CPUX86State *s)
-{
-    qemu_irq_raise(ferr_irq);
-}
-
-static void ioportF0_write(void *opaque, hwaddr addr, uint64_t data,
-                           unsigned size)
-{
-    qemu_irq_lower(ferr_irq);
-}
-
-static uint64_t ioportF0_read(void *opaque, hwaddr addr, unsigned size)
-{
-    return 0xffffffffffffffffULL;
-}
-
-/* TSC handling */
-uint64_t cpu_get_tsc(CPUX86State *env)
-{
-    return cpu_get_ticks();
-}
-
-/* SMM support */
-
-static cpu_set_smm_t smm_set;
-static void *smm_arg;
-
-void cpu_smm_register(cpu_set_smm_t callback, void *arg)
-{
-    assert(smm_set == NULL);
-    assert(smm_arg == NULL);
-    smm_set = callback;
-    smm_arg = arg;
-}
-
-void cpu_smm_update(CPUX86State *env)
-{
-    if (smm_set && smm_arg && env == first_cpu)
-        smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg);
-}
-
-
-/* IRQ handling */
-int cpu_get_pic_interrupt(CPUX86State *env)
-{
-    int intno;
-
-    intno = apic_get_interrupt(env->apic_state);
-    if (intno >= 0) {
-        return intno;
-    }
-    /* read the irq from the PIC */
-    if (!apic_accept_pic_intr(env->apic_state)) {
-        return -1;
-    }
-
-    intno = pic_read_irq(isa_pic);
-    return intno;
-}
-
-static void pic_irq_request(void *opaque, int irq, int level)
-{
-    CPUX86State *env = first_cpu;
-
-    DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
-    if (env->apic_state) {
-        while (env) {
-            if (apic_accept_pic_intr(env->apic_state)) {
-                apic_deliver_pic_intr(env->apic_state, level);
-            }
-            env = env->next_cpu;
-        }
-    } else {
-        if (level)
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
-        else
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-}
-
-/* PC cmos mappings */
-
-#define REG_EQUIPMENT_BYTE          0x14
-
-static int cmos_get_fd_drive_type(FDriveType fd0)
-{
-    int val;
-
-    switch (fd0) {
-    case FDRIVE_DRV_144:
-        /* 1.44 Mb 3"5 drive */
-        val = 4;
-        break;
-    case FDRIVE_DRV_288:
-        /* 2.88 Mb 3"5 drive */
-        val = 5;
-        break;
-    case FDRIVE_DRV_120:
-        /* 1.2 Mb 5"5 drive */
-        val = 2;
-        break;
-    case FDRIVE_DRV_NONE:
-    default:
-        val = 0;
-        break;
-    }
-    return val;
-}
-
-static void cmos_init_hd(ISADevice *s, int type_ofs, int info_ofs,
-                         int16_t cylinders, int8_t heads, int8_t sectors)
-{
-    rtc_set_memory(s, type_ofs, 47);
-    rtc_set_memory(s, info_ofs, cylinders);
-    rtc_set_memory(s, info_ofs + 1, cylinders >> 8);
-    rtc_set_memory(s, info_ofs + 2, heads);
-    rtc_set_memory(s, info_ofs + 3, 0xff);
-    rtc_set_memory(s, info_ofs + 4, 0xff);
-    rtc_set_memory(s, info_ofs + 5, 0xc0 | ((heads > 8) << 3));
-    rtc_set_memory(s, info_ofs + 6, cylinders);
-    rtc_set_memory(s, info_ofs + 7, cylinders >> 8);
-    rtc_set_memory(s, info_ofs + 8, sectors);
-}
-
-/* convert boot_device letter to something recognizable by the bios */
-static int boot_device2nibble(char boot_device)
-{
-    switch(boot_device) {
-    case 'a':
-    case 'b':
-        return 0x01; /* floppy boot */
-    case 'c':
-        return 0x02; /* hard drive boot */
-    case 'd':
-        return 0x03; /* CD-ROM boot */
-    case 'n':
-        return 0x04; /* Network boot */
-    }
-    return 0;
-}
-
-static int set_boot_dev(ISADevice *s, const char *boot_device, int fd_bootchk)
-{
-#define PC_MAX_BOOT_DEVICES 3
-    int nbds, bds[3] = { 0, };
-    int i;
-
-    nbds = strlen(boot_device);
-    if (nbds > PC_MAX_BOOT_DEVICES) {
-        error_report("Too many boot devices for PC");
-        return(1);
-    }
-    for (i = 0; i < nbds; i++) {
-        bds[i] = boot_device2nibble(boot_device[i]);
-        if (bds[i] == 0) {
-            error_report("Invalid boot device for PC: '%c'",
-                         boot_device[i]);
-            return(1);
-        }
-    }
-    rtc_set_memory(s, 0x3d, (bds[1] << 4) | bds[0]);
-    rtc_set_memory(s, 0x38, (bds[2] << 4) | (fd_bootchk ? 0x0 : 0x1));
-    return(0);
-}
-
-static int pc_boot_set(void *opaque, const char *boot_device)
-{
-    return set_boot_dev(opaque, boot_device, 0);
-}
-
-typedef struct pc_cmos_init_late_arg {
-    ISADevice *rtc_state;
-    BusState *idebus[2];
-} pc_cmos_init_late_arg;
-
-static void pc_cmos_init_late(void *opaque)
-{
-    pc_cmos_init_late_arg *arg = opaque;
-    ISADevice *s = arg->rtc_state;
-    int16_t cylinders;
-    int8_t heads, sectors;
-    int val;
-    int i, trans;
-
-    val = 0;
-    if (ide_get_geometry(arg->idebus[0], 0,
-                         &cylinders, &heads, &sectors) >= 0) {
-        cmos_init_hd(s, 0x19, 0x1b, cylinders, heads, sectors);
-        val |= 0xf0;
-    }
-    if (ide_get_geometry(arg->idebus[0], 1,
-                         &cylinders, &heads, &sectors) >= 0) {
-        cmos_init_hd(s, 0x1a, 0x24, cylinders, heads, sectors);
-        val |= 0x0f;
-    }
-    rtc_set_memory(s, 0x12, val);
-
-    val = 0;
-    for (i = 0; i < 4; i++) {
-        /* NOTE: ide_get_geometry() returns the physical
-           geometry.  It is always such that: 1 <= sects <= 63, 1
-           <= heads <= 16, 1 <= cylinders <= 16383. The BIOS
-           geometry can be different if a translation is done. */
-        if (ide_get_geometry(arg->idebus[i / 2], i % 2,
-                             &cylinders, &heads, &sectors) >= 0) {
-            trans = ide_get_bios_chs_trans(arg->idebus[i / 2], i % 2) - 1;
-            assert((trans & ~3) == 0);
-            val |= trans << (i * 2);
-        }
-    }
-    rtc_set_memory(s, 0x39, val);
-
-    qemu_unregister_reset(pc_cmos_init_late, opaque);
-}
-
-void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
-                  const char *boot_device,
-                  ISADevice *floppy, BusState *idebus0, BusState *idebus1,
-                  ISADevice *s)
-{
-    int val, nb, i;
-    FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
-    static pc_cmos_init_late_arg arg;
-
-    /* various important CMOS locations needed by PC/Bochs bios */
-
-    /* memory size */
-    /* base memory (first MiB) */
-    val = MIN(ram_size / 1024, 640);
-    rtc_set_memory(s, 0x15, val);
-    rtc_set_memory(s, 0x16, val >> 8);
-    /* extended memory (next 64MiB) */
-    if (ram_size > 1024 * 1024) {
-        val = (ram_size - 1024 * 1024) / 1024;
-    } else {
-        val = 0;
-    }
-    if (val > 65535)
-        val = 65535;
-    rtc_set_memory(s, 0x17, val);
-    rtc_set_memory(s, 0x18, val >> 8);
-    rtc_set_memory(s, 0x30, val);
-    rtc_set_memory(s, 0x31, val >> 8);
-    /* memory between 16MiB and 4GiB */
-    if (ram_size > 16 * 1024 * 1024) {
-        val = (ram_size - 16 * 1024 * 1024) / 65536;
-    } else {
-        val = 0;
-    }
-    if (val > 65535)
-        val = 65535;
-    rtc_set_memory(s, 0x34, val);
-    rtc_set_memory(s, 0x35, val >> 8);
-    /* memory above 4GiB */
-    val = above_4g_mem_size / 65536;
-    rtc_set_memory(s, 0x5b, val);
-    rtc_set_memory(s, 0x5c, val >> 8);
-    rtc_set_memory(s, 0x5d, val >> 16);
-
-    /* set the number of CPU */
-    rtc_set_memory(s, 0x5f, smp_cpus - 1);
-
-    /* set boot devices, and disable floppy signature check if requested */
-    if (set_boot_dev(s, boot_device, fd_bootchk)) {
-        exit(1);
-    }
-
-    /* floppy type */
-    if (floppy) {
-        for (i = 0; i < 2; i++) {
-            fd_type[i] = isa_fdc_get_drive_type(floppy, i);
-        }
-    }
-    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 (fd_type[0] < FDRIVE_DRV_NONE) {
-        nb++;
-    }
-    if (fd_type[1] < FDRIVE_DRV_NONE) {
-        nb++;
-    }
-    switch (nb) {
-    case 0:
-        break;
-    case 1:
-        val |= 0x01; /* 1 drive, ready for boot */
-        break;
-    case 2:
-        val |= 0x41; /* 2 drives, ready for boot */
-        break;
-    }
-    val |= 0x02; /* FPU is there */
-    val |= 0x04; /* PS/2 mouse installed */
-    rtc_set_memory(s, REG_EQUIPMENT_BYTE, val);
-
-    /* hard drives */
-    arg.rtc_state = s;
-    arg.idebus[0] = idebus0;
-    arg.idebus[1] = idebus1;
-    qemu_register_reset(pc_cmos_init_late, &arg);
-}
-
-/* port 92 stuff: could be split off */
-typedef struct Port92State {
-    ISADevice dev;
-    MemoryRegion io;
-    uint8_t outport;
-    qemu_irq *a20_out;
-} Port92State;
-
-static void port92_write(void *opaque, hwaddr addr, uint64_t val,
-                         unsigned size)
-{
-    Port92State *s = opaque;
-
-    DPRINTF("port92: write 0x%02x\n", val);
-    s->outport = val;
-    qemu_set_irq(*s->a20_out, (val >> 1) & 1);
-    if (val & 1) {
-        qemu_system_reset_request();
-    }
-}
-
-static uint64_t port92_read(void *opaque, hwaddr addr,
-                            unsigned size)
-{
-    Port92State *s = opaque;
-    uint32_t ret;
-
-    ret = s->outport;
-    DPRINTF("port92: read 0x%02x\n", ret);
-    return ret;
-}
-
-static void port92_init(ISADevice *dev, qemu_irq *a20_out)
-{
-    Port92State *s = DO_UPCAST(Port92State, dev, dev);
-
-    s->a20_out = a20_out;
-}
-
-static const VMStateDescription vmstate_port92_isa = {
-    .name = "port92",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField []) {
-        VMSTATE_UINT8(outport, Port92State),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void port92_reset(DeviceState *d)
-{
-    Port92State *s = container_of(d, Port92State, dev.qdev);
-
-    s->outport &= ~1;
-}
-
-static const MemoryRegionOps port92_ops = {
-    .read = port92_read,
-    .write = port92_write,
-    .impl = {
-        .min_access_size = 1,
-        .max_access_size = 1,
-    },
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static int port92_initfn(ISADevice *dev)
-{
-    Port92State *s = DO_UPCAST(Port92State, dev, dev);
-
-    memory_region_init_io(&s->io, &port92_ops, s, "port92", 1);
-    isa_register_ioport(dev, &s->io, 0x92);
-
-    s->outport = 0;
-    return 0;
-}
-
-static void port92_class_initfn(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
-    ic->init = port92_initfn;
-    dc->no_user = 1;
-    dc->reset = port92_reset;
-    dc->vmsd = &vmstate_port92_isa;
-}
-
-static const TypeInfo port92_info = {
-    .name          = "port92",
-    .parent        = TYPE_ISA_DEVICE,
-    .instance_size = sizeof(Port92State),
-    .class_init    = port92_class_initfn,
-};
-
-static void port92_register_types(void)
-{
-    type_register_static(&port92_info);
-}
-
-type_init(port92_register_types)
-
-static void handle_a20_line_change(void *opaque, int irq, int level)
-{
-    X86CPU *cpu = opaque;
-
-    /* XXX: send to all CPUs ? */
-    /* XXX: add logic to handle multiple A20 line sources */
-    x86_cpu_set_a20(cpu, level);
-}
-
-int e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
-{
-    int index = le32_to_cpu(e820_table.count);
-    struct e820_entry *entry;
-
-    if (index >= E820_NR_ENTRIES)
-        return -EBUSY;
-    entry = &e820_table.entry[index++];
-
-    entry->address = cpu_to_le64(address);
-    entry->length = cpu_to_le64(length);
-    entry->type = cpu_to_le32(type);
-
-    e820_table.count = cpu_to_le32(index);
-    return index;
-}
-
-/* Calculates the limit to CPU APIC ID values
- *
- * This function returns the limit for the APIC ID value, so that all
- * CPU APIC IDs are < pc_apic_id_limit().
- *
- * This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init().
- */
-static unsigned int pc_apic_id_limit(unsigned int max_cpus)
-{
-    return x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
-}
-
-static void *bochs_bios_init(void)
-{
-    void *fw_cfg;
-    uint8_t *smbios_table;
-    size_t smbios_len;
-    uint64_t *numa_fw_cfg;
-    int i, j;
-    unsigned int apic_id_limit = pc_apic_id_limit(max_cpus);
-
-    fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
-    /* FW_CFG_MAX_CPUS is a bit confusing/problematic on x86:
-     *
-     * SeaBIOS needs FW_CFG_MAX_CPUS for CPU hotplug, but the CPU hotplug
-     * QEMU<->SeaBIOS interface is not based on the "CPU index", but on the APIC
-     * ID of hotplugged CPUs[1]. This means that FW_CFG_MAX_CPUS is not the
-     * "maximum number of CPUs", but the "limit to the APIC ID values SeaBIOS
-     * may see".
-     *
-     * So, this means we must not use max_cpus, here, but the maximum possible
-     * APIC ID value, plus one.
-     *
-     * [1] The only kind of "CPU identifier" used between SeaBIOS and QEMU is
-     *     the APIC ID, not the "CPU index"
-     */
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)apic_id_limit);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
-    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
-    fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES,
-                     acpi_tables, acpi_tables_len);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
-
-    smbios_table = smbios_get_table(&smbios_len);
-    if (smbios_table)
-        fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES,
-                         smbios_table, smbios_len);
-    fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE,
-                     &e820_table, sizeof(e820_table));
-
-    fw_cfg_add_bytes(fw_cfg, FW_CFG_HPET, &hpet_cfg, sizeof(hpet_cfg));
-    /* allocate memory for the NUMA channel: one (64bit) word for the number
-     * of nodes, one word for each VCPU->node and one word for each node to
-     * hold the amount of memory.
-     */
-    numa_fw_cfg = g_new0(uint64_t, 1 + apic_id_limit + nb_numa_nodes);
-    numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes);
-    for (i = 0; i < max_cpus; i++) {
-        unsigned int apic_id = x86_cpu_apic_id_from_index(i);
-        assert(apic_id < apic_id_limit);
-        for (j = 0; j < nb_numa_nodes; j++) {
-            if (test_bit(i, node_cpumask[j])) {
-                numa_fw_cfg[apic_id + 1] = cpu_to_le64(j);
-                break;
-            }
-        }
-    }
-    for (i = 0; i < nb_numa_nodes; i++) {
-        numa_fw_cfg[apic_id_limit + 1 + i] = cpu_to_le64(node_mem[i]);
-    }
-    fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, numa_fw_cfg,
-                     (1 + apic_id_limit + nb_numa_nodes) *
-                     sizeof(*numa_fw_cfg));
-
-    return fw_cfg;
-}
-
-static long get_file_size(FILE *f)
-{
-    long where, size;
-
-    /* XXX: on Unix systems, using fstat() probably makes more sense */
-
-    where = ftell(f);
-    fseek(f, 0, SEEK_END);
-    size = ftell(f);
-    fseek(f, where, SEEK_SET);
-
-    return size;
-}
-
-static void load_linux(void *fw_cfg,
-                       const char *kernel_filename,
-		       const char *initrd_filename,
-		       const char *kernel_cmdline,
-                       hwaddr max_ram_size)
-{
-    uint16_t protocol;
-    int setup_size, kernel_size, initrd_size = 0, cmdline_size;
-    uint32_t initrd_max;
-    uint8_t header[8192], *setup, *kernel, *initrd_data;
-    hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0;
-    FILE *f;
-    char *vmode;
-
-    /* Align to 16 bytes as a paranoia measure */
-    cmdline_size = (strlen(kernel_cmdline)+16) & ~15;
-
-    /* load the kernel header */
-    f = fopen(kernel_filename, "rb");
-    if (!f || !(kernel_size = get_file_size(f)) ||
-	fread(header, 1, MIN(ARRAY_SIZE(header), kernel_size), f) !=
-	MIN(ARRAY_SIZE(header), kernel_size)) {
-	fprintf(stderr, "qemu: could not load kernel '%s': %s\n",
-		kernel_filename, strerror(errno));
-	exit(1);
-    }
-
-    /* kernel protocol version */
-#if 0
-    fprintf(stderr, "header magic: %#x\n", ldl_p(header+0x202));
-#endif
-    if (ldl_p(header+0x202) == 0x53726448)
-	protocol = lduw_p(header+0x206);
-    else {
-	/* This looks like a multiboot kernel. If it is, let's stop
-	   treating it like a Linux kernel. */
-        if (load_multiboot(fw_cfg, f, kernel_filename, initrd_filename,
-                           kernel_cmdline, kernel_size, header))
-            return;
-	protocol = 0;
-    }
-
-    if (protocol < 0x200 || !(header[0x211] & 0x01)) {
-	/* Low kernel */
-	real_addr    = 0x90000;
-	cmdline_addr = 0x9a000 - cmdline_size;
-	prot_addr    = 0x10000;
-    } else if (protocol < 0x202) {
-	/* High but ancient kernel */
-	real_addr    = 0x90000;
-	cmdline_addr = 0x9a000 - cmdline_size;
-	prot_addr    = 0x100000;
-    } else {
-	/* High and recent kernel */
-	real_addr    = 0x10000;
-	cmdline_addr = 0x20000;
-	prot_addr    = 0x100000;
-    }
-
-#if 0
-    fprintf(stderr,
-	    "qemu: real_addr     = 0x" TARGET_FMT_plx "\n"
-	    "qemu: cmdline_addr  = 0x" TARGET_FMT_plx "\n"
-	    "qemu: prot_addr     = 0x" TARGET_FMT_plx "\n",
-	    real_addr,
-	    cmdline_addr,
-	    prot_addr);
-#endif
-
-    /* highest address for loading the initrd */
-    if (protocol >= 0x203)
-	initrd_max = ldl_p(header+0x22c);
-    else
-	initrd_max = 0x37ffffff;
-
-    if (initrd_max >= max_ram_size-ACPI_DATA_SIZE)
-    	initrd_max = max_ram_size-ACPI_DATA_SIZE-1;
-
-    fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, strlen(kernel_cmdline)+1);
-    fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
-
-    if (protocol >= 0x202) {
-	stl_p(header+0x228, cmdline_addr);
-    } else {
-	stw_p(header+0x20, 0xA33F);
-	stw_p(header+0x22, cmdline_addr-real_addr);
-    }
-
-    /* handle vga= parameter */
-    vmode = strstr(kernel_cmdline, "vga=");
-    if (vmode) {
-        unsigned int video_mode;
-        /* skip "vga=" */
-        vmode += 4;
-        if (!strncmp(vmode, "normal", 6)) {
-            video_mode = 0xffff;
-        } else if (!strncmp(vmode, "ext", 3)) {
-            video_mode = 0xfffe;
-        } else if (!strncmp(vmode, "ask", 3)) {
-            video_mode = 0xfffd;
-        } else {
-            video_mode = strtol(vmode, NULL, 0);
-        }
-        stw_p(header+0x1fa, video_mode);
-    }
-
-    /* loader type */
-    /* High nybble = B reserved for QEMU; low nybble is revision number.
-       If this code is substantially changed, you may want to consider
-       incrementing the revision. */
-    if (protocol >= 0x200)
-	header[0x210] = 0xB0;
-
-    /* heap */
-    if (protocol >= 0x201) {
-	header[0x211] |= 0x80;	/* CAN_USE_HEAP */
-	stw_p(header+0x224, cmdline_addr-real_addr-0x200);
-    }
-
-    /* load initrd */
-    if (initrd_filename) {
-	if (protocol < 0x200) {
-	    fprintf(stderr, "qemu: linux kernel too old to load a ram disk\n");
-	    exit(1);
-	}
-
-	initrd_size = get_image_size(initrd_filename);
-        if (initrd_size < 0) {
-            fprintf(stderr, "qemu: error reading initrd %s\n",
-                    initrd_filename);
-            exit(1);
-        }
-
-        initrd_addr = (initrd_max-initrd_size) & ~4095;
-
-        initrd_data = g_malloc(initrd_size);
-        load_image(initrd_filename, initrd_data);
-
-        fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
-        fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
-        fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data, initrd_size);
-
-	stl_p(header+0x218, initrd_addr);
-	stl_p(header+0x21c, initrd_size);
-    }
-
-    /* load kernel and setup */
-    setup_size = header[0x1f1];
-    if (setup_size == 0)
-	setup_size = 4;
-    setup_size = (setup_size+1)*512;
-    kernel_size -= setup_size;
-
-    setup  = g_malloc(setup_size);
-    kernel = g_malloc(kernel_size);
-    fseek(f, 0, SEEK_SET);
-    if (fread(setup, 1, setup_size, f) != setup_size) {
-        fprintf(stderr, "fread() failed\n");
-        exit(1);
-    }
-    if (fread(kernel, 1, kernel_size, f) != kernel_size) {
-        fprintf(stderr, "fread() failed\n");
-        exit(1);
-    }
-    fclose(f);
-    memcpy(setup, header, MIN(sizeof(header), setup_size));
-
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
-    fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
-
-    fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size);
-    fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size);
-
-    option_rom[nb_option_roms].name = "linuxboot.bin";
-    option_rom[nb_option_roms].bootindex = 0;
-    nb_option_roms++;
-}
-
-#define NE2000_NB_MAX 6
-
-static const int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360,
-                                              0x280, 0x380 };
-static const int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
-
-static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
-static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
-
-void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd)
-{
-    static int nb_ne2k = 0;
-
-    if (nb_ne2k == NE2000_NB_MAX)
-        return;
-    isa_ne2000_init(bus, ne2000_io[nb_ne2k],
-                    ne2000_irq[nb_ne2k], nd);
-    nb_ne2k++;
-}
-
-DeviceState *cpu_get_current_apic(void)
-{
-    if (cpu_single_env) {
-        return cpu_single_env->apic_state;
-    } else {
-        return NULL;
-    }
-}
-
-void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
-{
-    CPUX86State *s = opaque;
-
-    if (level) {
-        cpu_interrupt(s, CPU_INTERRUPT_SMI);
-    }
-}
-
-void pc_cpus_init(const char *cpu_model)
-{
-    int i;
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-#ifdef TARGET_X86_64
-        cpu_model = "qemu64";
-#else
-        cpu_model = "qemu32";
-#endif
-    }
-
-    for (i = 0; i < smp_cpus; i++) {
-        if (!cpu_x86_init(cpu_model)) {
-            exit(1);
-        }
-    }
-}
-
-void pc_acpi_init(const char *default_dsdt)
-{
-    char *filename = NULL, *arg = NULL;
-
-    if (acpi_tables != NULL) {
-        /* manually set via -acpitable, leave it alone */
-        return;
-    }
-
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, default_dsdt);
-    if (filename == NULL) {
-        fprintf(stderr, "WARNING: failed to find %s\n", default_dsdt);
-        return;
-    }
-
-    arg = g_strdup_printf("file=%s", filename);
-    if (acpi_table_add(arg) != 0) {
-        fprintf(stderr, "WARNING: failed to load %s\n", filename);
-    }
-    g_free(arg);
-    g_free(filename);
-}
-
-void *pc_memory_init(MemoryRegion *system_memory,
-                    const char *kernel_filename,
-                    const char *kernel_cmdline,
-                    const char *initrd_filename,
-                    ram_addr_t below_4g_mem_size,
-                    ram_addr_t above_4g_mem_size,
-                    MemoryRegion *rom_memory,
-                    MemoryRegion **ram_memory)
-{
-    int linux_boot, i;
-    MemoryRegion *ram, *option_rom_mr;
-    MemoryRegion *ram_below_4g, *ram_above_4g;
-    void *fw_cfg;
-
-    linux_boot = (kernel_filename != NULL);
-
-    /* Allocate RAM.  We allocate it as a single memory region and use
-     * aliases to address portions of it, mostly for backwards compatibility
-     * with older qemus that used qemu_ram_alloc().
-     */
-    ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, "pc.ram",
-                           below_4g_mem_size + above_4g_mem_size);
-    vmstate_register_ram_global(ram);
-    *ram_memory = ram;
-    ram_below_4g = g_malloc(sizeof(*ram_below_4g));
-    memory_region_init_alias(ram_below_4g, "ram-below-4g", ram,
-                             0, below_4g_mem_size);
-    memory_region_add_subregion(system_memory, 0, ram_below_4g);
-    if (above_4g_mem_size > 0) {
-        ram_above_4g = g_malloc(sizeof(*ram_above_4g));
-        memory_region_init_alias(ram_above_4g, "ram-above-4g", ram,
-                                 below_4g_mem_size, above_4g_mem_size);
-        memory_region_add_subregion(system_memory, 0x100000000ULL,
-                                    ram_above_4g);
-    }
-
-
-    /* Initialize PC system firmware */
-    pc_system_firmware_init(rom_memory);
-
-    option_rom_mr = g_malloc(sizeof(*option_rom_mr));
-    memory_region_init_ram(option_rom_mr, "pc.rom", PC_ROM_SIZE);
-    vmstate_register_ram_global(option_rom_mr);
-    memory_region_add_subregion_overlap(rom_memory,
-                                        PC_ROM_MIN_VGA,
-                                        option_rom_mr,
-                                        1);
-
-    fw_cfg = bochs_bios_init();
-    rom_set_fw(fw_cfg);
-
-    if (linux_boot) {
-        load_linux(fw_cfg, kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size);
-    }
-
-    for (i = 0; i < nb_option_roms; i++) {
-        rom_add_option(option_rom[i].name, option_rom[i].bootindex);
-    }
-    return fw_cfg;
-}
-
-qemu_irq *pc_allocate_cpu_irq(void)
-{
-    return qemu_allocate_irqs(pic_irq_request, NULL, 1);
-}
-
-DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
-{
-    DeviceState *dev = NULL;
-
-    if (pci_bus) {
-        PCIDevice *pcidev = pci_vga_init(pci_bus);
-        dev = pcidev ? &pcidev->qdev : NULL;
-    } else if (isa_bus) {
-        ISADevice *isadev = isa_vga_init(isa_bus);
-        dev = isadev ? &isadev->qdev : NULL;
-    }
-    return dev;
-}
-
-static void cpu_request_exit(void *opaque, int irq, int level)
-{
-    CPUX86State *env = cpu_single_env;
-
-    if (env && level) {
-        cpu_exit(env);
-    }
-}
-
-static const MemoryRegionOps ioport80_io_ops = {
-    .write = ioport80_write,
-    .read = ioport80_read,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-    .impl = {
-        .min_access_size = 1,
-        .max_access_size = 1,
-    },
-};
-
-static const MemoryRegionOps ioportF0_io_ops = {
-    .write = ioportF0_write,
-    .read = ioportF0_read,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-    .impl = {
-        .min_access_size = 1,
-        .max_access_size = 1,
-    },
-};
-
-void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
-                          ISADevice **rtc_state,
-                          ISADevice **floppy,
-                          bool no_vmport)
-{
-    int i;
-    DriveInfo *fd[MAX_FD];
-    DeviceState *hpet = NULL;
-    int pit_isa_irq = 0;
-    qemu_irq pit_alt_irq = NULL;
-    qemu_irq rtc_irq = NULL;
-    qemu_irq *a20_line;
-    ISADevice *i8042, *port92, *vmmouse, *pit = NULL;
-    qemu_irq *cpu_exit_irq;
-    MemoryRegion *ioport80_io = g_new(MemoryRegion, 1);
-    MemoryRegion *ioportF0_io = g_new(MemoryRegion, 1);
-
-    memory_region_init_io(ioport80_io, &ioport80_io_ops, NULL, "ioport80", 1);
-    memory_region_add_subregion(isa_bus->address_space_io, 0x80, ioport80_io);
-
-    memory_region_init_io(ioportF0_io, &ioportF0_io_ops, NULL, "ioportF0", 1);
-    memory_region_add_subregion(isa_bus->address_space_io, 0xf0, ioportF0_io);
-
-    /*
-     * Check if an HPET shall be created.
-     *
-     * Without KVM_CAP_PIT_STATE2, we cannot switch off the in-kernel PIT
-     * when the HPET wants to take over. Thus we have to disable the latter.
-     */
-    if (!no_hpet && (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) {
-        hpet = sysbus_try_create_simple("hpet", HPET_BASE, NULL);
-
-        if (hpet) {
-            for (i = 0; i < GSI_NUM_PINS; i++) {
-                sysbus_connect_irq(SYS_BUS_DEVICE(hpet), i, gsi[i]);
-            }
-            pit_isa_irq = -1;
-            pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT);
-            rtc_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_RTC_INT);
-        }
-    }
-    *rtc_state = rtc_init(isa_bus, 2000, rtc_irq);
-
-    qemu_register_boot_set(pc_boot_set, *rtc_state);
-
-    if (!xen_enabled()) {
-        if (kvm_irqchip_in_kernel()) {
-            pit = kvm_pit_init(isa_bus, 0x40);
-        } else {
-            pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
-        }
-        if (hpet) {
-            /* connect PIT to output control line of the HPET */
-            qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0));
-        }
-        pcspk_init(isa_bus, pit);
-    }
-
-    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
-        if (serial_hds[i]) {
-            serial_isa_init(isa_bus, i, serial_hds[i]);
-        }
-    }
-
-    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
-        if (parallel_hds[i]) {
-            parallel_init(isa_bus, i, parallel_hds[i]);
-        }
-    }
-
-    a20_line = qemu_allocate_irqs(handle_a20_line_change,
-                                  x86_env_get_cpu(first_cpu), 2);
-    i8042 = isa_create_simple(isa_bus, "i8042");
-    i8042_setup_a20_line(i8042, &a20_line[0]);
-    if (!no_vmport) {
-        vmport_init(isa_bus);
-        vmmouse = isa_try_create(isa_bus, "vmmouse");
-    } else {
-        vmmouse = NULL;
-    }
-    if (vmmouse) {
-        qdev_prop_set_ptr(&vmmouse->qdev, "ps2_mouse", i8042);
-        qdev_init_nofail(&vmmouse->qdev);
-    }
-    port92 = isa_create_simple(isa_bus, "port92");
-    port92_init(port92, &a20_line[1]);
-
-    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
-    DMA_init(0, cpu_exit_irq);
-
-    for(i = 0; i < MAX_FD; i++) {
-        fd[i] = drive_get(IF_FLOPPY, 0, i);
-    }
-    *floppy = fdctrl_init_isa(isa_bus, fd);
-}
-
-void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus)
-{
-    int i;
-
-    for (i = 0; i < nb_nics; i++) {
-        NICInfo *nd = &nd_table[i];
-
-        if (!pci_bus || (nd->model && strcmp(nd->model, "ne2k_isa") == 0)) {
-            pc_init_ne2k_isa(isa_bus, nd);
-        } else {
-            pci_nic_init_nofail(nd, "e1000", NULL);
-        }
-    }
-}
-
-void pc_pci_device_init(PCIBus *pci_bus)
-{
-    int max_bus;
-    int bus;
-
-    max_bus = drive_get_max_bus(IF_SCSI);
-    for (bus = 0; bus <= max_bus; bus++) {
-        pci_create_simple(pci_bus, -1, "lsi53c895a");
-    }
-}
-
-void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name)
-{
-    DeviceState *dev;
-    SysBusDevice *d;
-    unsigned int i;
-
-    if (kvm_irqchip_in_kernel()) {
-        dev = qdev_create(NULL, "kvm-ioapic");
-    } else {
-        dev = qdev_create(NULL, "ioapic");
-    }
-    if (parent_name) {
-        object_property_add_child(object_resolve_path(parent_name, NULL),
-                                  "ioapic", OBJECT(dev), NULL);
-    }
-    qdev_init_nofail(dev);
-    d = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(d, 0, 0xfec00000);
-
-    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
-        gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i);
-    }
-}
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
deleted file mode 100644
index 73a8656..0000000
--- a/hw/pc_piix.c
+++ /dev/null
@@ -1,713 +0,0 @@
-/*
- * QEMU PC System Emulator
- *
- * Copyright (c) 2003-2004 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 <glib.h>
-
-#include "hw/hw.h"
-#include "hw/pc.h"
-#include "hw/apic.h"
-#include "hw/pci/pci.h"
-#include "hw/pci/pci_ids.h"
-#include "hw/usb.h"
-#include "net/net.h"
-#include "hw/boards.h"
-#include "hw/ide.h"
-#include "sysemu/kvm.h"
-#include "hw/kvm/clock.h"
-#include "sysemu/sysemu.h"
-#include "hw/sysbus.h"
-#include "sysemu/arch_init.h"
-#include "sysemu/blockdev.h"
-#include "hw/smbus.h"
-#include "hw/xen.h"
-#include "exec/memory.h"
-#include "exec/address-spaces.h"
-#include "cpu.h"
-#ifdef CONFIG_XEN
-#  include <xen/hvm/hvm_info_table.h>
-#endif
-
-#define MAX_IDE_BUS 2
-
-static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
-static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
-static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
-
-/* PC hardware initialisation */
-static void pc_init1(MemoryRegion *system_memory,
-                     MemoryRegion *system_io,
-                     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,
-                     int pci_enabled,
-                     int kvmclock_enabled)
-{
-    int i;
-    ram_addr_t below_4g_mem_size, above_4g_mem_size;
-    PCIBus *pci_bus;
-    ISABus *isa_bus;
-    PCII440FXState *i440fx_state;
-    int piix3_devfn = -1;
-    qemu_irq *cpu_irq;
-    qemu_irq *gsi;
-    qemu_irq *i8259;
-    qemu_irq *smi_irq;
-    GSIState *gsi_state;
-    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    BusState *idebus[MAX_IDE_BUS];
-    ISADevice *rtc_state;
-    ISADevice *floppy;
-    MemoryRegion *ram_memory;
-    MemoryRegion *pci_memory;
-    MemoryRegion *rom_memory;
-    void *fw_cfg = NULL;
-
-    pc_cpus_init(cpu_model);
-    pc_acpi_init("acpi-dsdt.aml");
-
-    if (kvmclock_enabled) {
-        kvmclock_create();
-    }
-
-    if (ram_size >= 0xe0000000 ) {
-        above_4g_mem_size = ram_size - 0xe0000000;
-        below_4g_mem_size = 0xe0000000;
-    } else {
-        above_4g_mem_size = 0;
-        below_4g_mem_size = ram_size;
-    }
-
-    if (pci_enabled) {
-        pci_memory = g_new(MemoryRegion, 1);
-        memory_region_init(pci_memory, "pci", INT64_MAX);
-        rom_memory = pci_memory;
-    } else {
-        pci_memory = NULL;
-        rom_memory = system_memory;
-    }
-
-    /* allocate ram and load rom/bios */
-    if (!xen_enabled()) {
-        fw_cfg = pc_memory_init(system_memory,
-                       kernel_filename, kernel_cmdline, initrd_filename,
-                       below_4g_mem_size, above_4g_mem_size,
-                       rom_memory, &ram_memory);
-    }
-
-    gsi_state = g_malloc0(sizeof(*gsi_state));
-    if (kvm_irqchip_in_kernel()) {
-        kvm_pc_setup_irq_routing(pci_enabled);
-        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
-                                 GSI_NUM_PINS);
-    } else {
-        gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
-    }
-
-    if (pci_enabled) {
-        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
-                              system_memory, system_io, ram_size,
-                              below_4g_mem_size,
-                              0x100000000ULL - below_4g_mem_size,
-                              0x100000000ULL + above_4g_mem_size,
-                              (sizeof(hwaddr) == 4
-                               ? 0
-                               : ((uint64_t)1 << 62)),
-                              pci_memory, ram_memory);
-    } else {
-        pci_bus = NULL;
-        i440fx_state = NULL;
-        isa_bus = isa_bus_new(NULL, system_io);
-        no_hpet = 1;
-    }
-    isa_bus_irqs(isa_bus, gsi);
-
-    if (kvm_irqchip_in_kernel()) {
-        i8259 = kvm_i8259_init(isa_bus);
-    } else if (xen_enabled()) {
-        i8259 = xen_interrupt_controller_init();
-    } else {
-        cpu_irq = pc_allocate_cpu_irq();
-        i8259 = i8259_init(isa_bus, cpu_irq[0]);
-    }
-
-    for (i = 0; i < ISA_NUM_IRQS; i++) {
-        gsi_state->i8259_irq[i] = i8259[i];
-    }
-    if (pci_enabled) {
-        ioapic_init_gsi(gsi_state, "i440fx");
-    }
-
-    pc_register_ferr_irq(gsi[13]);
-
-    pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
-    if (xen_enabled()) {
-        pci_create_simple(pci_bus, -1, "xen-platform");
-    }
-
-    /* init basic PC hardware */
-    pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled());
-
-    pc_nic_init(isa_bus, pci_bus);
-
-    ide_drive_get(hd, MAX_IDE_BUS);
-    if (pci_enabled) {
-        PCIDevice *dev;
-        if (xen_enabled()) {
-            dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
-        } else {
-            dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
-        }
-        idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
-        idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
-    } else {
-        for(i = 0; i < MAX_IDE_BUS; i++) {
-            ISADevice *dev;
-            dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
-                               ide_irq[i],
-                               hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
-            idebus[i] = qdev_get_child_bus(&dev->qdev, "ide.0");
-        }
-    }
-
-    audio_init(isa_bus, pci_enabled ? pci_bus : NULL);
-
-    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
-                 floppy, idebus[0], idebus[1], rtc_state);
-
-    if (pci_enabled && usb_enabled(false)) {
-        pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
-    }
-
-    if (pci_enabled && acpi_enabled) {
-        i2c_bus *smbus;
-
-        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,
-                              gsi[9], *smi_irq,
-                              kvm_enabled(), fw_cfg);
-        smbus_eeprom_init(smbus, 8, NULL, 0);
-    }
-
-    if (pci_enabled) {
-        pc_pci_device_init(pci_bus);
-    }
-}
-
-static void pc_init_pci(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    pc_init1(get_system_memory(),
-             get_system_io(),
-             ram_size, boot_device,
-             kernel_filename, kernel_cmdline,
-             initrd_filename, cpu_model, 1, 1);
-}
-
-static void pc_init_pci_1_3(QEMUMachineInitArgs *args)
-{
-    enable_compat_apic_id_mode();
-    pc_init_pci(args);
-}
-
-/* PC machine init function for pc-0.14 to pc-1.2 */
-static void pc_init_pci_1_2(QEMUMachineInitArgs *args)
-{
-    disable_kvm_pv_eoi();
-    pc_init_pci_1_3(args);
-}
-
-/* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */
-static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    disable_kvm_pv_eoi();
-    enable_compat_apic_id_mode();
-    pc_init1(get_system_memory(),
-             get_system_io(),
-             ram_size, boot_device,
-             kernel_filename, kernel_cmdline,
-             initrd_filename, cpu_model, 1, 0);
-}
-
-static void pc_init_isa(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    if (cpu_model == NULL)
-        cpu_model = "486";
-    disable_kvm_pv_eoi();
-    enable_compat_apic_id_mode();
-    pc_init1(get_system_memory(),
-             get_system_io(),
-             ram_size, boot_device,
-             kernel_filename, kernel_cmdline,
-             initrd_filename, cpu_model, 0, 1);
-}
-
-#ifdef CONFIG_XEN
-static void pc_xen_hvm_init(QEMUMachineInitArgs *args)
-{
-    if (xen_hvm_init() != 0) {
-        hw_error("xen hardware virtual machine initialisation failed");
-    }
-    pc_init_pci_no_kvmclock(args);
-    xen_vcpu_init();
-}
-#endif
-
-static QEMUMachine pc_i440fx_machine_v1_5 = {
-    .name = "pc-i440fx-1.5",
-    .alias = "pc",
-    .desc = "Standard PC (i440FX + PIIX, 1996)",
-    .init = pc_init_pci,
-    .max_cpus = 255,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine pc_i440fx_machine_v1_4 = {
-    .name = "pc-i440fx-1.4",
-    .desc = "Standard PC (i440FX + PIIX, 1996)",
-    .init = pc_init_pci,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_1_4,
-        { /* end of list */ }
-    },
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_1_3 \
-	PC_COMPAT_1_4, \
-        {\
-            .driver   = "usb-tablet",\
-            .property = "usb_version",\
-            .value    = stringify(1),\
-        },{\
-            .driver   = "virtio-net-pci",\
-            .property = "ctrl_mac_addr",\
-            .value    = "off",      \
-        },{ \
-            .driver   = "virtio-net-pci", \
-            .property = "mq", \
-            .value    = "off", \
-        }
-
-static QEMUMachine pc_machine_v1_3 = {
-    .name = "pc-1.3",
-    .desc = "Standard PC",
-    .init = pc_init_pci_1_3,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_1_3,
-        { /* end of list */ }
-    },
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_1_2 \
-        PC_COMPAT_1_3,\
-        {\
-            .driver   = "nec-usb-xhci",\
-            .property = "msi",\
-            .value    = "off",\
-        },{\
-            .driver   = "nec-usb-xhci",\
-            .property = "msix",\
-            .value    = "off",\
-        },{\
-            .driver   = "ivshmem",\
-            .property = "use64",\
-            .value    = "0",\
-        },{\
-            .driver   = "qxl",\
-            .property = "revision",\
-            .value    = stringify(3),\
-        },{\
-            .driver   = "qxl-vga",\
-            .property = "revision",\
-            .value    = stringify(3),\
-        },{\
-            .driver   = "VGA",\
-            .property = "mmio",\
-            .value    = "off",\
-        }
-
-static QEMUMachine pc_machine_v1_2 = {
-    .name = "pc-1.2",
-    .desc = "Standard PC",
-    .init = pc_init_pci_1_2,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_1_2,
-        { /* end of list */ }
-    },
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_1_1 \
-        PC_COMPAT_1_2,\
-        {\
-            .driver   = "virtio-scsi-pci",\
-            .property = "hotplug",\
-            .value    = "off",\
-        },{\
-            .driver   = "virtio-scsi-pci",\
-            .property = "param_change",\
-            .value    = "off",\
-        },{\
-            .driver   = "VGA",\
-            .property = "vgamem_mb",\
-            .value    = stringify(8),\
-        },{\
-            .driver   = "vmware-svga",\
-            .property = "vgamem_mb",\
-            .value    = stringify(8),\
-        },{\
-            .driver   = "qxl-vga",\
-            .property = "vgamem_mb",\
-            .value    = stringify(8),\
-        },{\
-            .driver   = "qxl",\
-            .property = "vgamem_mb",\
-            .value    = stringify(8),\
-        },{\
-            .driver   = "virtio-blk-pci",\
-            .property = "config-wce",\
-            .value    = "off",\
-        }
-
-static QEMUMachine pc_machine_v1_1 = {
-    .name = "pc-1.1",
-    .desc = "Standard PC",
-    .init = pc_init_pci_1_2,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_1_1,
-        { /* end of list */ }
-    },
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_1_0 \
-        PC_COMPAT_1_1,\
-        {\
-            .driver   = "pc-sysfw",\
-            .property = "rom_only",\
-            .value    = stringify(1),\
-        }, {\
-            .driver   = "isa-fdc",\
-            .property = "check_media_rate",\
-            .value    = "off",\
-        }, {\
-            .driver   = "virtio-balloon-pci",\
-            .property = "class",\
-            .value    = stringify(PCI_CLASS_MEMORY_RAM),\
-        },{\
-            .driver   = "apic",\
-            .property = "vapic",\
-            .value    = "off",\
-        },{\
-            .driver   = TYPE_USB_DEVICE,\
-            .property = "full-path",\
-            .value    = "no",\
-        }
-
-static QEMUMachine pc_machine_v1_0 = {
-    .name = "pc-1.0",
-    .desc = "Standard PC",
-    .init = pc_init_pci_1_2,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_1_0,
-        { /* end of list */ }
-    },
-    .hw_version = "1.0",
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_0_15 \
-        PC_COMPAT_1_0
-
-static QEMUMachine pc_machine_v0_15 = {
-    .name = "pc-0.15",
-    .desc = "Standard PC",
-    .init = pc_init_pci_1_2,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_0_15,
-        { /* end of list */ }
-    },
-    .hw_version = "0.15",
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_0_14 \
-        PC_COMPAT_0_15,\
-        {\
-            .driver   = "virtio-blk-pci",\
-            .property = "event_idx",\
-            .value    = "off",\
-        },{\
-            .driver   = "virtio-serial-pci",\
-            .property = "event_idx",\
-            .value    = "off",\
-        },{\
-            .driver   = "virtio-net-pci",\
-            .property = "event_idx",\
-            .value    = "off",\
-        },{\
-            .driver   = "virtio-balloon-pci",\
-            .property = "event_idx",\
-            .value    = "off",\
-        }
-
-static QEMUMachine pc_machine_v0_14 = {
-    .name = "pc-0.14",
-    .desc = "Standard PC",
-    .init = pc_init_pci_1_2,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_0_14, 
-        {
-            .driver   = "qxl",
-            .property = "revision",
-            .value    = stringify(2),
-        },{
-            .driver   = "qxl-vga",
-            .property = "revision",
-            .value    = stringify(2),
-        },
-        { /* end of list */ }
-    },
-    .hw_version = "0.14",
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_0_13 \
-        PC_COMPAT_0_14,\
-        {\
-            .driver   = TYPE_PCI_DEVICE,\
-            .property = "command_serr_enable",\
-            .value    = "off",\
-        },{\
-            .driver   = "AC97",\
-            .property = "use_broken_id",\
-            .value    = stringify(1),\
-        }
-
-static QEMUMachine pc_machine_v0_13 = {
-    .name = "pc-0.13",
-    .desc = "Standard PC",
-    .init = pc_init_pci_no_kvmclock,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_0_13,
-        {
-            .driver   = "virtio-9p-pci",
-            .property = "vectors",
-            .value    = stringify(0),
-        },{
-            .driver   = "VGA",
-            .property = "rombar",
-            .value    = stringify(0),
-        },{
-            .driver   = "vmware-svga",
-            .property = "rombar",
-            .value    = stringify(0),
-        },
-        { /* end of list */ }
-    },
-    .hw_version = "0.13",
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_0_12 \
-        PC_COMPAT_0_13,\
-        {\
-            .driver   = "virtio-serial-pci",\
-            .property = "max_ports",\
-            .value    = stringify(1),\
-        },{\
-            .driver   = "virtio-serial-pci",\
-            .property = "vectors",\
-            .value    = stringify(0),\
-        }
-
-static QEMUMachine pc_machine_v0_12 = {
-    .name = "pc-0.12",
-    .desc = "Standard PC",
-    .init = pc_init_pci_no_kvmclock,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_0_12,
-        {
-            .driver   = "VGA",
-            .property = "rombar",
-            .value    = stringify(0),
-        },{
-            .driver   = "vmware-svga",
-            .property = "rombar",
-            .value    = stringify(0),
-        },
-        { /* end of list */ }
-    },
-    .hw_version = "0.12",
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#define PC_COMPAT_0_11 \
-        PC_COMPAT_0_12,\
-        {\
-            .driver   = "virtio-blk-pci",\
-            .property = "vectors",\
-            .value    = stringify(0),\
-        },{\
-            .driver   = TYPE_PCI_DEVICE,\
-            .property = "rombar",\
-            .value    = stringify(0),\
-        }
-
-static QEMUMachine pc_machine_v0_11 = {
-    .name = "pc-0.11",
-    .desc = "Standard PC, qemu 0.11",
-    .init = pc_init_pci_no_kvmclock,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_0_11,
-        {
-            .driver   = "ide-drive",
-            .property = "ver",
-            .value    = "0.11",
-        },{
-            .driver   = "scsi-disk",
-            .property = "ver",
-            .value    = "0.11",
-        },
-        { /* end of list */ }
-    },
-    .hw_version = "0.11",
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine pc_machine_v0_10 = {
-    .name = "pc-0.10",
-    .desc = "Standard PC, qemu 0.10",
-    .init = pc_init_pci_no_kvmclock,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_0_11,
-        {
-            .driver   = "virtio-blk-pci",
-            .property = "class",
-            .value    = stringify(PCI_CLASS_STORAGE_OTHER),
-        },{
-            .driver   = "virtio-serial-pci",
-            .property = "class",
-            .value    = stringify(PCI_CLASS_DISPLAY_OTHER),
-        },{
-            .driver   = "virtio-net-pci",
-            .property = "vectors",
-            .value    = stringify(0),
-        },{
-            .driver   = "ide-drive",
-            .property = "ver",
-            .value    = "0.10",
-        },{
-            .driver   = "scsi-disk",
-            .property = "ver",
-            .value    = "0.10",
-        },
-        { /* end of list */ }
-    },
-    .hw_version = "0.10",
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine isapc_machine = {
-    .name = "isapc",
-    .desc = "ISA-only PC",
-    .init = pc_init_isa,
-    .max_cpus = 1,
-    .compat_props = (GlobalProperty[]) {
-        {
-            .driver   = "pc-sysfw",
-            .property = "rom_only",
-            .value    = stringify(1),
-        },
-        { /* end of list */ }
-    },
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-#ifdef CONFIG_XEN
-static QEMUMachine xenfv_machine = {
-    .name = "xenfv",
-    .desc = "Xen Fully-virtualized PC",
-    .init = pc_xen_hvm_init,
-    .max_cpus = HVM_MAX_VCPUS,
-    .default_machine_opts = "accel=xen",
-    DEFAULT_MACHINE_OPTIONS,
-};
-#endif
-
-static void pc_machine_init(void)
-{
-    qemu_register_machine(&pc_i440fx_machine_v1_5);
-    qemu_register_machine(&pc_i440fx_machine_v1_4);
-    qemu_register_machine(&pc_machine_v1_3);
-    qemu_register_machine(&pc_machine_v1_2);
-    qemu_register_machine(&pc_machine_v1_1);
-    qemu_register_machine(&pc_machine_v1_0);
-    qemu_register_machine(&pc_machine_v0_15);
-    qemu_register_machine(&pc_machine_v0_14);
-    qemu_register_machine(&pc_machine_v0_13);
-    qemu_register_machine(&pc_machine_v0_12);
-    qemu_register_machine(&pc_machine_v0_11);
-    qemu_register_machine(&pc_machine_v0_10);
-    qemu_register_machine(&isapc_machine);
-#ifdef CONFIG_XEN
-    qemu_register_machine(&xenfv_machine);
-#endif
-}
-
-machine_init(pc_machine_init);
diff --git a/hw/pc_q35.c b/hw/pc_q35.c
deleted file mode 100644
index 4f5f347..0000000
--- a/hw/pc_q35.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Q35 chipset based pc system emulator
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- * Copyright (c) 2009, 2010
- *               Isaku Yamahata <yamahata at valinux co jp>
- *               VA Linux Systems Japan K.K.
- * Copyright (C) 2012 Jason Baron <jbaron at redhat.com>
- *
- * This is based on pc.c, but heavily modified.
- *
- * 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/hw.h"
-#include "sysemu/arch_init.h"
-#include "hw/smbus.h"
-#include "hw/boards.h"
-#include "hw/mc146818rtc.h"
-#include "hw/xen.h"
-#include "sysemu/kvm.h"
-#include "hw/kvm/clock.h"
-#include "hw/q35.h"
-#include "exec/address-spaces.h"
-#include "hw/ich9.h"
-#include "hw/ide/pci.h"
-#include "hw/ide/ahci.h"
-#include "hw/usb.h"
-
-/* ICH9 AHCI has 6 ports */
-#define MAX_SATA_PORTS     6
-
-/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
- *    BIOS will read it and start S3 resume at POST Entry */
-static void pc_cmos_set_s3_resume(void *opaque, int irq, int level)
-{
-    ISADevice *s = opaque;
-
-    if (level) {
-        rtc_set_memory(s, 0xF, 0xFE);
-    }
-}
-
-/* PC hardware initialisation */
-static void pc_q35_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    ram_addr_t below_4g_mem_size, above_4g_mem_size;
-    Q35PCIHost *q35_host;
-    PCIBus *host_bus;
-    PCIDevice *lpc;
-    BusState *idebus[MAX_SATA_PORTS];
-    ISADevice *rtc_state;
-    ISADevice *floppy;
-    MemoryRegion *pci_memory;
-    MemoryRegion *rom_memory;
-    MemoryRegion *ram_memory;
-    GSIState *gsi_state;
-    ISABus *isa_bus;
-    int pci_enabled = 1;
-    qemu_irq *cpu_irq;
-    qemu_irq *gsi;
-    qemu_irq *i8259;
-    int i;
-    ICH9LPCState *ich9_lpc;
-    PCIDevice *ahci;
-    qemu_irq *cmos_s3;
-
-    pc_cpus_init(cpu_model);
-    pc_acpi_init("q35-acpi-dsdt.aml");
-
-    kvmclock_create();
-
-    if (ram_size >= 0xb0000000) {
-        above_4g_mem_size = ram_size - 0xb0000000;
-        below_4g_mem_size = 0xb0000000;
-    } else {
-        above_4g_mem_size = 0;
-        below_4g_mem_size = ram_size;
-    }
-
-    /* pci enabled */
-    if (pci_enabled) {
-        pci_memory = g_new(MemoryRegion, 1);
-        memory_region_init(pci_memory, "pci", INT64_MAX);
-        rom_memory = pci_memory;
-    } else {
-        pci_memory = NULL;
-        rom_memory = get_system_memory();
-    }
-
-    /* allocate ram and load rom/bios */
-    if (!xen_enabled()) {
-        pc_memory_init(get_system_memory(), kernel_filename, kernel_cmdline,
-                       initrd_filename, below_4g_mem_size, above_4g_mem_size,
-                       rom_memory, &ram_memory);
-    }
-
-    /* irq lines */
-    gsi_state = g_malloc0(sizeof(*gsi_state));
-    if (kvm_irqchip_in_kernel()) {
-        kvm_pc_setup_irq_routing(pci_enabled);
-        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
-                                 GSI_NUM_PINS);
-    } else {
-        gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
-    }
-
-    /* create pci host bus */
-    q35_host = Q35_HOST_DEVICE(qdev_create(NULL, TYPE_Q35_HOST_DEVICE));
-
-    q35_host->mch.ram_memory = ram_memory;
-    q35_host->mch.pci_address_space = pci_memory;
-    q35_host->mch.system_memory = get_system_memory();
-    q35_host->mch.address_space_io = get_system_io();;
-    q35_host->mch.below_4g_mem_size = below_4g_mem_size;
-    q35_host->mch.above_4g_mem_size = above_4g_mem_size;
-    /* pci */
-    qdev_init_nofail(DEVICE(q35_host));
-    host_bus = q35_host->host.pci.bus;
-    /* create ISA bus */
-    lpc = pci_create_simple_multifunction(host_bus, PCI_DEVFN(ICH9_LPC_DEV,
-                                          ICH9_LPC_FUNC), true,
-                                          TYPE_ICH9_LPC_DEVICE);
-    ich9_lpc = ICH9_LPC_DEVICE(lpc);
-    ich9_lpc->pic = gsi;
-    ich9_lpc->ioapic = gsi_state->ioapic_irq;
-    pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc,
-                 ICH9_LPC_NB_PIRQS);
-    pci_bus_set_route_irq_fn(host_bus, ich9_route_intx_pin_to_irq);
-    isa_bus = ich9_lpc->isa_bus;
-
-    /*end early*/
-    isa_bus_irqs(isa_bus, gsi);
-
-    if (kvm_irqchip_in_kernel()) {
-        i8259 = kvm_i8259_init(isa_bus);
-    } else if (xen_enabled()) {
-        i8259 = xen_interrupt_controller_init();
-    } else {
-        cpu_irq = pc_allocate_cpu_irq();
-        i8259 = i8259_init(isa_bus, cpu_irq[0]);
-    }
-
-    for (i = 0; i < ISA_NUM_IRQS; i++) {
-        gsi_state->i8259_irq[i] = i8259[i];
-    }
-    if (pci_enabled) {
-        ioapic_init_gsi(gsi_state, NULL);
-    }
-
-    pc_register_ferr_irq(gsi[13]);
-
-    /* init basic PC hardware */
-    pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, false);
-
-    /* connect pm stuff to lpc */
-    cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
-    ich9_lpc_pm_init(lpc, *cmos_s3);
-
-    /* ahci and SATA device, for q35 1 ahci controller is built-in */
-    ahci = pci_create_simple_multifunction(host_bus,
-                                           PCI_DEVFN(ICH9_SATA1_DEV,
-                                                     ICH9_SATA1_FUNC),
-                                           true, "ich9-ahci");
-    idebus[0] = qdev_get_child_bus(&ahci->qdev, "ide.0");
-    idebus[1] = qdev_get_child_bus(&ahci->qdev, "ide.1");
-
-    if (usb_enabled(false)) {
-        /* Should we create 6 UHCI according to ich9 spec? */
-        ehci_create_ich9_with_companions(host_bus, 0x1d);
-    }
-
-    /* TODO: Populate SPD eeprom data.  */
-    smbus_eeprom_init(ich9_smb_init(host_bus,
-                                    PCI_DEVFN(ICH9_SMB_DEV, ICH9_SMB_FUNC),
-                                    0xb100),
-                      8, NULL, 0);
-
-    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
-                 floppy, idebus[0], idebus[1], rtc_state);
-
-    /* the rest devices to which pci devfn is automatically assigned */
-    pc_vga_init(isa_bus, host_bus);
-    audio_init(isa_bus, host_bus);
-    pc_nic_init(isa_bus, host_bus);
-    if (pci_enabled) {
-        pc_pci_device_init(host_bus);
-    }
-}
-
-static QEMUMachine pc_q35_machine_v1_5 = {
-    .name = "pc-q35-1.5",
-    .alias = "q35",
-    .desc = "Standard PC (Q35 + ICH9, 2009)",
-    .init = pc_q35_init,
-    .max_cpus = 255,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine pc_q35_machine_v1_4 = {
-    .name = "pc-q35-1.4",
-    .desc = "Standard PC (Q35 + ICH9, 2009)",
-    .init = pc_q35_init,
-    .max_cpus = 255,
-    .compat_props = (GlobalProperty[]) {
-        PC_COMPAT_1_4,
-        { /* end of list */ }
-    },
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void pc_q35_machine_init(void)
-{
-    qemu_register_machine(&pc_q35_machine_v1_5);
-    qemu_register_machine(&pc_q35_machine_v1_4);
-}
-
-machine_init(pc_q35_machine_init);
diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c
deleted file mode 100644
index cfc0220..0000000
--- a/hw/petalogix_ml605_mmu.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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 "hw/sysbus.h"
-#include "hw/hw.h"
-#include "net/net.h"
-#include "hw/flash.h"
-#include "sysemu/sysemu.h"
-#include "hw/devices.h"
-#include "hw/boards.h"
-#include "hw/xilinx.h"
-#include "sysemu/blockdev.h"
-#include "hw/serial.h"
-#include "exec/address-spaces.h"
-#include "hw/ssi.h"
-
-#include "hw/microblaze_boot.h"
-#include "hw/microblaze_pic_cpu.h"
-
-#include "hw/stream.h"
-
-#define LMB_BRAM_SIZE  (128 * 1024)
-#define FLASH_SIZE     (32 * 1024 * 1024)
-
-#define BINARY_DEVICE_TREE_FILE "petalogix-ml605.dtb"
-
-#define NUM_SPI_FLASHES 4
-
-#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 machine_cpu_reset(MicroBlazeCPU *cpu)
-{
-    CPUMBState *env = &cpu->env;
-
-    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;
-}
-
-static void
-petalogix_ml605_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    MemoryRegion *address_space_mem = get_system_memory();
-    DeviceState *dev, *dma, *eth0;
-    MicroBlazeCPU *cpu;
-    SysBusDevice *busdev;
-    CPUMBState *env;
-    DriveInfo *dinfo;
-    int i;
-    hwaddr ddr_base = MEMORY_BASEADDR;
-    MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1);
-    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
-    qemu_irq irq[32], *cpu_irq;
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-        cpu_model = "microblaze";
-    }
-    cpu = cpu_mb_init(cpu_model);
-    env = &cpu->env;
-
-    /* Attach emulated BRAM through the LMB.  */
-    memory_region_init_ram(phys_lmb_bram, "petalogix_ml605.lmb_bram",
-                           LMB_BRAM_SIZE);
-    vmstate_register_ram_global(phys_lmb_bram);
-    memory_region_add_subregion(address_space_mem, 0x00000000, phys_lmb_bram);
-
-    memory_region_init_ram(phys_ram, "petalogix_ml605.ram", ram_size);
-    vmstate_register_ram_global(phys_ram);
-    memory_region_add_subregion(address_space_mem, ddr_base, phys_ram);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    /* 5th parameter 2 means bank-width
-     * 10th paremeter 0 means little-endian */
-    pflash_cfi01_register(FLASH_BASEADDR,
-                          NULL, "petalogix_ml605.flash", FLASH_SIZE,
-                          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_mm_init(address_space_mem, UART16550_BASEADDR + 0x1000, 2,
-                   irq[5], 115200, serial_hds[0], DEVICE_LITTLE_ENDIAN);
-
-    /* 2 timers at irq 2 @ 100 Mhz.  */
-    xilinx_timer_create(TIMER_BASEADDR, irq[2], 0, 100 * 1000000);
-
-    /* axi ethernet and dma initialization. */
-    qemu_check_nic_model(&nd_table[0], "xlnx.axi-ethernet");
-    eth0 = qdev_create(NULL, "xlnx.axi-ethernet");
-    dma = qdev_create(NULL, "xlnx.axi-dma");
-
-    /* FIXME: attach to the sysbus instead */
-    object_property_add_child(container_get(qdev_get_machine(), "/unattached"),
-                                  "xilinx-dma", OBJECT(dma), NULL);
-
-    xilinx_axiethernet_init(eth0, &nd_table[0], STREAM_SLAVE(dma),
-                                   0x82780000, irq[3], 0x1000, 0x1000);
-
-    xilinx_axidma_init(dma, STREAM_SLAVE(eth0), 0x84600000, irq[1], irq[0],
-                       100 * 1000000);
-
-    {
-        SSIBus *spi;
-
-        dev = qdev_create(NULL, "xlnx.xps-spi");
-        qdev_prop_set_uint8(dev, "num-ss-bits", NUM_SPI_FLASHES);
-        qdev_init_nofail(dev);
-        busdev = SYS_BUS_DEVICE(dev);
-        sysbus_mmio_map(busdev, 0, 0x40a00000);
-        sysbus_connect_irq(busdev, 0, irq[4]);
-
-        spi = (SSIBus *)qdev_get_child_bus(dev, "spi");
-
-        for (i = 0; i < NUM_SPI_FLASHES; i++) {
-            qemu_irq cs_line;
-
-            dev = ssi_create_slave_no_init(spi, "n25q128");
-            qdev_init_nofail(dev);
-            cs_line = qdev_get_gpio_in(dev, 0);
-            sysbus_connect_irq(busdev, i+1, cs_line);
-        }
-    }
-
-    microblaze_load_kernel(cpu, ddr_base, ram_size, BINARY_DEVICE_TREE_FILE,
-                                                            machine_cpu_reset);
-
-}
-
-static QEMUMachine petalogix_ml605_machine = {
-    .name = "petalogix-ml605",
-    .desc = "PetaLogix linux refdesign for xilinx ml605 little endian",
-    .init = petalogix_ml605_init,
-    .is_default = 0,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void petalogix_ml605_machine_init(void)
-{
-    qemu_register_machine(&petalogix_ml605_machine);
-}
-
-machine_init(petalogix_ml605_machine_init);
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
deleted file mode 100644
index 2498362..0000000
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Model of Petalogix linux reference design targeting Xilinx Spartan 3ADSP-1800
- * boards.
- *
- * 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 "hw/sysbus.h"
-#include "hw/hw.h"
-#include "net/net.h"
-#include "hw/flash.h"
-#include "sysemu/sysemu.h"
-#include "hw/devices.h"
-#include "hw/boards.h"
-#include "hw/xilinx.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-#include "hw/microblaze_boot.h"
-#include "hw/microblaze_pic_cpu.h"
-
-#define LMB_BRAM_SIZE  (128 * 1024)
-#define FLASH_SIZE     (16 * 1024 * 1024)
-
-#define BINARY_DEVICE_TREE_FILE "petalogix-s3adsp1800.dtb"
-
-#define MEMORY_BASEADDR 0x90000000
-#define FLASH_BASEADDR 0xa0000000
-#define INTC_BASEADDR 0x81800000
-#define TIMER_BASEADDR 0x83c00000
-#define UARTLITE_BASEADDR 0x84000000
-#define ETHLITE_BASEADDR 0x81000000
-
-static void machine_cpu_reset(MicroBlazeCPU *cpu)
-{
-    CPUMBState *env = &cpu->env;
-
-    env->pvr.regs[10] = 0x0c000000; /* spartan 3a dsp family.  */
-}
-
-static void
-petalogix_s3adsp1800_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    DeviceState *dev;
-    MicroBlazeCPU *cpu;
-    CPUMBState *env;
-    DriveInfo *dinfo;
-    int i;
-    hwaddr ddr_base = MEMORY_BASEADDR;
-    MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1);
-    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
-    qemu_irq irq[32], *cpu_irq;
-    MemoryRegion *sysmem = get_system_memory();
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-        cpu_model = "microblaze";
-    }
-    cpu = cpu_mb_init(cpu_model);
-    env = &cpu->env;
-
-    /* Attach emulated BRAM through the LMB.  */
-    memory_region_init_ram(phys_lmb_bram,
-                           "petalogix_s3adsp1800.lmb_bram", LMB_BRAM_SIZE);
-    vmstate_register_ram_global(phys_lmb_bram);
-    memory_region_add_subregion(sysmem, 0x00000000, phys_lmb_bram);
-
-    memory_region_init_ram(phys_ram, "petalogix_s3adsp1800.ram", ram_size);
-    vmstate_register_ram_global(phys_ram);
-    memory_region_add_subregion(sysmem, ddr_base, phys_ram);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi01_register(FLASH_BASEADDR,
-                          NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE,
-                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
-                          FLASH_SIZE >> 16,
-                          1, 0x89, 0x18, 0x0000, 0x0, 1);
-
-    cpu_irq = microblaze_pic_init_cpu(env);
-    dev = xilinx_intc_create(INTC_BASEADDR, cpu_irq[0], 2);
-    for (i = 0; i < 32; i++) {
-        irq[i] = qdev_get_gpio_in(dev, i);
-    }
-
-    sysbus_create_simple("xlnx.xps-uartlite", UARTLITE_BASEADDR, irq[3]);
-    /* 2 timers at irq 2 @ 62 Mhz.  */
-    xilinx_timer_create(TIMER_BASEADDR, irq[0], 0, 62 * 1000000);
-    xilinx_ethlite_create(&nd_table[0], ETHLITE_BASEADDR, irq[1], 0, 0);
-
-    microblaze_load_kernel(cpu, ddr_base, ram_size,
-                    BINARY_DEVICE_TREE_FILE, machine_cpu_reset);
-}
-
-static QEMUMachine petalogix_s3adsp1800_machine = {
-    .name = "petalogix-s3adsp1800",
-    .desc = "PetaLogix linux refdesign for xilinx Spartan 3ADSP1800",
-    .init = petalogix_s3adsp1800_init,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void petalogix_s3adsp1800_machine_init(void)
-{
-    qemu_register_machine(&petalogix_s3adsp1800_machine);
-}
-
-machine_init(petalogix_s3adsp1800_machine_init);
diff --git a/hw/ppc.c b/hw/ppc.c
deleted file mode 100644
index c9437fc..0000000
--- a/hw/ppc.c
+++ /dev/null
@@ -1,1356 +0,0 @@
-/*
- * QEMU generic PowerPC hardware System Emulator
- *
- * Copyright (c) 2003-2007 Jocelyn Mayer
- *
- * 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/hw.h"
-#include "hw/ppc.h"
-#include "qemu/timer.h"
-#include "sysemu/sysemu.h"
-#include "hw/nvram.h"
-#include "qemu/log.h"
-#include "hw/loader.h"
-#include "sysemu/kvm.h"
-#include "kvm_ppc.h"
-
-//#define PPC_DEBUG_IRQ
-//#define PPC_DEBUG_TB
-
-#ifdef PPC_DEBUG_IRQ
-#  define LOG_IRQ(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
-#else
-#  define LOG_IRQ(...) do { } while (0)
-#endif
-
-
-#ifdef PPC_DEBUG_TB
-#  define LOG_TB(...) qemu_log(__VA_ARGS__)
-#else
-#  define LOG_TB(...) do { } while (0)
-#endif
-
-static void cpu_ppc_tb_stop (CPUPPCState *env);
-static void cpu_ppc_tb_start (CPUPPCState *env);
-
-void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
-{
-    CPUPPCState *env = &cpu->env;
-    unsigned int old_pending = env->pending_interrupts;
-
-    if (level) {
-        env->pending_interrupts |= 1 << n_IRQ;
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    } else {
-        env->pending_interrupts &= ~(1 << n_IRQ);
-        if (env->pending_interrupts == 0)
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-
-    if (old_pending != env->pending_interrupts) {
-#ifdef CONFIG_KVM
-        kvmppc_set_interrupt(cpu, n_IRQ, level);
-#endif
-    }
-
-    LOG_IRQ("%s: %p n_IRQ %d level %d => pending %08" PRIx32
-                "req %08x\n", __func__, env, n_IRQ, level,
-                env->pending_interrupts, env->interrupt_request);
-}
-
-/* PowerPC 6xx / 7xx internal IRQ controller */
-static void ppc6xx_set_irq(void *opaque, int pin, int level)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-    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;
-    /* Don't generate spurious events */
-    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
-        switch (pin) {
-        case PPC6xx_INPUT_TBEN:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: %s the time base\n",
-                        __func__, level ? "start" : "stop");
-            if (level) {
-                cpu_ppc_tb_start(env);
-            } else {
-                cpu_ppc_tb_stop(env);
-            }
-        case PPC6xx_INPUT_INT:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the external IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
-            break;
-        case PPC6xx_INPUT_SMI:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the SMI IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_SMI, level);
-            break;
-        case PPC6xx_INPUT_MCP:
-            /* Negative edge sensitive */
-            /* XXX: TODO: actual reaction may depends on HID0 status
-             *            603/604/740/750: check HID0[EMCP]
-             */
-            if (cur_level == 1 && level == 0) {
-                LOG_IRQ("%s: raise machine check state\n",
-                            __func__);
-                ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1);
-            }
-            break;
-        case PPC6xx_INPUT_CKSTP_IN:
-            /* Level sensitive - active low */
-            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
-            /* XXX: Note that the only way to restart the CPU is to reset it */
-            if (level) {
-                LOG_IRQ("%s: stop the CPU\n", __func__);
-                env->halted = 1;
-            }
-            break;
-        case PPC6xx_INPUT_HRESET:
-            /* Level sensitive - active low */
-            if (level) {
-                LOG_IRQ("%s: reset the CPU\n", __func__);
-                cpu_interrupt(env, CPU_INTERRUPT_RESET);
-            }
-            break;
-        case PPC6xx_INPUT_SRESET:
-            LOG_IRQ("%s: set the RESET IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_RESET, 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 ppc6xx_irq_init(CPUPPCState *env)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, cpu,
-                                                  PPC6xx_INPUT_NB);
-}
-
-#if defined(TARGET_PPC64)
-/* PowerPC 970 internal IRQ controller */
-static void ppc970_set_irq(void *opaque, int pin, int level)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-    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;
-    /* Don't generate spurious events */
-    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
-        switch (pin) {
-        case PPC970_INPUT_INT:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the external IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
-            break;
-        case PPC970_INPUT_THINT:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the SMI IRQ state to %d\n", __func__,
-                        level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_THERM, level);
-            break;
-        case PPC970_INPUT_MCP:
-            /* Negative edge sensitive */
-            /* XXX: TODO: actual reaction may depends on HID0 status
-             *            603/604/740/750: check HID0[EMCP]
-             */
-            if (cur_level == 1 && level == 0) {
-                LOG_IRQ("%s: raise machine check state\n",
-                            __func__);
-                ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1);
-            }
-            break;
-        case PPC970_INPUT_CKSTP:
-            /* Level sensitive - active low */
-            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
-            if (level) {
-                LOG_IRQ("%s: stop the CPU\n", __func__);
-                env->halted = 1;
-            } else {
-                LOG_IRQ("%s: restart the CPU\n", __func__);
-                env->halted = 0;
-                qemu_cpu_kick(CPU(cpu));
-            }
-            break;
-        case PPC970_INPUT_HRESET:
-            /* Level sensitive - active low */
-            if (level) {
-                cpu_interrupt(env, CPU_INTERRUPT_RESET);
-            }
-            break;
-        case PPC970_INPUT_SRESET:
-            LOG_IRQ("%s: set the RESET IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level);
-            break;
-        case PPC970_INPUT_TBEN:
-            LOG_IRQ("%s: set the TBEN state to %d\n", __func__,
-                        level);
-            /* XXX: TODO */
-            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 ppc970_irq_init(CPUPPCState *env)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, cpu,
-                                                  PPC970_INPUT_NB);
-}
-
-/* POWER7 internal IRQ controller */
-static void power7_set_irq(void *opaque, int pin, int level)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-
-    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
-                env, pin, level);
-
-    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(cpu, 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(CPUPPCState *env)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, cpu,
-                                                  POWER7_INPUT_NB);
-}
-#endif /* defined(TARGET_PPC64) */
-
-/* PowerPC 40x internal IRQ controller */
-static void ppc40x_set_irq(void *opaque, int pin, int level)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-    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;
-    /* Don't generate spurious events */
-    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
-        switch (pin) {
-        case PPC40x_INPUT_RESET_SYS:
-            if (level) {
-                LOG_IRQ("%s: reset the PowerPC system\n",
-                            __func__);
-                ppc40x_system_reset(cpu);
-            }
-            break;
-        case PPC40x_INPUT_RESET_CHIP:
-            if (level) {
-                LOG_IRQ("%s: reset the PowerPC chip\n", __func__);
-                ppc40x_chip_reset(cpu);
-            }
-            break;
-        case PPC40x_INPUT_RESET_CORE:
-            /* XXX: TODO: update DBSR[MRR] */
-            if (level) {
-                LOG_IRQ("%s: reset the PowerPC core\n", __func__);
-                ppc40x_core_reset(cpu);
-            }
-            break;
-        case PPC40x_INPUT_CINT:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the critical IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level);
-            break;
-        case PPC40x_INPUT_INT:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the external IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
-            break;
-        case PPC40x_INPUT_HALT:
-            /* Level sensitive - active low */
-            if (level) {
-                LOG_IRQ("%s: stop the CPU\n", __func__);
-                env->halted = 1;
-            } else {
-                LOG_IRQ("%s: restart the CPU\n", __func__);
-                env->halted = 0;
-                qemu_cpu_kick(CPU(cpu));
-            }
-            break;
-        case PPC40x_INPUT_DEBUG:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the debug pin state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, 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 ppc40x_irq_init(CPUPPCState *env)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
-                                                  cpu, PPC40x_INPUT_NB);
-}
-
-/* PowerPC E500 internal IRQ controller */
-static void ppce500_set_irq(void *opaque, int pin, int level)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-    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;
-    /* Don't generate spurious events */
-    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
-        switch (pin) {
-        case PPCE500_INPUT_MCK:
-            if (level) {
-                LOG_IRQ("%s: reset the PowerPC system\n",
-                            __func__);
-                qemu_system_reset_request();
-            }
-            break;
-        case PPCE500_INPUT_RESET_CORE:
-            if (level) {
-                LOG_IRQ("%s: reset the PowerPC core\n", __func__);
-                ppc_set_irq(cpu, PPC_INTERRUPT_MCK, level);
-            }
-            break;
-        case PPCE500_INPUT_CINT:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the critical IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level);
-            break;
-        case PPCE500_INPUT_INT:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the core IRQ state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
-            break;
-        case PPCE500_INPUT_DEBUG:
-            /* Level sensitive - active high */
-            LOG_IRQ("%s: set the debug pin state to %d\n",
-                        __func__, level);
-            ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, 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 ppce500_irq_init(CPUPPCState *env)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
-                                                  cpu, PPCE500_INPUT_NB);
-}
-
-/* Enable or Disable the E500 EPR capability */
-void ppce500_set_mpic_proxy(bool enabled)
-{
-    CPUPPCState *env;
-
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        PowerPCCPU *cpu = ppc_env_get_cpu(env);
-        CPUState *cs = CPU(cpu);
-
-        env->mpic_proxy = enabled;
-        if (kvm_enabled()) {
-            kvmppc_set_mpic_proxy(POWERPC_CPU(cs), enabled);
-        }
-    }
-}
-
-/*****************************************************************************/
-/* PowerPC time base and decrementer emulation */
-
-uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset)
-{
-    /* TB time in tb periods */
-    return muldiv64(vmclk, tb_env->tb_freq, get_ticks_per_sec()) + tb_offset;
-}
-
-uint64_t cpu_ppc_load_tbl (CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t tb;
-
-    if (kvm_enabled()) {
-        return env->spr[SPR_TBL];
-    }
-
-    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;
-}
-
-static inline uint32_t _cpu_ppc_load_tbu(CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t tb;
-
-    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;
-}
-
-uint32_t cpu_ppc_load_tbu (CPUPPCState *env)
-{
-    if (kvm_enabled()) {
-        return env->spr[SPR_TBU];
-    }
-
-    return _cpu_ppc_load_tbu(env);
-}
-
-static inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, uint64_t vmclk,
-                                    int64_t *tb_offsetp, uint64_t value)
-{
-    *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, get_ticks_per_sec());
-    LOG_TB("%s: tb %016" PRIx64 " offset %08" PRIx64 "\n",
-                __func__, value, *tb_offsetp);
-}
-
-void cpu_ppc_store_tbl (CPUPPCState *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_ns(vm_clock), tb_env->tb_offset);
-    tb &= 0xFFFFFFFF00000000ULL;
-    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
-                     &tb_env->tb_offset, tb | (uint64_t)value);
-}
-
-static inline void _cpu_ppc_store_tbu(CPUPPCState *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_ns(vm_clock), tb_env->tb_offset);
-    tb &= 0x00000000FFFFFFFFULL;
-    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
-                     &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
-}
-
-void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value)
-{
-    _cpu_ppc_store_tbu(env, value);
-}
-
-uint64_t cpu_ppc_load_atbl (CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t tb;
-
-    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;
-}
-
-uint32_t cpu_ppc_load_atbu (CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t tb;
-
-    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;
-}
-
-void cpu_ppc_store_atbl (CPUPPCState *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_ns(vm_clock), tb_env->atb_offset);
-    tb &= 0xFFFFFFFF00000000ULL;
-    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
-                     &tb_env->atb_offset, tb | (uint64_t)value);
-}
-
-void cpu_ppc_store_atbu (CPUPPCState *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_ns(vm_clock), tb_env->atb_offset);
-    tb &= 0x00000000FFFFFFFFULL;
-    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
-                     &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
-}
-
-static void cpu_ppc_tb_stop (CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t tb, atb, vmclk;
-
-    /* If the time base is already frozen, do nothing */
-    if (tb_env->tb_freq != 0) {
-        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 */
-        atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset);
-        /* Store the time base value (ie compute the current offset) */
-        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
-        /* Store the alternate time base value (compute the current offset) */
-        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
-        /* Set the time base frequency to zero */
-        tb_env->tb_freq = 0;
-        /* Now, the time bases are frozen to tb_offset / atb_offset value */
-    }
-}
-
-static void cpu_ppc_tb_start (CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t tb, atb, vmclk;
-
-    /* If the time base is not frozen, do nothing */
-    if (tb_env->tb_freq == 0) {
-        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 */
-        atb = tb_env->atb_offset;
-        /* Restore the tb frequency from the decrementer frequency */
-        tb_env->tb_freq = tb_env->decr_freq;
-        /* Store the time base value */
-        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
-        /* Store the alternate time base value */
-        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
-    }
-}
-
-static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint32_t decr;
-    int64_t diff;
-
-    diff = next - qemu_get_clock_ns(vm_clock);
-    if (diff >= 0) {
-        decr = muldiv64(diff, tb_env->decr_freq, get_ticks_per_sec());
-    } else if (tb_env->flags & PPC_TIMER_BOOKE) {
-        decr = 0;
-    }  else {
-        decr = -muldiv64(-diff, tb_env->decr_freq, get_ticks_per_sec());
-    }
-    LOG_TB("%s: %08" PRIx32 "\n", __func__, decr);
-
-    return decr;
-}
-
-uint32_t cpu_ppc_load_decr (CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-
-    if (kvm_enabled()) {
-        return env->spr[SPR_DECR];
-    }
-
-    return _cpu_ppc_load_decr(env, tb_env->decr_next);
-}
-
-uint32_t cpu_ppc_load_hdecr (CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-
-    return _cpu_ppc_load_decr(env, tb_env->hdecr_next);
-}
-
-uint64_t cpu_ppc_load_purr (CPUPPCState *env)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t diff;
-
-    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());
-}
-
-/* When decrementer expires,
- * all we need to do is generate or queue a CPU exception
- */
-static inline void cpu_ppc_decr_excp(PowerPCCPU *cpu)
-{
-    /* Raise it */
-    LOG_TB("raise decrementer exception\n");
-    ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 1);
-}
-
-static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
-{
-    /* Raise it */
-    LOG_TB("raise decrementer exception\n");
-    ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
-}
-
-static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
-                                 struct QEMUTimer *timer,
-                                 void (*raise_excp)(PowerPCCPU *),
-                                 uint32_t decr, uint32_t value,
-                                 int is_excp)
-{
-    CPUPPCState *env = &cpu->env;
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t now, next;
-
-    LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__,
-                decr, value);
-
-    if (kvm_enabled()) {
-        /* KVM handles decrementer exceptions, we don't need our own timer */
-        return;
-    }
-
-    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;
-    }
-    if (next == now) {
-        next++;
-    }
-    *nextp = next;
-    /* Adjust timer */
-    qemu_mod_timer(timer, next);
-
-    /* If we set a negative value and the decrementer was positive, raise an
-     * exception.
-     */
-    if ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED)
-        && (value & 0x80000000)
-        && !(decr & 0x80000000)) {
-        (*raise_excp)(cpu);
-    }
-}
-
-static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, uint32_t decr,
-                                       uint32_t value, int is_excp)
-{
-    ppc_tb_t *tb_env = cpu->env.tb_env;
-
-    __cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer,
-                         &cpu_ppc_decr_excp, decr, value, is_excp);
-}
-
-void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    _cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value, 0);
-}
-
-static void cpu_ppc_decr_cb(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-
-    _cpu_ppc_store_decr(cpu, 0x00000000, 0xFFFFFFFF, 1);
-}
-
-static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, uint32_t hdecr,
-                                        uint32_t value, int is_excp)
-{
-    ppc_tb_t *tb_env = cpu->env.tb_env;
-
-    if (tb_env->hdecr_timer != NULL) {
-        __cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer,
-                             &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
-    }
-}
-
-void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    _cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value, 0);
-}
-
-static void cpu_ppc_hdecr_cb(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-
-    _cpu_ppc_store_hdecr(cpu, 0x00000000, 0xFFFFFFFF, 1);
-}
-
-static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value)
-{
-    ppc_tb_t *tb_env = cpu->env.tb_env;
-
-    tb_env->purr_load = value;
-    tb_env->purr_start = qemu_get_clock_ns(vm_clock);
-}
-
-static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
-{
-    CPUPPCState *env = opaque;
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-    ppc_tb_t *tb_env = env->tb_env;
-
-    tb_env->tb_freq = freq;
-    tb_env->decr_freq = freq;
-    /* There is a bug in Linux 2.4 kernels:
-     * if a decrementer exception is pending when it enables msr_ee at startup,
-     * it's not ready to handle it...
-     */
-    _cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
-    _cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
-    cpu_ppc_store_purr(cpu, 0x0000000000000000ULL);
-}
-
-/* Set up (once) timebase frequency (in Hz) */
-clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-    ppc_tb_t *tb_env;
-
-    tb_env = g_malloc0(sizeof(ppc_tb_t));
-    env->tb_env = tb_env;
-    tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
-    /* Create new timer */
-    tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_decr_cb, cpu);
-    if (0) {
-        /* XXX: find a suitable condition to enable the hypervisor decrementer
-         */
-        tb_env->hdecr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_hdecr_cb,
-                                                cpu);
-    } else {
-        tb_env->hdecr_timer = NULL;
-    }
-    cpu_ppc_set_tb_clk(env, freq);
-
-    return &cpu_ppc_set_tb_clk;
-}
-
-/* Specific helpers for POWER & PowerPC 601 RTC */
-#if 0
-static clk_setup_cb cpu_ppc601_rtc_init (CPUPPCState *env)
-{
-    return cpu_ppc_tb_init(env, 7812500);
-}
-#endif
-
-void cpu_ppc601_store_rtcu (CPUPPCState *env, uint32_t value)
-{
-    _cpu_ppc_store_tbu(env, value);
-}
-
-uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env)
-{
-    return _cpu_ppc_load_tbu(env);
-}
-
-void cpu_ppc601_store_rtcl (CPUPPCState *env, uint32_t value)
-{
-    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
-}
-
-uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env)
-{
-    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
-}
-
-/*****************************************************************************/
-/* PowerPC 40x timers */
-
-/* PIT, FIT & WDT */
-typedef struct ppc40x_timer_t ppc40x_timer_t;
-struct ppc40x_timer_t {
-    uint64_t pit_reload;  /* PIT auto-reload value        */
-    uint64_t fit_next;    /* Tick for next FIT interrupt  */
-    struct QEMUTimer *fit_timer;
-    uint64_t wdt_next;    /* Tick for next WDT interrupt  */
-    struct QEMUTimer *wdt_timer;
-
-    /* 405 have the PIT, 440 have a DECR.  */
-    unsigned int decr_excp;
-};
-
-/* Fixed interval timer */
-static void cpu_4xx_fit_cb (void *opaque)
-{
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    ppc_tb_t *tb_env;
-    ppc40x_timer_t *ppc40x_timer;
-    uint64_t now, next;
-
-    env = opaque;
-    cpu = ppc_env_get_cpu(env);
-    tb_env = env->tb_env;
-    ppc40x_timer = tb_env->opaque;
-    now = qemu_get_clock_ns(vm_clock);
-    switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
-    case 0:
-        next = 1 << 9;
-        break;
-    case 1:
-        next = 1 << 13;
-        break;
-    case 2:
-        next = 1 << 17;
-        break;
-    case 3:
-        next = 1 << 21;
-        break;
-    default:
-        /* Cannot occur, but makes gcc happy */
-        return;
-    }
-    next = now + muldiv64(next, get_ticks_per_sec(), tb_env->tb_freq);
-    if (next == now)
-        next++;
-    qemu_mod_timer(ppc40x_timer->fit_timer, next);
-    env->spr[SPR_40x_TSR] |= 1 << 26;
-    if ((env->spr[SPR_40x_TCR] >> 23) & 0x1) {
-        ppc_set_irq(cpu, PPC_INTERRUPT_FIT, 1);
-    }
-    LOG_TB("%s: ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
-           (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
-           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
-}
-
-/* Programmable interval timer */
-static void start_stop_pit (CPUPPCState *env, ppc_tb_t *tb_env, int is_excp)
-{
-    ppc40x_timer_t *ppc40x_timer;
-    uint64_t now, next;
-
-    ppc40x_timer = tb_env->opaque;
-    if (ppc40x_timer->pit_reload <= 1 ||
-        !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
-        (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
-        /* Stop PIT */
-        LOG_TB("%s: stop PIT\n", __func__);
-        qemu_del_timer(tb_env->decr_timer);
-    } else {
-        LOG_TB("%s: start PIT %016" PRIx64 "\n",
-                    __func__, ppc40x_timer->pit_reload);
-        now = qemu_get_clock_ns(vm_clock);
-        next = now + muldiv64(ppc40x_timer->pit_reload,
-                              get_ticks_per_sec(), tb_env->decr_freq);
-        if (is_excp)
-            next += tb_env->decr_next - now;
-        if (next == now)
-            next++;
-        qemu_mod_timer(tb_env->decr_timer, next);
-        tb_env->decr_next = next;
-    }
-}
-
-static void cpu_4xx_pit_cb (void *opaque)
-{
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    ppc_tb_t *tb_env;
-    ppc40x_timer_t *ppc40x_timer;
-
-    env = opaque;
-    cpu = ppc_env_get_cpu(env);
-    tb_env = env->tb_env;
-    ppc40x_timer = tb_env->opaque;
-    env->spr[SPR_40x_TSR] |= 1 << 27;
-    if ((env->spr[SPR_40x_TCR] >> 26) & 0x1) {
-        ppc_set_irq(cpu, ppc40x_timer->decr_excp, 1);
-    }
-    start_stop_pit(env, tb_env, 1);
-    LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " "
-           "%016" PRIx64 "\n", __func__,
-           (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
-           (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
-           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
-           ppc40x_timer->pit_reload);
-}
-
-/* Watchdog timer */
-static void cpu_4xx_wdt_cb (void *opaque)
-{
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    ppc_tb_t *tb_env;
-    ppc40x_timer_t *ppc40x_timer;
-    uint64_t now, next;
-
-    env = opaque;
-    cpu = ppc_env_get_cpu(env);
-    tb_env = env->tb_env;
-    ppc40x_timer = tb_env->opaque;
-    now = qemu_get_clock_ns(vm_clock);
-    switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
-    case 0:
-        next = 1 << 17;
-        break;
-    case 1:
-        next = 1 << 21;
-        break;
-    case 2:
-        next = 1 << 25;
-        break;
-    case 3:
-        next = 1 << 29;
-        break;
-    default:
-        /* Cannot occur, but makes gcc happy */
-        return;
-    }
-    next = now + muldiv64(next, get_ticks_per_sec(), tb_env->decr_freq);
-    if (next == now)
-        next++;
-    LOG_TB("%s: TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
-           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
-    switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
-    case 0x0:
-    case 0x1:
-        qemu_mod_timer(ppc40x_timer->wdt_timer, next);
-        ppc40x_timer->wdt_next = next;
-        env->spr[SPR_40x_TSR] |= 1 << 31;
-        break;
-    case 0x2:
-        qemu_mod_timer(ppc40x_timer->wdt_timer, next);
-        ppc40x_timer->wdt_next = next;
-        env->spr[SPR_40x_TSR] |= 1 << 30;
-        if ((env->spr[SPR_40x_TCR] >> 27) & 0x1) {
-            ppc_set_irq(cpu, PPC_INTERRUPT_WDT, 1);
-        }
-        break;
-    case 0x3:
-        env->spr[SPR_40x_TSR] &= ~0x30000000;
-        env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
-        switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
-        case 0x0:
-            /* No reset */
-            break;
-        case 0x1: /* Core reset */
-            ppc40x_core_reset(cpu);
-            break;
-        case 0x2: /* Chip reset */
-            ppc40x_chip_reset(cpu);
-            break;
-        case 0x3: /* System reset */
-            ppc40x_system_reset(cpu);
-            break;
-        }
-    }
-}
-
-void store_40x_pit (CPUPPCState *env, target_ulong val)
-{
-    ppc_tb_t *tb_env;
-    ppc40x_timer_t *ppc40x_timer;
-
-    tb_env = env->tb_env;
-    ppc40x_timer = tb_env->opaque;
-    LOG_TB("%s val" TARGET_FMT_lx "\n", __func__, val);
-    ppc40x_timer->pit_reload = val;
-    start_stop_pit(env, tb_env, 0);
-}
-
-target_ulong load_40x_pit (CPUPPCState *env)
-{
-    return cpu_ppc_load_decr(env);
-}
-
-static void ppc_40x_set_tb_clk (void *opaque, uint32_t freq)
-{
-    CPUPPCState *env = opaque;
-    ppc_tb_t *tb_env = env->tb_env;
-
-    LOG_TB("%s set new frequency to %" PRIu32 "\n", __func__,
-                freq);
-    tb_env->tb_freq = freq;
-    tb_env->decr_freq = freq;
-    /* XXX: we should also update all timers */
-}
-
-clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq,
-                                  unsigned int decr_excp)
-{
-    ppc_tb_t *tb_env;
-    ppc40x_timer_t *ppc40x_timer;
-
-    tb_env = g_malloc0(sizeof(ppc_tb_t));
-    env->tb_env = tb_env;
-    tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
-    ppc40x_timer = g_malloc0(sizeof(ppc40x_timer_t));
-    tb_env->tb_freq = freq;
-    tb_env->decr_freq = freq;
-    tb_env->opaque = ppc40x_timer;
-    LOG_TB("%s freq %" PRIu32 "\n", __func__, freq);
-    if (ppc40x_timer != NULL) {
-        /* We use decr timer for PIT */
-        tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_4xx_pit_cb, env);
-        ppc40x_timer->fit_timer =
-            qemu_new_timer_ns(vm_clock, &cpu_4xx_fit_cb, env);
-        ppc40x_timer->wdt_timer =
-            qemu_new_timer_ns(vm_clock, &cpu_4xx_wdt_cb, env);
-        ppc40x_timer->decr_excp = decr_excp;
-    }
-
-    return &ppc_40x_set_tb_clk;
-}
-
-/*****************************************************************************/
-/* Embedded PowerPC Device Control Registers */
-typedef struct ppc_dcrn_t ppc_dcrn_t;
-struct ppc_dcrn_t {
-    dcr_read_cb dcr_read;
-    dcr_write_cb dcr_write;
-    void *opaque;
-};
-
-/* XXX: on 460, DCR addresses are 32 bits wide,
- *      using DCRIPR to get the 22 upper bits of the DCR address
- */
-#define DCRN_NB 1024
-struct ppc_dcr_t {
-    ppc_dcrn_t dcrn[DCRN_NB];
-    int (*read_error)(int dcrn);
-    int (*write_error)(int dcrn);
-};
-
-int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
-{
-    ppc_dcrn_t *dcr;
-
-    if (dcrn < 0 || dcrn >= DCRN_NB)
-        goto error;
-    dcr = &dcr_env->dcrn[dcrn];
-    if (dcr->dcr_read == NULL)
-        goto error;
-    *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
-
-    return 0;
-
- error:
-    if (dcr_env->read_error != NULL)
-        return (*dcr_env->read_error)(dcrn);
-
-    return -1;
-}
-
-int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
-{
-    ppc_dcrn_t *dcr;
-
-    if (dcrn < 0 || dcrn >= DCRN_NB)
-        goto error;
-    dcr = &dcr_env->dcrn[dcrn];
-    if (dcr->dcr_write == NULL)
-        goto error;
-    (*dcr->dcr_write)(dcr->opaque, dcrn, val);
-
-    return 0;
-
- error:
-    if (dcr_env->write_error != NULL)
-        return (*dcr_env->write_error)(dcrn);
-
-    return -1;
-}
-
-int ppc_dcr_register (CPUPPCState *env, int dcrn, void *opaque,
-                      dcr_read_cb dcr_read, dcr_write_cb dcr_write)
-{
-    ppc_dcr_t *dcr_env;
-    ppc_dcrn_t *dcr;
-
-    dcr_env = env->dcr_env;
-    if (dcr_env == NULL)
-        return -1;
-    if (dcrn < 0 || dcrn >= DCRN_NB)
-        return -1;
-    dcr = &dcr_env->dcrn[dcrn];
-    if (dcr->opaque != NULL ||
-        dcr->dcr_read != NULL ||
-        dcr->dcr_write != NULL)
-        return -1;
-    dcr->opaque = opaque;
-    dcr->dcr_read = dcr_read;
-    dcr->dcr_write = dcr_write;
-
-    return 0;
-}
-
-int ppc_dcr_init (CPUPPCState *env, int (*read_error)(int dcrn),
-                  int (*write_error)(int dcrn))
-{
-    ppc_dcr_t *dcr_env;
-
-    dcr_env = g_malloc0(sizeof(ppc_dcr_t));
-    dcr_env->read_error = read_error;
-    dcr_env->write_error = write_error;
-    env->dcr_env = dcr_env;
-
-    return 0;
-}
-
-/*****************************************************************************/
-/* Debug port */
-void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
-{
-    addr &= 0xF;
-    switch (addr) {
-    case 0:
-        printf("%c", val);
-        break;
-    case 1:
-        printf("\n");
-        fflush(stdout);
-        break;
-    case 2:
-        printf("Set loglevel to %04" PRIx32 "\n", val);
-        qemu_set_log(val | 0x100);
-        break;
-    }
-}
-
-/*****************************************************************************/
-/* NVRAM helpers */
-static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
-{
-    return (*nvram->read_fn)(nvram->opaque, addr);
-}
-
-static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
-{
-    (*nvram->write_fn)(nvram->opaque, addr, val);
-}
-
-static void NVRAM_set_byte(nvram_t *nvram, uint32_t addr, uint8_t value)
-{
-    nvram_write(nvram, addr, value);
-}
-
-static uint8_t NVRAM_get_byte(nvram_t *nvram, uint32_t addr)
-{
-    return nvram_read(nvram, addr);
-}
-
-static void NVRAM_set_word(nvram_t *nvram, uint32_t addr, uint16_t value)
-{
-    nvram_write(nvram, addr, value >> 8);
-    nvram_write(nvram, addr + 1, value & 0xFF);
-}
-
-static uint16_t NVRAM_get_word(nvram_t *nvram, uint32_t addr)
-{
-    uint16_t tmp;
-
-    tmp = nvram_read(nvram, addr) << 8;
-    tmp |= nvram_read(nvram, addr + 1);
-
-    return tmp;
-}
-
-static void NVRAM_set_lword(nvram_t *nvram, uint32_t addr, uint32_t value)
-{
-    nvram_write(nvram, addr, value >> 24);
-    nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
-    nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
-    nvram_write(nvram, addr + 3, value & 0xFF);
-}
-
-uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
-{
-    uint32_t tmp;
-
-    tmp = nvram_read(nvram, addr) << 24;
-    tmp |= nvram_read(nvram, addr + 1) << 16;
-    tmp |= nvram_read(nvram, addr + 2) << 8;
-    tmp |= nvram_read(nvram, addr + 3);
-
-    return tmp;
-}
-
-static void NVRAM_set_string(nvram_t *nvram, uint32_t addr, const char *str,
-                             uint32_t max)
-{
-    int i;
-
-    for (i = 0; i < max && str[i] != '\0'; i++) {
-        nvram_write(nvram, addr + i, str[i]);
-    }
-    nvram_write(nvram, addr + i, str[i]);
-    nvram_write(nvram, addr + max - 1, '\0');
-}
-
-int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
-{
-    int i;
-
-    memset(dst, 0, max);
-    for (i = 0; i < max; i++) {
-        dst[i] = NVRAM_get_byte(nvram, addr + i);
-        if (dst[i] == '\0')
-            break;
-    }
-
-    return i;
-}
-
-static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
-{
-    uint16_t tmp;
-    uint16_t pd, pd1, pd2;
-
-    tmp = prev >> 8;
-    pd = prev ^ value;
-    pd1 = pd & 0x000F;
-    pd2 = ((pd >> 4) & 0x000F) ^ pd1;
-    tmp ^= (pd1 << 3) | (pd1 << 8);
-    tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
-
-    return tmp;
-}
-
-static uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
-{
-    uint32_t i;
-    uint16_t crc = 0xFFFF;
-    int odd;
-
-    odd = count & 1;
-    count &= ~1;
-    for (i = 0; i != count; i++) {
-        crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
-    }
-    if (odd) {
-        crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
-    }
-
-    return crc;
-}
-
-#define CMDLINE_ADDR 0x017ff000
-
-int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
-                          const char *arch,
-                          uint32_t RAM_size, int boot_device,
-                          uint32_t kernel_image, uint32_t kernel_size,
-                          const char *cmdline,
-                          uint32_t initrd_image, uint32_t initrd_size,
-                          uint32_t NVRAM_image,
-                          int width, int height, int depth)
-{
-    uint16_t crc;
-
-    /* Set parameters for Open Hack'Ware BIOS */
-    NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
-    NVRAM_set_lword(nvram,  0x10, 0x00000002); /* structure v2 */
-    NVRAM_set_word(nvram,   0x14, NVRAM_size);
-    NVRAM_set_string(nvram, 0x20, arch, 16);
-    NVRAM_set_lword(nvram,  0x30, RAM_size);
-    NVRAM_set_byte(nvram,   0x34, boot_device);
-    NVRAM_set_lword(nvram,  0x38, kernel_image);
-    NVRAM_set_lword(nvram,  0x3C, kernel_size);
-    if (cmdline) {
-        /* XXX: put the cmdline in NVRAM too ? */
-        pstrcpy_targphys("cmdline", CMDLINE_ADDR, RAM_size - CMDLINE_ADDR, cmdline);
-        NVRAM_set_lword(nvram,  0x40, CMDLINE_ADDR);
-        NVRAM_set_lword(nvram,  0x44, strlen(cmdline));
-    } else {
-        NVRAM_set_lword(nvram,  0x40, 0);
-        NVRAM_set_lword(nvram,  0x44, 0);
-    }
-    NVRAM_set_lword(nvram,  0x48, initrd_image);
-    NVRAM_set_lword(nvram,  0x4C, initrd_size);
-    NVRAM_set_lword(nvram,  0x50, NVRAM_image);
-
-    NVRAM_set_word(nvram,   0x54, width);
-    NVRAM_set_word(nvram,   0x56, height);
-    NVRAM_set_word(nvram,   0x58, depth);
-    crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
-    NVRAM_set_word(nvram,   0xFC, crc);
-
-    return 0;
-}
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 9141373..294d0de 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -1,19 +1,14 @@
-# shared objects
-obj-y = ppc.o ppc_booke.o
 # PREP target
 obj-y += mc146818rtc.o
 # IBM pSeries (sPAPR)
-obj-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
+obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_rtas.o spapr_vio.o
 obj-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
 obj-$(CONFIG_PSERIES) += spapr_pci.o pci/pci-hotplug.o spapr_iommu.o
 obj-$(CONFIG_PSERIES) += spapr_events.o spapr_nvram.o
 # PowerPC 4xx boards
-obj-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
-obj-y += ppc440_bamboo.o
+obj-y += ppc4xx_devs.o ppc4xx_pci.o
 # PowerPC E500 boards
 obj-$(CONFIG_E500) += mpc8544_guts.o ppce500_spin.o
-# PowerPC 440 Xilinx ML507 reference board.
-obj-y += virtex_ml507.o
 # PowerPC OpenPIC
 obj-y += openpic.o
 
@@ -22,6 +17,12 @@ obj-y += xilinx_ethlite.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
+# shared objects
+obj-y += ppc.o ppc_booke.o
+# IBM pSeries (sPAPR)
+obj-$(CONFIG_PSERIES) += spapr.o
+# PowerPC 4xx boards
+obj-y += ppc405_boards.o ppc405_uc.o ppc440_bamboo.o
 # PReP
 obj-y += prep.o
 # OldWorld PowerMac
@@ -30,3 +31,5 @@ obj-y += mac_oldworld.o
 obj-y += mac_newworld.o
 # e500
 obj-$(CONFIG_E500) += e500.o mpc8544ds.o e500plat.o
+# PowerPC 440 Xilinx ML507 reference board.
+obj-y += virtex_ml507.o
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
new file mode 100644
index 0000000..c9437fc
--- /dev/null
+++ b/hw/ppc/ppc.c
@@ -0,0 +1,1356 @@
+/*
+ * QEMU generic PowerPC hardware System Emulator
+ *
+ * Copyright (c) 2003-2007 Jocelyn Mayer
+ *
+ * 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/hw.h"
+#include "hw/ppc.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "hw/nvram.h"
+#include "qemu/log.h"
+#include "hw/loader.h"
+#include "sysemu/kvm.h"
+#include "kvm_ppc.h"
+
+//#define PPC_DEBUG_IRQ
+//#define PPC_DEBUG_TB
+
+#ifdef PPC_DEBUG_IRQ
+#  define LOG_IRQ(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
+#else
+#  define LOG_IRQ(...) do { } while (0)
+#endif
+
+
+#ifdef PPC_DEBUG_TB
+#  define LOG_TB(...) qemu_log(__VA_ARGS__)
+#else
+#  define LOG_TB(...) do { } while (0)
+#endif
+
+static void cpu_ppc_tb_stop (CPUPPCState *env);
+static void cpu_ppc_tb_start (CPUPPCState *env);
+
+void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
+{
+    CPUPPCState *env = &cpu->env;
+    unsigned int old_pending = env->pending_interrupts;
+
+    if (level) {
+        env->pending_interrupts |= 1 << n_IRQ;
+        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    } else {
+        env->pending_interrupts &= ~(1 << n_IRQ);
+        if (env->pending_interrupts == 0)
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+
+    if (old_pending != env->pending_interrupts) {
+#ifdef CONFIG_KVM
+        kvmppc_set_interrupt(cpu, n_IRQ, level);
+#endif
+    }
+
+    LOG_IRQ("%s: %p n_IRQ %d level %d => pending %08" PRIx32
+                "req %08x\n", __func__, env, n_IRQ, level,
+                env->pending_interrupts, env->interrupt_request);
+}
+
+/* PowerPC 6xx / 7xx internal IRQ controller */
+static void ppc6xx_set_irq(void *opaque, int pin, int level)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+    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;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPC6xx_INPUT_TBEN:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: %s the time base\n",
+                        __func__, level ? "start" : "stop");
+            if (level) {
+                cpu_ppc_tb_start(env);
+            } else {
+                cpu_ppc_tb_stop(env);
+            }
+        case PPC6xx_INPUT_INT:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the external IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPC6xx_INPUT_SMI:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the SMI IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_SMI, level);
+            break;
+        case PPC6xx_INPUT_MCP:
+            /* Negative edge sensitive */
+            /* XXX: TODO: actual reaction may depends on HID0 status
+             *            603/604/740/750: check HID0[EMCP]
+             */
+            if (cur_level == 1 && level == 0) {
+                LOG_IRQ("%s: raise machine check state\n",
+                            __func__);
+                ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1);
+            }
+            break;
+        case PPC6xx_INPUT_CKSTP_IN:
+            /* Level sensitive - active low */
+            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
+            /* XXX: Note that the only way to restart the CPU is to reset it */
+            if (level) {
+                LOG_IRQ("%s: stop the CPU\n", __func__);
+                env->halted = 1;
+            }
+            break;
+        case PPC6xx_INPUT_HRESET:
+            /* Level sensitive - active low */
+            if (level) {
+                LOG_IRQ("%s: reset the CPU\n", __func__);
+                cpu_interrupt(env, CPU_INTERRUPT_RESET);
+            }
+            break;
+        case PPC6xx_INPUT_SRESET:
+            LOG_IRQ("%s: set the RESET IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_RESET, 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 ppc6xx_irq_init(CPUPPCState *env)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, cpu,
+                                                  PPC6xx_INPUT_NB);
+}
+
+#if defined(TARGET_PPC64)
+/* PowerPC 970 internal IRQ controller */
+static void ppc970_set_irq(void *opaque, int pin, int level)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+    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;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPC970_INPUT_INT:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the external IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPC970_INPUT_THINT:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the SMI IRQ state to %d\n", __func__,
+                        level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_THERM, level);
+            break;
+        case PPC970_INPUT_MCP:
+            /* Negative edge sensitive */
+            /* XXX: TODO: actual reaction may depends on HID0 status
+             *            603/604/740/750: check HID0[EMCP]
+             */
+            if (cur_level == 1 && level == 0) {
+                LOG_IRQ("%s: raise machine check state\n",
+                            __func__);
+                ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1);
+            }
+            break;
+        case PPC970_INPUT_CKSTP:
+            /* Level sensitive - active low */
+            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
+            if (level) {
+                LOG_IRQ("%s: stop the CPU\n", __func__);
+                env->halted = 1;
+            } else {
+                LOG_IRQ("%s: restart the CPU\n", __func__);
+                env->halted = 0;
+                qemu_cpu_kick(CPU(cpu));
+            }
+            break;
+        case PPC970_INPUT_HRESET:
+            /* Level sensitive - active low */
+            if (level) {
+                cpu_interrupt(env, CPU_INTERRUPT_RESET);
+            }
+            break;
+        case PPC970_INPUT_SRESET:
+            LOG_IRQ("%s: set the RESET IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level);
+            break;
+        case PPC970_INPUT_TBEN:
+            LOG_IRQ("%s: set the TBEN state to %d\n", __func__,
+                        level);
+            /* XXX: TODO */
+            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 ppc970_irq_init(CPUPPCState *env)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, cpu,
+                                                  PPC970_INPUT_NB);
+}
+
+/* POWER7 internal IRQ controller */
+static void power7_set_irq(void *opaque, int pin, int level)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+
+    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
+                env, pin, level);
+
+    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(cpu, 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(CPUPPCState *env)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, cpu,
+                                                  POWER7_INPUT_NB);
+}
+#endif /* defined(TARGET_PPC64) */
+
+/* PowerPC 40x internal IRQ controller */
+static void ppc40x_set_irq(void *opaque, int pin, int level)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+    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;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPC40x_INPUT_RESET_SYS:
+            if (level) {
+                LOG_IRQ("%s: reset the PowerPC system\n",
+                            __func__);
+                ppc40x_system_reset(cpu);
+            }
+            break;
+        case PPC40x_INPUT_RESET_CHIP:
+            if (level) {
+                LOG_IRQ("%s: reset the PowerPC chip\n", __func__);
+                ppc40x_chip_reset(cpu);
+            }
+            break;
+        case PPC40x_INPUT_RESET_CORE:
+            /* XXX: TODO: update DBSR[MRR] */
+            if (level) {
+                LOG_IRQ("%s: reset the PowerPC core\n", __func__);
+                ppc40x_core_reset(cpu);
+            }
+            break;
+        case PPC40x_INPUT_CINT:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the critical IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level);
+            break;
+        case PPC40x_INPUT_INT:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the external IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPC40x_INPUT_HALT:
+            /* Level sensitive - active low */
+            if (level) {
+                LOG_IRQ("%s: stop the CPU\n", __func__);
+                env->halted = 1;
+            } else {
+                LOG_IRQ("%s: restart the CPU\n", __func__);
+                env->halted = 0;
+                qemu_cpu_kick(CPU(cpu));
+            }
+            break;
+        case PPC40x_INPUT_DEBUG:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the debug pin state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, 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 ppc40x_irq_init(CPUPPCState *env)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
+                                                  cpu, PPC40x_INPUT_NB);
+}
+
+/* PowerPC E500 internal IRQ controller */
+static void ppce500_set_irq(void *opaque, int pin, int level)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+    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;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPCE500_INPUT_MCK:
+            if (level) {
+                LOG_IRQ("%s: reset the PowerPC system\n",
+                            __func__);
+                qemu_system_reset_request();
+            }
+            break;
+        case PPCE500_INPUT_RESET_CORE:
+            if (level) {
+                LOG_IRQ("%s: reset the PowerPC core\n", __func__);
+                ppc_set_irq(cpu, PPC_INTERRUPT_MCK, level);
+            }
+            break;
+        case PPCE500_INPUT_CINT:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the critical IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level);
+            break;
+        case PPCE500_INPUT_INT:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the core IRQ state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPCE500_INPUT_DEBUG:
+            /* Level sensitive - active high */
+            LOG_IRQ("%s: set the debug pin state to %d\n",
+                        __func__, level);
+            ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, 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 ppce500_irq_init(CPUPPCState *env)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
+                                                  cpu, PPCE500_INPUT_NB);
+}
+
+/* Enable or Disable the E500 EPR capability */
+void ppce500_set_mpic_proxy(bool enabled)
+{
+    CPUPPCState *env;
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        PowerPCCPU *cpu = ppc_env_get_cpu(env);
+        CPUState *cs = CPU(cpu);
+
+        env->mpic_proxy = enabled;
+        if (kvm_enabled()) {
+            kvmppc_set_mpic_proxy(POWERPC_CPU(cs), enabled);
+        }
+    }
+}
+
+/*****************************************************************************/
+/* PowerPC time base and decrementer emulation */
+
+uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset)
+{
+    /* TB time in tb periods */
+    return muldiv64(vmclk, tb_env->tb_freq, get_ticks_per_sec()) + tb_offset;
+}
+
+uint64_t cpu_ppc_load_tbl (CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
+
+    if (kvm_enabled()) {
+        return env->spr[SPR_TBL];
+    }
+
+    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;
+}
+
+static inline uint32_t _cpu_ppc_load_tbu(CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
+
+    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;
+}
+
+uint32_t cpu_ppc_load_tbu (CPUPPCState *env)
+{
+    if (kvm_enabled()) {
+        return env->spr[SPR_TBU];
+    }
+
+    return _cpu_ppc_load_tbu(env);
+}
+
+static inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, uint64_t vmclk,
+                                    int64_t *tb_offsetp, uint64_t value)
+{
+    *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, get_ticks_per_sec());
+    LOG_TB("%s: tb %016" PRIx64 " offset %08" PRIx64 "\n",
+                __func__, value, *tb_offsetp);
+}
+
+void cpu_ppc_store_tbl (CPUPPCState *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_ns(vm_clock), tb_env->tb_offset);
+    tb &= 0xFFFFFFFF00000000ULL;
+    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
+                     &tb_env->tb_offset, tb | (uint64_t)value);
+}
+
+static inline void _cpu_ppc_store_tbu(CPUPPCState *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_ns(vm_clock), tb_env->tb_offset);
+    tb &= 0x00000000FFFFFFFFULL;
+    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
+                     &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
+}
+
+void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value)
+{
+    _cpu_ppc_store_tbu(env, value);
+}
+
+uint64_t cpu_ppc_load_atbl (CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
+
+    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;
+}
+
+uint32_t cpu_ppc_load_atbu (CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb;
+
+    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;
+}
+
+void cpu_ppc_store_atbl (CPUPPCState *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_ns(vm_clock), tb_env->atb_offset);
+    tb &= 0xFFFFFFFF00000000ULL;
+    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
+                     &tb_env->atb_offset, tb | (uint64_t)value);
+}
+
+void cpu_ppc_store_atbu (CPUPPCState *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_ns(vm_clock), tb_env->atb_offset);
+    tb &= 0x00000000FFFFFFFFULL;
+    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
+                     &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
+}
+
+static void cpu_ppc_tb_stop (CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb, atb, vmclk;
+
+    /* If the time base is already frozen, do nothing */
+    if (tb_env->tb_freq != 0) {
+        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 */
+        atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset);
+        /* Store the time base value (ie compute the current offset) */
+        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
+        /* Store the alternate time base value (compute the current offset) */
+        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
+        /* Set the time base frequency to zero */
+        tb_env->tb_freq = 0;
+        /* Now, the time bases are frozen to tb_offset / atb_offset value */
+    }
+}
+
+static void cpu_ppc_tb_start (CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t tb, atb, vmclk;
+
+    /* If the time base is not frozen, do nothing */
+    if (tb_env->tb_freq == 0) {
+        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 */
+        atb = tb_env->atb_offset;
+        /* Restore the tb frequency from the decrementer frequency */
+        tb_env->tb_freq = tb_env->decr_freq;
+        /* Store the time base value */
+        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
+        /* Store the alternate time base value */
+        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
+    }
+}
+
+static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint32_t decr;
+    int64_t diff;
+
+    diff = next - qemu_get_clock_ns(vm_clock);
+    if (diff >= 0) {
+        decr = muldiv64(diff, tb_env->decr_freq, get_ticks_per_sec());
+    } else if (tb_env->flags & PPC_TIMER_BOOKE) {
+        decr = 0;
+    }  else {
+        decr = -muldiv64(-diff, tb_env->decr_freq, get_ticks_per_sec());
+    }
+    LOG_TB("%s: %08" PRIx32 "\n", __func__, decr);
+
+    return decr;
+}
+
+uint32_t cpu_ppc_load_decr (CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+
+    if (kvm_enabled()) {
+        return env->spr[SPR_DECR];
+    }
+
+    return _cpu_ppc_load_decr(env, tb_env->decr_next);
+}
+
+uint32_t cpu_ppc_load_hdecr (CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+
+    return _cpu_ppc_load_decr(env, tb_env->hdecr_next);
+}
+
+uint64_t cpu_ppc_load_purr (CPUPPCState *env)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t diff;
+
+    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());
+}
+
+/* When decrementer expires,
+ * all we need to do is generate or queue a CPU exception
+ */
+static inline void cpu_ppc_decr_excp(PowerPCCPU *cpu)
+{
+    /* Raise it */
+    LOG_TB("raise decrementer exception\n");
+    ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 1);
+}
+
+static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
+{
+    /* Raise it */
+    LOG_TB("raise decrementer exception\n");
+    ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
+}
+
+static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
+                                 struct QEMUTimer *timer,
+                                 void (*raise_excp)(PowerPCCPU *),
+                                 uint32_t decr, uint32_t value,
+                                 int is_excp)
+{
+    CPUPPCState *env = &cpu->env;
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t now, next;
+
+    LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__,
+                decr, value);
+
+    if (kvm_enabled()) {
+        /* KVM handles decrementer exceptions, we don't need our own timer */
+        return;
+    }
+
+    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;
+    }
+    if (next == now) {
+        next++;
+    }
+    *nextp = next;
+    /* Adjust timer */
+    qemu_mod_timer(timer, next);
+
+    /* If we set a negative value and the decrementer was positive, raise an
+     * exception.
+     */
+    if ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED)
+        && (value & 0x80000000)
+        && !(decr & 0x80000000)) {
+        (*raise_excp)(cpu);
+    }
+}
+
+static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, uint32_t decr,
+                                       uint32_t value, int is_excp)
+{
+    ppc_tb_t *tb_env = cpu->env.tb_env;
+
+    __cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer,
+                         &cpu_ppc_decr_excp, decr, value, is_excp);
+}
+
+void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    _cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value, 0);
+}
+
+static void cpu_ppc_decr_cb(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+
+    _cpu_ppc_store_decr(cpu, 0x00000000, 0xFFFFFFFF, 1);
+}
+
+static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, uint32_t hdecr,
+                                        uint32_t value, int is_excp)
+{
+    ppc_tb_t *tb_env = cpu->env.tb_env;
+
+    if (tb_env->hdecr_timer != NULL) {
+        __cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer,
+                             &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
+    }
+}
+
+void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    _cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value, 0);
+}
+
+static void cpu_ppc_hdecr_cb(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+
+    _cpu_ppc_store_hdecr(cpu, 0x00000000, 0xFFFFFFFF, 1);
+}
+
+static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value)
+{
+    ppc_tb_t *tb_env = cpu->env.tb_env;
+
+    tb_env->purr_load = value;
+    tb_env->purr_start = qemu_get_clock_ns(vm_clock);
+}
+
+static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
+{
+    CPUPPCState *env = opaque;
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+    ppc_tb_t *tb_env = env->tb_env;
+
+    tb_env->tb_freq = freq;
+    tb_env->decr_freq = freq;
+    /* There is a bug in Linux 2.4 kernels:
+     * if a decrementer exception is pending when it enables msr_ee at startup,
+     * it's not ready to handle it...
+     */
+    _cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
+    _cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
+    cpu_ppc_store_purr(cpu, 0x0000000000000000ULL);
+}
+
+/* Set up (once) timebase frequency (in Hz) */
+clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+    ppc_tb_t *tb_env;
+
+    tb_env = g_malloc0(sizeof(ppc_tb_t));
+    env->tb_env = tb_env;
+    tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
+    /* Create new timer */
+    tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_decr_cb, cpu);
+    if (0) {
+        /* XXX: find a suitable condition to enable the hypervisor decrementer
+         */
+        tb_env->hdecr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_hdecr_cb,
+                                                cpu);
+    } else {
+        tb_env->hdecr_timer = NULL;
+    }
+    cpu_ppc_set_tb_clk(env, freq);
+
+    return &cpu_ppc_set_tb_clk;
+}
+
+/* Specific helpers for POWER & PowerPC 601 RTC */
+#if 0
+static clk_setup_cb cpu_ppc601_rtc_init (CPUPPCState *env)
+{
+    return cpu_ppc_tb_init(env, 7812500);
+}
+#endif
+
+void cpu_ppc601_store_rtcu (CPUPPCState *env, uint32_t value)
+{
+    _cpu_ppc_store_tbu(env, value);
+}
+
+uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env)
+{
+    return _cpu_ppc_load_tbu(env);
+}
+
+void cpu_ppc601_store_rtcl (CPUPPCState *env, uint32_t value)
+{
+    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
+}
+
+uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env)
+{
+    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
+}
+
+/*****************************************************************************/
+/* PowerPC 40x timers */
+
+/* PIT, FIT & WDT */
+typedef struct ppc40x_timer_t ppc40x_timer_t;
+struct ppc40x_timer_t {
+    uint64_t pit_reload;  /* PIT auto-reload value        */
+    uint64_t fit_next;    /* Tick for next FIT interrupt  */
+    struct QEMUTimer *fit_timer;
+    uint64_t wdt_next;    /* Tick for next WDT interrupt  */
+    struct QEMUTimer *wdt_timer;
+
+    /* 405 have the PIT, 440 have a DECR.  */
+    unsigned int decr_excp;
+};
+
+/* Fixed interval timer */
+static void cpu_4xx_fit_cb (void *opaque)
+{
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    ppc_tb_t *tb_env;
+    ppc40x_timer_t *ppc40x_timer;
+    uint64_t now, next;
+
+    env = opaque;
+    cpu = ppc_env_get_cpu(env);
+    tb_env = env->tb_env;
+    ppc40x_timer = tb_env->opaque;
+    now = qemu_get_clock_ns(vm_clock);
+    switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
+    case 0:
+        next = 1 << 9;
+        break;
+    case 1:
+        next = 1 << 13;
+        break;
+    case 2:
+        next = 1 << 17;
+        break;
+    case 3:
+        next = 1 << 21;
+        break;
+    default:
+        /* Cannot occur, but makes gcc happy */
+        return;
+    }
+    next = now + muldiv64(next, get_ticks_per_sec(), tb_env->tb_freq);
+    if (next == now)
+        next++;
+    qemu_mod_timer(ppc40x_timer->fit_timer, next);
+    env->spr[SPR_40x_TSR] |= 1 << 26;
+    if ((env->spr[SPR_40x_TCR] >> 23) & 0x1) {
+        ppc_set_irq(cpu, PPC_INTERRUPT_FIT, 1);
+    }
+    LOG_TB("%s: ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
+           (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
+           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
+}
+
+/* Programmable interval timer */
+static void start_stop_pit (CPUPPCState *env, ppc_tb_t *tb_env, int is_excp)
+{
+    ppc40x_timer_t *ppc40x_timer;
+    uint64_t now, next;
+
+    ppc40x_timer = tb_env->opaque;
+    if (ppc40x_timer->pit_reload <= 1 ||
+        !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
+        (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
+        /* Stop PIT */
+        LOG_TB("%s: stop PIT\n", __func__);
+        qemu_del_timer(tb_env->decr_timer);
+    } else {
+        LOG_TB("%s: start PIT %016" PRIx64 "\n",
+                    __func__, ppc40x_timer->pit_reload);
+        now = qemu_get_clock_ns(vm_clock);
+        next = now + muldiv64(ppc40x_timer->pit_reload,
+                              get_ticks_per_sec(), tb_env->decr_freq);
+        if (is_excp)
+            next += tb_env->decr_next - now;
+        if (next == now)
+            next++;
+        qemu_mod_timer(tb_env->decr_timer, next);
+        tb_env->decr_next = next;
+    }
+}
+
+static void cpu_4xx_pit_cb (void *opaque)
+{
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    ppc_tb_t *tb_env;
+    ppc40x_timer_t *ppc40x_timer;
+
+    env = opaque;
+    cpu = ppc_env_get_cpu(env);
+    tb_env = env->tb_env;
+    ppc40x_timer = tb_env->opaque;
+    env->spr[SPR_40x_TSR] |= 1 << 27;
+    if ((env->spr[SPR_40x_TCR] >> 26) & 0x1) {
+        ppc_set_irq(cpu, ppc40x_timer->decr_excp, 1);
+    }
+    start_stop_pit(env, tb_env, 1);
+    LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " "
+           "%016" PRIx64 "\n", __func__,
+           (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
+           (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
+           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
+           ppc40x_timer->pit_reload);
+}
+
+/* Watchdog timer */
+static void cpu_4xx_wdt_cb (void *opaque)
+{
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    ppc_tb_t *tb_env;
+    ppc40x_timer_t *ppc40x_timer;
+    uint64_t now, next;
+
+    env = opaque;
+    cpu = ppc_env_get_cpu(env);
+    tb_env = env->tb_env;
+    ppc40x_timer = tb_env->opaque;
+    now = qemu_get_clock_ns(vm_clock);
+    switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
+    case 0:
+        next = 1 << 17;
+        break;
+    case 1:
+        next = 1 << 21;
+        break;
+    case 2:
+        next = 1 << 25;
+        break;
+    case 3:
+        next = 1 << 29;
+        break;
+    default:
+        /* Cannot occur, but makes gcc happy */
+        return;
+    }
+    next = now + muldiv64(next, get_ticks_per_sec(), tb_env->decr_freq);
+    if (next == now)
+        next++;
+    LOG_TB("%s: TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
+           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
+    switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
+    case 0x0:
+    case 0x1:
+        qemu_mod_timer(ppc40x_timer->wdt_timer, next);
+        ppc40x_timer->wdt_next = next;
+        env->spr[SPR_40x_TSR] |= 1 << 31;
+        break;
+    case 0x2:
+        qemu_mod_timer(ppc40x_timer->wdt_timer, next);
+        ppc40x_timer->wdt_next = next;
+        env->spr[SPR_40x_TSR] |= 1 << 30;
+        if ((env->spr[SPR_40x_TCR] >> 27) & 0x1) {
+            ppc_set_irq(cpu, PPC_INTERRUPT_WDT, 1);
+        }
+        break;
+    case 0x3:
+        env->spr[SPR_40x_TSR] &= ~0x30000000;
+        env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
+        switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
+        case 0x0:
+            /* No reset */
+            break;
+        case 0x1: /* Core reset */
+            ppc40x_core_reset(cpu);
+            break;
+        case 0x2: /* Chip reset */
+            ppc40x_chip_reset(cpu);
+            break;
+        case 0x3: /* System reset */
+            ppc40x_system_reset(cpu);
+            break;
+        }
+    }
+}
+
+void store_40x_pit (CPUPPCState *env, target_ulong val)
+{
+    ppc_tb_t *tb_env;
+    ppc40x_timer_t *ppc40x_timer;
+
+    tb_env = env->tb_env;
+    ppc40x_timer = tb_env->opaque;
+    LOG_TB("%s val" TARGET_FMT_lx "\n", __func__, val);
+    ppc40x_timer->pit_reload = val;
+    start_stop_pit(env, tb_env, 0);
+}
+
+target_ulong load_40x_pit (CPUPPCState *env)
+{
+    return cpu_ppc_load_decr(env);
+}
+
+static void ppc_40x_set_tb_clk (void *opaque, uint32_t freq)
+{
+    CPUPPCState *env = opaque;
+    ppc_tb_t *tb_env = env->tb_env;
+
+    LOG_TB("%s set new frequency to %" PRIu32 "\n", __func__,
+                freq);
+    tb_env->tb_freq = freq;
+    tb_env->decr_freq = freq;
+    /* XXX: we should also update all timers */
+}
+
+clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq,
+                                  unsigned int decr_excp)
+{
+    ppc_tb_t *tb_env;
+    ppc40x_timer_t *ppc40x_timer;
+
+    tb_env = g_malloc0(sizeof(ppc_tb_t));
+    env->tb_env = tb_env;
+    tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
+    ppc40x_timer = g_malloc0(sizeof(ppc40x_timer_t));
+    tb_env->tb_freq = freq;
+    tb_env->decr_freq = freq;
+    tb_env->opaque = ppc40x_timer;
+    LOG_TB("%s freq %" PRIu32 "\n", __func__, freq);
+    if (ppc40x_timer != NULL) {
+        /* We use decr timer for PIT */
+        tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_4xx_pit_cb, env);
+        ppc40x_timer->fit_timer =
+            qemu_new_timer_ns(vm_clock, &cpu_4xx_fit_cb, env);
+        ppc40x_timer->wdt_timer =
+            qemu_new_timer_ns(vm_clock, &cpu_4xx_wdt_cb, env);
+        ppc40x_timer->decr_excp = decr_excp;
+    }
+
+    return &ppc_40x_set_tb_clk;
+}
+
+/*****************************************************************************/
+/* Embedded PowerPC Device Control Registers */
+typedef struct ppc_dcrn_t ppc_dcrn_t;
+struct ppc_dcrn_t {
+    dcr_read_cb dcr_read;
+    dcr_write_cb dcr_write;
+    void *opaque;
+};
+
+/* XXX: on 460, DCR addresses are 32 bits wide,
+ *      using DCRIPR to get the 22 upper bits of the DCR address
+ */
+#define DCRN_NB 1024
+struct ppc_dcr_t {
+    ppc_dcrn_t dcrn[DCRN_NB];
+    int (*read_error)(int dcrn);
+    int (*write_error)(int dcrn);
+};
+
+int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
+{
+    ppc_dcrn_t *dcr;
+
+    if (dcrn < 0 || dcrn >= DCRN_NB)
+        goto error;
+    dcr = &dcr_env->dcrn[dcrn];
+    if (dcr->dcr_read == NULL)
+        goto error;
+    *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
+
+    return 0;
+
+ error:
+    if (dcr_env->read_error != NULL)
+        return (*dcr_env->read_error)(dcrn);
+
+    return -1;
+}
+
+int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
+{
+    ppc_dcrn_t *dcr;
+
+    if (dcrn < 0 || dcrn >= DCRN_NB)
+        goto error;
+    dcr = &dcr_env->dcrn[dcrn];
+    if (dcr->dcr_write == NULL)
+        goto error;
+    (*dcr->dcr_write)(dcr->opaque, dcrn, val);
+
+    return 0;
+
+ error:
+    if (dcr_env->write_error != NULL)
+        return (*dcr_env->write_error)(dcrn);
+
+    return -1;
+}
+
+int ppc_dcr_register (CPUPPCState *env, int dcrn, void *opaque,
+                      dcr_read_cb dcr_read, dcr_write_cb dcr_write)
+{
+    ppc_dcr_t *dcr_env;
+    ppc_dcrn_t *dcr;
+
+    dcr_env = env->dcr_env;
+    if (dcr_env == NULL)
+        return -1;
+    if (dcrn < 0 || dcrn >= DCRN_NB)
+        return -1;
+    dcr = &dcr_env->dcrn[dcrn];
+    if (dcr->opaque != NULL ||
+        dcr->dcr_read != NULL ||
+        dcr->dcr_write != NULL)
+        return -1;
+    dcr->opaque = opaque;
+    dcr->dcr_read = dcr_read;
+    dcr->dcr_write = dcr_write;
+
+    return 0;
+}
+
+int ppc_dcr_init (CPUPPCState *env, int (*read_error)(int dcrn),
+                  int (*write_error)(int dcrn))
+{
+    ppc_dcr_t *dcr_env;
+
+    dcr_env = g_malloc0(sizeof(ppc_dcr_t));
+    dcr_env->read_error = read_error;
+    dcr_env->write_error = write_error;
+    env->dcr_env = dcr_env;
+
+    return 0;
+}
+
+/*****************************************************************************/
+/* Debug port */
+void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
+{
+    addr &= 0xF;
+    switch (addr) {
+    case 0:
+        printf("%c", val);
+        break;
+    case 1:
+        printf("\n");
+        fflush(stdout);
+        break;
+    case 2:
+        printf("Set loglevel to %04" PRIx32 "\n", val);
+        qemu_set_log(val | 0x100);
+        break;
+    }
+}
+
+/*****************************************************************************/
+/* NVRAM helpers */
+static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
+{
+    return (*nvram->read_fn)(nvram->opaque, addr);
+}
+
+static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
+{
+    (*nvram->write_fn)(nvram->opaque, addr, val);
+}
+
+static void NVRAM_set_byte(nvram_t *nvram, uint32_t addr, uint8_t value)
+{
+    nvram_write(nvram, addr, value);
+}
+
+static uint8_t NVRAM_get_byte(nvram_t *nvram, uint32_t addr)
+{
+    return nvram_read(nvram, addr);
+}
+
+static void NVRAM_set_word(nvram_t *nvram, uint32_t addr, uint16_t value)
+{
+    nvram_write(nvram, addr, value >> 8);
+    nvram_write(nvram, addr + 1, value & 0xFF);
+}
+
+static uint16_t NVRAM_get_word(nvram_t *nvram, uint32_t addr)
+{
+    uint16_t tmp;
+
+    tmp = nvram_read(nvram, addr) << 8;
+    tmp |= nvram_read(nvram, addr + 1);
+
+    return tmp;
+}
+
+static void NVRAM_set_lword(nvram_t *nvram, uint32_t addr, uint32_t value)
+{
+    nvram_write(nvram, addr, value >> 24);
+    nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
+    nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
+    nvram_write(nvram, addr + 3, value & 0xFF);
+}
+
+uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
+{
+    uint32_t tmp;
+
+    tmp = nvram_read(nvram, addr) << 24;
+    tmp |= nvram_read(nvram, addr + 1) << 16;
+    tmp |= nvram_read(nvram, addr + 2) << 8;
+    tmp |= nvram_read(nvram, addr + 3);
+
+    return tmp;
+}
+
+static void NVRAM_set_string(nvram_t *nvram, uint32_t addr, const char *str,
+                             uint32_t max)
+{
+    int i;
+
+    for (i = 0; i < max && str[i] != '\0'; i++) {
+        nvram_write(nvram, addr + i, str[i]);
+    }
+    nvram_write(nvram, addr + i, str[i]);
+    nvram_write(nvram, addr + max - 1, '\0');
+}
+
+int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
+{
+    int i;
+
+    memset(dst, 0, max);
+    for (i = 0; i < max; i++) {
+        dst[i] = NVRAM_get_byte(nvram, addr + i);
+        if (dst[i] == '\0')
+            break;
+    }
+
+    return i;
+}
+
+static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
+{
+    uint16_t tmp;
+    uint16_t pd, pd1, pd2;
+
+    tmp = prev >> 8;
+    pd = prev ^ value;
+    pd1 = pd & 0x000F;
+    pd2 = ((pd >> 4) & 0x000F) ^ pd1;
+    tmp ^= (pd1 << 3) | (pd1 << 8);
+    tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
+
+    return tmp;
+}
+
+static uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
+{
+    uint32_t i;
+    uint16_t crc = 0xFFFF;
+    int odd;
+
+    odd = count & 1;
+    count &= ~1;
+    for (i = 0; i != count; i++) {
+        crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
+    }
+    if (odd) {
+        crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
+    }
+
+    return crc;
+}
+
+#define CMDLINE_ADDR 0x017ff000
+
+int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
+                          const char *arch,
+                          uint32_t RAM_size, int boot_device,
+                          uint32_t kernel_image, uint32_t kernel_size,
+                          const char *cmdline,
+                          uint32_t initrd_image, uint32_t initrd_size,
+                          uint32_t NVRAM_image,
+                          int width, int height, int depth)
+{
+    uint16_t crc;
+
+    /* Set parameters for Open Hack'Ware BIOS */
+    NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
+    NVRAM_set_lword(nvram,  0x10, 0x00000002); /* structure v2 */
+    NVRAM_set_word(nvram,   0x14, NVRAM_size);
+    NVRAM_set_string(nvram, 0x20, arch, 16);
+    NVRAM_set_lword(nvram,  0x30, RAM_size);
+    NVRAM_set_byte(nvram,   0x34, boot_device);
+    NVRAM_set_lword(nvram,  0x38, kernel_image);
+    NVRAM_set_lword(nvram,  0x3C, kernel_size);
+    if (cmdline) {
+        /* XXX: put the cmdline in NVRAM too ? */
+        pstrcpy_targphys("cmdline", CMDLINE_ADDR, RAM_size - CMDLINE_ADDR, cmdline);
+        NVRAM_set_lword(nvram,  0x40, CMDLINE_ADDR);
+        NVRAM_set_lword(nvram,  0x44, strlen(cmdline));
+    } else {
+        NVRAM_set_lword(nvram,  0x40, 0);
+        NVRAM_set_lword(nvram,  0x44, 0);
+    }
+    NVRAM_set_lword(nvram,  0x48, initrd_image);
+    NVRAM_set_lword(nvram,  0x4C, initrd_size);
+    NVRAM_set_lword(nvram,  0x50, NVRAM_image);
+
+    NVRAM_set_word(nvram,   0x54, width);
+    NVRAM_set_word(nvram,   0x56, height);
+    NVRAM_set_word(nvram,   0x58, depth);
+    crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
+    NVRAM_set_word(nvram,   0xFC, crc);
+
+    return 0;
+}
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
new file mode 100644
index 0000000..ba443cf
--- /dev/null
+++ b/hw/ppc/ppc405_boards.c
@@ -0,0 +1,662 @@
+/*
+ * QEMU PowerPC 405 evaluation boards emulation
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * 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/hw.h"
+#include "hw/ppc.h"
+#include "hw/ppc405.h"
+#include "hw/nvram.h"
+#include "hw/flash.h"
+#include "sysemu/sysemu.h"
+#include "block/block.h"
+#include "hw/boards.h"
+#include "qemu/log.h"
+#include "hw/loader.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+#define BIOS_FILENAME "ppc405_rom.bin"
+#define BIOS_SIZE (2048 * 1024)
+
+#define KERNEL_LOAD_ADDR 0x00000000
+#define INITRD_LOAD_ADDR 0x01800000
+
+#define USE_FLASH_BIOS
+
+#define DEBUG_BOARD_INIT
+
+/*****************************************************************************/
+/* PPC405EP reference board (IBM) */
+/* Standalone board with:
+ * - PowerPC 405EP CPU
+ * - SDRAM (0x00000000)
+ * - Flash (0xFFF80000)
+ * - SRAM  (0xFFF00000)
+ * - NVRAM (0xF0000000)
+ * - FPGA  (0xF0300000)
+ */
+typedef struct ref405ep_fpga_t ref405ep_fpga_t;
+struct ref405ep_fpga_t {
+    uint8_t reg0;
+    uint8_t reg1;
+};
+
+static uint32_t ref405ep_fpga_readb (void *opaque, hwaddr addr)
+{
+    ref405ep_fpga_t *fpga;
+    uint32_t ret;
+
+    fpga = opaque;
+    switch (addr) {
+    case 0x0:
+        ret = fpga->reg0;
+        break;
+    case 0x1:
+        ret = fpga->reg1;
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void ref405ep_fpga_writeb (void *opaque,
+                                  hwaddr addr, uint32_t value)
+{
+    ref405ep_fpga_t *fpga;
+
+    fpga = opaque;
+    switch (addr) {
+    case 0x0:
+        /* Read only */
+        break;
+    case 0x1:
+        fpga->reg1 = value;
+        break;
+    default:
+        break;
+    }
+}
+
+static uint32_t ref405ep_fpga_readw (void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+    ret = ref405ep_fpga_readb(opaque, addr) << 8;
+    ret |= ref405ep_fpga_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void ref405ep_fpga_writew (void *opaque,
+                                  hwaddr addr, uint32_t value)
+{
+    ref405ep_fpga_writeb(opaque, addr, (value >> 8) & 0xFF);
+    ref405ep_fpga_writeb(opaque, addr + 1, value & 0xFF);
+}
+
+static uint32_t ref405ep_fpga_readl (void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+    ret = ref405ep_fpga_readb(opaque, addr) << 24;
+    ret |= ref405ep_fpga_readb(opaque, addr + 1) << 16;
+    ret |= ref405ep_fpga_readb(opaque, addr + 2) << 8;
+    ret |= ref405ep_fpga_readb(opaque, addr + 3);
+
+    return ret;
+}
+
+static void ref405ep_fpga_writel (void *opaque,
+                                  hwaddr addr, uint32_t value)
+{
+    ref405ep_fpga_writeb(opaque, addr, (value >> 24) & 0xFF);
+    ref405ep_fpga_writeb(opaque, addr + 1, (value >> 16) & 0xFF);
+    ref405ep_fpga_writeb(opaque, addr + 2, (value >> 8) & 0xFF);
+    ref405ep_fpga_writeb(opaque, addr + 3, value & 0xFF);
+}
+
+static const MemoryRegionOps ref405ep_fpga_ops = {
+    .old_mmio = {
+        .read = {
+            ref405ep_fpga_readb, ref405ep_fpga_readw, ref405ep_fpga_readl,
+        },
+        .write = {
+            ref405ep_fpga_writeb, ref405ep_fpga_writew, ref405ep_fpga_writel,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void ref405ep_fpga_reset (void *opaque)
+{
+    ref405ep_fpga_t *fpga;
+
+    fpga = opaque;
+    fpga->reg0 = 0x00;
+    fpga->reg1 = 0x0F;
+}
+
+static void ref405ep_fpga_init(MemoryRegion *sysmem, uint32_t base)
+{
+    ref405ep_fpga_t *fpga;
+    MemoryRegion *fpga_memory = g_new(MemoryRegion, 1);
+
+    fpga = g_malloc0(sizeof(ref405ep_fpga_t));
+    memory_region_init_io(fpga_memory, &ref405ep_fpga_ops, fpga,
+                          "fpga", 0x00000100);
+    memory_region_add_subregion(sysmem, base, fpga_memory);
+    qemu_register_reset(&ref405ep_fpga_reset, fpga);
+}
+
+static void ref405ep_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    char *filename;
+    ppc4xx_bd_info_t bd;
+    CPUPPCState *env;
+    qemu_irq *pic;
+    MemoryRegion *bios;
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    ram_addr_t bdloc;
+    MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
+    hwaddr ram_bases[2], ram_sizes[2];
+    target_ulong sram_size;
+    long bios_size;
+    //int phy_addr = 0;
+    //static int phy_addr = 1;
+    target_ulong kernel_base, initrd_base;
+    long kernel_size, initrd_size;
+    int linux_boot;
+    int fl_idx, fl_sectors, len;
+    DriveInfo *dinfo;
+    MemoryRegion *sysmem = get_system_memory();
+
+    /* XXX: fix this */
+    memory_region_init_ram(&ram_memories[0], "ef405ep.ram", 0x08000000);
+    vmstate_register_ram_global(&ram_memories[0]);
+    ram_bases[0] = 0;
+    ram_sizes[0] = 0x08000000;
+    memory_region_init(&ram_memories[1], "ef405ep.ram1", 0);
+    ram_bases[1] = 0x00000000;
+    ram_sizes[1] = 0x00000000;
+    ram_size = 128 * 1024 * 1024;
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register cpu\n", __func__);
+#endif
+    env = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
+                        33333333, &pic, kernel_filename == NULL ? 0 : 1);
+    /* allocate SRAM */
+    sram_size = 512 * 1024;
+    memory_region_init_ram(sram, "ef405ep.sram", sram_size);
+    vmstate_register_ram_global(sram);
+    memory_region_add_subregion(sysmem, 0xFFF00000, sram);
+    /* allocate and load BIOS */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register BIOS\n", __func__);
+#endif
+    fl_idx = 0;
+#ifdef USE_FLASH_BIOS
+    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
+    if (dinfo) {
+        bios_size = bdrv_getlength(dinfo->bdrv);
+        fl_sectors = (bios_size + 65535) >> 16;
+#ifdef DEBUG_BOARD_INIT
+        printf("Register parallel flash %d size %lx"
+               " at addr %lx '%s' %d\n",
+               fl_idx, bios_size, -bios_size,
+               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
+#endif
+        pflash_cfi02_register((uint32_t)(-bios_size),
+                              NULL, "ef405ep.bios", bios_size,
+                              dinfo->bdrv, 65536, fl_sectors, 1,
+                              2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
+                              1);
+        fl_idx++;
+    } else
+#endif
+    {
+#ifdef DEBUG_BOARD_INIT
+        printf("Load BIOS from file\n");
+#endif
+        bios = g_new(MemoryRegion, 1);
+        memory_region_init_ram(bios, "ef405ep.bios", BIOS_SIZE);
+        vmstate_register_ram_global(bios);
+        if (bios_name == NULL)
+            bios_name = BIOS_FILENAME;
+        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (filename) {
+            bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
+            g_free(filename);
+        } else {
+            bios_size = -1;
+        }
+        if (bios_size < 0 || bios_size > BIOS_SIZE) {
+            fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n",
+                    bios_name);
+            exit(1);
+        }
+        bios_size = (bios_size + 0xfff) & ~0xfff;
+        memory_region_set_readonly(bios, true);
+        memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
+    }
+    /* Register FPGA */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register FPGA\n", __func__);
+#endif
+    ref405ep_fpga_init(sysmem, 0xF0300000);
+    /* Register NVRAM */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register NVRAM\n", __func__);
+#endif
+    m48t59_init(NULL, 0xF0000000, 0, 8192, 8);
+    /* Load kernel */
+    linux_boot = (kernel_filename != NULL);
+    if (linux_boot) {
+#ifdef DEBUG_BOARD_INIT
+        printf("%s: load kernel\n", __func__);
+#endif
+        memset(&bd, 0, sizeof(bd));
+        bd.bi_memstart = 0x00000000;
+        bd.bi_memsize = ram_size;
+        bd.bi_flashstart = -bios_size;
+        bd.bi_flashsize = -bios_size;
+        bd.bi_flashoffset = 0;
+        bd.bi_sramstart = 0xFFF00000;
+        bd.bi_sramsize = sram_size;
+        bd.bi_bootflags = 0;
+        bd.bi_intfreq = 133333333;
+        bd.bi_busfreq = 33333333;
+        bd.bi_baudrate = 115200;
+        bd.bi_s_version[0] = 'Q';
+        bd.bi_s_version[1] = 'M';
+        bd.bi_s_version[2] = 'U';
+        bd.bi_s_version[3] = '\0';
+        bd.bi_r_version[0] = 'Q';
+        bd.bi_r_version[1] = 'E';
+        bd.bi_r_version[2] = 'M';
+        bd.bi_r_version[3] = 'U';
+        bd.bi_r_version[4] = '\0';
+        bd.bi_procfreq = 133333333;
+        bd.bi_plb_busfreq = 33333333;
+        bd.bi_pci_busfreq = 33333333;
+        bd.bi_opbfreq = 33333333;
+        bdloc = ppc405_set_bootinfo(env, &bd, 0x00000001);
+        env->gpr[3] = bdloc;
+        kernel_base = KERNEL_LOAD_ADDR;
+        /* now we can load the kernel */
+        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);
+        }
+        printf("Load kernel size %ld at " TARGET_FMT_lx,
+               kernel_size, kernel_base);
+        /* 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;
+        }
+        env->gpr[4] = initrd_base;
+        env->gpr[5] = initrd_size;
+        if (kernel_cmdline != NULL) {
+            len = strlen(kernel_cmdline);
+            bdloc -= ((len + 255) & ~255);
+            cpu_physical_memory_write(bdloc, (void *)kernel_cmdline, len + 1);
+            env->gpr[6] = bdloc;
+            env->gpr[7] = bdloc + len;
+        } else {
+            env->gpr[6] = 0;
+            env->gpr[7] = 0;
+        }
+        env->nip = KERNEL_LOAD_ADDR;
+    } else {
+        kernel_base = 0;
+        kernel_size = 0;
+        initrd_base = 0;
+        initrd_size = 0;
+        bdloc = 0;
+    }
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: Done\n", __func__);
+#endif
+    printf("bdloc " RAM_ADDR_FMT "\n", bdloc);
+}
+
+static QEMUMachine ref405ep_machine = {
+    .name = "ref405ep",
+    .desc = "ref405ep",
+    .init = ref405ep_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+/*****************************************************************************/
+/* AMCC Taihu evaluation board */
+/* - PowerPC 405EP processor
+ * - SDRAM               128 MB at 0x00000000
+ * - Boot flash          2 MB   at 0xFFE00000
+ * - Application flash   32 MB  at 0xFC000000
+ * - 2 serial ports
+ * - 2 ethernet PHY
+ * - 1 USB 1.1 device    0x50000000
+ * - 1 LCD display       0x50100000
+ * - 1 CPLD              0x50100000
+ * - 1 I2C EEPROM
+ * - 1 I2C thermal sensor
+ * - a set of LEDs
+ * - bit-bang SPI port using GPIOs
+ * - 1 EBC interface connector 0 0x50200000
+ * - 1 cardbus controller + expansion slot.
+ * - 1 PCI expansion slot.
+ */
+typedef struct taihu_cpld_t taihu_cpld_t;
+struct taihu_cpld_t {
+    uint8_t reg0;
+    uint8_t reg1;
+};
+
+static uint32_t taihu_cpld_readb (void *opaque, hwaddr addr)
+{
+    taihu_cpld_t *cpld;
+    uint32_t ret;
+
+    cpld = opaque;
+    switch (addr) {
+    case 0x0:
+        ret = cpld->reg0;
+        break;
+    case 0x1:
+        ret = cpld->reg1;
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void taihu_cpld_writeb (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+    taihu_cpld_t *cpld;
+
+    cpld = opaque;
+    switch (addr) {
+    case 0x0:
+        /* Read only */
+        break;
+    case 0x1:
+        cpld->reg1 = value;
+        break;
+    default:
+        break;
+    }
+}
+
+static uint32_t taihu_cpld_readw (void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+    ret = taihu_cpld_readb(opaque, addr) << 8;
+    ret |= taihu_cpld_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void taihu_cpld_writew (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+    taihu_cpld_writeb(opaque, addr, (value >> 8) & 0xFF);
+    taihu_cpld_writeb(opaque, addr + 1, value & 0xFF);
+}
+
+static uint32_t taihu_cpld_readl (void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+    ret = taihu_cpld_readb(opaque, addr) << 24;
+    ret |= taihu_cpld_readb(opaque, addr + 1) << 16;
+    ret |= taihu_cpld_readb(opaque, addr + 2) << 8;
+    ret |= taihu_cpld_readb(opaque, addr + 3);
+
+    return ret;
+}
+
+static void taihu_cpld_writel (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+    taihu_cpld_writel(opaque, addr, (value >> 24) & 0xFF);
+    taihu_cpld_writel(opaque, addr + 1, (value >> 16) & 0xFF);
+    taihu_cpld_writel(opaque, addr + 2, (value >> 8) & 0xFF);
+    taihu_cpld_writeb(opaque, addr + 3, value & 0xFF);
+}
+
+static const MemoryRegionOps taihu_cpld_ops = {
+    .old_mmio = {
+        .read = { taihu_cpld_readb, taihu_cpld_readw, taihu_cpld_readl, },
+        .write = { taihu_cpld_writeb, taihu_cpld_writew, taihu_cpld_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void taihu_cpld_reset (void *opaque)
+{
+    taihu_cpld_t *cpld;
+
+    cpld = opaque;
+    cpld->reg0 = 0x01;
+    cpld->reg1 = 0x80;
+}
+
+static void taihu_cpld_init(MemoryRegion *sysmem, uint32_t base)
+{
+    taihu_cpld_t *cpld;
+    MemoryRegion *cpld_memory = g_new(MemoryRegion, 1);
+
+    cpld = g_malloc0(sizeof(taihu_cpld_t));
+    memory_region_init_io(cpld_memory, &taihu_cpld_ops, cpld, "cpld", 0x100);
+    memory_region_add_subregion(sysmem, base, cpld_memory);
+    qemu_register_reset(&taihu_cpld_reset, cpld);
+}
+
+static void taihu_405ep_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *kernel_filename = args->kernel_filename;
+    const char *initrd_filename = args->initrd_filename;
+    char *filename;
+    qemu_irq *pic;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *bios;
+    MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
+    hwaddr ram_bases[2], ram_sizes[2];
+    long bios_size;
+    target_ulong kernel_base, initrd_base;
+    long kernel_size, initrd_size;
+    int linux_boot;
+    int fl_idx, fl_sectors;
+    DriveInfo *dinfo;
+
+    /* RAM is soldered to the board so the size cannot be changed */
+    memory_region_init_ram(&ram_memories[0],
+                           "taihu_405ep.ram-0", 0x04000000);
+    vmstate_register_ram_global(&ram_memories[0]);
+    ram_bases[0] = 0;
+    ram_sizes[0] = 0x04000000;
+    memory_region_init_ram(&ram_memories[1],
+                           "taihu_405ep.ram-1", 0x04000000);
+    vmstate_register_ram_global(&ram_memories[1]);
+    ram_bases[1] = 0x04000000;
+    ram_sizes[1] = 0x04000000;
+    ram_size = 0x08000000;
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register cpu\n", __func__);
+#endif
+    ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
+                  33333333, &pic, kernel_filename == NULL ? 0 : 1);
+    /* allocate and load BIOS */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register BIOS\n", __func__);
+#endif
+    fl_idx = 0;
+#if defined(USE_FLASH_BIOS)
+    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
+    if (dinfo) {
+        bios_size = bdrv_getlength(dinfo->bdrv);
+        /* XXX: should check that size is 2MB */
+        //        bios_size = 2 * 1024 * 1024;
+        fl_sectors = (bios_size + 65535) >> 16;
+#ifdef DEBUG_BOARD_INIT
+        printf("Register parallel flash %d size %lx"
+               " at addr %lx '%s' %d\n",
+               fl_idx, bios_size, -bios_size,
+               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
+#endif
+        pflash_cfi02_register((uint32_t)(-bios_size),
+                              NULL, "taihu_405ep.bios", bios_size,
+                              dinfo->bdrv, 65536, fl_sectors, 1,
+                              4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
+                              1);
+        fl_idx++;
+    } else
+#endif
+    {
+#ifdef DEBUG_BOARD_INIT
+        printf("Load BIOS from file\n");
+#endif
+        if (bios_name == NULL)
+            bios_name = BIOS_FILENAME;
+        bios = g_new(MemoryRegion, 1);
+        memory_region_init_ram(bios, "taihu_405ep.bios", BIOS_SIZE);
+        vmstate_register_ram_global(bios);
+        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (filename) {
+            bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
+            g_free(filename);
+        } else {
+            bios_size = -1;
+        }
+        if (bios_size < 0 || bios_size > BIOS_SIZE) {
+            fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n",
+                    bios_name);
+            exit(1);
+        }
+        bios_size = (bios_size + 0xfff) & ~0xfff;
+        memory_region_set_readonly(bios, true);
+        memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
+    }
+    /* Register Linux flash */
+    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
+    if (dinfo) {
+        bios_size = bdrv_getlength(dinfo->bdrv);
+        /* XXX: should check that size is 32MB */
+        bios_size = 32 * 1024 * 1024;
+        fl_sectors = (bios_size + 65535) >> 16;
+#ifdef DEBUG_BOARD_INIT
+        printf("Register parallel flash %d size %lx"
+               " at addr " TARGET_FMT_lx " '%s'\n",
+               fl_idx, bios_size, (target_ulong)0xfc000000,
+               bdrv_get_device_name(dinfo->bdrv));
+#endif
+        pflash_cfi02_register(0xfc000000, NULL, "taihu_405ep.flash", bios_size,
+                              dinfo->bdrv, 65536, fl_sectors, 1,
+                              4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
+                              1);
+        fl_idx++;
+    }
+    /* Register CLPD & LCD display */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register CPLD\n", __func__);
+#endif
+    taihu_cpld_init(sysmem, 0x50100000);
+    /* Load kernel */
+    linux_boot = (kernel_filename != NULL);
+    if (linux_boot) {
+#ifdef DEBUG_BOARD_INIT
+        printf("%s: load kernel\n", __func__);
+#endif
+        kernel_base = KERNEL_LOAD_ADDR;
+        /* now we can load the kernel */
+        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 {
+        kernel_base = 0;
+        kernel_size = 0;
+        initrd_base = 0;
+        initrd_size = 0;
+    }
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: Done\n", __func__);
+#endif
+}
+
+static QEMUMachine taihu_machine = {
+    .name = "taihu",
+    .desc = "taihu",
+    .init = taihu_405ep_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void ppc405_machine_init(void)
+{
+    qemu_register_machine(&ref405ep_machine);
+    qemu_register_machine(&taihu_machine);
+}
+
+machine_init(ppc405_machine_init);
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
new file mode 100644
index 0000000..8465f6d
--- /dev/null
+++ b/hw/ppc/ppc405_uc.c
@@ -0,0 +1,2548 @@
+/*
+ * QEMU PowerPC 405 embedded processors emulation
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * 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/hw.h"
+#include "hw/ppc.h"
+#include "hw/ppc405.h"
+#include "hw/serial.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "qemu/log.h"
+#include "exec/address-spaces.h"
+
+#define DEBUG_OPBA
+#define DEBUG_SDRAM
+#define DEBUG_GPIO
+#define DEBUG_SERIAL
+#define DEBUG_OCM
+//#define DEBUG_I2C
+#define DEBUG_GPT
+#define DEBUG_MAL
+#define DEBUG_CLOCKS
+//#define DEBUG_CLOCKS_LL
+
+ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
+                                uint32_t flags)
+{
+    ram_addr_t bdloc;
+    int i, n;
+
+    /* We put the bd structure at the top of memory */
+    if (bd->bi_memsize >= 0x01000000UL)
+        bdloc = 0x01000000UL - sizeof(struct ppc4xx_bd_info_t);
+    else
+        bdloc = bd->bi_memsize - sizeof(struct ppc4xx_bd_info_t);
+    stl_be_phys(bdloc + 0x00, bd->bi_memstart);
+    stl_be_phys(bdloc + 0x04, bd->bi_memsize);
+    stl_be_phys(bdloc + 0x08, bd->bi_flashstart);
+    stl_be_phys(bdloc + 0x0C, bd->bi_flashsize);
+    stl_be_phys(bdloc + 0x10, bd->bi_flashoffset);
+    stl_be_phys(bdloc + 0x14, bd->bi_sramstart);
+    stl_be_phys(bdloc + 0x18, bd->bi_sramsize);
+    stl_be_phys(bdloc + 0x1C, bd->bi_bootflags);
+    stl_be_phys(bdloc + 0x20, bd->bi_ipaddr);
+    for (i = 0; i < 6; i++) {
+        stb_phys(bdloc + 0x24 + i, bd->bi_enetaddr[i]);
+    }
+    stw_be_phys(bdloc + 0x2A, bd->bi_ethspeed);
+    stl_be_phys(bdloc + 0x2C, bd->bi_intfreq);
+    stl_be_phys(bdloc + 0x30, bd->bi_busfreq);
+    stl_be_phys(bdloc + 0x34, bd->bi_baudrate);
+    for (i = 0; i < 4; i++) {
+        stb_phys(bdloc + 0x38 + i, bd->bi_s_version[i]);
+    }
+    for (i = 0; i < 32; i++) {
+        stb_phys(bdloc + 0x3C + i, bd->bi_r_version[i]);
+    }
+    stl_be_phys(bdloc + 0x5C, bd->bi_plb_busfreq);
+    stl_be_phys(bdloc + 0x60, bd->bi_pci_busfreq);
+    for (i = 0; i < 6; i++) {
+        stb_phys(bdloc + 0x64 + i, bd->bi_pci_enetaddr[i]);
+    }
+    n = 0x6A;
+    if (flags & 0x00000001) {
+        for (i = 0; i < 6; i++)
+            stb_phys(bdloc + n++, bd->bi_pci_enetaddr2[i]);
+    }
+    stl_be_phys(bdloc + n, bd->bi_opbfreq);
+    n += 4;
+    for (i = 0; i < 2; i++) {
+        stl_be_phys(bdloc + n, bd->bi_iic_fast[i]);
+        n += 4;
+    }
+
+    return bdloc;
+}
+
+/*****************************************************************************/
+/* Shared peripherals */
+
+/*****************************************************************************/
+/* Peripheral local bus arbitrer */
+enum {
+    PLB0_BESR = 0x084,
+    PLB0_BEAR = 0x086,
+    PLB0_ACR  = 0x087,
+};
+
+typedef struct ppc4xx_plb_t ppc4xx_plb_t;
+struct ppc4xx_plb_t {
+    uint32_t acr;
+    uint32_t bear;
+    uint32_t besr;
+};
+
+static uint32_t dcr_read_plb (void *opaque, int dcrn)
+{
+    ppc4xx_plb_t *plb;
+    uint32_t ret;
+
+    plb = opaque;
+    switch (dcrn) {
+    case PLB0_ACR:
+        ret = plb->acr;
+        break;
+    case PLB0_BEAR:
+        ret = plb->bear;
+        break;
+    case PLB0_BESR:
+        ret = plb->besr;
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_plb (void *opaque, int dcrn, uint32_t val)
+{
+    ppc4xx_plb_t *plb;
+
+    plb = opaque;
+    switch (dcrn) {
+    case PLB0_ACR:
+        /* We don't care about the actual parameters written as
+         * we don't manage any priorities on the bus
+         */
+        plb->acr = val & 0xF8000000;
+        break;
+    case PLB0_BEAR:
+        /* Read only */
+        break;
+    case PLB0_BESR:
+        /* Write-clear */
+        plb->besr &= ~val;
+        break;
+    }
+}
+
+static void ppc4xx_plb_reset (void *opaque)
+{
+    ppc4xx_plb_t *plb;
+
+    plb = opaque;
+    plb->acr = 0x00000000;
+    plb->bear = 0x00000000;
+    plb->besr = 0x00000000;
+}
+
+static void ppc4xx_plb_init(CPUPPCState *env)
+{
+    ppc4xx_plb_t *plb;
+
+    plb = g_malloc0(sizeof(ppc4xx_plb_t));
+    ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
+    ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
+    ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
+    qemu_register_reset(ppc4xx_plb_reset, plb);
+}
+
+/*****************************************************************************/
+/* PLB to OPB bridge */
+enum {
+    POB0_BESR0 = 0x0A0,
+    POB0_BESR1 = 0x0A2,
+    POB0_BEAR  = 0x0A4,
+};
+
+typedef struct ppc4xx_pob_t ppc4xx_pob_t;
+struct ppc4xx_pob_t {
+    uint32_t bear;
+    uint32_t besr0;
+    uint32_t besr1;
+};
+
+static uint32_t dcr_read_pob (void *opaque, int dcrn)
+{
+    ppc4xx_pob_t *pob;
+    uint32_t ret;
+
+    pob = opaque;
+    switch (dcrn) {
+    case POB0_BEAR:
+        ret = pob->bear;
+        break;
+    case POB0_BESR0:
+        ret = pob->besr0;
+        break;
+    case POB0_BESR1:
+        ret = pob->besr1;
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_pob (void *opaque, int dcrn, uint32_t val)
+{
+    ppc4xx_pob_t *pob;
+
+    pob = opaque;
+    switch (dcrn) {
+    case POB0_BEAR:
+        /* Read only */
+        break;
+    case POB0_BESR0:
+        /* Write-clear */
+        pob->besr0 &= ~val;
+        break;
+    case POB0_BESR1:
+        /* Write-clear */
+        pob->besr1 &= ~val;
+        break;
+    }
+}
+
+static void ppc4xx_pob_reset (void *opaque)
+{
+    ppc4xx_pob_t *pob;
+
+    pob = opaque;
+    /* No error */
+    pob->bear = 0x00000000;
+    pob->besr0 = 0x0000000;
+    pob->besr1 = 0x0000000;
+}
+
+static void ppc4xx_pob_init(CPUPPCState *env)
+{
+    ppc4xx_pob_t *pob;
+
+    pob = g_malloc0(sizeof(ppc4xx_pob_t));
+    ppc_dcr_register(env, POB0_BEAR, pob, &dcr_read_pob, &dcr_write_pob);
+    ppc_dcr_register(env, POB0_BESR0, pob, &dcr_read_pob, &dcr_write_pob);
+    ppc_dcr_register(env, POB0_BESR1, pob, &dcr_read_pob, &dcr_write_pob);
+    qemu_register_reset(ppc4xx_pob_reset, pob);
+}
+
+/*****************************************************************************/
+/* OPB arbitrer */
+typedef struct ppc4xx_opba_t ppc4xx_opba_t;
+struct ppc4xx_opba_t {
+    MemoryRegion io;
+    uint8_t cr;
+    uint8_t pr;
+};
+
+static uint32_t opba_readb (void *opaque, hwaddr addr)
+{
+    ppc4xx_opba_t *opba;
+    uint32_t ret;
+
+#ifdef DEBUG_OPBA
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    opba = opaque;
+    switch (addr) {
+    case 0x00:
+        ret = opba->cr;
+        break;
+    case 0x01:
+        ret = opba->pr;
+        break;
+    default:
+        ret = 0x00;
+        break;
+    }
+
+    return ret;
+}
+
+static void opba_writeb (void *opaque,
+                         hwaddr addr, uint32_t value)
+{
+    ppc4xx_opba_t *opba;
+
+#ifdef DEBUG_OPBA
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    opba = opaque;
+    switch (addr) {
+    case 0x00:
+        opba->cr = value & 0xF8;
+        break;
+    case 0x01:
+        opba->pr = value & 0xFF;
+        break;
+    default:
+        break;
+    }
+}
+
+static uint32_t opba_readw (void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_OPBA
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    ret = opba_readb(opaque, addr) << 8;
+    ret |= opba_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void opba_writew (void *opaque,
+                         hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_OPBA
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    opba_writeb(opaque, addr, value >> 8);
+    opba_writeb(opaque, addr + 1, value);
+}
+
+static uint32_t opba_readl (void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_OPBA
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    ret = opba_readb(opaque, addr) << 24;
+    ret |= opba_readb(opaque, addr + 1) << 16;
+
+    return ret;
+}
+
+static void opba_writel (void *opaque,
+                         hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_OPBA
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    opba_writeb(opaque, addr, value >> 24);
+    opba_writeb(opaque, addr + 1, value >> 16);
+}
+
+static const MemoryRegionOps opba_ops = {
+    .old_mmio = {
+        .read = { opba_readb, opba_readw, opba_readl, },
+        .write = { opba_writeb, opba_writew, opba_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void ppc4xx_opba_reset (void *opaque)
+{
+    ppc4xx_opba_t *opba;
+
+    opba = opaque;
+    opba->cr = 0x00; /* No dynamic priorities - park disabled */
+    opba->pr = 0x11;
+}
+
+static void ppc4xx_opba_init(hwaddr base)
+{
+    ppc4xx_opba_t *opba;
+
+    opba = g_malloc0(sizeof(ppc4xx_opba_t));
+#ifdef DEBUG_OPBA
+    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
+#endif
+    memory_region_init_io(&opba->io, &opba_ops, opba, "opba", 0x002);
+    memory_region_add_subregion(get_system_memory(), base, &opba->io);
+    qemu_register_reset(ppc4xx_opba_reset, opba);
+}
+
+/*****************************************************************************/
+/* Code decompression controller */
+/* XXX: TODO */
+
+/*****************************************************************************/
+/* Peripheral controller */
+typedef struct ppc4xx_ebc_t ppc4xx_ebc_t;
+struct ppc4xx_ebc_t {
+    uint32_t addr;
+    uint32_t bcr[8];
+    uint32_t bap[8];
+    uint32_t bear;
+    uint32_t besr0;
+    uint32_t besr1;
+    uint32_t cfg;
+};
+
+enum {
+    EBC0_CFGADDR = 0x012,
+    EBC0_CFGDATA = 0x013,
+};
+
+static uint32_t dcr_read_ebc (void *opaque, int dcrn)
+{
+    ppc4xx_ebc_t *ebc;
+    uint32_t ret;
+
+    ebc = opaque;
+    switch (dcrn) {
+    case EBC0_CFGADDR:
+        ret = ebc->addr;
+        break;
+    case EBC0_CFGDATA:
+        switch (ebc->addr) {
+        case 0x00: /* B0CR */
+            ret = ebc->bcr[0];
+            break;
+        case 0x01: /* B1CR */
+            ret = ebc->bcr[1];
+            break;
+        case 0x02: /* B2CR */
+            ret = ebc->bcr[2];
+            break;
+        case 0x03: /* B3CR */
+            ret = ebc->bcr[3];
+            break;
+        case 0x04: /* B4CR */
+            ret = ebc->bcr[4];
+            break;
+        case 0x05: /* B5CR */
+            ret = ebc->bcr[5];
+            break;
+        case 0x06: /* B6CR */
+            ret = ebc->bcr[6];
+            break;
+        case 0x07: /* B7CR */
+            ret = ebc->bcr[7];
+            break;
+        case 0x10: /* B0AP */
+            ret = ebc->bap[0];
+            break;
+        case 0x11: /* B1AP */
+            ret = ebc->bap[1];
+            break;
+        case 0x12: /* B2AP */
+            ret = ebc->bap[2];
+            break;
+        case 0x13: /* B3AP */
+            ret = ebc->bap[3];
+            break;
+        case 0x14: /* B4AP */
+            ret = ebc->bap[4];
+            break;
+        case 0x15: /* B5AP */
+            ret = ebc->bap[5];
+            break;
+        case 0x16: /* B6AP */
+            ret = ebc->bap[6];
+            break;
+        case 0x17: /* B7AP */
+            ret = ebc->bap[7];
+            break;
+        case 0x20: /* BEAR */
+            ret = ebc->bear;
+            break;
+        case 0x21: /* BESR0 */
+            ret = ebc->besr0;
+            break;
+        case 0x22: /* BESR1 */
+            ret = ebc->besr1;
+            break;
+        case 0x23: /* CFG */
+            ret = ebc->cfg;
+            break;
+        default:
+            ret = 0x00000000;
+            break;
+        }
+        break;
+    default:
+        ret = 0x00000000;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_ebc (void *opaque, int dcrn, uint32_t val)
+{
+    ppc4xx_ebc_t *ebc;
+
+    ebc = opaque;
+    switch (dcrn) {
+    case EBC0_CFGADDR:
+        ebc->addr = val;
+        break;
+    case EBC0_CFGDATA:
+        switch (ebc->addr) {
+        case 0x00: /* B0CR */
+            break;
+        case 0x01: /* B1CR */
+            break;
+        case 0x02: /* B2CR */
+            break;
+        case 0x03: /* B3CR */
+            break;
+        case 0x04: /* B4CR */
+            break;
+        case 0x05: /* B5CR */
+            break;
+        case 0x06: /* B6CR */
+            break;
+        case 0x07: /* B7CR */
+            break;
+        case 0x10: /* B0AP */
+            break;
+        case 0x11: /* B1AP */
+            break;
+        case 0x12: /* B2AP */
+            break;
+        case 0x13: /* B3AP */
+            break;
+        case 0x14: /* B4AP */
+            break;
+        case 0x15: /* B5AP */
+            break;
+        case 0x16: /* B6AP */
+            break;
+        case 0x17: /* B7AP */
+            break;
+        case 0x20: /* BEAR */
+            break;
+        case 0x21: /* BESR0 */
+            break;
+        case 0x22: /* BESR1 */
+            break;
+        case 0x23: /* CFG */
+            break;
+        default:
+            break;
+        }
+        break;
+    default:
+        break;
+    }
+}
+
+static void ebc_reset (void *opaque)
+{
+    ppc4xx_ebc_t *ebc;
+    int i;
+
+    ebc = opaque;
+    ebc->addr = 0x00000000;
+    ebc->bap[0] = 0x7F8FFE80;
+    ebc->bcr[0] = 0xFFE28000;
+    for (i = 0; i < 8; i++) {
+        ebc->bap[i] = 0x00000000;
+        ebc->bcr[i] = 0x00000000;
+    }
+    ebc->besr0 = 0x00000000;
+    ebc->besr1 = 0x00000000;
+    ebc->cfg = 0x80400000;
+}
+
+static void ppc405_ebc_init(CPUPPCState *env)
+{
+    ppc4xx_ebc_t *ebc;
+
+    ebc = g_malloc0(sizeof(ppc4xx_ebc_t));
+    qemu_register_reset(&ebc_reset, ebc);
+    ppc_dcr_register(env, EBC0_CFGADDR,
+                     ebc, &dcr_read_ebc, &dcr_write_ebc);
+    ppc_dcr_register(env, EBC0_CFGDATA,
+                     ebc, &dcr_read_ebc, &dcr_write_ebc);
+}
+
+/*****************************************************************************/
+/* DMA controller */
+enum {
+    DMA0_CR0 = 0x100,
+    DMA0_CT0 = 0x101,
+    DMA0_DA0 = 0x102,
+    DMA0_SA0 = 0x103,
+    DMA0_SG0 = 0x104,
+    DMA0_CR1 = 0x108,
+    DMA0_CT1 = 0x109,
+    DMA0_DA1 = 0x10A,
+    DMA0_SA1 = 0x10B,
+    DMA0_SG1 = 0x10C,
+    DMA0_CR2 = 0x110,
+    DMA0_CT2 = 0x111,
+    DMA0_DA2 = 0x112,
+    DMA0_SA2 = 0x113,
+    DMA0_SG2 = 0x114,
+    DMA0_CR3 = 0x118,
+    DMA0_CT3 = 0x119,
+    DMA0_DA3 = 0x11A,
+    DMA0_SA3 = 0x11B,
+    DMA0_SG3 = 0x11C,
+    DMA0_SR  = 0x120,
+    DMA0_SGC = 0x123,
+    DMA0_SLP = 0x125,
+    DMA0_POL = 0x126,
+};
+
+typedef struct ppc405_dma_t ppc405_dma_t;
+struct ppc405_dma_t {
+    qemu_irq irqs[4];
+    uint32_t cr[4];
+    uint32_t ct[4];
+    uint32_t da[4];
+    uint32_t sa[4];
+    uint32_t sg[4];
+    uint32_t sr;
+    uint32_t sgc;
+    uint32_t slp;
+    uint32_t pol;
+};
+
+static uint32_t dcr_read_dma (void *opaque, int dcrn)
+{
+    return 0;
+}
+
+static void dcr_write_dma (void *opaque, int dcrn, uint32_t val)
+{
+}
+
+static void ppc405_dma_reset (void *opaque)
+{
+    ppc405_dma_t *dma;
+    int i;
+
+    dma = opaque;
+    for (i = 0; i < 4; i++) {
+        dma->cr[i] = 0x00000000;
+        dma->ct[i] = 0x00000000;
+        dma->da[i] = 0x00000000;
+        dma->sa[i] = 0x00000000;
+        dma->sg[i] = 0x00000000;
+    }
+    dma->sr = 0x00000000;
+    dma->sgc = 0x00000000;
+    dma->slp = 0x7C000000;
+    dma->pol = 0x00000000;
+}
+
+static void ppc405_dma_init(CPUPPCState *env, qemu_irq irqs[4])
+{
+    ppc405_dma_t *dma;
+
+    dma = g_malloc0(sizeof(ppc405_dma_t));
+    memcpy(dma->irqs, irqs, 4 * sizeof(qemu_irq));
+    qemu_register_reset(&ppc405_dma_reset, dma);
+    ppc_dcr_register(env, DMA0_CR0,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_CT0,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_DA0,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SA0,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SG0,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_CR1,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_CT1,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_DA1,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SA1,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SG1,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_CR2,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_CT2,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_DA2,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SA2,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SG2,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_CR3,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_CT3,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_DA3,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SA3,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SG3,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SR,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SGC,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_SLP,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+    ppc_dcr_register(env, DMA0_POL,
+                     dma, &dcr_read_dma, &dcr_write_dma);
+}
+
+/*****************************************************************************/
+/* GPIO */
+typedef struct ppc405_gpio_t ppc405_gpio_t;
+struct ppc405_gpio_t {
+    MemoryRegion io;
+    uint32_t or;
+    uint32_t tcr;
+    uint32_t osrh;
+    uint32_t osrl;
+    uint32_t tsrh;
+    uint32_t tsrl;
+    uint32_t odr;
+    uint32_t ir;
+    uint32_t rr1;
+    uint32_t isr1h;
+    uint32_t isr1l;
+};
+
+static uint32_t ppc405_gpio_readb (void *opaque, hwaddr addr)
+{
+#ifdef DEBUG_GPIO
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+
+    return 0;
+}
+
+static void ppc405_gpio_writeb (void *opaque,
+                                hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_GPIO
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+}
+
+static uint32_t ppc405_gpio_readw (void *opaque, hwaddr addr)
+{
+#ifdef DEBUG_GPIO
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+
+    return 0;
+}
+
+static void ppc405_gpio_writew (void *opaque,
+                                hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_GPIO
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+}
+
+static uint32_t ppc405_gpio_readl (void *opaque, hwaddr addr)
+{
+#ifdef DEBUG_GPIO
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+
+    return 0;
+}
+
+static void ppc405_gpio_writel (void *opaque,
+                                hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_GPIO
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+}
+
+static const MemoryRegionOps ppc405_gpio_ops = {
+    .old_mmio = {
+        .read = { ppc405_gpio_readb, ppc405_gpio_readw, ppc405_gpio_readl, },
+        .write = { ppc405_gpio_writeb, ppc405_gpio_writew, ppc405_gpio_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void ppc405_gpio_reset (void *opaque)
+{
+}
+
+static void ppc405_gpio_init(hwaddr base)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = g_malloc0(sizeof(ppc405_gpio_t));
+#ifdef DEBUG_GPIO
+    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
+#endif
+    memory_region_init_io(&gpio->io, &ppc405_gpio_ops, gpio, "pgio", 0x038);
+    memory_region_add_subregion(get_system_memory(), base, &gpio->io);
+    qemu_register_reset(&ppc405_gpio_reset, gpio);
+}
+
+/*****************************************************************************/
+/* On Chip Memory */
+enum {
+    OCM0_ISARC   = 0x018,
+    OCM0_ISACNTL = 0x019,
+    OCM0_DSARC   = 0x01A,
+    OCM0_DSACNTL = 0x01B,
+};
+
+typedef struct ppc405_ocm_t ppc405_ocm_t;
+struct ppc405_ocm_t {
+    MemoryRegion ram;
+    MemoryRegion isarc_ram;
+    MemoryRegion dsarc_ram;
+    uint32_t isarc;
+    uint32_t isacntl;
+    uint32_t dsarc;
+    uint32_t dsacntl;
+};
+
+static void ocm_update_mappings (ppc405_ocm_t *ocm,
+                                 uint32_t isarc, uint32_t isacntl,
+                                 uint32_t dsarc, uint32_t dsacntl)
+{
+#ifdef DEBUG_OCM
+    printf("OCM update ISA %08" PRIx32 " %08" PRIx32 " (%08" PRIx32
+           " %08" PRIx32 ") DSA %08" PRIx32 " %08" PRIx32
+           " (%08" PRIx32 " %08" PRIx32 ")\n",
+           isarc, isacntl, dsarc, dsacntl,
+           ocm->isarc, ocm->isacntl, ocm->dsarc, ocm->dsacntl);
+#endif
+    if (ocm->isarc != isarc ||
+        (ocm->isacntl & 0x80000000) != (isacntl & 0x80000000)) {
+        if (ocm->isacntl & 0x80000000) {
+            /* Unmap previously assigned memory region */
+            printf("OCM unmap ISA %08" PRIx32 "\n", ocm->isarc);
+            memory_region_del_subregion(get_system_memory(), &ocm->isarc_ram);
+        }
+        if (isacntl & 0x80000000) {
+            /* Map new instruction memory region */
+#ifdef DEBUG_OCM
+            printf("OCM map ISA %08" PRIx32 "\n", isarc);
+#endif
+            memory_region_add_subregion(get_system_memory(), isarc,
+                                        &ocm->isarc_ram);
+        }
+    }
+    if (ocm->dsarc != dsarc ||
+        (ocm->dsacntl & 0x80000000) != (dsacntl & 0x80000000)) {
+        if (ocm->dsacntl & 0x80000000) {
+            /* Beware not to unmap the region we just mapped */
+            if (!(isacntl & 0x80000000) || ocm->dsarc != isarc) {
+                /* Unmap previously assigned memory region */
+#ifdef DEBUG_OCM
+                printf("OCM unmap DSA %08" PRIx32 "\n", ocm->dsarc);
+#endif
+                memory_region_del_subregion(get_system_memory(),
+                                            &ocm->dsarc_ram);
+            }
+        }
+        if (dsacntl & 0x80000000) {
+            /* Beware not to remap the region we just mapped */
+            if (!(isacntl & 0x80000000) || dsarc != isarc) {
+                /* Map new data memory region */
+#ifdef DEBUG_OCM
+                printf("OCM map DSA %08" PRIx32 "\n", dsarc);
+#endif
+                memory_region_add_subregion(get_system_memory(), dsarc,
+                                            &ocm->dsarc_ram);
+            }
+        }
+    }
+}
+
+static uint32_t dcr_read_ocm (void *opaque, int dcrn)
+{
+    ppc405_ocm_t *ocm;
+    uint32_t ret;
+
+    ocm = opaque;
+    switch (dcrn) {
+    case OCM0_ISARC:
+        ret = ocm->isarc;
+        break;
+    case OCM0_ISACNTL:
+        ret = ocm->isacntl;
+        break;
+    case OCM0_DSARC:
+        ret = ocm->dsarc;
+        break;
+    case OCM0_DSACNTL:
+        ret = ocm->dsacntl;
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_ocm (void *opaque, int dcrn, uint32_t val)
+{
+    ppc405_ocm_t *ocm;
+    uint32_t isarc, dsarc, isacntl, dsacntl;
+
+    ocm = opaque;
+    isarc = ocm->isarc;
+    dsarc = ocm->dsarc;
+    isacntl = ocm->isacntl;
+    dsacntl = ocm->dsacntl;
+    switch (dcrn) {
+    case OCM0_ISARC:
+        isarc = val & 0xFC000000;
+        break;
+    case OCM0_ISACNTL:
+        isacntl = val & 0xC0000000;
+        break;
+    case OCM0_DSARC:
+        isarc = val & 0xFC000000;
+        break;
+    case OCM0_DSACNTL:
+        isacntl = val & 0xC0000000;
+        break;
+    }
+    ocm_update_mappings(ocm, isarc, isacntl, dsarc, dsacntl);
+    ocm->isarc = isarc;
+    ocm->dsarc = dsarc;
+    ocm->isacntl = isacntl;
+    ocm->dsacntl = dsacntl;
+}
+
+static void ocm_reset (void *opaque)
+{
+    ppc405_ocm_t *ocm;
+    uint32_t isarc, dsarc, isacntl, dsacntl;
+
+    ocm = opaque;
+    isarc = 0x00000000;
+    isacntl = 0x00000000;
+    dsarc = 0x00000000;
+    dsacntl = 0x00000000;
+    ocm_update_mappings(ocm, isarc, isacntl, dsarc, dsacntl);
+    ocm->isarc = isarc;
+    ocm->dsarc = dsarc;
+    ocm->isacntl = isacntl;
+    ocm->dsacntl = dsacntl;
+}
+
+static void ppc405_ocm_init(CPUPPCState *env)
+{
+    ppc405_ocm_t *ocm;
+
+    ocm = g_malloc0(sizeof(ppc405_ocm_t));
+    /* XXX: Size is 4096 or 0x04000000 */
+    memory_region_init_ram(&ocm->isarc_ram, "ppc405.ocm", 4096);
+    vmstate_register_ram_global(&ocm->isarc_ram);
+    memory_region_init_alias(&ocm->dsarc_ram, "ppc405.dsarc", &ocm->isarc_ram,
+                             0, 4096);
+    qemu_register_reset(&ocm_reset, ocm);
+    ppc_dcr_register(env, OCM0_ISARC,
+                     ocm, &dcr_read_ocm, &dcr_write_ocm);
+    ppc_dcr_register(env, OCM0_ISACNTL,
+                     ocm, &dcr_read_ocm, &dcr_write_ocm);
+    ppc_dcr_register(env, OCM0_DSARC,
+                     ocm, &dcr_read_ocm, &dcr_write_ocm);
+    ppc_dcr_register(env, OCM0_DSACNTL,
+                     ocm, &dcr_read_ocm, &dcr_write_ocm);
+}
+
+/*****************************************************************************/
+/* I2C controller */
+typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
+struct ppc4xx_i2c_t {
+    qemu_irq irq;
+    MemoryRegion iomem;
+    uint8_t mdata;
+    uint8_t lmadr;
+    uint8_t hmadr;
+    uint8_t cntl;
+    uint8_t mdcntl;
+    uint8_t sts;
+    uint8_t extsts;
+    uint8_t sdata;
+    uint8_t lsadr;
+    uint8_t hsadr;
+    uint8_t clkdiv;
+    uint8_t intrmsk;
+    uint8_t xfrcnt;
+    uint8_t xtcntlss;
+    uint8_t directcntl;
+};
+
+static uint32_t ppc4xx_i2c_readb (void *opaque, hwaddr addr)
+{
+    ppc4xx_i2c_t *i2c;
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    i2c = opaque;
+    switch (addr) {
+    case 0x00:
+        //        i2c_readbyte(&i2c->mdata);
+        ret = i2c->mdata;
+        break;
+    case 0x02:
+        ret = i2c->sdata;
+        break;
+    case 0x04:
+        ret = i2c->lmadr;
+        break;
+    case 0x05:
+        ret = i2c->hmadr;
+        break;
+    case 0x06:
+        ret = i2c->cntl;
+        break;
+    case 0x07:
+        ret = i2c->mdcntl;
+        break;
+    case 0x08:
+        ret = i2c->sts;
+        break;
+    case 0x09:
+        ret = i2c->extsts;
+        break;
+    case 0x0A:
+        ret = i2c->lsadr;
+        break;
+    case 0x0B:
+        ret = i2c->hsadr;
+        break;
+    case 0x0C:
+        ret = i2c->clkdiv;
+        break;
+    case 0x0D:
+        ret = i2c->intrmsk;
+        break;
+    case 0x0E:
+        ret = i2c->xfrcnt;
+        break;
+    case 0x0F:
+        ret = i2c->xtcntlss;
+        break;
+    case 0x10:
+        ret = i2c->directcntl;
+        break;
+    default:
+        ret = 0x00;
+        break;
+    }
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, ret);
+#endif
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writeb (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+    ppc4xx_i2c_t *i2c;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    i2c = opaque;
+    switch (addr) {
+    case 0x00:
+        i2c->mdata = value;
+        //        i2c_sendbyte(&i2c->mdata);
+        break;
+    case 0x02:
+        i2c->sdata = value;
+        break;
+    case 0x04:
+        i2c->lmadr = value;
+        break;
+    case 0x05:
+        i2c->hmadr = value;
+        break;
+    case 0x06:
+        i2c->cntl = value;
+        break;
+    case 0x07:
+        i2c->mdcntl = value & 0xDF;
+        break;
+    case 0x08:
+        i2c->sts &= ~(value & 0x0A);
+        break;
+    case 0x09:
+        i2c->extsts &= ~(value & 0x8F);
+        break;
+    case 0x0A:
+        i2c->lsadr = value;
+        break;
+    case 0x0B:
+        i2c->hsadr = value;
+        break;
+    case 0x0C:
+        i2c->clkdiv = value;
+        break;
+    case 0x0D:
+        i2c->intrmsk = value;
+        break;
+    case 0x0E:
+        i2c->xfrcnt = value & 0x77;
+        break;
+    case 0x0F:
+        i2c->xtcntlss = value;
+        break;
+    case 0x10:
+        i2c->directcntl = value & 0x7;
+        break;
+    }
+}
+
+static uint32_t ppc4xx_i2c_readw (void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    ret = ppc4xx_i2c_readb(opaque, addr) << 8;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writew (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    ppc4xx_i2c_writeb(opaque, addr, value >> 8);
+    ppc4xx_i2c_writeb(opaque, addr + 1, value);
+}
+
+static uint32_t ppc4xx_i2c_readl (void *opaque, hwaddr addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    ret = ppc4xx_i2c_readb(opaque, addr) << 24;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 3);
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writel (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    ppc4xx_i2c_writeb(opaque, addr, value >> 24);
+    ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16);
+    ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8);
+    ppc4xx_i2c_writeb(opaque, addr + 3, value);
+}
+
+static const MemoryRegionOps i2c_ops = {
+    .old_mmio = {
+        .read = { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, },
+        .write = { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void ppc4xx_i2c_reset (void *opaque)
+{
+    ppc4xx_i2c_t *i2c;
+
+    i2c = opaque;
+    i2c->mdata = 0x00;
+    i2c->sdata = 0x00;
+    i2c->cntl = 0x00;
+    i2c->mdcntl = 0x00;
+    i2c->sts = 0x00;
+    i2c->extsts = 0x00;
+    i2c->clkdiv = 0x00;
+    i2c->xfrcnt = 0x00;
+    i2c->directcntl = 0x0F;
+}
+
+static void ppc405_i2c_init(hwaddr base, qemu_irq irq)
+{
+    ppc4xx_i2c_t *i2c;
+
+    i2c = g_malloc0(sizeof(ppc4xx_i2c_t));
+    i2c->irq = irq;
+#ifdef DEBUG_I2C
+    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
+#endif
+    memory_region_init_io(&i2c->iomem, &i2c_ops, i2c, "i2c", 0x011);
+    memory_region_add_subregion(get_system_memory(), base, &i2c->iomem);
+    qemu_register_reset(ppc4xx_i2c_reset, i2c);
+}
+
+/*****************************************************************************/
+/* General purpose timers */
+typedef struct ppc4xx_gpt_t ppc4xx_gpt_t;
+struct ppc4xx_gpt_t {
+    MemoryRegion iomem;
+    int64_t tb_offset;
+    uint32_t tb_freq;
+    struct QEMUTimer *timer;
+    qemu_irq irqs[5];
+    uint32_t oe;
+    uint32_t ol;
+    uint32_t im;
+    uint32_t is;
+    uint32_t ie;
+    uint32_t comp[5];
+    uint32_t mask[5];
+};
+
+static uint32_t ppc4xx_gpt_readb (void *opaque, hwaddr addr)
+{
+#ifdef DEBUG_GPT
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    /* XXX: generate a bus fault */
+    return -1;
+}
+
+static void ppc4xx_gpt_writeb (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    /* XXX: generate a bus fault */
+}
+
+static uint32_t ppc4xx_gpt_readw (void *opaque, hwaddr addr)
+{
+#ifdef DEBUG_GPT
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    /* XXX: generate a bus fault */
+    return -1;
+}
+
+static void ppc4xx_gpt_writew (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    /* XXX: generate a bus fault */
+}
+
+static int ppc4xx_gpt_compare (ppc4xx_gpt_t *gpt, int n)
+{
+    /* XXX: TODO */
+    return 0;
+}
+
+static void ppc4xx_gpt_set_output (ppc4xx_gpt_t *gpt, int n, int level)
+{
+    /* XXX: TODO */
+}
+
+static void ppc4xx_gpt_set_outputs (ppc4xx_gpt_t *gpt)
+{
+    uint32_t mask;
+    int i;
+
+    mask = 0x80000000;
+    for (i = 0; i < 5; i++) {
+        if (gpt->oe & mask) {
+            /* Output is enabled */
+            if (ppc4xx_gpt_compare(gpt, i)) {
+                /* Comparison is OK */
+                ppc4xx_gpt_set_output(gpt, i, gpt->ol & mask);
+            } else {
+                /* Comparison is KO */
+                ppc4xx_gpt_set_output(gpt, i, gpt->ol & mask ? 0 : 1);
+            }
+        }
+        mask = mask >> 1;
+    }
+}
+
+static void ppc4xx_gpt_set_irqs (ppc4xx_gpt_t *gpt)
+{
+    uint32_t mask;
+    int i;
+
+    mask = 0x00008000;
+    for (i = 0; i < 5; i++) {
+        if (gpt->is & gpt->im & mask)
+            qemu_irq_raise(gpt->irqs[i]);
+        else
+            qemu_irq_lower(gpt->irqs[i]);
+        mask = mask >> 1;
+    }
+}
+
+static void ppc4xx_gpt_compute_timer (ppc4xx_gpt_t *gpt)
+{
+    /* XXX: TODO */
+}
+
+static uint32_t ppc4xx_gpt_readl (void *opaque, hwaddr addr)
+{
+    ppc4xx_gpt_t *gpt;
+    uint32_t ret;
+    int idx;
+
+#ifdef DEBUG_GPT
+    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+    gpt = opaque;
+    switch (addr) {
+    case 0x00:
+        /* Time base counter */
+        ret = muldiv64(qemu_get_clock_ns(vm_clock) + gpt->tb_offset,
+                       gpt->tb_freq, get_ticks_per_sec());
+        break;
+    case 0x10:
+        /* Output enable */
+        ret = gpt->oe;
+        break;
+    case 0x14:
+        /* Output level */
+        ret = gpt->ol;
+        break;
+    case 0x18:
+        /* Interrupt mask */
+        ret = gpt->im;
+        break;
+    case 0x1C:
+    case 0x20:
+        /* Interrupt status */
+        ret = gpt->is;
+        break;
+    case 0x24:
+        /* Interrupt enable */
+        ret = gpt->ie;
+        break;
+    case 0x80 ... 0x90:
+        /* Compare timer */
+        idx = (addr - 0x80) >> 2;
+        ret = gpt->comp[idx];
+        break;
+    case 0xC0 ... 0xD0:
+        /* Compare mask */
+        idx = (addr - 0xC0) >> 2;
+        ret = gpt->mask[idx];
+        break;
+    default:
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
+
+static void ppc4xx_gpt_writel (void *opaque,
+                               hwaddr addr, uint32_t value)
+{
+    ppc4xx_gpt_t *gpt;
+    int idx;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
+           value);
+#endif
+    gpt = opaque;
+    switch (addr) {
+    case 0x00:
+        /* Time base counter */
+        gpt->tb_offset = muldiv64(value, get_ticks_per_sec(), gpt->tb_freq)
+            - qemu_get_clock_ns(vm_clock);
+        ppc4xx_gpt_compute_timer(gpt);
+        break;
+    case 0x10:
+        /* Output enable */
+        gpt->oe = value & 0xF8000000;
+        ppc4xx_gpt_set_outputs(gpt);
+        break;
+    case 0x14:
+        /* Output level */
+        gpt->ol = value & 0xF8000000;
+        ppc4xx_gpt_set_outputs(gpt);
+        break;
+    case 0x18:
+        /* Interrupt mask */
+        gpt->im = value & 0x0000F800;
+        break;
+    case 0x1C:
+        /* Interrupt status set */
+        gpt->is |= value & 0x0000F800;
+        ppc4xx_gpt_set_irqs(gpt);
+        break;
+    case 0x20:
+        /* Interrupt status clear */
+        gpt->is &= ~(value & 0x0000F800);
+        ppc4xx_gpt_set_irqs(gpt);
+        break;
+    case 0x24:
+        /* Interrupt enable */
+        gpt->ie = value & 0x0000F800;
+        ppc4xx_gpt_set_irqs(gpt);
+        break;
+    case 0x80 ... 0x90:
+        /* Compare timer */
+        idx = (addr - 0x80) >> 2;
+        gpt->comp[idx] = value & 0xF8000000;
+        ppc4xx_gpt_compute_timer(gpt);
+        break;
+    case 0xC0 ... 0xD0:
+        /* Compare mask */
+        idx = (addr - 0xC0) >> 2;
+        gpt->mask[idx] = value & 0xF8000000;
+        ppc4xx_gpt_compute_timer(gpt);
+        break;
+    }
+}
+
+static const MemoryRegionOps gpt_ops = {
+    .old_mmio = {
+        .read = { ppc4xx_gpt_readb, ppc4xx_gpt_readw, ppc4xx_gpt_readl, },
+        .write = { ppc4xx_gpt_writeb, ppc4xx_gpt_writew, ppc4xx_gpt_writel, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void ppc4xx_gpt_cb (void *opaque)
+{
+    ppc4xx_gpt_t *gpt;
+
+    gpt = opaque;
+    ppc4xx_gpt_set_irqs(gpt);
+    ppc4xx_gpt_set_outputs(gpt);
+    ppc4xx_gpt_compute_timer(gpt);
+}
+
+static void ppc4xx_gpt_reset (void *opaque)
+{
+    ppc4xx_gpt_t *gpt;
+    int i;
+
+    gpt = opaque;
+    qemu_del_timer(gpt->timer);
+    gpt->oe = 0x00000000;
+    gpt->ol = 0x00000000;
+    gpt->im = 0x00000000;
+    gpt->is = 0x00000000;
+    gpt->ie = 0x00000000;
+    for (i = 0; i < 5; i++) {
+        gpt->comp[i] = 0x00000000;
+        gpt->mask[i] = 0x00000000;
+    }
+}
+
+static void ppc4xx_gpt_init(hwaddr base, qemu_irq irqs[5])
+{
+    ppc4xx_gpt_t *gpt;
+    int i;
+
+    gpt = g_malloc0(sizeof(ppc4xx_gpt_t));
+    for (i = 0; i < 5; i++) {
+        gpt->irqs[i] = irqs[i];
+    }
+    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
+    memory_region_init_io(&gpt->iomem, &gpt_ops, gpt, "gpt", 0x0d4);
+    memory_region_add_subregion(get_system_memory(), base, &gpt->iomem);
+    qemu_register_reset(ppc4xx_gpt_reset, gpt);
+}
+
+/*****************************************************************************/
+/* MAL */
+enum {
+    MAL0_CFG      = 0x180,
+    MAL0_ESR      = 0x181,
+    MAL0_IER      = 0x182,
+    MAL0_TXCASR   = 0x184,
+    MAL0_TXCARR   = 0x185,
+    MAL0_TXEOBISR = 0x186,
+    MAL0_TXDEIR   = 0x187,
+    MAL0_RXCASR   = 0x190,
+    MAL0_RXCARR   = 0x191,
+    MAL0_RXEOBISR = 0x192,
+    MAL0_RXDEIR   = 0x193,
+    MAL0_TXCTP0R  = 0x1A0,
+    MAL0_TXCTP1R  = 0x1A1,
+    MAL0_TXCTP2R  = 0x1A2,
+    MAL0_TXCTP3R  = 0x1A3,
+    MAL0_RXCTP0R  = 0x1C0,
+    MAL0_RXCTP1R  = 0x1C1,
+    MAL0_RCBS0    = 0x1E0,
+    MAL0_RCBS1    = 0x1E1,
+};
+
+typedef struct ppc40x_mal_t ppc40x_mal_t;
+struct ppc40x_mal_t {
+    qemu_irq irqs[4];
+    uint32_t cfg;
+    uint32_t esr;
+    uint32_t ier;
+    uint32_t txcasr;
+    uint32_t txcarr;
+    uint32_t txeobisr;
+    uint32_t txdeir;
+    uint32_t rxcasr;
+    uint32_t rxcarr;
+    uint32_t rxeobisr;
+    uint32_t rxdeir;
+    uint32_t txctpr[4];
+    uint32_t rxctpr[2];
+    uint32_t rcbs[2];
+};
+
+static void ppc40x_mal_reset (void *opaque);
+
+static uint32_t dcr_read_mal (void *opaque, int dcrn)
+{
+    ppc40x_mal_t *mal;
+    uint32_t ret;
+
+    mal = opaque;
+    switch (dcrn) {
+    case MAL0_CFG:
+        ret = mal->cfg;
+        break;
+    case MAL0_ESR:
+        ret = mal->esr;
+        break;
+    case MAL0_IER:
+        ret = mal->ier;
+        break;
+    case MAL0_TXCASR:
+        ret = mal->txcasr;
+        break;
+    case MAL0_TXCARR:
+        ret = mal->txcarr;
+        break;
+    case MAL0_TXEOBISR:
+        ret = mal->txeobisr;
+        break;
+    case MAL0_TXDEIR:
+        ret = mal->txdeir;
+        break;
+    case MAL0_RXCASR:
+        ret = mal->rxcasr;
+        break;
+    case MAL0_RXCARR:
+        ret = mal->rxcarr;
+        break;
+    case MAL0_RXEOBISR:
+        ret = mal->rxeobisr;
+        break;
+    case MAL0_RXDEIR:
+        ret = mal->rxdeir;
+        break;
+    case MAL0_TXCTP0R:
+        ret = mal->txctpr[0];
+        break;
+    case MAL0_TXCTP1R:
+        ret = mal->txctpr[1];
+        break;
+    case MAL0_TXCTP2R:
+        ret = mal->txctpr[2];
+        break;
+    case MAL0_TXCTP3R:
+        ret = mal->txctpr[3];
+        break;
+    case MAL0_RXCTP0R:
+        ret = mal->rxctpr[0];
+        break;
+    case MAL0_RXCTP1R:
+        ret = mal->rxctpr[1];
+        break;
+    case MAL0_RCBS0:
+        ret = mal->rcbs[0];
+        break;
+    case MAL0_RCBS1:
+        ret = mal->rcbs[1];
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_mal (void *opaque, int dcrn, uint32_t val)
+{
+    ppc40x_mal_t *mal;
+    int idx;
+
+    mal = opaque;
+    switch (dcrn) {
+    case MAL0_CFG:
+        if (val & 0x80000000)
+            ppc40x_mal_reset(mal);
+        mal->cfg = val & 0x00FFC087;
+        break;
+    case MAL0_ESR:
+        /* Read/clear */
+        mal->esr &= ~val;
+        break;
+    case MAL0_IER:
+        mal->ier = val & 0x0000001F;
+        break;
+    case MAL0_TXCASR:
+        mal->txcasr = val & 0xF0000000;
+        break;
+    case MAL0_TXCARR:
+        mal->txcarr = val & 0xF0000000;
+        break;
+    case MAL0_TXEOBISR:
+        /* Read/clear */
+        mal->txeobisr &= ~val;
+        break;
+    case MAL0_TXDEIR:
+        /* Read/clear */
+        mal->txdeir &= ~val;
+        break;
+    case MAL0_RXCASR:
+        mal->rxcasr = val & 0xC0000000;
+        break;
+    case MAL0_RXCARR:
+        mal->rxcarr = val & 0xC0000000;
+        break;
+    case MAL0_RXEOBISR:
+        /* Read/clear */
+        mal->rxeobisr &= ~val;
+        break;
+    case MAL0_RXDEIR:
+        /* Read/clear */
+        mal->rxdeir &= ~val;
+        break;
+    case MAL0_TXCTP0R:
+        idx = 0;
+        goto update_tx_ptr;
+    case MAL0_TXCTP1R:
+        idx = 1;
+        goto update_tx_ptr;
+    case MAL0_TXCTP2R:
+        idx = 2;
+        goto update_tx_ptr;
+    case MAL0_TXCTP3R:
+        idx = 3;
+    update_tx_ptr:
+        mal->txctpr[idx] = val;
+        break;
+    case MAL0_RXCTP0R:
+        idx = 0;
+        goto update_rx_ptr;
+    case MAL0_RXCTP1R:
+        idx = 1;
+    update_rx_ptr:
+        mal->rxctpr[idx] = val;
+        break;
+    case MAL0_RCBS0:
+        idx = 0;
+        goto update_rx_size;
+    case MAL0_RCBS1:
+        idx = 1;
+    update_rx_size:
+        mal->rcbs[idx] = val & 0x000000FF;
+        break;
+    }
+}
+
+static void ppc40x_mal_reset (void *opaque)
+{
+    ppc40x_mal_t *mal;
+
+    mal = opaque;
+    mal->cfg = 0x0007C000;
+    mal->esr = 0x00000000;
+    mal->ier = 0x00000000;
+    mal->rxcasr = 0x00000000;
+    mal->rxdeir = 0x00000000;
+    mal->rxeobisr = 0x00000000;
+    mal->txcasr = 0x00000000;
+    mal->txdeir = 0x00000000;
+    mal->txeobisr = 0x00000000;
+}
+
+static void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
+{
+    ppc40x_mal_t *mal;
+    int i;
+
+    mal = g_malloc0(sizeof(ppc40x_mal_t));
+    for (i = 0; i < 4; i++)
+        mal->irqs[i] = irqs[i];
+    qemu_register_reset(&ppc40x_mal_reset, mal);
+    ppc_dcr_register(env, MAL0_CFG,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_ESR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_IER,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCASR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCARR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXEOBISR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXDEIR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXCASR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXCARR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXEOBISR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXDEIR,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCTP0R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCTP1R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCTP2R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_TXCTP3R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXCTP0R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RXCTP1R,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RCBS0,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+    ppc_dcr_register(env, MAL0_RCBS1,
+                     mal, &dcr_read_mal, &dcr_write_mal);
+}
+
+/*****************************************************************************/
+/* SPR */
+void ppc40x_core_reset(PowerPCCPU *cpu)
+{
+    CPUPPCState *env = &cpu->env;
+    target_ulong dbsr;
+
+    printf("Reset PowerPC core\n");
+    cpu_interrupt(env, CPU_INTERRUPT_RESET);
+    dbsr = env->spr[SPR_40x_DBSR];
+    dbsr &= ~0x00000300;
+    dbsr |= 0x00000100;
+    env->spr[SPR_40x_DBSR] = dbsr;
+}
+
+void ppc40x_chip_reset(PowerPCCPU *cpu)
+{
+    CPUPPCState *env = &cpu->env;
+    target_ulong dbsr;
+
+    printf("Reset PowerPC chip\n");
+    cpu_interrupt(env, CPU_INTERRUPT_RESET);
+    /* XXX: TODO reset all internal peripherals */
+    dbsr = env->spr[SPR_40x_DBSR];
+    dbsr &= ~0x00000300;
+    dbsr |= 0x00000200;
+    env->spr[SPR_40x_DBSR] = dbsr;
+}
+
+void ppc40x_system_reset(PowerPCCPU *cpu)
+{
+    printf("Reset PowerPC system\n");
+    qemu_system_reset_request();
+}
+
+void store_40x_dbcr0 (CPUPPCState *env, uint32_t val)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    switch ((val >> 28) & 0x3) {
+    case 0x0:
+        /* No action */
+        break;
+    case 0x1:
+        /* Core reset */
+        ppc40x_core_reset(cpu);
+        break;
+    case 0x2:
+        /* Chip reset */
+        ppc40x_chip_reset(cpu);
+        break;
+    case 0x3:
+        /* System reset */
+        ppc40x_system_reset(cpu);
+        break;
+    }
+}
+
+/*****************************************************************************/
+/* PowerPC 405CR */
+enum {
+    PPC405CR_CPC0_PLLMR  = 0x0B0,
+    PPC405CR_CPC0_CR0    = 0x0B1,
+    PPC405CR_CPC0_CR1    = 0x0B2,
+    PPC405CR_CPC0_PSR    = 0x0B4,
+    PPC405CR_CPC0_JTAGID = 0x0B5,
+    PPC405CR_CPC0_ER     = 0x0B9,
+    PPC405CR_CPC0_FR     = 0x0BA,
+    PPC405CR_CPC0_SR     = 0x0BB,
+};
+
+enum {
+    PPC405CR_CPU_CLK   = 0,
+    PPC405CR_TMR_CLK   = 1,
+    PPC405CR_PLB_CLK   = 2,
+    PPC405CR_SDRAM_CLK = 3,
+    PPC405CR_OPB_CLK   = 4,
+    PPC405CR_EXT_CLK   = 5,
+    PPC405CR_UART_CLK  = 6,
+    PPC405CR_CLK_NB    = 7,
+};
+
+typedef struct ppc405cr_cpc_t ppc405cr_cpc_t;
+struct ppc405cr_cpc_t {
+    clk_setup_t clk_setup[PPC405CR_CLK_NB];
+    uint32_t sysclk;
+    uint32_t psr;
+    uint32_t cr0;
+    uint32_t cr1;
+    uint32_t jtagid;
+    uint32_t pllmr;
+    uint32_t er;
+    uint32_t fr;
+};
+
+static void ppc405cr_clk_setup (ppc405cr_cpc_t *cpc)
+{
+    uint64_t VCO_out, PLL_out;
+    uint32_t CPU_clk, TMR_clk, SDRAM_clk, PLB_clk, OPB_clk, EXT_clk, UART_clk;
+    int M, D0, D1, D2;
+
+    D0 = ((cpc->pllmr >> 26) & 0x3) + 1; /* CBDV */
+    if (cpc->pllmr & 0x80000000) {
+        D1 = (((cpc->pllmr >> 20) - 1) & 0xF) + 1; /* FBDV */
+        D2 = 8 - ((cpc->pllmr >> 16) & 0x7); /* FWDVA */
+        M = D0 * D1 * D2;
+        VCO_out = cpc->sysclk * M;
+        if (VCO_out < 400000000 || VCO_out > 800000000) {
+            /* PLL cannot lock */
+            cpc->pllmr &= ~0x80000000;
+            goto bypass_pll;
+        }
+        PLL_out = VCO_out / D2;
+    } else {
+        /* Bypass PLL */
+    bypass_pll:
+        M = D0;
+        PLL_out = cpc->sysclk * M;
+    }
+    CPU_clk = PLL_out;
+    if (cpc->cr1 & 0x00800000)
+        TMR_clk = cpc->sysclk; /* Should have a separate clock */
+    else
+        TMR_clk = CPU_clk;
+    PLB_clk = CPU_clk / D0;
+    SDRAM_clk = PLB_clk;
+    D0 = ((cpc->pllmr >> 10) & 0x3) + 1;
+    OPB_clk = PLB_clk / D0;
+    D0 = ((cpc->pllmr >> 24) & 0x3) + 2;
+    EXT_clk = PLB_clk / D0;
+    D0 = ((cpc->cr0 >> 1) & 0x1F) + 1;
+    UART_clk = CPU_clk / D0;
+    /* Setup CPU clocks */
+    clk_setup(&cpc->clk_setup[PPC405CR_CPU_CLK], CPU_clk);
+    /* Setup time-base clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_TMR_CLK], TMR_clk);
+    /* Setup PLB clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_PLB_CLK], PLB_clk);
+    /* Setup SDRAM clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_SDRAM_CLK], SDRAM_clk);
+    /* Setup OPB clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_OPB_CLK], OPB_clk);
+    /* Setup external clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_EXT_CLK], EXT_clk);
+    /* Setup UART clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_UART_CLK], UART_clk);
+}
+
+static uint32_t dcr_read_crcpc (void *opaque, int dcrn)
+{
+    ppc405cr_cpc_t *cpc;
+    uint32_t ret;
+
+    cpc = opaque;
+    switch (dcrn) {
+    case PPC405CR_CPC0_PLLMR:
+        ret = cpc->pllmr;
+        break;
+    case PPC405CR_CPC0_CR0:
+        ret = cpc->cr0;
+        break;
+    case PPC405CR_CPC0_CR1:
+        ret = cpc->cr1;
+        break;
+    case PPC405CR_CPC0_PSR:
+        ret = cpc->psr;
+        break;
+    case PPC405CR_CPC0_JTAGID:
+        ret = cpc->jtagid;
+        break;
+    case PPC405CR_CPC0_ER:
+        ret = cpc->er;
+        break;
+    case PPC405CR_CPC0_FR:
+        ret = cpc->fr;
+        break;
+    case PPC405CR_CPC0_SR:
+        ret = ~(cpc->er | cpc->fr) & 0xFFFF0000;
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_crcpc (void *opaque, int dcrn, uint32_t val)
+{
+    ppc405cr_cpc_t *cpc;
+
+    cpc = opaque;
+    switch (dcrn) {
+    case PPC405CR_CPC0_PLLMR:
+        cpc->pllmr = val & 0xFFF77C3F;
+        break;
+    case PPC405CR_CPC0_CR0:
+        cpc->cr0 = val & 0x0FFFFFFE;
+        break;
+    case PPC405CR_CPC0_CR1:
+        cpc->cr1 = val & 0x00800000;
+        break;
+    case PPC405CR_CPC0_PSR:
+        /* Read-only */
+        break;
+    case PPC405CR_CPC0_JTAGID:
+        /* Read-only */
+        break;
+    case PPC405CR_CPC0_ER:
+        cpc->er = val & 0xBFFC0000;
+        break;
+    case PPC405CR_CPC0_FR:
+        cpc->fr = val & 0xBFFC0000;
+        break;
+    case PPC405CR_CPC0_SR:
+        /* Read-only */
+        break;
+    }
+}
+
+static void ppc405cr_cpc_reset (void *opaque)
+{
+    ppc405cr_cpc_t *cpc;
+    int D;
+
+    cpc = opaque;
+    /* Compute PLLMR value from PSR settings */
+    cpc->pllmr = 0x80000000;
+    /* PFWD */
+    switch ((cpc->psr >> 30) & 3) {
+    case 0:
+        /* Bypass */
+        cpc->pllmr &= ~0x80000000;
+        break;
+    case 1:
+        /* Divide by 3 */
+        cpc->pllmr |= 5 << 16;
+        break;
+    case 2:
+        /* Divide by 4 */
+        cpc->pllmr |= 4 << 16;
+        break;
+    case 3:
+        /* Divide by 6 */
+        cpc->pllmr |= 2 << 16;
+        break;
+    }
+    /* PFBD */
+    D = (cpc->psr >> 28) & 3;
+    cpc->pllmr |= (D + 1) << 20;
+    /* PT   */
+    D = (cpc->psr >> 25) & 7;
+    switch (D) {
+    case 0x2:
+        cpc->pllmr |= 0x13;
+        break;
+    case 0x4:
+        cpc->pllmr |= 0x15;
+        break;
+    case 0x5:
+        cpc->pllmr |= 0x16;
+        break;
+    default:
+        break;
+    }
+    /* PDC  */
+    D = (cpc->psr >> 23) & 3;
+    cpc->pllmr |= D << 26;
+    /* ODP  */
+    D = (cpc->psr >> 21) & 3;
+    cpc->pllmr |= D << 10;
+    /* EBPD */
+    D = (cpc->psr >> 17) & 3;
+    cpc->pllmr |= D << 24;
+    cpc->cr0 = 0x0000003C;
+    cpc->cr1 = 0x2B0D8800;
+    cpc->er = 0x00000000;
+    cpc->fr = 0x00000000;
+    ppc405cr_clk_setup(cpc);
+}
+
+static void ppc405cr_clk_init (ppc405cr_cpc_t *cpc)
+{
+    int D;
+
+    /* XXX: this should be read from IO pins */
+    cpc->psr = 0x00000000; /* 8 bits ROM */
+    /* PFWD */
+    D = 0x2; /* Divide by 4 */
+    cpc->psr |= D << 30;
+    /* PFBD */
+    D = 0x1; /* Divide by 2 */
+    cpc->psr |= D << 28;
+    /* PDC */
+    D = 0x1; /* Divide by 2 */
+    cpc->psr |= D << 23;
+    /* PT */
+    D = 0x5; /* M = 16 */
+    cpc->psr |= D << 25;
+    /* ODP */
+    D = 0x1; /* Divide by 2 */
+    cpc->psr |= D << 21;
+    /* EBDP */
+    D = 0x2; /* Divide by 4 */
+    cpc->psr |= D << 17;
+}
+
+static void ppc405cr_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[7],
+                               uint32_t sysclk)
+{
+    ppc405cr_cpc_t *cpc;
+
+    cpc = g_malloc0(sizeof(ppc405cr_cpc_t));
+    memcpy(cpc->clk_setup, clk_setup,
+           PPC405CR_CLK_NB * sizeof(clk_setup_t));
+    cpc->sysclk = sysclk;
+    cpc->jtagid = 0x42051049;
+    ppc_dcr_register(env, PPC405CR_CPC0_PSR, cpc,
+                     &dcr_read_crcpc, &dcr_write_crcpc);
+    ppc_dcr_register(env, PPC405CR_CPC0_CR0, cpc,
+                     &dcr_read_crcpc, &dcr_write_crcpc);
+    ppc_dcr_register(env, PPC405CR_CPC0_CR1, cpc,
+                     &dcr_read_crcpc, &dcr_write_crcpc);
+    ppc_dcr_register(env, PPC405CR_CPC0_JTAGID, cpc,
+                     &dcr_read_crcpc, &dcr_write_crcpc);
+    ppc_dcr_register(env, PPC405CR_CPC0_PLLMR, cpc,
+                     &dcr_read_crcpc, &dcr_write_crcpc);
+    ppc_dcr_register(env, PPC405CR_CPC0_ER, cpc,
+                     &dcr_read_crcpc, &dcr_write_crcpc);
+    ppc_dcr_register(env, PPC405CR_CPC0_FR, cpc,
+                     &dcr_read_crcpc, &dcr_write_crcpc);
+    ppc_dcr_register(env, PPC405CR_CPC0_SR, cpc,
+                     &dcr_read_crcpc, &dcr_write_crcpc);
+    ppc405cr_clk_init(cpc);
+    qemu_register_reset(ppc405cr_cpc_reset, cpc);
+}
+
+CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
+                        MemoryRegion ram_memories[4],
+                        hwaddr ram_bases[4],
+                        hwaddr ram_sizes[4],
+                        uint32_t sysclk, qemu_irq **picp,
+                        int do_init)
+{
+    clk_setup_t clk_setup[PPC405CR_CLK_NB];
+    qemu_irq dma_irqs[4];
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    qemu_irq *pic, *irqs;
+
+    memset(clk_setup, 0, sizeof(clk_setup));
+    cpu = ppc4xx_init("405cr", &clk_setup[PPC405CR_CPU_CLK],
+                      &clk_setup[PPC405CR_TMR_CLK], sysclk);
+    env = &cpu->env;
+    /* Memory mapped devices registers */
+    /* PLB arbitrer */
+    ppc4xx_plb_init(env);
+    /* PLB to OPB bridge */
+    ppc4xx_pob_init(env);
+    /* OBP arbitrer */
+    ppc4xx_opba_init(0xef600600);
+    /* Universal interrupt controller */
+    irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+    irqs[PPCUIC_OUTPUT_INT] =
+        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
+    irqs[PPCUIC_OUTPUT_CINT] =
+        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
+    pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
+    *picp = pic;
+    /* SDRAM controller */
+    ppc4xx_sdram_init(env, pic[14], 1, ram_memories,
+                      ram_bases, ram_sizes, do_init);
+    /* External bus controller */
+    ppc405_ebc_init(env);
+    /* DMA controller */
+    dma_irqs[0] = pic[26];
+    dma_irqs[1] = pic[25];
+    dma_irqs[2] = pic[24];
+    dma_irqs[3] = pic[23];
+    ppc405_dma_init(env, dma_irqs);
+    /* Serial ports */
+    if (serial_hds[0] != NULL) {
+        serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
+                       DEVICE_BIG_ENDIAN);
+    }
+    if (serial_hds[1] != NULL) {
+        serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
+                       DEVICE_BIG_ENDIAN);
+    }
+    /* IIC controller */
+    ppc405_i2c_init(0xef600500, pic[2]);
+    /* GPIO */
+    ppc405_gpio_init(0xef600700);
+    /* CPU control */
+    ppc405cr_cpc_init(env, clk_setup, sysclk);
+
+    return env;
+}
+
+/*****************************************************************************/
+/* PowerPC 405EP */
+/* CPU control */
+enum {
+    PPC405EP_CPC0_PLLMR0 = 0x0F0,
+    PPC405EP_CPC0_BOOT   = 0x0F1,
+    PPC405EP_CPC0_EPCTL  = 0x0F3,
+    PPC405EP_CPC0_PLLMR1 = 0x0F4,
+    PPC405EP_CPC0_UCR    = 0x0F5,
+    PPC405EP_CPC0_SRR    = 0x0F6,
+    PPC405EP_CPC0_JTAGID = 0x0F7,
+    PPC405EP_CPC0_PCI    = 0x0F9,
+#if 0
+    PPC405EP_CPC0_ER     = xxx,
+    PPC405EP_CPC0_FR     = xxx,
+    PPC405EP_CPC0_SR     = xxx,
+#endif
+};
+
+enum {
+    PPC405EP_CPU_CLK   = 0,
+    PPC405EP_PLB_CLK   = 1,
+    PPC405EP_OPB_CLK   = 2,
+    PPC405EP_EBC_CLK   = 3,
+    PPC405EP_MAL_CLK   = 4,
+    PPC405EP_PCI_CLK   = 5,
+    PPC405EP_UART0_CLK = 6,
+    PPC405EP_UART1_CLK = 7,
+    PPC405EP_CLK_NB    = 8,
+};
+
+typedef struct ppc405ep_cpc_t ppc405ep_cpc_t;
+struct ppc405ep_cpc_t {
+    uint32_t sysclk;
+    clk_setup_t clk_setup[PPC405EP_CLK_NB];
+    uint32_t boot;
+    uint32_t epctl;
+    uint32_t pllmr[2];
+    uint32_t ucr;
+    uint32_t srr;
+    uint32_t jtagid;
+    uint32_t pci;
+    /* Clock and power management */
+    uint32_t er;
+    uint32_t fr;
+    uint32_t sr;
+};
+
+static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc)
+{
+    uint32_t CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk;
+    uint32_t UART0_clk, UART1_clk;
+    uint64_t VCO_out, PLL_out;
+    int M, D;
+
+    VCO_out = 0;
+    if ((cpc->pllmr[1] & 0x80000000) && !(cpc->pllmr[1] & 0x40000000)) {
+        M = (((cpc->pllmr[1] >> 20) - 1) & 0xF) + 1; /* FBMUL */
+#ifdef DEBUG_CLOCKS_LL
+        printf("FBMUL %01" PRIx32 " %d\n", (cpc->pllmr[1] >> 20) & 0xF, M);
+#endif
+        D = 8 - ((cpc->pllmr[1] >> 16) & 0x7); /* FWDA */
+#ifdef DEBUG_CLOCKS_LL
+        printf("FWDA %01" PRIx32 " %d\n", (cpc->pllmr[1] >> 16) & 0x7, D);
+#endif
+        VCO_out = cpc->sysclk * M * D;
+        if (VCO_out < 500000000UL || VCO_out > 1000000000UL) {
+            /* Error - unlock the PLL */
+            printf("VCO out of range %" PRIu64 "\n", VCO_out);
+#if 0
+            cpc->pllmr[1] &= ~0x80000000;
+            goto pll_bypass;
+#endif
+        }
+        PLL_out = VCO_out / D;
+        /* Pretend the PLL is locked */
+        cpc->boot |= 0x00000001;
+    } else {
+#if 0
+    pll_bypass:
+#endif
+        PLL_out = cpc->sysclk;
+        if (cpc->pllmr[1] & 0x40000000) {
+            /* Pretend the PLL is not locked */
+            cpc->boot &= ~0x00000001;
+        }
+    }
+    /* Now, compute all other clocks */
+    D = ((cpc->pllmr[0] >> 20) & 0x3) + 1; /* CCDV */
+#ifdef DEBUG_CLOCKS_LL
+    printf("CCDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 20) & 0x3, D);
+#endif
+    CPU_clk = PLL_out / D;
+    D = ((cpc->pllmr[0] >> 16) & 0x3) + 1; /* CBDV */
+#ifdef DEBUG_CLOCKS_LL
+    printf("CBDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 16) & 0x3, D);
+#endif
+    PLB_clk = CPU_clk / D;
+    D = ((cpc->pllmr[0] >> 12) & 0x3) + 1; /* OPDV */
+#ifdef DEBUG_CLOCKS_LL
+    printf("OPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 12) & 0x3, D);
+#endif
+    OPB_clk = PLB_clk / D;
+    D = ((cpc->pllmr[0] >> 8) & 0x3) + 2; /* EPDV */
+#ifdef DEBUG_CLOCKS_LL
+    printf("EPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 8) & 0x3, D);
+#endif
+    EBC_clk = PLB_clk / D;
+    D = ((cpc->pllmr[0] >> 4) & 0x3) + 1; /* MPDV */
+#ifdef DEBUG_CLOCKS_LL
+    printf("MPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 4) & 0x3, D);
+#endif
+    MAL_clk = PLB_clk / D;
+    D = (cpc->pllmr[0] & 0x3) + 1; /* PPDV */
+#ifdef DEBUG_CLOCKS_LL
+    printf("PPDV %01" PRIx32 " %d\n", cpc->pllmr[0] & 0x3, D);
+#endif
+    PCI_clk = PLB_clk / D;
+    D = ((cpc->ucr - 1) & 0x7F) + 1; /* U0DIV */
+#ifdef DEBUG_CLOCKS_LL
+    printf("U0DIV %01" PRIx32 " %d\n", cpc->ucr & 0x7F, D);
+#endif
+    UART0_clk = PLL_out / D;
+    D = (((cpc->ucr >> 8) - 1) & 0x7F) + 1; /* U1DIV */
+#ifdef DEBUG_CLOCKS_LL
+    printf("U1DIV %01" PRIx32 " %d\n", (cpc->ucr >> 8) & 0x7F, D);
+#endif
+    UART1_clk = PLL_out / D;
+#ifdef DEBUG_CLOCKS
+    printf("Setup PPC405EP clocks - sysclk %" PRIu32 " VCO %" PRIu64
+           " PLL out %" PRIu64 " Hz\n", cpc->sysclk, VCO_out, PLL_out);
+    printf("CPU %" PRIu32 " PLB %" PRIu32 " OPB %" PRIu32 " EBC %" PRIu32
+           " MAL %" PRIu32 " PCI %" PRIu32 " UART0 %" PRIu32
+           " UART1 %" PRIu32 "\n",
+           CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk,
+           UART0_clk, UART1_clk);
+#endif
+    /* Setup CPU clocks */
+    clk_setup(&cpc->clk_setup[PPC405EP_CPU_CLK], CPU_clk);
+    /* Setup PLB clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_PLB_CLK], PLB_clk);
+    /* Setup OPB clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_OPB_CLK], OPB_clk);
+    /* Setup external clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_EBC_CLK], EBC_clk);
+    /* Setup MAL clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_MAL_CLK], MAL_clk);
+    /* Setup PCI clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_PCI_CLK], PCI_clk);
+    /* Setup UART0 clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_UART0_CLK], UART0_clk);
+    /* Setup UART1 clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_UART1_CLK], UART1_clk);
+}
+
+static uint32_t dcr_read_epcpc (void *opaque, int dcrn)
+{
+    ppc405ep_cpc_t *cpc;
+    uint32_t ret;
+
+    cpc = opaque;
+    switch (dcrn) {
+    case PPC405EP_CPC0_BOOT:
+        ret = cpc->boot;
+        break;
+    case PPC405EP_CPC0_EPCTL:
+        ret = cpc->epctl;
+        break;
+    case PPC405EP_CPC0_PLLMR0:
+        ret = cpc->pllmr[0];
+        break;
+    case PPC405EP_CPC0_PLLMR1:
+        ret = cpc->pllmr[1];
+        break;
+    case PPC405EP_CPC0_UCR:
+        ret = cpc->ucr;
+        break;
+    case PPC405EP_CPC0_SRR:
+        ret = cpc->srr;
+        break;
+    case PPC405EP_CPC0_JTAGID:
+        ret = cpc->jtagid;
+        break;
+    case PPC405EP_CPC0_PCI:
+        ret = cpc->pci;
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_epcpc (void *opaque, int dcrn, uint32_t val)
+{
+    ppc405ep_cpc_t *cpc;
+
+    cpc = opaque;
+    switch (dcrn) {
+    case PPC405EP_CPC0_BOOT:
+        /* Read-only register */
+        break;
+    case PPC405EP_CPC0_EPCTL:
+        /* Don't care for now */
+        cpc->epctl = val & 0xC00000F3;
+        break;
+    case PPC405EP_CPC0_PLLMR0:
+        cpc->pllmr[0] = val & 0x00633333;
+        ppc405ep_compute_clocks(cpc);
+        break;
+    case PPC405EP_CPC0_PLLMR1:
+        cpc->pllmr[1] = val & 0xC0F73FFF;
+        ppc405ep_compute_clocks(cpc);
+        break;
+    case PPC405EP_CPC0_UCR:
+        /* UART control - don't care for now */
+        cpc->ucr = val & 0x003F7F7F;
+        break;
+    case PPC405EP_CPC0_SRR:
+        cpc->srr = val;
+        break;
+    case PPC405EP_CPC0_JTAGID:
+        /* Read-only */
+        break;
+    case PPC405EP_CPC0_PCI:
+        cpc->pci = val;
+        break;
+    }
+}
+
+static void ppc405ep_cpc_reset (void *opaque)
+{
+    ppc405ep_cpc_t *cpc = opaque;
+
+    cpc->boot = 0x00000010;     /* Boot from PCI - IIC EEPROM disabled */
+    cpc->epctl = 0x00000000;
+    cpc->pllmr[0] = 0x00011010;
+    cpc->pllmr[1] = 0x40000000;
+    cpc->ucr = 0x00000000;
+    cpc->srr = 0x00040000;
+    cpc->pci = 0x00000000;
+    cpc->er = 0x00000000;
+    cpc->fr = 0x00000000;
+    cpc->sr = 0x00000000;
+    ppc405ep_compute_clocks(cpc);
+}
+
+/* XXX: sysclk should be between 25 and 100 MHz */
+static void ppc405ep_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[8],
+                               uint32_t sysclk)
+{
+    ppc405ep_cpc_t *cpc;
+
+    cpc = g_malloc0(sizeof(ppc405ep_cpc_t));
+    memcpy(cpc->clk_setup, clk_setup,
+           PPC405EP_CLK_NB * sizeof(clk_setup_t));
+    cpc->jtagid = 0x20267049;
+    cpc->sysclk = sysclk;
+    qemu_register_reset(&ppc405ep_cpc_reset, cpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_BOOT, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_EPCTL, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_PLLMR0, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_PLLMR1, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_UCR, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_SRR, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_JTAGID, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_PCI, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+#if 0
+    ppc_dcr_register(env, PPC405EP_CPC0_ER, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_FR, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+    ppc_dcr_register(env, PPC405EP_CPC0_SR, cpc,
+                     &dcr_read_epcpc, &dcr_write_epcpc);
+#endif
+}
+
+CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
+                        MemoryRegion ram_memories[2],
+                        hwaddr ram_bases[2],
+                        hwaddr ram_sizes[2],
+                        uint32_t sysclk, qemu_irq **picp,
+                        int do_init)
+{
+    clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup;
+    qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4];
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    qemu_irq *pic, *irqs;
+
+    memset(clk_setup, 0, sizeof(clk_setup));
+    /* init CPUs */
+    cpu = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
+                      &tlb_clk_setup, sysclk);
+    env = &cpu->env;
+    clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
+    clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque;
+    /* Internal devices init */
+    /* Memory mapped devices registers */
+    /* PLB arbitrer */
+    ppc4xx_plb_init(env);
+    /* PLB to OPB bridge */
+    ppc4xx_pob_init(env);
+    /* OBP arbitrer */
+    ppc4xx_opba_init(0xef600600);
+    /* Initialize timers */
+    ppc_booke_timers_init(cpu, sysclk, 0);
+    /* Universal interrupt controller */
+    irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+    irqs[PPCUIC_OUTPUT_INT] =
+        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
+    irqs[PPCUIC_OUTPUT_CINT] =
+        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
+    pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
+    *picp = pic;
+    /* SDRAM controller */
+	/* XXX 405EP has no ECC interrupt */
+    ppc4xx_sdram_init(env, pic[17], 2, ram_memories,
+                      ram_bases, ram_sizes, do_init);
+    /* External bus controller */
+    ppc405_ebc_init(env);
+    /* DMA controller */
+    dma_irqs[0] = pic[5];
+    dma_irqs[1] = pic[6];
+    dma_irqs[2] = pic[7];
+    dma_irqs[3] = pic[8];
+    ppc405_dma_init(env, dma_irqs);
+    /* IIC controller */
+    ppc405_i2c_init(0xef600500, pic[2]);
+    /* GPIO */
+    ppc405_gpio_init(0xef600700);
+    /* Serial ports */
+    if (serial_hds[0] != NULL) {
+        serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
+                       DEVICE_BIG_ENDIAN);
+    }
+    if (serial_hds[1] != NULL) {
+        serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
+                       DEVICE_BIG_ENDIAN);
+    }
+    /* OCM */
+    ppc405_ocm_init(env);
+    /* GPT */
+    gpt_irqs[0] = pic[19];
+    gpt_irqs[1] = pic[20];
+    gpt_irqs[2] = pic[21];
+    gpt_irqs[3] = pic[22];
+    gpt_irqs[4] = pic[23];
+    ppc4xx_gpt_init(0xef600000, gpt_irqs);
+    /* PCI */
+    /* Uses pic[3], pic[16], pic[18] */
+    /* MAL */
+    mal_irqs[0] = pic[11];
+    mal_irqs[1] = pic[12];
+    mal_irqs[2] = pic[13];
+    mal_irqs[3] = pic[14];
+    ppc405_mal_init(env, mal_irqs);
+    /* Ethernet */
+    /* Uses pic[9], pic[15], pic[17] */
+    /* CPU control */
+    ppc405ep_cpc_init(env, clk_setup, sysclk);
+
+    return env;
+}
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
new file mode 100644
index 0000000..66911b5
--- /dev/null
+++ b/hw/ppc/ppc440_bamboo.c
@@ -0,0 +1,306 @@
+/*
+ * QEMU PowerPC 440 Bamboo board emulation
+ *
+ * Copyright 2007 IBM Corporation.
+ * Authors:
+ *	Jerone Young <jyoung5 at us.ibm.com>
+ *	Christian Ehrhardt <ehrhardt at linux.vnet.ibm.com>
+ *	Hollis Blanchard <hollisb at us.ibm.com>
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+
+#include "config.h"
+#include "qemu-common.h"
+#include "net/net.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/boards.h"
+#include "sysemu/kvm.h"
+#include "kvm_ppc.h"
+#include "sysemu/device_tree.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "exec/address-spaces.h"
+#include "hw/serial.h"
+#include "hw/ppc.h"
+#include "hw/ppc405.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+
+#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
+
+/* from u-boot */
+#define KERNEL_ADDR  0x1000000
+#define FDT_ADDR     0x1800000
+#define RAMDISK_ADDR 0x1900000
+
+#define PPC440EP_PCI_CONFIG     0xeec00000
+#define PPC440EP_PCI_INTACK     0xeed00000
+#define PPC440EP_PCI_SPECIAL    0xeed00000
+#define PPC440EP_PCI_REGS       0xef400000
+#define PPC440EP_PCI_IO         0xe8000000
+#define PPC440EP_PCI_IOLEN      0x00010000
+
+#define PPC440EP_SDRAM_NR_BANKS 4
+
+static const unsigned int ppc440ep_sdram_bank_sizes[] = {
+    256<<20, 128<<20, 64<<20, 32<<20, 16<<20, 8<<20, 0
+};
+
+static hwaddr entry;
+
+static int bamboo_load_device_tree(hwaddr addr,
+                                     uint32_t ramsize,
+                                     hwaddr initrd_base,
+                                     hwaddr initrd_size,
+                                     const char *kernel_cmdline)
+{
+    int ret = -1;
+#ifdef CONFIG_FDT
+    uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) };
+    char *filename;
+    int fdt_size;
+    void *fdt;
+    uint32_t tb_freq = 400000000;
+    uint32_t clock_freq = 400000000;
+
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
+    if (!filename) {
+        goto out;
+    }
+    fdt = load_device_tree(filename, &fdt_size);
+    g_free(filename);
+    if (fdt == NULL) {
+        goto out;
+    }
+
+    /* Manipulate device tree in memory. */
+
+    ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
+                               sizeof(mem_reg_property));
+    if (ret < 0)
+        fprintf(stderr, "couldn't set /memory/reg\n");
+
+    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
+                                    initrd_base);
+    if (ret < 0)
+        fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
+
+    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
+                                    (initrd_base + initrd_size));
+    if (ret < 0)
+        fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
+
+    ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
+                                      kernel_cmdline);
+    if (ret < 0)
+        fprintf(stderr, "couldn't set /chosen/bootargs\n");
+
+    /* Copy data from the host device tree into the guest. Since the guest can
+     * directly access the timebase without host involvement, we must expose
+     * the correct frequencies. */
+    if (kvm_enabled()) {
+        tb_freq = kvmppc_get_tbfreq();
+        clock_freq = kvmppc_get_clockfreq();
+    }
+
+    qemu_devtree_setprop_cell(fdt, "/cpus/cpu at 0", "clock-frequency",
+                              clock_freq);
+    qemu_devtree_setprop_cell(fdt, "/cpus/cpu at 0", "timebase-frequency",
+                              tb_freq);
+
+    ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
+    g_free(fdt);
+
+out:
+#endif
+
+    return ret;
+}
+
+/* Create reset TLB entries for BookE, spanning the 32bit addr space.  */
+static void mmubooke_create_initial_mapping(CPUPPCState *env,
+                                     target_ulong va,
+                                     hwaddr pa)
+{
+    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
+
+    tlb->attr = 0;
+    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
+    tlb->size = 1 << 31; /* up to 0x80000000  */
+    tlb->EPN = va & TARGET_PAGE_MASK;
+    tlb->RPN = pa & TARGET_PAGE_MASK;
+    tlb->PID = 0;
+
+    tlb = &env->tlb.tlbe[1];
+    tlb->attr = 0;
+    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
+    tlb->size = 1 << 31; /* up to 0xffffffff  */
+    tlb->EPN = 0x80000000 & TARGET_PAGE_MASK;
+    tlb->RPN = 0x80000000 & TARGET_PAGE_MASK;
+    tlb->PID = 0;
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+
+    cpu_reset(CPU(cpu));
+    env->gpr[1] = (16<<20) - 8;
+    env->gpr[3] = FDT_ADDR;
+    env->nip = entry;
+
+    /* Create a mapping for the kernel.  */
+    mmubooke_create_initial_mapping(env, 0, 0);
+}
+
+static void bamboo_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram_memories
+        = g_malloc(PPC440EP_SDRAM_NR_BANKS * sizeof(*ram_memories));
+    hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS];
+    hwaddr ram_sizes[PPC440EP_SDRAM_NR_BANKS];
+    qemu_irq *pic;
+    qemu_irq *irqs;
+    PCIBus *pcibus;
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    uint64_t elf_entry;
+    uint64_t elf_lowaddr;
+    hwaddr loadaddr = 0;
+    target_long initrd_size = 0;
+    DeviceState *dev;
+    int success;
+    int i;
+
+    /* Setup CPU. */
+    if (cpu_model == NULL) {
+        cpu_model = "440EP";
+    }
+    cpu = cpu_ppc_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to initialize CPU!\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    qemu_register_reset(main_cpu_reset, cpu);
+    ppc_booke_timers_init(cpu, 400000000, 0);
+    ppc_dcr_init(env, NULL, NULL);
+
+    /* interrupt controller */
+    irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+    irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
+    irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
+    pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
+
+    /* SDRAM controller */
+    memset(ram_bases, 0, sizeof(ram_bases));
+    memset(ram_sizes, 0, sizeof(ram_sizes));
+    ram_size = ppc4xx_sdram_adjust(ram_size, PPC440EP_SDRAM_NR_BANKS,
+                                   ram_memories,
+                                   ram_bases, ram_sizes,
+                                   ppc440ep_sdram_bank_sizes);
+    /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
+    ppc4xx_sdram_init(env, pic[14], PPC440EP_SDRAM_NR_BANKS, ram_memories,
+                      ram_bases, ram_sizes, 1);
+
+    /* PCI */
+    dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST_BRIDGE,
+                                PPC440EP_PCI_CONFIG,
+                                pic[pci_irq_nrs[0]], pic[pci_irq_nrs[1]],
+                                pic[pci_irq_nrs[2]], pic[pci_irq_nrs[3]],
+                                NULL);
+    pcibus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
+    if (!pcibus) {
+        fprintf(stderr, "couldn't create PCI controller!\n");
+        exit(1);
+    }
+
+    isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN);
+
+    if (serial_hds[0] != NULL) {
+        serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
+                       DEVICE_BIG_ENDIAN);
+    }
+    if (serial_hds[1] != NULL) {
+        serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
+                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
+                       DEVICE_BIG_ENDIAN);
+    }
+
+    if (pcibus) {
+        /* Register network interfaces. */
+        for (i = 0; i < nb_nics; i++) {
+            /* There are no PCI NICs on the Bamboo board, but there are
+             * PCI slots, so we can pick whatever default model we want. */
+            pci_nic_init_nofail(&nd_table[i], "e1000", NULL);
+        }
+    }
+
+    /* Load kernel. */
+    if (kernel_filename) {
+        success = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
+        if (success < 0) {
+            success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+                               &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
+            entry = elf_entry;
+            loadaddr = elf_lowaddr;
+        }
+        /* XXX try again as binary */
+        if (success < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+    }
+
+    /* Load initrd. */
+    if (initrd_filename) {
+        initrd_size = load_image_targphys(initrd_filename, RAMDISK_ADDR,
+                                          ram_size - RAMDISK_ADDR);
+
+        if (initrd_size < 0) {
+            fprintf(stderr, "qemu: could not load ram disk '%s' at %x\n",
+                    initrd_filename, RAMDISK_ADDR);
+            exit(1);
+        }
+    }
+
+    /* If we're loading a kernel directly, we must load the device tree too. */
+    if (kernel_filename) {
+        if (bamboo_load_device_tree(FDT_ADDR, ram_size, RAMDISK_ADDR,
+                                    initrd_size, kernel_cmdline) < 0) {
+            fprintf(stderr, "couldn't load device tree\n");
+            exit(1);
+        }
+    }
+
+    if (kvm_enabled())
+        kvmppc_init();
+}
+
+static QEMUMachine bamboo_machine = {
+    .name = "bamboo",
+    .desc = "bamboo",
+    .init = bamboo_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void bamboo_machine_init(void)
+{
+    qemu_register_machine(&bamboo_machine);
+}
+
+machine_init(bamboo_machine_init);
diff --git a/hw/ppc/ppc_booke.c b/hw/ppc/ppc_booke.c
new file mode 100644
index 0000000..30375c0
--- /dev/null
+++ b/hw/ppc/ppc_booke.c
@@ -0,0 +1,273 @@
+/*
+ * QEMU PowerPC Booke hardware System Emulator
+ *
+ * Copyright (c) 2011 AdaCore
+ *
+ * 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/hw.h"
+#include "hw/ppc.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "hw/nvram.h"
+#include "qemu/log.h"
+#include "hw/loader.h"
+
+
+/* Timer Control Register */
+
+#define TCR_WP_SHIFT  30        /* Watchdog Timer Period */
+#define TCR_WP_MASK   (0x3 << TCR_WP_SHIFT)
+#define TCR_WRC_SHIFT 28        /* Watchdog Timer Reset Control */
+#define TCR_WRC_MASK  (0x3 << TCR_WRC_SHIFT)
+#define TCR_WIE       (1 << 27) /* Watchdog Timer Interrupt Enable */
+#define TCR_DIE       (1 << 26) /* Decrementer Interrupt Enable */
+#define TCR_FP_SHIFT  24        /* Fixed-Interval Timer Period */
+#define TCR_FP_MASK   (0x3 << TCR_FP_SHIFT)
+#define TCR_FIE       (1 << 23) /* Fixed-Interval Timer Interrupt Enable */
+#define TCR_ARE       (1 << 22) /* Auto-Reload Enable */
+
+/* Timer Control Register (e500 specific fields) */
+
+#define TCR_E500_FPEXT_SHIFT 13 /* Fixed-Interval Timer Period Extension */
+#define TCR_E500_FPEXT_MASK  (0xf << TCR_E500_FPEXT_SHIFT)
+#define TCR_E500_WPEXT_SHIFT 17 /* Watchdog Timer Period Extension */
+#define TCR_E500_WPEXT_MASK  (0xf << TCR_E500_WPEXT_SHIFT)
+
+/* Timer Status Register  */
+
+#define TSR_FIS       (1 << 26) /* Fixed-Interval Timer Interrupt Status */
+#define TSR_DIS       (1 << 27) /* Decrementer Interrupt Status */
+#define TSR_WRS_SHIFT 28        /* Watchdog Timer Reset Status */
+#define TSR_WRS_MASK  (0x3 << TSR_WRS_SHIFT)
+#define TSR_WIS       (1 << 30) /* Watchdog Timer Interrupt Status */
+#define TSR_ENW       (1 << 31) /* Enable Next Watchdog Timer */
+
+typedef struct booke_timer_t booke_timer_t;
+struct booke_timer_t {
+
+    uint64_t fit_next;
+    struct QEMUTimer *fit_timer;
+
+    uint64_t wdt_next;
+    struct QEMUTimer *wdt_timer;
+
+    uint32_t flags;
+};
+
+static void booke_update_irq(PowerPCCPU *cpu)
+{
+    CPUPPCState *env = &cpu->env;
+
+    ppc_set_irq(cpu, PPC_INTERRUPT_DECR,
+                (env->spr[SPR_BOOKE_TSR] & TSR_DIS
+                 && env->spr[SPR_BOOKE_TCR] & TCR_DIE));
+
+    ppc_set_irq(cpu, PPC_INTERRUPT_WDT,
+                (env->spr[SPR_BOOKE_TSR] & TSR_WIS
+                 && env->spr[SPR_BOOKE_TCR] & TCR_WIE));
+
+    ppc_set_irq(cpu, PPC_INTERRUPT_FIT,
+                (env->spr[SPR_BOOKE_TSR] & TSR_FIS
+                 && env->spr[SPR_BOOKE_TCR] & TCR_FIE));
+}
+
+/* Return the location of the bit of time base at which the FIT will raise an
+   interrupt */
+static uint8_t booke_get_fit_target(CPUPPCState *env, ppc_tb_t *tb_env)
+{
+    uint8_t fp = (env->spr[SPR_BOOKE_TCR] & TCR_FP_MASK) >> TCR_FP_SHIFT;
+
+    if (tb_env->flags & PPC_TIMER_E500) {
+        /* e500 Fixed-interval timer period extension */
+        uint32_t fpext = (env->spr[SPR_BOOKE_TCR] & TCR_E500_FPEXT_MASK)
+            >> TCR_E500_FPEXT_SHIFT;
+        fp = 63 - (fp | fpext << 2);
+    } else {
+        fp = env->fit_period[fp];
+    }
+
+    return fp;
+}
+
+/* Return the location of the bit of time base at which the WDT will raise an
+   interrupt */
+static uint8_t booke_get_wdt_target(CPUPPCState *env, ppc_tb_t *tb_env)
+{
+    uint8_t wp = (env->spr[SPR_BOOKE_TCR] & TCR_WP_MASK) >> TCR_WP_SHIFT;
+
+    if (tb_env->flags & PPC_TIMER_E500) {
+        /* e500 Watchdog timer period extension */
+        uint32_t wpext = (env->spr[SPR_BOOKE_TCR] & TCR_E500_WPEXT_MASK)
+            >> TCR_E500_WPEXT_SHIFT;
+        wp = 63 - (wp | wpext << 2);
+    } else {
+        wp = env->wdt_period[wp];
+    }
+
+    return wp;
+}
+
+static void booke_update_fixed_timer(CPUPPCState         *env,
+                                     uint8_t           target_bit,
+                                     uint64_t          *next,
+                                     struct QEMUTimer *timer)
+{
+    ppc_tb_t *tb_env = env->tb_env;
+    uint64_t lapse;
+    uint64_t tb;
+    uint64_t period = 1 << (target_bit + 1);
+    uint64_t now;
+
+    now = qemu_get_clock_ns(vm_clock);
+    tb  = cpu_ppc_get_tb(tb_env, now, tb_env->tb_offset);
+
+    lapse = period - ((tb - (1 << target_bit)) & (period - 1));
+
+    *next = now + muldiv64(lapse, get_ticks_per_sec(), tb_env->tb_freq);
+
+    /* XXX: If expire time is now. We can't run the callback because we don't
+     * have access to it. So we just set the timer one nanosecond later.
+     */
+
+    if (*next == now) {
+        (*next)++;
+    }
+
+    qemu_mod_timer(timer, *next);
+}
+
+static void booke_decr_cb(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+
+    env->spr[SPR_BOOKE_TSR] |= TSR_DIS;
+    booke_update_irq(cpu);
+
+    if (env->spr[SPR_BOOKE_TCR] & TCR_ARE) {
+        /* Auto Reload */
+        cpu_ppc_store_decr(env, env->spr[SPR_BOOKE_DECAR]);
+    }
+}
+
+static void booke_fit_cb(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+    ppc_tb_t *tb_env;
+    booke_timer_t *booke_timer;
+
+    tb_env = env->tb_env;
+    booke_timer = tb_env->opaque;
+    env->spr[SPR_BOOKE_TSR] |= TSR_FIS;
+
+    booke_update_irq(cpu);
+
+    booke_update_fixed_timer(env,
+                             booke_get_fit_target(env, tb_env),
+                             &booke_timer->fit_next,
+                             booke_timer->fit_timer);
+}
+
+static void booke_wdt_cb(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+    ppc_tb_t *tb_env;
+    booke_timer_t *booke_timer;
+
+    tb_env = env->tb_env;
+    booke_timer = tb_env->opaque;
+
+    /* TODO: There's lots of complicated stuff to do here */
+
+    booke_update_irq(cpu);
+
+    booke_update_fixed_timer(env,
+                             booke_get_wdt_target(env, tb_env),
+                             &booke_timer->wdt_next,
+                             booke_timer->wdt_timer);
+}
+
+void store_booke_tsr(CPUPPCState *env, target_ulong val)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+
+    env->spr[SPR_BOOKE_TSR] &= ~val;
+    booke_update_irq(cpu);
+}
+
+void store_booke_tcr(CPUPPCState *env, target_ulong val)
+{
+    PowerPCCPU *cpu = ppc_env_get_cpu(env);
+    ppc_tb_t *tb_env = env->tb_env;
+    booke_timer_t *booke_timer = tb_env->opaque;
+
+    tb_env = env->tb_env;
+    env->spr[SPR_BOOKE_TCR] = val;
+
+    booke_update_irq(cpu);
+
+    booke_update_fixed_timer(env,
+                             booke_get_fit_target(env, tb_env),
+                             &booke_timer->fit_next,
+                             booke_timer->fit_timer);
+
+    booke_update_fixed_timer(env,
+                             booke_get_wdt_target(env, tb_env),
+                             &booke_timer->wdt_next,
+                             booke_timer->wdt_timer);
+
+}
+
+static void ppc_booke_timer_reset_handle(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+
+    env->spr[SPR_BOOKE_TSR] = 0;
+    env->spr[SPR_BOOKE_TCR] = 0;
+
+    booke_update_irq(cpu);
+}
+
+void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags)
+{
+    ppc_tb_t *tb_env;
+    booke_timer_t *booke_timer;
+
+    tb_env      = g_malloc0(sizeof(ppc_tb_t));
+    booke_timer = g_malloc0(sizeof(booke_timer_t));
+
+    cpu->env.tb_env = tb_env;
+    tb_env->flags = flags | PPC_TIMER_BOOKE | PPC_DECR_ZERO_TRIGGERED;
+
+    tb_env->tb_freq    = freq;
+    tb_env->decr_freq  = freq;
+    tb_env->opaque     = booke_timer;
+    tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &booke_decr_cb, cpu);
+
+    booke_timer->fit_timer =
+        qemu_new_timer_ns(vm_clock, &booke_fit_cb, cpu);
+    booke_timer->wdt_timer =
+        qemu_new_timer_ns(vm_clock, &booke_wdt_cb, cpu);
+
+    qemu_register_reset(ppc_booke_timer_reset_handle, cpu);
+}
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
new file mode 100644
index 0000000..2709c66
--- /dev/null
+++ b/hw/ppc/spapr.c
@@ -0,0 +1,963 @@
+/*
+ * 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/sysemu.h"
+#include "hw/hw.h"
+#include "elf.h"
+#include "net/net.h"
+#include "sysemu/blockdev.h"
+#include "sysemu/cpus.h"
+#include "sysemu/kvm.h"
+#include "kvm_ppc.h"
+
+#include "hw/boards.h"
+#include "hw/ppc.h"
+#include "hw/loader.h"
+
+#include "hw/spapr.h"
+#include "hw/spapr_vio.h"
+#include "hw/spapr_pci.h"
+#include "hw/xics.h"
+#include "hw/pci/msi.h"
+
+#include "sysemu/kvm.h"
+#include "kvm_ppc.h"
+#include "hw/pci/pci.h"
+
+#include "exec/address-spaces.h"
+#include "hw/usb.h"
+#include "qemu/config-file.h"
+
+#include <libfdt.h>
+
+/* SLOF memory layout:
+ *
+ * SLOF raw image loaded at 0, copies its romfs right below the flat
+ * device-tree, then position SLOF itself 31M below that
+ *
+ * So we set FW_OVERHEAD to 40MB which should account for all of that
+ * and more
+ *
+ * We load our kernel at 4M, leaving space for SLOF initial image
+ */
+#define FDT_MAX_SIZE            0x10000
+#define RTAS_MAX_SIZE           0x10000
+#define FW_MAX_SIZE             0x400000
+#define FW_FILE_NAME            "slof.bin"
+#define FW_OVERHEAD             0x2800000
+#define KERNEL_LOAD_ADDR        FW_MAX_SIZE
+
+#define MIN_RMA_SLOF            128UL
+
+#define TIMEBASE_FREQ           512000000ULL
+
+#define MAX_CPUS                256
+#define XICS_IRQS               1024
+
+#define PHANDLE_XICP            0x00001111
+
+#define HTAB_SIZE(spapr)        (1ULL << ((spapr)->htab_shift))
+
+sPAPREnvironment *spapr;
+
+int spapr_allocate_irq(int hint, bool lsi)
+{
+    int irq;
+
+    if (hint) {
+        irq = hint;
+        /* FIXME: we should probably check for collisions somehow */
+    } else {
+        irq = spapr->next_irq++;
+    }
+
+    /* Configure irq type */
+    if (!xics_get_qirq(spapr->icp, irq)) {
+        return 0;
+    }
+
+    xics_set_irq_type(spapr->icp, irq, lsi);
+
+    return irq;
+}
+
+/* Allocate block of consequtive IRQs, returns a number of the first */
+int spapr_allocate_irq_block(int num, bool lsi)
+{
+    int first = -1;
+    int i;
+
+    for (i = 0; i < num; ++i) {
+        int irq;
+
+        irq = spapr_allocate_irq(0, lsi);
+        if (!irq) {
+            return -1;
+        }
+
+        if (0 == i) {
+            first = irq;
+        }
+
+        /* If the above doesn't create a consecutive block then that's
+         * an internal bug */
+        assert(irq == (first + i));
+    }
+
+    return first;
+}
+
+static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
+{
+    int ret = 0, offset;
+    CPUPPCState *env;
+    CPUState *cpu;
+    char cpu_model[32];
+    int smt = kvmppc_smt_threads();
+    uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
+
+    assert(spapr->cpu_model);
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        cpu = CPU(ppc_env_get_cpu(env));
+        uint32_t associativity[] = {cpu_to_be32(0x5),
+                                    cpu_to_be32(0x0),
+                                    cpu_to_be32(0x0),
+                                    cpu_to_be32(0x0),
+                                    cpu_to_be32(cpu->numa_node),
+                                    cpu_to_be32(cpu->cpu_index)};
+
+        if ((cpu->cpu_index % smt) != 0) {
+            continue;
+        }
+
+        snprintf(cpu_model, 32, "/cpus/%s@%x", spapr->cpu_model,
+                 cpu->cpu_index);
+
+        offset = fdt_path_offset(fdt, cpu_model);
+        if (offset < 0) {
+            return offset;
+        }
+
+        if (nb_numa_nodes > 1) {
+            ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity,
+                              sizeof(associativity));
+            if (ret < 0) {
+                return ret;
+            }
+        }
+
+        ret = fdt_setprop(fdt, offset, "ibm,pft-size",
+                          pft_size_prop, sizeof(pft_size_prop));
+        if (ret < 0) {
+            return ret;
+        }
+    }
+    return ret;
+}
+
+
+static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop,
+                                     size_t maxsize)
+{
+    size_t maxcells = maxsize / sizeof(uint32_t);
+    int i, j, count;
+    uint32_t *p = prop;
+
+    for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
+        struct ppc_one_seg_page_size *sps = &env->sps.sps[i];
+
+        if (!sps->page_shift) {
+            break;
+        }
+        for (count = 0; count < PPC_PAGE_SIZES_MAX_SZ; count++) {
+            if (sps->enc[count].page_shift == 0) {
+                break;
+            }
+        }
+        if ((p - prop) >= (maxcells - 3 - count * 2)) {
+            break;
+        }
+        *(p++) = cpu_to_be32(sps->page_shift);
+        *(p++) = cpu_to_be32(sps->slb_enc);
+        *(p++) = cpu_to_be32(count);
+        for (j = 0; j < count; j++) {
+            *(p++) = cpu_to_be32(sps->enc[j].page_shift);
+            *(p++) = cpu_to_be32(sps->enc[j].pte_enc);
+        }
+    }
+
+    return (p - prop) * sizeof(uint32_t);
+}
+
+#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)
+
+
+static void *spapr_create_fdt_skel(const char *cpu_model,
+                                   hwaddr initrd_base,
+                                   hwaddr initrd_size,
+                                   hwaddr kernel_size,
+                                   const char *boot_device,
+                                   const char *kernel_cmdline,
+                                   uint32_t epow_irq)
+{
+    void *fdt;
+    CPUPPCState *env;
+    uint32_t start_prop = cpu_to_be32(initrd_base);
+    uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
+    char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
+        "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk";
+    char qemu_hypertas_prop[] = "hcall-memop1";
+    uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
+    uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
+    char *modelname;
+    int i, smt = kvmppc_smt_threads();
+    unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
+
+    fdt = g_malloc0(FDT_MAX_SIZE);
+    _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
+
+    if (kernel_size) {
+        _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR, kernel_size)));
+    }
+    if (initrd_size) {
+        _FDT((fdt_add_reservemap_entry(fdt, initrd_base, initrd_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", "IBM pSeries (emulated by qemu)")));
+
+    _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
+    _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
+
+    /* /chosen */
+    _FDT((fdt_begin_node(fdt, "chosen")));
+
+    /* Set Form1_affinity */
+    _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
+
+    _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))));
+    if (kernel_size) {
+        uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
+                              cpu_to_be64(kernel_size) };
+
+        _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
+    }
+    if (boot_device) {
+        _FDT((fdt_property_string(fdt, "qemu,boot-device", boot_device)));
+    }
+    _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width)));
+    _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height)));
+    _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth)));
+
+    _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 = g_strdup(cpu_model);
+
+    for (i = 0; i < strlen(modelname); i++) {
+        modelname[i] = toupper(modelname[i]);
+    }
+
+    /* This is needed during FDT finalization */
+    spapr->cpu_model = g_strdup(modelname);
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        CPUState *cpu = CPU(ppc_env_get_cpu(env));
+        int index = cpu->cpu_index;
+        uint32_t servers_prop[smp_threads];
+        uint32_t gservers_prop[smp_threads * 2];
+        char *nodename;
+        uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
+                           0xffffffff, 0xffffffff};
+        uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ;
+        uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000;
+        uint32_t page_sizes_prop[64];
+        size_t page_sizes_prop_size;
+
+        if ((index % smt) != 0) {
+            continue;
+        }
+
+        nodename = g_strdup_printf("%s@%x", modelname, index);
+
+        _FDT((fdt_begin_node(fdt, nodename)));
+
+        g_free(nodename);
+
+        _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])));
+        _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", tbfreq)));
+        _FDT((fdt_property_cell(fdt, "clock-frequency", cpufreq)));
+        _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)));
+
+        /* Build interrupt servers and gservers properties */
+        for (i = 0; i < smp_threads; i++) {
+            servers_prop[i] = cpu_to_be32(index + i);
+            /* Hack, direct the group queues back to cpu 0 */
+            gservers_prop[i*2] = cpu_to_be32(index + i);
+            gservers_prop[i*2 + 1] = 0;
+        }
+        _FDT((fdt_property(fdt, "ibm,ppc-interrupt-server#s",
+                           servers_prop, sizeof(servers_prop))));
+        _FDT((fdt_property(fdt, "ibm,ppc-interrupt-gserver#s",
+                           gservers_prop, sizeof(gservers_prop))));
+
+        if (env->mmu_model & POWERPC_MMU_1TSEG) {
+            _FDT((fdt_property(fdt, "ibm,processor-segment-sizes",
+                               segs, sizeof(segs))));
+        }
+
+        /* Advertise VMX/VSX (vector extensions) if available
+         *   0 / no property == no vector extensions
+         *   1               == VMX / Altivec available
+         *   2               == VSX available */
+        if (env->insns_flags & PPC_ALTIVEC) {
+            uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
+
+            _FDT((fdt_property_cell(fdt, "ibm,vmx", vmx)));
+        }
+
+        /* Advertise DFP (Decimal Floating Point) if available
+         *   0 / no property == no DFP
+         *   1               == DFP available */
+        if (env->insns_flags2 & PPC2_DFP) {
+            _FDT((fdt_property_cell(fdt, "ibm,dfp", 1)));
+        }
+
+        page_sizes_prop_size = create_page_sizes_prop(env, page_sizes_prop,
+                                                      sizeof(page_sizes_prop));
+        if (page_sizes_prop_size) {
+            _FDT((fdt_property(fdt, "ibm,segment-page-sizes",
+                               page_sizes_prop, page_sizes_prop_size)));
+        }
+
+        _FDT((fdt_end_node(fdt)));
+    }
+
+    g_free(modelname);
+
+    _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_property(fdt, "qemu,hypertas-functions", qemu_hypertas_prop,
+                       sizeof(qemu_hypertas_prop))));
+
+    _FDT((fdt_property(fdt, "ibm,associativity-reference-points",
+        refpoints, sizeof(refpoints))));
+
+    _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
+
+    _FDT((fdt_end_node(fdt)));
+
+    /* interrupt controller */
+    _FDT((fdt_begin_node(fdt, "interrupt-controller")));
+
+    _FDT((fdt_property_string(fdt, "device_type",
+                              "PowerPC-External-Interrupt-Presentation")));
+    _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
+    _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_property_cell(fdt, "#interrupt-cells", 2)));
+    _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP)));
+    _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP)));
+
+    _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_property_cell(fdt, "#interrupt-cells", 0x2)));
+    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
+
+    _FDT((fdt_end_node(fdt)));
+
+    /* event-sources */
+    spapr_events_fdt_skel(fdt, epow_irq);
+
+    _FDT((fdt_end_node(fdt))); /* close root node */
+    _FDT((fdt_finish(fdt)));
+
+    return fdt;
+}
+
+static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt)
+{
+    uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0),
+                                cpu_to_be32(0x0), cpu_to_be32(0x0),
+                                cpu_to_be32(0x0)};
+    char mem_name[32];
+    hwaddr node0_size, mem_start;
+    uint64_t mem_reg_property[2];
+    int i, off;
+
+    /* memory node(s) */
+    node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size;
+    if (spapr->rma_size > node0_size) {
+        spapr->rma_size = node0_size;
+    }
+
+    /* RMA */
+    mem_reg_property[0] = 0;
+    mem_reg_property[1] = cpu_to_be64(spapr->rma_size);
+    off = fdt_add_subnode(fdt, 0, "memory at 0");
+    _FDT(off);
+    _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
+    _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
+                      sizeof(mem_reg_property))));
+    _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
+                      sizeof(associativity))));
+
+    /* RAM: Node 0 */
+    if (node0_size > spapr->rma_size) {
+        mem_reg_property[0] = cpu_to_be64(spapr->rma_size);
+        mem_reg_property[1] = cpu_to_be64(node0_size - spapr->rma_size);
+
+        sprintf(mem_name, "memory@" TARGET_FMT_lx, spapr->rma_size);
+        off = fdt_add_subnode(fdt, 0, mem_name);
+        _FDT(off);
+        _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
+        _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
+                          sizeof(mem_reg_property))));
+        _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
+                          sizeof(associativity))));
+    }
+
+    /* RAM: Node 1 and beyond */
+    mem_start = node0_size;
+    for (i = 1; i < nb_numa_nodes; i++) {
+        mem_reg_property[0] = cpu_to_be64(mem_start);
+        mem_reg_property[1] = cpu_to_be64(node_mem[i]);
+        associativity[3] = associativity[4] = cpu_to_be32(i);
+        sprintf(mem_name, "memory@" TARGET_FMT_lx, mem_start);
+        off = fdt_add_subnode(fdt, 0, mem_name);
+        _FDT(off);
+        _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
+        _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
+                          sizeof(mem_reg_property))));
+        _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
+                          sizeof(associativity))));
+        mem_start += node_mem[i];
+    }
+
+    return 0;
+}
+
+static void spapr_finalize_fdt(sPAPREnvironment *spapr,
+                               hwaddr fdt_addr,
+                               hwaddr rtas_addr,
+                               hwaddr rtas_size)
+{
+    int ret;
+    void *fdt;
+    sPAPRPHBState *phb;
+
+    fdt = g_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_memory(spapr, fdt);
+    if (ret < 0) {
+        fprintf(stderr, "couldn't setup memory nodes in fdt\n");
+        exit(1);
+    }
+
+    ret = spapr_populate_vdevice(spapr->vio_bus, fdt);
+    if (ret < 0) {
+        fprintf(stderr, "couldn't setup vio devices in fdt\n");
+        exit(1);
+    }
+
+    QLIST_FOREACH(phb, &spapr->phbs, list) {
+        ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt);
+    }
+
+    if (ret < 0) {
+        fprintf(stderr, "couldn't setup PCI devices in fdt\n");
+        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");
+    }
+
+    /* Advertise NUMA via ibm,associativity */
+    ret = spapr_fixup_cpu_dt(fdt, spapr);
+    if (ret < 0) {
+        fprintf(stderr, "Couldn't finalize CPU device tree properties\n");
+    }
+
+    if (!spapr->has_graphics) {
+        spapr_populate_chosen_stdout(fdt, spapr->vio_bus);
+    }
+
+    _FDT((fdt_pack(fdt)));
+
+    if (fdt_totalsize(fdt) > FDT_MAX_SIZE) {
+        hw_error("FDT too big ! 0x%x bytes (max is 0x%x)\n",
+                 fdt_totalsize(fdt), FDT_MAX_SIZE);
+        exit(1);
+    }
+
+    cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
+
+    g_free(fdt);
+}
+
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+    return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
+}
+
+static void emulate_spapr_hypercall(PowerPCCPU *cpu)
+{
+    CPUPPCState *env = &cpu->env;
+
+    if (msr_pr) {
+        hcall_dprintf("Hypercall made with MSR[PR]=1\n");
+        env->gpr[3] = H_PRIVILEGE;
+    } else {
+        env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]);
+    }
+}
+
+static void spapr_reset_htab(sPAPREnvironment *spapr)
+{
+    long shift;
+
+    /* allocate hash page table.  For now we always make this 16mb,
+     * later we should probably make it scale to the size of guest
+     * RAM */
+
+    shift = kvmppc_reset_htab(spapr->htab_shift);
+
+    if (shift > 0) {
+        /* Kernel handles htab, we don't need to allocate one */
+        spapr->htab_shift = shift;
+    } else {
+        if (!spapr->htab) {
+            /* Allocate an htab if we don't yet have one */
+            spapr->htab = qemu_memalign(HTAB_SIZE(spapr), HTAB_SIZE(spapr));
+        }
+
+        /* And clear it */
+        memset(spapr->htab, 0, HTAB_SIZE(spapr));
+    }
+
+    /* Update the RMA size if necessary */
+    if (spapr->vrma_adjust) {
+        spapr->rma_size = kvmppc_rma_size(ram_size, spapr->htab_shift);
+    }
+}
+
+static void ppc_spapr_reset(void)
+{
+    /* Reset the hash table & recalc the RMA */
+    spapr_reset_htab(spapr);
+
+    qemu_devices_reset();
+
+    /* 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;
+
+}
+
+static void spapr_cpu_reset(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+
+    cpu_reset(CPU(cpu));
+
+    /* All CPUs start halted.  CPU0 is unhalted from the machine level
+     * reset code and the rest are explicitly started up by the guest
+     * using an RTAS call */
+    env->halted = 1;
+
+    env->spr[SPR_HIOR] = 0;
+
+    env->external_htab = spapr->htab;
+    env->htab_base = -1;
+    env->htab_mask = HTAB_SIZE(spapr) - 1;
+    env->spr[SPR_SDR1] = (unsigned long)spapr->htab |
+        (spapr->htab_shift - 18);
+}
+
+static void spapr_create_nvram(sPAPREnvironment *spapr)
+{
+    QemuOpts *machine_opts;
+    DeviceState *dev;
+
+    dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
+
+    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
+    if (machine_opts) {
+        const char *drivename;
+
+        drivename = qemu_opt_get(machine_opts, "nvram");
+        if (drivename) {
+            BlockDriverState *bs;
+
+            bs = bdrv_find(drivename);
+            if (!bs) {
+                fprintf(stderr, "No such block device \"%s\" for nvram\n",
+                        drivename);
+                exit(1);
+            }
+            qdev_prop_set_drive_nofail(dev, "drive", bs);
+        }
+    }
+
+    qdev_init_nofail(dev);
+
+    spapr->nvram = (struct sPAPRNVRAM *)dev;
+}
+
+/* Returns whether we want to use VGA or not */
+static int spapr_vga_init(PCIBus *pci_bus)
+{
+    switch (vga_interface_type) {
+    case VGA_NONE:
+    case VGA_STD:
+        return pci_vga_init(pci_bus) != NULL;
+    default:
+        fprintf(stderr, "This vga model is not supported,"
+                "currently it only supports -vga std\n");
+        exit(0);
+        break;
+    }
+}
+
+/* pSeries LPAR / sPAPR hardware init */
+static void ppc_spapr_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    PCIHostState *phb;
+    int i;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    hwaddr rma_alloc_size;
+    uint32_t initrd_base = 0;
+    long kernel_size = 0, initrd_size = 0;
+    long load_limit, rtas_limit, fw_size;
+    char *filename;
+
+    msi_supported = true;
+
+    spapr = g_malloc0(sizeof(*spapr));
+    QLIST_INIT(&spapr->phbs);
+
+    cpu_ppc_hypercall = emulate_spapr_hypercall;
+
+    /* Allocate RMA if necessary */
+    rma_alloc_size = kvmppc_alloc_rma("ppc_spapr.rma", sysmem);
+
+    if (rma_alloc_size == -1) {
+        hw_error("qemu: Unable to create RMA\n");
+        exit(1);
+    }
+
+    if (rma_alloc_size && (rma_alloc_size < ram_size)) {
+        spapr->rma_size = rma_alloc_size;
+    } else {
+        spapr->rma_size = ram_size;
+
+        /* With KVM, we don't actually know whether KVM supports an
+         * unbounded RMA (PR KVM) or is limited by the hash table size
+         * (HV KVM using VRMA), so we always assume the latter
+         *
+         * In that case, we also limit the initial allocations for RTAS
+         * etc... to 256M since we have no way to know what the VRMA size
+         * is going to be as it depends on the size of the hash table
+         * isn't determined yet.
+         */
+        if (kvm_enabled()) {
+            spapr->vrma_adjust = 1;
+            spapr->rma_size = MIN(spapr->rma_size, 0x10000000);
+        }
+    }
+
+    /* We place the device tree and RTAS just below either the top of the RMA,
+     * or just below 2GB, whichever is lowere, so that it can be
+     * processed with 32-bit real mode code if necessary */
+    rtas_limit = MIN(spapr->rma_size, 0x80000000);
+    spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE;
+    spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE;
+    load_limit = spapr->fdt_addr - FW_OVERHEAD;
+
+    /* We aim for a hash table of size 1/128 the size of RAM.  The
+     * normal rule of thumb is 1/64 the size of RAM, but that's much
+     * more than needed for the Linux guests we support. */
+    spapr->htab_shift = 18; /* Minimum architected size */
+    while (spapr->htab_shift <= 46) {
+        if ((1ULL << (spapr->htab_shift + 7)) >= ram_size) {
+            break;
+        }
+        spapr->htab_shift++;
+    }
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+        cpu_model = kvm_enabled() ? "host" : "POWER7";
+    }
+    for (i = 0; i < smp_cpus; i++) {
+        cpu = cpu_ppc_init(cpu_model);
+        if (cpu == NULL) {
+            fprintf(stderr, "Unable to find PowerPC CPU definition\n");
+            exit(1);
+        }
+        env = &cpu->env;
+
+        /* Set time-base frequency to 512 MHz */
+        cpu_ppc_tb_init(env, TIMEBASE_FREQ);
+
+        /* PAPR always has exception vectors in RAM not ROM */
+        env->hreset_excp_prefix = 0;
+
+        /* Tell KVM that we're in PAPR mode */
+        if (kvm_enabled()) {
+            kvmppc_set_papr(cpu);
+        }
+
+        qemu_register_reset(spapr_cpu_reset, cpu);
+    }
+
+    /* allocate RAM */
+    spapr->ram_limit = ram_size;
+    if (spapr->ram_limit > rma_alloc_size) {
+        ram_addr_t nonrma_base = rma_alloc_size;
+        ram_addr_t nonrma_size = spapr->ram_limit - rma_alloc_size;
+
+        memory_region_init_ram(ram, "ppc_spapr.ram", nonrma_size);
+        vmstate_register_ram_global(ram);
+        memory_region_add_subregion(sysmem, nonrma_base, ram);
+    }
+
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
+    spapr->rtas_size = load_image_targphys(filename, spapr->rtas_addr,
+                                           rtas_limit - spapr->rtas_addr);
+    if (spapr->rtas_size < 0) {
+        hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
+        exit(1);
+    }
+    if (spapr->rtas_size > RTAS_MAX_SIZE) {
+        hw_error("RTAS too big ! 0x%lx bytes (max is 0x%x)\n",
+                 spapr->rtas_size, RTAS_MAX_SIZE);
+        exit(1);
+    }
+    g_free(filename);
+
+
+    /* Set up Interrupt Controller */
+    spapr->icp = xics_system_init(XICS_IRQS);
+    spapr->next_irq = XICS_IRQ_BASE;
+
+    /* Set up EPOW events infrastructure */
+    spapr_events_init(spapr);
+
+    /* Set up IOMMU */
+    spapr_iommu_init();
+
+    /* Set up VIO bus */
+    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, serial_hds[i]);
+        }
+    }
+
+    /* We always have at least the nvram device on VIO */
+    spapr_create_nvram(spapr);
+
+    /* Set up PCI */
+    spapr_pci_rtas_init();
+
+    phb = spapr_create_phb(spapr, 0, "pci");
+
+    for (i = 0; i < nb_nics; i++) {
+        NICInfo *nd = &nd_table[i];
+
+        if (!nd->model) {
+            nd->model = g_strdup("ibmveth");
+        }
+
+        if (strcmp(nd->model, "ibmveth") == 0) {
+            spapr_vlan_create(spapr->vio_bus, nd);
+        } else {
+            pci_nic_init_nofail(&nd_table[i], nd->model, NULL);
+        }
+    }
+
+    for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) {
+        spapr_vscsi_create(spapr->vio_bus);
+    }
+
+    /* Graphics */
+    if (spapr_vga_init(phb->bus)) {
+        spapr->has_graphics = true;
+    }
+
+    if (usb_enabled(spapr->has_graphics)) {
+        pci_create_simple(phb->bus, -1, "pci-ohci");
+        if (spapr->has_graphics) {
+            usbdevice_create("keyboard");
+            usbdevice_create("mouse");
+        }
+    }
+
+    if (spapr->rma_size < (MIN_RMA_SLOF << 20)) {
+        fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
+                "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF);
+        exit(1);
+    }
+
+    if (kernel_filename) {
+        uint64_t lowaddr = 0;
+
+        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_LOAD_ADDR,
+                                              load_limit - KERNEL_LOAD_ADDR);
+        }
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+
+        /* load initrd */
+        if (initrd_filename) {
+            /* Try to locate the initrd in the gap between the kernel
+             * and the firmware. Add a bit of space just in case
+             */
+            initrd_base = (KERNEL_LOAD_ADDR + kernel_size + 0x1ffff) & ~0xffff;
+            initrd_size = load_image_targphys(initrd_filename, initrd_base,
+                                              load_limit - 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;
+        }
+    }
+
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME);
+    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);
+    }
+    g_free(filename);
+
+    spapr->entry_point = 0x100;
+
+    /* Prepare the device tree */
+    spapr->fdt_skel = spapr_create_fdt_skel(cpu_model,
+                                            initrd_base, initrd_size,
+                                            kernel_size,
+                                            boot_device, kernel_cmdline,
+                                            spapr->epow_irq);
+    assert(spapr->fdt_skel != NULL);
+}
+
+static QEMUMachine spapr_machine = {
+    .name = "pseries",
+    .desc = "pSeries Logical Partition (PAPR compliant)",
+    .init = ppc_spapr_init,
+    .reset = ppc_spapr_reset,
+    .block_default_type = IF_SCSI,
+    .max_cpus = MAX_CPUS,
+    .no_parallel = 1,
+    .boot_order = NULL,
+};
+
+static void spapr_machine_init(void)
+{
+    qemu_register_machine(&spapr_machine);
+}
+
+machine_init(spapr_machine_init);
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
new file mode 100644
index 0000000..41eab16
--- /dev/null
+++ b/hw/ppc/virtex_ml507.c
@@ -0,0 +1,274 @@
+/*
+ * Model of Xilinx Virtex5 ML507 PPC-440 refdesign.
+ *
+ * Copyright (c) 2010 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 "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/serial.h"
+#include "hw/flash.h"
+#include "sysemu/sysemu.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "sysemu/device_tree.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "qemu/log.h"
+#include "exec/address-spaces.h"
+
+#include "hw/ppc.h"
+#include "hw/ppc4xx.h"
+#include "hw/ppc405.h"
+
+#include "sysemu/blockdev.h"
+#include "hw/xilinx.h"
+
+#define EPAPR_MAGIC    (0x45504150)
+#define FLASH_SIZE     (16 * 1024 * 1024)
+
+static struct boot_info
+{
+    uint32_t bootstrap_pc;
+    uint32_t cmdline;
+    uint32_t fdt;
+    uint32_t ima_size;
+    void *vfdt;
+} boot_info;
+
+/* Create reset TLB entries for BookE, spanning the 32bit addr space.  */
+static void mmubooke_create_initial_mapping(CPUPPCState *env,
+                                     target_ulong va,
+                                     hwaddr pa)
+{
+    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
+
+    tlb->attr = 0;
+    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
+    tlb->size = 1 << 31; /* up to 0x80000000  */
+    tlb->EPN = va & TARGET_PAGE_MASK;
+    tlb->RPN = pa & TARGET_PAGE_MASK;
+    tlb->PID = 0;
+
+    tlb = &env->tlb.tlbe[1];
+    tlb->attr = 0;
+    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
+    tlb->size = 1 << 31; /* up to 0xffffffff  */
+    tlb->EPN = 0x80000000 & TARGET_PAGE_MASK;
+    tlb->RPN = 0x80000000 & TARGET_PAGE_MASK;
+    tlb->PID = 0;
+}
+
+static PowerPCCPU *ppc440_init_xilinx(ram_addr_t *ram_size,
+                                      int do_init,
+                                      const char *cpu_model,
+                                      uint32_t sysclk)
+{
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    qemu_irq *irqs;
+
+    cpu = cpu_ppc_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to initialize CPU!\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    ppc_booke_timers_init(cpu, sysclk, 0/* no flags */);
+
+    ppc_dcr_init(env, NULL, NULL);
+
+    /* interrupt controller */
+    irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+    irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
+    irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
+    ppcuic_init(env, irqs, 0x0C0, 0, 1);
+    return cpu;
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+    struct boot_info *bi = env->load_info;
+
+    cpu_reset(CPU(cpu));
+    /* Linux Kernel Parameters (passing device tree):
+       *   r3: pointer to the fdt
+       *   r4: 0
+       *   r5: 0
+       *   r6: epapr magic
+       *   r7: size of IMA in bytes
+       *   r8: 0
+       *   r9: 0
+    */
+    env->gpr[1] = (16<<20) - 8;
+    /* Provide a device-tree.  */
+    env->gpr[3] = bi->fdt;
+    env->nip = bi->bootstrap_pc;
+
+    /* Create a mapping for the kernel.  */
+    mmubooke_create_initial_mapping(env, 0, 0);
+    env->gpr[6] = tswap32(EPAPR_MAGIC);
+    env->gpr[7] = bi->ima_size;
+}
+
+#define BINARY_DEVICE_TREE_FILE "virtex-ml507.dtb"
+static int xilinx_load_device_tree(hwaddr addr,
+                                      uint32_t ramsize,
+                                      hwaddr initrd_base,
+                                      hwaddr initrd_size,
+                                      const char *kernel_cmdline)
+{
+    char *path;
+    int fdt_size;
+#ifdef CONFIG_FDT
+    void *fdt;
+    int r;
+
+    /* Try the local "ppc.dtb" override.  */
+    fdt = load_device_tree("ppc.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);
+            g_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("ppc.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);
+            g_free(path);
+        }
+    }
+
+    if (kernel_cmdline) {
+        fprintf(stderr,
+                "Warning: missing libfdt, cannot pass cmdline to kernel!\n");
+    }
+#endif
+    return fdt_size;
+}
+
+static void virtex_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    MemoryRegion *address_space_mem = get_system_memory();
+    DeviceState *dev;
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    hwaddr ram_base = 0;
+    DriveInfo *dinfo;
+    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
+    qemu_irq irq[32], *cpu_irq;
+    int kernel_size;
+    int i;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+        cpu_model = "440-Xilinx";
+    }
+
+    cpu = ppc440_init_xilinx(&ram_size, 1, cpu_model, 400000000);
+    env = &cpu->env;
+    qemu_register_reset(main_cpu_reset, cpu);
+
+    memory_region_init_ram(phys_ram, "ram", ram_size);
+    vmstate_register_ram_global(phys_ram);
+    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    pflash_cfi01_register(0xfc000000, NULL, "virtex.flash", FLASH_SIZE,
+                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
+                          FLASH_SIZE >> 16,
+                          1, 0x89, 0x18, 0x0000, 0x0, 1);
+
+    cpu_irq = (qemu_irq *) &env->irq_inputs[PPC40x_INPUT_INT];
+    dev = xilinx_intc_create(0x81800000, cpu_irq[0], 0);
+    for (i = 0; i < 32; i++) {
+        irq[i] = qdev_get_gpio_in(dev, i);
+    }
+
+    serial_mm_init(address_space_mem, 0x83e01003ULL, 2, irq[9], 115200,
+                   serial_hds[0], DEVICE_LITTLE_ENDIAN);
+
+    /* 2 timers at irq 2 @ 62 Mhz.  */
+    xilinx_timer_create(0x83c00000, irq[3], 0, 62 * 1000000);
+
+    if (kernel_filename) {
+        uint64_t entry, low, high;
+        hwaddr boot_offset;
+
+        /* Boots a kernel elf binary.  */
+        kernel_size = load_elf(kernel_filename, NULL, NULL,
+                               &entry, &low, &high, 1, ELF_MACHINE, 0);
+        boot_info.bootstrap_pc = entry & 0x00ffffff;
+
+        if (kernel_size < 0) {
+            boot_offset = 0x1200000;
+            /* If we failed loading ELF's try a raw image.  */
+            kernel_size = load_image_targphys(kernel_filename,
+                                              boot_offset,
+                                              ram_size);
+            boot_info.bootstrap_pc = boot_offset;
+            high = boot_info.bootstrap_pc + kernel_size + 8192;
+        }
+
+        boot_info.ima_size = kernel_size;
+
+        /* Provide a device-tree.  */
+        boot_info.fdt = high + (8192 * 2);
+        boot_info.fdt &= ~8191;
+        xilinx_load_device_tree(boot_info.fdt, ram_size, 0, 0, kernel_cmdline);
+    }
+    env->load_info = &boot_info;
+}
+
+static QEMUMachine virtex_machine = {
+    .name = "virtex-ml507",
+    .desc = "Xilinx Virtex ML507 reference design",
+    .init = virtex_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void virtex_machine_init(void)
+{
+    qemu_register_machine(&virtex_machine);
+}
+
+machine_init(virtex_machine_init);
diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c
deleted file mode 100644
index ba443cf..0000000
--- a/hw/ppc405_boards.c
+++ /dev/null
@@ -1,662 +0,0 @@
-/*
- * QEMU PowerPC 405 evaluation boards emulation
- *
- * Copyright (c) 2007 Jocelyn Mayer
- *
- * 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/hw.h"
-#include "hw/ppc.h"
-#include "hw/ppc405.h"
-#include "hw/nvram.h"
-#include "hw/flash.h"
-#include "sysemu/sysemu.h"
-#include "block/block.h"
-#include "hw/boards.h"
-#include "qemu/log.h"
-#include "hw/loader.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-#define BIOS_FILENAME "ppc405_rom.bin"
-#define BIOS_SIZE (2048 * 1024)
-
-#define KERNEL_LOAD_ADDR 0x00000000
-#define INITRD_LOAD_ADDR 0x01800000
-
-#define USE_FLASH_BIOS
-
-#define DEBUG_BOARD_INIT
-
-/*****************************************************************************/
-/* PPC405EP reference board (IBM) */
-/* Standalone board with:
- * - PowerPC 405EP CPU
- * - SDRAM (0x00000000)
- * - Flash (0xFFF80000)
- * - SRAM  (0xFFF00000)
- * - NVRAM (0xF0000000)
- * - FPGA  (0xF0300000)
- */
-typedef struct ref405ep_fpga_t ref405ep_fpga_t;
-struct ref405ep_fpga_t {
-    uint8_t reg0;
-    uint8_t reg1;
-};
-
-static uint32_t ref405ep_fpga_readb (void *opaque, hwaddr addr)
-{
-    ref405ep_fpga_t *fpga;
-    uint32_t ret;
-
-    fpga = opaque;
-    switch (addr) {
-    case 0x0:
-        ret = fpga->reg0;
-        break;
-    case 0x1:
-        ret = fpga->reg1;
-        break;
-    default:
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void ref405ep_fpga_writeb (void *opaque,
-                                  hwaddr addr, uint32_t value)
-{
-    ref405ep_fpga_t *fpga;
-
-    fpga = opaque;
-    switch (addr) {
-    case 0x0:
-        /* Read only */
-        break;
-    case 0x1:
-        fpga->reg1 = value;
-        break;
-    default:
-        break;
-    }
-}
-
-static uint32_t ref405ep_fpga_readw (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-    ret = ref405ep_fpga_readb(opaque, addr) << 8;
-    ret |= ref405ep_fpga_readb(opaque, addr + 1);
-
-    return ret;
-}
-
-static void ref405ep_fpga_writew (void *opaque,
-                                  hwaddr addr, uint32_t value)
-{
-    ref405ep_fpga_writeb(opaque, addr, (value >> 8) & 0xFF);
-    ref405ep_fpga_writeb(opaque, addr + 1, value & 0xFF);
-}
-
-static uint32_t ref405ep_fpga_readl (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-    ret = ref405ep_fpga_readb(opaque, addr) << 24;
-    ret |= ref405ep_fpga_readb(opaque, addr + 1) << 16;
-    ret |= ref405ep_fpga_readb(opaque, addr + 2) << 8;
-    ret |= ref405ep_fpga_readb(opaque, addr + 3);
-
-    return ret;
-}
-
-static void ref405ep_fpga_writel (void *opaque,
-                                  hwaddr addr, uint32_t value)
-{
-    ref405ep_fpga_writeb(opaque, addr, (value >> 24) & 0xFF);
-    ref405ep_fpga_writeb(opaque, addr + 1, (value >> 16) & 0xFF);
-    ref405ep_fpga_writeb(opaque, addr + 2, (value >> 8) & 0xFF);
-    ref405ep_fpga_writeb(opaque, addr + 3, value & 0xFF);
-}
-
-static const MemoryRegionOps ref405ep_fpga_ops = {
-    .old_mmio = {
-        .read = {
-            ref405ep_fpga_readb, ref405ep_fpga_readw, ref405ep_fpga_readl,
-        },
-        .write = {
-            ref405ep_fpga_writeb, ref405ep_fpga_writew, ref405ep_fpga_writel,
-        },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void ref405ep_fpga_reset (void *opaque)
-{
-    ref405ep_fpga_t *fpga;
-
-    fpga = opaque;
-    fpga->reg0 = 0x00;
-    fpga->reg1 = 0x0F;
-}
-
-static void ref405ep_fpga_init(MemoryRegion *sysmem, uint32_t base)
-{
-    ref405ep_fpga_t *fpga;
-    MemoryRegion *fpga_memory = g_new(MemoryRegion, 1);
-
-    fpga = g_malloc0(sizeof(ref405ep_fpga_t));
-    memory_region_init_io(fpga_memory, &ref405ep_fpga_ops, fpga,
-                          "fpga", 0x00000100);
-    memory_region_add_subregion(sysmem, base, fpga_memory);
-    qemu_register_reset(&ref405ep_fpga_reset, fpga);
-}
-
-static void ref405ep_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    char *filename;
-    ppc4xx_bd_info_t bd;
-    CPUPPCState *env;
-    qemu_irq *pic;
-    MemoryRegion *bios;
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-    ram_addr_t bdloc;
-    MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
-    hwaddr ram_bases[2], ram_sizes[2];
-    target_ulong sram_size;
-    long bios_size;
-    //int phy_addr = 0;
-    //static int phy_addr = 1;
-    target_ulong kernel_base, initrd_base;
-    long kernel_size, initrd_size;
-    int linux_boot;
-    int fl_idx, fl_sectors, len;
-    DriveInfo *dinfo;
-    MemoryRegion *sysmem = get_system_memory();
-
-    /* XXX: fix this */
-    memory_region_init_ram(&ram_memories[0], "ef405ep.ram", 0x08000000);
-    vmstate_register_ram_global(&ram_memories[0]);
-    ram_bases[0] = 0;
-    ram_sizes[0] = 0x08000000;
-    memory_region_init(&ram_memories[1], "ef405ep.ram1", 0);
-    ram_bases[1] = 0x00000000;
-    ram_sizes[1] = 0x00000000;
-    ram_size = 128 * 1024 * 1024;
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register cpu\n", __func__);
-#endif
-    env = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
-                        33333333, &pic, kernel_filename == NULL ? 0 : 1);
-    /* allocate SRAM */
-    sram_size = 512 * 1024;
-    memory_region_init_ram(sram, "ef405ep.sram", sram_size);
-    vmstate_register_ram_global(sram);
-    memory_region_add_subregion(sysmem, 0xFFF00000, sram);
-    /* allocate and load BIOS */
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register BIOS\n", __func__);
-#endif
-    fl_idx = 0;
-#ifdef USE_FLASH_BIOS
-    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
-    if (dinfo) {
-        bios_size = bdrv_getlength(dinfo->bdrv);
-        fl_sectors = (bios_size + 65535) >> 16;
-#ifdef DEBUG_BOARD_INIT
-        printf("Register parallel flash %d size %lx"
-               " at addr %lx '%s' %d\n",
-               fl_idx, bios_size, -bios_size,
-               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
-#endif
-        pflash_cfi02_register((uint32_t)(-bios_size),
-                              NULL, "ef405ep.bios", bios_size,
-                              dinfo->bdrv, 65536, fl_sectors, 1,
-                              2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
-                              1);
-        fl_idx++;
-    } else
-#endif
-    {
-#ifdef DEBUG_BOARD_INIT
-        printf("Load BIOS from file\n");
-#endif
-        bios = g_new(MemoryRegion, 1);
-        memory_region_init_ram(bios, "ef405ep.bios", BIOS_SIZE);
-        vmstate_register_ram_global(bios);
-        if (bios_name == NULL)
-            bios_name = BIOS_FILENAME;
-        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-        if (filename) {
-            bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
-            g_free(filename);
-        } else {
-            bios_size = -1;
-        }
-        if (bios_size < 0 || bios_size > BIOS_SIZE) {
-            fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n",
-                    bios_name);
-            exit(1);
-        }
-        bios_size = (bios_size + 0xfff) & ~0xfff;
-        memory_region_set_readonly(bios, true);
-        memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
-    }
-    /* Register FPGA */
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register FPGA\n", __func__);
-#endif
-    ref405ep_fpga_init(sysmem, 0xF0300000);
-    /* Register NVRAM */
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register NVRAM\n", __func__);
-#endif
-    m48t59_init(NULL, 0xF0000000, 0, 8192, 8);
-    /* Load kernel */
-    linux_boot = (kernel_filename != NULL);
-    if (linux_boot) {
-#ifdef DEBUG_BOARD_INIT
-        printf("%s: load kernel\n", __func__);
-#endif
-        memset(&bd, 0, sizeof(bd));
-        bd.bi_memstart = 0x00000000;
-        bd.bi_memsize = ram_size;
-        bd.bi_flashstart = -bios_size;
-        bd.bi_flashsize = -bios_size;
-        bd.bi_flashoffset = 0;
-        bd.bi_sramstart = 0xFFF00000;
-        bd.bi_sramsize = sram_size;
-        bd.bi_bootflags = 0;
-        bd.bi_intfreq = 133333333;
-        bd.bi_busfreq = 33333333;
-        bd.bi_baudrate = 115200;
-        bd.bi_s_version[0] = 'Q';
-        bd.bi_s_version[1] = 'M';
-        bd.bi_s_version[2] = 'U';
-        bd.bi_s_version[3] = '\0';
-        bd.bi_r_version[0] = 'Q';
-        bd.bi_r_version[1] = 'E';
-        bd.bi_r_version[2] = 'M';
-        bd.bi_r_version[3] = 'U';
-        bd.bi_r_version[4] = '\0';
-        bd.bi_procfreq = 133333333;
-        bd.bi_plb_busfreq = 33333333;
-        bd.bi_pci_busfreq = 33333333;
-        bd.bi_opbfreq = 33333333;
-        bdloc = ppc405_set_bootinfo(env, &bd, 0x00000001);
-        env->gpr[3] = bdloc;
-        kernel_base = KERNEL_LOAD_ADDR;
-        /* now we can load the kernel */
-        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);
-        }
-        printf("Load kernel size %ld at " TARGET_FMT_lx,
-               kernel_size, kernel_base);
-        /* 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;
-        }
-        env->gpr[4] = initrd_base;
-        env->gpr[5] = initrd_size;
-        if (kernel_cmdline != NULL) {
-            len = strlen(kernel_cmdline);
-            bdloc -= ((len + 255) & ~255);
-            cpu_physical_memory_write(bdloc, (void *)kernel_cmdline, len + 1);
-            env->gpr[6] = bdloc;
-            env->gpr[7] = bdloc + len;
-        } else {
-            env->gpr[6] = 0;
-            env->gpr[7] = 0;
-        }
-        env->nip = KERNEL_LOAD_ADDR;
-    } else {
-        kernel_base = 0;
-        kernel_size = 0;
-        initrd_base = 0;
-        initrd_size = 0;
-        bdloc = 0;
-    }
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: Done\n", __func__);
-#endif
-    printf("bdloc " RAM_ADDR_FMT "\n", bdloc);
-}
-
-static QEMUMachine ref405ep_machine = {
-    .name = "ref405ep",
-    .desc = "ref405ep",
-    .init = ref405ep_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-/*****************************************************************************/
-/* AMCC Taihu evaluation board */
-/* - PowerPC 405EP processor
- * - SDRAM               128 MB at 0x00000000
- * - Boot flash          2 MB   at 0xFFE00000
- * - Application flash   32 MB  at 0xFC000000
- * - 2 serial ports
- * - 2 ethernet PHY
- * - 1 USB 1.1 device    0x50000000
- * - 1 LCD display       0x50100000
- * - 1 CPLD              0x50100000
- * - 1 I2C EEPROM
- * - 1 I2C thermal sensor
- * - a set of LEDs
- * - bit-bang SPI port using GPIOs
- * - 1 EBC interface connector 0 0x50200000
- * - 1 cardbus controller + expansion slot.
- * - 1 PCI expansion slot.
- */
-typedef struct taihu_cpld_t taihu_cpld_t;
-struct taihu_cpld_t {
-    uint8_t reg0;
-    uint8_t reg1;
-};
-
-static uint32_t taihu_cpld_readb (void *opaque, hwaddr addr)
-{
-    taihu_cpld_t *cpld;
-    uint32_t ret;
-
-    cpld = opaque;
-    switch (addr) {
-    case 0x0:
-        ret = cpld->reg0;
-        break;
-    case 0x1:
-        ret = cpld->reg1;
-        break;
-    default:
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void taihu_cpld_writeb (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-    taihu_cpld_t *cpld;
-
-    cpld = opaque;
-    switch (addr) {
-    case 0x0:
-        /* Read only */
-        break;
-    case 0x1:
-        cpld->reg1 = value;
-        break;
-    default:
-        break;
-    }
-}
-
-static uint32_t taihu_cpld_readw (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-    ret = taihu_cpld_readb(opaque, addr) << 8;
-    ret |= taihu_cpld_readb(opaque, addr + 1);
-
-    return ret;
-}
-
-static void taihu_cpld_writew (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-    taihu_cpld_writeb(opaque, addr, (value >> 8) & 0xFF);
-    taihu_cpld_writeb(opaque, addr + 1, value & 0xFF);
-}
-
-static uint32_t taihu_cpld_readl (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-    ret = taihu_cpld_readb(opaque, addr) << 24;
-    ret |= taihu_cpld_readb(opaque, addr + 1) << 16;
-    ret |= taihu_cpld_readb(opaque, addr + 2) << 8;
-    ret |= taihu_cpld_readb(opaque, addr + 3);
-
-    return ret;
-}
-
-static void taihu_cpld_writel (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-    taihu_cpld_writel(opaque, addr, (value >> 24) & 0xFF);
-    taihu_cpld_writel(opaque, addr + 1, (value >> 16) & 0xFF);
-    taihu_cpld_writel(opaque, addr + 2, (value >> 8) & 0xFF);
-    taihu_cpld_writeb(opaque, addr + 3, value & 0xFF);
-}
-
-static const MemoryRegionOps taihu_cpld_ops = {
-    .old_mmio = {
-        .read = { taihu_cpld_readb, taihu_cpld_readw, taihu_cpld_readl, },
-        .write = { taihu_cpld_writeb, taihu_cpld_writew, taihu_cpld_writel, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void taihu_cpld_reset (void *opaque)
-{
-    taihu_cpld_t *cpld;
-
-    cpld = opaque;
-    cpld->reg0 = 0x01;
-    cpld->reg1 = 0x80;
-}
-
-static void taihu_cpld_init(MemoryRegion *sysmem, uint32_t base)
-{
-    taihu_cpld_t *cpld;
-    MemoryRegion *cpld_memory = g_new(MemoryRegion, 1);
-
-    cpld = g_malloc0(sizeof(taihu_cpld_t));
-    memory_region_init_io(cpld_memory, &taihu_cpld_ops, cpld, "cpld", 0x100);
-    memory_region_add_subregion(sysmem, base, cpld_memory);
-    qemu_register_reset(&taihu_cpld_reset, cpld);
-}
-
-static void taihu_405ep_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *kernel_filename = args->kernel_filename;
-    const char *initrd_filename = args->initrd_filename;
-    char *filename;
-    qemu_irq *pic;
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *bios;
-    MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories));
-    hwaddr ram_bases[2], ram_sizes[2];
-    long bios_size;
-    target_ulong kernel_base, initrd_base;
-    long kernel_size, initrd_size;
-    int linux_boot;
-    int fl_idx, fl_sectors;
-    DriveInfo *dinfo;
-
-    /* RAM is soldered to the board so the size cannot be changed */
-    memory_region_init_ram(&ram_memories[0],
-                           "taihu_405ep.ram-0", 0x04000000);
-    vmstate_register_ram_global(&ram_memories[0]);
-    ram_bases[0] = 0;
-    ram_sizes[0] = 0x04000000;
-    memory_region_init_ram(&ram_memories[1],
-                           "taihu_405ep.ram-1", 0x04000000);
-    vmstate_register_ram_global(&ram_memories[1]);
-    ram_bases[1] = 0x04000000;
-    ram_sizes[1] = 0x04000000;
-    ram_size = 0x08000000;
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register cpu\n", __func__);
-#endif
-    ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
-                  33333333, &pic, kernel_filename == NULL ? 0 : 1);
-    /* allocate and load BIOS */
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register BIOS\n", __func__);
-#endif
-    fl_idx = 0;
-#if defined(USE_FLASH_BIOS)
-    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
-    if (dinfo) {
-        bios_size = bdrv_getlength(dinfo->bdrv);
-        /* XXX: should check that size is 2MB */
-        //        bios_size = 2 * 1024 * 1024;
-        fl_sectors = (bios_size + 65535) >> 16;
-#ifdef DEBUG_BOARD_INIT
-        printf("Register parallel flash %d size %lx"
-               " at addr %lx '%s' %d\n",
-               fl_idx, bios_size, -bios_size,
-               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
-#endif
-        pflash_cfi02_register((uint32_t)(-bios_size),
-                              NULL, "taihu_405ep.bios", bios_size,
-                              dinfo->bdrv, 65536, fl_sectors, 1,
-                              4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
-                              1);
-        fl_idx++;
-    } else
-#endif
-    {
-#ifdef DEBUG_BOARD_INIT
-        printf("Load BIOS from file\n");
-#endif
-        if (bios_name == NULL)
-            bios_name = BIOS_FILENAME;
-        bios = g_new(MemoryRegion, 1);
-        memory_region_init_ram(bios, "taihu_405ep.bios", BIOS_SIZE);
-        vmstate_register_ram_global(bios);
-        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-        if (filename) {
-            bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
-            g_free(filename);
-        } else {
-            bios_size = -1;
-        }
-        if (bios_size < 0 || bios_size > BIOS_SIZE) {
-            fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n",
-                    bios_name);
-            exit(1);
-        }
-        bios_size = (bios_size + 0xfff) & ~0xfff;
-        memory_region_set_readonly(bios, true);
-        memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
-    }
-    /* Register Linux flash */
-    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
-    if (dinfo) {
-        bios_size = bdrv_getlength(dinfo->bdrv);
-        /* XXX: should check that size is 32MB */
-        bios_size = 32 * 1024 * 1024;
-        fl_sectors = (bios_size + 65535) >> 16;
-#ifdef DEBUG_BOARD_INIT
-        printf("Register parallel flash %d size %lx"
-               " at addr " TARGET_FMT_lx " '%s'\n",
-               fl_idx, bios_size, (target_ulong)0xfc000000,
-               bdrv_get_device_name(dinfo->bdrv));
-#endif
-        pflash_cfi02_register(0xfc000000, NULL, "taihu_405ep.flash", bios_size,
-                              dinfo->bdrv, 65536, fl_sectors, 1,
-                              4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
-                              1);
-        fl_idx++;
-    }
-    /* Register CLPD & LCD display */
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: register CPLD\n", __func__);
-#endif
-    taihu_cpld_init(sysmem, 0x50100000);
-    /* Load kernel */
-    linux_boot = (kernel_filename != NULL);
-    if (linux_boot) {
-#ifdef DEBUG_BOARD_INIT
-        printf("%s: load kernel\n", __func__);
-#endif
-        kernel_base = KERNEL_LOAD_ADDR;
-        /* now we can load the kernel */
-        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 {
-        kernel_base = 0;
-        kernel_size = 0;
-        initrd_base = 0;
-        initrd_size = 0;
-    }
-#ifdef DEBUG_BOARD_INIT
-    printf("%s: Done\n", __func__);
-#endif
-}
-
-static QEMUMachine taihu_machine = {
-    .name = "taihu",
-    .desc = "taihu",
-    .init = taihu_405ep_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void ppc405_machine_init(void)
-{
-    qemu_register_machine(&ref405ep_machine);
-    qemu_register_machine(&taihu_machine);
-}
-
-machine_init(ppc405_machine_init);
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
deleted file mode 100644
index 8465f6d..0000000
--- a/hw/ppc405_uc.c
+++ /dev/null
@@ -1,2548 +0,0 @@
-/*
- * QEMU PowerPC 405 embedded processors emulation
- *
- * Copyright (c) 2007 Jocelyn Mayer
- *
- * 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/hw.h"
-#include "hw/ppc.h"
-#include "hw/ppc405.h"
-#include "hw/serial.h"
-#include "qemu/timer.h"
-#include "sysemu/sysemu.h"
-#include "qemu/log.h"
-#include "exec/address-spaces.h"
-
-#define DEBUG_OPBA
-#define DEBUG_SDRAM
-#define DEBUG_GPIO
-#define DEBUG_SERIAL
-#define DEBUG_OCM
-//#define DEBUG_I2C
-#define DEBUG_GPT
-#define DEBUG_MAL
-#define DEBUG_CLOCKS
-//#define DEBUG_CLOCKS_LL
-
-ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
-                                uint32_t flags)
-{
-    ram_addr_t bdloc;
-    int i, n;
-
-    /* We put the bd structure at the top of memory */
-    if (bd->bi_memsize >= 0x01000000UL)
-        bdloc = 0x01000000UL - sizeof(struct ppc4xx_bd_info_t);
-    else
-        bdloc = bd->bi_memsize - sizeof(struct ppc4xx_bd_info_t);
-    stl_be_phys(bdloc + 0x00, bd->bi_memstart);
-    stl_be_phys(bdloc + 0x04, bd->bi_memsize);
-    stl_be_phys(bdloc + 0x08, bd->bi_flashstart);
-    stl_be_phys(bdloc + 0x0C, bd->bi_flashsize);
-    stl_be_phys(bdloc + 0x10, bd->bi_flashoffset);
-    stl_be_phys(bdloc + 0x14, bd->bi_sramstart);
-    stl_be_phys(bdloc + 0x18, bd->bi_sramsize);
-    stl_be_phys(bdloc + 0x1C, bd->bi_bootflags);
-    stl_be_phys(bdloc + 0x20, bd->bi_ipaddr);
-    for (i = 0; i < 6; i++) {
-        stb_phys(bdloc + 0x24 + i, bd->bi_enetaddr[i]);
-    }
-    stw_be_phys(bdloc + 0x2A, bd->bi_ethspeed);
-    stl_be_phys(bdloc + 0x2C, bd->bi_intfreq);
-    stl_be_phys(bdloc + 0x30, bd->bi_busfreq);
-    stl_be_phys(bdloc + 0x34, bd->bi_baudrate);
-    for (i = 0; i < 4; i++) {
-        stb_phys(bdloc + 0x38 + i, bd->bi_s_version[i]);
-    }
-    for (i = 0; i < 32; i++) {
-        stb_phys(bdloc + 0x3C + i, bd->bi_r_version[i]);
-    }
-    stl_be_phys(bdloc + 0x5C, bd->bi_plb_busfreq);
-    stl_be_phys(bdloc + 0x60, bd->bi_pci_busfreq);
-    for (i = 0; i < 6; i++) {
-        stb_phys(bdloc + 0x64 + i, bd->bi_pci_enetaddr[i]);
-    }
-    n = 0x6A;
-    if (flags & 0x00000001) {
-        for (i = 0; i < 6; i++)
-            stb_phys(bdloc + n++, bd->bi_pci_enetaddr2[i]);
-    }
-    stl_be_phys(bdloc + n, bd->bi_opbfreq);
-    n += 4;
-    for (i = 0; i < 2; i++) {
-        stl_be_phys(bdloc + n, bd->bi_iic_fast[i]);
-        n += 4;
-    }
-
-    return bdloc;
-}
-
-/*****************************************************************************/
-/* Shared peripherals */
-
-/*****************************************************************************/
-/* Peripheral local bus arbitrer */
-enum {
-    PLB0_BESR = 0x084,
-    PLB0_BEAR = 0x086,
-    PLB0_ACR  = 0x087,
-};
-
-typedef struct ppc4xx_plb_t ppc4xx_plb_t;
-struct ppc4xx_plb_t {
-    uint32_t acr;
-    uint32_t bear;
-    uint32_t besr;
-};
-
-static uint32_t dcr_read_plb (void *opaque, int dcrn)
-{
-    ppc4xx_plb_t *plb;
-    uint32_t ret;
-
-    plb = opaque;
-    switch (dcrn) {
-    case PLB0_ACR:
-        ret = plb->acr;
-        break;
-    case PLB0_BEAR:
-        ret = plb->bear;
-        break;
-    case PLB0_BESR:
-        ret = plb->besr;
-        break;
-    default:
-        /* Avoid gcc warning */
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_plb (void *opaque, int dcrn, uint32_t val)
-{
-    ppc4xx_plb_t *plb;
-
-    plb = opaque;
-    switch (dcrn) {
-    case PLB0_ACR:
-        /* We don't care about the actual parameters written as
-         * we don't manage any priorities on the bus
-         */
-        plb->acr = val & 0xF8000000;
-        break;
-    case PLB0_BEAR:
-        /* Read only */
-        break;
-    case PLB0_BESR:
-        /* Write-clear */
-        plb->besr &= ~val;
-        break;
-    }
-}
-
-static void ppc4xx_plb_reset (void *opaque)
-{
-    ppc4xx_plb_t *plb;
-
-    plb = opaque;
-    plb->acr = 0x00000000;
-    plb->bear = 0x00000000;
-    plb->besr = 0x00000000;
-}
-
-static void ppc4xx_plb_init(CPUPPCState *env)
-{
-    ppc4xx_plb_t *plb;
-
-    plb = g_malloc0(sizeof(ppc4xx_plb_t));
-    ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
-    ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
-    ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
-    qemu_register_reset(ppc4xx_plb_reset, plb);
-}
-
-/*****************************************************************************/
-/* PLB to OPB bridge */
-enum {
-    POB0_BESR0 = 0x0A0,
-    POB0_BESR1 = 0x0A2,
-    POB0_BEAR  = 0x0A4,
-};
-
-typedef struct ppc4xx_pob_t ppc4xx_pob_t;
-struct ppc4xx_pob_t {
-    uint32_t bear;
-    uint32_t besr0;
-    uint32_t besr1;
-};
-
-static uint32_t dcr_read_pob (void *opaque, int dcrn)
-{
-    ppc4xx_pob_t *pob;
-    uint32_t ret;
-
-    pob = opaque;
-    switch (dcrn) {
-    case POB0_BEAR:
-        ret = pob->bear;
-        break;
-    case POB0_BESR0:
-        ret = pob->besr0;
-        break;
-    case POB0_BESR1:
-        ret = pob->besr1;
-        break;
-    default:
-        /* Avoid gcc warning */
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_pob (void *opaque, int dcrn, uint32_t val)
-{
-    ppc4xx_pob_t *pob;
-
-    pob = opaque;
-    switch (dcrn) {
-    case POB0_BEAR:
-        /* Read only */
-        break;
-    case POB0_BESR0:
-        /* Write-clear */
-        pob->besr0 &= ~val;
-        break;
-    case POB0_BESR1:
-        /* Write-clear */
-        pob->besr1 &= ~val;
-        break;
-    }
-}
-
-static void ppc4xx_pob_reset (void *opaque)
-{
-    ppc4xx_pob_t *pob;
-
-    pob = opaque;
-    /* No error */
-    pob->bear = 0x00000000;
-    pob->besr0 = 0x0000000;
-    pob->besr1 = 0x0000000;
-}
-
-static void ppc4xx_pob_init(CPUPPCState *env)
-{
-    ppc4xx_pob_t *pob;
-
-    pob = g_malloc0(sizeof(ppc4xx_pob_t));
-    ppc_dcr_register(env, POB0_BEAR, pob, &dcr_read_pob, &dcr_write_pob);
-    ppc_dcr_register(env, POB0_BESR0, pob, &dcr_read_pob, &dcr_write_pob);
-    ppc_dcr_register(env, POB0_BESR1, pob, &dcr_read_pob, &dcr_write_pob);
-    qemu_register_reset(ppc4xx_pob_reset, pob);
-}
-
-/*****************************************************************************/
-/* OPB arbitrer */
-typedef struct ppc4xx_opba_t ppc4xx_opba_t;
-struct ppc4xx_opba_t {
-    MemoryRegion io;
-    uint8_t cr;
-    uint8_t pr;
-};
-
-static uint32_t opba_readb (void *opaque, hwaddr addr)
-{
-    ppc4xx_opba_t *opba;
-    uint32_t ret;
-
-#ifdef DEBUG_OPBA
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    opba = opaque;
-    switch (addr) {
-    case 0x00:
-        ret = opba->cr;
-        break;
-    case 0x01:
-        ret = opba->pr;
-        break;
-    default:
-        ret = 0x00;
-        break;
-    }
-
-    return ret;
-}
-
-static void opba_writeb (void *opaque,
-                         hwaddr addr, uint32_t value)
-{
-    ppc4xx_opba_t *opba;
-
-#ifdef DEBUG_OPBA
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    opba = opaque;
-    switch (addr) {
-    case 0x00:
-        opba->cr = value & 0xF8;
-        break;
-    case 0x01:
-        opba->pr = value & 0xFF;
-        break;
-    default:
-        break;
-    }
-}
-
-static uint32_t opba_readw (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-#ifdef DEBUG_OPBA
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    ret = opba_readb(opaque, addr) << 8;
-    ret |= opba_readb(opaque, addr + 1);
-
-    return ret;
-}
-
-static void opba_writew (void *opaque,
-                         hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_OPBA
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    opba_writeb(opaque, addr, value >> 8);
-    opba_writeb(opaque, addr + 1, value);
-}
-
-static uint32_t opba_readl (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-#ifdef DEBUG_OPBA
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    ret = opba_readb(opaque, addr) << 24;
-    ret |= opba_readb(opaque, addr + 1) << 16;
-
-    return ret;
-}
-
-static void opba_writel (void *opaque,
-                         hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_OPBA
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    opba_writeb(opaque, addr, value >> 24);
-    opba_writeb(opaque, addr + 1, value >> 16);
-}
-
-static const MemoryRegionOps opba_ops = {
-    .old_mmio = {
-        .read = { opba_readb, opba_readw, opba_readl, },
-        .write = { opba_writeb, opba_writew, opba_writel, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void ppc4xx_opba_reset (void *opaque)
-{
-    ppc4xx_opba_t *opba;
-
-    opba = opaque;
-    opba->cr = 0x00; /* No dynamic priorities - park disabled */
-    opba->pr = 0x11;
-}
-
-static void ppc4xx_opba_init(hwaddr base)
-{
-    ppc4xx_opba_t *opba;
-
-    opba = g_malloc0(sizeof(ppc4xx_opba_t));
-#ifdef DEBUG_OPBA
-    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
-#endif
-    memory_region_init_io(&opba->io, &opba_ops, opba, "opba", 0x002);
-    memory_region_add_subregion(get_system_memory(), base, &opba->io);
-    qemu_register_reset(ppc4xx_opba_reset, opba);
-}
-
-/*****************************************************************************/
-/* Code decompression controller */
-/* XXX: TODO */
-
-/*****************************************************************************/
-/* Peripheral controller */
-typedef struct ppc4xx_ebc_t ppc4xx_ebc_t;
-struct ppc4xx_ebc_t {
-    uint32_t addr;
-    uint32_t bcr[8];
-    uint32_t bap[8];
-    uint32_t bear;
-    uint32_t besr0;
-    uint32_t besr1;
-    uint32_t cfg;
-};
-
-enum {
-    EBC0_CFGADDR = 0x012,
-    EBC0_CFGDATA = 0x013,
-};
-
-static uint32_t dcr_read_ebc (void *opaque, int dcrn)
-{
-    ppc4xx_ebc_t *ebc;
-    uint32_t ret;
-
-    ebc = opaque;
-    switch (dcrn) {
-    case EBC0_CFGADDR:
-        ret = ebc->addr;
-        break;
-    case EBC0_CFGDATA:
-        switch (ebc->addr) {
-        case 0x00: /* B0CR */
-            ret = ebc->bcr[0];
-            break;
-        case 0x01: /* B1CR */
-            ret = ebc->bcr[1];
-            break;
-        case 0x02: /* B2CR */
-            ret = ebc->bcr[2];
-            break;
-        case 0x03: /* B3CR */
-            ret = ebc->bcr[3];
-            break;
-        case 0x04: /* B4CR */
-            ret = ebc->bcr[4];
-            break;
-        case 0x05: /* B5CR */
-            ret = ebc->bcr[5];
-            break;
-        case 0x06: /* B6CR */
-            ret = ebc->bcr[6];
-            break;
-        case 0x07: /* B7CR */
-            ret = ebc->bcr[7];
-            break;
-        case 0x10: /* B0AP */
-            ret = ebc->bap[0];
-            break;
-        case 0x11: /* B1AP */
-            ret = ebc->bap[1];
-            break;
-        case 0x12: /* B2AP */
-            ret = ebc->bap[2];
-            break;
-        case 0x13: /* B3AP */
-            ret = ebc->bap[3];
-            break;
-        case 0x14: /* B4AP */
-            ret = ebc->bap[4];
-            break;
-        case 0x15: /* B5AP */
-            ret = ebc->bap[5];
-            break;
-        case 0x16: /* B6AP */
-            ret = ebc->bap[6];
-            break;
-        case 0x17: /* B7AP */
-            ret = ebc->bap[7];
-            break;
-        case 0x20: /* BEAR */
-            ret = ebc->bear;
-            break;
-        case 0x21: /* BESR0 */
-            ret = ebc->besr0;
-            break;
-        case 0x22: /* BESR1 */
-            ret = ebc->besr1;
-            break;
-        case 0x23: /* CFG */
-            ret = ebc->cfg;
-            break;
-        default:
-            ret = 0x00000000;
-            break;
-        }
-        break;
-    default:
-        ret = 0x00000000;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_ebc (void *opaque, int dcrn, uint32_t val)
-{
-    ppc4xx_ebc_t *ebc;
-
-    ebc = opaque;
-    switch (dcrn) {
-    case EBC0_CFGADDR:
-        ebc->addr = val;
-        break;
-    case EBC0_CFGDATA:
-        switch (ebc->addr) {
-        case 0x00: /* B0CR */
-            break;
-        case 0x01: /* B1CR */
-            break;
-        case 0x02: /* B2CR */
-            break;
-        case 0x03: /* B3CR */
-            break;
-        case 0x04: /* B4CR */
-            break;
-        case 0x05: /* B5CR */
-            break;
-        case 0x06: /* B6CR */
-            break;
-        case 0x07: /* B7CR */
-            break;
-        case 0x10: /* B0AP */
-            break;
-        case 0x11: /* B1AP */
-            break;
-        case 0x12: /* B2AP */
-            break;
-        case 0x13: /* B3AP */
-            break;
-        case 0x14: /* B4AP */
-            break;
-        case 0x15: /* B5AP */
-            break;
-        case 0x16: /* B6AP */
-            break;
-        case 0x17: /* B7AP */
-            break;
-        case 0x20: /* BEAR */
-            break;
-        case 0x21: /* BESR0 */
-            break;
-        case 0x22: /* BESR1 */
-            break;
-        case 0x23: /* CFG */
-            break;
-        default:
-            break;
-        }
-        break;
-    default:
-        break;
-    }
-}
-
-static void ebc_reset (void *opaque)
-{
-    ppc4xx_ebc_t *ebc;
-    int i;
-
-    ebc = opaque;
-    ebc->addr = 0x00000000;
-    ebc->bap[0] = 0x7F8FFE80;
-    ebc->bcr[0] = 0xFFE28000;
-    for (i = 0; i < 8; i++) {
-        ebc->bap[i] = 0x00000000;
-        ebc->bcr[i] = 0x00000000;
-    }
-    ebc->besr0 = 0x00000000;
-    ebc->besr1 = 0x00000000;
-    ebc->cfg = 0x80400000;
-}
-
-static void ppc405_ebc_init(CPUPPCState *env)
-{
-    ppc4xx_ebc_t *ebc;
-
-    ebc = g_malloc0(sizeof(ppc4xx_ebc_t));
-    qemu_register_reset(&ebc_reset, ebc);
-    ppc_dcr_register(env, EBC0_CFGADDR,
-                     ebc, &dcr_read_ebc, &dcr_write_ebc);
-    ppc_dcr_register(env, EBC0_CFGDATA,
-                     ebc, &dcr_read_ebc, &dcr_write_ebc);
-}
-
-/*****************************************************************************/
-/* DMA controller */
-enum {
-    DMA0_CR0 = 0x100,
-    DMA0_CT0 = 0x101,
-    DMA0_DA0 = 0x102,
-    DMA0_SA0 = 0x103,
-    DMA0_SG0 = 0x104,
-    DMA0_CR1 = 0x108,
-    DMA0_CT1 = 0x109,
-    DMA0_DA1 = 0x10A,
-    DMA0_SA1 = 0x10B,
-    DMA0_SG1 = 0x10C,
-    DMA0_CR2 = 0x110,
-    DMA0_CT2 = 0x111,
-    DMA0_DA2 = 0x112,
-    DMA0_SA2 = 0x113,
-    DMA0_SG2 = 0x114,
-    DMA0_CR3 = 0x118,
-    DMA0_CT3 = 0x119,
-    DMA0_DA3 = 0x11A,
-    DMA0_SA3 = 0x11B,
-    DMA0_SG3 = 0x11C,
-    DMA0_SR  = 0x120,
-    DMA0_SGC = 0x123,
-    DMA0_SLP = 0x125,
-    DMA0_POL = 0x126,
-};
-
-typedef struct ppc405_dma_t ppc405_dma_t;
-struct ppc405_dma_t {
-    qemu_irq irqs[4];
-    uint32_t cr[4];
-    uint32_t ct[4];
-    uint32_t da[4];
-    uint32_t sa[4];
-    uint32_t sg[4];
-    uint32_t sr;
-    uint32_t sgc;
-    uint32_t slp;
-    uint32_t pol;
-};
-
-static uint32_t dcr_read_dma (void *opaque, int dcrn)
-{
-    return 0;
-}
-
-static void dcr_write_dma (void *opaque, int dcrn, uint32_t val)
-{
-}
-
-static void ppc405_dma_reset (void *opaque)
-{
-    ppc405_dma_t *dma;
-    int i;
-
-    dma = opaque;
-    for (i = 0; i < 4; i++) {
-        dma->cr[i] = 0x00000000;
-        dma->ct[i] = 0x00000000;
-        dma->da[i] = 0x00000000;
-        dma->sa[i] = 0x00000000;
-        dma->sg[i] = 0x00000000;
-    }
-    dma->sr = 0x00000000;
-    dma->sgc = 0x00000000;
-    dma->slp = 0x7C000000;
-    dma->pol = 0x00000000;
-}
-
-static void ppc405_dma_init(CPUPPCState *env, qemu_irq irqs[4])
-{
-    ppc405_dma_t *dma;
-
-    dma = g_malloc0(sizeof(ppc405_dma_t));
-    memcpy(dma->irqs, irqs, 4 * sizeof(qemu_irq));
-    qemu_register_reset(&ppc405_dma_reset, dma);
-    ppc_dcr_register(env, DMA0_CR0,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_CT0,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_DA0,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SA0,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SG0,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_CR1,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_CT1,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_DA1,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SA1,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SG1,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_CR2,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_CT2,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_DA2,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SA2,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SG2,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_CR3,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_CT3,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_DA3,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SA3,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SG3,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SR,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SGC,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_SLP,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-    ppc_dcr_register(env, DMA0_POL,
-                     dma, &dcr_read_dma, &dcr_write_dma);
-}
-
-/*****************************************************************************/
-/* GPIO */
-typedef struct ppc405_gpio_t ppc405_gpio_t;
-struct ppc405_gpio_t {
-    MemoryRegion io;
-    uint32_t or;
-    uint32_t tcr;
-    uint32_t osrh;
-    uint32_t osrl;
-    uint32_t tsrh;
-    uint32_t tsrl;
-    uint32_t odr;
-    uint32_t ir;
-    uint32_t rr1;
-    uint32_t isr1h;
-    uint32_t isr1l;
-};
-
-static uint32_t ppc405_gpio_readb (void *opaque, hwaddr addr)
-{
-#ifdef DEBUG_GPIO
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-
-    return 0;
-}
-
-static void ppc405_gpio_writeb (void *opaque,
-                                hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_GPIO
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-}
-
-static uint32_t ppc405_gpio_readw (void *opaque, hwaddr addr)
-{
-#ifdef DEBUG_GPIO
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-
-    return 0;
-}
-
-static void ppc405_gpio_writew (void *opaque,
-                                hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_GPIO
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-}
-
-static uint32_t ppc405_gpio_readl (void *opaque, hwaddr addr)
-{
-#ifdef DEBUG_GPIO
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-
-    return 0;
-}
-
-static void ppc405_gpio_writel (void *opaque,
-                                hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_GPIO
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-}
-
-static const MemoryRegionOps ppc405_gpio_ops = {
-    .old_mmio = {
-        .read = { ppc405_gpio_readb, ppc405_gpio_readw, ppc405_gpio_readl, },
-        .write = { ppc405_gpio_writeb, ppc405_gpio_writew, ppc405_gpio_writel, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void ppc405_gpio_reset (void *opaque)
-{
-}
-
-static void ppc405_gpio_init(hwaddr base)
-{
-    ppc405_gpio_t *gpio;
-
-    gpio = g_malloc0(sizeof(ppc405_gpio_t));
-#ifdef DEBUG_GPIO
-    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
-#endif
-    memory_region_init_io(&gpio->io, &ppc405_gpio_ops, gpio, "pgio", 0x038);
-    memory_region_add_subregion(get_system_memory(), base, &gpio->io);
-    qemu_register_reset(&ppc405_gpio_reset, gpio);
-}
-
-/*****************************************************************************/
-/* On Chip Memory */
-enum {
-    OCM0_ISARC   = 0x018,
-    OCM0_ISACNTL = 0x019,
-    OCM0_DSARC   = 0x01A,
-    OCM0_DSACNTL = 0x01B,
-};
-
-typedef struct ppc405_ocm_t ppc405_ocm_t;
-struct ppc405_ocm_t {
-    MemoryRegion ram;
-    MemoryRegion isarc_ram;
-    MemoryRegion dsarc_ram;
-    uint32_t isarc;
-    uint32_t isacntl;
-    uint32_t dsarc;
-    uint32_t dsacntl;
-};
-
-static void ocm_update_mappings (ppc405_ocm_t *ocm,
-                                 uint32_t isarc, uint32_t isacntl,
-                                 uint32_t dsarc, uint32_t dsacntl)
-{
-#ifdef DEBUG_OCM
-    printf("OCM update ISA %08" PRIx32 " %08" PRIx32 " (%08" PRIx32
-           " %08" PRIx32 ") DSA %08" PRIx32 " %08" PRIx32
-           " (%08" PRIx32 " %08" PRIx32 ")\n",
-           isarc, isacntl, dsarc, dsacntl,
-           ocm->isarc, ocm->isacntl, ocm->dsarc, ocm->dsacntl);
-#endif
-    if (ocm->isarc != isarc ||
-        (ocm->isacntl & 0x80000000) != (isacntl & 0x80000000)) {
-        if (ocm->isacntl & 0x80000000) {
-            /* Unmap previously assigned memory region */
-            printf("OCM unmap ISA %08" PRIx32 "\n", ocm->isarc);
-            memory_region_del_subregion(get_system_memory(), &ocm->isarc_ram);
-        }
-        if (isacntl & 0x80000000) {
-            /* Map new instruction memory region */
-#ifdef DEBUG_OCM
-            printf("OCM map ISA %08" PRIx32 "\n", isarc);
-#endif
-            memory_region_add_subregion(get_system_memory(), isarc,
-                                        &ocm->isarc_ram);
-        }
-    }
-    if (ocm->dsarc != dsarc ||
-        (ocm->dsacntl & 0x80000000) != (dsacntl & 0x80000000)) {
-        if (ocm->dsacntl & 0x80000000) {
-            /* Beware not to unmap the region we just mapped */
-            if (!(isacntl & 0x80000000) || ocm->dsarc != isarc) {
-                /* Unmap previously assigned memory region */
-#ifdef DEBUG_OCM
-                printf("OCM unmap DSA %08" PRIx32 "\n", ocm->dsarc);
-#endif
-                memory_region_del_subregion(get_system_memory(),
-                                            &ocm->dsarc_ram);
-            }
-        }
-        if (dsacntl & 0x80000000) {
-            /* Beware not to remap the region we just mapped */
-            if (!(isacntl & 0x80000000) || dsarc != isarc) {
-                /* Map new data memory region */
-#ifdef DEBUG_OCM
-                printf("OCM map DSA %08" PRIx32 "\n", dsarc);
-#endif
-                memory_region_add_subregion(get_system_memory(), dsarc,
-                                            &ocm->dsarc_ram);
-            }
-        }
-    }
-}
-
-static uint32_t dcr_read_ocm (void *opaque, int dcrn)
-{
-    ppc405_ocm_t *ocm;
-    uint32_t ret;
-
-    ocm = opaque;
-    switch (dcrn) {
-    case OCM0_ISARC:
-        ret = ocm->isarc;
-        break;
-    case OCM0_ISACNTL:
-        ret = ocm->isacntl;
-        break;
-    case OCM0_DSARC:
-        ret = ocm->dsarc;
-        break;
-    case OCM0_DSACNTL:
-        ret = ocm->dsacntl;
-        break;
-    default:
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_ocm (void *opaque, int dcrn, uint32_t val)
-{
-    ppc405_ocm_t *ocm;
-    uint32_t isarc, dsarc, isacntl, dsacntl;
-
-    ocm = opaque;
-    isarc = ocm->isarc;
-    dsarc = ocm->dsarc;
-    isacntl = ocm->isacntl;
-    dsacntl = ocm->dsacntl;
-    switch (dcrn) {
-    case OCM0_ISARC:
-        isarc = val & 0xFC000000;
-        break;
-    case OCM0_ISACNTL:
-        isacntl = val & 0xC0000000;
-        break;
-    case OCM0_DSARC:
-        isarc = val & 0xFC000000;
-        break;
-    case OCM0_DSACNTL:
-        isacntl = val & 0xC0000000;
-        break;
-    }
-    ocm_update_mappings(ocm, isarc, isacntl, dsarc, dsacntl);
-    ocm->isarc = isarc;
-    ocm->dsarc = dsarc;
-    ocm->isacntl = isacntl;
-    ocm->dsacntl = dsacntl;
-}
-
-static void ocm_reset (void *opaque)
-{
-    ppc405_ocm_t *ocm;
-    uint32_t isarc, dsarc, isacntl, dsacntl;
-
-    ocm = opaque;
-    isarc = 0x00000000;
-    isacntl = 0x00000000;
-    dsarc = 0x00000000;
-    dsacntl = 0x00000000;
-    ocm_update_mappings(ocm, isarc, isacntl, dsarc, dsacntl);
-    ocm->isarc = isarc;
-    ocm->dsarc = dsarc;
-    ocm->isacntl = isacntl;
-    ocm->dsacntl = dsacntl;
-}
-
-static void ppc405_ocm_init(CPUPPCState *env)
-{
-    ppc405_ocm_t *ocm;
-
-    ocm = g_malloc0(sizeof(ppc405_ocm_t));
-    /* XXX: Size is 4096 or 0x04000000 */
-    memory_region_init_ram(&ocm->isarc_ram, "ppc405.ocm", 4096);
-    vmstate_register_ram_global(&ocm->isarc_ram);
-    memory_region_init_alias(&ocm->dsarc_ram, "ppc405.dsarc", &ocm->isarc_ram,
-                             0, 4096);
-    qemu_register_reset(&ocm_reset, ocm);
-    ppc_dcr_register(env, OCM0_ISARC,
-                     ocm, &dcr_read_ocm, &dcr_write_ocm);
-    ppc_dcr_register(env, OCM0_ISACNTL,
-                     ocm, &dcr_read_ocm, &dcr_write_ocm);
-    ppc_dcr_register(env, OCM0_DSARC,
-                     ocm, &dcr_read_ocm, &dcr_write_ocm);
-    ppc_dcr_register(env, OCM0_DSACNTL,
-                     ocm, &dcr_read_ocm, &dcr_write_ocm);
-}
-
-/*****************************************************************************/
-/* I2C controller */
-typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
-struct ppc4xx_i2c_t {
-    qemu_irq irq;
-    MemoryRegion iomem;
-    uint8_t mdata;
-    uint8_t lmadr;
-    uint8_t hmadr;
-    uint8_t cntl;
-    uint8_t mdcntl;
-    uint8_t sts;
-    uint8_t extsts;
-    uint8_t sdata;
-    uint8_t lsadr;
-    uint8_t hsadr;
-    uint8_t clkdiv;
-    uint8_t intrmsk;
-    uint8_t xfrcnt;
-    uint8_t xtcntlss;
-    uint8_t directcntl;
-};
-
-static uint32_t ppc4xx_i2c_readb (void *opaque, hwaddr addr)
-{
-    ppc4xx_i2c_t *i2c;
-    uint32_t ret;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    i2c = opaque;
-    switch (addr) {
-    case 0x00:
-        //        i2c_readbyte(&i2c->mdata);
-        ret = i2c->mdata;
-        break;
-    case 0x02:
-        ret = i2c->sdata;
-        break;
-    case 0x04:
-        ret = i2c->lmadr;
-        break;
-    case 0x05:
-        ret = i2c->hmadr;
-        break;
-    case 0x06:
-        ret = i2c->cntl;
-        break;
-    case 0x07:
-        ret = i2c->mdcntl;
-        break;
-    case 0x08:
-        ret = i2c->sts;
-        break;
-    case 0x09:
-        ret = i2c->extsts;
-        break;
-    case 0x0A:
-        ret = i2c->lsadr;
-        break;
-    case 0x0B:
-        ret = i2c->hsadr;
-        break;
-    case 0x0C:
-        ret = i2c->clkdiv;
-        break;
-    case 0x0D:
-        ret = i2c->intrmsk;
-        break;
-    case 0x0E:
-        ret = i2c->xfrcnt;
-        break;
-    case 0x0F:
-        ret = i2c->xtcntlss;
-        break;
-    case 0x10:
-        ret = i2c->directcntl;
-        break;
-    default:
-        ret = 0x00;
-        break;
-    }
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, ret);
-#endif
-
-    return ret;
-}
-
-static void ppc4xx_i2c_writeb (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-    ppc4xx_i2c_t *i2c;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    i2c = opaque;
-    switch (addr) {
-    case 0x00:
-        i2c->mdata = value;
-        //        i2c_sendbyte(&i2c->mdata);
-        break;
-    case 0x02:
-        i2c->sdata = value;
-        break;
-    case 0x04:
-        i2c->lmadr = value;
-        break;
-    case 0x05:
-        i2c->hmadr = value;
-        break;
-    case 0x06:
-        i2c->cntl = value;
-        break;
-    case 0x07:
-        i2c->mdcntl = value & 0xDF;
-        break;
-    case 0x08:
-        i2c->sts &= ~(value & 0x0A);
-        break;
-    case 0x09:
-        i2c->extsts &= ~(value & 0x8F);
-        break;
-    case 0x0A:
-        i2c->lsadr = value;
-        break;
-    case 0x0B:
-        i2c->hsadr = value;
-        break;
-    case 0x0C:
-        i2c->clkdiv = value;
-        break;
-    case 0x0D:
-        i2c->intrmsk = value;
-        break;
-    case 0x0E:
-        i2c->xfrcnt = value & 0x77;
-        break;
-    case 0x0F:
-        i2c->xtcntlss = value;
-        break;
-    case 0x10:
-        i2c->directcntl = value & 0x7;
-        break;
-    }
-}
-
-static uint32_t ppc4xx_i2c_readw (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    ret = ppc4xx_i2c_readb(opaque, addr) << 8;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 1);
-
-    return ret;
-}
-
-static void ppc4xx_i2c_writew (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    ppc4xx_i2c_writeb(opaque, addr, value >> 8);
-    ppc4xx_i2c_writeb(opaque, addr + 1, value);
-}
-
-static uint32_t ppc4xx_i2c_readl (void *opaque, hwaddr addr)
-{
-    uint32_t ret;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    ret = ppc4xx_i2c_readb(opaque, addr) << 24;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
-    ret |= ppc4xx_i2c_readb(opaque, addr + 3);
-
-    return ret;
-}
-
-static void ppc4xx_i2c_writel (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    ppc4xx_i2c_writeb(opaque, addr, value >> 24);
-    ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16);
-    ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8);
-    ppc4xx_i2c_writeb(opaque, addr + 3, value);
-}
-
-static const MemoryRegionOps i2c_ops = {
-    .old_mmio = {
-        .read = { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, },
-        .write = { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writel, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void ppc4xx_i2c_reset (void *opaque)
-{
-    ppc4xx_i2c_t *i2c;
-
-    i2c = opaque;
-    i2c->mdata = 0x00;
-    i2c->sdata = 0x00;
-    i2c->cntl = 0x00;
-    i2c->mdcntl = 0x00;
-    i2c->sts = 0x00;
-    i2c->extsts = 0x00;
-    i2c->clkdiv = 0x00;
-    i2c->xfrcnt = 0x00;
-    i2c->directcntl = 0x0F;
-}
-
-static void ppc405_i2c_init(hwaddr base, qemu_irq irq)
-{
-    ppc4xx_i2c_t *i2c;
-
-    i2c = g_malloc0(sizeof(ppc4xx_i2c_t));
-    i2c->irq = irq;
-#ifdef DEBUG_I2C
-    printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
-#endif
-    memory_region_init_io(&i2c->iomem, &i2c_ops, i2c, "i2c", 0x011);
-    memory_region_add_subregion(get_system_memory(), base, &i2c->iomem);
-    qemu_register_reset(ppc4xx_i2c_reset, i2c);
-}
-
-/*****************************************************************************/
-/* General purpose timers */
-typedef struct ppc4xx_gpt_t ppc4xx_gpt_t;
-struct ppc4xx_gpt_t {
-    MemoryRegion iomem;
-    int64_t tb_offset;
-    uint32_t tb_freq;
-    struct QEMUTimer *timer;
-    qemu_irq irqs[5];
-    uint32_t oe;
-    uint32_t ol;
-    uint32_t im;
-    uint32_t is;
-    uint32_t ie;
-    uint32_t comp[5];
-    uint32_t mask[5];
-};
-
-static uint32_t ppc4xx_gpt_readb (void *opaque, hwaddr addr)
-{
-#ifdef DEBUG_GPT
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    /* XXX: generate a bus fault */
-    return -1;
-}
-
-static void ppc4xx_gpt_writeb (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    /* XXX: generate a bus fault */
-}
-
-static uint32_t ppc4xx_gpt_readw (void *opaque, hwaddr addr)
-{
-#ifdef DEBUG_GPT
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    /* XXX: generate a bus fault */
-    return -1;
-}
-
-static void ppc4xx_gpt_writew (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    /* XXX: generate a bus fault */
-}
-
-static int ppc4xx_gpt_compare (ppc4xx_gpt_t *gpt, int n)
-{
-    /* XXX: TODO */
-    return 0;
-}
-
-static void ppc4xx_gpt_set_output (ppc4xx_gpt_t *gpt, int n, int level)
-{
-    /* XXX: TODO */
-}
-
-static void ppc4xx_gpt_set_outputs (ppc4xx_gpt_t *gpt)
-{
-    uint32_t mask;
-    int i;
-
-    mask = 0x80000000;
-    for (i = 0; i < 5; i++) {
-        if (gpt->oe & mask) {
-            /* Output is enabled */
-            if (ppc4xx_gpt_compare(gpt, i)) {
-                /* Comparison is OK */
-                ppc4xx_gpt_set_output(gpt, i, gpt->ol & mask);
-            } else {
-                /* Comparison is KO */
-                ppc4xx_gpt_set_output(gpt, i, gpt->ol & mask ? 0 : 1);
-            }
-        }
-        mask = mask >> 1;
-    }
-}
-
-static void ppc4xx_gpt_set_irqs (ppc4xx_gpt_t *gpt)
-{
-    uint32_t mask;
-    int i;
-
-    mask = 0x00008000;
-    for (i = 0; i < 5; i++) {
-        if (gpt->is & gpt->im & mask)
-            qemu_irq_raise(gpt->irqs[i]);
-        else
-            qemu_irq_lower(gpt->irqs[i]);
-        mask = mask >> 1;
-    }
-}
-
-static void ppc4xx_gpt_compute_timer (ppc4xx_gpt_t *gpt)
-{
-    /* XXX: TODO */
-}
-
-static uint32_t ppc4xx_gpt_readl (void *opaque, hwaddr addr)
-{
-    ppc4xx_gpt_t *gpt;
-    uint32_t ret;
-    int idx;
-
-#ifdef DEBUG_GPT
-    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-    gpt = opaque;
-    switch (addr) {
-    case 0x00:
-        /* Time base counter */
-        ret = muldiv64(qemu_get_clock_ns(vm_clock) + gpt->tb_offset,
-                       gpt->tb_freq, get_ticks_per_sec());
-        break;
-    case 0x10:
-        /* Output enable */
-        ret = gpt->oe;
-        break;
-    case 0x14:
-        /* Output level */
-        ret = gpt->ol;
-        break;
-    case 0x18:
-        /* Interrupt mask */
-        ret = gpt->im;
-        break;
-    case 0x1C:
-    case 0x20:
-        /* Interrupt status */
-        ret = gpt->is;
-        break;
-    case 0x24:
-        /* Interrupt enable */
-        ret = gpt->ie;
-        break;
-    case 0x80 ... 0x90:
-        /* Compare timer */
-        idx = (addr - 0x80) >> 2;
-        ret = gpt->comp[idx];
-        break;
-    case 0xC0 ... 0xD0:
-        /* Compare mask */
-        idx = (addr - 0xC0) >> 2;
-        ret = gpt->mask[idx];
-        break;
-    default:
-        ret = -1;
-        break;
-    }
-
-    return ret;
-}
-
-static void ppc4xx_gpt_writel (void *opaque,
-                               hwaddr addr, uint32_t value)
-{
-    ppc4xx_gpt_t *gpt;
-    int idx;
-
-#ifdef DEBUG_I2C
-    printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
-           value);
-#endif
-    gpt = opaque;
-    switch (addr) {
-    case 0x00:
-        /* Time base counter */
-        gpt->tb_offset = muldiv64(value, get_ticks_per_sec(), gpt->tb_freq)
-            - qemu_get_clock_ns(vm_clock);
-        ppc4xx_gpt_compute_timer(gpt);
-        break;
-    case 0x10:
-        /* Output enable */
-        gpt->oe = value & 0xF8000000;
-        ppc4xx_gpt_set_outputs(gpt);
-        break;
-    case 0x14:
-        /* Output level */
-        gpt->ol = value & 0xF8000000;
-        ppc4xx_gpt_set_outputs(gpt);
-        break;
-    case 0x18:
-        /* Interrupt mask */
-        gpt->im = value & 0x0000F800;
-        break;
-    case 0x1C:
-        /* Interrupt status set */
-        gpt->is |= value & 0x0000F800;
-        ppc4xx_gpt_set_irqs(gpt);
-        break;
-    case 0x20:
-        /* Interrupt status clear */
-        gpt->is &= ~(value & 0x0000F800);
-        ppc4xx_gpt_set_irqs(gpt);
-        break;
-    case 0x24:
-        /* Interrupt enable */
-        gpt->ie = value & 0x0000F800;
-        ppc4xx_gpt_set_irqs(gpt);
-        break;
-    case 0x80 ... 0x90:
-        /* Compare timer */
-        idx = (addr - 0x80) >> 2;
-        gpt->comp[idx] = value & 0xF8000000;
-        ppc4xx_gpt_compute_timer(gpt);
-        break;
-    case 0xC0 ... 0xD0:
-        /* Compare mask */
-        idx = (addr - 0xC0) >> 2;
-        gpt->mask[idx] = value & 0xF8000000;
-        ppc4xx_gpt_compute_timer(gpt);
-        break;
-    }
-}
-
-static const MemoryRegionOps gpt_ops = {
-    .old_mmio = {
-        .read = { ppc4xx_gpt_readb, ppc4xx_gpt_readw, ppc4xx_gpt_readl, },
-        .write = { ppc4xx_gpt_writeb, ppc4xx_gpt_writew, ppc4xx_gpt_writel, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void ppc4xx_gpt_cb (void *opaque)
-{
-    ppc4xx_gpt_t *gpt;
-
-    gpt = opaque;
-    ppc4xx_gpt_set_irqs(gpt);
-    ppc4xx_gpt_set_outputs(gpt);
-    ppc4xx_gpt_compute_timer(gpt);
-}
-
-static void ppc4xx_gpt_reset (void *opaque)
-{
-    ppc4xx_gpt_t *gpt;
-    int i;
-
-    gpt = opaque;
-    qemu_del_timer(gpt->timer);
-    gpt->oe = 0x00000000;
-    gpt->ol = 0x00000000;
-    gpt->im = 0x00000000;
-    gpt->is = 0x00000000;
-    gpt->ie = 0x00000000;
-    for (i = 0; i < 5; i++) {
-        gpt->comp[i] = 0x00000000;
-        gpt->mask[i] = 0x00000000;
-    }
-}
-
-static void ppc4xx_gpt_init(hwaddr base, qemu_irq irqs[5])
-{
-    ppc4xx_gpt_t *gpt;
-    int i;
-
-    gpt = g_malloc0(sizeof(ppc4xx_gpt_t));
-    for (i = 0; i < 5; i++) {
-        gpt->irqs[i] = irqs[i];
-    }
-    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
-    memory_region_init_io(&gpt->iomem, &gpt_ops, gpt, "gpt", 0x0d4);
-    memory_region_add_subregion(get_system_memory(), base, &gpt->iomem);
-    qemu_register_reset(ppc4xx_gpt_reset, gpt);
-}
-
-/*****************************************************************************/
-/* MAL */
-enum {
-    MAL0_CFG      = 0x180,
-    MAL0_ESR      = 0x181,
-    MAL0_IER      = 0x182,
-    MAL0_TXCASR   = 0x184,
-    MAL0_TXCARR   = 0x185,
-    MAL0_TXEOBISR = 0x186,
-    MAL0_TXDEIR   = 0x187,
-    MAL0_RXCASR   = 0x190,
-    MAL0_RXCARR   = 0x191,
-    MAL0_RXEOBISR = 0x192,
-    MAL0_RXDEIR   = 0x193,
-    MAL0_TXCTP0R  = 0x1A0,
-    MAL0_TXCTP1R  = 0x1A1,
-    MAL0_TXCTP2R  = 0x1A2,
-    MAL0_TXCTP3R  = 0x1A3,
-    MAL0_RXCTP0R  = 0x1C0,
-    MAL0_RXCTP1R  = 0x1C1,
-    MAL0_RCBS0    = 0x1E0,
-    MAL0_RCBS1    = 0x1E1,
-};
-
-typedef struct ppc40x_mal_t ppc40x_mal_t;
-struct ppc40x_mal_t {
-    qemu_irq irqs[4];
-    uint32_t cfg;
-    uint32_t esr;
-    uint32_t ier;
-    uint32_t txcasr;
-    uint32_t txcarr;
-    uint32_t txeobisr;
-    uint32_t txdeir;
-    uint32_t rxcasr;
-    uint32_t rxcarr;
-    uint32_t rxeobisr;
-    uint32_t rxdeir;
-    uint32_t txctpr[4];
-    uint32_t rxctpr[2];
-    uint32_t rcbs[2];
-};
-
-static void ppc40x_mal_reset (void *opaque);
-
-static uint32_t dcr_read_mal (void *opaque, int dcrn)
-{
-    ppc40x_mal_t *mal;
-    uint32_t ret;
-
-    mal = opaque;
-    switch (dcrn) {
-    case MAL0_CFG:
-        ret = mal->cfg;
-        break;
-    case MAL0_ESR:
-        ret = mal->esr;
-        break;
-    case MAL0_IER:
-        ret = mal->ier;
-        break;
-    case MAL0_TXCASR:
-        ret = mal->txcasr;
-        break;
-    case MAL0_TXCARR:
-        ret = mal->txcarr;
-        break;
-    case MAL0_TXEOBISR:
-        ret = mal->txeobisr;
-        break;
-    case MAL0_TXDEIR:
-        ret = mal->txdeir;
-        break;
-    case MAL0_RXCASR:
-        ret = mal->rxcasr;
-        break;
-    case MAL0_RXCARR:
-        ret = mal->rxcarr;
-        break;
-    case MAL0_RXEOBISR:
-        ret = mal->rxeobisr;
-        break;
-    case MAL0_RXDEIR:
-        ret = mal->rxdeir;
-        break;
-    case MAL0_TXCTP0R:
-        ret = mal->txctpr[0];
-        break;
-    case MAL0_TXCTP1R:
-        ret = mal->txctpr[1];
-        break;
-    case MAL0_TXCTP2R:
-        ret = mal->txctpr[2];
-        break;
-    case MAL0_TXCTP3R:
-        ret = mal->txctpr[3];
-        break;
-    case MAL0_RXCTP0R:
-        ret = mal->rxctpr[0];
-        break;
-    case MAL0_RXCTP1R:
-        ret = mal->rxctpr[1];
-        break;
-    case MAL0_RCBS0:
-        ret = mal->rcbs[0];
-        break;
-    case MAL0_RCBS1:
-        ret = mal->rcbs[1];
-        break;
-    default:
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_mal (void *opaque, int dcrn, uint32_t val)
-{
-    ppc40x_mal_t *mal;
-    int idx;
-
-    mal = opaque;
-    switch (dcrn) {
-    case MAL0_CFG:
-        if (val & 0x80000000)
-            ppc40x_mal_reset(mal);
-        mal->cfg = val & 0x00FFC087;
-        break;
-    case MAL0_ESR:
-        /* Read/clear */
-        mal->esr &= ~val;
-        break;
-    case MAL0_IER:
-        mal->ier = val & 0x0000001F;
-        break;
-    case MAL0_TXCASR:
-        mal->txcasr = val & 0xF0000000;
-        break;
-    case MAL0_TXCARR:
-        mal->txcarr = val & 0xF0000000;
-        break;
-    case MAL0_TXEOBISR:
-        /* Read/clear */
-        mal->txeobisr &= ~val;
-        break;
-    case MAL0_TXDEIR:
-        /* Read/clear */
-        mal->txdeir &= ~val;
-        break;
-    case MAL0_RXCASR:
-        mal->rxcasr = val & 0xC0000000;
-        break;
-    case MAL0_RXCARR:
-        mal->rxcarr = val & 0xC0000000;
-        break;
-    case MAL0_RXEOBISR:
-        /* Read/clear */
-        mal->rxeobisr &= ~val;
-        break;
-    case MAL0_RXDEIR:
-        /* Read/clear */
-        mal->rxdeir &= ~val;
-        break;
-    case MAL0_TXCTP0R:
-        idx = 0;
-        goto update_tx_ptr;
-    case MAL0_TXCTP1R:
-        idx = 1;
-        goto update_tx_ptr;
-    case MAL0_TXCTP2R:
-        idx = 2;
-        goto update_tx_ptr;
-    case MAL0_TXCTP3R:
-        idx = 3;
-    update_tx_ptr:
-        mal->txctpr[idx] = val;
-        break;
-    case MAL0_RXCTP0R:
-        idx = 0;
-        goto update_rx_ptr;
-    case MAL0_RXCTP1R:
-        idx = 1;
-    update_rx_ptr:
-        mal->rxctpr[idx] = val;
-        break;
-    case MAL0_RCBS0:
-        idx = 0;
-        goto update_rx_size;
-    case MAL0_RCBS1:
-        idx = 1;
-    update_rx_size:
-        mal->rcbs[idx] = val & 0x000000FF;
-        break;
-    }
-}
-
-static void ppc40x_mal_reset (void *opaque)
-{
-    ppc40x_mal_t *mal;
-
-    mal = opaque;
-    mal->cfg = 0x0007C000;
-    mal->esr = 0x00000000;
-    mal->ier = 0x00000000;
-    mal->rxcasr = 0x00000000;
-    mal->rxdeir = 0x00000000;
-    mal->rxeobisr = 0x00000000;
-    mal->txcasr = 0x00000000;
-    mal->txdeir = 0x00000000;
-    mal->txeobisr = 0x00000000;
-}
-
-static void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
-{
-    ppc40x_mal_t *mal;
-    int i;
-
-    mal = g_malloc0(sizeof(ppc40x_mal_t));
-    for (i = 0; i < 4; i++)
-        mal->irqs[i] = irqs[i];
-    qemu_register_reset(&ppc40x_mal_reset, mal);
-    ppc_dcr_register(env, MAL0_CFG,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_ESR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_IER,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCASR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCARR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXEOBISR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXDEIR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCASR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCARR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXEOBISR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXDEIR,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP0R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP1R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP2R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_TXCTP3R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCTP0R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RXCTP1R,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RCBS0,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-    ppc_dcr_register(env, MAL0_RCBS1,
-                     mal, &dcr_read_mal, &dcr_write_mal);
-}
-
-/*****************************************************************************/
-/* SPR */
-void ppc40x_core_reset(PowerPCCPU *cpu)
-{
-    CPUPPCState *env = &cpu->env;
-    target_ulong dbsr;
-
-    printf("Reset PowerPC core\n");
-    cpu_interrupt(env, CPU_INTERRUPT_RESET);
-    dbsr = env->spr[SPR_40x_DBSR];
-    dbsr &= ~0x00000300;
-    dbsr |= 0x00000100;
-    env->spr[SPR_40x_DBSR] = dbsr;
-}
-
-void ppc40x_chip_reset(PowerPCCPU *cpu)
-{
-    CPUPPCState *env = &cpu->env;
-    target_ulong dbsr;
-
-    printf("Reset PowerPC chip\n");
-    cpu_interrupt(env, CPU_INTERRUPT_RESET);
-    /* XXX: TODO reset all internal peripherals */
-    dbsr = env->spr[SPR_40x_DBSR];
-    dbsr &= ~0x00000300;
-    dbsr |= 0x00000200;
-    env->spr[SPR_40x_DBSR] = dbsr;
-}
-
-void ppc40x_system_reset(PowerPCCPU *cpu)
-{
-    printf("Reset PowerPC system\n");
-    qemu_system_reset_request();
-}
-
-void store_40x_dbcr0 (CPUPPCState *env, uint32_t val)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    switch ((val >> 28) & 0x3) {
-    case 0x0:
-        /* No action */
-        break;
-    case 0x1:
-        /* Core reset */
-        ppc40x_core_reset(cpu);
-        break;
-    case 0x2:
-        /* Chip reset */
-        ppc40x_chip_reset(cpu);
-        break;
-    case 0x3:
-        /* System reset */
-        ppc40x_system_reset(cpu);
-        break;
-    }
-}
-
-/*****************************************************************************/
-/* PowerPC 405CR */
-enum {
-    PPC405CR_CPC0_PLLMR  = 0x0B0,
-    PPC405CR_CPC0_CR0    = 0x0B1,
-    PPC405CR_CPC0_CR1    = 0x0B2,
-    PPC405CR_CPC0_PSR    = 0x0B4,
-    PPC405CR_CPC0_JTAGID = 0x0B5,
-    PPC405CR_CPC0_ER     = 0x0B9,
-    PPC405CR_CPC0_FR     = 0x0BA,
-    PPC405CR_CPC0_SR     = 0x0BB,
-};
-
-enum {
-    PPC405CR_CPU_CLK   = 0,
-    PPC405CR_TMR_CLK   = 1,
-    PPC405CR_PLB_CLK   = 2,
-    PPC405CR_SDRAM_CLK = 3,
-    PPC405CR_OPB_CLK   = 4,
-    PPC405CR_EXT_CLK   = 5,
-    PPC405CR_UART_CLK  = 6,
-    PPC405CR_CLK_NB    = 7,
-};
-
-typedef struct ppc405cr_cpc_t ppc405cr_cpc_t;
-struct ppc405cr_cpc_t {
-    clk_setup_t clk_setup[PPC405CR_CLK_NB];
-    uint32_t sysclk;
-    uint32_t psr;
-    uint32_t cr0;
-    uint32_t cr1;
-    uint32_t jtagid;
-    uint32_t pllmr;
-    uint32_t er;
-    uint32_t fr;
-};
-
-static void ppc405cr_clk_setup (ppc405cr_cpc_t *cpc)
-{
-    uint64_t VCO_out, PLL_out;
-    uint32_t CPU_clk, TMR_clk, SDRAM_clk, PLB_clk, OPB_clk, EXT_clk, UART_clk;
-    int M, D0, D1, D2;
-
-    D0 = ((cpc->pllmr >> 26) & 0x3) + 1; /* CBDV */
-    if (cpc->pllmr & 0x80000000) {
-        D1 = (((cpc->pllmr >> 20) - 1) & 0xF) + 1; /* FBDV */
-        D2 = 8 - ((cpc->pllmr >> 16) & 0x7); /* FWDVA */
-        M = D0 * D1 * D2;
-        VCO_out = cpc->sysclk * M;
-        if (VCO_out < 400000000 || VCO_out > 800000000) {
-            /* PLL cannot lock */
-            cpc->pllmr &= ~0x80000000;
-            goto bypass_pll;
-        }
-        PLL_out = VCO_out / D2;
-    } else {
-        /* Bypass PLL */
-    bypass_pll:
-        M = D0;
-        PLL_out = cpc->sysclk * M;
-    }
-    CPU_clk = PLL_out;
-    if (cpc->cr1 & 0x00800000)
-        TMR_clk = cpc->sysclk; /* Should have a separate clock */
-    else
-        TMR_clk = CPU_clk;
-    PLB_clk = CPU_clk / D0;
-    SDRAM_clk = PLB_clk;
-    D0 = ((cpc->pllmr >> 10) & 0x3) + 1;
-    OPB_clk = PLB_clk / D0;
-    D0 = ((cpc->pllmr >> 24) & 0x3) + 2;
-    EXT_clk = PLB_clk / D0;
-    D0 = ((cpc->cr0 >> 1) & 0x1F) + 1;
-    UART_clk = CPU_clk / D0;
-    /* Setup CPU clocks */
-    clk_setup(&cpc->clk_setup[PPC405CR_CPU_CLK], CPU_clk);
-    /* Setup time-base clock */
-    clk_setup(&cpc->clk_setup[PPC405CR_TMR_CLK], TMR_clk);
-    /* Setup PLB clock */
-    clk_setup(&cpc->clk_setup[PPC405CR_PLB_CLK], PLB_clk);
-    /* Setup SDRAM clock */
-    clk_setup(&cpc->clk_setup[PPC405CR_SDRAM_CLK], SDRAM_clk);
-    /* Setup OPB clock */
-    clk_setup(&cpc->clk_setup[PPC405CR_OPB_CLK], OPB_clk);
-    /* Setup external clock */
-    clk_setup(&cpc->clk_setup[PPC405CR_EXT_CLK], EXT_clk);
-    /* Setup UART clock */
-    clk_setup(&cpc->clk_setup[PPC405CR_UART_CLK], UART_clk);
-}
-
-static uint32_t dcr_read_crcpc (void *opaque, int dcrn)
-{
-    ppc405cr_cpc_t *cpc;
-    uint32_t ret;
-
-    cpc = opaque;
-    switch (dcrn) {
-    case PPC405CR_CPC0_PLLMR:
-        ret = cpc->pllmr;
-        break;
-    case PPC405CR_CPC0_CR0:
-        ret = cpc->cr0;
-        break;
-    case PPC405CR_CPC0_CR1:
-        ret = cpc->cr1;
-        break;
-    case PPC405CR_CPC0_PSR:
-        ret = cpc->psr;
-        break;
-    case PPC405CR_CPC0_JTAGID:
-        ret = cpc->jtagid;
-        break;
-    case PPC405CR_CPC0_ER:
-        ret = cpc->er;
-        break;
-    case PPC405CR_CPC0_FR:
-        ret = cpc->fr;
-        break;
-    case PPC405CR_CPC0_SR:
-        ret = ~(cpc->er | cpc->fr) & 0xFFFF0000;
-        break;
-    default:
-        /* Avoid gcc warning */
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_crcpc (void *opaque, int dcrn, uint32_t val)
-{
-    ppc405cr_cpc_t *cpc;
-
-    cpc = opaque;
-    switch (dcrn) {
-    case PPC405CR_CPC0_PLLMR:
-        cpc->pllmr = val & 0xFFF77C3F;
-        break;
-    case PPC405CR_CPC0_CR0:
-        cpc->cr0 = val & 0x0FFFFFFE;
-        break;
-    case PPC405CR_CPC0_CR1:
-        cpc->cr1 = val & 0x00800000;
-        break;
-    case PPC405CR_CPC0_PSR:
-        /* Read-only */
-        break;
-    case PPC405CR_CPC0_JTAGID:
-        /* Read-only */
-        break;
-    case PPC405CR_CPC0_ER:
-        cpc->er = val & 0xBFFC0000;
-        break;
-    case PPC405CR_CPC0_FR:
-        cpc->fr = val & 0xBFFC0000;
-        break;
-    case PPC405CR_CPC0_SR:
-        /* Read-only */
-        break;
-    }
-}
-
-static void ppc405cr_cpc_reset (void *opaque)
-{
-    ppc405cr_cpc_t *cpc;
-    int D;
-
-    cpc = opaque;
-    /* Compute PLLMR value from PSR settings */
-    cpc->pllmr = 0x80000000;
-    /* PFWD */
-    switch ((cpc->psr >> 30) & 3) {
-    case 0:
-        /* Bypass */
-        cpc->pllmr &= ~0x80000000;
-        break;
-    case 1:
-        /* Divide by 3 */
-        cpc->pllmr |= 5 << 16;
-        break;
-    case 2:
-        /* Divide by 4 */
-        cpc->pllmr |= 4 << 16;
-        break;
-    case 3:
-        /* Divide by 6 */
-        cpc->pllmr |= 2 << 16;
-        break;
-    }
-    /* PFBD */
-    D = (cpc->psr >> 28) & 3;
-    cpc->pllmr |= (D + 1) << 20;
-    /* PT   */
-    D = (cpc->psr >> 25) & 7;
-    switch (D) {
-    case 0x2:
-        cpc->pllmr |= 0x13;
-        break;
-    case 0x4:
-        cpc->pllmr |= 0x15;
-        break;
-    case 0x5:
-        cpc->pllmr |= 0x16;
-        break;
-    default:
-        break;
-    }
-    /* PDC  */
-    D = (cpc->psr >> 23) & 3;
-    cpc->pllmr |= D << 26;
-    /* ODP  */
-    D = (cpc->psr >> 21) & 3;
-    cpc->pllmr |= D << 10;
-    /* EBPD */
-    D = (cpc->psr >> 17) & 3;
-    cpc->pllmr |= D << 24;
-    cpc->cr0 = 0x0000003C;
-    cpc->cr1 = 0x2B0D8800;
-    cpc->er = 0x00000000;
-    cpc->fr = 0x00000000;
-    ppc405cr_clk_setup(cpc);
-}
-
-static void ppc405cr_clk_init (ppc405cr_cpc_t *cpc)
-{
-    int D;
-
-    /* XXX: this should be read from IO pins */
-    cpc->psr = 0x00000000; /* 8 bits ROM */
-    /* PFWD */
-    D = 0x2; /* Divide by 4 */
-    cpc->psr |= D << 30;
-    /* PFBD */
-    D = 0x1; /* Divide by 2 */
-    cpc->psr |= D << 28;
-    /* PDC */
-    D = 0x1; /* Divide by 2 */
-    cpc->psr |= D << 23;
-    /* PT */
-    D = 0x5; /* M = 16 */
-    cpc->psr |= D << 25;
-    /* ODP */
-    D = 0x1; /* Divide by 2 */
-    cpc->psr |= D << 21;
-    /* EBDP */
-    D = 0x2; /* Divide by 4 */
-    cpc->psr |= D << 17;
-}
-
-static void ppc405cr_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[7],
-                               uint32_t sysclk)
-{
-    ppc405cr_cpc_t *cpc;
-
-    cpc = g_malloc0(sizeof(ppc405cr_cpc_t));
-    memcpy(cpc->clk_setup, clk_setup,
-           PPC405CR_CLK_NB * sizeof(clk_setup_t));
-    cpc->sysclk = sysclk;
-    cpc->jtagid = 0x42051049;
-    ppc_dcr_register(env, PPC405CR_CPC0_PSR, cpc,
-                     &dcr_read_crcpc, &dcr_write_crcpc);
-    ppc_dcr_register(env, PPC405CR_CPC0_CR0, cpc,
-                     &dcr_read_crcpc, &dcr_write_crcpc);
-    ppc_dcr_register(env, PPC405CR_CPC0_CR1, cpc,
-                     &dcr_read_crcpc, &dcr_write_crcpc);
-    ppc_dcr_register(env, PPC405CR_CPC0_JTAGID, cpc,
-                     &dcr_read_crcpc, &dcr_write_crcpc);
-    ppc_dcr_register(env, PPC405CR_CPC0_PLLMR, cpc,
-                     &dcr_read_crcpc, &dcr_write_crcpc);
-    ppc_dcr_register(env, PPC405CR_CPC0_ER, cpc,
-                     &dcr_read_crcpc, &dcr_write_crcpc);
-    ppc_dcr_register(env, PPC405CR_CPC0_FR, cpc,
-                     &dcr_read_crcpc, &dcr_write_crcpc);
-    ppc_dcr_register(env, PPC405CR_CPC0_SR, cpc,
-                     &dcr_read_crcpc, &dcr_write_crcpc);
-    ppc405cr_clk_init(cpc);
-    qemu_register_reset(ppc405cr_cpc_reset, cpc);
-}
-
-CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
-                        MemoryRegion ram_memories[4],
-                        hwaddr ram_bases[4],
-                        hwaddr ram_sizes[4],
-                        uint32_t sysclk, qemu_irq **picp,
-                        int do_init)
-{
-    clk_setup_t clk_setup[PPC405CR_CLK_NB];
-    qemu_irq dma_irqs[4];
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    qemu_irq *pic, *irqs;
-
-    memset(clk_setup, 0, sizeof(clk_setup));
-    cpu = ppc4xx_init("405cr", &clk_setup[PPC405CR_CPU_CLK],
-                      &clk_setup[PPC405CR_TMR_CLK], sysclk);
-    env = &cpu->env;
-    /* Memory mapped devices registers */
-    /* PLB arbitrer */
-    ppc4xx_plb_init(env);
-    /* PLB to OPB bridge */
-    ppc4xx_pob_init(env);
-    /* OBP arbitrer */
-    ppc4xx_opba_init(0xef600600);
-    /* Universal interrupt controller */
-    irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
-    irqs[PPCUIC_OUTPUT_INT] =
-        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
-    irqs[PPCUIC_OUTPUT_CINT] =
-        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
-    pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
-    *picp = pic;
-    /* SDRAM controller */
-    ppc4xx_sdram_init(env, pic[14], 1, ram_memories,
-                      ram_bases, ram_sizes, do_init);
-    /* External bus controller */
-    ppc405_ebc_init(env);
-    /* DMA controller */
-    dma_irqs[0] = pic[26];
-    dma_irqs[1] = pic[25];
-    dma_irqs[2] = pic[24];
-    dma_irqs[3] = pic[23];
-    ppc405_dma_init(env, dma_irqs);
-    /* Serial ports */
-    if (serial_hds[0] != NULL) {
-        serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
-                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
-                       DEVICE_BIG_ENDIAN);
-    }
-    if (serial_hds[1] != NULL) {
-        serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
-                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
-                       DEVICE_BIG_ENDIAN);
-    }
-    /* IIC controller */
-    ppc405_i2c_init(0xef600500, pic[2]);
-    /* GPIO */
-    ppc405_gpio_init(0xef600700);
-    /* CPU control */
-    ppc405cr_cpc_init(env, clk_setup, sysclk);
-
-    return env;
-}
-
-/*****************************************************************************/
-/* PowerPC 405EP */
-/* CPU control */
-enum {
-    PPC405EP_CPC0_PLLMR0 = 0x0F0,
-    PPC405EP_CPC0_BOOT   = 0x0F1,
-    PPC405EP_CPC0_EPCTL  = 0x0F3,
-    PPC405EP_CPC0_PLLMR1 = 0x0F4,
-    PPC405EP_CPC0_UCR    = 0x0F5,
-    PPC405EP_CPC0_SRR    = 0x0F6,
-    PPC405EP_CPC0_JTAGID = 0x0F7,
-    PPC405EP_CPC0_PCI    = 0x0F9,
-#if 0
-    PPC405EP_CPC0_ER     = xxx,
-    PPC405EP_CPC0_FR     = xxx,
-    PPC405EP_CPC0_SR     = xxx,
-#endif
-};
-
-enum {
-    PPC405EP_CPU_CLK   = 0,
-    PPC405EP_PLB_CLK   = 1,
-    PPC405EP_OPB_CLK   = 2,
-    PPC405EP_EBC_CLK   = 3,
-    PPC405EP_MAL_CLK   = 4,
-    PPC405EP_PCI_CLK   = 5,
-    PPC405EP_UART0_CLK = 6,
-    PPC405EP_UART1_CLK = 7,
-    PPC405EP_CLK_NB    = 8,
-};
-
-typedef struct ppc405ep_cpc_t ppc405ep_cpc_t;
-struct ppc405ep_cpc_t {
-    uint32_t sysclk;
-    clk_setup_t clk_setup[PPC405EP_CLK_NB];
-    uint32_t boot;
-    uint32_t epctl;
-    uint32_t pllmr[2];
-    uint32_t ucr;
-    uint32_t srr;
-    uint32_t jtagid;
-    uint32_t pci;
-    /* Clock and power management */
-    uint32_t er;
-    uint32_t fr;
-    uint32_t sr;
-};
-
-static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc)
-{
-    uint32_t CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk;
-    uint32_t UART0_clk, UART1_clk;
-    uint64_t VCO_out, PLL_out;
-    int M, D;
-
-    VCO_out = 0;
-    if ((cpc->pllmr[1] & 0x80000000) && !(cpc->pllmr[1] & 0x40000000)) {
-        M = (((cpc->pllmr[1] >> 20) - 1) & 0xF) + 1; /* FBMUL */
-#ifdef DEBUG_CLOCKS_LL
-        printf("FBMUL %01" PRIx32 " %d\n", (cpc->pllmr[1] >> 20) & 0xF, M);
-#endif
-        D = 8 - ((cpc->pllmr[1] >> 16) & 0x7); /* FWDA */
-#ifdef DEBUG_CLOCKS_LL
-        printf("FWDA %01" PRIx32 " %d\n", (cpc->pllmr[1] >> 16) & 0x7, D);
-#endif
-        VCO_out = cpc->sysclk * M * D;
-        if (VCO_out < 500000000UL || VCO_out > 1000000000UL) {
-            /* Error - unlock the PLL */
-            printf("VCO out of range %" PRIu64 "\n", VCO_out);
-#if 0
-            cpc->pllmr[1] &= ~0x80000000;
-            goto pll_bypass;
-#endif
-        }
-        PLL_out = VCO_out / D;
-        /* Pretend the PLL is locked */
-        cpc->boot |= 0x00000001;
-    } else {
-#if 0
-    pll_bypass:
-#endif
-        PLL_out = cpc->sysclk;
-        if (cpc->pllmr[1] & 0x40000000) {
-            /* Pretend the PLL is not locked */
-            cpc->boot &= ~0x00000001;
-        }
-    }
-    /* Now, compute all other clocks */
-    D = ((cpc->pllmr[0] >> 20) & 0x3) + 1; /* CCDV */
-#ifdef DEBUG_CLOCKS_LL
-    printf("CCDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 20) & 0x3, D);
-#endif
-    CPU_clk = PLL_out / D;
-    D = ((cpc->pllmr[0] >> 16) & 0x3) + 1; /* CBDV */
-#ifdef DEBUG_CLOCKS_LL
-    printf("CBDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 16) & 0x3, D);
-#endif
-    PLB_clk = CPU_clk / D;
-    D = ((cpc->pllmr[0] >> 12) & 0x3) + 1; /* OPDV */
-#ifdef DEBUG_CLOCKS_LL
-    printf("OPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 12) & 0x3, D);
-#endif
-    OPB_clk = PLB_clk / D;
-    D = ((cpc->pllmr[0] >> 8) & 0x3) + 2; /* EPDV */
-#ifdef DEBUG_CLOCKS_LL
-    printf("EPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 8) & 0x3, D);
-#endif
-    EBC_clk = PLB_clk / D;
-    D = ((cpc->pllmr[0] >> 4) & 0x3) + 1; /* MPDV */
-#ifdef DEBUG_CLOCKS_LL
-    printf("MPDV %01" PRIx32 " %d\n", (cpc->pllmr[0] >> 4) & 0x3, D);
-#endif
-    MAL_clk = PLB_clk / D;
-    D = (cpc->pllmr[0] & 0x3) + 1; /* PPDV */
-#ifdef DEBUG_CLOCKS_LL
-    printf("PPDV %01" PRIx32 " %d\n", cpc->pllmr[0] & 0x3, D);
-#endif
-    PCI_clk = PLB_clk / D;
-    D = ((cpc->ucr - 1) & 0x7F) + 1; /* U0DIV */
-#ifdef DEBUG_CLOCKS_LL
-    printf("U0DIV %01" PRIx32 " %d\n", cpc->ucr & 0x7F, D);
-#endif
-    UART0_clk = PLL_out / D;
-    D = (((cpc->ucr >> 8) - 1) & 0x7F) + 1; /* U1DIV */
-#ifdef DEBUG_CLOCKS_LL
-    printf("U1DIV %01" PRIx32 " %d\n", (cpc->ucr >> 8) & 0x7F, D);
-#endif
-    UART1_clk = PLL_out / D;
-#ifdef DEBUG_CLOCKS
-    printf("Setup PPC405EP clocks - sysclk %" PRIu32 " VCO %" PRIu64
-           " PLL out %" PRIu64 " Hz\n", cpc->sysclk, VCO_out, PLL_out);
-    printf("CPU %" PRIu32 " PLB %" PRIu32 " OPB %" PRIu32 " EBC %" PRIu32
-           " MAL %" PRIu32 " PCI %" PRIu32 " UART0 %" PRIu32
-           " UART1 %" PRIu32 "\n",
-           CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk,
-           UART0_clk, UART1_clk);
-#endif
-    /* Setup CPU clocks */
-    clk_setup(&cpc->clk_setup[PPC405EP_CPU_CLK], CPU_clk);
-    /* Setup PLB clock */
-    clk_setup(&cpc->clk_setup[PPC405EP_PLB_CLK], PLB_clk);
-    /* Setup OPB clock */
-    clk_setup(&cpc->clk_setup[PPC405EP_OPB_CLK], OPB_clk);
-    /* Setup external clock */
-    clk_setup(&cpc->clk_setup[PPC405EP_EBC_CLK], EBC_clk);
-    /* Setup MAL clock */
-    clk_setup(&cpc->clk_setup[PPC405EP_MAL_CLK], MAL_clk);
-    /* Setup PCI clock */
-    clk_setup(&cpc->clk_setup[PPC405EP_PCI_CLK], PCI_clk);
-    /* Setup UART0 clock */
-    clk_setup(&cpc->clk_setup[PPC405EP_UART0_CLK], UART0_clk);
-    /* Setup UART1 clock */
-    clk_setup(&cpc->clk_setup[PPC405EP_UART1_CLK], UART1_clk);
-}
-
-static uint32_t dcr_read_epcpc (void *opaque, int dcrn)
-{
-    ppc405ep_cpc_t *cpc;
-    uint32_t ret;
-
-    cpc = opaque;
-    switch (dcrn) {
-    case PPC405EP_CPC0_BOOT:
-        ret = cpc->boot;
-        break;
-    case PPC405EP_CPC0_EPCTL:
-        ret = cpc->epctl;
-        break;
-    case PPC405EP_CPC0_PLLMR0:
-        ret = cpc->pllmr[0];
-        break;
-    case PPC405EP_CPC0_PLLMR1:
-        ret = cpc->pllmr[1];
-        break;
-    case PPC405EP_CPC0_UCR:
-        ret = cpc->ucr;
-        break;
-    case PPC405EP_CPC0_SRR:
-        ret = cpc->srr;
-        break;
-    case PPC405EP_CPC0_JTAGID:
-        ret = cpc->jtagid;
-        break;
-    case PPC405EP_CPC0_PCI:
-        ret = cpc->pci;
-        break;
-    default:
-        /* Avoid gcc warning */
-        ret = 0;
-        break;
-    }
-
-    return ret;
-}
-
-static void dcr_write_epcpc (void *opaque, int dcrn, uint32_t val)
-{
-    ppc405ep_cpc_t *cpc;
-
-    cpc = opaque;
-    switch (dcrn) {
-    case PPC405EP_CPC0_BOOT:
-        /* Read-only register */
-        break;
-    case PPC405EP_CPC0_EPCTL:
-        /* Don't care for now */
-        cpc->epctl = val & 0xC00000F3;
-        break;
-    case PPC405EP_CPC0_PLLMR0:
-        cpc->pllmr[0] = val & 0x00633333;
-        ppc405ep_compute_clocks(cpc);
-        break;
-    case PPC405EP_CPC0_PLLMR1:
-        cpc->pllmr[1] = val & 0xC0F73FFF;
-        ppc405ep_compute_clocks(cpc);
-        break;
-    case PPC405EP_CPC0_UCR:
-        /* UART control - don't care for now */
-        cpc->ucr = val & 0x003F7F7F;
-        break;
-    case PPC405EP_CPC0_SRR:
-        cpc->srr = val;
-        break;
-    case PPC405EP_CPC0_JTAGID:
-        /* Read-only */
-        break;
-    case PPC405EP_CPC0_PCI:
-        cpc->pci = val;
-        break;
-    }
-}
-
-static void ppc405ep_cpc_reset (void *opaque)
-{
-    ppc405ep_cpc_t *cpc = opaque;
-
-    cpc->boot = 0x00000010;     /* Boot from PCI - IIC EEPROM disabled */
-    cpc->epctl = 0x00000000;
-    cpc->pllmr[0] = 0x00011010;
-    cpc->pllmr[1] = 0x40000000;
-    cpc->ucr = 0x00000000;
-    cpc->srr = 0x00040000;
-    cpc->pci = 0x00000000;
-    cpc->er = 0x00000000;
-    cpc->fr = 0x00000000;
-    cpc->sr = 0x00000000;
-    ppc405ep_compute_clocks(cpc);
-}
-
-/* XXX: sysclk should be between 25 and 100 MHz */
-static void ppc405ep_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[8],
-                               uint32_t sysclk)
-{
-    ppc405ep_cpc_t *cpc;
-
-    cpc = g_malloc0(sizeof(ppc405ep_cpc_t));
-    memcpy(cpc->clk_setup, clk_setup,
-           PPC405EP_CLK_NB * sizeof(clk_setup_t));
-    cpc->jtagid = 0x20267049;
-    cpc->sysclk = sysclk;
-    qemu_register_reset(&ppc405ep_cpc_reset, cpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_BOOT, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_EPCTL, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_PLLMR0, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_PLLMR1, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_UCR, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_SRR, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_JTAGID, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_PCI, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-#if 0
-    ppc_dcr_register(env, PPC405EP_CPC0_ER, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_FR, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-    ppc_dcr_register(env, PPC405EP_CPC0_SR, cpc,
-                     &dcr_read_epcpc, &dcr_write_epcpc);
-#endif
-}
-
-CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
-                        MemoryRegion ram_memories[2],
-                        hwaddr ram_bases[2],
-                        hwaddr ram_sizes[2],
-                        uint32_t sysclk, qemu_irq **picp,
-                        int do_init)
-{
-    clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup;
-    qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4];
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    qemu_irq *pic, *irqs;
-
-    memset(clk_setup, 0, sizeof(clk_setup));
-    /* init CPUs */
-    cpu = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
-                      &tlb_clk_setup, sysclk);
-    env = &cpu->env;
-    clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
-    clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque;
-    /* Internal devices init */
-    /* Memory mapped devices registers */
-    /* PLB arbitrer */
-    ppc4xx_plb_init(env);
-    /* PLB to OPB bridge */
-    ppc4xx_pob_init(env);
-    /* OBP arbitrer */
-    ppc4xx_opba_init(0xef600600);
-    /* Initialize timers */
-    ppc_booke_timers_init(cpu, sysclk, 0);
-    /* Universal interrupt controller */
-    irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
-    irqs[PPCUIC_OUTPUT_INT] =
-        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
-    irqs[PPCUIC_OUTPUT_CINT] =
-        ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
-    pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
-    *picp = pic;
-    /* SDRAM controller */
-	/* XXX 405EP has no ECC interrupt */
-    ppc4xx_sdram_init(env, pic[17], 2, ram_memories,
-                      ram_bases, ram_sizes, do_init);
-    /* External bus controller */
-    ppc405_ebc_init(env);
-    /* DMA controller */
-    dma_irqs[0] = pic[5];
-    dma_irqs[1] = pic[6];
-    dma_irqs[2] = pic[7];
-    dma_irqs[3] = pic[8];
-    ppc405_dma_init(env, dma_irqs);
-    /* IIC controller */
-    ppc405_i2c_init(0xef600500, pic[2]);
-    /* GPIO */
-    ppc405_gpio_init(0xef600700);
-    /* Serial ports */
-    if (serial_hds[0] != NULL) {
-        serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
-                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
-                       DEVICE_BIG_ENDIAN);
-    }
-    if (serial_hds[1] != NULL) {
-        serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
-                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
-                       DEVICE_BIG_ENDIAN);
-    }
-    /* OCM */
-    ppc405_ocm_init(env);
-    /* GPT */
-    gpt_irqs[0] = pic[19];
-    gpt_irqs[1] = pic[20];
-    gpt_irqs[2] = pic[21];
-    gpt_irqs[3] = pic[22];
-    gpt_irqs[4] = pic[23];
-    ppc4xx_gpt_init(0xef600000, gpt_irqs);
-    /* PCI */
-    /* Uses pic[3], pic[16], pic[18] */
-    /* MAL */
-    mal_irqs[0] = pic[11];
-    mal_irqs[1] = pic[12];
-    mal_irqs[2] = pic[13];
-    mal_irqs[3] = pic[14];
-    ppc405_mal_init(env, mal_irqs);
-    /* Ethernet */
-    /* Uses pic[9], pic[15], pic[17] */
-    /* CPU control */
-    ppc405ep_cpc_init(env, clk_setup, sysclk);
-
-    return env;
-}
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
deleted file mode 100644
index 66911b5..0000000
--- a/hw/ppc440_bamboo.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * QEMU PowerPC 440 Bamboo board emulation
- *
- * Copyright 2007 IBM Corporation.
- * Authors:
- *	Jerone Young <jyoung5 at us.ibm.com>
- *	Christian Ehrhardt <ehrhardt at linux.vnet.ibm.com>
- *	Hollis Blanchard <hollisb at us.ibm.com>
- *
- * This work is licensed under the GNU GPL license version 2 or later.
- *
- */
-
-#include "config.h"
-#include "qemu-common.h"
-#include "net/net.h"
-#include "hw/hw.h"
-#include "hw/pci/pci.h"
-#include "hw/boards.h"
-#include "sysemu/kvm.h"
-#include "kvm_ppc.h"
-#include "sysemu/device_tree.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "exec/address-spaces.h"
-#include "hw/serial.h"
-#include "hw/ppc.h"
-#include "hw/ppc405.h"
-#include "sysemu/sysemu.h"
-#include "hw/sysbus.h"
-
-#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
-
-/* from u-boot */
-#define KERNEL_ADDR  0x1000000
-#define FDT_ADDR     0x1800000
-#define RAMDISK_ADDR 0x1900000
-
-#define PPC440EP_PCI_CONFIG     0xeec00000
-#define PPC440EP_PCI_INTACK     0xeed00000
-#define PPC440EP_PCI_SPECIAL    0xeed00000
-#define PPC440EP_PCI_REGS       0xef400000
-#define PPC440EP_PCI_IO         0xe8000000
-#define PPC440EP_PCI_IOLEN      0x00010000
-
-#define PPC440EP_SDRAM_NR_BANKS 4
-
-static const unsigned int ppc440ep_sdram_bank_sizes[] = {
-    256<<20, 128<<20, 64<<20, 32<<20, 16<<20, 8<<20, 0
-};
-
-static hwaddr entry;
-
-static int bamboo_load_device_tree(hwaddr addr,
-                                     uint32_t ramsize,
-                                     hwaddr initrd_base,
-                                     hwaddr initrd_size,
-                                     const char *kernel_cmdline)
-{
-    int ret = -1;
-#ifdef CONFIG_FDT
-    uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) };
-    char *filename;
-    int fdt_size;
-    void *fdt;
-    uint32_t tb_freq = 400000000;
-    uint32_t clock_freq = 400000000;
-
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
-    if (!filename) {
-        goto out;
-    }
-    fdt = load_device_tree(filename, &fdt_size);
-    g_free(filename);
-    if (fdt == NULL) {
-        goto out;
-    }
-
-    /* Manipulate device tree in memory. */
-
-    ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
-                               sizeof(mem_reg_property));
-    if (ret < 0)
-        fprintf(stderr, "couldn't set /memory/reg\n");
-
-    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
-                                    initrd_base);
-    if (ret < 0)
-        fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
-
-    ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
-                                    (initrd_base + initrd_size));
-    if (ret < 0)
-        fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
-
-    ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
-                                      kernel_cmdline);
-    if (ret < 0)
-        fprintf(stderr, "couldn't set /chosen/bootargs\n");
-
-    /* Copy data from the host device tree into the guest. Since the guest can
-     * directly access the timebase without host involvement, we must expose
-     * the correct frequencies. */
-    if (kvm_enabled()) {
-        tb_freq = kvmppc_get_tbfreq();
-        clock_freq = kvmppc_get_clockfreq();
-    }
-
-    qemu_devtree_setprop_cell(fdt, "/cpus/cpu at 0", "clock-frequency",
-                              clock_freq);
-    qemu_devtree_setprop_cell(fdt, "/cpus/cpu at 0", "timebase-frequency",
-                              tb_freq);
-
-    ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
-    g_free(fdt);
-
-out:
-#endif
-
-    return ret;
-}
-
-/* Create reset TLB entries for BookE, spanning the 32bit addr space.  */
-static void mmubooke_create_initial_mapping(CPUPPCState *env,
-                                     target_ulong va,
-                                     hwaddr pa)
-{
-    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
-
-    tlb->attr = 0;
-    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
-    tlb->size = 1 << 31; /* up to 0x80000000  */
-    tlb->EPN = va & TARGET_PAGE_MASK;
-    tlb->RPN = pa & TARGET_PAGE_MASK;
-    tlb->PID = 0;
-
-    tlb = &env->tlb.tlbe[1];
-    tlb->attr = 0;
-    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
-    tlb->size = 1 << 31; /* up to 0xffffffff  */
-    tlb->EPN = 0x80000000 & TARGET_PAGE_MASK;
-    tlb->RPN = 0x80000000 & TARGET_PAGE_MASK;
-    tlb->PID = 0;
-}
-
-static void main_cpu_reset(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-
-    cpu_reset(CPU(cpu));
-    env->gpr[1] = (16<<20) - 8;
-    env->gpr[3] = FDT_ADDR;
-    env->nip = entry;
-
-    /* Create a mapping for the kernel.  */
-    mmubooke_create_initial_mapping(env, 0, 0);
-}
-
-static void bamboo_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ram_memories
-        = g_malloc(PPC440EP_SDRAM_NR_BANKS * sizeof(*ram_memories));
-    hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS];
-    hwaddr ram_sizes[PPC440EP_SDRAM_NR_BANKS];
-    qemu_irq *pic;
-    qemu_irq *irqs;
-    PCIBus *pcibus;
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    uint64_t elf_entry;
-    uint64_t elf_lowaddr;
-    hwaddr loadaddr = 0;
-    target_long initrd_size = 0;
-    DeviceState *dev;
-    int success;
-    int i;
-
-    /* Setup CPU. */
-    if (cpu_model == NULL) {
-        cpu_model = "440EP";
-    }
-    cpu = cpu_ppc_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to initialize CPU!\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    qemu_register_reset(main_cpu_reset, cpu);
-    ppc_booke_timers_init(cpu, 400000000, 0);
-    ppc_dcr_init(env, NULL, NULL);
-
-    /* interrupt controller */
-    irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
-    irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
-    irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
-    pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
-
-    /* SDRAM controller */
-    memset(ram_bases, 0, sizeof(ram_bases));
-    memset(ram_sizes, 0, sizeof(ram_sizes));
-    ram_size = ppc4xx_sdram_adjust(ram_size, PPC440EP_SDRAM_NR_BANKS,
-                                   ram_memories,
-                                   ram_bases, ram_sizes,
-                                   ppc440ep_sdram_bank_sizes);
-    /* XXX 440EP's ECC interrupts are on UIC1, but we've only created UIC0. */
-    ppc4xx_sdram_init(env, pic[14], PPC440EP_SDRAM_NR_BANKS, ram_memories,
-                      ram_bases, ram_sizes, 1);
-
-    /* PCI */
-    dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST_BRIDGE,
-                                PPC440EP_PCI_CONFIG,
-                                pic[pci_irq_nrs[0]], pic[pci_irq_nrs[1]],
-                                pic[pci_irq_nrs[2]], pic[pci_irq_nrs[3]],
-                                NULL);
-    pcibus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
-    if (!pcibus) {
-        fprintf(stderr, "couldn't create PCI controller!\n");
-        exit(1);
-    }
-
-    isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN);
-
-    if (serial_hds[0] != NULL) {
-        serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
-                       PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
-                       DEVICE_BIG_ENDIAN);
-    }
-    if (serial_hds[1] != NULL) {
-        serial_mm_init(address_space_mem, 0xef600400, 0, pic[1],
-                       PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
-                       DEVICE_BIG_ENDIAN);
-    }
-
-    if (pcibus) {
-        /* Register network interfaces. */
-        for (i = 0; i < nb_nics; i++) {
-            /* There are no PCI NICs on the Bamboo board, but there are
-             * PCI slots, so we can pick whatever default model we want. */
-            pci_nic_init_nofail(&nd_table[i], "e1000", NULL);
-        }
-    }
-
-    /* Load kernel. */
-    if (kernel_filename) {
-        success = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
-        if (success < 0) {
-            success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
-                               &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
-            entry = elf_entry;
-            loadaddr = elf_lowaddr;
-        }
-        /* XXX try again as binary */
-        if (success < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                    kernel_filename);
-            exit(1);
-        }
-    }
-
-    /* Load initrd. */
-    if (initrd_filename) {
-        initrd_size = load_image_targphys(initrd_filename, RAMDISK_ADDR,
-                                          ram_size - RAMDISK_ADDR);
-
-        if (initrd_size < 0) {
-            fprintf(stderr, "qemu: could not load ram disk '%s' at %x\n",
-                    initrd_filename, RAMDISK_ADDR);
-            exit(1);
-        }
-    }
-
-    /* If we're loading a kernel directly, we must load the device tree too. */
-    if (kernel_filename) {
-        if (bamboo_load_device_tree(FDT_ADDR, ram_size, RAMDISK_ADDR,
-                                    initrd_size, kernel_cmdline) < 0) {
-            fprintf(stderr, "couldn't load device tree\n");
-            exit(1);
-        }
-    }
-
-    if (kvm_enabled())
-        kvmppc_init();
-}
-
-static QEMUMachine bamboo_machine = {
-    .name = "bamboo",
-    .desc = "bamboo",
-    .init = bamboo_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void bamboo_machine_init(void)
-{
-    qemu_register_machine(&bamboo_machine);
-}
-
-machine_init(bamboo_machine_init);
diff --git a/hw/ppc_booke.c b/hw/ppc_booke.c
deleted file mode 100644
index 30375c0..0000000
--- a/hw/ppc_booke.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * QEMU PowerPC Booke hardware System Emulator
- *
- * Copyright (c) 2011 AdaCore
- *
- * 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/hw.h"
-#include "hw/ppc.h"
-#include "qemu/timer.h"
-#include "sysemu/sysemu.h"
-#include "hw/nvram.h"
-#include "qemu/log.h"
-#include "hw/loader.h"
-
-
-/* Timer Control Register */
-
-#define TCR_WP_SHIFT  30        /* Watchdog Timer Period */
-#define TCR_WP_MASK   (0x3 << TCR_WP_SHIFT)
-#define TCR_WRC_SHIFT 28        /* Watchdog Timer Reset Control */
-#define TCR_WRC_MASK  (0x3 << TCR_WRC_SHIFT)
-#define TCR_WIE       (1 << 27) /* Watchdog Timer Interrupt Enable */
-#define TCR_DIE       (1 << 26) /* Decrementer Interrupt Enable */
-#define TCR_FP_SHIFT  24        /* Fixed-Interval Timer Period */
-#define TCR_FP_MASK   (0x3 << TCR_FP_SHIFT)
-#define TCR_FIE       (1 << 23) /* Fixed-Interval Timer Interrupt Enable */
-#define TCR_ARE       (1 << 22) /* Auto-Reload Enable */
-
-/* Timer Control Register (e500 specific fields) */
-
-#define TCR_E500_FPEXT_SHIFT 13 /* Fixed-Interval Timer Period Extension */
-#define TCR_E500_FPEXT_MASK  (0xf << TCR_E500_FPEXT_SHIFT)
-#define TCR_E500_WPEXT_SHIFT 17 /* Watchdog Timer Period Extension */
-#define TCR_E500_WPEXT_MASK  (0xf << TCR_E500_WPEXT_SHIFT)
-
-/* Timer Status Register  */
-
-#define TSR_FIS       (1 << 26) /* Fixed-Interval Timer Interrupt Status */
-#define TSR_DIS       (1 << 27) /* Decrementer Interrupt Status */
-#define TSR_WRS_SHIFT 28        /* Watchdog Timer Reset Status */
-#define TSR_WRS_MASK  (0x3 << TSR_WRS_SHIFT)
-#define TSR_WIS       (1 << 30) /* Watchdog Timer Interrupt Status */
-#define TSR_ENW       (1 << 31) /* Enable Next Watchdog Timer */
-
-typedef struct booke_timer_t booke_timer_t;
-struct booke_timer_t {
-
-    uint64_t fit_next;
-    struct QEMUTimer *fit_timer;
-
-    uint64_t wdt_next;
-    struct QEMUTimer *wdt_timer;
-
-    uint32_t flags;
-};
-
-static void booke_update_irq(PowerPCCPU *cpu)
-{
-    CPUPPCState *env = &cpu->env;
-
-    ppc_set_irq(cpu, PPC_INTERRUPT_DECR,
-                (env->spr[SPR_BOOKE_TSR] & TSR_DIS
-                 && env->spr[SPR_BOOKE_TCR] & TCR_DIE));
-
-    ppc_set_irq(cpu, PPC_INTERRUPT_WDT,
-                (env->spr[SPR_BOOKE_TSR] & TSR_WIS
-                 && env->spr[SPR_BOOKE_TCR] & TCR_WIE));
-
-    ppc_set_irq(cpu, PPC_INTERRUPT_FIT,
-                (env->spr[SPR_BOOKE_TSR] & TSR_FIS
-                 && env->spr[SPR_BOOKE_TCR] & TCR_FIE));
-}
-
-/* Return the location of the bit of time base at which the FIT will raise an
-   interrupt */
-static uint8_t booke_get_fit_target(CPUPPCState *env, ppc_tb_t *tb_env)
-{
-    uint8_t fp = (env->spr[SPR_BOOKE_TCR] & TCR_FP_MASK) >> TCR_FP_SHIFT;
-
-    if (tb_env->flags & PPC_TIMER_E500) {
-        /* e500 Fixed-interval timer period extension */
-        uint32_t fpext = (env->spr[SPR_BOOKE_TCR] & TCR_E500_FPEXT_MASK)
-            >> TCR_E500_FPEXT_SHIFT;
-        fp = 63 - (fp | fpext << 2);
-    } else {
-        fp = env->fit_period[fp];
-    }
-
-    return fp;
-}
-
-/* Return the location of the bit of time base at which the WDT will raise an
-   interrupt */
-static uint8_t booke_get_wdt_target(CPUPPCState *env, ppc_tb_t *tb_env)
-{
-    uint8_t wp = (env->spr[SPR_BOOKE_TCR] & TCR_WP_MASK) >> TCR_WP_SHIFT;
-
-    if (tb_env->flags & PPC_TIMER_E500) {
-        /* e500 Watchdog timer period extension */
-        uint32_t wpext = (env->spr[SPR_BOOKE_TCR] & TCR_E500_WPEXT_MASK)
-            >> TCR_E500_WPEXT_SHIFT;
-        wp = 63 - (wp | wpext << 2);
-    } else {
-        wp = env->wdt_period[wp];
-    }
-
-    return wp;
-}
-
-static void booke_update_fixed_timer(CPUPPCState         *env,
-                                     uint8_t           target_bit,
-                                     uint64_t          *next,
-                                     struct QEMUTimer *timer)
-{
-    ppc_tb_t *tb_env = env->tb_env;
-    uint64_t lapse;
-    uint64_t tb;
-    uint64_t period = 1 << (target_bit + 1);
-    uint64_t now;
-
-    now = qemu_get_clock_ns(vm_clock);
-    tb  = cpu_ppc_get_tb(tb_env, now, tb_env->tb_offset);
-
-    lapse = period - ((tb - (1 << target_bit)) & (period - 1));
-
-    *next = now + muldiv64(lapse, get_ticks_per_sec(), tb_env->tb_freq);
-
-    /* XXX: If expire time is now. We can't run the callback because we don't
-     * have access to it. So we just set the timer one nanosecond later.
-     */
-
-    if (*next == now) {
-        (*next)++;
-    }
-
-    qemu_mod_timer(timer, *next);
-}
-
-static void booke_decr_cb(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-
-    env->spr[SPR_BOOKE_TSR] |= TSR_DIS;
-    booke_update_irq(cpu);
-
-    if (env->spr[SPR_BOOKE_TCR] & TCR_ARE) {
-        /* Auto Reload */
-        cpu_ppc_store_decr(env, env->spr[SPR_BOOKE_DECAR]);
-    }
-}
-
-static void booke_fit_cb(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-    ppc_tb_t *tb_env;
-    booke_timer_t *booke_timer;
-
-    tb_env = env->tb_env;
-    booke_timer = tb_env->opaque;
-    env->spr[SPR_BOOKE_TSR] |= TSR_FIS;
-
-    booke_update_irq(cpu);
-
-    booke_update_fixed_timer(env,
-                             booke_get_fit_target(env, tb_env),
-                             &booke_timer->fit_next,
-                             booke_timer->fit_timer);
-}
-
-static void booke_wdt_cb(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-    ppc_tb_t *tb_env;
-    booke_timer_t *booke_timer;
-
-    tb_env = env->tb_env;
-    booke_timer = tb_env->opaque;
-
-    /* TODO: There's lots of complicated stuff to do here */
-
-    booke_update_irq(cpu);
-
-    booke_update_fixed_timer(env,
-                             booke_get_wdt_target(env, tb_env),
-                             &booke_timer->wdt_next,
-                             booke_timer->wdt_timer);
-}
-
-void store_booke_tsr(CPUPPCState *env, target_ulong val)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
-    env->spr[SPR_BOOKE_TSR] &= ~val;
-    booke_update_irq(cpu);
-}
-
-void store_booke_tcr(CPUPPCState *env, target_ulong val)
-{
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-    ppc_tb_t *tb_env = env->tb_env;
-    booke_timer_t *booke_timer = tb_env->opaque;
-
-    tb_env = env->tb_env;
-    env->spr[SPR_BOOKE_TCR] = val;
-
-    booke_update_irq(cpu);
-
-    booke_update_fixed_timer(env,
-                             booke_get_fit_target(env, tb_env),
-                             &booke_timer->fit_next,
-                             booke_timer->fit_timer);
-
-    booke_update_fixed_timer(env,
-                             booke_get_wdt_target(env, tb_env),
-                             &booke_timer->wdt_next,
-                             booke_timer->wdt_timer);
-
-}
-
-static void ppc_booke_timer_reset_handle(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-
-    env->spr[SPR_BOOKE_TSR] = 0;
-    env->spr[SPR_BOOKE_TCR] = 0;
-
-    booke_update_irq(cpu);
-}
-
-void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags)
-{
-    ppc_tb_t *tb_env;
-    booke_timer_t *booke_timer;
-
-    tb_env      = g_malloc0(sizeof(ppc_tb_t));
-    booke_timer = g_malloc0(sizeof(booke_timer_t));
-
-    cpu->env.tb_env = tb_env;
-    tb_env->flags = flags | PPC_TIMER_BOOKE | PPC_DECR_ZERO_TRIGGERED;
-
-    tb_env->tb_freq    = freq;
-    tb_env->decr_freq  = freq;
-    tb_env->opaque     = booke_timer;
-    tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &booke_decr_cb, cpu);
-
-    booke_timer->fit_timer =
-        qemu_new_timer_ns(vm_clock, &booke_fit_cb, cpu);
-    booke_timer->wdt_timer =
-        qemu_new_timer_ns(vm_clock, &booke_wdt_cb, cpu);
-
-    qemu_register_reset(ppc_booke_timer_reset_handle, cpu);
-}
diff --git a/hw/puv3.c b/hw/puv3.c
deleted file mode 100644
index f9d0c2b..0000000
--- a/hw/puv3.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Generic PKUnity SoC machine and board descriptor
- *
- * Copyright (C) 2010-2012 Guan Xuetao
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation, or any later version.
- * See the COPYING file in the top-level directory.
- */
-
-#include "qemu-common.h"
-#include "ui/console.h"
-#include "elf.h"
-#include "exec/address-spaces.h"
-#include "hw/sysbus.h"
-#include "hw/boards.h"
-#include "hw/loader.h"
-#include "hw/pc.h"
-
-#undef DEBUG_PUV3
-#include "hw/puv3.h"
-
-#define KERNEL_LOAD_ADDR        0x03000000
-#define KERNEL_MAX_SIZE         0x00800000 /* Just a guess */
-
-static void puv3_intc_cpu_handler(void *opaque, int irq, int level)
-{
-    CPUUniCore32State *env = opaque;
-
-    assert(irq == 0);
-    if (level) {
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    } else {
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-}
-
-static void puv3_soc_init(CPUUniCore32State *env)
-{
-    qemu_irq *cpu_intc, irqs[PUV3_IRQS_NR];
-    DeviceState *dev;
-    MemoryRegion *i8042 = g_new(MemoryRegion, 1);
-    int i;
-
-    /* Initialize interrupt controller */
-    cpu_intc = qemu_allocate_irqs(puv3_intc_cpu_handler, env, 1);
-    dev = sysbus_create_simple("puv3_intc", PUV3_INTC_BASE, *cpu_intc);
-    for (i = 0; i < PUV3_IRQS_NR; i++) {
-        irqs[i] = qdev_get_gpio_in(dev, i);
-    }
-
-    /* Initialize minimal necessary devices for kernel booting */
-    sysbus_create_simple("puv3_pm", PUV3_PM_BASE, NULL);
-    sysbus_create_simple("puv3_dma", PUV3_DMA_BASE, NULL);
-    sysbus_create_simple("puv3_ost", PUV3_OST_BASE, irqs[PUV3_IRQS_OST0]);
-    sysbus_create_varargs("puv3_gpio", PUV3_GPIO_BASE,
-            irqs[PUV3_IRQS_GPIOLOW0], irqs[PUV3_IRQS_GPIOLOW1],
-            irqs[PUV3_IRQS_GPIOLOW2], irqs[PUV3_IRQS_GPIOLOW3],
-            irqs[PUV3_IRQS_GPIOLOW4], irqs[PUV3_IRQS_GPIOLOW5],
-            irqs[PUV3_IRQS_GPIOLOW6], irqs[PUV3_IRQS_GPIOLOW7],
-            irqs[PUV3_IRQS_GPIOHIGH], NULL);
-
-    /* Keyboard (i8042), mouse disabled for nographic */
-    i8042_mm_init(irqs[PUV3_IRQS_PS2_KBD], NULL, i8042, PUV3_REGS_OFFSET, 4);
-    memory_region_add_subregion(get_system_memory(), PUV3_PS2_BASE, i8042);
-}
-
-static void puv3_board_init(CPUUniCore32State *env, ram_addr_t ram_size)
-{
-    MemoryRegion *ram_memory = g_new(MemoryRegion, 1);
-
-    /* SDRAM at address zero.  */
-    memory_region_init_ram(ram_memory, "puv3.ram", ram_size);
-    vmstate_register_ram_global(ram_memory);
-    memory_region_add_subregion(get_system_memory(), 0, ram_memory);
-}
-
-static void puv3_load_kernel(const char *kernel_filename)
-{
-    int size;
-
-    assert(kernel_filename != NULL);
-
-    /* only zImage format supported */
-    size = load_image_targphys(kernel_filename, KERNEL_LOAD_ADDR,
-            KERNEL_MAX_SIZE);
-    if (size < 0) {
-        hw_error("Load kernel error: '%s'\n", kernel_filename);
-    }
-
-    /* cheat curses that we have a graphic console, only under ocd console */
-    graphic_console_init(NULL, NULL, NULL, NULL, NULL);
-}
-
-static void puv3_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *initrd_filename = args->initrd_filename;
-    CPUUniCore32State *env;
-
-    if (initrd_filename) {
-        hw_error("Please use kernel built-in initramdisk.\n");
-    }
-
-    if (!cpu_model) {
-        cpu_model = "UniCore-II";
-    }
-
-    env = cpu_init(cpu_model);
-    if (!env) {
-        hw_error("Unable to find CPU definition\n");
-    }
-
-    puv3_soc_init(env);
-    puv3_board_init(env, ram_size);
-    puv3_load_kernel(kernel_filename);
-}
-
-static QEMUMachine puv3_machine = {
-    .name = "puv3",
-    .desc = "PKUnity Version-3 based on UniCore32",
-    .init = puv3_init,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void puv3_machine_init(void)
-{
-    qemu_register_machine(&puv3_machine);
-}
-
-machine_init(puv3_machine_init)
diff --git a/hw/r2d.c b/hw/r2d.c
deleted file mode 100644
index faa03d2..0000000
--- a/hw/r2d.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Renesas SH7751R R2D-PLUS emulation
- *
- * Copyright (c) 2007 Magnus Damm
- * Copyright (c) 2008 Paul Mundt
- *
- * 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/sysbus.h"
-#include "hw/hw.h"
-#include "hw/sh.h"
-#include "hw/devices.h"
-#include "sysemu/sysemu.h"
-#include "hw/boards.h"
-#include "hw/pci/pci.h"
-#include "net/net.h"
-#include "hw/sh7750_regs.h"
-#include "hw/ide.h"
-#include "hw/loader.h"
-#include "hw/usb.h"
-#include "hw/flash.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-#define FLASH_BASE 0x00000000
-#define FLASH_SIZE 0x02000000
-
-#define SDRAM_BASE 0x0c000000 /* Physical location of SDRAM: Area 3 */
-#define SDRAM_SIZE 0x04000000
-
-#define SM501_VRAM_SIZE 0x800000
-
-#define BOOT_PARAMS_OFFSET 0x0010000
-/* CONFIG_BOOT_LINK_OFFSET of Linux kernel */
-#define LINUX_LOAD_OFFSET  0x0800000
-#define INITRD_LOAD_OFFSET 0x1800000
-
-#define PA_IRLMSK	0x00
-#define PA_POWOFF	0x30
-#define PA_VERREG	0x32
-#define PA_OUTPORT	0x36
-
-typedef struct {
-    uint16_t bcr;
-    uint16_t irlmsk;
-    uint16_t irlmon;
-    uint16_t cfctl;
-    uint16_t cfpow;
-    uint16_t dispctl;
-    uint16_t sdmpow;
-    uint16_t rtcce;
-    uint16_t pcicd;
-    uint16_t voyagerrts;
-    uint16_t cfrst;
-    uint16_t admrts;
-    uint16_t extrst;
-    uint16_t cfcdintclr;
-    uint16_t keyctlclr;
-    uint16_t pad0;
-    uint16_t pad1;
-    uint16_t verreg;
-    uint16_t inport;
-    uint16_t outport;
-    uint16_t bverreg;
-
-/* output pin */
-    qemu_irq irl;
-    MemoryRegion iomem;
-} r2d_fpga_t;
-
-enum r2d_fpga_irq {
-    PCI_INTD, CF_IDE, CF_CD, PCI_INTC, SM501, KEY, RTC_A, RTC_T,
-    SDCARD, PCI_INTA, PCI_INTB, EXT, TP,
-    NR_IRQS
-};
-
-static const struct { short irl; uint16_t msk; } irqtab[NR_IRQS] = {
-    [CF_IDE]	= {  1, 1<<9 },
-    [CF_CD]	= {  2, 1<<8 },
-    [PCI_INTA]	= {  9, 1<<14 },
-    [PCI_INTB]	= { 10, 1<<13 },
-    [PCI_INTC]	= {  3, 1<<12 },
-    [PCI_INTD]	= {  0, 1<<11 },
-    [SM501]	= {  4, 1<<10 },
-    [KEY]	= {  5, 1<<6 },
-    [RTC_A]	= {  6, 1<<5 },
-    [RTC_T]	= {  7, 1<<4 },
-    [SDCARD]	= {  8, 1<<7 },
-    [EXT]	= { 11, 1<<0 },
-    [TP]	= { 12, 1<<15 },
-};
-
-static void update_irl(r2d_fpga_t *fpga)
-{
-    int i, irl = 15;
-    for (i = 0; i < NR_IRQS; i++)
-        if (fpga->irlmon & fpga->irlmsk & irqtab[i].msk)
-            if (irqtab[i].irl < irl)
-                irl = irqtab[i].irl;
-    qemu_set_irq(fpga->irl, irl ^ 15);
-}
-
-static void r2d_fpga_irq_set(void *opaque, int n, int level)
-{
-    r2d_fpga_t *fpga = opaque;
-    if (level)
-        fpga->irlmon |= irqtab[n].msk;
-    else
-        fpga->irlmon &= ~irqtab[n].msk;
-    update_irl(fpga);
-}
-
-static uint32_t r2d_fpga_read(void *opaque, hwaddr addr)
-{
-    r2d_fpga_t *s = opaque;
-
-    switch (addr) {
-    case PA_IRLMSK:
-        return s->irlmsk;
-    case PA_OUTPORT:
-	return s->outport;
-    case PA_POWOFF:
-	return 0x00;
-    case PA_VERREG:
-	return 0x10;
-    }
-
-    return 0;
-}
-
-static void
-r2d_fpga_write(void *opaque, hwaddr addr, uint32_t value)
-{
-    r2d_fpga_t *s = opaque;
-
-    switch (addr) {
-    case PA_IRLMSK:
-        s->irlmsk = value;
-        update_irl(s);
-	break;
-    case PA_OUTPORT:
-	s->outport = value;
-	break;
-    case PA_POWOFF:
-        if (value & 1) {
-            qemu_system_shutdown_request();
-        }
-        break;
-    case PA_VERREG:
-	/* Discard writes */
-	break;
-    }
-}
-
-static const MemoryRegionOps r2d_fpga_ops = {
-    .old_mmio = {
-        .read = { r2d_fpga_read, r2d_fpga_read, NULL, },
-        .write = { r2d_fpga_write, r2d_fpga_write, NULL, },
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static qemu_irq *r2d_fpga_init(MemoryRegion *sysmem,
-                               hwaddr base, qemu_irq irl)
-{
-    r2d_fpga_t *s;
-
-    s = g_malloc0(sizeof(r2d_fpga_t));
-
-    s->irl = irl;
-
-    memory_region_init_io(&s->iomem, &r2d_fpga_ops, s, "r2d-fpga", 0x40);
-    memory_region_add_subregion(sysmem, base, &s->iomem);
-    return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS);
-}
-
-typedef struct ResetData {
-    SuperHCPU *cpu;
-    uint32_t vector;
-} ResetData;
-
-static void main_cpu_reset(void *opaque)
-{
-    ResetData *s = (ResetData *)opaque;
-    CPUSH4State *env = &s->cpu->env;
-
-    cpu_reset(CPU(s->cpu));
-    env->pc = s->vector;
-}
-
-static struct QEMU_PACKED
-{
-    int mount_root_rdonly;
-    int ramdisk_flags;
-    int orig_root_dev;
-    int loader_type;
-    int initrd_start;
-    int initrd_size;
-
-    char pad[232];
-
-    char kernel_cmdline[256];
-} boot_params;
-
-static void r2d_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    SuperHCPU *cpu;
-    CPUSH4State *env;
-    ResetData *reset_info;
-    struct SH7750State *s;
-    MemoryRegion *sdram = g_new(MemoryRegion, 1);
-    qemu_irq *irq;
-    DriveInfo *dinfo;
-    int i;
-    DeviceState *dev;
-    SysBusDevice *busdev;
-    MemoryRegion *address_space_mem = get_system_memory();
-
-    if (cpu_model == NULL) {
-        cpu_model = "SH7751R";
-    }
-
-    cpu = cpu_sh4_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    reset_info = g_malloc0(sizeof(ResetData));
-    reset_info->cpu = cpu;
-    reset_info->vector = env->pc;
-    qemu_register_reset(main_cpu_reset, reset_info);
-
-    /* Allocate memory space */
-    memory_region_init_ram(sdram, "r2d.sdram", SDRAM_SIZE);
-    vmstate_register_ram_global(sdram);
-    memory_region_add_subregion(address_space_mem, SDRAM_BASE, sdram);
-    /* Register peripherals */
-    s = sh7750_init(env, address_space_mem);
-    irq = r2d_fpga_init(address_space_mem, 0x04000000, sh7750_irl(s));
-
-    dev = qdev_create(NULL, "sh_pci");
-    busdev = SYS_BUS_DEVICE(dev);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(busdev, 0, P4ADDR(0x1e200000));
-    sysbus_mmio_map(busdev, 1, A7ADDR(0x1e200000));
-    sysbus_connect_irq(busdev, 0, irq[PCI_INTA]);
-    sysbus_connect_irq(busdev, 1, irq[PCI_INTB]);
-    sysbus_connect_irq(busdev, 2, irq[PCI_INTC]);
-    sysbus_connect_irq(busdev, 3, irq[PCI_INTD]);
-
-    sm501_init(address_space_mem, 0x10000000, SM501_VRAM_SIZE,
-               irq[SM501], serial_hds[2]);
-
-    /* onboard CF (True IDE mode, Master only). */
-    dinfo = drive_get(IF_IDE, 0, 0);
-    dev = qdev_create(NULL, "mmio-ide");
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_connect_irq(busdev, 0, irq[CF_IDE]);
-    qdev_prop_set_uint32(dev, "shift", 1);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(busdev, 0, 0x14001000);
-    sysbus_mmio_map(busdev, 1, 0x1400080c);
-    mmio_ide_init_drives(dev, dinfo, NULL);
-
-    /* onboard flash memory */
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi02_register(0x0, NULL, "r2d.flash", FLASH_SIZE,
-                          dinfo ? dinfo->bdrv : NULL, (16 * 1024),
-                          FLASH_SIZE >> 16,
-                          1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
-                          0x555, 0x2aa, 0);
-
-    /* NIC: rtl8139 on-board, and 2 slots. */
-    for (i = 0; i < nb_nics; i++)
-        pci_nic_init_nofail(&nd_table[i], "rtl8139", i==0 ? "2" : NULL);
-
-    /* USB keyboard */
-    usbdevice_create("keyboard");
-
-    /* Todo: register on board registers */
-    memset(&boot_params, 0, sizeof(boot_params));
-
-    if (kernel_filename) {
-        int kernel_size;
-
-        kernel_size = load_image_targphys(kernel_filename,
-                                          SDRAM_BASE + LINUX_LOAD_OFFSET,
-                                          INITRD_LOAD_OFFSET - LINUX_LOAD_OFFSET);
-        if (kernel_size < 0) {
-          fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
-          exit(1);
-        }
-
-        /* initialization which should be done by firmware */
-        stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */
-        stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */
-        reset_info->vector = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */
-    }
-
-    if (initrd_filename) {
-        int initrd_size;
-
-        initrd_size = load_image_targphys(initrd_filename,
-                                          SDRAM_BASE + INITRD_LOAD_OFFSET,
-                                          SDRAM_SIZE - INITRD_LOAD_OFFSET);
-
-        if (initrd_size < 0) {
-          fprintf(stderr, "qemu: could not load initrd '%s'\n", initrd_filename);
-          exit(1);
-        }
-
-        /* initialization which should be done by firmware */
-        boot_params.loader_type = 1;
-        boot_params.initrd_start = INITRD_LOAD_OFFSET;
-        boot_params.initrd_size = initrd_size;
-    }
-
-    if (kernel_cmdline) {
-        /* I see no evidence that this .kernel_cmdline buffer requires
-           NUL-termination, so using strncpy should be ok. */
-        strncpy(boot_params.kernel_cmdline, kernel_cmdline,
-                sizeof(boot_params.kernel_cmdline));
-    }
-
-    rom_add_blob_fixed("boot_params", &boot_params, sizeof(boot_params),
-                       SDRAM_BASE + BOOT_PARAMS_OFFSET);
-}
-
-static QEMUMachine r2d_machine = {
-    .name = "r2d",
-    .desc = "r2d-plus board",
-    .init = r2d_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void r2d_machine_init(void)
-{
-    qemu_register_machine(&r2d_machine);
-}
-
-machine_init(r2d_machine_init);
diff --git a/hw/realview.c b/hw/realview.c
deleted file mode 100644
index 5fb490c..0000000
--- a/hw/realview.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * ARM RealView Baseboard System emulation.
- *
- * Copyright (c) 2006-2007 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GPL.
- */
-
-#include "hw/sysbus.h"
-#include "hw/arm-misc.h"
-#include "hw/primecell.h"
-#include "hw/devices.h"
-#include "hw/pci/pci.h"
-#include "net/net.h"
-#include "sysemu/sysemu.h"
-#include "hw/boards.h"
-#include "hw/i2c.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-#define SMP_BOOT_ADDR 0xe0000000
-#define SMP_BOOTREG_ADDR 0x10000030
-
-/* Board init.  */
-
-static struct arm_boot_info realview_binfo = {
-    .smp_loader_start = SMP_BOOT_ADDR,
-    .smp_bootreg_addr = SMP_BOOTREG_ADDR,
-};
-
-/* The following two lists must be consistent.  */
-enum realview_board_type {
-    BOARD_EB,
-    BOARD_EB_MPCORE,
-    BOARD_PB_A8,
-    BOARD_PBX_A9,
-};
-
-static const int realview_board_id[] = {
-    0x33b,
-    0x33b,
-    0x769,
-    0x76d
-};
-
-static void realview_init(QEMUMachineInitArgs *args,
-                          enum realview_board_type board_type)
-{
-    ARMCPU *cpu = NULL;
-    CPUARMState *env;
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *ram_lo = g_new(MemoryRegion, 1);
-    MemoryRegion *ram_hi = g_new(MemoryRegion, 1);
-    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
-    MemoryRegion *ram_hack = g_new(MemoryRegion, 1);
-    DeviceState *dev, *sysctl, *gpio2, *pl041;
-    SysBusDevice *busdev;
-    qemu_irq *irqp;
-    qemu_irq pic[64];
-    qemu_irq mmc_irq[2];
-    PCIBus *pci_bus;
-    NICInfo *nd;
-    i2c_bus *i2c;
-    int n;
-    int done_nic = 0;
-    qemu_irq cpu_irq[4];
-    int is_mpcore = 0;
-    int is_pb = 0;
-    uint32_t proc_id = 0;
-    uint32_t sys_id;
-    ram_addr_t low_ram_size;
-    ram_addr_t ram_size = args->ram_size;
-
-    switch (board_type) {
-    case BOARD_EB:
-        break;
-    case BOARD_EB_MPCORE:
-        is_mpcore = 1;
-        break;
-    case BOARD_PB_A8:
-        is_pb = 1;
-        break;
-    case BOARD_PBX_A9:
-        is_mpcore = 1;
-        is_pb = 1;
-        break;
-    }
-    for (n = 0; n < smp_cpus; n++) {
-        cpu = cpu_arm_init(args->cpu_model);
-        if (!cpu) {
-            fprintf(stderr, "Unable to find CPU definition\n");
-            exit(1);
-        }
-        irqp = arm_pic_init_cpu(cpu);
-        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
-    }
-    env = &cpu->env;
-    if (arm_feature(env, ARM_FEATURE_V7)) {
-        if (is_mpcore) {
-            proc_id = 0x0c000000;
-        } else {
-            proc_id = 0x0e000000;
-        }
-    } else if (arm_feature(env, ARM_FEATURE_V6K)) {
-        proc_id = 0x06000000;
-    } else if (arm_feature(env, ARM_FEATURE_V6)) {
-        proc_id = 0x04000000;
-    } else {
-        proc_id = 0x02000000;
-    }
-
-    if (is_pb && ram_size > 0x20000000) {
-        /* Core tile RAM.  */
-        low_ram_size = ram_size - 0x20000000;
-        ram_size = 0x20000000;
-        memory_region_init_ram(ram_lo, "realview.lowmem", low_ram_size);
-        vmstate_register_ram_global(ram_lo);
-        memory_region_add_subregion(sysmem, 0x20000000, ram_lo);
-    }
-
-    memory_region_init_ram(ram_hi, "realview.highmem", ram_size);
-    vmstate_register_ram_global(ram_hi);
-    low_ram_size = ram_size;
-    if (low_ram_size > 0x10000000)
-      low_ram_size = 0x10000000;
-    /* SDRAM at address zero.  */
-    memory_region_init_alias(ram_alias, "realview.alias",
-                             ram_hi, 0, low_ram_size);
-    memory_region_add_subregion(sysmem, 0, ram_alias);
-    if (is_pb) {
-        /* And again at a high address.  */
-        memory_region_add_subregion(sysmem, 0x70000000, ram_hi);
-    } else {
-        ram_size = low_ram_size;
-    }
-
-    sys_id = is_pb ? 0x01780500 : 0xc1400400;
-    sysctl = qdev_create(NULL, "realview_sysctl");
-    qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
-    qdev_prop_set_uint32(sysctl, "proc_id", proc_id);
-    qdev_init_nofail(sysctl);
-    sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
-
-    if (is_mpcore) {
-        hwaddr periphbase;
-        dev = qdev_create(NULL, is_pb ? "a9mpcore_priv": "realview_mpcore");
-        qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
-        qdev_init_nofail(dev);
-        busdev = SYS_BUS_DEVICE(dev);
-        if (is_pb) {
-            periphbase = 0x1f000000;
-        } else {
-            periphbase = 0x10100000;
-        }
-        sysbus_mmio_map(busdev, 0, periphbase);
-        for (n = 0; n < smp_cpus; n++) {
-            sysbus_connect_irq(busdev, n, cpu_irq[n]);
-        }
-        sysbus_create_varargs("l2x0", periphbase + 0x2000, NULL);
-        /* Both A9 and 11MPCore put the GIC CPU i/f at base + 0x100 */
-        realview_binfo.gic_cpu_if_addr = periphbase + 0x100;
-    } else {
-        uint32_t gic_addr = is_pb ? 0x1e000000 : 0x10040000;
-        /* For now just create the nIRQ GIC, and ignore the others.  */
-        dev = sysbus_create_simple("realview_gic", gic_addr, cpu_irq[0]);
-    }
-    for (n = 0; n < 64; n++) {
-        pic[n] = qdev_get_gpio_in(dev, n);
-    }
-
-    pl041 = qdev_create(NULL, "pl041");
-    qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
-    qdev_init_nofail(pl041);
-    sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000);
-    sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, pic[19]);
-
-    sysbus_create_simple("pl050_keyboard", 0x10006000, pic[20]);
-    sysbus_create_simple("pl050_mouse", 0x10007000, pic[21]);
-
-    sysbus_create_simple("pl011", 0x10009000, pic[12]);
-    sysbus_create_simple("pl011", 0x1000a000, pic[13]);
-    sysbus_create_simple("pl011", 0x1000b000, pic[14]);
-    sysbus_create_simple("pl011", 0x1000c000, pic[15]);
-
-    /* DMA controller is optional, apparently.  */
-    sysbus_create_simple("pl081", 0x10030000, pic[24]);
-
-    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("pl111", 0x10020000, pic[23]);
-
-    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]);
-
-    if (!is_pb) {
-        dev = qdev_create(NULL, "realview_pci");
-        busdev = SYS_BUS_DEVICE(dev);
-        qdev_init_nofail(dev);
-        sysbus_mmio_map(busdev, 0, 0x61000000); /* PCI self-config */
-        sysbus_mmio_map(busdev, 1, 0x62000000); /* PCI config */
-        sysbus_mmio_map(busdev, 2, 0x63000000); /* PCI I/O */
-        sysbus_connect_irq(busdev, 0, pic[48]);
-        sysbus_connect_irq(busdev, 1, pic[49]);
-        sysbus_connect_irq(busdev, 2, pic[50]);
-        sysbus_connect_irq(busdev, 3, pic[51]);
-        pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
-        if (usb_enabled(false)) {
-            pci_create_simple(pci_bus, -1, "pci-ohci");
-        }
-        n = drive_get_max_bus(IF_SCSI);
-        while (n >= 0) {
-            pci_create_simple(pci_bus, -1, "lsi53c895a");
-            n--;
-        }
-    }
-    for(n = 0; n < nb_nics; n++) {
-        nd = &nd_table[n];
-
-        if (!done_nic && (!nd->model ||
-                    strcmp(nd->model, is_pb ? "lan9118" : "smc91c111") == 0)) {
-            if (is_pb) {
-                lan9118_init(nd, 0x4e000000, pic[28]);
-            } else {
-                smc91c111_init(nd, 0x4e000000, pic[28]);
-            }
-            done_nic = 1;
-        } else {
-            pci_nic_init_nofail(nd, "rtl8139", NULL);
-        }
-    }
-
-    dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL);
-    i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
-    i2c_create_slave(i2c, "ds1338", 0x68);
-
-    /* Memory map for RealView Emulation Baseboard:  */
-    /* 0x10000000 System registers.  */
-    /*  0x10001000 System controller.  */
-    /* 0x10002000 Two-Wire Serial Bus.  */
-    /* 0x10003000 Reserved.  */
-    /*  0x10004000 AACI.  */
-    /*  0x10005000 MCI.  */
-    /* 0x10006000 KMI0.  */
-    /* 0x10007000 KMI1.  */
-    /*  0x10008000 Character LCD. (EB) */
-    /* 0x10009000 UART0.  */
-    /* 0x1000a000 UART1.  */
-    /* 0x1000b000 UART2.  */
-    /* 0x1000c000 UART3.  */
-    /*  0x1000d000 SSPI.  */
-    /*  0x1000e000 SCI.  */
-    /* 0x1000f000 Reserved.  */
-    /*  0x10010000 Watchdog.  */
-    /* 0x10011000 Timer 0+1.  */
-    /* 0x10012000 Timer 2+3.  */
-    /*  0x10013000 GPIO 0.  */
-    /*  0x10014000 GPIO 1.  */
-    /*  0x10015000 GPIO 2.  */
-    /*  0x10002000 Two-Wire Serial Bus - DVI. (PB) */
-    /* 0x10017000 RTC.  */
-    /*  0x10018000 DMC.  */
-    /*  0x10019000 PCI controller config.  */
-    /*  0x10020000 CLCD.  */
-    /* 0x10030000 DMA Controller.  */
-    /* 0x10040000 GIC1. (EB) */
-    /*  0x10050000 GIC2. (EB) */
-    /*  0x10060000 GIC3. (EB) */
-    /*  0x10070000 GIC4. (EB) */
-    /*  0x10080000 SMC.  */
-    /* 0x1e000000 GIC1. (PB) */
-    /*  0x1e001000 GIC2. (PB) */
-    /*  0x1e002000 GIC3. (PB) */
-    /*  0x1e003000 GIC4. (PB) */
-    /*  0x40000000 NOR flash.  */
-    /*  0x44000000 DoC flash.  */
-    /*  0x48000000 SRAM.  */
-    /*  0x4c000000 Configuration flash.  */
-    /* 0x4e000000 Ethernet.  */
-    /*  0x4f000000 USB.  */
-    /*  0x50000000 PISMO.  */
-    /*  0x54000000 PISMO.  */
-    /*  0x58000000 PISMO.  */
-    /*  0x5c000000 PISMO.  */
-    /* 0x60000000 PCI.  */
-    /* 0x61000000 PCI Self Config.  */
-    /* 0x62000000 PCI Config.  */
-    /* 0x63000000 PCI IO.  */
-    /* 0x64000000 PCI mem 0.  */
-    /* 0x68000000 PCI mem 1.  */
-    /* 0x6c000000 PCI mem 2.  */
-
-    /* ??? 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.  */
-    memory_region_init_ram(ram_hack, "realview.hack", 0x1000);
-    vmstate_register_ram_global(ram_hack);
-    memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack);
-
-    realview_binfo.ram_size = ram_size;
-    realview_binfo.kernel_filename = args->kernel_filename;
-    realview_binfo.kernel_cmdline = args->kernel_cmdline;
-    realview_binfo.initrd_filename = args->initrd_filename;
-    realview_binfo.nb_cpus = smp_cpus;
-    realview_binfo.board_id = realview_board_id[board_type];
-    realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0);
-    arm_load_kernel(arm_env_get_cpu(first_cpu), &realview_binfo);
-}
-
-static void realview_eb_init(QEMUMachineInitArgs *args)
-{
-    if (!args->cpu_model) {
-        args->cpu_model = "arm926";
-    }
-    realview_init(args, BOARD_EB);
-}
-
-static void realview_eb_mpcore_init(QEMUMachineInitArgs *args)
-{
-    if (!args->cpu_model) {
-        args->cpu_model = "arm11mpcore";
-    }
-    realview_init(args, BOARD_EB_MPCORE);
-}
-
-static void realview_pb_a8_init(QEMUMachineInitArgs *args)
-{
-    if (!args->cpu_model) {
-        args->cpu_model = "cortex-a8";
-    }
-    realview_init(args, BOARD_PB_A8);
-}
-
-static void realview_pbx_a9_init(QEMUMachineInitArgs *args)
-{
-    if (!args->cpu_model) {
-        args->cpu_model = "cortex-a9";
-    }
-    realview_init(args, BOARD_PBX_A9);
-}
-
-static QEMUMachine realview_eb_machine = {
-    .name = "realview-eb",
-    .desc = "ARM RealView Emulation Baseboard (ARM926EJ-S)",
-    .init = realview_eb_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine realview_eb_mpcore_machine = {
-    .name = "realview-eb-mpcore",
-    .desc = "ARM RealView Emulation Baseboard (ARM11MPCore)",
-    .init = realview_eb_mpcore_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine realview_pb_a8_machine = {
-    .name = "realview-pb-a8",
-    .desc = "ARM RealView Platform Baseboard for Cortex-A8",
-    .init = realview_pb_a8_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine realview_pbx_a9_machine = {
-    .name = "realview-pbx-a9",
-    .desc = "ARM RealView Platform Baseboard Explore for Cortex-A9",
-    .init = realview_pbx_a9_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void realview_machine_init(void)
-{
-    qemu_register_machine(&realview_eb_machine);
-    qemu_register_machine(&realview_eb_mpcore_machine);
-    qemu_register_machine(&realview_pb_a8_machine);
-    qemu_register_machine(&realview_pbx_a9_machine);
-}
-
-machine_init(realview_machine_init);
diff --git a/hw/sh4/Makefile.objs b/hw/sh4/Makefile.objs
index 68c5921..b2e1f1e 100644
--- a/hw/sh4/Makefile.objs
+++ b/hw/sh4/Makefile.objs
@@ -1,5 +1,7 @@
-obj-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
+obj-y = sh7750.o sh7750_regnames.o tc58128.o
 obj-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
 obj-y += ide/mmio.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += shix.o r2d.o
diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
new file mode 100644
index 0000000..faa03d2
--- /dev/null
+++ b/hw/sh4/r2d.c
@@ -0,0 +1,364 @@
+/*
+ * Renesas SH7751R R2D-PLUS emulation
+ *
+ * Copyright (c) 2007 Magnus Damm
+ * Copyright (c) 2008 Paul Mundt
+ *
+ * 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/sysbus.h"
+#include "hw/hw.h"
+#include "hw/sh.h"
+#include "hw/devices.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/pci/pci.h"
+#include "net/net.h"
+#include "hw/sh7750_regs.h"
+#include "hw/ide.h"
+#include "hw/loader.h"
+#include "hw/usb.h"
+#include "hw/flash.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+#define FLASH_BASE 0x00000000
+#define FLASH_SIZE 0x02000000
+
+#define SDRAM_BASE 0x0c000000 /* Physical location of SDRAM: Area 3 */
+#define SDRAM_SIZE 0x04000000
+
+#define SM501_VRAM_SIZE 0x800000
+
+#define BOOT_PARAMS_OFFSET 0x0010000
+/* CONFIG_BOOT_LINK_OFFSET of Linux kernel */
+#define LINUX_LOAD_OFFSET  0x0800000
+#define INITRD_LOAD_OFFSET 0x1800000
+
+#define PA_IRLMSK	0x00
+#define PA_POWOFF	0x30
+#define PA_VERREG	0x32
+#define PA_OUTPORT	0x36
+
+typedef struct {
+    uint16_t bcr;
+    uint16_t irlmsk;
+    uint16_t irlmon;
+    uint16_t cfctl;
+    uint16_t cfpow;
+    uint16_t dispctl;
+    uint16_t sdmpow;
+    uint16_t rtcce;
+    uint16_t pcicd;
+    uint16_t voyagerrts;
+    uint16_t cfrst;
+    uint16_t admrts;
+    uint16_t extrst;
+    uint16_t cfcdintclr;
+    uint16_t keyctlclr;
+    uint16_t pad0;
+    uint16_t pad1;
+    uint16_t verreg;
+    uint16_t inport;
+    uint16_t outport;
+    uint16_t bverreg;
+
+/* output pin */
+    qemu_irq irl;
+    MemoryRegion iomem;
+} r2d_fpga_t;
+
+enum r2d_fpga_irq {
+    PCI_INTD, CF_IDE, CF_CD, PCI_INTC, SM501, KEY, RTC_A, RTC_T,
+    SDCARD, PCI_INTA, PCI_INTB, EXT, TP,
+    NR_IRQS
+};
+
+static const struct { short irl; uint16_t msk; } irqtab[NR_IRQS] = {
+    [CF_IDE]	= {  1, 1<<9 },
+    [CF_CD]	= {  2, 1<<8 },
+    [PCI_INTA]	= {  9, 1<<14 },
+    [PCI_INTB]	= { 10, 1<<13 },
+    [PCI_INTC]	= {  3, 1<<12 },
+    [PCI_INTD]	= {  0, 1<<11 },
+    [SM501]	= {  4, 1<<10 },
+    [KEY]	= {  5, 1<<6 },
+    [RTC_A]	= {  6, 1<<5 },
+    [RTC_T]	= {  7, 1<<4 },
+    [SDCARD]	= {  8, 1<<7 },
+    [EXT]	= { 11, 1<<0 },
+    [TP]	= { 12, 1<<15 },
+};
+
+static void update_irl(r2d_fpga_t *fpga)
+{
+    int i, irl = 15;
+    for (i = 0; i < NR_IRQS; i++)
+        if (fpga->irlmon & fpga->irlmsk & irqtab[i].msk)
+            if (irqtab[i].irl < irl)
+                irl = irqtab[i].irl;
+    qemu_set_irq(fpga->irl, irl ^ 15);
+}
+
+static void r2d_fpga_irq_set(void *opaque, int n, int level)
+{
+    r2d_fpga_t *fpga = opaque;
+    if (level)
+        fpga->irlmon |= irqtab[n].msk;
+    else
+        fpga->irlmon &= ~irqtab[n].msk;
+    update_irl(fpga);
+}
+
+static uint32_t r2d_fpga_read(void *opaque, hwaddr addr)
+{
+    r2d_fpga_t *s = opaque;
+
+    switch (addr) {
+    case PA_IRLMSK:
+        return s->irlmsk;
+    case PA_OUTPORT:
+	return s->outport;
+    case PA_POWOFF:
+	return 0x00;
+    case PA_VERREG:
+	return 0x10;
+    }
+
+    return 0;
+}
+
+static void
+r2d_fpga_write(void *opaque, hwaddr addr, uint32_t value)
+{
+    r2d_fpga_t *s = opaque;
+
+    switch (addr) {
+    case PA_IRLMSK:
+        s->irlmsk = value;
+        update_irl(s);
+	break;
+    case PA_OUTPORT:
+	s->outport = value;
+	break;
+    case PA_POWOFF:
+        if (value & 1) {
+            qemu_system_shutdown_request();
+        }
+        break;
+    case PA_VERREG:
+	/* Discard writes */
+	break;
+    }
+}
+
+static const MemoryRegionOps r2d_fpga_ops = {
+    .old_mmio = {
+        .read = { r2d_fpga_read, r2d_fpga_read, NULL, },
+        .write = { r2d_fpga_write, r2d_fpga_write, NULL, },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static qemu_irq *r2d_fpga_init(MemoryRegion *sysmem,
+                               hwaddr base, qemu_irq irl)
+{
+    r2d_fpga_t *s;
+
+    s = g_malloc0(sizeof(r2d_fpga_t));
+
+    s->irl = irl;
+
+    memory_region_init_io(&s->iomem, &r2d_fpga_ops, s, "r2d-fpga", 0x40);
+    memory_region_add_subregion(sysmem, base, &s->iomem);
+    return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS);
+}
+
+typedef struct ResetData {
+    SuperHCPU *cpu;
+    uint32_t vector;
+} ResetData;
+
+static void main_cpu_reset(void *opaque)
+{
+    ResetData *s = (ResetData *)opaque;
+    CPUSH4State *env = &s->cpu->env;
+
+    cpu_reset(CPU(s->cpu));
+    env->pc = s->vector;
+}
+
+static struct QEMU_PACKED
+{
+    int mount_root_rdonly;
+    int ramdisk_flags;
+    int orig_root_dev;
+    int loader_type;
+    int initrd_start;
+    int initrd_size;
+
+    char pad[232];
+
+    char kernel_cmdline[256];
+} boot_params;
+
+static void r2d_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    SuperHCPU *cpu;
+    CPUSH4State *env;
+    ResetData *reset_info;
+    struct SH7750State *s;
+    MemoryRegion *sdram = g_new(MemoryRegion, 1);
+    qemu_irq *irq;
+    DriveInfo *dinfo;
+    int i;
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    MemoryRegion *address_space_mem = get_system_memory();
+
+    if (cpu_model == NULL) {
+        cpu_model = "SH7751R";
+    }
+
+    cpu = cpu_sh4_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    reset_info = g_malloc0(sizeof(ResetData));
+    reset_info->cpu = cpu;
+    reset_info->vector = env->pc;
+    qemu_register_reset(main_cpu_reset, reset_info);
+
+    /* Allocate memory space */
+    memory_region_init_ram(sdram, "r2d.sdram", SDRAM_SIZE);
+    vmstate_register_ram_global(sdram);
+    memory_region_add_subregion(address_space_mem, SDRAM_BASE, sdram);
+    /* Register peripherals */
+    s = sh7750_init(env, address_space_mem);
+    irq = r2d_fpga_init(address_space_mem, 0x04000000, sh7750_irl(s));
+
+    dev = qdev_create(NULL, "sh_pci");
+    busdev = SYS_BUS_DEVICE(dev);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(busdev, 0, P4ADDR(0x1e200000));
+    sysbus_mmio_map(busdev, 1, A7ADDR(0x1e200000));
+    sysbus_connect_irq(busdev, 0, irq[PCI_INTA]);
+    sysbus_connect_irq(busdev, 1, irq[PCI_INTB]);
+    sysbus_connect_irq(busdev, 2, irq[PCI_INTC]);
+    sysbus_connect_irq(busdev, 3, irq[PCI_INTD]);
+
+    sm501_init(address_space_mem, 0x10000000, SM501_VRAM_SIZE,
+               irq[SM501], serial_hds[2]);
+
+    /* onboard CF (True IDE mode, Master only). */
+    dinfo = drive_get(IF_IDE, 0, 0);
+    dev = qdev_create(NULL, "mmio-ide");
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(busdev, 0, irq[CF_IDE]);
+    qdev_prop_set_uint32(dev, "shift", 1);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(busdev, 0, 0x14001000);
+    sysbus_mmio_map(busdev, 1, 0x1400080c);
+    mmio_ide_init_drives(dev, dinfo, NULL);
+
+    /* onboard flash memory */
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    pflash_cfi02_register(0x0, NULL, "r2d.flash", FLASH_SIZE,
+                          dinfo ? dinfo->bdrv : NULL, (16 * 1024),
+                          FLASH_SIZE >> 16,
+                          1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
+                          0x555, 0x2aa, 0);
+
+    /* NIC: rtl8139 on-board, and 2 slots. */
+    for (i = 0; i < nb_nics; i++)
+        pci_nic_init_nofail(&nd_table[i], "rtl8139", i==0 ? "2" : NULL);
+
+    /* USB keyboard */
+    usbdevice_create("keyboard");
+
+    /* Todo: register on board registers */
+    memset(&boot_params, 0, sizeof(boot_params));
+
+    if (kernel_filename) {
+        int kernel_size;
+
+        kernel_size = load_image_targphys(kernel_filename,
+                                          SDRAM_BASE + LINUX_LOAD_OFFSET,
+                                          INITRD_LOAD_OFFSET - LINUX_LOAD_OFFSET);
+        if (kernel_size < 0) {
+          fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
+          exit(1);
+        }
+
+        /* initialization which should be done by firmware */
+        stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */
+        stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */
+        reset_info->vector = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */
+    }
+
+    if (initrd_filename) {
+        int initrd_size;
+
+        initrd_size = load_image_targphys(initrd_filename,
+                                          SDRAM_BASE + INITRD_LOAD_OFFSET,
+                                          SDRAM_SIZE - INITRD_LOAD_OFFSET);
+
+        if (initrd_size < 0) {
+          fprintf(stderr, "qemu: could not load initrd '%s'\n", initrd_filename);
+          exit(1);
+        }
+
+        /* initialization which should be done by firmware */
+        boot_params.loader_type = 1;
+        boot_params.initrd_start = INITRD_LOAD_OFFSET;
+        boot_params.initrd_size = initrd_size;
+    }
+
+    if (kernel_cmdline) {
+        /* I see no evidence that this .kernel_cmdline buffer requires
+           NUL-termination, so using strncpy should be ok. */
+        strncpy(boot_params.kernel_cmdline, kernel_cmdline,
+                sizeof(boot_params.kernel_cmdline));
+    }
+
+    rom_add_blob_fixed("boot_params", &boot_params, sizeof(boot_params),
+                       SDRAM_BASE + BOOT_PARAMS_OFFSET);
+}
+
+static QEMUMachine r2d_machine = {
+    .name = "r2d",
+    .desc = "r2d-plus board",
+    .init = r2d_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void r2d_machine_init(void)
+{
+    qemu_register_machine(&r2d_machine);
+}
+
+machine_init(r2d_machine_init);
diff --git a/hw/sh4/shix.c b/hw/sh4/shix.c
new file mode 100644
index 0000000..192579d
--- /dev/null
+++ b/hw/sh4/shix.c
@@ -0,0 +1,103 @@
+/*
+ * SHIX 2.0 board description
+ *
+ * Copyright (c) 2005 Samuel Tardieu
+ *
+ * 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.
+ */
+/*
+   Shix 2.0 board by Alexis Polti, described at
+   http://perso.enst.fr/~polti/realisations/shix20/
+
+   More information in target-sh4/README.sh4
+*/
+#include "hw/hw.h"
+#include "hw/sh.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "exec/address-spaces.h"
+
+#define BIOS_FILENAME "shix_bios.bin"
+#define BIOS_ADDRESS 0xA0000000
+
+static void shix_init(QEMUMachineInitArgs *args)
+{
+    const char *cpu_model = args->cpu_model;
+    int ret;
+    CPUSH4State *env;
+    struct SH7750State *s;
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *rom = g_new(MemoryRegion, 1);
+    MemoryRegion *sdram = g_new(MemoryRegion, 2);
+    
+    if (!cpu_model)
+        cpu_model = "any";
+
+    printf("Initializing CPU\n");
+    env = cpu_init(cpu_model);
+
+    /* Allocate memory space */
+    printf("Allocating ROM\n");
+    memory_region_init_ram(rom, "shix.rom", 0x4000);
+    vmstate_register_ram_global(rom);
+    memory_region_set_readonly(rom, true);
+    memory_region_add_subregion(sysmem, 0x00000000, rom);
+    printf("Allocating SDRAM 1\n");
+    memory_region_init_ram(&sdram[0], "shix.sdram1", 0x01000000);
+    vmstate_register_ram_global(&sdram[0]);
+    memory_region_add_subregion(sysmem, 0x08000000, &sdram[0]);
+    printf("Allocating SDRAM 2\n");
+    memory_region_init_ram(&sdram[1], "shix.sdram2", 0x01000000);
+    vmstate_register_ram_global(&sdram[1]);
+    memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]);
+
+    /* Load BIOS in 0 (and access it through P2, 0xA0000000) */
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    printf("%s: load BIOS '%s'\n", __func__, bios_name);
+    ret = load_image_targphys(bios_name, 0, 0x4000);
+    if (ret < 0) {		/* Check bios size */
+	fprintf(stderr, "ret=%d\n", ret);
+	fprintf(stderr, "qemu: could not load SHIX bios '%s'\n",
+		bios_name);
+	exit(1);
+    }
+
+    /* Register peripherals */
+    s = sh7750_init(env, sysmem);
+    /* XXXXX Check success */
+    tc58128_init(s, "shix_linux_nand.bin", NULL);
+    fprintf(stderr, "initialization terminated\n");
+}
+
+static QEMUMachine shix_machine = {
+    .name = "shix",
+    .desc = "shix card",
+    .init = shix_init,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void shix_machine_init(void)
+{
+    qemu_register_machine(&shix_machine);
+}
+
+machine_init(shix_machine_init);
diff --git a/hw/shix.c b/hw/shix.c
deleted file mode 100644
index 192579d..0000000
--- a/hw/shix.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * SHIX 2.0 board description
- *
- * Copyright (c) 2005 Samuel Tardieu
- *
- * 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.
- */
-/*
-   Shix 2.0 board by Alexis Polti, described at
-   http://perso.enst.fr/~polti/realisations/shix20/
-
-   More information in target-sh4/README.sh4
-*/
-#include "hw/hw.h"
-#include "hw/sh.h"
-#include "sysemu/sysemu.h"
-#include "hw/boards.h"
-#include "hw/loader.h"
-#include "exec/address-spaces.h"
-
-#define BIOS_FILENAME "shix_bios.bin"
-#define BIOS_ADDRESS 0xA0000000
-
-static void shix_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    int ret;
-    CPUSH4State *env;
-    struct SH7750State *s;
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *rom = g_new(MemoryRegion, 1);
-    MemoryRegion *sdram = g_new(MemoryRegion, 2);
-    
-    if (!cpu_model)
-        cpu_model = "any";
-
-    printf("Initializing CPU\n");
-    env = cpu_init(cpu_model);
-
-    /* Allocate memory space */
-    printf("Allocating ROM\n");
-    memory_region_init_ram(rom, "shix.rom", 0x4000);
-    vmstate_register_ram_global(rom);
-    memory_region_set_readonly(rom, true);
-    memory_region_add_subregion(sysmem, 0x00000000, rom);
-    printf("Allocating SDRAM 1\n");
-    memory_region_init_ram(&sdram[0], "shix.sdram1", 0x01000000);
-    vmstate_register_ram_global(&sdram[0]);
-    memory_region_add_subregion(sysmem, 0x08000000, &sdram[0]);
-    printf("Allocating SDRAM 2\n");
-    memory_region_init_ram(&sdram[1], "shix.sdram2", 0x01000000);
-    vmstate_register_ram_global(&sdram[1]);
-    memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]);
-
-    /* Load BIOS in 0 (and access it through P2, 0xA0000000) */
-    if (bios_name == NULL)
-        bios_name = BIOS_FILENAME;
-    printf("%s: load BIOS '%s'\n", __func__, bios_name);
-    ret = load_image_targphys(bios_name, 0, 0x4000);
-    if (ret < 0) {		/* Check bios size */
-	fprintf(stderr, "ret=%d\n", ret);
-	fprintf(stderr, "qemu: could not load SHIX bios '%s'\n",
-		bios_name);
-	exit(1);
-    }
-
-    /* Register peripherals */
-    s = sh7750_init(env, sysmem);
-    /* XXXXX Check success */
-    tc58128_init(s, "shix_linux_nand.bin", NULL);
-    fprintf(stderr, "initialization terminated\n");
-}
-
-static QEMUMachine shix_machine = {
-    .name = "shix",
-    .desc = "shix card",
-    .init = shix_init,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void shix_machine_init(void)
-{
-    qemu_register_machine(&shix_machine);
-}
-
-machine_init(shix_machine_init);
diff --git a/hw/smbios.c b/hw/smbios.c
deleted file mode 100644
index 672ee9b..0000000
--- a/hw/smbios.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * SMBIOS Support
- *
- * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
- *
- * Authors:
- *  Alex Williamson <alex.williamson at hp.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "sysemu/sysemu.h"
-#include "hw/smbios.h"
-#include "hw/loader.h"
-
-/*
- * Structures shared with the BIOS
- */
-struct smbios_header {
-    uint16_t length;
-    uint8_t type;
-} QEMU_PACKED;
-
-struct smbios_field {
-    struct smbios_header header;
-    uint8_t type;
-    uint16_t offset;
-    uint8_t data[];
-} QEMU_PACKED;
-
-struct smbios_table {
-    struct smbios_header header;
-    uint8_t data[];
-} QEMU_PACKED;
-
-#define SMBIOS_FIELD_ENTRY 0
-#define SMBIOS_TABLE_ENTRY 1
-
-
-static uint8_t *smbios_entries;
-static size_t smbios_entries_len;
-static int smbios_type4_count = 0;
-
-static void smbios_validate_table(void)
-{
-    if (smbios_type4_count && smbios_type4_count != smp_cpus) {
-         fprintf(stderr,
-                 "Number of SMBIOS Type 4 tables must match cpu count.\n");
-        exit(1);
-    }
-}
-
-uint8_t *smbios_get_table(size_t *length)
-{
-    smbios_validate_table();
-    *length = smbios_entries_len;
-    return smbios_entries;
-}
-
-/*
- * To avoid unresolvable overlaps in data, don't allow both
- * tables and fields for the same smbios type.
- */
-static void smbios_check_collision(int type, int entry)
-{
-    uint16_t *num_entries = (uint16_t *)smbios_entries;
-    struct smbios_header *header;
-    char *p;
-    int i;
-
-    if (!num_entries)
-        return;
-
-    p = (char *)(num_entries + 1);
-
-    for (i = 0; i < *num_entries; i++) {
-        header = (struct smbios_header *)p;
-        if (entry == SMBIOS_TABLE_ENTRY && header->type == SMBIOS_FIELD_ENTRY) {
-            struct smbios_field *field = (void *)header;
-            if (type == field->type) {
-                fprintf(stderr, "SMBIOS type %d field already defined, "
-                                "cannot add table\n", type);
-                exit(1);
-            }
-        } else if (entry == SMBIOS_FIELD_ENTRY &&
-                   header->type == SMBIOS_TABLE_ENTRY) {
-            struct smbios_structure_header *table = (void *)(header + 1);
-            if (type == table->type) {
-                fprintf(stderr, "SMBIOS type %d table already defined, "
-                                "cannot add field\n", type);
-                exit(1);
-            }
-        }
-        p += le16_to_cpu(header->length);
-    }
-}
-
-void smbios_add_field(int type, int offset, int len, void *data)
-{
-    struct smbios_field *field;
-
-    smbios_check_collision(type, SMBIOS_FIELD_ENTRY);
-
-    if (!smbios_entries) {
-        smbios_entries_len = sizeof(uint16_t);
-        smbios_entries = g_malloc0(smbios_entries_len);
-    }
-    smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
-                                                  sizeof(*field) + len);
-    field = (struct smbios_field *)(smbios_entries + smbios_entries_len);
-    field->header.type = SMBIOS_FIELD_ENTRY;
-    field->header.length = cpu_to_le16(sizeof(*field) + len);
-
-    field->type = type;
-    field->offset = cpu_to_le16(offset);
-    memcpy(field->data, data, len);
-
-    smbios_entries_len += sizeof(*field) + len;
-    (*(uint16_t *)smbios_entries) =
-            cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
-}
-
-static void smbios_build_type_0_fields(const char *t)
-{
-    char buf[1024];
-
-    if (get_param_value(buf, sizeof(buf), "vendor", t))
-        smbios_add_field(0, offsetof(struct smbios_type_0, vendor_str),
-                         strlen(buf) + 1, buf);
-    if (get_param_value(buf, sizeof(buf), "version", t))
-        smbios_add_field(0, offsetof(struct smbios_type_0, bios_version_str),
-                         strlen(buf) + 1, buf);
-    if (get_param_value(buf, sizeof(buf), "date", t))
-        smbios_add_field(0, offsetof(struct smbios_type_0,
-                                     bios_release_date_str),
-                                     strlen(buf) + 1, buf);
-    if (get_param_value(buf, sizeof(buf), "release", t)) {
-        int major, minor;
-        sscanf(buf, "%d.%d", &major, &minor);
-        smbios_add_field(0, offsetof(struct smbios_type_0,
-                                     system_bios_major_release), 1, &major);
-        smbios_add_field(0, offsetof(struct smbios_type_0,
-                                     system_bios_minor_release), 1, &minor);
-    }
-}
-
-static void smbios_build_type_1_fields(const char *t)
-{
-    char buf[1024];
-
-    if (get_param_value(buf, sizeof(buf), "manufacturer", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, manufacturer_str),
-                         strlen(buf) + 1, buf);
-    if (get_param_value(buf, sizeof(buf), "product", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, product_name_str),
-                         strlen(buf) + 1, buf);
-    if (get_param_value(buf, sizeof(buf), "version", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, version_str),
-                         strlen(buf) + 1, buf);
-    if (get_param_value(buf, sizeof(buf), "serial", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, serial_number_str),
-                         strlen(buf) + 1, buf);
-    if (get_param_value(buf, sizeof(buf), "uuid", t)) {
-        if (qemu_uuid_parse(buf, qemu_uuid) != 0) {
-            fprintf(stderr, "Invalid SMBIOS UUID string\n");
-            exit(1);
-        }
-    }
-    if (get_param_value(buf, sizeof(buf), "sku", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, sku_number_str),
-                         strlen(buf) + 1, buf);
-    if (get_param_value(buf, sizeof(buf), "family", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, family_str),
-                         strlen(buf) + 1, buf);
-}
-
-int smbios_entry_add(const char *t)
-{
-    char buf[1024];
-
-    if (get_param_value(buf, sizeof(buf), "file", t)) {
-        struct smbios_structure_header *header;
-        struct smbios_table *table;
-        int size = get_image_size(buf);
-
-        if (size == -1 || size < sizeof(struct smbios_structure_header)) {
-            fprintf(stderr, "Cannot read smbios file %s\n", buf);
-            exit(1);
-        }
-
-        if (!smbios_entries) {
-            smbios_entries_len = sizeof(uint16_t);
-            smbios_entries = g_malloc0(smbios_entries_len);
-        }
-
-        smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
-                                                      sizeof(*table) + size);
-        table = (struct smbios_table *)(smbios_entries + smbios_entries_len);
-        table->header.type = SMBIOS_TABLE_ENTRY;
-        table->header.length = cpu_to_le16(sizeof(*table) + size);
-
-        if (load_image(buf, table->data) != size) {
-            fprintf(stderr, "Failed to load smbios file %s", buf);
-            exit(1);
-        }
-
-        header = (struct smbios_structure_header *)(table->data);
-        smbios_check_collision(header->type, SMBIOS_TABLE_ENTRY);
-        if (header->type == 4) {
-            smbios_type4_count++;
-        }
-
-        smbios_entries_len += sizeof(*table) + size;
-        (*(uint16_t *)smbios_entries) =
-                cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
-        return 0;
-    }
-
-    if (get_param_value(buf, sizeof(buf), "type", t)) {
-        unsigned long type = strtoul(buf, NULL, 0);
-        switch (type) {
-        case 0:
-            smbios_build_type_0_fields(t);
-            return 0;
-        case 1:
-            smbios_build_type_1_fields(t);
-            return 0;
-        default:
-            fprintf(stderr, "Don't know how to build fields for SMBIOS type "
-                    "%ld\n", type);
-            exit(1);
-        }
-    }
-
-    fprintf(stderr, "smbios: must specify type= or file=\n");
-    return -1;
-}
diff --git a/hw/spapr.c b/hw/spapr.c
deleted file mode 100644
index 2709c66..0000000
--- a/hw/spapr.c
+++ /dev/null
@@ -1,963 +0,0 @@
-/*
- * 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/sysemu.h"
-#include "hw/hw.h"
-#include "elf.h"
-#include "net/net.h"
-#include "sysemu/blockdev.h"
-#include "sysemu/cpus.h"
-#include "sysemu/kvm.h"
-#include "kvm_ppc.h"
-
-#include "hw/boards.h"
-#include "hw/ppc.h"
-#include "hw/loader.h"
-
-#include "hw/spapr.h"
-#include "hw/spapr_vio.h"
-#include "hw/spapr_pci.h"
-#include "hw/xics.h"
-#include "hw/pci/msi.h"
-
-#include "sysemu/kvm.h"
-#include "kvm_ppc.h"
-#include "hw/pci/pci.h"
-
-#include "exec/address-spaces.h"
-#include "hw/usb.h"
-#include "qemu/config-file.h"
-
-#include <libfdt.h>
-
-/* SLOF memory layout:
- *
- * SLOF raw image loaded at 0, copies its romfs right below the flat
- * device-tree, then position SLOF itself 31M below that
- *
- * So we set FW_OVERHEAD to 40MB which should account for all of that
- * and more
- *
- * We load our kernel at 4M, leaving space for SLOF initial image
- */
-#define FDT_MAX_SIZE            0x10000
-#define RTAS_MAX_SIZE           0x10000
-#define FW_MAX_SIZE             0x400000
-#define FW_FILE_NAME            "slof.bin"
-#define FW_OVERHEAD             0x2800000
-#define KERNEL_LOAD_ADDR        FW_MAX_SIZE
-
-#define MIN_RMA_SLOF            128UL
-
-#define TIMEBASE_FREQ           512000000ULL
-
-#define MAX_CPUS                256
-#define XICS_IRQS               1024
-
-#define PHANDLE_XICP            0x00001111
-
-#define HTAB_SIZE(spapr)        (1ULL << ((spapr)->htab_shift))
-
-sPAPREnvironment *spapr;
-
-int spapr_allocate_irq(int hint, bool lsi)
-{
-    int irq;
-
-    if (hint) {
-        irq = hint;
-        /* FIXME: we should probably check for collisions somehow */
-    } else {
-        irq = spapr->next_irq++;
-    }
-
-    /* Configure irq type */
-    if (!xics_get_qirq(spapr->icp, irq)) {
-        return 0;
-    }
-
-    xics_set_irq_type(spapr->icp, irq, lsi);
-
-    return irq;
-}
-
-/* Allocate block of consequtive IRQs, returns a number of the first */
-int spapr_allocate_irq_block(int num, bool lsi)
-{
-    int first = -1;
-    int i;
-
-    for (i = 0; i < num; ++i) {
-        int irq;
-
-        irq = spapr_allocate_irq(0, lsi);
-        if (!irq) {
-            return -1;
-        }
-
-        if (0 == i) {
-            first = irq;
-        }
-
-        /* If the above doesn't create a consecutive block then that's
-         * an internal bug */
-        assert(irq == (first + i));
-    }
-
-    return first;
-}
-
-static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
-{
-    int ret = 0, offset;
-    CPUPPCState *env;
-    CPUState *cpu;
-    char cpu_model[32];
-    int smt = kvmppc_smt_threads();
-    uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
-
-    assert(spapr->cpu_model);
-
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        cpu = CPU(ppc_env_get_cpu(env));
-        uint32_t associativity[] = {cpu_to_be32(0x5),
-                                    cpu_to_be32(0x0),
-                                    cpu_to_be32(0x0),
-                                    cpu_to_be32(0x0),
-                                    cpu_to_be32(cpu->numa_node),
-                                    cpu_to_be32(cpu->cpu_index)};
-
-        if ((cpu->cpu_index % smt) != 0) {
-            continue;
-        }
-
-        snprintf(cpu_model, 32, "/cpus/%s@%x", spapr->cpu_model,
-                 cpu->cpu_index);
-
-        offset = fdt_path_offset(fdt, cpu_model);
-        if (offset < 0) {
-            return offset;
-        }
-
-        if (nb_numa_nodes > 1) {
-            ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity,
-                              sizeof(associativity));
-            if (ret < 0) {
-                return ret;
-            }
-        }
-
-        ret = fdt_setprop(fdt, offset, "ibm,pft-size",
-                          pft_size_prop, sizeof(pft_size_prop));
-        if (ret < 0) {
-            return ret;
-        }
-    }
-    return ret;
-}
-
-
-static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop,
-                                     size_t maxsize)
-{
-    size_t maxcells = maxsize / sizeof(uint32_t);
-    int i, j, count;
-    uint32_t *p = prop;
-
-    for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
-        struct ppc_one_seg_page_size *sps = &env->sps.sps[i];
-
-        if (!sps->page_shift) {
-            break;
-        }
-        for (count = 0; count < PPC_PAGE_SIZES_MAX_SZ; count++) {
-            if (sps->enc[count].page_shift == 0) {
-                break;
-            }
-        }
-        if ((p - prop) >= (maxcells - 3 - count * 2)) {
-            break;
-        }
-        *(p++) = cpu_to_be32(sps->page_shift);
-        *(p++) = cpu_to_be32(sps->slb_enc);
-        *(p++) = cpu_to_be32(count);
-        for (j = 0; j < count; j++) {
-            *(p++) = cpu_to_be32(sps->enc[j].page_shift);
-            *(p++) = cpu_to_be32(sps->enc[j].pte_enc);
-        }
-    }
-
-    return (p - prop) * sizeof(uint32_t);
-}
-
-#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)
-
-
-static void *spapr_create_fdt_skel(const char *cpu_model,
-                                   hwaddr initrd_base,
-                                   hwaddr initrd_size,
-                                   hwaddr kernel_size,
-                                   const char *boot_device,
-                                   const char *kernel_cmdline,
-                                   uint32_t epow_irq)
-{
-    void *fdt;
-    CPUPPCState *env;
-    uint32_t start_prop = cpu_to_be32(initrd_base);
-    uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
-    char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
-        "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk";
-    char qemu_hypertas_prop[] = "hcall-memop1";
-    uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
-    uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
-    char *modelname;
-    int i, smt = kvmppc_smt_threads();
-    unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
-
-    fdt = g_malloc0(FDT_MAX_SIZE);
-    _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
-
-    if (kernel_size) {
-        _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR, kernel_size)));
-    }
-    if (initrd_size) {
-        _FDT((fdt_add_reservemap_entry(fdt, initrd_base, initrd_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", "IBM pSeries (emulated by qemu)")));
-
-    _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
-    _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
-
-    /* /chosen */
-    _FDT((fdt_begin_node(fdt, "chosen")));
-
-    /* Set Form1_affinity */
-    _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
-
-    _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))));
-    if (kernel_size) {
-        uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
-                              cpu_to_be64(kernel_size) };
-
-        _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
-    }
-    if (boot_device) {
-        _FDT((fdt_property_string(fdt, "qemu,boot-device", boot_device)));
-    }
-    _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width)));
-    _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height)));
-    _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth)));
-
-    _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 = g_strdup(cpu_model);
-
-    for (i = 0; i < strlen(modelname); i++) {
-        modelname[i] = toupper(modelname[i]);
-    }
-
-    /* This is needed during FDT finalization */
-    spapr->cpu_model = g_strdup(modelname);
-
-    for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        CPUState *cpu = CPU(ppc_env_get_cpu(env));
-        int index = cpu->cpu_index;
-        uint32_t servers_prop[smp_threads];
-        uint32_t gservers_prop[smp_threads * 2];
-        char *nodename;
-        uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
-                           0xffffffff, 0xffffffff};
-        uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ;
-        uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000;
-        uint32_t page_sizes_prop[64];
-        size_t page_sizes_prop_size;
-
-        if ((index % smt) != 0) {
-            continue;
-        }
-
-        nodename = g_strdup_printf("%s@%x", modelname, index);
-
-        _FDT((fdt_begin_node(fdt, nodename)));
-
-        g_free(nodename);
-
-        _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])));
-        _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", tbfreq)));
-        _FDT((fdt_property_cell(fdt, "clock-frequency", cpufreq)));
-        _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)));
-
-        /* Build interrupt servers and gservers properties */
-        for (i = 0; i < smp_threads; i++) {
-            servers_prop[i] = cpu_to_be32(index + i);
-            /* Hack, direct the group queues back to cpu 0 */
-            gservers_prop[i*2] = cpu_to_be32(index + i);
-            gservers_prop[i*2 + 1] = 0;
-        }
-        _FDT((fdt_property(fdt, "ibm,ppc-interrupt-server#s",
-                           servers_prop, sizeof(servers_prop))));
-        _FDT((fdt_property(fdt, "ibm,ppc-interrupt-gserver#s",
-                           gservers_prop, sizeof(gservers_prop))));
-
-        if (env->mmu_model & POWERPC_MMU_1TSEG) {
-            _FDT((fdt_property(fdt, "ibm,processor-segment-sizes",
-                               segs, sizeof(segs))));
-        }
-
-        /* Advertise VMX/VSX (vector extensions) if available
-         *   0 / no property == no vector extensions
-         *   1               == VMX / Altivec available
-         *   2               == VSX available */
-        if (env->insns_flags & PPC_ALTIVEC) {
-            uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
-
-            _FDT((fdt_property_cell(fdt, "ibm,vmx", vmx)));
-        }
-
-        /* Advertise DFP (Decimal Floating Point) if available
-         *   0 / no property == no DFP
-         *   1               == DFP available */
-        if (env->insns_flags2 & PPC2_DFP) {
-            _FDT((fdt_property_cell(fdt, "ibm,dfp", 1)));
-        }
-
-        page_sizes_prop_size = create_page_sizes_prop(env, page_sizes_prop,
-                                                      sizeof(page_sizes_prop));
-        if (page_sizes_prop_size) {
-            _FDT((fdt_property(fdt, "ibm,segment-page-sizes",
-                               page_sizes_prop, page_sizes_prop_size)));
-        }
-
-        _FDT((fdt_end_node(fdt)));
-    }
-
-    g_free(modelname);
-
-    _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_property(fdt, "qemu,hypertas-functions", qemu_hypertas_prop,
-                       sizeof(qemu_hypertas_prop))));
-
-    _FDT((fdt_property(fdt, "ibm,associativity-reference-points",
-        refpoints, sizeof(refpoints))));
-
-    _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
-
-    _FDT((fdt_end_node(fdt)));
-
-    /* interrupt controller */
-    _FDT((fdt_begin_node(fdt, "interrupt-controller")));
-
-    _FDT((fdt_property_string(fdt, "device_type",
-                              "PowerPC-External-Interrupt-Presentation")));
-    _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
-    _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_property_cell(fdt, "#interrupt-cells", 2)));
-    _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP)));
-    _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP)));
-
-    _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_property_cell(fdt, "#interrupt-cells", 0x2)));
-    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
-
-    _FDT((fdt_end_node(fdt)));
-
-    /* event-sources */
-    spapr_events_fdt_skel(fdt, epow_irq);
-
-    _FDT((fdt_end_node(fdt))); /* close root node */
-    _FDT((fdt_finish(fdt)));
-
-    return fdt;
-}
-
-static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt)
-{
-    uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0),
-                                cpu_to_be32(0x0), cpu_to_be32(0x0),
-                                cpu_to_be32(0x0)};
-    char mem_name[32];
-    hwaddr node0_size, mem_start;
-    uint64_t mem_reg_property[2];
-    int i, off;
-
-    /* memory node(s) */
-    node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size;
-    if (spapr->rma_size > node0_size) {
-        spapr->rma_size = node0_size;
-    }
-
-    /* RMA */
-    mem_reg_property[0] = 0;
-    mem_reg_property[1] = cpu_to_be64(spapr->rma_size);
-    off = fdt_add_subnode(fdt, 0, "memory at 0");
-    _FDT(off);
-    _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
-    _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
-                      sizeof(mem_reg_property))));
-    _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
-                      sizeof(associativity))));
-
-    /* RAM: Node 0 */
-    if (node0_size > spapr->rma_size) {
-        mem_reg_property[0] = cpu_to_be64(spapr->rma_size);
-        mem_reg_property[1] = cpu_to_be64(node0_size - spapr->rma_size);
-
-        sprintf(mem_name, "memory@" TARGET_FMT_lx, spapr->rma_size);
-        off = fdt_add_subnode(fdt, 0, mem_name);
-        _FDT(off);
-        _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
-        _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
-                          sizeof(mem_reg_property))));
-        _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
-                          sizeof(associativity))));
-    }
-
-    /* RAM: Node 1 and beyond */
-    mem_start = node0_size;
-    for (i = 1; i < nb_numa_nodes; i++) {
-        mem_reg_property[0] = cpu_to_be64(mem_start);
-        mem_reg_property[1] = cpu_to_be64(node_mem[i]);
-        associativity[3] = associativity[4] = cpu_to_be32(i);
-        sprintf(mem_name, "memory@" TARGET_FMT_lx, mem_start);
-        off = fdt_add_subnode(fdt, 0, mem_name);
-        _FDT(off);
-        _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
-        _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
-                          sizeof(mem_reg_property))));
-        _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
-                          sizeof(associativity))));
-        mem_start += node_mem[i];
-    }
-
-    return 0;
-}
-
-static void spapr_finalize_fdt(sPAPREnvironment *spapr,
-                               hwaddr fdt_addr,
-                               hwaddr rtas_addr,
-                               hwaddr rtas_size)
-{
-    int ret;
-    void *fdt;
-    sPAPRPHBState *phb;
-
-    fdt = g_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_memory(spapr, fdt);
-    if (ret < 0) {
-        fprintf(stderr, "couldn't setup memory nodes in fdt\n");
-        exit(1);
-    }
-
-    ret = spapr_populate_vdevice(spapr->vio_bus, fdt);
-    if (ret < 0) {
-        fprintf(stderr, "couldn't setup vio devices in fdt\n");
-        exit(1);
-    }
-
-    QLIST_FOREACH(phb, &spapr->phbs, list) {
-        ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt);
-    }
-
-    if (ret < 0) {
-        fprintf(stderr, "couldn't setup PCI devices in fdt\n");
-        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");
-    }
-
-    /* Advertise NUMA via ibm,associativity */
-    ret = spapr_fixup_cpu_dt(fdt, spapr);
-    if (ret < 0) {
-        fprintf(stderr, "Couldn't finalize CPU device tree properties\n");
-    }
-
-    if (!spapr->has_graphics) {
-        spapr_populate_chosen_stdout(fdt, spapr->vio_bus);
-    }
-
-    _FDT((fdt_pack(fdt)));
-
-    if (fdt_totalsize(fdt) > FDT_MAX_SIZE) {
-        hw_error("FDT too big ! 0x%x bytes (max is 0x%x)\n",
-                 fdt_totalsize(fdt), FDT_MAX_SIZE);
-        exit(1);
-    }
-
-    cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
-
-    g_free(fdt);
-}
-
-static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
-{
-    return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
-}
-
-static void emulate_spapr_hypercall(PowerPCCPU *cpu)
-{
-    CPUPPCState *env = &cpu->env;
-
-    if (msr_pr) {
-        hcall_dprintf("Hypercall made with MSR[PR]=1\n");
-        env->gpr[3] = H_PRIVILEGE;
-    } else {
-        env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]);
-    }
-}
-
-static void spapr_reset_htab(sPAPREnvironment *spapr)
-{
-    long shift;
-
-    /* allocate hash page table.  For now we always make this 16mb,
-     * later we should probably make it scale to the size of guest
-     * RAM */
-
-    shift = kvmppc_reset_htab(spapr->htab_shift);
-
-    if (shift > 0) {
-        /* Kernel handles htab, we don't need to allocate one */
-        spapr->htab_shift = shift;
-    } else {
-        if (!spapr->htab) {
-            /* Allocate an htab if we don't yet have one */
-            spapr->htab = qemu_memalign(HTAB_SIZE(spapr), HTAB_SIZE(spapr));
-        }
-
-        /* And clear it */
-        memset(spapr->htab, 0, HTAB_SIZE(spapr));
-    }
-
-    /* Update the RMA size if necessary */
-    if (spapr->vrma_adjust) {
-        spapr->rma_size = kvmppc_rma_size(ram_size, spapr->htab_shift);
-    }
-}
-
-static void ppc_spapr_reset(void)
-{
-    /* Reset the hash table & recalc the RMA */
-    spapr_reset_htab(spapr);
-
-    qemu_devices_reset();
-
-    /* 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;
-
-}
-
-static void spapr_cpu_reset(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-
-    cpu_reset(CPU(cpu));
-
-    /* All CPUs start halted.  CPU0 is unhalted from the machine level
-     * reset code and the rest are explicitly started up by the guest
-     * using an RTAS call */
-    env->halted = 1;
-
-    env->spr[SPR_HIOR] = 0;
-
-    env->external_htab = spapr->htab;
-    env->htab_base = -1;
-    env->htab_mask = HTAB_SIZE(spapr) - 1;
-    env->spr[SPR_SDR1] = (unsigned long)spapr->htab |
-        (spapr->htab_shift - 18);
-}
-
-static void spapr_create_nvram(sPAPREnvironment *spapr)
-{
-    QemuOpts *machine_opts;
-    DeviceState *dev;
-
-    dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
-
-    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
-    if (machine_opts) {
-        const char *drivename;
-
-        drivename = qemu_opt_get(machine_opts, "nvram");
-        if (drivename) {
-            BlockDriverState *bs;
-
-            bs = bdrv_find(drivename);
-            if (!bs) {
-                fprintf(stderr, "No such block device \"%s\" for nvram\n",
-                        drivename);
-                exit(1);
-            }
-            qdev_prop_set_drive_nofail(dev, "drive", bs);
-        }
-    }
-
-    qdev_init_nofail(dev);
-
-    spapr->nvram = (struct sPAPRNVRAM *)dev;
-}
-
-/* Returns whether we want to use VGA or not */
-static int spapr_vga_init(PCIBus *pci_bus)
-{
-    switch (vga_interface_type) {
-    case VGA_NONE:
-    case VGA_STD:
-        return pci_vga_init(pci_bus) != NULL;
-    default:
-        fprintf(stderr, "This vga model is not supported,"
-                "currently it only supports -vga std\n");
-        exit(0);
-        break;
-    }
-}
-
-/* pSeries LPAR / sPAPR hardware init */
-static void ppc_spapr_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    PCIHostState *phb;
-    int i;
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    hwaddr rma_alloc_size;
-    uint32_t initrd_base = 0;
-    long kernel_size = 0, initrd_size = 0;
-    long load_limit, rtas_limit, fw_size;
-    char *filename;
-
-    msi_supported = true;
-
-    spapr = g_malloc0(sizeof(*spapr));
-    QLIST_INIT(&spapr->phbs);
-
-    cpu_ppc_hypercall = emulate_spapr_hypercall;
-
-    /* Allocate RMA if necessary */
-    rma_alloc_size = kvmppc_alloc_rma("ppc_spapr.rma", sysmem);
-
-    if (rma_alloc_size == -1) {
-        hw_error("qemu: Unable to create RMA\n");
-        exit(1);
-    }
-
-    if (rma_alloc_size && (rma_alloc_size < ram_size)) {
-        spapr->rma_size = rma_alloc_size;
-    } else {
-        spapr->rma_size = ram_size;
-
-        /* With KVM, we don't actually know whether KVM supports an
-         * unbounded RMA (PR KVM) or is limited by the hash table size
-         * (HV KVM using VRMA), so we always assume the latter
-         *
-         * In that case, we also limit the initial allocations for RTAS
-         * etc... to 256M since we have no way to know what the VRMA size
-         * is going to be as it depends on the size of the hash table
-         * isn't determined yet.
-         */
-        if (kvm_enabled()) {
-            spapr->vrma_adjust = 1;
-            spapr->rma_size = MIN(spapr->rma_size, 0x10000000);
-        }
-    }
-
-    /* We place the device tree and RTAS just below either the top of the RMA,
-     * or just below 2GB, whichever is lowere, so that it can be
-     * processed with 32-bit real mode code if necessary */
-    rtas_limit = MIN(spapr->rma_size, 0x80000000);
-    spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE;
-    spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE;
-    load_limit = spapr->fdt_addr - FW_OVERHEAD;
-
-    /* We aim for a hash table of size 1/128 the size of RAM.  The
-     * normal rule of thumb is 1/64 the size of RAM, but that's much
-     * more than needed for the Linux guests we support. */
-    spapr->htab_shift = 18; /* Minimum architected size */
-    while (spapr->htab_shift <= 46) {
-        if ((1ULL << (spapr->htab_shift + 7)) >= ram_size) {
-            break;
-        }
-        spapr->htab_shift++;
-    }
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-        cpu_model = kvm_enabled() ? "host" : "POWER7";
-    }
-    for (i = 0; i < smp_cpus; i++) {
-        cpu = cpu_ppc_init(cpu_model);
-        if (cpu == NULL) {
-            fprintf(stderr, "Unable to find PowerPC CPU definition\n");
-            exit(1);
-        }
-        env = &cpu->env;
-
-        /* Set time-base frequency to 512 MHz */
-        cpu_ppc_tb_init(env, TIMEBASE_FREQ);
-
-        /* PAPR always has exception vectors in RAM not ROM */
-        env->hreset_excp_prefix = 0;
-
-        /* Tell KVM that we're in PAPR mode */
-        if (kvm_enabled()) {
-            kvmppc_set_papr(cpu);
-        }
-
-        qemu_register_reset(spapr_cpu_reset, cpu);
-    }
-
-    /* allocate RAM */
-    spapr->ram_limit = ram_size;
-    if (spapr->ram_limit > rma_alloc_size) {
-        ram_addr_t nonrma_base = rma_alloc_size;
-        ram_addr_t nonrma_size = spapr->ram_limit - rma_alloc_size;
-
-        memory_region_init_ram(ram, "ppc_spapr.ram", nonrma_size);
-        vmstate_register_ram_global(ram);
-        memory_region_add_subregion(sysmem, nonrma_base, ram);
-    }
-
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
-    spapr->rtas_size = load_image_targphys(filename, spapr->rtas_addr,
-                                           rtas_limit - spapr->rtas_addr);
-    if (spapr->rtas_size < 0) {
-        hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
-        exit(1);
-    }
-    if (spapr->rtas_size > RTAS_MAX_SIZE) {
-        hw_error("RTAS too big ! 0x%lx bytes (max is 0x%x)\n",
-                 spapr->rtas_size, RTAS_MAX_SIZE);
-        exit(1);
-    }
-    g_free(filename);
-
-
-    /* Set up Interrupt Controller */
-    spapr->icp = xics_system_init(XICS_IRQS);
-    spapr->next_irq = XICS_IRQ_BASE;
-
-    /* Set up EPOW events infrastructure */
-    spapr_events_init(spapr);
-
-    /* Set up IOMMU */
-    spapr_iommu_init();
-
-    /* Set up VIO bus */
-    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, serial_hds[i]);
-        }
-    }
-
-    /* We always have at least the nvram device on VIO */
-    spapr_create_nvram(spapr);
-
-    /* Set up PCI */
-    spapr_pci_rtas_init();
-
-    phb = spapr_create_phb(spapr, 0, "pci");
-
-    for (i = 0; i < nb_nics; i++) {
-        NICInfo *nd = &nd_table[i];
-
-        if (!nd->model) {
-            nd->model = g_strdup("ibmveth");
-        }
-
-        if (strcmp(nd->model, "ibmveth") == 0) {
-            spapr_vlan_create(spapr->vio_bus, nd);
-        } else {
-            pci_nic_init_nofail(&nd_table[i], nd->model, NULL);
-        }
-    }
-
-    for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) {
-        spapr_vscsi_create(spapr->vio_bus);
-    }
-
-    /* Graphics */
-    if (spapr_vga_init(phb->bus)) {
-        spapr->has_graphics = true;
-    }
-
-    if (usb_enabled(spapr->has_graphics)) {
-        pci_create_simple(phb->bus, -1, "pci-ohci");
-        if (spapr->has_graphics) {
-            usbdevice_create("keyboard");
-            usbdevice_create("mouse");
-        }
-    }
-
-    if (spapr->rma_size < (MIN_RMA_SLOF << 20)) {
-        fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
-                "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF);
-        exit(1);
-    }
-
-    if (kernel_filename) {
-        uint64_t lowaddr = 0;
-
-        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_LOAD_ADDR,
-                                              load_limit - KERNEL_LOAD_ADDR);
-        }
-        if (kernel_size < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n",
-                    kernel_filename);
-            exit(1);
-        }
-
-        /* load initrd */
-        if (initrd_filename) {
-            /* Try to locate the initrd in the gap between the kernel
-             * and the firmware. Add a bit of space just in case
-             */
-            initrd_base = (KERNEL_LOAD_ADDR + kernel_size + 0x1ffff) & ~0xffff;
-            initrd_size = load_image_targphys(initrd_filename, initrd_base,
-                                              load_limit - 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;
-        }
-    }
-
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME);
-    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);
-    }
-    g_free(filename);
-
-    spapr->entry_point = 0x100;
-
-    /* Prepare the device tree */
-    spapr->fdt_skel = spapr_create_fdt_skel(cpu_model,
-                                            initrd_base, initrd_size,
-                                            kernel_size,
-                                            boot_device, kernel_cmdline,
-                                            spapr->epow_irq);
-    assert(spapr->fdt_skel != NULL);
-}
-
-static QEMUMachine spapr_machine = {
-    .name = "pseries",
-    .desc = "pSeries Logical Partition (PAPR compliant)",
-    .init = ppc_spapr_init,
-    .reset = ppc_spapr_reset,
-    .block_default_type = IF_SCSI,
-    .max_cpus = MAX_CPUS,
-    .no_parallel = 1,
-    .boot_order = NULL,
-};
-
-static void spapr_machine_init(void)
-{
-    qemu_register_machine(&spapr_machine);
-}
-
-machine_init(spapr_machine_init);
diff --git a/hw/sparc/Makefile.objs b/hw/sparc/Makefile.objs
index a39a511..71bbddf 100644
--- a/hw/sparc/Makefile.objs
+++ b/hw/sparc/Makefile.objs
@@ -1,8 +1,10 @@
-obj-y = sun4m.o lance.o tcx.o sun4m_iommu.o slavio_intctl.o
+obj-y = lance.o tcx.o sun4m_iommu.o slavio_intctl.o
 obj-y += slavio_timer.o slavio_misc.o sparc32_dma.o
-obj-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o leon3.o
+obj-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o
 
 # GRLIB
 obj-y += grlib_gptimer.o grlib_irqmp.o grlib_apbuart.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += sun4m.o leon3.o
diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
new file mode 100644
index 0000000..f58061f
--- /dev/null
+++ b/hw/sparc/leon3.c
@@ -0,0 +1,223 @@
+/*
+ * QEMU Leon3 System Emulator
+ *
+ * Copyright (c) 2010-2011 AdaCore
+ *
+ * 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/hw.h"
+#include "qemu/timer.h"
+#include "hw/ptimer.h"
+#include "char/char.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "trace.h"
+#include "exec/address-spaces.h"
+
+#include "hw/grlib.h"
+
+/* Default system clock.  */
+#define CPU_CLK (40 * 1000 * 1000)
+
+#define PROM_FILENAME        "u-boot.bin"
+
+#define MAX_PILS 16
+
+typedef struct ResetData {
+    SPARCCPU *cpu;
+    uint32_t  entry;            /* save kernel entry in case of reset */
+} ResetData;
+
+static void main_cpu_reset(void *opaque)
+{
+    ResetData *s   = (ResetData *)opaque;
+    CPUSPARCState  *env = &s->cpu->env;
+
+    cpu_reset(CPU(s->cpu));
+
+    env->halted = 0;
+    env->pc     = s->entry;
+    env->npc    = s->entry + 4;
+}
+
+void leon3_irq_ack(void *irq_manager, int intno)
+{
+    grlib_irqmp_ack((DeviceState *)irq_manager, intno);
+}
+
+static void leon3_set_pil_in(void *opaque, uint32_t pil_in)
+{
+    CPUSPARCState *env = (CPUSPARCState *)opaque;
+
+    assert(env != NULL);
+
+    env->pil_in = pil_in;
+
+    if (env->pil_in && (env->interrupt_index == 0 ||
+                        (env->interrupt_index & ~15) == TT_EXTINT)) {
+        unsigned int i;
+
+        for (i = 15; i > 0; i--) {
+            if (env->pil_in & (1 << i)) {
+                int old_interrupt = env->interrupt_index;
+
+                env->interrupt_index = TT_EXTINT | i;
+                if (old_interrupt != env->interrupt_index) {
+                    trace_leon3_set_irq(i);
+                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+                }
+                break;
+            }
+        }
+    } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
+        trace_leon3_reset_irq(env->interrupt_index & 15);
+        env->interrupt_index = 0;
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+static void leon3_generic_hw_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    SPARCCPU *cpu;
+    CPUSPARCState   *env;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *prom = g_new(MemoryRegion, 1);
+    int         ret;
+    char       *filename;
+    qemu_irq   *cpu_irqs = NULL;
+    int         bios_size;
+    int         prom_size;
+    ResetData  *reset_info;
+
+    /* Init CPU */
+    if (!cpu_model) {
+        cpu_model = "LEON3";
+    }
+
+    cpu = cpu_sparc_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    cpu_sparc_set_id(env, 0);
+
+    /* Reset data */
+    reset_info        = g_malloc0(sizeof(ResetData));
+    reset_info->cpu   = cpu;
+    qemu_register_reset(main_cpu_reset, reset_info);
+
+    /* Allocate IRQ manager */
+    grlib_irqmp_create(0x80000200, env, &cpu_irqs, MAX_PILS, &leon3_set_pil_in);
+
+    env->qemu_irq_ack = leon3_irq_manager;
+
+    /* Allocate RAM */
+    if ((uint64_t)ram_size > (1UL << 30)) {
+        fprintf(stderr,
+                "qemu: Too much memory for this machine: %d, maximum 1G\n",
+                (unsigned int)(ram_size / (1024 * 1024)));
+        exit(1);
+    }
+
+    memory_region_init_ram(ram, "leon3.ram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(address_space_mem, 0x40000000, ram);
+
+    /* Allocate BIOS */
+    prom_size = 8 * 1024 * 1024; /* 8Mb */
+    memory_region_init_ram(prom, "Leon3.bios", prom_size);
+    vmstate_register_ram_global(prom);
+    memory_region_set_readonly(prom, true);
+    memory_region_add_subregion(address_space_mem, 0x00000000, prom);
+
+    /* Load boot prom */
+    if (bios_name == NULL) {
+        bios_name = PROM_FILENAME;
+    }
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+
+    bios_size = get_image_size(filename);
+
+    if (bios_size > prom_size) {
+        fprintf(stderr, "qemu: could not load prom '%s': file too big\n",
+                filename);
+        exit(1);
+    }
+
+    if (bios_size > 0) {
+        ret = load_image_targphys(filename, 0x00000000, bios_size);
+        if (ret < 0 || ret > prom_size) {
+            fprintf(stderr, "qemu: could not load prom '%s'\n", filename);
+            exit(1);
+        }
+    } else if (kernel_filename == NULL) {
+        fprintf(stderr, "Can't read bios image %s\n", filename);
+        exit(1);
+    }
+
+    /* Can directly load an application. */
+    if (kernel_filename != NULL) {
+        long     kernel_size;
+        uint64_t entry;
+
+        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
+                               1 /* big endian */, ELF_MACHINE, 0);
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+        if (bios_size <= 0) {
+            /* If there is no bios/monitor, start the application.  */
+            env->pc = entry;
+            env->npc = entry + 4;
+            reset_info->entry = entry;
+        }
+    }
+
+    /* Allocate timers */
+    grlib_gptimer_create(0x80000300, 2, CPU_CLK, cpu_irqs, 6);
+
+    /* Allocate uart */
+    if (serial_hds[0]) {
+        grlib_apbuart_create(0x80000100, serial_hds[0], cpu_irqs[3]);
+    }
+}
+
+static QEMUMachine leon3_generic_machine = {
+    .name     = "leon3_generic",
+    .desc     = "Leon-3 generic",
+    .init     = leon3_generic_hw_init,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void leon3_machine_init(void)
+{
+    qemu_register_machine(&leon3_generic_machine);
+}
+
+machine_init(leon3_machine_init);
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
new file mode 100644
index 0000000..37bd041
--- /dev/null
+++ b/hw/sparc/sun4m.c
@@ -0,0 +1,1936 @@
+/*
+ * QEMU Sun4m & Sun4d & Sun4c System Emulator
+ *
+ * Copyright (c) 2003-2005 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 "hw/sysbus.h"
+#include "qemu/timer.h"
+#include "hw/sun4m.h"
+#include "hw/nvram.h"
+#include "hw/sparc32_dma.h"
+#include "hw/fdc.h"
+#include "sysemu/sysemu.h"
+#include "net/net.h"
+#include "hw/boards.h"
+#include "hw/firmware_abi.h"
+#include "hw/esp.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
+#include "hw/fw_cfg.h"
+#include "hw/escc.h"
+#include "hw/empty_slot.h"
+#include "hw/qdev-addr.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "sysemu/blockdev.h"
+#include "trace.h"
+
+/*
+ * Sun4m architecture was used in the following machines:
+ *
+ * SPARCserver 6xxMP/xx
+ * SPARCclassic (SPARCclassic Server)(SPARCstation LC) (4/15),
+ * SPARCclassic X (4/10)
+ * SPARCstation LX/ZX (4/30)
+ * SPARCstation Voyager
+ * SPARCstation 10/xx, SPARCserver 10/xx
+ * SPARCstation 5, SPARCserver 5
+ * SPARCstation 20/xx, SPARCserver 20
+ * SPARCstation 4
+ *
+ * Sun4d architecture was used in the following machines:
+ *
+ * SPARCcenter 2000
+ * SPARCserver 1000
+ *
+ * Sun4c architecture was used in the following machines:
+ * SPARCstation 1/1+, SPARCserver 1/1+
+ * SPARCstation SLC
+ * SPARCstation IPC
+ * SPARCstation ELC
+ * SPARCstation IPX
+ *
+ * See for example: http://www.sunhelp.org/faq/sunref1.html
+ */
+
+#define KERNEL_LOAD_ADDR     0x00004000
+#define CMDLINE_ADDR         0x007ff000
+#define INITRD_LOAD_ADDR     0x00800000
+#define PROM_SIZE_MAX        (1024 * 1024)
+#define PROM_VADDR           0xffd00000
+#define PROM_FILENAME        "openbios-sparc32"
+#define CFG_ADDR             0xd00000510ULL
+#define FW_CFG_SUN4M_DEPTH   (FW_CFG_ARCH_LOCAL + 0x00)
+
+#define MAX_CPUS 16
+#define MAX_PILS 16
+#define MAX_VSIMMS 4
+
+#define ESCC_CLOCK 4915200
+
+struct sun4m_hwdef {
+    hwaddr iommu_base, iommu_pad_base, iommu_pad_len, slavio_base;
+    hwaddr intctl_base, counter_base, nvram_base, ms_kb_base;
+    hwaddr serial_base, fd_base;
+    hwaddr afx_base, idreg_base, dma_base, esp_base, le_base;
+    hwaddr tcx_base, cs_base, apc_base, aux1_base, aux2_base;
+    hwaddr bpp_base, dbri_base, sx_base;
+    struct {
+        hwaddr reg_base, vram_base;
+    } vsimm[MAX_VSIMMS];
+    hwaddr ecc_base;
+    uint64_t max_mem;
+    const char * const default_cpu_model;
+    uint32_t ecc_version;
+    uint32_t iommu_version;
+    uint16_t machine_id;
+    uint8_t nvram_machine_id;
+};
+
+#define MAX_IOUNITS 5
+
+struct sun4d_hwdef {
+    hwaddr iounit_bases[MAX_IOUNITS], slavio_base;
+    hwaddr counter_base, nvram_base, ms_kb_base;
+    hwaddr serial_base;
+    hwaddr espdma_base, esp_base;
+    hwaddr ledma_base, le_base;
+    hwaddr tcx_base;
+    hwaddr sbi_base;
+    uint64_t max_mem;
+    const char * const default_cpu_model;
+    uint32_t iounit_version;
+    uint16_t machine_id;
+    uint8_t nvram_machine_id;
+};
+
+struct sun4c_hwdef {
+    hwaddr iommu_base, slavio_base;
+    hwaddr intctl_base, counter_base, nvram_base, ms_kb_base;
+    hwaddr serial_base, fd_base;
+    hwaddr idreg_base, dma_base, esp_base, le_base;
+    hwaddr tcx_base, aux1_base;
+    uint64_t max_mem;
+    const char * const default_cpu_model;
+    uint32_t iommu_version;
+    uint16_t machine_id;
+    uint8_t nvram_machine_id;
+};
+
+int DMA_get_channel_mode (int nchan)
+{
+    return 0;
+}
+int DMA_read_memory (int nchan, void *buf, int pos, int size)
+{
+    return 0;
+}
+int DMA_write_memory (int nchan, void *buf, int pos, int size)
+{
+    return 0;
+}
+void DMA_hold_DREQ (int nchan) {}
+void DMA_release_DREQ (int nchan) {}
+void DMA_schedule(int nchan) {}
+
+void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
+{
+}
+
+void DMA_register_channel (int nchan,
+                           DMA_transfer_handler transfer_handler,
+                           void *opaque)
+{
+}
+
+static int fw_cfg_boot_set(void *opaque, const char *boot_device)
+{
+    fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
+    return 0;
+}
+
+static void nvram_init(M48t59State *nvram, uint8_t *macaddr,
+                       const char *cmdline, const char *boot_devices,
+                       ram_addr_t RAM_size, uint32_t kernel_size,
+                       int width, int height, int depth,
+                       int nvram_machine_id, const char *arch)
+{
+    unsigned int i;
+    uint32_t start, end;
+    uint8_t image[0x1ff0];
+    struct OpenBIOS_nvpart_v1 *part_header;
+
+    memset(image, '\0', sizeof(image));
+
+    start = 0;
+
+    // OpenBIOS nvram variables
+    // Variable partition
+    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
+    part_header->signature = OPENBIOS_PART_SYSTEM;
+    pstrcpy(part_header->name, sizeof(part_header->name), "system");
+
+    end = start + sizeof(struct OpenBIOS_nvpart_v1);
+    for (i = 0; i < nb_prom_envs; i++)
+        end = OpenBIOS_set_var(image, end, prom_envs[i]);
+
+    // End marker
+    image[end++] = '\0';
+
+    end = start + ((end - start + 15) & ~15);
+    OpenBIOS_finish_partition(part_header, end - start);
+
+    // free partition
+    start = end;
+    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
+    part_header->signature = OPENBIOS_PART_FREE;
+    pstrcpy(part_header->name, sizeof(part_header->name), "free");
+
+    end = 0x1fd0;
+    OpenBIOS_finish_partition(part_header, end - start);
+
+    Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr,
+                    nvram_machine_id);
+
+    for (i = 0; i < sizeof(image); i++)
+        m48t59_write(nvram, i, image[i]);
+}
+
+static DeviceState *slavio_intctl;
+
+void sun4m_pic_info(Monitor *mon, const QDict *qdict)
+{
+    if (slavio_intctl)
+        slavio_pic_info(mon, slavio_intctl);
+}
+
+void sun4m_irq_info(Monitor *mon, const QDict *qdict)
+{
+    if (slavio_intctl)
+        slavio_irq_info(mon, slavio_intctl);
+}
+
+void cpu_check_irqs(CPUSPARCState *env)
+{
+    if (env->pil_in && (env->interrupt_index == 0 ||
+                        (env->interrupt_index & ~15) == TT_EXTINT)) {
+        unsigned int i;
+
+        for (i = 15; i > 0; i--) {
+            if (env->pil_in & (1 << i)) {
+                int old_interrupt = env->interrupt_index;
+
+                env->interrupt_index = TT_EXTINT | i;
+                if (old_interrupt != env->interrupt_index) {
+                    trace_sun4m_cpu_interrupt(i);
+                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+                }
+                break;
+            }
+        }
+    } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
+        trace_sun4m_cpu_reset_interrupt(env->interrupt_index & 15);
+        env->interrupt_index = 0;
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+static void cpu_kick_irq(SPARCCPU *cpu)
+{
+    CPUSPARCState *env = &cpu->env;
+
+    env->halted = 0;
+    cpu_check_irqs(env);
+    qemu_cpu_kick(CPU(cpu));
+}
+
+static void cpu_set_irq(void *opaque, int irq, int level)
+{
+    SPARCCPU *cpu = opaque;
+    CPUSPARCState *env = &cpu->env;
+
+    if (level) {
+        trace_sun4m_cpu_set_irq_raise(irq);
+        env->pil_in |= 1 << irq;
+        cpu_kick_irq(cpu);
+    } else {
+        trace_sun4m_cpu_set_irq_lower(irq);
+        env->pil_in &= ~(1 << irq);
+        cpu_check_irqs(env);
+    }
+}
+
+static void dummy_cpu_set_irq(void *opaque, int irq, int level)
+{
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    SPARCCPU *cpu = opaque;
+    CPUSPARCState *env = &cpu->env;
+
+    cpu_reset(CPU(cpu));
+    env->halted = 0;
+}
+
+static void secondary_cpu_reset(void *opaque)
+{
+    SPARCCPU *cpu = opaque;
+    CPUSPARCState *env = &cpu->env;
+
+    cpu_reset(CPU(cpu));
+    env->halted = 1;
+}
+
+static void cpu_halt_signal(void *opaque, int irq, int level)
+{
+    if (level && cpu_single_env)
+        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
+}
+
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+    return addr - 0xf0000000ULL;
+}
+
+static unsigned long sun4m_load_kernel(const char *kernel_filename,
+                                       const char *initrd_filename,
+                                       ram_addr_t RAM_size)
+{
+    int linux_boot;
+    unsigned int i;
+    long initrd_size, kernel_size;
+    uint8_t *ptr;
+
+    linux_boot = (kernel_filename != NULL);
+
+    kernel_size = 0;
+    if (linux_boot) {
+        int bswap_needed;
+
+#ifdef BSWAP_NEEDED
+        bswap_needed = 1;
+#else
+        bswap_needed = 0;
+#endif
+        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+                               NULL, NULL, NULL, 1, ELF_MACHINE, 0);
+        if (kernel_size < 0)
+            kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
+                                    RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
+                                    TARGET_PAGE_SIZE);
+        if (kernel_size < 0)
+            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",
+                    kernel_filename);
+            exit(1);
+        }
+
+        /* load initrd */
+        initrd_size = 0;
+        if (initrd_filename) {
+            initrd_size = load_image_targphys(initrd_filename,
+                                              INITRD_LOAD_ADDR,
+                                              RAM_size - INITRD_LOAD_ADDR);
+            if (initrd_size < 0) {
+                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                        initrd_filename);
+                exit(1);
+            }
+        }
+        if (initrd_size > 0) {
+            for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
+                ptr = rom_ptr(KERNEL_LOAD_ADDR + i);
+                if (ldl_p(ptr) == 0x48647253) { // HdrS
+                    stl_p(ptr + 16, INITRD_LOAD_ADDR);
+                    stl_p(ptr + 20, initrd_size);
+                    break;
+                }
+            }
+        }
+    }
+    return kernel_size;
+}
+
+static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "iommu");
+    qdev_prop_set_uint32(dev, "version", version);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(s, 0, irq);
+    sysbus_mmio_map(s, 0, addr);
+
+    return s;
+}
+
+static void *sparc32_dma_init(hwaddr daddr, qemu_irq parent_irq,
+                              void *iommu, qemu_irq *dev_irq, int is_ledma)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "sparc32_dma");
+    qdev_prop_set_ptr(dev, "iommu_opaque", iommu);
+    qdev_prop_set_uint32(dev, "is_ledma", is_ledma);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(s, 0, parent_irq);
+    *dev_irq = qdev_get_gpio_in(dev, 0);
+    sysbus_mmio_map(s, 0, daddr);
+
+    return s;
+}
+
+static void lance_init(NICInfo *nd, hwaddr leaddr,
+                       void *dma_opaque, qemu_irq irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    qemu_irq reset;
+
+    qemu_check_nic_model(&nd_table[0], "lance");
+
+    dev = qdev_create(NULL, "lance");
+    qdev_set_nic_properties(dev, nd);
+    qdev_prop_set_ptr(dev, "dma", dma_opaque);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(s, 0, leaddr);
+    sysbus_connect_irq(s, 0, irq);
+    reset = qdev_get_gpio_in(dev, 0);
+    qdev_connect_gpio_out(dma_opaque, 0, reset);
+}
+
+static DeviceState *slavio_intctl_init(hwaddr addr,
+                                       hwaddr addrg,
+                                       qemu_irq **parent_irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    unsigned int i, j;
+
+    dev = qdev_create(NULL, "slavio_intctl");
+    qdev_init_nofail(dev);
+
+    s = SYS_BUS_DEVICE(dev);
+
+    for (i = 0; i < MAX_CPUS; i++) {
+        for (j = 0; j < MAX_PILS; j++) {
+            sysbus_connect_irq(s, i * MAX_PILS + j, parent_irq[i][j]);
+        }
+    }
+    sysbus_mmio_map(s, 0, addrg);
+    for (i = 0; i < MAX_CPUS; i++) {
+        sysbus_mmio_map(s, i + 1, addr + i * TARGET_PAGE_SIZE);
+    }
+
+    return dev;
+}
+
+#define SYS_TIMER_OFFSET      0x10000ULL
+#define CPU_TIMER_OFFSET(cpu) (0x1000ULL * cpu)
+
+static void slavio_timer_init_all(hwaddr addr, qemu_irq master_irq,
+                                  qemu_irq *cpu_irqs, unsigned int num_cpus)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    unsigned int i;
+
+    dev = qdev_create(NULL, "slavio_timer");
+    qdev_prop_set_uint32(dev, "num_cpus", num_cpus);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(s, 0, master_irq);
+    sysbus_mmio_map(s, 0, addr + SYS_TIMER_OFFSET);
+
+    for (i = 0; i < MAX_CPUS; i++) {
+        sysbus_mmio_map(s, i + 1, addr + (hwaddr)CPU_TIMER_OFFSET(i));
+        sysbus_connect_irq(s, i + 1, cpu_irqs[i]);
+    }
+}
+
+static qemu_irq  slavio_system_powerdown;
+
+static void slavio_powerdown_req(Notifier *n, void *opaque)
+{
+    qemu_irq_raise(slavio_system_powerdown);
+}
+
+static Notifier slavio_system_powerdown_notifier = {
+    .notify = slavio_powerdown_req
+};
+
+#define MISC_LEDS 0x01600000
+#define MISC_CFG  0x01800000
+#define MISC_DIAG 0x01a00000
+#define MISC_MDM  0x01b00000
+#define MISC_SYS  0x01f00000
+
+static void slavio_misc_init(hwaddr base,
+                             hwaddr aux1_base,
+                             hwaddr aux2_base, qemu_irq irq,
+                             qemu_irq fdc_tc)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "slavio_misc");
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    if (base) {
+        /* 8 bit registers */
+        /* Slavio control */
+        sysbus_mmio_map(s, 0, base + MISC_CFG);
+        /* Diagnostics */
+        sysbus_mmio_map(s, 1, base + MISC_DIAG);
+        /* Modem control */
+        sysbus_mmio_map(s, 2, base + MISC_MDM);
+        /* 16 bit registers */
+        /* ss600mp diag LEDs */
+        sysbus_mmio_map(s, 3, base + MISC_LEDS);
+        /* 32 bit registers */
+        /* System control */
+        sysbus_mmio_map(s, 4, base + MISC_SYS);
+    }
+    if (aux1_base) {
+        /* AUX 1 (Misc System Functions) */
+        sysbus_mmio_map(s, 5, aux1_base);
+    }
+    if (aux2_base) {
+        /* AUX 2 (Software Powerdown Control) */
+        sysbus_mmio_map(s, 6, aux2_base);
+    }
+    sysbus_connect_irq(s, 0, irq);
+    sysbus_connect_irq(s, 1, fdc_tc);
+    slavio_system_powerdown = qdev_get_gpio_in(dev, 0);
+    qemu_register_powerdown_notifier(&slavio_system_powerdown_notifier);
+}
+
+static void ecc_init(hwaddr base, qemu_irq irq, uint32_t version)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "eccmemctl");
+    qdev_prop_set_uint32(dev, "version", version);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(s, 0, irq);
+    sysbus_mmio_map(s, 0, base);
+    if (version == 0) { // SS-600MP only
+        sysbus_mmio_map(s, 1, base + 0x1000);
+    }
+}
+
+static void apc_init(hwaddr power_base, qemu_irq cpu_halt)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "apc");
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    /* Power management (APC) XXX: not a Slavio device */
+    sysbus_mmio_map(s, 0, power_base);
+    sysbus_connect_irq(s, 0, cpu_halt);
+}
+
+static void tcx_init(hwaddr addr, int vram_size, int width,
+                     int height, int depth)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "SUNW,tcx");
+    qdev_prop_set_taddr(dev, "addr", addr);
+    qdev_prop_set_uint32(dev, "vram_size", vram_size);
+    qdev_prop_set_uint16(dev, "width", width);
+    qdev_prop_set_uint16(dev, "height", height);
+    qdev_prop_set_uint16(dev, "depth", depth);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    /* 8-bit plane */
+    sysbus_mmio_map(s, 0, addr + 0x00800000ULL);
+    /* DAC */
+    sysbus_mmio_map(s, 1, addr + 0x00200000ULL);
+    /* TEC (dummy) */
+    sysbus_mmio_map(s, 2, addr + 0x00700000ULL);
+    /* THC 24 bit: NetBSD writes here even with 8-bit display: dummy */
+    sysbus_mmio_map(s, 3, addr + 0x00301000ULL);
+    if (depth == 24) {
+        /* 24-bit plane */
+        sysbus_mmio_map(s, 4, addr + 0x02000000ULL);
+        /* Control plane */
+        sysbus_mmio_map(s, 5, addr + 0x0a000000ULL);
+    } else {
+        /* THC 8 bit (dummy) */
+        sysbus_mmio_map(s, 4, addr + 0x00300000ULL);
+    }
+}
+
+/* NCR89C100/MACIO Internal ID register */
+static const uint8_t idreg_data[] = { 0xfe, 0x81, 0x01, 0x03 };
+
+static void idreg_init(hwaddr addr)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "macio_idreg");
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+
+    sysbus_mmio_map(s, 0, addr);
+    cpu_physical_memory_write_rom(addr, idreg_data, sizeof(idreg_data));
+}
+
+typedef struct IDRegState {
+    SysBusDevice busdev;
+    MemoryRegion mem;
+} IDRegState;
+
+static int idreg_init1(SysBusDevice *dev)
+{
+    IDRegState *s = FROM_SYSBUS(IDRegState, dev);
+
+    memory_region_init_ram(&s->mem, "sun4m.idreg", sizeof(idreg_data));
+    vmstate_register_ram_global(&s->mem);
+    memory_region_set_readonly(&s->mem, true);
+    sysbus_init_mmio(dev, &s->mem);
+    return 0;
+}
+
+static void idreg_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = idreg_init1;
+}
+
+static const TypeInfo idreg_info = {
+    .name          = "macio_idreg",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(IDRegState),
+    .class_init    = idreg_class_init,
+};
+
+typedef struct AFXState {
+    SysBusDevice busdev;
+    MemoryRegion mem;
+} AFXState;
+
+/* SS-5 TCX AFX register */
+static void afx_init(hwaddr addr)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "tcx_afx");
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+
+    sysbus_mmio_map(s, 0, addr);
+}
+
+static int afx_init1(SysBusDevice *dev)
+{
+    AFXState *s = FROM_SYSBUS(AFXState, dev);
+
+    memory_region_init_ram(&s->mem, "sun4m.afx", 4);
+    vmstate_register_ram_global(&s->mem);
+    sysbus_init_mmio(dev, &s->mem);
+    return 0;
+}
+
+static void afx_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = afx_init1;
+}
+
+static const TypeInfo afx_info = {
+    .name          = "tcx_afx",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(AFXState),
+    .class_init    = afx_class_init,
+};
+
+typedef struct PROMState {
+    SysBusDevice busdev;
+    MemoryRegion prom;
+} PROMState;
+
+/* Boot PROM (OpenBIOS) */
+static uint64_t translate_prom_address(void *opaque, uint64_t addr)
+{
+    hwaddr *base_addr = (hwaddr *)opaque;
+    return addr + *base_addr - PROM_VADDR;
+}
+
+static void prom_init(hwaddr addr, const char *bios_name)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    char *filename;
+    int ret;
+
+    dev = qdev_create(NULL, "openprom");
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+
+    sysbus_mmio_map(s, 0, addr);
+
+    /* load boot prom */
+    if (bios_name == NULL) {
+        bios_name = PROM_FILENAME;
+    }
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+    if (filename) {
+        ret = load_elf(filename, translate_prom_address, &addr, NULL,
+                       NULL, NULL, 1, ELF_MACHINE, 0);
+        if (ret < 0 || ret > PROM_SIZE_MAX) {
+            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
+        }
+        g_free(filename);
+    } else {
+        ret = -1;
+    }
+    if (ret < 0 || ret > PROM_SIZE_MAX) {
+        fprintf(stderr, "qemu: could not load prom '%s'\n", bios_name);
+        exit(1);
+    }
+}
+
+static int prom_init1(SysBusDevice *dev)
+{
+    PROMState *s = FROM_SYSBUS(PROMState, dev);
+
+    memory_region_init_ram(&s->prom, "sun4m.prom", PROM_SIZE_MAX);
+    vmstate_register_ram_global(&s->prom);
+    memory_region_set_readonly(&s->prom, true);
+    sysbus_init_mmio(dev, &s->prom);
+    return 0;
+}
+
+static Property prom_properties[] = {
+    {/* end of property list */},
+};
+
+static void prom_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = prom_init1;
+    dc->props = prom_properties;
+}
+
+static const TypeInfo prom_info = {
+    .name          = "openprom",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PROMState),
+    .class_init    = prom_class_init,
+};
+
+typedef struct RamDevice
+{
+    SysBusDevice busdev;
+    MemoryRegion ram;
+    uint64_t size;
+} RamDevice;
+
+/* System RAM */
+static int ram_init1(SysBusDevice *dev)
+{
+    RamDevice *d = FROM_SYSBUS(RamDevice, dev);
+
+    memory_region_init_ram(&d->ram, "sun4m.ram", d->size);
+    vmstate_register_ram_global(&d->ram);
+    sysbus_init_mmio(dev, &d->ram);
+    return 0;
+}
+
+static void ram_init(hwaddr addr, ram_addr_t RAM_size,
+                     uint64_t max_mem)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    RamDevice *d;
+
+    /* allocate RAM */
+    if ((uint64_t)RAM_size > max_mem) {
+        fprintf(stderr,
+                "qemu: Too much memory for this machine: %d, maximum %d\n",
+                (unsigned int)(RAM_size / (1024 * 1024)),
+                (unsigned int)(max_mem / (1024 * 1024)));
+        exit(1);
+    }
+    dev = qdev_create(NULL, "memory");
+    s = SYS_BUS_DEVICE(dev);
+
+    d = FROM_SYSBUS(RamDevice, s);
+    d->size = RAM_size;
+    qdev_init_nofail(dev);
+
+    sysbus_mmio_map(s, 0, addr);
+}
+
+static Property ram_properties[] = {
+    DEFINE_PROP_UINT64("size", RamDevice, size, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ram_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = ram_init1;
+    dc->props = ram_properties;
+}
+
+static const TypeInfo ram_info = {
+    .name          = "memory",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(RamDevice),
+    .class_init    = ram_class_init,
+};
+
+static void cpu_devinit(const char *cpu_model, unsigned int id,
+                        uint64_t prom_addr, qemu_irq **cpu_irqs)
+{
+    SPARCCPU *cpu;
+    CPUSPARCState *env;
+
+    cpu = cpu_sparc_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    cpu_sparc_set_id(env, id);
+    if (id == 0) {
+        qemu_register_reset(main_cpu_reset, cpu);
+    } else {
+        qemu_register_reset(secondary_cpu_reset, cpu);
+        env->halted = 1;
+    }
+    *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, cpu, MAX_PILS);
+    env->prom_addr = prom_addr;
+}
+
+static void dummy_fdc_tc(void *opaque, int irq, int level)
+{
+}
+
+static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, 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)
+{
+    unsigned int i;
+    void *iommu, *espdma, *ledma, *nvram;
+    qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS],
+        espdma_irq, ledma_irq;
+    qemu_irq esp_reset, dma_enable;
+    qemu_irq fdc_tc;
+    qemu_irq *cpu_halt;
+    unsigned long kernel_size;
+    DriveInfo *fd[MAX_FD];
+    void *fw_cfg;
+    unsigned int num_vsimms;
+
+    /* init CPUs */
+    if (!cpu_model)
+        cpu_model = hwdef->default_cpu_model;
+
+    for(i = 0; i < smp_cpus; i++) {
+        cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]);
+    }
+
+    for (i = smp_cpus; i < MAX_CPUS; i++)
+        cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS);
+
+
+    /* set up devices */
+    ram_init(0, RAM_size, hwdef->max_mem);
+    /* models without ECC don't trap when missing ram is accessed */
+    if (!hwdef->ecc_base) {
+        empty_slot_init(RAM_size, hwdef->max_mem - RAM_size);
+    }
+
+    prom_init(hwdef->slavio_base, bios_name);
+
+    slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
+                                       hwdef->intctl_base + 0x10000ULL,
+                                       cpu_irqs);
+
+    for (i = 0; i < 32; i++) {
+        slavio_irq[i] = qdev_get_gpio_in(slavio_intctl, i);
+    }
+    for (i = 0; i < MAX_CPUS; i++) {
+        slavio_cpu_irq[i] = qdev_get_gpio_in(slavio_intctl, 32 + i);
+    }
+
+    if (hwdef->idreg_base) {
+        idreg_init(hwdef->idreg_base);
+    }
+
+    if (hwdef->afx_base) {
+        afx_init(hwdef->afx_base);
+    }
+
+    iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
+                       slavio_irq[30]);
+
+    if (hwdef->iommu_pad_base) {
+        /* On the real hardware (SS-5, LX) the MMU is not padded, but aliased.
+           Software shouldn't use aliased addresses, neither should it crash
+           when does. Using empty_slot instead of aliasing can help with
+           debugging such accesses */
+        empty_slot_init(hwdef->iommu_pad_base,hwdef->iommu_pad_len);
+    }
+
+    espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[18],
+                              iommu, &espdma_irq, 0);
+
+    ledma = sparc32_dma_init(hwdef->dma_base + 16ULL,
+                             slavio_irq[16], iommu, &ledma_irq, 1);
+
+    if (graphic_depth != 8 && graphic_depth != 24) {
+        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
+        exit (1);
+    }
+    num_vsimms = 0;
+    if (num_vsimms == 0) {
+        tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height,
+                 graphic_depth);
+    }
+
+    for (i = num_vsimms; i < MAX_VSIMMS; i++) {
+        /* vsimm registers probed by OBP */
+        if (hwdef->vsimm[i].reg_base) {
+            empty_slot_init(hwdef->vsimm[i].reg_base, 0x2000);
+        }
+    }
+
+    if (hwdef->sx_base) {
+        empty_slot_init(hwdef->sx_base, 0x2000);
+    }
+
+    lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq);
+
+    nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x2000, 8);
+
+    slavio_timer_init_all(hwdef->counter_base, slavio_irq[19], slavio_cpu_irq, smp_cpus);
+
+    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[14],
+                              display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
+    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
+       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
+    escc_init(hwdef->serial_base, slavio_irq[15], slavio_irq[15],
+              serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);
+
+    cpu_halt = qemu_allocate_irqs(cpu_halt_signal, NULL, 1);
+    if (hwdef->apc_base) {
+        apc_init(hwdef->apc_base, cpu_halt[0]);
+    }
+
+    if (hwdef->fd_base) {
+        /* there is zero or one floppy drive */
+        memset(fd, 0, sizeof(fd));
+        fd[0] = drive_get(IF_FLOPPY, 0, 0);
+        sun4m_fdctrl_init(slavio_irq[22], hwdef->fd_base, fd,
+                          &fdc_tc);
+    } else {
+        fdc_tc = *qemu_allocate_irqs(dummy_fdc_tc, NULL, 1);
+    }
+
+    slavio_misc_init(hwdef->slavio_base, hwdef->aux1_base, hwdef->aux2_base,
+                     slavio_irq[30], fdc_tc);
+
+    if (drive_get_max_bus(IF_SCSI) > 0) {
+        fprintf(stderr, "qemu: too many SCSI bus\n");
+        exit(1);
+    }
+
+    esp_init(hwdef->esp_base, 2,
+             espdma_memory_read, espdma_memory_write,
+             espdma, espdma_irq, &esp_reset, &dma_enable);
+
+    qdev_connect_gpio_out(espdma, 0, esp_reset);
+    qdev_connect_gpio_out(espdma, 1, dma_enable);
+
+    if (hwdef->cs_base) {
+        sysbus_create_simple("SUNW,CS4231", hwdef->cs_base,
+                             slavio_irq[5]);
+    }
+
+    if (hwdef->dbri_base) {
+        /* ISDN chip with attached CS4215 audio codec */
+        /* prom space */
+        empty_slot_init(hwdef->dbri_base+0x1000, 0x30);
+        /* reg space */
+        empty_slot_init(hwdef->dbri_base+0x10000, 0x100);
+    }
+
+    if (hwdef->bpp_base) {
+        /* parallel port */
+        empty_slot_init(hwdef->bpp_base, 0x20);
+    }
+
+    kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename,
+                                    RAM_size);
+
+    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
+               boot_device, RAM_size, kernel_size, graphic_width,
+               graphic_height, graphic_depth, hwdef->nvram_machine_id,
+               "Sun4m");
+
+    if (hwdef->ecc_base)
+        ecc_init(hwdef->ecc_base, slavio_irq[28],
+                 hwdef->ecc_version);
+
+    fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+    if (kernel_cmdline) {
+        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
+        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
+        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
+        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
+                       strlen(kernel_cmdline) + 1);
+    } else {
+        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
+        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
+    }
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used
+    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device[0]);
+    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
+}
+
+enum {
+    ss2_id = 0,
+    ss5_id = 32,
+    vger_id,
+    lx_id,
+    ss4_id,
+    scls_id,
+    sbook_id,
+    ss10_id = 64,
+    ss20_id,
+    ss600mp_id,
+    ss1000_id = 96,
+    ss2000_id,
+};
+
+static const struct sun4m_hwdef sun4m_hwdefs[] = {
+    /* SS-5 */
+    {
+        .iommu_base   = 0x10000000,
+        .iommu_pad_base = 0x10004000,
+        .iommu_pad_len  = 0x0fffb000,
+        .tcx_base     = 0x50000000,
+        .cs_base      = 0x6c000000,
+        .slavio_base  = 0x70000000,
+        .ms_kb_base   = 0x71000000,
+        .serial_base  = 0x71100000,
+        .nvram_base   = 0x71200000,
+        .fd_base      = 0x71400000,
+        .counter_base = 0x71d00000,
+        .intctl_base  = 0x71e00000,
+        .idreg_base   = 0x78000000,
+        .dma_base     = 0x78400000,
+        .esp_base     = 0x78800000,
+        .le_base      = 0x78c00000,
+        .apc_base     = 0x6a000000,
+        .afx_base     = 0x6e000000,
+        .aux1_base    = 0x71900000,
+        .aux2_base    = 0x71910000,
+        .nvram_machine_id = 0x80,
+        .machine_id = ss5_id,
+        .iommu_version = 0x05000000,
+        .max_mem = 0x10000000,
+        .default_cpu_model = "Fujitsu MB86904",
+    },
+    /* SS-10 */
+    {
+        .iommu_base   = 0xfe0000000ULL,
+        .tcx_base     = 0xe20000000ULL,
+        .slavio_base  = 0xff0000000ULL,
+        .ms_kb_base   = 0xff1000000ULL,
+        .serial_base  = 0xff1100000ULL,
+        .nvram_base   = 0xff1200000ULL,
+        .fd_base      = 0xff1700000ULL,
+        .counter_base = 0xff1300000ULL,
+        .intctl_base  = 0xff1400000ULL,
+        .idreg_base   = 0xef0000000ULL,
+        .dma_base     = 0xef0400000ULL,
+        .esp_base     = 0xef0800000ULL,
+        .le_base      = 0xef0c00000ULL,
+        .apc_base     = 0xefa000000ULL, // XXX should not exist
+        .aux1_base    = 0xff1800000ULL,
+        .aux2_base    = 0xff1a01000ULL,
+        .ecc_base     = 0xf00000000ULL,
+        .ecc_version  = 0x10000000, // version 0, implementation 1
+        .nvram_machine_id = 0x72,
+        .machine_id = ss10_id,
+        .iommu_version = 0x03000000,
+        .max_mem = 0xf00000000ULL,
+        .default_cpu_model = "TI SuperSparc II",
+    },
+    /* SS-600MP */
+    {
+        .iommu_base   = 0xfe0000000ULL,
+        .tcx_base     = 0xe20000000ULL,
+        .slavio_base  = 0xff0000000ULL,
+        .ms_kb_base   = 0xff1000000ULL,
+        .serial_base  = 0xff1100000ULL,
+        .nvram_base   = 0xff1200000ULL,
+        .counter_base = 0xff1300000ULL,
+        .intctl_base  = 0xff1400000ULL,
+        .dma_base     = 0xef0081000ULL,
+        .esp_base     = 0xef0080000ULL,
+        .le_base      = 0xef0060000ULL,
+        .apc_base     = 0xefa000000ULL, // XXX should not exist
+        .aux1_base    = 0xff1800000ULL,
+        .aux2_base    = 0xff1a01000ULL, // XXX should not exist
+        .ecc_base     = 0xf00000000ULL,
+        .ecc_version  = 0x00000000, // version 0, implementation 0
+        .nvram_machine_id = 0x71,
+        .machine_id = ss600mp_id,
+        .iommu_version = 0x01000000,
+        .max_mem = 0xf00000000ULL,
+        .default_cpu_model = "TI SuperSparc II",
+    },
+    /* SS-20 */
+    {
+        .iommu_base   = 0xfe0000000ULL,
+        .tcx_base     = 0xe20000000ULL,
+        .slavio_base  = 0xff0000000ULL,
+        .ms_kb_base   = 0xff1000000ULL,
+        .serial_base  = 0xff1100000ULL,
+        .nvram_base   = 0xff1200000ULL,
+        .fd_base      = 0xff1700000ULL,
+        .counter_base = 0xff1300000ULL,
+        .intctl_base  = 0xff1400000ULL,
+        .idreg_base   = 0xef0000000ULL,
+        .dma_base     = 0xef0400000ULL,
+        .esp_base     = 0xef0800000ULL,
+        .le_base      = 0xef0c00000ULL,
+        .bpp_base     = 0xef4800000ULL,
+        .apc_base     = 0xefa000000ULL, // XXX should not exist
+        .aux1_base    = 0xff1800000ULL,
+        .aux2_base    = 0xff1a01000ULL,
+        .dbri_base    = 0xee0000000ULL,
+        .sx_base      = 0xf80000000ULL,
+        .vsimm        = {
+            {
+                .reg_base  = 0x9c000000ULL,
+                .vram_base = 0xfc000000ULL
+            }, {
+                .reg_base  = 0x90000000ULL,
+                .vram_base = 0xf0000000ULL
+            }, {
+                .reg_base  = 0x94000000ULL
+            }, {
+                .reg_base  = 0x98000000ULL
+            }
+        },
+        .ecc_base     = 0xf00000000ULL,
+        .ecc_version  = 0x20000000, // version 0, implementation 2
+        .nvram_machine_id = 0x72,
+        .machine_id = ss20_id,
+        .iommu_version = 0x13000000,
+        .max_mem = 0xf00000000ULL,
+        .default_cpu_model = "TI SuperSparc II",
+    },
+    /* Voyager */
+    {
+        .iommu_base   = 0x10000000,
+        .tcx_base     = 0x50000000,
+        .slavio_base  = 0x70000000,
+        .ms_kb_base   = 0x71000000,
+        .serial_base  = 0x71100000,
+        .nvram_base   = 0x71200000,
+        .fd_base      = 0x71400000,
+        .counter_base = 0x71d00000,
+        .intctl_base  = 0x71e00000,
+        .idreg_base   = 0x78000000,
+        .dma_base     = 0x78400000,
+        .esp_base     = 0x78800000,
+        .le_base      = 0x78c00000,
+        .apc_base     = 0x71300000, // pmc
+        .aux1_base    = 0x71900000,
+        .aux2_base    = 0x71910000,
+        .nvram_machine_id = 0x80,
+        .machine_id = vger_id,
+        .iommu_version = 0x05000000,
+        .max_mem = 0x10000000,
+        .default_cpu_model = "Fujitsu MB86904",
+    },
+    /* LX */
+    {
+        .iommu_base   = 0x10000000,
+        .iommu_pad_base = 0x10004000,
+        .iommu_pad_len  = 0x0fffb000,
+        .tcx_base     = 0x50000000,
+        .slavio_base  = 0x70000000,
+        .ms_kb_base   = 0x71000000,
+        .serial_base  = 0x71100000,
+        .nvram_base   = 0x71200000,
+        .fd_base      = 0x71400000,
+        .counter_base = 0x71d00000,
+        .intctl_base  = 0x71e00000,
+        .idreg_base   = 0x78000000,
+        .dma_base     = 0x78400000,
+        .esp_base     = 0x78800000,
+        .le_base      = 0x78c00000,
+        .aux1_base    = 0x71900000,
+        .aux2_base    = 0x71910000,
+        .nvram_machine_id = 0x80,
+        .machine_id = lx_id,
+        .iommu_version = 0x04000000,
+        .max_mem = 0x10000000,
+        .default_cpu_model = "TI MicroSparc I",
+    },
+    /* SS-4 */
+    {
+        .iommu_base   = 0x10000000,
+        .tcx_base     = 0x50000000,
+        .cs_base      = 0x6c000000,
+        .slavio_base  = 0x70000000,
+        .ms_kb_base   = 0x71000000,
+        .serial_base  = 0x71100000,
+        .nvram_base   = 0x71200000,
+        .fd_base      = 0x71400000,
+        .counter_base = 0x71d00000,
+        .intctl_base  = 0x71e00000,
+        .idreg_base   = 0x78000000,
+        .dma_base     = 0x78400000,
+        .esp_base     = 0x78800000,
+        .le_base      = 0x78c00000,
+        .apc_base     = 0x6a000000,
+        .aux1_base    = 0x71900000,
+        .aux2_base    = 0x71910000,
+        .nvram_machine_id = 0x80,
+        .machine_id = ss4_id,
+        .iommu_version = 0x05000000,
+        .max_mem = 0x10000000,
+        .default_cpu_model = "Fujitsu MB86904",
+    },
+    /* SPARCClassic */
+    {
+        .iommu_base   = 0x10000000,
+        .tcx_base     = 0x50000000,
+        .slavio_base  = 0x70000000,
+        .ms_kb_base   = 0x71000000,
+        .serial_base  = 0x71100000,
+        .nvram_base   = 0x71200000,
+        .fd_base      = 0x71400000,
+        .counter_base = 0x71d00000,
+        .intctl_base  = 0x71e00000,
+        .idreg_base   = 0x78000000,
+        .dma_base     = 0x78400000,
+        .esp_base     = 0x78800000,
+        .le_base      = 0x78c00000,
+        .apc_base     = 0x6a000000,
+        .aux1_base    = 0x71900000,
+        .aux2_base    = 0x71910000,
+        .nvram_machine_id = 0x80,
+        .machine_id = scls_id,
+        .iommu_version = 0x05000000,
+        .max_mem = 0x10000000,
+        .default_cpu_model = "TI MicroSparc I",
+    },
+    /* SPARCbook */
+    {
+        .iommu_base   = 0x10000000,
+        .tcx_base     = 0x50000000, // XXX
+        .slavio_base  = 0x70000000,
+        .ms_kb_base   = 0x71000000,
+        .serial_base  = 0x71100000,
+        .nvram_base   = 0x71200000,
+        .fd_base      = 0x71400000,
+        .counter_base = 0x71d00000,
+        .intctl_base  = 0x71e00000,
+        .idreg_base   = 0x78000000,
+        .dma_base     = 0x78400000,
+        .esp_base     = 0x78800000,
+        .le_base      = 0x78c00000,
+        .apc_base     = 0x6a000000,
+        .aux1_base    = 0x71900000,
+        .aux2_base    = 0x71910000,
+        .nvram_machine_id = 0x80,
+        .machine_id = sbook_id,
+        .iommu_version = 0x05000000,
+        .max_mem = 0x10000000,
+        .default_cpu_model = "TI MicroSparc I",
+    },
+};
+
+/* SPARCstation 5 hardware initialisation */
+static void ss5_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[0], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCstation 10 hardware initialisation */
+static void ss10_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[1], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCserver 600MP hardware initialisation */
+static void ss600mp_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[2], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCstation 20 hardware initialisation */
+static void ss20_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[3], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCstation Voyager hardware initialisation */
+static void vger_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[4], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCstation LX hardware initialisation */
+static void ss_lx_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[5], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCstation 4 hardware initialisation */
+static void ss4_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[6], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCClassic hardware initialisation */
+static void scls_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[7], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCbook hardware initialisation */
+static void sbook_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4m_hw_init(&sun4m_hwdefs[8], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+static QEMUMachine ss5_machine = {
+    .name = "SS-5",
+    .desc = "Sun4m platform, SPARCstation 5",
+    .init = ss5_init,
+    .block_default_type = IF_SCSI,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine ss10_machine = {
+    .name = "SS-10",
+    .desc = "Sun4m platform, SPARCstation 10",
+    .init = ss10_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine ss600mp_machine = {
+    .name = "SS-600MP",
+    .desc = "Sun4m platform, SPARCserver 600MP",
+    .init = ss600mp_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine ss20_machine = {
+    .name = "SS-20",
+    .desc = "Sun4m platform, SPARCstation 20",
+    .init = ss20_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine voyager_machine = {
+    .name = "Voyager",
+    .desc = "Sun4m platform, SPARCstation Voyager",
+    .init = vger_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine ss_lx_machine = {
+    .name = "LX",
+    .desc = "Sun4m platform, SPARCstation LX",
+    .init = ss_lx_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine ss4_machine = {
+    .name = "SS-4",
+    .desc = "Sun4m platform, SPARCstation 4",
+    .init = ss4_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine scls_machine = {
+    .name = "SPARCClassic",
+    .desc = "Sun4m platform, SPARCClassic",
+    .init = scls_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine sbook_machine = {
+    .name = "SPARCbook",
+    .desc = "Sun4m platform, SPARCbook",
+    .init = sbook_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static const struct sun4d_hwdef sun4d_hwdefs[] = {
+    /* SS-1000 */
+    {
+        .iounit_bases   = {
+            0xfe0200000ULL,
+            0xfe1200000ULL,
+            0xfe2200000ULL,
+            0xfe3200000ULL,
+            -1,
+        },
+        .tcx_base     = 0x820000000ULL,
+        .slavio_base  = 0xf00000000ULL,
+        .ms_kb_base   = 0xf00240000ULL,
+        .serial_base  = 0xf00200000ULL,
+        .nvram_base   = 0xf00280000ULL,
+        .counter_base = 0xf00300000ULL,
+        .espdma_base  = 0x800081000ULL,
+        .esp_base     = 0x800080000ULL,
+        .ledma_base   = 0x800040000ULL,
+        .le_base      = 0x800060000ULL,
+        .sbi_base     = 0xf02800000ULL,
+        .nvram_machine_id = 0x80,
+        .machine_id = ss1000_id,
+        .iounit_version = 0x03000000,
+        .max_mem = 0xf00000000ULL,
+        .default_cpu_model = "TI SuperSparc II",
+    },
+    /* SS-2000 */
+    {
+        .iounit_bases   = {
+            0xfe0200000ULL,
+            0xfe1200000ULL,
+            0xfe2200000ULL,
+            0xfe3200000ULL,
+            0xfe4200000ULL,
+        },
+        .tcx_base     = 0x820000000ULL,
+        .slavio_base  = 0xf00000000ULL,
+        .ms_kb_base   = 0xf00240000ULL,
+        .serial_base  = 0xf00200000ULL,
+        .nvram_base   = 0xf00280000ULL,
+        .counter_base = 0xf00300000ULL,
+        .espdma_base  = 0x800081000ULL,
+        .esp_base     = 0x800080000ULL,
+        .ledma_base   = 0x800040000ULL,
+        .le_base      = 0x800060000ULL,
+        .sbi_base     = 0xf02800000ULL,
+        .nvram_machine_id = 0x80,
+        .machine_id = ss2000_id,
+        .iounit_version = 0x03000000,
+        .max_mem = 0xf00000000ULL,
+        .default_cpu_model = "TI SuperSparc II",
+    },
+};
+
+static DeviceState *sbi_init(hwaddr addr, qemu_irq **parent_irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    unsigned int i;
+
+    dev = qdev_create(NULL, "sbi");
+    qdev_init_nofail(dev);
+
+    s = SYS_BUS_DEVICE(dev);
+
+    for (i = 0; i < MAX_CPUS; i++) {
+        sysbus_connect_irq(s, i, *parent_irq[i]);
+    }
+
+    sysbus_mmio_map(s, 0, addr);
+
+    return dev;
+}
+
+static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, 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)
+{
+    unsigned int i;
+    void *iounits[MAX_IOUNITS], *espdma, *ledma, *nvram;
+    qemu_irq *cpu_irqs[MAX_CPUS], sbi_irq[32], sbi_cpu_irq[MAX_CPUS],
+        espdma_irq, ledma_irq;
+    qemu_irq esp_reset, dma_enable;
+    unsigned long kernel_size;
+    void *fw_cfg;
+    DeviceState *dev;
+
+    /* init CPUs */
+    if (!cpu_model)
+        cpu_model = hwdef->default_cpu_model;
+
+    for(i = 0; i < smp_cpus; i++) {
+        cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]);
+    }
+
+    for (i = smp_cpus; i < MAX_CPUS; i++)
+        cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS);
+
+    /* set up devices */
+    ram_init(0, RAM_size, hwdef->max_mem);
+
+    prom_init(hwdef->slavio_base, bios_name);
+
+    dev = sbi_init(hwdef->sbi_base, cpu_irqs);
+
+    for (i = 0; i < 32; i++) {
+        sbi_irq[i] = qdev_get_gpio_in(dev, i);
+    }
+    for (i = 0; i < MAX_CPUS; i++) {
+        sbi_cpu_irq[i] = qdev_get_gpio_in(dev, 32 + i);
+    }
+
+    for (i = 0; i < MAX_IOUNITS; i++)
+        if (hwdef->iounit_bases[i] != (hwaddr)-1)
+            iounits[i] = iommu_init(hwdef->iounit_bases[i],
+                                    hwdef->iounit_version,
+                                    sbi_irq[0]);
+
+    espdma = sparc32_dma_init(hwdef->espdma_base, sbi_irq[3],
+                              iounits[0], &espdma_irq, 0);
+
+    /* should be lebuffer instead */
+    ledma = sparc32_dma_init(hwdef->ledma_base, sbi_irq[4],
+                             iounits[0], &ledma_irq, 0);
+
+    if (graphic_depth != 8 && graphic_depth != 24) {
+        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
+        exit (1);
+    }
+    tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height,
+             graphic_depth);
+
+    lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq);
+
+    nvram = m48t59_init(sbi_irq[0], hwdef->nvram_base, 0, 0x2000, 8);
+
+    slavio_timer_init_all(hwdef->counter_base, sbi_irq[10], sbi_cpu_irq, smp_cpus);
+
+    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, sbi_irq[12],
+                              display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
+    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
+       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
+    escc_init(hwdef->serial_base, sbi_irq[12], sbi_irq[12],
+              serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);
+
+    if (drive_get_max_bus(IF_SCSI) > 0) {
+        fprintf(stderr, "qemu: too many SCSI bus\n");
+        exit(1);
+    }
+
+    esp_init(hwdef->esp_base, 2,
+             espdma_memory_read, espdma_memory_write,
+             espdma, espdma_irq, &esp_reset, &dma_enable);
+
+    qdev_connect_gpio_out(espdma, 0, esp_reset);
+    qdev_connect_gpio_out(espdma, 1, dma_enable);
+
+    kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename,
+                                    RAM_size);
+
+    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
+               boot_device, RAM_size, kernel_size, graphic_width,
+               graphic_height, graphic_depth, hwdef->nvram_machine_id,
+               "Sun4d");
+
+    fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+    if (kernel_cmdline) {
+        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
+        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
+        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
+    } else {
+        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
+    }
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used
+    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device[0]);
+    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
+}
+
+/* SPARCserver 1000 hardware initialisation */
+static void ss1000_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4d_hw_init(&sun4d_hwdefs[0], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+/* SPARCcenter 2000 hardware initialisation */
+static void ss2000_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4d_hw_init(&sun4d_hwdefs[1], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+static QEMUMachine ss1000_machine = {
+    .name = "SS-1000",
+    .desc = "Sun4d platform, SPARCserver 1000",
+    .init = ss1000_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 8,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine ss2000_machine = {
+    .name = "SS-2000",
+    .desc = "Sun4d platform, SPARCcenter 2000",
+    .init = ss2000_init,
+    .block_default_type = IF_SCSI,
+    .max_cpus = 20,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static const struct sun4c_hwdef sun4c_hwdefs[] = {
+    /* SS-2 */
+    {
+        .iommu_base   = 0xf8000000,
+        .tcx_base     = 0xfe000000,
+        .slavio_base  = 0xf6000000,
+        .intctl_base  = 0xf5000000,
+        .counter_base = 0xf3000000,
+        .ms_kb_base   = 0xf0000000,
+        .serial_base  = 0xf1000000,
+        .nvram_base   = 0xf2000000,
+        .fd_base      = 0xf7200000,
+        .dma_base     = 0xf8400000,
+        .esp_base     = 0xf8800000,
+        .le_base      = 0xf8c00000,
+        .aux1_base    = 0xf7400003,
+        .nvram_machine_id = 0x55,
+        .machine_id = ss2_id,
+        .max_mem = 0x10000000,
+        .default_cpu_model = "Cypress CY7C601",
+    },
+};
+
+static DeviceState *sun4c_intctl_init(hwaddr addr,
+                                      qemu_irq *parent_irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    unsigned int i;
+
+    dev = qdev_create(NULL, "sun4c_intctl");
+    qdev_init_nofail(dev);
+
+    s = SYS_BUS_DEVICE(dev);
+
+    for (i = 0; i < MAX_PILS; i++) {
+        sysbus_connect_irq(s, i, parent_irq[i]);
+    }
+    sysbus_mmio_map(s, 0, addr);
+
+    return dev;
+}
+
+static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, 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)
+{
+    void *iommu, *espdma, *ledma, *nvram;
+    qemu_irq *cpu_irqs, slavio_irq[8], espdma_irq, ledma_irq;
+    qemu_irq esp_reset, dma_enable;
+    qemu_irq fdc_tc;
+    unsigned long kernel_size;
+    DriveInfo *fd[MAX_FD];
+    void *fw_cfg;
+    DeviceState *dev;
+    unsigned int i;
+
+    /* init CPU */
+    if (!cpu_model)
+        cpu_model = hwdef->default_cpu_model;
+
+    cpu_devinit(cpu_model, 0, hwdef->slavio_base, &cpu_irqs);
+
+    /* set up devices */
+    ram_init(0, RAM_size, hwdef->max_mem);
+
+    prom_init(hwdef->slavio_base, bios_name);
+
+    dev = sun4c_intctl_init(hwdef->intctl_base, cpu_irqs);
+
+    for (i = 0; i < 8; i++) {
+        slavio_irq[i] = qdev_get_gpio_in(dev, i);
+    }
+
+    iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
+                       slavio_irq[1]);
+
+    espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[2],
+                              iommu, &espdma_irq, 0);
+
+    ledma = sparc32_dma_init(hwdef->dma_base + 16ULL,
+                             slavio_irq[3], iommu, &ledma_irq, 1);
+
+    if (graphic_depth != 8 && graphic_depth != 24) {
+        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
+        exit (1);
+    }
+    tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height,
+             graphic_depth);
+
+    lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq);
+
+    nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x800, 2);
+
+    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[1],
+                              display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
+    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
+       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
+    escc_init(hwdef->serial_base, slavio_irq[1],
+              slavio_irq[1], serial_hds[0], serial_hds[1],
+              ESCC_CLOCK, 1);
+
+    if (hwdef->fd_base != (hwaddr)-1) {
+        /* there is zero or one floppy drive */
+        memset(fd, 0, sizeof(fd));
+        fd[0] = drive_get(IF_FLOPPY, 0, 0);
+        sun4m_fdctrl_init(slavio_irq[1], hwdef->fd_base, fd,
+                          &fdc_tc);
+    } else {
+        fdc_tc = *qemu_allocate_irqs(dummy_fdc_tc, NULL, 1);
+    }
+
+    slavio_misc_init(0, hwdef->aux1_base, 0, slavio_irq[1], fdc_tc);
+
+    if (drive_get_max_bus(IF_SCSI) > 0) {
+        fprintf(stderr, "qemu: too many SCSI bus\n");
+        exit(1);
+    }
+
+    esp_init(hwdef->esp_base, 2,
+             espdma_memory_read, espdma_memory_write,
+             espdma, espdma_irq, &esp_reset, &dma_enable);
+
+    qdev_connect_gpio_out(espdma, 0, esp_reset);
+    qdev_connect_gpio_out(espdma, 1, dma_enable);
+
+    kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename,
+                                    RAM_size);
+
+    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
+               boot_device, RAM_size, kernel_size, graphic_width,
+               graphic_height, graphic_depth, hwdef->nvram_machine_id,
+               "Sun4c");
+
+    fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+    if (kernel_cmdline) {
+        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
+        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
+        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
+    } else {
+        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
+    }
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used
+    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device[0]);
+    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
+}
+
+/* SPARCstation 2 hardware initialisation */
+static void ss2_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_device = args->boot_device;
+    sun4c_hw_init(&sun4c_hwdefs[0], RAM_size, boot_device, kernel_filename,
+                  kernel_cmdline, initrd_filename, cpu_model);
+}
+
+static QEMUMachine ss2_machine = {
+    .name = "SS-2",
+    .desc = "Sun4c platform, SPARCstation 2",
+    .init = ss2_init,
+    .block_default_type = IF_SCSI,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void sun4m_register_types(void)
+{
+    type_register_static(&idreg_info);
+    type_register_static(&afx_info);
+    type_register_static(&prom_info);
+    type_register_static(&ram_info);
+}
+
+static void ss2_machine_init(void)
+{
+    qemu_register_machine(&ss5_machine);
+    qemu_register_machine(&ss10_machine);
+    qemu_register_machine(&ss600mp_machine);
+    qemu_register_machine(&ss20_machine);
+    qemu_register_machine(&voyager_machine);
+    qemu_register_machine(&ss_lx_machine);
+    qemu_register_machine(&ss4_machine);
+    qemu_register_machine(&scls_machine);
+    qemu_register_machine(&sbook_machine);
+    qemu_register_machine(&ss1000_machine);
+    qemu_register_machine(&ss2000_machine);
+    qemu_register_machine(&ss2_machine);
+}
+
+type_init(sun4m_register_types)
+machine_init(ss2_machine_init);
diff --git a/hw/sparc64/Makefile.objs b/hw/sparc64/Makefile.objs
index 8c65fc4..4df0d90 100644
--- a/hw/sparc64/Makefile.objs
+++ b/hw/sparc64/Makefile.objs
@@ -1,4 +1,6 @@
-obj-y = sun4u.o apb_pci.o
+obj-y = apb_pci.o
 obj-y += mc146818rtc.o
 
 obj-y := $(addprefix ../,$(obj-y))
+
+obj-y += sun4u.o
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
new file mode 100644
index 0000000..51ffa1c
--- /dev/null
+++ b/hw/sparc64/sun4u.c
@@ -0,0 +1,1014 @@
+/*
+ * QEMU Sun4u/Sun4v System Emulator
+ *
+ * Copyright (c) 2005 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 "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/apb_pci.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/nvram.h"
+#include "hw/fdc.h"
+#include "net/net.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/firmware_abi.h"
+#include "hw/fw_cfg.h"
+#include "hw/sysbus.h"
+#include "hw/ide.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+
+//#define DEBUG_IRQ
+//#define DEBUG_EBUS
+//#define DEBUG_TIMER
+
+#ifdef DEBUG_IRQ
+#define CPUIRQ_DPRINTF(fmt, ...)                                \
+    do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define CPUIRQ_DPRINTF(fmt, ...)
+#endif
+
+#ifdef DEBUG_EBUS
+#define EBUS_DPRINTF(fmt, ...)                                  \
+    do { printf("EBUS: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define EBUS_DPRINTF(fmt, ...)
+#endif
+
+#ifdef DEBUG_TIMER
+#define TIMER_DPRINTF(fmt, ...)                                  \
+    do { printf("TIMER: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define TIMER_DPRINTF(fmt, ...)
+#endif
+
+#define KERNEL_LOAD_ADDR     0x00404000
+#define CMDLINE_ADDR         0x003ff000
+#define PROM_SIZE_MAX        (4 * 1024 * 1024)
+#define PROM_VADDR           0x000ffd00000ULL
+#define APB_SPECIAL_BASE     0x1fe00000000ULL
+#define APB_MEM_BASE         0x1ff00000000ULL
+#define APB_PCI_IO_BASE      (APB_SPECIAL_BASE + 0x02000000ULL)
+#define PROM_FILENAME        "openbios-sparc64"
+#define NVRAM_SIZE           0x2000
+#define MAX_IDE_BUS          2
+#define BIOS_CFG_IOPORT      0x510
+#define FW_CFG_SPARC64_WIDTH (FW_CFG_ARCH_LOCAL + 0x00)
+#define FW_CFG_SPARC64_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
+#define FW_CFG_SPARC64_DEPTH (FW_CFG_ARCH_LOCAL + 0x02)
+
+#define IVEC_MAX             0x30
+
+#define TICK_MAX             0x7fffffffffffffffULL
+
+struct hwdef {
+    const char * const default_cpu_model;
+    uint16_t machine_id;
+    uint64_t prom_addr;
+    uint64_t console_serial_base;
+};
+
+typedef struct EbusState {
+    PCIDevice pci_dev;
+    MemoryRegion bar0;
+    MemoryRegion bar1;
+} EbusState;
+
+int DMA_get_channel_mode (int nchan)
+{
+    return 0;
+}
+int DMA_read_memory (int nchan, void *buf, int pos, int size)
+{
+    return 0;
+}
+int DMA_write_memory (int nchan, void *buf, int pos, int size)
+{
+    return 0;
+}
+void DMA_hold_DREQ (int nchan) {}
+void DMA_release_DREQ (int nchan) {}
+void DMA_schedule(int nchan) {}
+
+void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
+{
+}
+
+void DMA_register_channel (int nchan,
+                           DMA_transfer_handler transfer_handler,
+                           void *opaque)
+{
+}
+
+static int fw_cfg_boot_set(void *opaque, const char *boot_device)
+{
+    fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
+    return 0;
+}
+
+static int sun4u_NVRAM_set_params(M48t59State *nvram, uint16_t NVRAM_size,
+                                  const char *arch, ram_addr_t RAM_size,
+                                  const char *boot_devices,
+                                  uint32_t kernel_image, uint32_t kernel_size,
+                                  const char *cmdline,
+                                  uint32_t initrd_image, uint32_t initrd_size,
+                                  uint32_t NVRAM_image,
+                                  int width, int height, int depth,
+                                  const uint8_t *macaddr)
+{
+    unsigned int i;
+    uint32_t start, end;
+    uint8_t image[0x1ff0];
+    struct OpenBIOS_nvpart_v1 *part_header;
+
+    memset(image, '\0', sizeof(image));
+
+    start = 0;
+
+    // OpenBIOS nvram variables
+    // Variable partition
+    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
+    part_header->signature = OPENBIOS_PART_SYSTEM;
+    pstrcpy(part_header->name, sizeof(part_header->name), "system");
+
+    end = start + sizeof(struct OpenBIOS_nvpart_v1);
+    for (i = 0; i < nb_prom_envs; i++)
+        end = OpenBIOS_set_var(image, end, prom_envs[i]);
+
+    // End marker
+    image[end++] = '\0';
+
+    end = start + ((end - start + 15) & ~15);
+    OpenBIOS_finish_partition(part_header, end - start);
+
+    // free partition
+    start = end;
+    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
+    part_header->signature = OPENBIOS_PART_FREE;
+    pstrcpy(part_header->name, sizeof(part_header->name), "free");
+
+    end = 0x1fd0;
+    OpenBIOS_finish_partition(part_header, end - start);
+
+    Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr, 0x80);
+
+    for (i = 0; i < sizeof(image); i++)
+        m48t59_write(nvram, i, image[i]);
+
+    return 0;
+}
+
+static uint64_t sun4u_load_kernel(const char *kernel_filename,
+                                  const char *initrd_filename,
+                                  ram_addr_t RAM_size, uint64_t *initrd_size,
+                                  uint64_t *initrd_addr, uint64_t *kernel_addr,
+                                  uint64_t *kernel_entry)
+{
+    int linux_boot;
+    unsigned int i;
+    long kernel_size;
+    uint8_t *ptr;
+    uint64_t kernel_top;
+
+    linux_boot = (kernel_filename != NULL);
+
+    kernel_size = 0;
+    if (linux_boot) {
+        int bswap_needed;
+
+#ifdef BSWAP_NEEDED
+        bswap_needed = 1;
+#else
+        bswap_needed = 0;
+#endif
+        kernel_size = load_elf(kernel_filename, NULL, NULL, kernel_entry,
+                               kernel_addr, &kernel_top, 1, ELF_MACHINE, 0);
+        if (kernel_size < 0) {
+            *kernel_addr = KERNEL_LOAD_ADDR;
+            *kernel_entry = KERNEL_LOAD_ADDR;
+            kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
+                                    RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
+                                    TARGET_PAGE_SIZE);
+        }
+        if (kernel_size < 0) {
+            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",
+                    kernel_filename);
+            exit(1);
+        }
+        /* load initrd above kernel */
+        *initrd_size = 0;
+        if (initrd_filename) {
+            *initrd_addr = TARGET_PAGE_ALIGN(kernel_top);
+
+            *initrd_size = load_image_targphys(initrd_filename,
+                                               *initrd_addr,
+                                               RAM_size - *initrd_addr);
+            if ((int)*initrd_size < 0) {
+                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                        initrd_filename);
+                exit(1);
+            }
+        }
+        if (*initrd_size > 0) {
+            for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
+                ptr = rom_ptr(*kernel_addr + i);
+                if (ldl_p(ptr + 8) == 0x48647253) { /* HdrS */
+                    stl_p(ptr + 24, *initrd_addr + *kernel_addr);
+                    stl_p(ptr + 28, *initrd_size);
+                    break;
+                }
+            }
+        }
+    }
+    return kernel_size;
+}
+
+void cpu_check_irqs(CPUSPARCState *env)
+{
+    uint32_t pil = env->pil_in |
+                  (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));
+
+    /* TT_IVEC has a higher priority (16) than TT_EXTINT (31..17) */
+    if (env->ivec_status & 0x20) {
+        return;
+    }
+    /* check if TM or SM in SOFTINT are set
+       setting these also causes interrupt 14 */
+    if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) {
+        pil |= 1 << 14;
+    }
+
+    /* The bit corresponding to psrpil is (1<< psrpil), the next bit
+       is (2 << psrpil). */
+    if (pil < (2 << env->psrpil)){
+        if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+            CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n",
+                           env->interrupt_index);
+            env->interrupt_index = 0;
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        }
+        return;
+    }
+
+    if (cpu_interrupts_enabled(env)) {
+
+        unsigned int i;
+
+        for (i = 15; i > env->psrpil; i--) {
+            if (pil & (1 << i)) {
+                int old_interrupt = env->interrupt_index;
+                int new_interrupt = TT_EXTINT | i;
+
+                if (unlikely(env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt
+                  && ((cpu_tsptr(env)->tt & 0x1f0) == TT_EXTINT))) {
+                    CPUIRQ_DPRINTF("Not setting CPU IRQ: TL=%d "
+                                   "current %x >= pending %x\n",
+                                   env->tl, cpu_tsptr(env)->tt, new_interrupt);
+                } else if (old_interrupt != new_interrupt) {
+                    env->interrupt_index = new_interrupt;
+                    CPUIRQ_DPRINTF("Set CPU IRQ %d old=%x new=%x\n", i,
+                                   old_interrupt, new_interrupt);
+                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+                }
+                break;
+            }
+        }
+    } else if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+        CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x "
+                       "current interrupt %x\n",
+                       pil, env->pil_in, env->softint, env->interrupt_index);
+        env->interrupt_index = 0;
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+static void cpu_kick_irq(SPARCCPU *cpu)
+{
+    CPUSPARCState *env = &cpu->env;
+
+    env->halted = 0;
+    cpu_check_irqs(env);
+    qemu_cpu_kick(CPU(cpu));
+}
+
+static void cpu_set_ivec_irq(void *opaque, int irq, int level)
+{
+    SPARCCPU *cpu = opaque;
+    CPUSPARCState *env = &cpu->env;
+
+    if (level) {
+        if (!(env->ivec_status & 0x20)) {
+            CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
+            env->halted = 0;
+            env->interrupt_index = TT_IVEC;
+            env->ivec_status |= 0x20;
+            env->ivec_data[0] = (0x1f << 6) | irq;
+            env->ivec_data[1] = 0;
+            env->ivec_data[2] = 0;
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+        }
+    } else {
+        if (env->ivec_status & 0x20) {
+            CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq);
+            env->ivec_status &= ~0x20;
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        }
+    }
+}
+
+typedef struct ResetData {
+    SPARCCPU *cpu;
+    uint64_t prom_addr;
+} ResetData;
+
+void cpu_put_timer(QEMUFile *f, CPUTimer *s)
+{
+    qemu_put_be32s(f, &s->frequency);
+    qemu_put_be32s(f, &s->disabled);
+    qemu_put_be64s(f, &s->disabled_mask);
+    qemu_put_sbe64s(f, &s->clock_offset);
+
+    qemu_put_timer(f, s->qtimer);
+}
+
+void cpu_get_timer(QEMUFile *f, CPUTimer *s)
+{
+    qemu_get_be32s(f, &s->frequency);
+    qemu_get_be32s(f, &s->disabled);
+    qemu_get_be64s(f, &s->disabled_mask);
+    qemu_get_sbe64s(f, &s->clock_offset);
+
+    qemu_get_timer(f, s->qtimer);
+}
+
+static CPUTimer *cpu_timer_create(const char *name, SPARCCPU *cpu,
+                                  QEMUBHFunc *cb, uint32_t frequency,
+                                  uint64_t disabled_mask)
+{
+    CPUTimer *timer = g_malloc0(sizeof (CPUTimer));
+
+    timer->name = name;
+    timer->frequency = frequency;
+    timer->disabled_mask = disabled_mask;
+
+    timer->disabled = 1;
+    timer->clock_offset = qemu_get_clock_ns(vm_clock);
+
+    timer->qtimer = qemu_new_timer_ns(vm_clock, cb, cpu);
+
+    return timer;
+}
+
+static void cpu_timer_reset(CPUTimer *timer)
+{
+    timer->disabled = 1;
+    timer->clock_offset = qemu_get_clock_ns(vm_clock);
+
+    qemu_del_timer(timer->qtimer);
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    ResetData *s = (ResetData *)opaque;
+    CPUSPARCState *env = &s->cpu->env;
+    static unsigned int nr_resets;
+
+    cpu_reset(CPU(s->cpu));
+
+    cpu_timer_reset(env->tick);
+    cpu_timer_reset(env->stick);
+    cpu_timer_reset(env->hstick);
+
+    env->gregs[1] = 0; // Memory start
+    env->gregs[2] = ram_size; // Memory size
+    env->gregs[3] = 0; // Machine description XXX
+    if (nr_resets++ == 0) {
+        /* Power on reset */
+        env->pc = s->prom_addr + 0x20ULL;
+    } else {
+        env->pc = s->prom_addr + 0x40ULL;
+    }
+    env->npc = env->pc + 4;
+}
+
+static void tick_irq(void *opaque)
+{
+    SPARCCPU *cpu = opaque;
+    CPUSPARCState *env = &cpu->env;
+
+    CPUTimer* timer = env->tick;
+
+    if (timer->disabled) {
+        CPUIRQ_DPRINTF("tick_irq: softint disabled\n");
+        return;
+    } else {
+        CPUIRQ_DPRINTF("tick: fire\n");
+    }
+
+    env->softint |= SOFTINT_TIMER;
+    cpu_kick_irq(cpu);
+}
+
+static void stick_irq(void *opaque)
+{
+    SPARCCPU *cpu = opaque;
+    CPUSPARCState *env = &cpu->env;
+
+    CPUTimer* timer = env->stick;
+
+    if (timer->disabled) {
+        CPUIRQ_DPRINTF("stick_irq: softint disabled\n");
+        return;
+    } else {
+        CPUIRQ_DPRINTF("stick: fire\n");
+    }
+
+    env->softint |= SOFTINT_STIMER;
+    cpu_kick_irq(cpu);
+}
+
+static void hstick_irq(void *opaque)
+{
+    SPARCCPU *cpu = opaque;
+    CPUSPARCState *env = &cpu->env;
+
+    CPUTimer* timer = env->hstick;
+
+    if (timer->disabled) {
+        CPUIRQ_DPRINTF("hstick_irq: softint disabled\n");
+        return;
+    } else {
+        CPUIRQ_DPRINTF("hstick: fire\n");
+    }
+
+    env->softint |= SOFTINT_STIMER;
+    cpu_kick_irq(cpu);
+}
+
+static int64_t cpu_to_timer_ticks(int64_t cpu_ticks, uint32_t frequency)
+{
+    return muldiv64(cpu_ticks, get_ticks_per_sec(), frequency);
+}
+
+static uint64_t timer_to_cpu_ticks(int64_t timer_ticks, uint32_t frequency)
+{
+    return muldiv64(timer_ticks, frequency, get_ticks_per_sec());
+}
+
+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_ns(vm_clock) -
+                    cpu_to_timer_ticks(real_count, timer->frequency);
+
+    TIMER_DPRINTF("%s set_count count=0x%016lx (%s) p=%p\n",
+                  timer->name, real_count,
+                  timer->disabled?"disabled":"enabled", timer);
+
+    timer->disabled = disabled_bit ? 1 : 0;
+    timer->clock_offset = vm_clock_offset;
+}
+
+uint64_t cpu_tick_get_count(CPUTimer *timer)
+{
+    uint64_t real_count = timer_to_cpu_ticks(
+                    qemu_get_clock_ns(vm_clock) - timer->clock_offset,
+                    timer->frequency);
+
+    TIMER_DPRINTF("%s get_count count=0x%016lx (%s) p=%p\n",
+           timer->name, real_count,
+           timer->disabled?"disabled":"enabled", timer);
+
+    if (timer->disabled)
+        real_count |= timer->disabled_mask;
+
+    return real_count;
+}
+
+void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit)
+{
+    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;
+
+    int64_t expires = cpu_to_timer_ticks(real_limit, timer->frequency) +
+                    timer->clock_offset;
+
+    if (expires < now) {
+        expires = now + 1;
+    }
+
+    TIMER_DPRINTF("%s set_limit limit=0x%016lx (%s) p=%p "
+                  "called with limit=0x%016lx at 0x%016lx (delta=0x%016lx)\n",
+                  timer->name, real_limit,
+                  timer->disabled?"disabled":"enabled",
+                  timer, limit,
+                  timer_to_cpu_ticks(now - timer->clock_offset,
+                                     timer->frequency),
+                  timer_to_cpu_ticks(expires - now, timer->frequency));
+
+    if (!real_limit) {
+        TIMER_DPRINTF("%s set_limit limit=ZERO - not starting timer\n",
+                timer->name);
+        qemu_del_timer(timer->qtimer);
+    } else if (timer->disabled) {
+        qemu_del_timer(timer->qtimer);
+    } else {
+        qemu_mod_timer(timer->qtimer, expires);
+    }
+}
+
+static void isa_irq_handler(void *opaque, int n, int level)
+{
+    static const int isa_irq_to_ivec[16] = {
+        [1] = 0x29, /* keyboard */
+        [4] = 0x2b, /* serial */
+        [6] = 0x27, /* floppy */
+        [7] = 0x22, /* parallel */
+        [12] = 0x2a, /* mouse */
+    };
+    qemu_irq *irqs = opaque;
+    int ivec;
+
+    assert(n < 16);
+    ivec = isa_irq_to_ivec[n];
+    EBUS_DPRINTF("Set ISA IRQ %d level %d -> ivec 0x%x\n", n, level, ivec);
+    if (ivec) {
+        qemu_set_irq(irqs[ivec], level);
+    }
+}
+
+/* EBUS (Eight bit bus) bridge */
+static ISABus *
+pci_ebus_init(PCIBus *bus, int devfn, qemu_irq *irqs)
+{
+    qemu_irq *isa_irq;
+    PCIDevice *pci_dev;
+    ISABus *isa_bus;
+
+    pci_dev = pci_create_simple(bus, devfn, "ebus");
+    isa_bus = DO_UPCAST(ISABus, qbus,
+                        qdev_get_child_bus(&pci_dev->qdev, "isa.0"));
+    isa_irq = qemu_allocate_irqs(isa_irq_handler, irqs, 16);
+    isa_bus_irqs(isa_bus, isa_irq);
+    return isa_bus;
+}
+
+static int
+pci_ebus_init1(PCIDevice *pci_dev)
+{
+    EbusState *s = DO_UPCAST(EbusState, pci_dev, pci_dev);
+
+    isa_bus_new(&pci_dev->qdev, pci_address_space_io(pci_dev));
+
+    pci_dev->config[0x04] = 0x06; // command = bus master, pci mem
+    pci_dev->config[0x05] = 0x00;
+    pci_dev->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
+    pci_dev->config[0x07] = 0x03; // status = medium devsel
+    pci_dev->config[0x09] = 0x00; // programming i/f
+    pci_dev->config[0x0D] = 0x0a; // latency_timer
+
+    isa_mmio_setup(&s->bar0, 0x1000000);
+    pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0);
+    isa_mmio_setup(&s->bar1, 0x800000);
+    pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar1);
+    return 0;
+}
+
+static void ebus_class_init(ObjectClass *klass, void *data)
+{
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = pci_ebus_init1;
+    k->vendor_id = PCI_VENDOR_ID_SUN;
+    k->device_id = PCI_DEVICE_ID_SUN_EBUS;
+    k->revision = 0x01;
+    k->class_id = PCI_CLASS_BRIDGE_OTHER;
+}
+
+static const TypeInfo ebus_info = {
+    .name          = "ebus",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(EbusState),
+    .class_init    = ebus_class_init,
+};
+
+typedef struct PROMState {
+    SysBusDevice busdev;
+    MemoryRegion prom;
+} PROMState;
+
+static uint64_t translate_prom_address(void *opaque, uint64_t addr)
+{
+    hwaddr *base_addr = (hwaddr *)opaque;
+    return addr + *base_addr - PROM_VADDR;
+}
+
+/* Boot PROM (OpenBIOS) */
+static void prom_init(hwaddr addr, const char *bios_name)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    char *filename;
+    int ret;
+
+    dev = qdev_create(NULL, "openprom");
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+
+    sysbus_mmio_map(s, 0, addr);
+
+    /* load boot prom */
+    if (bios_name == NULL) {
+        bios_name = PROM_FILENAME;
+    }
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+    if (filename) {
+        ret = load_elf(filename, translate_prom_address, &addr,
+                       NULL, NULL, NULL, 1, ELF_MACHINE, 0);
+        if (ret < 0 || ret > PROM_SIZE_MAX) {
+            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
+        }
+        g_free(filename);
+    } else {
+        ret = -1;
+    }
+    if (ret < 0 || ret > PROM_SIZE_MAX) {
+        fprintf(stderr, "qemu: could not load prom '%s'\n", bios_name);
+        exit(1);
+    }
+}
+
+static int prom_init1(SysBusDevice *dev)
+{
+    PROMState *s = FROM_SYSBUS(PROMState, dev);
+
+    memory_region_init_ram(&s->prom, "sun4u.prom", PROM_SIZE_MAX);
+    vmstate_register_ram_global(&s->prom);
+    memory_region_set_readonly(&s->prom, true);
+    sysbus_init_mmio(dev, &s->prom);
+    return 0;
+}
+
+static Property prom_properties[] = {
+    {/* end of property list */},
+};
+
+static void prom_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = prom_init1;
+    dc->props = prom_properties;
+}
+
+static const TypeInfo prom_info = {
+    .name          = "openprom",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(PROMState),
+    .class_init    = prom_class_init,
+};
+
+
+typedef struct RamDevice
+{
+    SysBusDevice busdev;
+    MemoryRegion ram;
+    uint64_t size;
+} RamDevice;
+
+/* System RAM */
+static int ram_init1(SysBusDevice *dev)
+{
+    RamDevice *d = FROM_SYSBUS(RamDevice, dev);
+
+    memory_region_init_ram(&d->ram, "sun4u.ram", d->size);
+    vmstate_register_ram_global(&d->ram);
+    sysbus_init_mmio(dev, &d->ram);
+    return 0;
+}
+
+static void ram_init(hwaddr addr, ram_addr_t RAM_size)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    RamDevice *d;
+
+    /* allocate RAM */
+    dev = qdev_create(NULL, "memory");
+    s = SYS_BUS_DEVICE(dev);
+
+    d = FROM_SYSBUS(RamDevice, s);
+    d->size = RAM_size;
+    qdev_init_nofail(dev);
+
+    sysbus_mmio_map(s, 0, addr);
+}
+
+static Property ram_properties[] = {
+    DEFINE_PROP_UINT64("size", RamDevice, size, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ram_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = ram_init1;
+    dc->props = ram_properties;
+}
+
+static const TypeInfo ram_info = {
+    .name          = "memory",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(RamDevice),
+    .class_init    = ram_class_init,
+};
+
+static SPARCCPU *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
+{
+    SPARCCPU *cpu;
+    CPUSPARCState *env;
+    ResetData *reset_info;
+
+    uint32_t   tick_frequency = 100*1000000;
+    uint32_t  stick_frequency = 100*1000000;
+    uint32_t hstick_frequency = 100*1000000;
+
+    if (cpu_model == NULL) {
+        cpu_model = hwdef->default_cpu_model;
+    }
+    cpu = cpu_sparc_init(cpu_model);
+    if (cpu == NULL) {
+        fprintf(stderr, "Unable to find Sparc CPU definition\n");
+        exit(1);
+    }
+    env = &cpu->env;
+
+    env->tick = cpu_timer_create("tick", cpu, tick_irq,
+                                  tick_frequency, TICK_NPT_MASK);
+
+    env->stick = cpu_timer_create("stick", cpu, stick_irq,
+                                   stick_frequency, TICK_INT_DIS);
+
+    env->hstick = cpu_timer_create("hstick", cpu, hstick_irq,
+                                    hstick_frequency, TICK_INT_DIS);
+
+    reset_info = g_malloc0(sizeof(ResetData));
+    reset_info->cpu = cpu;
+    reset_info->prom_addr = hwdef->prom_addr;
+    qemu_register_reset(main_cpu_reset, reset_info);
+
+    return cpu;
+}
+
+static void sun4uv_init(MemoryRegion *address_space_mem,
+                        ram_addr_t RAM_size,
+                        const char *boot_devices,
+                        const char *kernel_filename, const char *kernel_cmdline,
+                        const char *initrd_filename, const char *cpu_model,
+                        const struct hwdef *hwdef)
+{
+    SPARCCPU *cpu;
+    M48t59State *nvram;
+    unsigned int i;
+    uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry;
+    PCIBus *pci_bus, *pci_bus2, *pci_bus3;
+    ISABus *isa_bus;
+    qemu_irq *ivec_irqs, *pbm_irqs;
+    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    DriveInfo *fd[MAX_FD];
+    void *fw_cfg;
+
+    /* init CPUs */
+    cpu = cpu_devinit(cpu_model, hwdef);
+
+    /* set up devices */
+    ram_init(0, RAM_size);
+
+    prom_init(hwdef->prom_addr, bios_name);
+
+    ivec_irqs = qemu_allocate_irqs(cpu_set_ivec_irq, cpu, IVEC_MAX);
+    pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_bus2,
+                           &pci_bus3, &pbm_irqs);
+    pci_vga_init(pci_bus);
+
+    // XXX Should be pci_bus3
+    isa_bus = pci_ebus_init(pci_bus, -1, pbm_irqs);
+
+    i = 0;
+    if (hwdef->console_serial_base) {
+        serial_mm_init(address_space_mem, hwdef->console_serial_base, 0,
+                       NULL, 115200, serial_hds[i], DEVICE_BIG_ENDIAN);
+        i++;
+    }
+    for(; i < MAX_SERIAL_PORTS; i++) {
+        if (serial_hds[i]) {
+            serial_isa_init(isa_bus, i, serial_hds[i]);
+        }
+    }
+
+    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
+        if (parallel_hds[i]) {
+            parallel_init(isa_bus, i, parallel_hds[i]);
+        }
+    }
+
+    for(i = 0; i < nb_nics; i++)
+        pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
+
+    ide_drive_get(hd, MAX_IDE_BUS);
+
+    pci_cmd646_ide_init(pci_bus, hd, 1);
+
+    isa_create_simple(isa_bus, "i8042");
+    for(i = 0; i < MAX_FD; i++) {
+        fd[i] = drive_get(IF_FLOPPY, 0, i);
+    }
+    fdctrl_init_isa(isa_bus, fd);
+    nvram = m48t59_init_isa(isa_bus, 0x0074, NVRAM_SIZE, 59);
+
+    initrd_size = 0;
+    initrd_addr = 0;
+    kernel_size = sun4u_load_kernel(kernel_filename, initrd_filename,
+                                    ram_size, &initrd_size, &initrd_addr,
+                                    &kernel_addr, &kernel_entry);
+
+    sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", RAM_size, boot_devices,
+                           kernel_addr, kernel_size,
+                           kernel_cmdline,
+                           initrd_addr, initrd_size,
+                           /* XXX: need an option to load a NVRAM image */
+                           0,
+                           graphic_width, graphic_height, graphic_depth,
+                           (uint8_t *)&nd_table[0].macaddr);
+
+    fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_entry);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+    if (kernel_cmdline) {
+        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
+                       strlen(kernel_cmdline) + 1);
+        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
+    } else {
+        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
+    }
+    fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_devices[0]);
+
+    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_WIDTH, graphic_width);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_HEIGHT, graphic_height);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_DEPTH, graphic_depth);
+
+    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
+}
+
+enum {
+    sun4u_id = 0,
+    sun4v_id = 64,
+    niagara_id,
+};
+
+static const struct hwdef hwdefs[] = {
+    /* Sun4u generic PC-like machine */
+    {
+        .default_cpu_model = "TI UltraSparc IIi",
+        .machine_id = sun4u_id,
+        .prom_addr = 0x1fff0000000ULL,
+        .console_serial_base = 0,
+    },
+    /* Sun4v generic PC-like machine */
+    {
+        .default_cpu_model = "Sun UltraSparc T1",
+        .machine_id = sun4v_id,
+        .prom_addr = 0x1fff0000000ULL,
+        .console_serial_base = 0,
+    },
+    /* Sun4v generic Niagara machine */
+    {
+        .default_cpu_model = "Sun UltraSparc T1",
+        .machine_id = niagara_id,
+        .prom_addr = 0xfff0000000ULL,
+        .console_serial_base = 0xfff0c2c000ULL,
+    },
+};
+
+/* Sun4u hardware initialisation */
+static void sun4u_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_devices = args->boot_device;
+    sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
+                kernel_cmdline, initrd_filename, cpu_model, &hwdefs[0]);
+}
+
+/* Sun4v hardware initialisation */
+static void sun4v_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_devices = args->boot_device;
+    sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
+                kernel_cmdline, initrd_filename, cpu_model, &hwdefs[1]);
+}
+
+/* Niagara hardware initialisation */
+static void niagara_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t RAM_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    const char *boot_devices = args->boot_device;
+    sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
+                kernel_cmdline, initrd_filename, cpu_model, &hwdefs[2]);
+}
+
+static QEMUMachine sun4u_machine = {
+    .name = "sun4u",
+    .desc = "Sun4u platform",
+    .init = sun4u_init,
+    .max_cpus = 1, // XXX for now
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine sun4v_machine = {
+    .name = "sun4v",
+    .desc = "Sun4v platform",
+    .init = sun4v_init,
+    .max_cpus = 1, // XXX for now
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine niagara_machine = {
+    .name = "Niagara",
+    .desc = "Sun4v platform, Niagara",
+    .init = niagara_init,
+    .max_cpus = 1, // XXX for now
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void sun4u_register_types(void)
+{
+    type_register_static(&ebus_info);
+    type_register_static(&prom_info);
+    type_register_static(&ram_info);
+}
+
+static void sun4u_machine_init(void)
+{
+    qemu_register_machine(&sun4u_machine);
+    qemu_register_machine(&sun4v_machine);
+    qemu_register_machine(&niagara_machine);
+}
+
+type_init(sun4u_register_types)
+machine_init(sun4u_machine_init);
diff --git a/hw/spitz.c b/hw/spitz.c
deleted file mode 100644
index f5832be..0000000
--- a/hw/spitz.c
+++ /dev/null
@@ -1,1138 +0,0 @@
-/*
- * PXA270-based Clamshell PDA platforms.
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Written by Andrzej Zaborowski <balrog at zabor.org>
- *
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "hw/hw.h"
-#include "hw/pxa.h"
-#include "hw/arm-misc.h"
-#include "sysemu/sysemu.h"
-#include "hw/pcmcia.h"
-#include "hw/i2c.h"
-#include "hw/ssi.h"
-#include "hw/flash.h"
-#include "qemu/timer.h"
-#include "hw/devices.h"
-#include "hw/sharpsl.h"
-#include "ui/console.h"
-#include "block/block.h"
-#include "audio/audio.h"
-#include "hw/boards.h"
-#include "sysemu/blockdev.h"
-#include "hw/sysbus.h"
-#include "exec/address-spaces.h"
-
-#undef REG_FMT
-#define REG_FMT			"0x%02lx"
-
-/* Spitz Flash */
-#define FLASH_BASE		0x0c000000
-#define FLASH_ECCLPLB		0x00	/* Line parity 7 - 0 bit */
-#define FLASH_ECCLPUB		0x04	/* Line parity 15 - 8 bit */
-#define FLASH_ECCCP		0x08	/* Column parity 5 - 0 bit */
-#define FLASH_ECCCNTR		0x0c	/* ECC byte counter */
-#define FLASH_ECCCLRR		0x10	/* Clear ECC */
-#define FLASH_FLASHIO		0x14	/* Flash I/O */
-#define FLASH_FLASHCTL		0x18	/* Flash Control */
-
-#define FLASHCTL_CE0		(1 << 0)
-#define FLASHCTL_CLE		(1 << 1)
-#define FLASHCTL_ALE		(1 << 2)
-#define FLASHCTL_WP		(1 << 3)
-#define FLASHCTL_CE1		(1 << 4)
-#define FLASHCTL_RYBY		(1 << 5)
-#define FLASHCTL_NCE		(FLASHCTL_CE0 | FLASHCTL_CE1)
-
-typedef struct {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    DeviceState *nand;
-    uint8_t ctl;
-    uint8_t manf_id;
-    uint8_t chip_id;
-    ECCState ecc;
-} SLNANDState;
-
-static uint64_t sl_read(void *opaque, hwaddr addr, unsigned size)
-{
-    SLNANDState *s = (SLNANDState *) opaque;
-    int ryby;
-
-    switch (addr) {
-#define BSHR(byte, from, to)	((s->ecc.lp[byte] >> (from - to)) & (1 << to))
-    case FLASH_ECCLPLB:
-        return BSHR(0, 4, 0) | BSHR(0, 5, 2) | BSHR(0, 6, 4) | BSHR(0, 7, 6) |
-                BSHR(1, 4, 1) | BSHR(1, 5, 3) | BSHR(1, 6, 5) | BSHR(1, 7, 7);
-
-#define BSHL(byte, from, to)	((s->ecc.lp[byte] << (to - from)) & (1 << to))
-    case FLASH_ECCLPUB:
-        return BSHL(0, 0, 0) | BSHL(0, 1, 2) | BSHL(0, 2, 4) | BSHL(0, 3, 6) |
-                BSHL(1, 0, 1) | BSHL(1, 1, 3) | BSHL(1, 2, 5) | BSHL(1, 3, 7);
-
-    case FLASH_ECCCP:
-        return s->ecc.cp;
-
-    case FLASH_ECCCNTR:
-        return s->ecc.count & 0xff;
-
-    case FLASH_FLASHCTL:
-        nand_getpins(s->nand, &ryby);
-        if (ryby)
-            return s->ctl | FLASHCTL_RYBY;
-        else
-            return s->ctl;
-
-    case FLASH_FLASHIO:
-        if (size == 4) {
-            return ecc_digest(&s->ecc, nand_getio(s->nand)) |
-                (ecc_digest(&s->ecc, nand_getio(s->nand)) << 16);
-        }
-        return ecc_digest(&s->ecc, nand_getio(s->nand));
-
-    default:
-        zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr);
-    }
-    return 0;
-}
-
-static void sl_write(void *opaque, hwaddr addr,
-                     uint64_t value, unsigned size)
-{
-    SLNANDState *s = (SLNANDState *) opaque;
-
-    switch (addr) {
-    case FLASH_ECCCLRR:
-        /* Value is ignored.  */
-        ecc_reset(&s->ecc);
-        break;
-
-    case FLASH_FLASHCTL:
-        s->ctl = value & 0xff & ~FLASHCTL_RYBY;
-        nand_setpins(s->nand,
-                        s->ctl & FLASHCTL_CLE,
-                        s->ctl & FLASHCTL_ALE,
-                        s->ctl & FLASHCTL_NCE,
-                        s->ctl & FLASHCTL_WP,
-                        0);
-        break;
-
-    case FLASH_FLASHIO:
-        nand_setio(s->nand, ecc_digest(&s->ecc, value & 0xff));
-        break;
-
-    default:
-        zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr);
-    }
-}
-
-enum {
-    FLASH_128M,
-    FLASH_1024M,
-};
-
-static const MemoryRegionOps sl_ops = {
-    .read = sl_read,
-    .write = sl_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void sl_flash_register(PXA2xxState *cpu, int size)
-{
-    DeviceState *dev;
-
-    dev = qdev_create(NULL, "sl-nand");
-
-    qdev_prop_set_uint8(dev, "manf_id", NAND_MFR_SAMSUNG);
-    if (size == FLASH_128M)
-        qdev_prop_set_uint8(dev, "chip_id", 0x73);
-    else if (size == FLASH_1024M)
-        qdev_prop_set_uint8(dev, "chip_id", 0xf1);
-
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, FLASH_BASE);
-}
-
-static int sl_nand_init(SysBusDevice *dev) {
-    SLNANDState *s;
-    DriveInfo *nand;
-
-    s = FROM_SYSBUS(SLNANDState, dev);
-
-    s->ctl = 0;
-    nand = drive_get(IF_MTD, 0, 0);
-    s->nand = nand_init(nand ? nand->bdrv : NULL, s->manf_id, s->chip_id);
-
-    memory_region_init_io(&s->iomem, &sl_ops, s, "sl", 0x40);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    return 0;
-}
-
-/* Spitz Keyboard */
-
-#define SPITZ_KEY_STROBE_NUM	11
-#define SPITZ_KEY_SENSE_NUM	7
-
-static const int spitz_gpio_key_sense[SPITZ_KEY_SENSE_NUM] = {
-    12, 17, 91, 34, 36, 38, 39
-};
-
-static const int spitz_gpio_key_strobe[SPITZ_KEY_STROBE_NUM] = {
-    88, 23, 24, 25, 26, 27, 52, 103, 107, 108, 114
-};
-
-/* Eighth additional row maps the special keys */
-static int spitz_keymap[SPITZ_KEY_SENSE_NUM + 1][SPITZ_KEY_STROBE_NUM] = {
-    { 0x1d, 0x02, 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0e, 0x3f, 0x40 },
-    {  -1 , 0x03, 0x05, 0x13, 0x15, 0x09, 0x17, 0x18, 0x19, 0x41, 0x42 },
-    { 0x0f, 0x10, 0x12, 0x14, 0x22, 0x16, 0x24, 0x25,  -1 ,  -1 ,  -1  },
-    { 0x3c, 0x11, 0x1f, 0x21, 0x2f, 0x23, 0x32, 0x26,  -1 , 0x36,  -1  },
-    { 0x3b, 0x1e, 0x20, 0x2e, 0x30, 0x31, 0x34,  -1 , 0x1c, 0x2a,  -1  },
-    { 0x44, 0x2c, 0x2d, 0x0c, 0x39, 0x33,  -1 , 0x48,  -1 ,  -1 , 0x38 },
-    { 0x37, 0x3d,  -1 , 0x45, 0x57, 0x58, 0x4b, 0x50, 0x4d,  -1 ,  -1  },
-    { 0x52, 0x43, 0x01, 0x47, 0x49,  -1 ,  -1 ,  -1 ,  -1 ,  -1 ,  -1  },
-};
-
-#define SPITZ_GPIO_AK_INT	13	/* Remote control */
-#define SPITZ_GPIO_SYNC		16	/* Sync button */
-#define SPITZ_GPIO_ON_KEY	95	/* Power button */
-#define SPITZ_GPIO_SWA		97	/* Lid */
-#define SPITZ_GPIO_SWB		96	/* Tablet mode */
-
-/* The special buttons are mapped to unused keys */
-static const int spitz_gpiomap[5] = {
-    SPITZ_GPIO_AK_INT, SPITZ_GPIO_SYNC, SPITZ_GPIO_ON_KEY,
-    SPITZ_GPIO_SWA, SPITZ_GPIO_SWB,
-};
-
-typedef struct {
-    SysBusDevice busdev;
-    qemu_irq sense[SPITZ_KEY_SENSE_NUM];
-    qemu_irq gpiomap[5];
-    int keymap[0x80];
-    uint16_t keyrow[SPITZ_KEY_SENSE_NUM];
-    uint16_t strobe_state;
-    uint16_t sense_state;
-
-    uint16_t pre_map[0x100];
-    uint16_t modifiers;
-    uint16_t imodifiers;
-    uint8_t fifo[16];
-    int fifopos, fifolen;
-    QEMUTimer *kbdtimer;
-} SpitzKeyboardState;
-
-static void spitz_keyboard_sense_update(SpitzKeyboardState *s)
-{
-    int i;
-    uint16_t strobe, sense = 0;
-    for (i = 0; i < SPITZ_KEY_SENSE_NUM; i ++) {
-        strobe = s->keyrow[i] & s->strobe_state;
-        if (strobe) {
-            sense |= 1 << i;
-            if (!(s->sense_state & (1 << i)))
-                qemu_irq_raise(s->sense[i]);
-        } else if (s->sense_state & (1 << i))
-            qemu_irq_lower(s->sense[i]);
-    }
-
-    s->sense_state = sense;
-}
-
-static void spitz_keyboard_strobe(void *opaque, int line, int level)
-{
-    SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
-
-    if (level)
-        s->strobe_state |= 1 << line;
-    else
-        s->strobe_state &= ~(1 << line);
-    spitz_keyboard_sense_update(s);
-}
-
-static void spitz_keyboard_keydown(SpitzKeyboardState *s, int keycode)
-{
-    int spitz_keycode = s->keymap[keycode & 0x7f];
-    if (spitz_keycode == -1)
-        return;
-
-    /* Handle the additional keys */
-    if ((spitz_keycode >> 4) == SPITZ_KEY_SENSE_NUM) {
-        qemu_set_irq(s->gpiomap[spitz_keycode & 0xf], (keycode < 0x80));
-        return;
-    }
-
-    if (keycode & 0x80)
-        s->keyrow[spitz_keycode >> 4] &= ~(1 << (spitz_keycode & 0xf));
-    else
-        s->keyrow[spitz_keycode >> 4] |= 1 << (spitz_keycode & 0xf);
-
-    spitz_keyboard_sense_update(s);
-}
-
-#define SHIFT	(1 << 7)
-#define CTRL	(1 << 8)
-#define FN	(1 << 9)
-
-#define QUEUE_KEY(c)	s->fifo[(s->fifopos + s->fifolen ++) & 0xf] = c
-
-static void spitz_keyboard_handler(void *opaque, int keycode)
-{
-    SpitzKeyboardState *s = opaque;
-    uint16_t code;
-    int mapcode;
-    switch (keycode) {
-    case 0x2a:	/* Left Shift */
-        s->modifiers |= 1;
-        break;
-    case 0xaa:
-        s->modifiers &= ~1;
-        break;
-    case 0x36:	/* Right Shift */
-        s->modifiers |= 2;
-        break;
-    case 0xb6:
-        s->modifiers &= ~2;
-        break;
-    case 0x1d:	/* Control */
-        s->modifiers |= 4;
-        break;
-    case 0x9d:
-        s->modifiers &= ~4;
-        break;
-    case 0x38:	/* Alt */
-        s->modifiers |= 8;
-        break;
-    case 0xb8:
-        s->modifiers &= ~8;
-        break;
-    }
-
-    code = s->pre_map[mapcode = ((s->modifiers & 3) ?
-            (keycode | SHIFT) :
-            (keycode & ~SHIFT))];
-
-    if (code != mapcode) {
-#if 0
-        if ((code & SHIFT) && !(s->modifiers & 1))
-            QUEUE_KEY(0x2a | (keycode & 0x80));
-        if ((code & CTRL ) && !(s->modifiers & 4))
-            QUEUE_KEY(0x1d | (keycode & 0x80));
-        if ((code & FN   ) && !(s->modifiers & 8))
-            QUEUE_KEY(0x38 | (keycode & 0x80));
-        if ((code & FN   ) && (s->modifiers & 1))
-            QUEUE_KEY(0x2a | (~keycode & 0x80));
-        if ((code & FN   ) && (s->modifiers & 2))
-            QUEUE_KEY(0x36 | (~keycode & 0x80));
-#else
-        if (keycode & 0x80) {
-            if ((s->imodifiers & 1   ) && !(s->modifiers & 1))
-                QUEUE_KEY(0x2a | 0x80);
-            if ((s->imodifiers & 4   ) && !(s->modifiers & 4))
-                QUEUE_KEY(0x1d | 0x80);
-            if ((s->imodifiers & 8   ) && !(s->modifiers & 8))
-                QUEUE_KEY(0x38 | 0x80);
-            if ((s->imodifiers & 0x10) && (s->modifiers & 1))
-                QUEUE_KEY(0x2a);
-            if ((s->imodifiers & 0x20) && (s->modifiers & 2))
-                QUEUE_KEY(0x36);
-            s->imodifiers = 0;
-        } else {
-            if ((code & SHIFT) && !((s->modifiers | s->imodifiers) & 1)) {
-                QUEUE_KEY(0x2a);
-                s->imodifiers |= 1;
-            }
-            if ((code & CTRL ) && !((s->modifiers | s->imodifiers) & 4)) {
-                QUEUE_KEY(0x1d);
-                s->imodifiers |= 4;
-            }
-            if ((code & FN   ) && !((s->modifiers | s->imodifiers) & 8)) {
-                QUEUE_KEY(0x38);
-                s->imodifiers |= 8;
-            }
-            if ((code & FN   ) && (s->modifiers & 1) &&
-                            !(s->imodifiers & 0x10)) {
-                QUEUE_KEY(0x2a | 0x80);
-                s->imodifiers |= 0x10;
-            }
-            if ((code & FN   ) && (s->modifiers & 2) &&
-                            !(s->imodifiers & 0x20)) {
-                QUEUE_KEY(0x36 | 0x80);
-                s->imodifiers |= 0x20;
-            }
-        }
-#endif
-    }
-
-    QUEUE_KEY((code & 0x7f) | (keycode & 0x80));
-}
-
-static void spitz_keyboard_tick(void *opaque)
-{
-    SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
-
-    if (s->fifolen) {
-        spitz_keyboard_keydown(s, s->fifo[s->fifopos ++]);
-        s->fifolen --;
-        if (s->fifopos >= 16)
-            s->fifopos = 0;
-    }
-
-    qemu_mod_timer(s->kbdtimer, qemu_get_clock_ns(vm_clock) +
-                   get_ticks_per_sec() / 32);
-}
-
-static void spitz_keyboard_pre_map(SpitzKeyboardState *s)
-{
-    int i;
-    for (i = 0; i < 0x100; i ++)
-        s->pre_map[i] = i;
-    s->pre_map[0x02 | SHIFT	] = 0x02 | SHIFT;	/* exclam */
-    s->pre_map[0x28 | SHIFT	] = 0x03 | SHIFT;	/* quotedbl */
-    s->pre_map[0x04 | SHIFT	] = 0x04 | SHIFT;	/* numbersign */
-    s->pre_map[0x05 | SHIFT	] = 0x05 | SHIFT;	/* dollar */
-    s->pre_map[0x06 | SHIFT	] = 0x06 | SHIFT;	/* percent */
-    s->pre_map[0x08 | SHIFT	] = 0x07 | SHIFT;	/* ampersand */
-    s->pre_map[0x28		] = 0x08 | SHIFT;	/* apostrophe */
-    s->pre_map[0x0a | SHIFT	] = 0x09 | SHIFT;	/* parenleft */
-    s->pre_map[0x0b | SHIFT	] = 0x0a | SHIFT;	/* parenright */
-    s->pre_map[0x29 | SHIFT	] = 0x0b | SHIFT;	/* asciitilde */
-    s->pre_map[0x03 | SHIFT	] = 0x0c | SHIFT;	/* at */
-    s->pre_map[0xd3		] = 0x0e | FN;		/* Delete */
-    s->pre_map[0x3a		] = 0x0f | FN;		/* Caps_Lock */
-    s->pre_map[0x07 | SHIFT	] = 0x11 | FN;		/* asciicircum */
-    s->pre_map[0x0d		] = 0x12 | FN;		/* equal */
-    s->pre_map[0x0d | SHIFT	] = 0x13 | FN;		/* plus */
-    s->pre_map[0x1a		] = 0x14 | FN;		/* bracketleft */
-    s->pre_map[0x1b		] = 0x15 | FN;		/* bracketright */
-    s->pre_map[0x1a | SHIFT	] = 0x16 | FN;		/* braceleft */
-    s->pre_map[0x1b | SHIFT	] = 0x17 | FN;		/* braceright */
-    s->pre_map[0x27		] = 0x22 | FN;		/* semicolon */
-    s->pre_map[0x27 | SHIFT	] = 0x23 | FN;		/* colon */
-    s->pre_map[0x09 | SHIFT	] = 0x24 | FN;		/* asterisk */
-    s->pre_map[0x2b		] = 0x25 | FN;		/* backslash */
-    s->pre_map[0x2b | SHIFT	] = 0x26 | FN;		/* bar */
-    s->pre_map[0x0c | SHIFT	] = 0x30 | FN;		/* underscore */
-    s->pre_map[0x33 | SHIFT	] = 0x33 | FN;		/* less */
-    s->pre_map[0x35		] = 0x33 | SHIFT;	/* slash */
-    s->pre_map[0x34 | SHIFT	] = 0x34 | FN;		/* greater */
-    s->pre_map[0x35 | SHIFT	] = 0x34 | SHIFT;	/* question */
-    s->pre_map[0x49		] = 0x48 | FN;		/* Page_Up */
-    s->pre_map[0x51		] = 0x50 | FN;		/* Page_Down */
-
-    s->modifiers = 0;
-    s->imodifiers = 0;
-    s->fifopos = 0;
-    s->fifolen = 0;
-}
-
-#undef SHIFT
-#undef CTRL
-#undef FN
-
-static int spitz_keyboard_post_load(void *opaque, int version_id)
-{
-    SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
-
-    /* Release all pressed keys */
-    memset(s->keyrow, 0, sizeof(s->keyrow));
-    spitz_keyboard_sense_update(s);
-    s->modifiers = 0;
-    s->imodifiers = 0;
-    s->fifopos = 0;
-    s->fifolen = 0;
-
-    return 0;
-}
-
-static void spitz_keyboard_register(PXA2xxState *cpu)
-{
-    int i;
-    DeviceState *dev;
-    SpitzKeyboardState *s;
-
-    dev = sysbus_create_simple("spitz-keyboard", -1, NULL);
-    s = FROM_SYSBUS(SpitzKeyboardState, SYS_BUS_DEVICE(dev));
-
-    for (i = 0; i < SPITZ_KEY_SENSE_NUM; i ++)
-        qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(cpu->gpio, spitz_gpio_key_sense[i]));
-
-    for (i = 0; i < 5; i ++)
-        s->gpiomap[i] = qdev_get_gpio_in(cpu->gpio, spitz_gpiomap[i]);
-
-    if (!graphic_rotate)
-        s->gpiomap[4] = qemu_irq_invert(s->gpiomap[4]);
-
-    for (i = 0; i < 5; i++)
-        qemu_set_irq(s->gpiomap[i], 0);
-
-    for (i = 0; i < SPITZ_KEY_STROBE_NUM; i ++)
-        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_ns(vm_clock));
-
-    qemu_add_kbd_event_handler(spitz_keyboard_handler, s);
-}
-
-static int spitz_keyboard_init(SysBusDevice *dev)
-{
-    SpitzKeyboardState *s;
-    int i, j;
-
-    s = FROM_SYSBUS(SpitzKeyboardState, dev);
-
-    for (i = 0; i < 0x80; i ++)
-        s->keymap[i] = -1;
-    for (i = 0; i < SPITZ_KEY_SENSE_NUM + 1; i ++)
-        for (j = 0; j < SPITZ_KEY_STROBE_NUM; j ++)
-            if (spitz_keymap[i][j] != -1)
-                s->keymap[spitz_keymap[i][j]] = (i << 4) | j;
-
-    spitz_keyboard_pre_map(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);
-
-    return 0;
-}
-
-/* LCD backlight controller */
-
-#define LCDTG_RESCTL	0x00
-#define LCDTG_PHACTRL	0x01
-#define LCDTG_DUTYCTRL	0x02
-#define LCDTG_POWERREG0	0x03
-#define LCDTG_POWERREG1	0x04
-#define LCDTG_GPOR3	0x05
-#define LCDTG_PICTRL	0x06
-#define LCDTG_POLCTRL	0x07
-
-typedef struct {
-    SSISlave ssidev;
-    uint32_t bl_intensity;
-    uint32_t bl_power;
-} SpitzLCDTG;
-
-static void spitz_bl_update(SpitzLCDTG *s)
-{
-    if (s->bl_power && s->bl_intensity)
-        zaurus_printf("LCD Backlight now at %i/63\n", s->bl_intensity);
-    else
-        zaurus_printf("LCD Backlight now off\n");
-}
-
-/* FIXME: Implement GPIO properly and remove this hack.  */
-static SpitzLCDTG *spitz_lcdtg;
-
-static inline void spitz_bl_bit5(void *opaque, int line, int level)
-{
-    SpitzLCDTG *s = spitz_lcdtg;
-    int prev = s->bl_intensity;
-
-    if (level)
-        s->bl_intensity &= ~0x20;
-    else
-        s->bl_intensity |= 0x20;
-
-    if (s->bl_power && prev != s->bl_intensity)
-        spitz_bl_update(s);
-}
-
-static inline void spitz_bl_power(void *opaque, int line, int level)
-{
-    SpitzLCDTG *s = spitz_lcdtg;
-    s->bl_power = !!level;
-    spitz_bl_update(s);
-}
-
-static uint32_t spitz_lcdtg_transfer(SSISlave *dev, uint32_t value)
-{
-    SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev);
-    int addr;
-    addr = value >> 5;
-    value &= 0x1f;
-
-    switch (addr) {
-    case LCDTG_RESCTL:
-        if (value)
-            zaurus_printf("LCD in QVGA mode\n");
-        else
-            zaurus_printf("LCD in VGA mode\n");
-        break;
-
-    case LCDTG_DUTYCTRL:
-        s->bl_intensity &= ~0x1f;
-        s->bl_intensity |= value;
-        if (s->bl_power)
-            spitz_bl_update(s);
-        break;
-
-    case LCDTG_POWERREG0:
-        /* Set common voltage to M62332FP */
-        break;
-    }
-    return 0;
-}
-
-static int spitz_lcdtg_init(SSISlave *dev)
-{
-    SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev);
-
-    spitz_lcdtg = s;
-    s->bl_power = 0;
-    s->bl_intensity = 0x20;
-
-    return 0;
-}
-
-/* SSP devices */
-
-#define CORGI_SSP_PORT		2
-
-#define SPITZ_GPIO_LCDCON_CS	53
-#define SPITZ_GPIO_ADS7846_CS	14
-#define SPITZ_GPIO_MAX1111_CS	20
-#define SPITZ_GPIO_TP_INT	11
-
-static DeviceState *max1111;
-
-/* "Demux" the signal based on current chipselect */
-typedef struct {
-    SSISlave ssidev;
-    SSIBus *bus[3];
-    uint32_t enable[3];
-} CorgiSSPState;
-
-static uint32_t corgi_ssp_transfer(SSISlave *dev, uint32_t value)
-{
-    CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev);
-    int i;
-
-    for (i = 0; i < 3; i++) {
-        if (s->enable[i]) {
-            return ssi_transfer(s->bus[i], value);
-        }
-    }
-    return 0;
-}
-
-static void corgi_ssp_gpio_cs(void *opaque, int line, int level)
-{
-    CorgiSSPState *s = (CorgiSSPState *)opaque;
-    assert(line >= 0 && line < 3);
-    s->enable[line] = !level;
-}
-
-#define MAX1111_BATT_VOLT	1
-#define MAX1111_BATT_TEMP	2
-#define MAX1111_ACIN_VOLT	3
-
-#define SPITZ_BATTERY_TEMP	0xe0	/* About 2.9V */
-#define SPITZ_BATTERY_VOLT	0xd0	/* About 4.0V */
-#define SPITZ_CHARGEON_ACIN	0x80	/* About 5.0V */
-
-static void spitz_adc_temp_on(void *opaque, int line, int level)
-{
-    if (!max1111)
-        return;
-
-    if (level)
-        max111x_set_input(max1111, MAX1111_BATT_TEMP, SPITZ_BATTERY_TEMP);
-    else
-        max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
-}
-
-static int corgi_ssp_init(SSISlave *dev)
-{
-    CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev);
-
-    qdev_init_gpio_in(&dev->qdev, corgi_ssp_gpio_cs, 3);
-    s->bus[0] = ssi_create_bus(&dev->qdev, "ssi0");
-    s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1");
-    s->bus[2] = ssi_create_bus(&dev->qdev, "ssi2");
-
-    return 0;
-}
-
-static void spitz_ssp_attach(PXA2xxState *cpu)
-{
-    DeviceState *mux;
-    DeviceState *dev;
-    void *bus;
-
-    mux = ssi_create_slave(cpu->ssp[CORGI_SSP_PORT - 1], "corgi-ssp");
-
-    bus = qdev_get_child_bus(mux, "ssi0");
-    ssi_create_slave(bus, "spitz-lcdtg");
-
-    bus = qdev_get_child_bus(mux, "ssi1");
-    dev = ssi_create_slave(bus, "ads7846");
-    qdev_connect_gpio_out(dev, 0,
-                          qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_TP_INT));
-
-    bus = qdev_get_child_bus(mux, "ssi2");
-    max1111 = ssi_create_slave(bus, "max1111");
-    max111x_set_input(max1111, MAX1111_BATT_VOLT, SPITZ_BATTERY_VOLT);
-    max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
-    max111x_set_input(max1111, MAX1111_ACIN_VOLT, SPITZ_CHARGEON_ACIN);
-
-    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_LCDCON_CS,
-                        qdev_get_gpio_in(mux, 0));
-    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_ADS7846_CS,
-                        qdev_get_gpio_in(mux, 1));
-    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_MAX1111_CS,
-                        qdev_get_gpio_in(mux, 2));
-}
-
-/* CF Microdrive */
-
-static void spitz_microdrive_attach(PXA2xxState *cpu, int slot)
-{
-    PCMCIACardState *md;
-    DriveInfo *dinfo;
-
-    dinfo = drive_get(IF_IDE, 0, 0);
-    if (!dinfo || dinfo->media_cd)
-        return;
-    md = dscm1xxxx_init(dinfo);
-    pxa2xx_pcmcia_attach(cpu->pcmcia[slot], md);
-}
-
-/* Wm8750 and Max7310 on I2C */
-
-#define AKITA_MAX_ADDR	0x18
-#define SPITZ_WM_ADDRL	0x1b
-#define SPITZ_WM_ADDRH	0x1a
-
-#define SPITZ_GPIO_WM	5
-
-static void spitz_wm8750_addr(void *opaque, int line, int level)
-{
-    I2CSlave *wm = (I2CSlave *) opaque;
-    if (level)
-        i2c_set_slave_address(wm, SPITZ_WM_ADDRH);
-    else
-        i2c_set_slave_address(wm, SPITZ_WM_ADDRL);
-}
-
-static void spitz_i2c_setup(PXA2xxState *cpu)
-{
-    /* Attach the CPU on one end of our I2C bus.  */
-    i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]);
-
-    DeviceState *wm;
-
-    /* Attach a WM8750 to the bus */
-    wm = i2c_create_slave(bus, "wm8750", 0);
-
-    spitz_wm8750_addr(wm, 0, 0);
-    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_WM,
-                    qemu_allocate_irqs(spitz_wm8750_addr, wm, 1)[0]);
-    /* .. and to the sound interface.  */
-    cpu->i2s->opaque = wm;
-    cpu->i2s->codec_out = wm8750_dac_dat;
-    cpu->i2s->codec_in = wm8750_adc_dat;
-    wm8750_data_req_set(wm, cpu->i2s->data_req, cpu->i2s);
-}
-
-static void spitz_akita_i2c_setup(PXA2xxState *cpu)
-{
-    /* Attach a Max7310 to Akita I2C bus.  */
-    i2c_create_slave(pxa2xx_i2c_bus(cpu->i2c[0]), "max7310",
-                     AKITA_MAX_ADDR);
-}
-
-/* Other peripherals */
-
-static void spitz_out_switch(void *opaque, int line, int level)
-{
-    switch (line) {
-    case 0:
-        zaurus_printf("Charging %s.\n", level ? "off" : "on");
-        break;
-    case 1:
-        zaurus_printf("Discharging %s.\n", level ? "on" : "off");
-        break;
-    case 2:
-        zaurus_printf("Green LED %s.\n", level ? "on" : "off");
-        break;
-    case 3:
-        zaurus_printf("Orange LED %s.\n", level ? "on" : "off");
-        break;
-    case 4:
-        spitz_bl_bit5(opaque, line, level);
-        break;
-    case 5:
-        spitz_bl_power(opaque, line, level);
-        break;
-    case 6:
-        spitz_adc_temp_on(opaque, line, level);
-        break;
-    }
-}
-
-#define SPITZ_SCP_LED_GREEN		1
-#define SPITZ_SCP_JK_B			2
-#define SPITZ_SCP_CHRG_ON		3
-#define SPITZ_SCP_MUTE_L		4
-#define SPITZ_SCP_MUTE_R		5
-#define SPITZ_SCP_CF_POWER		6
-#define SPITZ_SCP_LED_ORANGE		7
-#define SPITZ_SCP_JK_A			8
-#define SPITZ_SCP_ADC_TEMP_ON		9
-#define SPITZ_SCP2_IR_ON		1
-#define SPITZ_SCP2_AKIN_PULLUP		2
-#define SPITZ_SCP2_BACKLIGHT_CONT	7
-#define SPITZ_SCP2_BACKLIGHT_ON		8
-#define SPITZ_SCP2_MIC_BIAS		9
-
-static void spitz_scoop_gpio_setup(PXA2xxState *cpu,
-                DeviceState *scp0, DeviceState *scp1)
-{
-    qemu_irq *outsignals = qemu_allocate_irqs(spitz_out_switch, cpu, 8);
-
-    qdev_connect_gpio_out(scp0, SPITZ_SCP_CHRG_ON, outsignals[0]);
-    qdev_connect_gpio_out(scp0, SPITZ_SCP_JK_B, outsignals[1]);
-    qdev_connect_gpio_out(scp0, SPITZ_SCP_LED_GREEN, outsignals[2]);
-    qdev_connect_gpio_out(scp0, SPITZ_SCP_LED_ORANGE, outsignals[3]);
-
-    if (scp1) {
-        qdev_connect_gpio_out(scp1, SPITZ_SCP2_BACKLIGHT_CONT, outsignals[4]);
-        qdev_connect_gpio_out(scp1, SPITZ_SCP2_BACKLIGHT_ON, outsignals[5]);
-    }
-
-    qdev_connect_gpio_out(scp0, SPITZ_SCP_ADC_TEMP_ON, outsignals[6]);
-}
-
-#define SPITZ_GPIO_HSYNC		22
-#define SPITZ_GPIO_SD_DETECT		9
-#define SPITZ_GPIO_SD_WP		81
-#define SPITZ_GPIO_ON_RESET		89
-#define SPITZ_GPIO_BAT_COVER		90
-#define SPITZ_GPIO_CF1_IRQ		105
-#define SPITZ_GPIO_CF1_CD		94
-#define SPITZ_GPIO_CF2_IRQ		106
-#define SPITZ_GPIO_CF2_CD		93
-
-static int spitz_hsync;
-
-static void spitz_lcd_hsync_handler(void *opaque, int line, int level)
-{
-    PXA2xxState *cpu = (PXA2xxState *) opaque;
-    qemu_set_irq(qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_HSYNC), spitz_hsync);
-    spitz_hsync ^= 1;
-}
-
-static void spitz_gpio_setup(PXA2xxState *cpu, int slots)
-{
-    qemu_irq lcd_hsync;
-    /*
-     * Bad hack: We toggle the LCD hsync GPIO on every GPIO status
-     * read to satisfy broken guests that poll-wait for hsync.
-     * Simulating a real hsync event would be less practical and
-     * wouldn't guarantee that a guest ever exits the loop.
-     */
-    spitz_hsync = 0;
-    lcd_hsync = qemu_allocate_irqs(spitz_lcd_hsync_handler, cpu, 1)[0];
-    pxa2xx_gpio_read_notifier(cpu->gpio, lcd_hsync);
-    pxa2xx_lcd_vsync_notifier(cpu->lcd, lcd_hsync);
-
-    /* MMC/SD host */
-    pxa2xx_mmci_handlers(cpu->mmc,
-                    qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_SD_WP),
-                    qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_SD_DETECT));
-
-    /* Battery lock always closed */
-    qemu_irq_raise(qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_BAT_COVER));
-
-    /* Handle reset */
-    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_ON_RESET, cpu->reset);
-
-    /* PCMCIA signals: card's IRQ and Card-Detect */
-    if (slots >= 1)
-        pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
-                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF1_IRQ),
-                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF1_CD));
-    if (slots >= 2)
-        pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
-                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF2_IRQ),
-                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF2_CD));
-}
-
-/* Board init.  */
-enum spitz_model_e { spitz, akita, borzoi, terrier };
-
-#define SPITZ_RAM	0x04000000
-#define SPITZ_ROM	0x00800000
-
-static struct arm_boot_info spitz_binfo = {
-    .loader_start = PXA2XX_SDRAM_BASE,
-    .ram_size = 0x04000000,
-};
-
-static void spitz_common_init(QEMUMachineInitArgs *args,
-                              enum spitz_model_e model, int arm_id)
-{
-    PXA2xxState *mpu;
-    DeviceState *scp0, *scp1 = NULL;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *rom = g_new(MemoryRegion, 1);
-    const char *cpu_model = args->cpu_model;
-
-    if (!cpu_model)
-        cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0";
-
-    /* Setup CPU & memory */
-    mpu = pxa270_init(address_space_mem, spitz_binfo.ram_size, cpu_model);
-
-    sl_flash_register(mpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
-
-    memory_region_init_ram(rom, "spitz.rom", SPITZ_ROM);
-    vmstate_register_ram_global(rom);
-    memory_region_set_readonly(rom, true);
-    memory_region_add_subregion(address_space_mem, 0, rom);
-
-    /* Setup peripherals */
-    spitz_keyboard_register(mpu);
-
-    spitz_ssp_attach(mpu);
-
-    scp0 = sysbus_create_simple("scoop", 0x10800000, NULL);
-    if (model != akita) {
-        scp1 = sysbus_create_simple("scoop", 0x08800040, NULL);
-    }
-
-    spitz_scoop_gpio_setup(mpu, scp0, scp1);
-
-    spitz_gpio_setup(mpu, (model == akita) ? 1 : 2);
-
-    spitz_i2c_setup(mpu);
-
-    if (model == akita)
-        spitz_akita_i2c_setup(mpu);
-
-    if (model == terrier)
-        /* A 6.0 GB microdrive is permanently sitting in CF slot 1.  */
-        spitz_microdrive_attach(mpu, 1);
-    else if (model != akita)
-        /* A 4.0 GB microdrive is permanently sitting in CF slot 0.  */
-        spitz_microdrive_attach(mpu, 0);
-
-    spitz_binfo.kernel_filename = args->kernel_filename;
-    spitz_binfo.kernel_cmdline = args->kernel_cmdline;
-    spitz_binfo.initrd_filename = args->initrd_filename;
-    spitz_binfo.board_id = arm_id;
-    arm_load_kernel(mpu->cpu, &spitz_binfo);
-    sl_bootparam_write(SL_PXA_PARAM_BASE);
-}
-
-static void spitz_init(QEMUMachineInitArgs *args)
-{
-    spitz_common_init(args, spitz, 0x2c9);
-}
-
-static void borzoi_init(QEMUMachineInitArgs *args)
-{
-    spitz_common_init(args, borzoi, 0x33f);
-}
-
-static void akita_init(QEMUMachineInitArgs *args)
-{
-    spitz_common_init(args, akita, 0x2e8);
-}
-
-static void terrier_init(QEMUMachineInitArgs *args)
-{
-    spitz_common_init(args, terrier, 0x33f);
-}
-
-static QEMUMachine akitapda_machine = {
-    .name = "akita",
-    .desc = "Akita PDA (PXA270)",
-    .init = akita_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine spitzpda_machine = {
-    .name = "spitz",
-    .desc = "Spitz PDA (PXA270)",
-    .init = spitz_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine borzoipda_machine = {
-    .name = "borzoi",
-    .desc = "Borzoi PDA (PXA270)",
-    .init = borzoi_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine terrierpda_machine = {
-    .name = "terrier",
-    .desc = "Terrier PDA (PXA270)",
-    .init = terrier_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void spitz_machine_init(void)
-{
-    qemu_register_machine(&akitapda_machine);
-    qemu_register_machine(&spitzpda_machine);
-    qemu_register_machine(&borzoipda_machine);
-    qemu_register_machine(&terrierpda_machine);
-}
-
-machine_init(spitz_machine_init);
-
-static bool is_version_0(void *opaque, int version_id)
-{
-    return version_id == 0;
-}
-
-static VMStateDescription vmstate_sl_nand_info = {
-    .name = "sl-nand",
-    .version_id = 0,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .fields = (VMStateField []) {
-        VMSTATE_UINT8(ctl, SLNANDState),
-        VMSTATE_STRUCT(ecc, SLNANDState, 0, vmstate_ecc_state, ECCState),
-        VMSTATE_END_OF_LIST(),
-    },
-};
-
-static Property sl_nand_properties[] = {
-    DEFINE_PROP_UINT8("manf_id", SLNANDState, manf_id, NAND_MFR_SAMSUNG),
-    DEFINE_PROP_UINT8("chip_id", SLNANDState, chip_id, 0xf1),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void sl_nand_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = sl_nand_init;
-    dc->vmsd = &vmstate_sl_nand_info;
-    dc->props = sl_nand_properties;
-}
-
-static const TypeInfo sl_nand_info = {
-    .name          = "sl-nand",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(SLNANDState),
-    .class_init    = sl_nand_class_init,
-};
-
-static VMStateDescription vmstate_spitz_kbd = {
-    .name = "spitz-keyboard",
-    .version_id = 1,
-    .minimum_version_id = 0,
-    .minimum_version_id_old = 0,
-    .post_load = spitz_keyboard_post_load,
-    .fields = (VMStateField []) {
-        VMSTATE_UINT16(sense_state, SpitzKeyboardState),
-        VMSTATE_UINT16(strobe_state, SpitzKeyboardState),
-        VMSTATE_UNUSED_TEST(is_version_0, 5),
-        VMSTATE_END_OF_LIST(),
-    },
-};
-
-static Property spitz_keyboard_properties[] = {
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void spitz_keyboard_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = spitz_keyboard_init;
-    dc->vmsd = &vmstate_spitz_kbd;
-    dc->props = spitz_keyboard_properties;
-}
-
-static const TypeInfo spitz_keyboard_info = {
-    .name          = "spitz-keyboard",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(SpitzKeyboardState),
-    .class_init    = spitz_keyboard_class_init,
-};
-
-static const VMStateDescription vmstate_corgi_ssp_regs = {
-    .name = "corgi-ssp",
-    .version_id = 2,
-    .minimum_version_id = 2,
-    .minimum_version_id_old = 2,
-    .fields = (VMStateField []) {
-        VMSTATE_SSI_SLAVE(ssidev, CorgiSSPState),
-        VMSTATE_UINT32_ARRAY(enable, CorgiSSPState, 3),
-        VMSTATE_END_OF_LIST(),
-    }
-};
-
-static void corgi_ssp_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
-
-    k->init = corgi_ssp_init;
-    k->transfer = corgi_ssp_transfer;
-    dc->vmsd = &vmstate_corgi_ssp_regs;
-}
-
-static const TypeInfo corgi_ssp_info = {
-    .name          = "corgi-ssp",
-    .parent        = TYPE_SSI_SLAVE,
-    .instance_size = sizeof(CorgiSSPState),
-    .class_init    = corgi_ssp_class_init,
-};
-
-static const VMStateDescription vmstate_spitz_lcdtg_regs = {
-    .name = "spitz-lcdtg",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField []) {
-        VMSTATE_SSI_SLAVE(ssidev, SpitzLCDTG),
-        VMSTATE_UINT32(bl_intensity, SpitzLCDTG),
-        VMSTATE_UINT32(bl_power, SpitzLCDTG),
-        VMSTATE_END_OF_LIST(),
-    }
-};
-
-static void spitz_lcdtg_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
-
-    k->init = spitz_lcdtg_init;
-    k->transfer = spitz_lcdtg_transfer;
-    dc->vmsd = &vmstate_spitz_lcdtg_regs;
-}
-
-static const TypeInfo spitz_lcdtg_info = {
-    .name          = "spitz-lcdtg",
-    .parent        = TYPE_SSI_SLAVE,
-    .instance_size = sizeof(SpitzLCDTG),
-    .class_init    = spitz_lcdtg_class_init,
-};
-
-static void spitz_register_types(void)
-{
-    type_register_static(&corgi_ssp_info);
-    type_register_static(&spitz_lcdtg_info);
-    type_register_static(&spitz_keyboard_info);
-    type_register_static(&sl_nand_info);
-}
-
-type_init(spitz_register_types)
diff --git a/hw/stellaris.c b/hw/stellaris.c
deleted file mode 100644
index f4ce794..0000000
--- a/hw/stellaris.c
+++ /dev/null
@@ -1,1401 +0,0 @@
-/*
- * Luminary Micro Stellaris peripherals
- *
- * Copyright (c) 2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GPL.
- */
-
-#include "hw/sysbus.h"
-#include "hw/ssi.h"
-#include "hw/arm-misc.h"
-#include "hw/devices.h"
-#include "qemu/timer.h"
-#include "hw/i2c.h"
-#include "net/net.h"
-#include "hw/boards.h"
-#include "exec/address-spaces.h"
-
-#define GPIO_A 0
-#define GPIO_B 1
-#define GPIO_C 2
-#define GPIO_D 3
-#define GPIO_E 4
-#define GPIO_F 5
-#define GPIO_G 6
-
-#define BP_OLED_I2C  0x01
-#define BP_OLED_SSI  0x02
-#define BP_GAMEPAD   0x04
-
-typedef const struct {
-    const char *name;
-    uint32_t did0;
-    uint32_t did1;
-    uint32_t dc0;
-    uint32_t dc1;
-    uint32_t dc2;
-    uint32_t dc3;
-    uint32_t dc4;
-    uint32_t peripherals;
-} stellaris_board_info;
-
-/* General purpose timer module.  */
-
-typedef struct gptm_state {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t config;
-    uint32_t mode[2];
-    uint32_t control;
-    uint32_t state;
-    uint32_t mask;
-    uint32_t load[2];
-    uint32_t match[2];
-    uint32_t prescale[2];
-    uint32_t match_prescale[2];
-    uint32_t rtc;
-    int64_t tick[2];
-    struct gptm_state *opaque[2];
-    QEMUTimer *timer[2];
-    /* The timers have an alternate output used to trigger the ADC.  */
-    qemu_irq trigger;
-    qemu_irq irq;
-} gptm_state;
-
-static void gptm_update_irq(gptm_state *s)
-{
-    int level;
-    level = (s->state & s->mask) != 0;
-    qemu_set_irq(s->irq, level);
-}
-
-static void gptm_stop(gptm_state *s, int n)
-{
-    qemu_del_timer(s->timer[n]);
-}
-
-static void gptm_reload(gptm_state *s, int n, int reset)
-{
-    int64_t tick;
-    if (reset)
-        tick = qemu_get_clock_ns(vm_clock);
-    else
-        tick = s->tick[n];
-
-    if (s->config == 0) {
-        /* 32-bit CountDown.  */
-        uint32_t count;
-        count = s->load[0] | (s->load[1] << 16);
-        tick += (int64_t)count * system_clock_scale;
-    } else if (s->config == 1) {
-        /* 32-bit RTC.  1Hz tick.  */
-        tick += get_ticks_per_sec();
-    } else if (s->mode[n] == 0xa) {
-        /* PWM mode.  Not implemented.  */
-    } else {
-        hw_error("TODO: 16-bit timer mode 0x%x\n", s->mode[n]);
-    }
-    s->tick[n] = tick;
-    qemu_mod_timer(s->timer[n], tick);
-}
-
-static void gptm_tick(void *opaque)
-{
-    gptm_state **p = (gptm_state **)opaque;
-    gptm_state *s;
-    int n;
-
-    s = *p;
-    n = p - s->opaque;
-    if (s->config == 0) {
-        s->state |= 1;
-        if ((s->control & 0x20)) {
-            /* Output trigger.  */
-	    qemu_irq_pulse(s->trigger);
-        }
-        if (s->mode[0] & 1) {
-            /* One-shot.  */
-            s->control &= ~1;
-        } else {
-            /* Periodic.  */
-            gptm_reload(s, 0, 0);
-        }
-    } else if (s->config == 1) {
-        /* RTC.  */
-        uint32_t match;
-        s->rtc++;
-        match = s->match[0] | (s->match[1] << 16);
-        if (s->rtc > match)
-            s->rtc = 0;
-        if (s->rtc == 0) {
-            s->state |= 8;
-        }
-        gptm_reload(s, 0, 0);
-    } else if (s->mode[n] == 0xa) {
-        /* PWM mode.  Not implemented.  */
-    } else {
-        hw_error("TODO: 16-bit timer mode 0x%x\n", s->mode[n]);
-    }
-    gptm_update_irq(s);
-}
-
-static uint64_t gptm_read(void *opaque, hwaddr offset,
-                          unsigned size)
-{
-    gptm_state *s = (gptm_state *)opaque;
-
-    switch (offset) {
-    case 0x00: /* CFG */
-        return s->config;
-    case 0x04: /* TAMR */
-        return s->mode[0];
-    case 0x08: /* TBMR */
-        return s->mode[1];
-    case 0x0c: /* CTL */
-        return s->control;
-    case 0x18: /* IMR */
-        return s->mask;
-    case 0x1c: /* RIS */
-        return s->state;
-    case 0x20: /* MIS */
-        return s->state & s->mask;
-    case 0x24: /* CR */
-        return 0;
-    case 0x28: /* TAILR */
-        return s->load[0] | ((s->config < 4) ? (s->load[1] << 16) : 0);
-    case 0x2c: /* TBILR */
-        return s->load[1];
-    case 0x30: /* TAMARCHR */
-        return s->match[0] | ((s->config < 4) ? (s->match[1] << 16) : 0);
-    case 0x34: /* TBMATCHR */
-        return s->match[1];
-    case 0x38: /* TAPR */
-        return s->prescale[0];
-    case 0x3c: /* TBPR */
-        return s->prescale[1];
-    case 0x40: /* TAPMR */
-        return s->match_prescale[0];
-    case 0x44: /* TBPMR */
-        return s->match_prescale[1];
-    case 0x48: /* TAR */
-        if (s->control == 1)
-            return s->rtc;
-    case 0x4c: /* TBR */
-        hw_error("TODO: Timer value read\n");
-    default:
-        hw_error("gptm_read: Bad offset 0x%x\n", (int)offset);
-        return 0;
-    }
-}
-
-static void gptm_write(void *opaque, hwaddr offset,
-                       uint64_t value, unsigned size)
-{
-    gptm_state *s = (gptm_state *)opaque;
-    uint32_t oldval;
-
-    /* The timers should be disabled before changing the configuration.
-       We take advantage of this and defer everything until the timer
-       is enabled.  */
-    switch (offset) {
-    case 0x00: /* CFG */
-        s->config = value;
-        break;
-    case 0x04: /* TAMR */
-        s->mode[0] = value;
-        break;
-    case 0x08: /* TBMR */
-        s->mode[1] = value;
-        break;
-    case 0x0c: /* CTL */
-        oldval = s->control;
-        s->control = value;
-        /* TODO: Implement pause.  */
-        if ((oldval ^ value) & 1) {
-            if (value & 1) {
-                gptm_reload(s, 0, 1);
-            } else {
-                gptm_stop(s, 0);
-            }
-        }
-        if (((oldval ^ value) & 0x100) && s->config >= 4) {
-            if (value & 0x100) {
-                gptm_reload(s, 1, 1);
-            } else {
-                gptm_stop(s, 1);
-            }
-        }
-        break;
-    case 0x18: /* IMR */
-        s->mask = value & 0x77;
-        gptm_update_irq(s);
-        break;
-    case 0x24: /* CR */
-        s->state &= ~value;
-        break;
-    case 0x28: /* TAILR */
-        s->load[0] = value & 0xffff;
-        if (s->config < 4) {
-            s->load[1] = value >> 16;
-        }
-        break;
-    case 0x2c: /* TBILR */
-        s->load[1] = value & 0xffff;
-        break;
-    case 0x30: /* TAMARCHR */
-        s->match[0] = value & 0xffff;
-        if (s->config < 4) {
-            s->match[1] = value >> 16;
-        }
-        break;
-    case 0x34: /* TBMATCHR */
-        s->match[1] = value >> 16;
-        break;
-    case 0x38: /* TAPR */
-        s->prescale[0] = value;
-        break;
-    case 0x3c: /* TBPR */
-        s->prescale[1] = value;
-        break;
-    case 0x40: /* TAPMR */
-        s->match_prescale[0] = value;
-        break;
-    case 0x44: /* TBPMR */
-        s->match_prescale[0] = value;
-        break;
-    default:
-        hw_error("gptm_write: Bad offset 0x%x\n", (int)offset);
-    }
-    gptm_update_irq(s);
-}
-
-static const MemoryRegionOps gptm_ops = {
-    .read = gptm_read,
-    .write = gptm_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-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_UNUSED(8),
-        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)
-{
-    gptm_state *s = FROM_SYSBUS(gptm_state, dev);
-
-    sysbus_init_irq(dev, &s->irq);
-    qdev_init_gpio_out(&dev->qdev, &s->trigger, 1);
-
-    memory_region_init_io(&s->iomem, &gptm_ops, s,
-                          "gptm", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    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]);
-    vmstate_register(&dev->qdev, -1, &vmstate_stellaris_gptm, s);
-    return 0;
-}
-
-
-/* System controller.  */
-
-typedef struct {
-    MemoryRegion iomem;
-    uint32_t pborctl;
-    uint32_t ldopctl;
-    uint32_t int_status;
-    uint32_t int_mask;
-    uint32_t resc;
-    uint32_t rcc;
-    uint32_t rcc2;
-    uint32_t rcgc[3];
-    uint32_t scgc[3];
-    uint32_t dcgc[3];
-    uint32_t clkvclr;
-    uint32_t ldoarst;
-    uint32_t user0;
-    uint32_t user1;
-    qemu_irq irq;
-    stellaris_board_info *board;
-} ssys_state;
-
-static void ssys_update(ssys_state *s)
-{
-  qemu_set_irq(s->irq, (s->int_status & s->int_mask) != 0);
-}
-
-static uint32_t pllcfg_sandstorm[16] = {
-    0x31c0, /* 1 Mhz */
-    0x1ae0, /* 1.8432 Mhz */
-    0x18c0, /* 2 Mhz */
-    0xd573, /* 2.4576 Mhz */
-    0x37a6, /* 3.57954 Mhz */
-    0x1ae2, /* 3.6864 Mhz */
-    0x0c40, /* 4 Mhz */
-    0x98bc, /* 4.906 Mhz */
-    0x935b, /* 4.9152 Mhz */
-    0x09c0, /* 5 Mhz */
-    0x4dee, /* 5.12 Mhz */
-    0x0c41, /* 6 Mhz */
-    0x75db, /* 6.144 Mhz */
-    0x1ae6, /* 7.3728 Mhz */
-    0x0600, /* 8 Mhz */
-    0x585b /* 8.192 Mhz */
-};
-
-static uint32_t pllcfg_fury[16] = {
-    0x3200, /* 1 Mhz */
-    0x1b20, /* 1.8432 Mhz */
-    0x1900, /* 2 Mhz */
-    0xf42b, /* 2.4576 Mhz */
-    0x37e3, /* 3.57954 Mhz */
-    0x1b21, /* 3.6864 Mhz */
-    0x0c80, /* 4 Mhz */
-    0x98ee, /* 4.906 Mhz */
-    0xd5b4, /* 4.9152 Mhz */
-    0x0a00, /* 5 Mhz */
-    0x4e27, /* 5.12 Mhz */
-    0x1902, /* 6 Mhz */
-    0xec1c, /* 6.144 Mhz */
-    0x1b23, /* 7.3728 Mhz */
-    0x0640, /* 8 Mhz */
-    0xb11c /* 8.192 Mhz */
-};
-
-#define DID0_VER_MASK        0x70000000
-#define DID0_VER_0           0x00000000
-#define DID0_VER_1           0x10000000
-
-#define DID0_CLASS_MASK      0x00FF0000
-#define DID0_CLASS_SANDSTORM 0x00000000
-#define DID0_CLASS_FURY      0x00010000
-
-static int ssys_board_class(const ssys_state *s)
-{
-    uint32_t did0 = s->board->did0;
-    switch (did0 & DID0_VER_MASK) {
-    case DID0_VER_0:
-        return DID0_CLASS_SANDSTORM;
-    case DID0_VER_1:
-        switch (did0 & DID0_CLASS_MASK) {
-        case DID0_CLASS_SANDSTORM:
-        case DID0_CLASS_FURY:
-            return did0 & DID0_CLASS_MASK;
-        }
-        /* for unknown classes, fall through */
-    default:
-        hw_error("ssys_board_class: Unknown class 0x%08x\n", did0);
-    }
-}
-
-static uint64_t ssys_read(void *opaque, hwaddr offset,
-                          unsigned size)
-{
-    ssys_state *s = (ssys_state *)opaque;
-
-    switch (offset) {
-    case 0x000: /* DID0 */
-        return s->board->did0;
-    case 0x004: /* DID1 */
-        return s->board->did1;
-    case 0x008: /* DC0 */
-        return s->board->dc0;
-    case 0x010: /* DC1 */
-        return s->board->dc1;
-    case 0x014: /* DC2 */
-        return s->board->dc2;
-    case 0x018: /* DC3 */
-        return s->board->dc3;
-    case 0x01c: /* DC4 */
-        return s->board->dc4;
-    case 0x030: /* PBORCTL */
-        return s->pborctl;
-    case 0x034: /* LDOPCTL */
-        return s->ldopctl;
-    case 0x040: /* SRCR0 */
-        return 0;
-    case 0x044: /* SRCR1 */
-        return 0;
-    case 0x048: /* SRCR2 */
-        return 0;
-    case 0x050: /* RIS */
-        return s->int_status;
-    case 0x054: /* IMC */
-        return s->int_mask;
-    case 0x058: /* MISC */
-        return s->int_status & s->int_mask;
-    case 0x05c: /* RESC */
-        return s->resc;
-    case 0x060: /* RCC */
-        return s->rcc;
-    case 0x064: /* PLLCFG */
-        {
-            int xtal;
-            xtal = (s->rcc >> 6) & 0xf;
-            switch (ssys_board_class(s)) {
-            case DID0_CLASS_FURY:
-                return pllcfg_fury[xtal];
-            case DID0_CLASS_SANDSTORM:
-                return pllcfg_sandstorm[xtal];
-            default:
-                hw_error("ssys_read: Unhandled class for PLLCFG read.\n");
-                return 0;
-            }
-        }
-    case 0x070: /* RCC2 */
-        return s->rcc2;
-    case 0x100: /* RCGC0 */
-        return s->rcgc[0];
-    case 0x104: /* RCGC1 */
-        return s->rcgc[1];
-    case 0x108: /* RCGC2 */
-        return s->rcgc[2];
-    case 0x110: /* SCGC0 */
-        return s->scgc[0];
-    case 0x114: /* SCGC1 */
-        return s->scgc[1];
-    case 0x118: /* SCGC2 */
-        return s->scgc[2];
-    case 0x120: /* DCGC0 */
-        return s->dcgc[0];
-    case 0x124: /* DCGC1 */
-        return s->dcgc[1];
-    case 0x128: /* DCGC2 */
-        return s->dcgc[2];
-    case 0x150: /* CLKVCLR */
-        return s->clkvclr;
-    case 0x160: /* LDOARST */
-        return s->ldoarst;
-    case 0x1e0: /* USER0 */
-        return s->user0;
-    case 0x1e4: /* USER1 */
-        return s->user1;
-    default:
-        hw_error("ssys_read: Bad offset 0x%x\n", (int)offset);
-        return 0;
-    }
-}
-
-static bool ssys_use_rcc2(ssys_state *s)
-{
-    return (s->rcc2 >> 31) & 0x1;
-}
-
-/*
- * Caculate the sys. clock period in ms.
- */
-static void ssys_calculate_system_clock(ssys_state *s)
-{
-    if (ssys_use_rcc2(s)) {
-        system_clock_scale = 5 * (((s->rcc2 >> 23) & 0x3f) + 1);
-    } else {
-        system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
-    }
-}
-
-static void ssys_write(void *opaque, hwaddr offset,
-                       uint64_t value, unsigned size)
-{
-    ssys_state *s = (ssys_state *)opaque;
-
-    switch (offset) {
-    case 0x030: /* PBORCTL */
-        s->pborctl = value & 0xffff;
-        break;
-    case 0x034: /* LDOPCTL */
-        s->ldopctl = value & 0x1f;
-        break;
-    case 0x040: /* SRCR0 */
-    case 0x044: /* SRCR1 */
-    case 0x048: /* SRCR2 */
-        fprintf(stderr, "Peripheral reset not implemented\n");
-        break;
-    case 0x054: /* IMC */
-        s->int_mask = value & 0x7f;
-        break;
-    case 0x058: /* MISC */
-        s->int_status &= ~value;
-        break;
-    case 0x05c: /* RESC */
-        s->resc = value & 0x3f;
-        break;
-    case 0x060: /* RCC */
-        if ((s->rcc & (1 << 13)) != 0 && (value & (1 << 13)) == 0) {
-            /* PLL enable.  */
-            s->int_status |= (1 << 6);
-        }
-        s->rcc = value;
-        ssys_calculate_system_clock(s);
-        break;
-    case 0x070: /* RCC2 */
-        if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) {
-            break;
-        }
-
-        if ((s->rcc2 & (1 << 13)) != 0 && (value & (1 << 13)) == 0) {
-            /* PLL enable.  */
-            s->int_status |= (1 << 6);
-        }
-        s->rcc2 = value;
-        ssys_calculate_system_clock(s);
-        break;
-    case 0x100: /* RCGC0 */
-        s->rcgc[0] = value;
-        break;
-    case 0x104: /* RCGC1 */
-        s->rcgc[1] = value;
-        break;
-    case 0x108: /* RCGC2 */
-        s->rcgc[2] = value;
-        break;
-    case 0x110: /* SCGC0 */
-        s->scgc[0] = value;
-        break;
-    case 0x114: /* SCGC1 */
-        s->scgc[1] = value;
-        break;
-    case 0x118: /* SCGC2 */
-        s->scgc[2] = value;
-        break;
-    case 0x120: /* DCGC0 */
-        s->dcgc[0] = value;
-        break;
-    case 0x124: /* DCGC1 */
-        s->dcgc[1] = value;
-        break;
-    case 0x128: /* DCGC2 */
-        s->dcgc[2] = value;
-        break;
-    case 0x150: /* CLKVCLR */
-        s->clkvclr = value;
-        break;
-    case 0x160: /* LDOARST */
-        s->ldoarst = value;
-        break;
-    default:
-        hw_error("ssys_write: Bad offset 0x%x\n", (int)offset);
-    }
-    ssys_update(s);
-}
-
-static const MemoryRegionOps ssys_ops = {
-    .read = ssys_read,
-    .write = ssys_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void ssys_reset(void *opaque)
-{
-    ssys_state *s = (ssys_state *)opaque;
-
-    s->pborctl = 0x7ffd;
-    s->rcc = 0x078e3ac0;
-
-    if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) {
-        s->rcc2 = 0;
-    } else {
-        s->rcc2 = 0x07802810;
-    }
-    s->rcgc[0] = 1;
-    s->scgc[0] = 1;
-    s->dcgc[0] = 1;
-    ssys_calculate_system_clock(s);
-}
-
-static int stellaris_sys_post_load(void *opaque, int version_id)
-{
-    ssys_state *s = opaque;
-
-    ssys_calculate_system_clock(s);
-
-    return 0;
-}
-
-static const VMStateDescription vmstate_stellaris_sys = {
-    .name = "stellaris_sys",
-    .version_id = 2,
-    .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_V(rcc2, ssys_state, 2),
-        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)
-{
-    ssys_state *s;
-
-    s = (ssys_state *)g_malloc0(sizeof(ssys_state));
-    s->irq = irq;
-    s->board = board;
-    /* Most devices come preprogrammed with a MAC address in the user data. */
-    s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16);
-    s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16);
-
-    memory_region_init_io(&s->iomem, &ssys_ops, s, "ssys", 0x00001000);
-    memory_region_add_subregion(get_system_memory(), base, &s->iomem);
-    ssys_reset(s);
-    vmstate_register(NULL, -1, &vmstate_stellaris_sys, s);
-    return 0;
-}
-
-
-/* I2C controller.  */
-
-typedef struct {
-    SysBusDevice busdev;
-    i2c_bus *bus;
-    qemu_irq irq;
-    MemoryRegion iomem;
-    uint32_t msa;
-    uint32_t mcs;
-    uint32_t mdr;
-    uint32_t mtpr;
-    uint32_t mimr;
-    uint32_t mris;
-    uint32_t mcr;
-} stellaris_i2c_state;
-
-#define STELLARIS_I2C_MCS_BUSY    0x01
-#define STELLARIS_I2C_MCS_ERROR   0x02
-#define STELLARIS_I2C_MCS_ADRACK  0x04
-#define STELLARIS_I2C_MCS_DATACK  0x08
-#define STELLARIS_I2C_MCS_ARBLST  0x10
-#define STELLARIS_I2C_MCS_IDLE    0x20
-#define STELLARIS_I2C_MCS_BUSBSY  0x40
-
-static uint64_t stellaris_i2c_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
-
-    switch (offset) {
-    case 0x00: /* MSA */
-        return s->msa;
-    case 0x04: /* MCS */
-        /* We don't emulate timing, so the controller is never busy.  */
-        return s->mcs | STELLARIS_I2C_MCS_IDLE;
-    case 0x08: /* MDR */
-        return s->mdr;
-    case 0x0c: /* MTPR */
-        return s->mtpr;
-    case 0x10: /* MIMR */
-        return s->mimr;
-    case 0x14: /* MRIS */
-        return s->mris;
-    case 0x18: /* MMIS */
-        return s->mris & s->mimr;
-    case 0x20: /* MCR */
-        return s->mcr;
-    default:
-        hw_error("strllaris_i2c_read: Bad offset 0x%x\n", (int)offset);
-        return 0;
-    }
-}
-
-static void stellaris_i2c_update(stellaris_i2c_state *s)
-{
-    int level;
-
-    level = (s->mris & s->mimr) != 0;
-    qemu_set_irq(s->irq, level);
-}
-
-static void stellaris_i2c_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-    stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
-
-    switch (offset) {
-    case 0x00: /* MSA */
-        s->msa = value & 0xff;
-        break;
-    case 0x04: /* MCS */
-        if ((s->mcr & 0x10) == 0) {
-            /* Disabled.  Do nothing.  */
-            break;
-        }
-        /* Grab the bus if this is starting a transfer.  */
-        if ((value & 2) && (s->mcs & STELLARIS_I2C_MCS_BUSBSY) == 0) {
-            if (i2c_start_transfer(s->bus, s->msa >> 1, s->msa & 1)) {
-                s->mcs |= STELLARIS_I2C_MCS_ARBLST;
-            } else {
-                s->mcs &= ~STELLARIS_I2C_MCS_ARBLST;
-                s->mcs |= STELLARIS_I2C_MCS_BUSBSY;
-            }
-        }
-        /* If we don't have the bus then indicate an error.  */
-        if (!i2c_bus_busy(s->bus)
-                || (s->mcs & STELLARIS_I2C_MCS_BUSBSY) == 0) {
-            s->mcs |= STELLARIS_I2C_MCS_ERROR;
-            break;
-        }
-        s->mcs &= ~STELLARIS_I2C_MCS_ERROR;
-        if (value & 1) {
-            /* Transfer a byte.  */
-            /* TODO: Handle errors.  */
-            if (s->msa & 1) {
-                /* Recv */
-                s->mdr = i2c_recv(s->bus) & 0xff;
-            } else {
-                /* Send */
-                i2c_send(s->bus, s->mdr);
-            }
-            /* Raise an interrupt.  */
-            s->mris |= 1;
-        }
-        if (value & 4) {
-            /* Finish transfer.  */
-            i2c_end_transfer(s->bus);
-            s->mcs &= ~STELLARIS_I2C_MCS_BUSBSY;
-        }
-        break;
-    case 0x08: /* MDR */
-        s->mdr = value & 0xff;
-        break;
-    case 0x0c: /* MTPR */
-        s->mtpr = value & 0xff;
-        break;
-    case 0x10: /* MIMR */
-        s->mimr = 1;
-        break;
-    case 0x1c: /* MICR */
-        s->mris &= ~value;
-        break;
-    case 0x20: /* MCR */
-        if (value & 1)
-            hw_error(
-                      "stellaris_i2c_write: Loopback not implemented\n");
-        if (value & 0x20)
-            hw_error(
-                      "stellaris_i2c_write: Slave mode not implemented\n");
-        s->mcr = value & 0x31;
-        break;
-    default:
-        hw_error("stellaris_i2c_write: Bad offset 0x%x\n",
-                  (int)offset);
-    }
-    stellaris_i2c_update(s);
-}
-
-static void stellaris_i2c_reset(stellaris_i2c_state *s)
-{
-    if (s->mcs & STELLARIS_I2C_MCS_BUSBSY)
-        i2c_end_transfer(s->bus);
-
-    s->msa = 0;
-    s->mcs = 0;
-    s->mdr = 0;
-    s->mtpr = 1;
-    s->mimr = 0;
-    s->mris = 0;
-    s->mcr = 0;
-    stellaris_i2c_update(s);
-}
-
-static const MemoryRegionOps stellaris_i2c_ops = {
-    .read = stellaris_i2c_read,
-    .write = stellaris_i2c_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-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)
-{
-    stellaris_i2c_state *s = FROM_SYSBUS(stellaris_i2c_state, dev);
-    i2c_bus *bus;
-
-    sysbus_init_irq(dev, &s->irq);
-    bus = i2c_init_bus(&dev->qdev, "i2c");
-    s->bus = bus;
-
-    memory_region_init_io(&s->iomem, &stellaris_i2c_ops, s,
-                          "i2c", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    /* ??? For now we only implement the master interface.  */
-    stellaris_i2c_reset(s);
-    vmstate_register(&dev->qdev, -1, &vmstate_stellaris_i2c, s);
-    return 0;
-}
-
-/* Analogue to Digital Converter.  This is only partially implemented,
-   enough for applications that use a combined ADC and timer tick.  */
-
-#define STELLARIS_ADC_EM_CONTROLLER 0
-#define STELLARIS_ADC_EM_COMP       1
-#define STELLARIS_ADC_EM_EXTERNAL   4
-#define STELLARIS_ADC_EM_TIMER      5
-#define STELLARIS_ADC_EM_PWM0       6
-#define STELLARIS_ADC_EM_PWM1       7
-#define STELLARIS_ADC_EM_PWM2       8
-
-#define STELLARIS_ADC_FIFO_EMPTY    0x0100
-#define STELLARIS_ADC_FIFO_FULL     0x1000
-
-typedef struct
-{
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint32_t actss;
-    uint32_t ris;
-    uint32_t im;
-    uint32_t emux;
-    uint32_t ostat;
-    uint32_t ustat;
-    uint32_t sspri;
-    uint32_t sac;
-    struct {
-        uint32_t state;
-        uint32_t data[16];
-    } fifo[4];
-    uint32_t ssmux[4];
-    uint32_t ssctl[4];
-    uint32_t noise;
-    qemu_irq irq[4];
-} stellaris_adc_state;
-
-static uint32_t stellaris_adc_fifo_read(stellaris_adc_state *s, int n)
-{
-    int tail;
-
-    tail = s->fifo[n].state & 0xf;
-    if (s->fifo[n].state & STELLARIS_ADC_FIFO_EMPTY) {
-        s->ustat |= 1 << n;
-    } else {
-        s->fifo[n].state = (s->fifo[n].state & ~0xf) | ((tail + 1) & 0xf);
-        s->fifo[n].state &= ~STELLARIS_ADC_FIFO_FULL;
-        if (tail + 1 == ((s->fifo[n].state >> 4) & 0xf))
-            s->fifo[n].state |= STELLARIS_ADC_FIFO_EMPTY;
-    }
-    return s->fifo[n].data[tail];
-}
-
-static void stellaris_adc_fifo_write(stellaris_adc_state *s, int n,
-                                     uint32_t value)
-{
-    int head;
-
-    /* TODO: Real hardware has limited size FIFOs.  We have a full 16 entry 
-       FIFO fir each sequencer.  */
-    head = (s->fifo[n].state >> 4) & 0xf;
-    if (s->fifo[n].state & STELLARIS_ADC_FIFO_FULL) {
-        s->ostat |= 1 << n;
-        return;
-    }
-    s->fifo[n].data[head] = value;
-    head = (head + 1) & 0xf;
-    s->fifo[n].state &= ~STELLARIS_ADC_FIFO_EMPTY;
-    s->fifo[n].state = (s->fifo[n].state & ~0xf0) | (head << 4);
-    if ((s->fifo[n].state & 0xf) == head)
-        s->fifo[n].state |= STELLARIS_ADC_FIFO_FULL;
-}
-
-static void stellaris_adc_update(stellaris_adc_state *s)
-{
-    int level;
-    int n;
-
-    for (n = 0; n < 4; n++) {
-        level = (s->ris & s->im & (1 << n)) != 0;
-        qemu_set_irq(s->irq[n], level);
-    }
-}
-
-static void stellaris_adc_trigger(void *opaque, int irq, int level)
-{
-    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
-    int n;
-
-    for (n = 0; n < 4; n++) {
-        if ((s->actss & (1 << n)) == 0) {
-            continue;
-        }
-
-        if (((s->emux >> (n * 4)) & 0xff) != 5) {
-            continue;
-        }
-
-        /* Some applications use the ADC as a random number source, so introduce
-           some variation into the signal.  */
-        s->noise = s->noise * 314159 + 1;
-        /* ??? actual inputs not implemented.  Return an arbitrary value.  */
-        stellaris_adc_fifo_write(s, n, 0x200 + ((s->noise >> 16) & 7));
-        s->ris |= (1 << n);
-        stellaris_adc_update(s);
-    }
-}
-
-static void stellaris_adc_reset(stellaris_adc_state *s)
-{
-    int n;
-
-    for (n = 0; n < 4; n++) {
-        s->ssmux[n] = 0;
-        s->ssctl[n] = 0;
-        s->fifo[n].state = STELLARIS_ADC_FIFO_EMPTY;
-    }
-}
-
-static uint64_t stellaris_adc_read(void *opaque, hwaddr offset,
-                                   unsigned size)
-{
-    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
-
-    /* TODO: Implement this.  */
-    if (offset >= 0x40 && offset < 0xc0) {
-        int n;
-        n = (offset - 0x40) >> 5;
-        switch (offset & 0x1f) {
-        case 0x00: /* SSMUX */
-            return s->ssmux[n];
-        case 0x04: /* SSCTL */
-            return s->ssctl[n];
-        case 0x08: /* SSFIFO */
-            return stellaris_adc_fifo_read(s, n);
-        case 0x0c: /* SSFSTAT */
-            return s->fifo[n].state;
-        default:
-            break;
-        }
-    }
-    switch (offset) {
-    case 0x00: /* ACTSS */
-        return s->actss;
-    case 0x04: /* RIS */
-        return s->ris;
-    case 0x08: /* IM */
-        return s->im;
-    case 0x0c: /* ISC */
-        return s->ris & s->im;
-    case 0x10: /* OSTAT */
-        return s->ostat;
-    case 0x14: /* EMUX */
-        return s->emux;
-    case 0x18: /* USTAT */
-        return s->ustat;
-    case 0x20: /* SSPRI */
-        return s->sspri;
-    case 0x30: /* SAC */
-        return s->sac;
-    default:
-        hw_error("strllaris_adc_read: Bad offset 0x%x\n",
-                  (int)offset);
-        return 0;
-    }
-}
-
-static void stellaris_adc_write(void *opaque, hwaddr offset,
-                                uint64_t value, unsigned size)
-{
-    stellaris_adc_state *s = (stellaris_adc_state *)opaque;
-
-    /* TODO: Implement this.  */
-    if (offset >= 0x40 && offset < 0xc0) {
-        int n;
-        n = (offset - 0x40) >> 5;
-        switch (offset & 0x1f) {
-        case 0x00: /* SSMUX */
-            s->ssmux[n] = value & 0x33333333;
-            return;
-        case 0x04: /* SSCTL */
-            if (value != 6) {
-                hw_error("ADC: Unimplemented sequence %" PRIx64 "\n",
-                          value);
-            }
-            s->ssctl[n] = value;
-            return;
-        default:
-            break;
-        }
-    }
-    switch (offset) {
-    case 0x00: /* ACTSS */
-        s->actss = value & 0xf;
-        break;
-    case 0x08: /* IM */
-        s->im = value;
-        break;
-    case 0x0c: /* ISC */
-        s->ris &= ~value;
-        break;
-    case 0x10: /* OSTAT */
-        s->ostat &= ~value;
-        break;
-    case 0x14: /* EMUX */
-        s->emux = value;
-        break;
-    case 0x18: /* USTAT */
-        s->ustat &= ~value;
-        break;
-    case 0x20: /* SSPRI */
-        s->sspri = value;
-        break;
-    case 0x28: /* PSSI */
-        hw_error("Not implemented:  ADC sample initiate\n");
-        break;
-    case 0x30: /* SAC */
-        s->sac = value;
-        break;
-    default:
-        hw_error("stellaris_adc_write: Bad offset 0x%x\n", (int)offset);
-    }
-    stellaris_adc_update(s);
-}
-
-static const MemoryRegionOps stellaris_adc_ops = {
-    .read = stellaris_adc_read,
-    .write = stellaris_adc_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-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()
-    }
-};
-
-static int stellaris_adc_init(SysBusDevice *dev)
-{
-    stellaris_adc_state *s = FROM_SYSBUS(stellaris_adc_state, dev);
-    int n;
-
-    for (n = 0; n < 4; n++) {
-        sysbus_init_irq(dev, &s->irq[n]);
-    }
-
-    memory_region_init_io(&s->iomem, &stellaris_adc_ops, s,
-                          "adc", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    stellaris_adc_reset(s);
-    qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1);
-    vmstate_register(&dev->qdev, -1, &vmstate_stellaris_adc, s);
-    return 0;
-}
-
-/* Board init.  */
-static stellaris_board_info stellaris_boards[] = {
-  { "LM3S811EVB",
-    0,
-    0x0032000e,
-    0x001f001f, /* dc0 */
-    0x001132bf,
-    0x01071013,
-    0x3f0f01ff,
-    0x0000001f,
-    BP_OLED_I2C
-  },
-  { "LM3S6965EVB",
-    0x10010002,
-    0x1073402e,
-    0x00ff007f, /* dc0 */
-    0x001133ff,
-    0x030f5317,
-    0x0f0f87ff,
-    0x5000007f,
-    BP_OLED_SSI | BP_GAMEPAD
-  }
-};
-
-static void stellaris_init(const char *kernel_filename, const char *cpu_model,
-                           stellaris_board_info *board)
-{
-    static const int uart_irq[] = {5, 6, 33, 34};
-    static const int timer_irq[] = {19, 21, 23, 35};
-    static const uint32_t gpio_addr[7] =
-      { 0x40004000, 0x40005000, 0x40006000, 0x40007000,
-        0x40024000, 0x40025000, 0x40026000};
-    static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31};
-
-    MemoryRegion *address_space_mem = get_system_memory();
-    qemu_irq *pic;
-    DeviceState *gpio_dev[7];
-    qemu_irq gpio_in[7][8];
-    qemu_irq gpio_out[7][8];
-    qemu_irq adc;
-    int sram_size;
-    int flash_size;
-    i2c_bus *i2c;
-    DeviceState *dev;
-    int i;
-    int j;
-
-    flash_size = ((board->dc0 & 0xffff) + 1) << 1;
-    sram_size = (board->dc0 >> 18) + 1;
-    pic = armv7m_init(address_space_mem,
-                      flash_size, sram_size, kernel_filename, cpu_model);
-
-    if (board->dc1 & (1 << 16)) {
-        dev = sysbus_create_varargs("stellaris-adc", 0x40038000,
-                                    pic[14], pic[15], pic[16], pic[17], NULL);
-        adc = qdev_get_gpio_in(dev, 0);
-    } else {
-        adc = NULL;
-    }
-    for (i = 0; i < 4; i++) {
-        if (board->dc2 & (0x10000 << i)) {
-            dev = sysbus_create_simple("stellaris-gptm",
-                                       0x40030000 + i * 0x1000,
-                                       pic[timer_irq[i]]);
-            /* TODO: This is incorrect, but we get away with it because
-               the ADC output is only ever pulsed.  */
-            qdev_connect_gpio_out(dev, 0, adc);
-        }
-    }
-
-    stellaris_sys_init(0x400fe000, pic[28], board, nd_table[0].macaddr.a);
-
-    for (i = 0; i < 7; i++) {
-        if (board->dc4 & (1 << 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);
-                gpio_out[i][j] = NULL;
-            }
-        }
-    }
-
-    if (board->dc2 & (1 << 12)) {
-        dev = sysbus_create_simple("stellaris-i2c", 0x40020000, pic[8]);
-        i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
-        if (board->peripherals & BP_OLED_I2C) {
-            i2c_create_slave(i2c, "ssd0303", 0x3d);
-        }
-    }
-
-    for (i = 0; i < 4; i++) {
-        if (board->dc2 & (1 << i)) {
-            sysbus_create_simple("pl011_luminary", 0x4000c000 + i * 0x1000,
-                                 pic[uart_irq[i]]);
-        }
-    }
-    if (board->dc2 & (1 << 4)) {
-        dev = sysbus_create_simple("pl022", 0x40008000, pic[7]);
-        if (board->peripherals & BP_OLED_SSI) {
-            void *bus;
-            DeviceState *sddev;
-            DeviceState *ssddev;
-
-            /* Some boards have both an OLED controller and SD card connected to
-             * the same SSI port, with the SD card chip select connected to a
-             * GPIO pin.  Technically the OLED chip select is connected to the
-             * SSI Fss pin.  We do not bother emulating that as both devices
-             * should never be selected simultaneously, and our OLED controller
-             * ignores stray 0xff commands that occur when deselecting the SD
-             * card.
-             */
-            bus = qdev_get_child_bus(dev, "ssi");
-
-            sddev = ssi_create_slave(bus, "ssi-sd");
-            ssddev = ssi_create_slave(bus, "ssd0323");
-            gpio_out[GPIO_D][0] = qemu_irq_split(qdev_get_gpio_in(sddev, 0),
-                                                 qdev_get_gpio_in(ssddev, 0));
-            gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 1);
-
-            /* Make sure the select pin is high.  */
-            qemu_irq_raise(gpio_out[GPIO_D][0]);
-        }
-    }
-    if (board->dc4 & (1 << 28)) {
-        DeviceState *enet;
-
-        qemu_check_nic_model(&nd_table[0], "stellaris");
-
-        enet = qdev_create(NULL, "stellaris_enet");
-        qdev_set_nic_properties(enet, &nd_table[0]);
-        qdev_init_nofail(enet);
-        sysbus_mmio_map(SYS_BUS_DEVICE(enet), 0, 0x40048000);
-        sysbus_connect_irq(SYS_BUS_DEVICE(enet), 0, pic[42]);
-    }
-    if (board->peripherals & BP_GAMEPAD) {
-        qemu_irq gpad_irq[5];
-        static const int gpad_keycode[5] = { 0xc8, 0xd0, 0xcb, 0xcd, 0x1d };
-
-        gpad_irq[0] = qemu_irq_invert(gpio_in[GPIO_E][0]); /* up */
-        gpad_irq[1] = qemu_irq_invert(gpio_in[GPIO_E][1]); /* down */
-        gpad_irq[2] = qemu_irq_invert(gpio_in[GPIO_E][2]); /* left */
-        gpad_irq[3] = qemu_irq_invert(gpio_in[GPIO_E][3]); /* right */
-        gpad_irq[4] = qemu_irq_invert(gpio_in[GPIO_F][1]); /* select */
-
-        stellaris_gamepad_init(5, gpad_irq, gpad_keycode);
-    }
-    for (i = 0; i < 7; i++) {
-        if (board->dc4 & (1 << i)) {
-            for (j = 0; j < 8; j++) {
-                if (gpio_out[i][j]) {
-                    qdev_connect_gpio_out(gpio_dev[i], j, gpio_out[i][j]);
-                }
-            }
-        }
-    }
-}
-
-/* FIXME: Figure out how to generate these from stellaris_boards.  */
-static void lm3s811evb_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    stellaris_init(kernel_filename, cpu_model, &stellaris_boards[0]);
-}
-
-static void lm3s6965evb_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    stellaris_init(kernel_filename, cpu_model, &stellaris_boards[1]);
-}
-
-static QEMUMachine lm3s811evb_machine = {
-    .name = "lm3s811evb",
-    .desc = "Stellaris LM3S811EVB",
-    .init = lm3s811evb_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine lm3s6965evb_machine = {
-    .name = "lm3s6965evb",
-    .desc = "Stellaris LM3S6965EVB",
-    .init = lm3s6965evb_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void stellaris_machine_init(void)
-{
-    qemu_register_machine(&lm3s811evb_machine);
-    qemu_register_machine(&lm3s6965evb_machine);
-}
-
-machine_init(stellaris_machine_init);
-
-static void stellaris_i2c_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = stellaris_i2c_init;
-}
-
-static const TypeInfo stellaris_i2c_info = {
-    .name          = "stellaris-i2c",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(stellaris_i2c_state),
-    .class_init    = stellaris_i2c_class_init,
-};
-
-static void stellaris_gptm_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = stellaris_gptm_init;
-}
-
-static const TypeInfo stellaris_gptm_info = {
-    .name          = "stellaris-gptm",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(gptm_state),
-    .class_init    = stellaris_gptm_class_init,
-};
-
-static void stellaris_adc_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
-    sdc->init = stellaris_adc_init;
-}
-
-static const TypeInfo stellaris_adc_info = {
-    .name          = "stellaris-adc",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(stellaris_adc_state),
-    .class_init    = stellaris_adc_class_init,
-};
-
-static void stellaris_register_types(void)
-{
-    type_register_static(&stellaris_i2c_info);
-    type_register_static(&stellaris_gptm_info);
-    type_register_static(&stellaris_adc_info);
-}
-
-type_init(stellaris_register_types)
diff --git a/hw/sun4m.c b/hw/sun4m.c
deleted file mode 100644
index 37bd041..0000000
--- a/hw/sun4m.c
+++ /dev/null
@@ -1,1936 +0,0 @@
-/*
- * QEMU Sun4m & Sun4d & Sun4c System Emulator
- *
- * Copyright (c) 2003-2005 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 "hw/sysbus.h"
-#include "qemu/timer.h"
-#include "hw/sun4m.h"
-#include "hw/nvram.h"
-#include "hw/sparc32_dma.h"
-#include "hw/fdc.h"
-#include "sysemu/sysemu.h"
-#include "net/net.h"
-#include "hw/boards.h"
-#include "hw/firmware_abi.h"
-#include "hw/esp.h"
-#include "hw/pc.h"
-#include "hw/isa.h"
-#include "hw/fw_cfg.h"
-#include "hw/escc.h"
-#include "hw/empty_slot.h"
-#include "hw/qdev-addr.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "sysemu/blockdev.h"
-#include "trace.h"
-
-/*
- * Sun4m architecture was used in the following machines:
- *
- * SPARCserver 6xxMP/xx
- * SPARCclassic (SPARCclassic Server)(SPARCstation LC) (4/15),
- * SPARCclassic X (4/10)
- * SPARCstation LX/ZX (4/30)
- * SPARCstation Voyager
- * SPARCstation 10/xx, SPARCserver 10/xx
- * SPARCstation 5, SPARCserver 5
- * SPARCstation 20/xx, SPARCserver 20
- * SPARCstation 4
- *
- * Sun4d architecture was used in the following machines:
- *
- * SPARCcenter 2000
- * SPARCserver 1000
- *
- * Sun4c architecture was used in the following machines:
- * SPARCstation 1/1+, SPARCserver 1/1+
- * SPARCstation SLC
- * SPARCstation IPC
- * SPARCstation ELC
- * SPARCstation IPX
- *
- * See for example: http://www.sunhelp.org/faq/sunref1.html
- */
-
-#define KERNEL_LOAD_ADDR     0x00004000
-#define CMDLINE_ADDR         0x007ff000
-#define INITRD_LOAD_ADDR     0x00800000
-#define PROM_SIZE_MAX        (1024 * 1024)
-#define PROM_VADDR           0xffd00000
-#define PROM_FILENAME        "openbios-sparc32"
-#define CFG_ADDR             0xd00000510ULL
-#define FW_CFG_SUN4M_DEPTH   (FW_CFG_ARCH_LOCAL + 0x00)
-
-#define MAX_CPUS 16
-#define MAX_PILS 16
-#define MAX_VSIMMS 4
-
-#define ESCC_CLOCK 4915200
-
-struct sun4m_hwdef {
-    hwaddr iommu_base, iommu_pad_base, iommu_pad_len, slavio_base;
-    hwaddr intctl_base, counter_base, nvram_base, ms_kb_base;
-    hwaddr serial_base, fd_base;
-    hwaddr afx_base, idreg_base, dma_base, esp_base, le_base;
-    hwaddr tcx_base, cs_base, apc_base, aux1_base, aux2_base;
-    hwaddr bpp_base, dbri_base, sx_base;
-    struct {
-        hwaddr reg_base, vram_base;
-    } vsimm[MAX_VSIMMS];
-    hwaddr ecc_base;
-    uint64_t max_mem;
-    const char * const default_cpu_model;
-    uint32_t ecc_version;
-    uint32_t iommu_version;
-    uint16_t machine_id;
-    uint8_t nvram_machine_id;
-};
-
-#define MAX_IOUNITS 5
-
-struct sun4d_hwdef {
-    hwaddr iounit_bases[MAX_IOUNITS], slavio_base;
-    hwaddr counter_base, nvram_base, ms_kb_base;
-    hwaddr serial_base;
-    hwaddr espdma_base, esp_base;
-    hwaddr ledma_base, le_base;
-    hwaddr tcx_base;
-    hwaddr sbi_base;
-    uint64_t max_mem;
-    const char * const default_cpu_model;
-    uint32_t iounit_version;
-    uint16_t machine_id;
-    uint8_t nvram_machine_id;
-};
-
-struct sun4c_hwdef {
-    hwaddr iommu_base, slavio_base;
-    hwaddr intctl_base, counter_base, nvram_base, ms_kb_base;
-    hwaddr serial_base, fd_base;
-    hwaddr idreg_base, dma_base, esp_base, le_base;
-    hwaddr tcx_base, aux1_base;
-    uint64_t max_mem;
-    const char * const default_cpu_model;
-    uint32_t iommu_version;
-    uint16_t machine_id;
-    uint8_t nvram_machine_id;
-};
-
-int DMA_get_channel_mode (int nchan)
-{
-    return 0;
-}
-int DMA_read_memory (int nchan, void *buf, int pos, int size)
-{
-    return 0;
-}
-int DMA_write_memory (int nchan, void *buf, int pos, int size)
-{
-    return 0;
-}
-void DMA_hold_DREQ (int nchan) {}
-void DMA_release_DREQ (int nchan) {}
-void DMA_schedule(int nchan) {}
-
-void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
-{
-}
-
-void DMA_register_channel (int nchan,
-                           DMA_transfer_handler transfer_handler,
-                           void *opaque)
-{
-}
-
-static int fw_cfg_boot_set(void *opaque, const char *boot_device)
-{
-    fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
-    return 0;
-}
-
-static void nvram_init(M48t59State *nvram, uint8_t *macaddr,
-                       const char *cmdline, const char *boot_devices,
-                       ram_addr_t RAM_size, uint32_t kernel_size,
-                       int width, int height, int depth,
-                       int nvram_machine_id, const char *arch)
-{
-    unsigned int i;
-    uint32_t start, end;
-    uint8_t image[0x1ff0];
-    struct OpenBIOS_nvpart_v1 *part_header;
-
-    memset(image, '\0', sizeof(image));
-
-    start = 0;
-
-    // OpenBIOS nvram variables
-    // Variable partition
-    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
-    part_header->signature = OPENBIOS_PART_SYSTEM;
-    pstrcpy(part_header->name, sizeof(part_header->name), "system");
-
-    end = start + sizeof(struct OpenBIOS_nvpart_v1);
-    for (i = 0; i < nb_prom_envs; i++)
-        end = OpenBIOS_set_var(image, end, prom_envs[i]);
-
-    // End marker
-    image[end++] = '\0';
-
-    end = start + ((end - start + 15) & ~15);
-    OpenBIOS_finish_partition(part_header, end - start);
-
-    // free partition
-    start = end;
-    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
-    part_header->signature = OPENBIOS_PART_FREE;
-    pstrcpy(part_header->name, sizeof(part_header->name), "free");
-
-    end = 0x1fd0;
-    OpenBIOS_finish_partition(part_header, end - start);
-
-    Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr,
-                    nvram_machine_id);
-
-    for (i = 0; i < sizeof(image); i++)
-        m48t59_write(nvram, i, image[i]);
-}
-
-static DeviceState *slavio_intctl;
-
-void sun4m_pic_info(Monitor *mon, const QDict *qdict)
-{
-    if (slavio_intctl)
-        slavio_pic_info(mon, slavio_intctl);
-}
-
-void sun4m_irq_info(Monitor *mon, const QDict *qdict)
-{
-    if (slavio_intctl)
-        slavio_irq_info(mon, slavio_intctl);
-}
-
-void cpu_check_irqs(CPUSPARCState *env)
-{
-    if (env->pil_in && (env->interrupt_index == 0 ||
-                        (env->interrupt_index & ~15) == TT_EXTINT)) {
-        unsigned int i;
-
-        for (i = 15; i > 0; i--) {
-            if (env->pil_in & (1 << i)) {
-                int old_interrupt = env->interrupt_index;
-
-                env->interrupt_index = TT_EXTINT | i;
-                if (old_interrupt != env->interrupt_index) {
-                    trace_sun4m_cpu_interrupt(i);
-                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
-                }
-                break;
-            }
-        }
-    } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
-        trace_sun4m_cpu_reset_interrupt(env->interrupt_index & 15);
-        env->interrupt_index = 0;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-}
-
-static void cpu_kick_irq(SPARCCPU *cpu)
-{
-    CPUSPARCState *env = &cpu->env;
-
-    env->halted = 0;
-    cpu_check_irqs(env);
-    qemu_cpu_kick(CPU(cpu));
-}
-
-static void cpu_set_irq(void *opaque, int irq, int level)
-{
-    SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
-
-    if (level) {
-        trace_sun4m_cpu_set_irq_raise(irq);
-        env->pil_in |= 1 << irq;
-        cpu_kick_irq(cpu);
-    } else {
-        trace_sun4m_cpu_set_irq_lower(irq);
-        env->pil_in &= ~(1 << irq);
-        cpu_check_irqs(env);
-    }
-}
-
-static void dummy_cpu_set_irq(void *opaque, int irq, int level)
-{
-}
-
-static void main_cpu_reset(void *opaque)
-{
-    SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
-
-    cpu_reset(CPU(cpu));
-    env->halted = 0;
-}
-
-static void secondary_cpu_reset(void *opaque)
-{
-    SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
-
-    cpu_reset(CPU(cpu));
-    env->halted = 1;
-}
-
-static void cpu_halt_signal(void *opaque, int irq, int level)
-{
-    if (level && cpu_single_env)
-        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
-}
-
-static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
-{
-    return addr - 0xf0000000ULL;
-}
-
-static unsigned long sun4m_load_kernel(const char *kernel_filename,
-                                       const char *initrd_filename,
-                                       ram_addr_t RAM_size)
-{
-    int linux_boot;
-    unsigned int i;
-    long initrd_size, kernel_size;
-    uint8_t *ptr;
-
-    linux_boot = (kernel_filename != NULL);
-
-    kernel_size = 0;
-    if (linux_boot) {
-        int bswap_needed;
-
-#ifdef BSWAP_NEEDED
-        bswap_needed = 1;
-#else
-        bswap_needed = 0;
-#endif
-        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
-                               NULL, NULL, NULL, 1, ELF_MACHINE, 0);
-        if (kernel_size < 0)
-            kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
-                                    RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
-                                    TARGET_PAGE_SIZE);
-        if (kernel_size < 0)
-            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",
-                    kernel_filename);
-            exit(1);
-        }
-
-        /* load initrd */
-        initrd_size = 0;
-        if (initrd_filename) {
-            initrd_size = load_image_targphys(initrd_filename,
-                                              INITRD_LOAD_ADDR,
-                                              RAM_size - INITRD_LOAD_ADDR);
-            if (initrd_size < 0) {
-                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
-                        initrd_filename);
-                exit(1);
-            }
-        }
-        if (initrd_size > 0) {
-            for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
-                ptr = rom_ptr(KERNEL_LOAD_ADDR + i);
-                if (ldl_p(ptr) == 0x48647253) { // HdrS
-                    stl_p(ptr + 16, INITRD_LOAD_ADDR);
-                    stl_p(ptr + 20, initrd_size);
-                    break;
-                }
-            }
-        }
-    }
-    return kernel_size;
-}
-
-static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "iommu");
-    qdev_prop_set_uint32(dev, "version", version);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_connect_irq(s, 0, irq);
-    sysbus_mmio_map(s, 0, addr);
-
-    return s;
-}
-
-static void *sparc32_dma_init(hwaddr daddr, qemu_irq parent_irq,
-                              void *iommu, qemu_irq *dev_irq, int is_ledma)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "sparc32_dma");
-    qdev_prop_set_ptr(dev, "iommu_opaque", iommu);
-    qdev_prop_set_uint32(dev, "is_ledma", is_ledma);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_connect_irq(s, 0, parent_irq);
-    *dev_irq = qdev_get_gpio_in(dev, 0);
-    sysbus_mmio_map(s, 0, daddr);
-
-    return s;
-}
-
-static void lance_init(NICInfo *nd, hwaddr leaddr,
-                       void *dma_opaque, qemu_irq irq)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    qemu_irq reset;
-
-    qemu_check_nic_model(&nd_table[0], "lance");
-
-    dev = qdev_create(NULL, "lance");
-    qdev_set_nic_properties(dev, nd);
-    qdev_prop_set_ptr(dev, "dma", dma_opaque);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(s, 0, leaddr);
-    sysbus_connect_irq(s, 0, irq);
-    reset = qdev_get_gpio_in(dev, 0);
-    qdev_connect_gpio_out(dma_opaque, 0, reset);
-}
-
-static DeviceState *slavio_intctl_init(hwaddr addr,
-                                       hwaddr addrg,
-                                       qemu_irq **parent_irq)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    unsigned int i, j;
-
-    dev = qdev_create(NULL, "slavio_intctl");
-    qdev_init_nofail(dev);
-
-    s = SYS_BUS_DEVICE(dev);
-
-    for (i = 0; i < MAX_CPUS; i++) {
-        for (j = 0; j < MAX_PILS; j++) {
-            sysbus_connect_irq(s, i * MAX_PILS + j, parent_irq[i][j]);
-        }
-    }
-    sysbus_mmio_map(s, 0, addrg);
-    for (i = 0; i < MAX_CPUS; i++) {
-        sysbus_mmio_map(s, i + 1, addr + i * TARGET_PAGE_SIZE);
-    }
-
-    return dev;
-}
-
-#define SYS_TIMER_OFFSET      0x10000ULL
-#define CPU_TIMER_OFFSET(cpu) (0x1000ULL * cpu)
-
-static void slavio_timer_init_all(hwaddr addr, qemu_irq master_irq,
-                                  qemu_irq *cpu_irqs, unsigned int num_cpus)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    unsigned int i;
-
-    dev = qdev_create(NULL, "slavio_timer");
-    qdev_prop_set_uint32(dev, "num_cpus", num_cpus);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_connect_irq(s, 0, master_irq);
-    sysbus_mmio_map(s, 0, addr + SYS_TIMER_OFFSET);
-
-    for (i = 0; i < MAX_CPUS; i++) {
-        sysbus_mmio_map(s, i + 1, addr + (hwaddr)CPU_TIMER_OFFSET(i));
-        sysbus_connect_irq(s, i + 1, cpu_irqs[i]);
-    }
-}
-
-static qemu_irq  slavio_system_powerdown;
-
-static void slavio_powerdown_req(Notifier *n, void *opaque)
-{
-    qemu_irq_raise(slavio_system_powerdown);
-}
-
-static Notifier slavio_system_powerdown_notifier = {
-    .notify = slavio_powerdown_req
-};
-
-#define MISC_LEDS 0x01600000
-#define MISC_CFG  0x01800000
-#define MISC_DIAG 0x01a00000
-#define MISC_MDM  0x01b00000
-#define MISC_SYS  0x01f00000
-
-static void slavio_misc_init(hwaddr base,
-                             hwaddr aux1_base,
-                             hwaddr aux2_base, qemu_irq irq,
-                             qemu_irq fdc_tc)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "slavio_misc");
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    if (base) {
-        /* 8 bit registers */
-        /* Slavio control */
-        sysbus_mmio_map(s, 0, base + MISC_CFG);
-        /* Diagnostics */
-        sysbus_mmio_map(s, 1, base + MISC_DIAG);
-        /* Modem control */
-        sysbus_mmio_map(s, 2, base + MISC_MDM);
-        /* 16 bit registers */
-        /* ss600mp diag LEDs */
-        sysbus_mmio_map(s, 3, base + MISC_LEDS);
-        /* 32 bit registers */
-        /* System control */
-        sysbus_mmio_map(s, 4, base + MISC_SYS);
-    }
-    if (aux1_base) {
-        /* AUX 1 (Misc System Functions) */
-        sysbus_mmio_map(s, 5, aux1_base);
-    }
-    if (aux2_base) {
-        /* AUX 2 (Software Powerdown Control) */
-        sysbus_mmio_map(s, 6, aux2_base);
-    }
-    sysbus_connect_irq(s, 0, irq);
-    sysbus_connect_irq(s, 1, fdc_tc);
-    slavio_system_powerdown = qdev_get_gpio_in(dev, 0);
-    qemu_register_powerdown_notifier(&slavio_system_powerdown_notifier);
-}
-
-static void ecc_init(hwaddr base, qemu_irq irq, uint32_t version)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "eccmemctl");
-    qdev_prop_set_uint32(dev, "version", version);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_connect_irq(s, 0, irq);
-    sysbus_mmio_map(s, 0, base);
-    if (version == 0) { // SS-600MP only
-        sysbus_mmio_map(s, 1, base + 0x1000);
-    }
-}
-
-static void apc_init(hwaddr power_base, qemu_irq cpu_halt)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "apc");
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    /* Power management (APC) XXX: not a Slavio device */
-    sysbus_mmio_map(s, 0, power_base);
-    sysbus_connect_irq(s, 0, cpu_halt);
-}
-
-static void tcx_init(hwaddr addr, int vram_size, int width,
-                     int height, int depth)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "SUNW,tcx");
-    qdev_prop_set_taddr(dev, "addr", addr);
-    qdev_prop_set_uint32(dev, "vram_size", vram_size);
-    qdev_prop_set_uint16(dev, "width", width);
-    qdev_prop_set_uint16(dev, "height", height);
-    qdev_prop_set_uint16(dev, "depth", depth);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    /* 8-bit plane */
-    sysbus_mmio_map(s, 0, addr + 0x00800000ULL);
-    /* DAC */
-    sysbus_mmio_map(s, 1, addr + 0x00200000ULL);
-    /* TEC (dummy) */
-    sysbus_mmio_map(s, 2, addr + 0x00700000ULL);
-    /* THC 24 bit: NetBSD writes here even with 8-bit display: dummy */
-    sysbus_mmio_map(s, 3, addr + 0x00301000ULL);
-    if (depth == 24) {
-        /* 24-bit plane */
-        sysbus_mmio_map(s, 4, addr + 0x02000000ULL);
-        /* Control plane */
-        sysbus_mmio_map(s, 5, addr + 0x0a000000ULL);
-    } else {
-        /* THC 8 bit (dummy) */
-        sysbus_mmio_map(s, 4, addr + 0x00300000ULL);
-    }
-}
-
-/* NCR89C100/MACIO Internal ID register */
-static const uint8_t idreg_data[] = { 0xfe, 0x81, 0x01, 0x03 };
-
-static void idreg_init(hwaddr addr)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "macio_idreg");
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-
-    sysbus_mmio_map(s, 0, addr);
-    cpu_physical_memory_write_rom(addr, idreg_data, sizeof(idreg_data));
-}
-
-typedef struct IDRegState {
-    SysBusDevice busdev;
-    MemoryRegion mem;
-} IDRegState;
-
-static int idreg_init1(SysBusDevice *dev)
-{
-    IDRegState *s = FROM_SYSBUS(IDRegState, dev);
-
-    memory_region_init_ram(&s->mem, "sun4m.idreg", sizeof(idreg_data));
-    vmstate_register_ram_global(&s->mem);
-    memory_region_set_readonly(&s->mem, true);
-    sysbus_init_mmio(dev, &s->mem);
-    return 0;
-}
-
-static void idreg_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = idreg_init1;
-}
-
-static const TypeInfo idreg_info = {
-    .name          = "macio_idreg",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(IDRegState),
-    .class_init    = idreg_class_init,
-};
-
-typedef struct AFXState {
-    SysBusDevice busdev;
-    MemoryRegion mem;
-} AFXState;
-
-/* SS-5 TCX AFX register */
-static void afx_init(hwaddr addr)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    dev = qdev_create(NULL, "tcx_afx");
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-
-    sysbus_mmio_map(s, 0, addr);
-}
-
-static int afx_init1(SysBusDevice *dev)
-{
-    AFXState *s = FROM_SYSBUS(AFXState, dev);
-
-    memory_region_init_ram(&s->mem, "sun4m.afx", 4);
-    vmstate_register_ram_global(&s->mem);
-    sysbus_init_mmio(dev, &s->mem);
-    return 0;
-}
-
-static void afx_class_init(ObjectClass *klass, void *data)
-{
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = afx_init1;
-}
-
-static const TypeInfo afx_info = {
-    .name          = "tcx_afx",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(AFXState),
-    .class_init    = afx_class_init,
-};
-
-typedef struct PROMState {
-    SysBusDevice busdev;
-    MemoryRegion prom;
-} PROMState;
-
-/* Boot PROM (OpenBIOS) */
-static uint64_t translate_prom_address(void *opaque, uint64_t addr)
-{
-    hwaddr *base_addr = (hwaddr *)opaque;
-    return addr + *base_addr - PROM_VADDR;
-}
-
-static void prom_init(hwaddr addr, const char *bios_name)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    char *filename;
-    int ret;
-
-    dev = qdev_create(NULL, "openprom");
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-
-    sysbus_mmio_map(s, 0, addr);
-
-    /* load boot prom */
-    if (bios_name == NULL) {
-        bios_name = PROM_FILENAME;
-    }
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-    if (filename) {
-        ret = load_elf(filename, translate_prom_address, &addr, NULL,
-                       NULL, NULL, 1, ELF_MACHINE, 0);
-        if (ret < 0 || ret > PROM_SIZE_MAX) {
-            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
-        }
-        g_free(filename);
-    } else {
-        ret = -1;
-    }
-    if (ret < 0 || ret > PROM_SIZE_MAX) {
-        fprintf(stderr, "qemu: could not load prom '%s'\n", bios_name);
-        exit(1);
-    }
-}
-
-static int prom_init1(SysBusDevice *dev)
-{
-    PROMState *s = FROM_SYSBUS(PROMState, dev);
-
-    memory_region_init_ram(&s->prom, "sun4m.prom", PROM_SIZE_MAX);
-    vmstate_register_ram_global(&s->prom);
-    memory_region_set_readonly(&s->prom, true);
-    sysbus_init_mmio(dev, &s->prom);
-    return 0;
-}
-
-static Property prom_properties[] = {
-    {/* end of property list */},
-};
-
-static void prom_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = prom_init1;
-    dc->props = prom_properties;
-}
-
-static const TypeInfo prom_info = {
-    .name          = "openprom",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(PROMState),
-    .class_init    = prom_class_init,
-};
-
-typedef struct RamDevice
-{
-    SysBusDevice busdev;
-    MemoryRegion ram;
-    uint64_t size;
-} RamDevice;
-
-/* System RAM */
-static int ram_init1(SysBusDevice *dev)
-{
-    RamDevice *d = FROM_SYSBUS(RamDevice, dev);
-
-    memory_region_init_ram(&d->ram, "sun4m.ram", d->size);
-    vmstate_register_ram_global(&d->ram);
-    sysbus_init_mmio(dev, &d->ram);
-    return 0;
-}
-
-static void ram_init(hwaddr addr, ram_addr_t RAM_size,
-                     uint64_t max_mem)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    RamDevice *d;
-
-    /* allocate RAM */
-    if ((uint64_t)RAM_size > max_mem) {
-        fprintf(stderr,
-                "qemu: Too much memory for this machine: %d, maximum %d\n",
-                (unsigned int)(RAM_size / (1024 * 1024)),
-                (unsigned int)(max_mem / (1024 * 1024)));
-        exit(1);
-    }
-    dev = qdev_create(NULL, "memory");
-    s = SYS_BUS_DEVICE(dev);
-
-    d = FROM_SYSBUS(RamDevice, s);
-    d->size = RAM_size;
-    qdev_init_nofail(dev);
-
-    sysbus_mmio_map(s, 0, addr);
-}
-
-static Property ram_properties[] = {
-    DEFINE_PROP_UINT64("size", RamDevice, size, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void ram_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = ram_init1;
-    dc->props = ram_properties;
-}
-
-static const TypeInfo ram_info = {
-    .name          = "memory",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(RamDevice),
-    .class_init    = ram_class_init,
-};
-
-static void cpu_devinit(const char *cpu_model, unsigned int id,
-                        uint64_t prom_addr, qemu_irq **cpu_irqs)
-{
-    SPARCCPU *cpu;
-    CPUSPARCState *env;
-
-    cpu = cpu_sparc_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    cpu_sparc_set_id(env, id);
-    if (id == 0) {
-        qemu_register_reset(main_cpu_reset, cpu);
-    } else {
-        qemu_register_reset(secondary_cpu_reset, cpu);
-        env->halted = 1;
-    }
-    *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, cpu, MAX_PILS);
-    env->prom_addr = prom_addr;
-}
-
-static void dummy_fdc_tc(void *opaque, int irq, int level)
-{
-}
-
-static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, 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)
-{
-    unsigned int i;
-    void *iommu, *espdma, *ledma, *nvram;
-    qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS],
-        espdma_irq, ledma_irq;
-    qemu_irq esp_reset, dma_enable;
-    qemu_irq fdc_tc;
-    qemu_irq *cpu_halt;
-    unsigned long kernel_size;
-    DriveInfo *fd[MAX_FD];
-    void *fw_cfg;
-    unsigned int num_vsimms;
-
-    /* init CPUs */
-    if (!cpu_model)
-        cpu_model = hwdef->default_cpu_model;
-
-    for(i = 0; i < smp_cpus; i++) {
-        cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]);
-    }
-
-    for (i = smp_cpus; i < MAX_CPUS; i++)
-        cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS);
-
-
-    /* set up devices */
-    ram_init(0, RAM_size, hwdef->max_mem);
-    /* models without ECC don't trap when missing ram is accessed */
-    if (!hwdef->ecc_base) {
-        empty_slot_init(RAM_size, hwdef->max_mem - RAM_size);
-    }
-
-    prom_init(hwdef->slavio_base, bios_name);
-
-    slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
-                                       hwdef->intctl_base + 0x10000ULL,
-                                       cpu_irqs);
-
-    for (i = 0; i < 32; i++) {
-        slavio_irq[i] = qdev_get_gpio_in(slavio_intctl, i);
-    }
-    for (i = 0; i < MAX_CPUS; i++) {
-        slavio_cpu_irq[i] = qdev_get_gpio_in(slavio_intctl, 32 + i);
-    }
-
-    if (hwdef->idreg_base) {
-        idreg_init(hwdef->idreg_base);
-    }
-
-    if (hwdef->afx_base) {
-        afx_init(hwdef->afx_base);
-    }
-
-    iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
-                       slavio_irq[30]);
-
-    if (hwdef->iommu_pad_base) {
-        /* On the real hardware (SS-5, LX) the MMU is not padded, but aliased.
-           Software shouldn't use aliased addresses, neither should it crash
-           when does. Using empty_slot instead of aliasing can help with
-           debugging such accesses */
-        empty_slot_init(hwdef->iommu_pad_base,hwdef->iommu_pad_len);
-    }
-
-    espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[18],
-                              iommu, &espdma_irq, 0);
-
-    ledma = sparc32_dma_init(hwdef->dma_base + 16ULL,
-                             slavio_irq[16], iommu, &ledma_irq, 1);
-
-    if (graphic_depth != 8 && graphic_depth != 24) {
-        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
-        exit (1);
-    }
-    num_vsimms = 0;
-    if (num_vsimms == 0) {
-        tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height,
-                 graphic_depth);
-    }
-
-    for (i = num_vsimms; i < MAX_VSIMMS; i++) {
-        /* vsimm registers probed by OBP */
-        if (hwdef->vsimm[i].reg_base) {
-            empty_slot_init(hwdef->vsimm[i].reg_base, 0x2000);
-        }
-    }
-
-    if (hwdef->sx_base) {
-        empty_slot_init(hwdef->sx_base, 0x2000);
-    }
-
-    lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq);
-
-    nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x2000, 8);
-
-    slavio_timer_init_all(hwdef->counter_base, slavio_irq[19], slavio_cpu_irq, smp_cpus);
-
-    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[14],
-                              display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
-    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
-       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
-    escc_init(hwdef->serial_base, slavio_irq[15], slavio_irq[15],
-              serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);
-
-    cpu_halt = qemu_allocate_irqs(cpu_halt_signal, NULL, 1);
-    if (hwdef->apc_base) {
-        apc_init(hwdef->apc_base, cpu_halt[0]);
-    }
-
-    if (hwdef->fd_base) {
-        /* there is zero or one floppy drive */
-        memset(fd, 0, sizeof(fd));
-        fd[0] = drive_get(IF_FLOPPY, 0, 0);
-        sun4m_fdctrl_init(slavio_irq[22], hwdef->fd_base, fd,
-                          &fdc_tc);
-    } else {
-        fdc_tc = *qemu_allocate_irqs(dummy_fdc_tc, NULL, 1);
-    }
-
-    slavio_misc_init(hwdef->slavio_base, hwdef->aux1_base, hwdef->aux2_base,
-                     slavio_irq[30], fdc_tc);
-
-    if (drive_get_max_bus(IF_SCSI) > 0) {
-        fprintf(stderr, "qemu: too many SCSI bus\n");
-        exit(1);
-    }
-
-    esp_init(hwdef->esp_base, 2,
-             espdma_memory_read, espdma_memory_write,
-             espdma, espdma_irq, &esp_reset, &dma_enable);
-
-    qdev_connect_gpio_out(espdma, 0, esp_reset);
-    qdev_connect_gpio_out(espdma, 1, dma_enable);
-
-    if (hwdef->cs_base) {
-        sysbus_create_simple("SUNW,CS4231", hwdef->cs_base,
-                             slavio_irq[5]);
-    }
-
-    if (hwdef->dbri_base) {
-        /* ISDN chip with attached CS4215 audio codec */
-        /* prom space */
-        empty_slot_init(hwdef->dbri_base+0x1000, 0x30);
-        /* reg space */
-        empty_slot_init(hwdef->dbri_base+0x10000, 0x100);
-    }
-
-    if (hwdef->bpp_base) {
-        /* parallel port */
-        empty_slot_init(hwdef->bpp_base, 0x20);
-    }
-
-    kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename,
-                                    RAM_size);
-
-    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
-               boot_device, RAM_size, kernel_size, graphic_width,
-               graphic_height, graphic_depth, hwdef->nvram_machine_id,
-               "Sun4m");
-
-    if (hwdef->ecc_base)
-        ecc_init(hwdef->ecc_base, slavio_irq[28],
-                 hwdef->ecc_version);
-
-    fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
-    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
-    if (kernel_cmdline) {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
-        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
-        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
-        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
-                       strlen(kernel_cmdline) + 1);
-    } else {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
-        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
-    }
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used
-    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device[0]);
-    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
-}
-
-enum {
-    ss2_id = 0,
-    ss5_id = 32,
-    vger_id,
-    lx_id,
-    ss4_id,
-    scls_id,
-    sbook_id,
-    ss10_id = 64,
-    ss20_id,
-    ss600mp_id,
-    ss1000_id = 96,
-    ss2000_id,
-};
-
-static const struct sun4m_hwdef sun4m_hwdefs[] = {
-    /* SS-5 */
-    {
-        .iommu_base   = 0x10000000,
-        .iommu_pad_base = 0x10004000,
-        .iommu_pad_len  = 0x0fffb000,
-        .tcx_base     = 0x50000000,
-        .cs_base      = 0x6c000000,
-        .slavio_base  = 0x70000000,
-        .ms_kb_base   = 0x71000000,
-        .serial_base  = 0x71100000,
-        .nvram_base   = 0x71200000,
-        .fd_base      = 0x71400000,
-        .counter_base = 0x71d00000,
-        .intctl_base  = 0x71e00000,
-        .idreg_base   = 0x78000000,
-        .dma_base     = 0x78400000,
-        .esp_base     = 0x78800000,
-        .le_base      = 0x78c00000,
-        .apc_base     = 0x6a000000,
-        .afx_base     = 0x6e000000,
-        .aux1_base    = 0x71900000,
-        .aux2_base    = 0x71910000,
-        .nvram_machine_id = 0x80,
-        .machine_id = ss5_id,
-        .iommu_version = 0x05000000,
-        .max_mem = 0x10000000,
-        .default_cpu_model = "Fujitsu MB86904",
-    },
-    /* SS-10 */
-    {
-        .iommu_base   = 0xfe0000000ULL,
-        .tcx_base     = 0xe20000000ULL,
-        .slavio_base  = 0xff0000000ULL,
-        .ms_kb_base   = 0xff1000000ULL,
-        .serial_base  = 0xff1100000ULL,
-        .nvram_base   = 0xff1200000ULL,
-        .fd_base      = 0xff1700000ULL,
-        .counter_base = 0xff1300000ULL,
-        .intctl_base  = 0xff1400000ULL,
-        .idreg_base   = 0xef0000000ULL,
-        .dma_base     = 0xef0400000ULL,
-        .esp_base     = 0xef0800000ULL,
-        .le_base      = 0xef0c00000ULL,
-        .apc_base     = 0xefa000000ULL, // XXX should not exist
-        .aux1_base    = 0xff1800000ULL,
-        .aux2_base    = 0xff1a01000ULL,
-        .ecc_base     = 0xf00000000ULL,
-        .ecc_version  = 0x10000000, // version 0, implementation 1
-        .nvram_machine_id = 0x72,
-        .machine_id = ss10_id,
-        .iommu_version = 0x03000000,
-        .max_mem = 0xf00000000ULL,
-        .default_cpu_model = "TI SuperSparc II",
-    },
-    /* SS-600MP */
-    {
-        .iommu_base   = 0xfe0000000ULL,
-        .tcx_base     = 0xe20000000ULL,
-        .slavio_base  = 0xff0000000ULL,
-        .ms_kb_base   = 0xff1000000ULL,
-        .serial_base  = 0xff1100000ULL,
-        .nvram_base   = 0xff1200000ULL,
-        .counter_base = 0xff1300000ULL,
-        .intctl_base  = 0xff1400000ULL,
-        .dma_base     = 0xef0081000ULL,
-        .esp_base     = 0xef0080000ULL,
-        .le_base      = 0xef0060000ULL,
-        .apc_base     = 0xefa000000ULL, // XXX should not exist
-        .aux1_base    = 0xff1800000ULL,
-        .aux2_base    = 0xff1a01000ULL, // XXX should not exist
-        .ecc_base     = 0xf00000000ULL,
-        .ecc_version  = 0x00000000, // version 0, implementation 0
-        .nvram_machine_id = 0x71,
-        .machine_id = ss600mp_id,
-        .iommu_version = 0x01000000,
-        .max_mem = 0xf00000000ULL,
-        .default_cpu_model = "TI SuperSparc II",
-    },
-    /* SS-20 */
-    {
-        .iommu_base   = 0xfe0000000ULL,
-        .tcx_base     = 0xe20000000ULL,
-        .slavio_base  = 0xff0000000ULL,
-        .ms_kb_base   = 0xff1000000ULL,
-        .serial_base  = 0xff1100000ULL,
-        .nvram_base   = 0xff1200000ULL,
-        .fd_base      = 0xff1700000ULL,
-        .counter_base = 0xff1300000ULL,
-        .intctl_base  = 0xff1400000ULL,
-        .idreg_base   = 0xef0000000ULL,
-        .dma_base     = 0xef0400000ULL,
-        .esp_base     = 0xef0800000ULL,
-        .le_base      = 0xef0c00000ULL,
-        .bpp_base     = 0xef4800000ULL,
-        .apc_base     = 0xefa000000ULL, // XXX should not exist
-        .aux1_base    = 0xff1800000ULL,
-        .aux2_base    = 0xff1a01000ULL,
-        .dbri_base    = 0xee0000000ULL,
-        .sx_base      = 0xf80000000ULL,
-        .vsimm        = {
-            {
-                .reg_base  = 0x9c000000ULL,
-                .vram_base = 0xfc000000ULL
-            }, {
-                .reg_base  = 0x90000000ULL,
-                .vram_base = 0xf0000000ULL
-            }, {
-                .reg_base  = 0x94000000ULL
-            }, {
-                .reg_base  = 0x98000000ULL
-            }
-        },
-        .ecc_base     = 0xf00000000ULL,
-        .ecc_version  = 0x20000000, // version 0, implementation 2
-        .nvram_machine_id = 0x72,
-        .machine_id = ss20_id,
-        .iommu_version = 0x13000000,
-        .max_mem = 0xf00000000ULL,
-        .default_cpu_model = "TI SuperSparc II",
-    },
-    /* Voyager */
-    {
-        .iommu_base   = 0x10000000,
-        .tcx_base     = 0x50000000,
-        .slavio_base  = 0x70000000,
-        .ms_kb_base   = 0x71000000,
-        .serial_base  = 0x71100000,
-        .nvram_base   = 0x71200000,
-        .fd_base      = 0x71400000,
-        .counter_base = 0x71d00000,
-        .intctl_base  = 0x71e00000,
-        .idreg_base   = 0x78000000,
-        .dma_base     = 0x78400000,
-        .esp_base     = 0x78800000,
-        .le_base      = 0x78c00000,
-        .apc_base     = 0x71300000, // pmc
-        .aux1_base    = 0x71900000,
-        .aux2_base    = 0x71910000,
-        .nvram_machine_id = 0x80,
-        .machine_id = vger_id,
-        .iommu_version = 0x05000000,
-        .max_mem = 0x10000000,
-        .default_cpu_model = "Fujitsu MB86904",
-    },
-    /* LX */
-    {
-        .iommu_base   = 0x10000000,
-        .iommu_pad_base = 0x10004000,
-        .iommu_pad_len  = 0x0fffb000,
-        .tcx_base     = 0x50000000,
-        .slavio_base  = 0x70000000,
-        .ms_kb_base   = 0x71000000,
-        .serial_base  = 0x71100000,
-        .nvram_base   = 0x71200000,
-        .fd_base      = 0x71400000,
-        .counter_base = 0x71d00000,
-        .intctl_base  = 0x71e00000,
-        .idreg_base   = 0x78000000,
-        .dma_base     = 0x78400000,
-        .esp_base     = 0x78800000,
-        .le_base      = 0x78c00000,
-        .aux1_base    = 0x71900000,
-        .aux2_base    = 0x71910000,
-        .nvram_machine_id = 0x80,
-        .machine_id = lx_id,
-        .iommu_version = 0x04000000,
-        .max_mem = 0x10000000,
-        .default_cpu_model = "TI MicroSparc I",
-    },
-    /* SS-4 */
-    {
-        .iommu_base   = 0x10000000,
-        .tcx_base     = 0x50000000,
-        .cs_base      = 0x6c000000,
-        .slavio_base  = 0x70000000,
-        .ms_kb_base   = 0x71000000,
-        .serial_base  = 0x71100000,
-        .nvram_base   = 0x71200000,
-        .fd_base      = 0x71400000,
-        .counter_base = 0x71d00000,
-        .intctl_base  = 0x71e00000,
-        .idreg_base   = 0x78000000,
-        .dma_base     = 0x78400000,
-        .esp_base     = 0x78800000,
-        .le_base      = 0x78c00000,
-        .apc_base     = 0x6a000000,
-        .aux1_base    = 0x71900000,
-        .aux2_base    = 0x71910000,
-        .nvram_machine_id = 0x80,
-        .machine_id = ss4_id,
-        .iommu_version = 0x05000000,
-        .max_mem = 0x10000000,
-        .default_cpu_model = "Fujitsu MB86904",
-    },
-    /* SPARCClassic */
-    {
-        .iommu_base   = 0x10000000,
-        .tcx_base     = 0x50000000,
-        .slavio_base  = 0x70000000,
-        .ms_kb_base   = 0x71000000,
-        .serial_base  = 0x71100000,
-        .nvram_base   = 0x71200000,
-        .fd_base      = 0x71400000,
-        .counter_base = 0x71d00000,
-        .intctl_base  = 0x71e00000,
-        .idreg_base   = 0x78000000,
-        .dma_base     = 0x78400000,
-        .esp_base     = 0x78800000,
-        .le_base      = 0x78c00000,
-        .apc_base     = 0x6a000000,
-        .aux1_base    = 0x71900000,
-        .aux2_base    = 0x71910000,
-        .nvram_machine_id = 0x80,
-        .machine_id = scls_id,
-        .iommu_version = 0x05000000,
-        .max_mem = 0x10000000,
-        .default_cpu_model = "TI MicroSparc I",
-    },
-    /* SPARCbook */
-    {
-        .iommu_base   = 0x10000000,
-        .tcx_base     = 0x50000000, // XXX
-        .slavio_base  = 0x70000000,
-        .ms_kb_base   = 0x71000000,
-        .serial_base  = 0x71100000,
-        .nvram_base   = 0x71200000,
-        .fd_base      = 0x71400000,
-        .counter_base = 0x71d00000,
-        .intctl_base  = 0x71e00000,
-        .idreg_base   = 0x78000000,
-        .dma_base     = 0x78400000,
-        .esp_base     = 0x78800000,
-        .le_base      = 0x78c00000,
-        .apc_base     = 0x6a000000,
-        .aux1_base    = 0x71900000,
-        .aux2_base    = 0x71910000,
-        .nvram_machine_id = 0x80,
-        .machine_id = sbook_id,
-        .iommu_version = 0x05000000,
-        .max_mem = 0x10000000,
-        .default_cpu_model = "TI MicroSparc I",
-    },
-};
-
-/* SPARCstation 5 hardware initialisation */
-static void ss5_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[0], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCstation 10 hardware initialisation */
-static void ss10_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[1], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCserver 600MP hardware initialisation */
-static void ss600mp_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[2], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCstation 20 hardware initialisation */
-static void ss20_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[3], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCstation Voyager hardware initialisation */
-static void vger_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[4], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCstation LX hardware initialisation */
-static void ss_lx_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[5], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCstation 4 hardware initialisation */
-static void ss4_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[6], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCClassic hardware initialisation */
-static void scls_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[7], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCbook hardware initialisation */
-static void sbook_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4m_hw_init(&sun4m_hwdefs[8], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-static QEMUMachine ss5_machine = {
-    .name = "SS-5",
-    .desc = "Sun4m platform, SPARCstation 5",
-    .init = ss5_init,
-    .block_default_type = IF_SCSI,
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine ss10_machine = {
-    .name = "SS-10",
-    .desc = "Sun4m platform, SPARCstation 10",
-    .init = ss10_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine ss600mp_machine = {
-    .name = "SS-600MP",
-    .desc = "Sun4m platform, SPARCserver 600MP",
-    .init = ss600mp_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine ss20_machine = {
-    .name = "SS-20",
-    .desc = "Sun4m platform, SPARCstation 20",
-    .init = ss20_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine voyager_machine = {
-    .name = "Voyager",
-    .desc = "Sun4m platform, SPARCstation Voyager",
-    .init = vger_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine ss_lx_machine = {
-    .name = "LX",
-    .desc = "Sun4m platform, SPARCstation LX",
-    .init = ss_lx_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine ss4_machine = {
-    .name = "SS-4",
-    .desc = "Sun4m platform, SPARCstation 4",
-    .init = ss4_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine scls_machine = {
-    .name = "SPARCClassic",
-    .desc = "Sun4m platform, SPARCClassic",
-    .init = scls_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine sbook_machine = {
-    .name = "SPARCbook",
-    .desc = "Sun4m platform, SPARCbook",
-    .init = sbook_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static const struct sun4d_hwdef sun4d_hwdefs[] = {
-    /* SS-1000 */
-    {
-        .iounit_bases   = {
-            0xfe0200000ULL,
-            0xfe1200000ULL,
-            0xfe2200000ULL,
-            0xfe3200000ULL,
-            -1,
-        },
-        .tcx_base     = 0x820000000ULL,
-        .slavio_base  = 0xf00000000ULL,
-        .ms_kb_base   = 0xf00240000ULL,
-        .serial_base  = 0xf00200000ULL,
-        .nvram_base   = 0xf00280000ULL,
-        .counter_base = 0xf00300000ULL,
-        .espdma_base  = 0x800081000ULL,
-        .esp_base     = 0x800080000ULL,
-        .ledma_base   = 0x800040000ULL,
-        .le_base      = 0x800060000ULL,
-        .sbi_base     = 0xf02800000ULL,
-        .nvram_machine_id = 0x80,
-        .machine_id = ss1000_id,
-        .iounit_version = 0x03000000,
-        .max_mem = 0xf00000000ULL,
-        .default_cpu_model = "TI SuperSparc II",
-    },
-    /* SS-2000 */
-    {
-        .iounit_bases   = {
-            0xfe0200000ULL,
-            0xfe1200000ULL,
-            0xfe2200000ULL,
-            0xfe3200000ULL,
-            0xfe4200000ULL,
-        },
-        .tcx_base     = 0x820000000ULL,
-        .slavio_base  = 0xf00000000ULL,
-        .ms_kb_base   = 0xf00240000ULL,
-        .serial_base  = 0xf00200000ULL,
-        .nvram_base   = 0xf00280000ULL,
-        .counter_base = 0xf00300000ULL,
-        .espdma_base  = 0x800081000ULL,
-        .esp_base     = 0x800080000ULL,
-        .ledma_base   = 0x800040000ULL,
-        .le_base      = 0x800060000ULL,
-        .sbi_base     = 0xf02800000ULL,
-        .nvram_machine_id = 0x80,
-        .machine_id = ss2000_id,
-        .iounit_version = 0x03000000,
-        .max_mem = 0xf00000000ULL,
-        .default_cpu_model = "TI SuperSparc II",
-    },
-};
-
-static DeviceState *sbi_init(hwaddr addr, qemu_irq **parent_irq)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    unsigned int i;
-
-    dev = qdev_create(NULL, "sbi");
-    qdev_init_nofail(dev);
-
-    s = SYS_BUS_DEVICE(dev);
-
-    for (i = 0; i < MAX_CPUS; i++) {
-        sysbus_connect_irq(s, i, *parent_irq[i]);
-    }
-
-    sysbus_mmio_map(s, 0, addr);
-
-    return dev;
-}
-
-static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, 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)
-{
-    unsigned int i;
-    void *iounits[MAX_IOUNITS], *espdma, *ledma, *nvram;
-    qemu_irq *cpu_irqs[MAX_CPUS], sbi_irq[32], sbi_cpu_irq[MAX_CPUS],
-        espdma_irq, ledma_irq;
-    qemu_irq esp_reset, dma_enable;
-    unsigned long kernel_size;
-    void *fw_cfg;
-    DeviceState *dev;
-
-    /* init CPUs */
-    if (!cpu_model)
-        cpu_model = hwdef->default_cpu_model;
-
-    for(i = 0; i < smp_cpus; i++) {
-        cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]);
-    }
-
-    for (i = smp_cpus; i < MAX_CPUS; i++)
-        cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS);
-
-    /* set up devices */
-    ram_init(0, RAM_size, hwdef->max_mem);
-
-    prom_init(hwdef->slavio_base, bios_name);
-
-    dev = sbi_init(hwdef->sbi_base, cpu_irqs);
-
-    for (i = 0; i < 32; i++) {
-        sbi_irq[i] = qdev_get_gpio_in(dev, i);
-    }
-    for (i = 0; i < MAX_CPUS; i++) {
-        sbi_cpu_irq[i] = qdev_get_gpio_in(dev, 32 + i);
-    }
-
-    for (i = 0; i < MAX_IOUNITS; i++)
-        if (hwdef->iounit_bases[i] != (hwaddr)-1)
-            iounits[i] = iommu_init(hwdef->iounit_bases[i],
-                                    hwdef->iounit_version,
-                                    sbi_irq[0]);
-
-    espdma = sparc32_dma_init(hwdef->espdma_base, sbi_irq[3],
-                              iounits[0], &espdma_irq, 0);
-
-    /* should be lebuffer instead */
-    ledma = sparc32_dma_init(hwdef->ledma_base, sbi_irq[4],
-                             iounits[0], &ledma_irq, 0);
-
-    if (graphic_depth != 8 && graphic_depth != 24) {
-        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
-        exit (1);
-    }
-    tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height,
-             graphic_depth);
-
-    lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq);
-
-    nvram = m48t59_init(sbi_irq[0], hwdef->nvram_base, 0, 0x2000, 8);
-
-    slavio_timer_init_all(hwdef->counter_base, sbi_irq[10], sbi_cpu_irq, smp_cpus);
-
-    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, sbi_irq[12],
-                              display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
-    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
-       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
-    escc_init(hwdef->serial_base, sbi_irq[12], sbi_irq[12],
-              serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);
-
-    if (drive_get_max_bus(IF_SCSI) > 0) {
-        fprintf(stderr, "qemu: too many SCSI bus\n");
-        exit(1);
-    }
-
-    esp_init(hwdef->esp_base, 2,
-             espdma_memory_read, espdma_memory_write,
-             espdma, espdma_irq, &esp_reset, &dma_enable);
-
-    qdev_connect_gpio_out(espdma, 0, esp_reset);
-    qdev_connect_gpio_out(espdma, 1, dma_enable);
-
-    kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename,
-                                    RAM_size);
-
-    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
-               boot_device, RAM_size, kernel_size, graphic_width,
-               graphic_height, graphic_depth, hwdef->nvram_machine_id,
-               "Sun4d");
-
-    fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
-    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
-    if (kernel_cmdline) {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
-        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
-        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
-    } else {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
-    }
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used
-    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device[0]);
-    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
-}
-
-/* SPARCserver 1000 hardware initialisation */
-static void ss1000_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4d_hw_init(&sun4d_hwdefs[0], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-/* SPARCcenter 2000 hardware initialisation */
-static void ss2000_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4d_hw_init(&sun4d_hwdefs[1], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-static QEMUMachine ss1000_machine = {
-    .name = "SS-1000",
-    .desc = "Sun4d platform, SPARCserver 1000",
-    .init = ss1000_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 8,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine ss2000_machine = {
-    .name = "SS-2000",
-    .desc = "Sun4d platform, SPARCcenter 2000",
-    .init = ss2000_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 20,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static const struct sun4c_hwdef sun4c_hwdefs[] = {
-    /* SS-2 */
-    {
-        .iommu_base   = 0xf8000000,
-        .tcx_base     = 0xfe000000,
-        .slavio_base  = 0xf6000000,
-        .intctl_base  = 0xf5000000,
-        .counter_base = 0xf3000000,
-        .ms_kb_base   = 0xf0000000,
-        .serial_base  = 0xf1000000,
-        .nvram_base   = 0xf2000000,
-        .fd_base      = 0xf7200000,
-        .dma_base     = 0xf8400000,
-        .esp_base     = 0xf8800000,
-        .le_base      = 0xf8c00000,
-        .aux1_base    = 0xf7400003,
-        .nvram_machine_id = 0x55,
-        .machine_id = ss2_id,
-        .max_mem = 0x10000000,
-        .default_cpu_model = "Cypress CY7C601",
-    },
-};
-
-static DeviceState *sun4c_intctl_init(hwaddr addr,
-                                      qemu_irq *parent_irq)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    unsigned int i;
-
-    dev = qdev_create(NULL, "sun4c_intctl");
-    qdev_init_nofail(dev);
-
-    s = SYS_BUS_DEVICE(dev);
-
-    for (i = 0; i < MAX_PILS; i++) {
-        sysbus_connect_irq(s, i, parent_irq[i]);
-    }
-    sysbus_mmio_map(s, 0, addr);
-
-    return dev;
-}
-
-static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, 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)
-{
-    void *iommu, *espdma, *ledma, *nvram;
-    qemu_irq *cpu_irqs, slavio_irq[8], espdma_irq, ledma_irq;
-    qemu_irq esp_reset, dma_enable;
-    qemu_irq fdc_tc;
-    unsigned long kernel_size;
-    DriveInfo *fd[MAX_FD];
-    void *fw_cfg;
-    DeviceState *dev;
-    unsigned int i;
-
-    /* init CPU */
-    if (!cpu_model)
-        cpu_model = hwdef->default_cpu_model;
-
-    cpu_devinit(cpu_model, 0, hwdef->slavio_base, &cpu_irqs);
-
-    /* set up devices */
-    ram_init(0, RAM_size, hwdef->max_mem);
-
-    prom_init(hwdef->slavio_base, bios_name);
-
-    dev = sun4c_intctl_init(hwdef->intctl_base, cpu_irqs);
-
-    for (i = 0; i < 8; i++) {
-        slavio_irq[i] = qdev_get_gpio_in(dev, i);
-    }
-
-    iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
-                       slavio_irq[1]);
-
-    espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[2],
-                              iommu, &espdma_irq, 0);
-
-    ledma = sparc32_dma_init(hwdef->dma_base + 16ULL,
-                             slavio_irq[3], iommu, &ledma_irq, 1);
-
-    if (graphic_depth != 8 && graphic_depth != 24) {
-        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
-        exit (1);
-    }
-    tcx_init(hwdef->tcx_base, 0x00100000, graphic_width, graphic_height,
-             graphic_depth);
-
-    lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq);
-
-    nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x800, 2);
-
-    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[1],
-                              display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1);
-    /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device
-       Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */
-    escc_init(hwdef->serial_base, slavio_irq[1],
-              slavio_irq[1], serial_hds[0], serial_hds[1],
-              ESCC_CLOCK, 1);
-
-    if (hwdef->fd_base != (hwaddr)-1) {
-        /* there is zero or one floppy drive */
-        memset(fd, 0, sizeof(fd));
-        fd[0] = drive_get(IF_FLOPPY, 0, 0);
-        sun4m_fdctrl_init(slavio_irq[1], hwdef->fd_base, fd,
-                          &fdc_tc);
-    } else {
-        fdc_tc = *qemu_allocate_irqs(dummy_fdc_tc, NULL, 1);
-    }
-
-    slavio_misc_init(0, hwdef->aux1_base, 0, slavio_irq[1], fdc_tc);
-
-    if (drive_get_max_bus(IF_SCSI) > 0) {
-        fprintf(stderr, "qemu: too many SCSI bus\n");
-        exit(1);
-    }
-
-    esp_init(hwdef->esp_base, 2,
-             espdma_memory_read, espdma_memory_write,
-             espdma, espdma_irq, &esp_reset, &dma_enable);
-
-    qdev_connect_gpio_out(espdma, 0, esp_reset);
-    qdev_connect_gpio_out(espdma, 1, dma_enable);
-
-    kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename,
-                                    RAM_size);
-
-    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
-               boot_device, RAM_size, kernel_size, graphic_width,
-               graphic_height, graphic_depth, hwdef->nvram_machine_id,
-               "Sun4c");
-
-    fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
-    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
-    if (kernel_cmdline) {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
-        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
-        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
-    } else {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
-    }
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used
-    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device[0]);
-    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
-}
-
-/* SPARCstation 2 hardware initialisation */
-static void ss2_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_device = args->boot_device;
-    sun4c_hw_init(&sun4c_hwdefs[0], RAM_size, boot_device, kernel_filename,
-                  kernel_cmdline, initrd_filename, cpu_model);
-}
-
-static QEMUMachine ss2_machine = {
-    .name = "SS-2",
-    .desc = "Sun4c platform, SPARCstation 2",
-    .init = ss2_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void sun4m_register_types(void)
-{
-    type_register_static(&idreg_info);
-    type_register_static(&afx_info);
-    type_register_static(&prom_info);
-    type_register_static(&ram_info);
-}
-
-static void ss2_machine_init(void)
-{
-    qemu_register_machine(&ss5_machine);
-    qemu_register_machine(&ss10_machine);
-    qemu_register_machine(&ss600mp_machine);
-    qemu_register_machine(&ss20_machine);
-    qemu_register_machine(&voyager_machine);
-    qemu_register_machine(&ss_lx_machine);
-    qemu_register_machine(&ss4_machine);
-    qemu_register_machine(&scls_machine);
-    qemu_register_machine(&sbook_machine);
-    qemu_register_machine(&ss1000_machine);
-    qemu_register_machine(&ss2000_machine);
-    qemu_register_machine(&ss2_machine);
-}
-
-type_init(sun4m_register_types)
-machine_init(ss2_machine_init);
diff --git a/hw/sun4u.c b/hw/sun4u.c
deleted file mode 100644
index 51ffa1c..0000000
--- a/hw/sun4u.c
+++ /dev/null
@@ -1,1014 +0,0 @@
-/*
- * QEMU Sun4u/Sun4v System Emulator
- *
- * Copyright (c) 2005 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 "hw/hw.h"
-#include "hw/pci/pci.h"
-#include "hw/apb_pci.h"
-#include "hw/pc.h"
-#include "hw/serial.h"
-#include "hw/nvram.h"
-#include "hw/fdc.h"
-#include "net/net.h"
-#include "qemu/timer.h"
-#include "sysemu/sysemu.h"
-#include "hw/boards.h"
-#include "hw/firmware_abi.h"
-#include "hw/fw_cfg.h"
-#include "hw/sysbus.h"
-#include "hw/ide.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-
-//#define DEBUG_IRQ
-//#define DEBUG_EBUS
-//#define DEBUG_TIMER
-
-#ifdef DEBUG_IRQ
-#define CPUIRQ_DPRINTF(fmt, ...)                                \
-    do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define CPUIRQ_DPRINTF(fmt, ...)
-#endif
-
-#ifdef DEBUG_EBUS
-#define EBUS_DPRINTF(fmt, ...)                                  \
-    do { printf("EBUS: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define EBUS_DPRINTF(fmt, ...)
-#endif
-
-#ifdef DEBUG_TIMER
-#define TIMER_DPRINTF(fmt, ...)                                  \
-    do { printf("TIMER: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define TIMER_DPRINTF(fmt, ...)
-#endif
-
-#define KERNEL_LOAD_ADDR     0x00404000
-#define CMDLINE_ADDR         0x003ff000
-#define PROM_SIZE_MAX        (4 * 1024 * 1024)
-#define PROM_VADDR           0x000ffd00000ULL
-#define APB_SPECIAL_BASE     0x1fe00000000ULL
-#define APB_MEM_BASE         0x1ff00000000ULL
-#define APB_PCI_IO_BASE      (APB_SPECIAL_BASE + 0x02000000ULL)
-#define PROM_FILENAME        "openbios-sparc64"
-#define NVRAM_SIZE           0x2000
-#define MAX_IDE_BUS          2
-#define BIOS_CFG_IOPORT      0x510
-#define FW_CFG_SPARC64_WIDTH (FW_CFG_ARCH_LOCAL + 0x00)
-#define FW_CFG_SPARC64_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
-#define FW_CFG_SPARC64_DEPTH (FW_CFG_ARCH_LOCAL + 0x02)
-
-#define IVEC_MAX             0x30
-
-#define TICK_MAX             0x7fffffffffffffffULL
-
-struct hwdef {
-    const char * const default_cpu_model;
-    uint16_t machine_id;
-    uint64_t prom_addr;
-    uint64_t console_serial_base;
-};
-
-typedef struct EbusState {
-    PCIDevice pci_dev;
-    MemoryRegion bar0;
-    MemoryRegion bar1;
-} EbusState;
-
-int DMA_get_channel_mode (int nchan)
-{
-    return 0;
-}
-int DMA_read_memory (int nchan, void *buf, int pos, int size)
-{
-    return 0;
-}
-int DMA_write_memory (int nchan, void *buf, int pos, int size)
-{
-    return 0;
-}
-void DMA_hold_DREQ (int nchan) {}
-void DMA_release_DREQ (int nchan) {}
-void DMA_schedule(int nchan) {}
-
-void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
-{
-}
-
-void DMA_register_channel (int nchan,
-                           DMA_transfer_handler transfer_handler,
-                           void *opaque)
-{
-}
-
-static int fw_cfg_boot_set(void *opaque, const char *boot_device)
-{
-    fw_cfg_add_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
-    return 0;
-}
-
-static int sun4u_NVRAM_set_params(M48t59State *nvram, uint16_t NVRAM_size,
-                                  const char *arch, ram_addr_t RAM_size,
-                                  const char *boot_devices,
-                                  uint32_t kernel_image, uint32_t kernel_size,
-                                  const char *cmdline,
-                                  uint32_t initrd_image, uint32_t initrd_size,
-                                  uint32_t NVRAM_image,
-                                  int width, int height, int depth,
-                                  const uint8_t *macaddr)
-{
-    unsigned int i;
-    uint32_t start, end;
-    uint8_t image[0x1ff0];
-    struct OpenBIOS_nvpart_v1 *part_header;
-
-    memset(image, '\0', sizeof(image));
-
-    start = 0;
-
-    // OpenBIOS nvram variables
-    // Variable partition
-    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
-    part_header->signature = OPENBIOS_PART_SYSTEM;
-    pstrcpy(part_header->name, sizeof(part_header->name), "system");
-
-    end = start + sizeof(struct OpenBIOS_nvpart_v1);
-    for (i = 0; i < nb_prom_envs; i++)
-        end = OpenBIOS_set_var(image, end, prom_envs[i]);
-
-    // End marker
-    image[end++] = '\0';
-
-    end = start + ((end - start + 15) & ~15);
-    OpenBIOS_finish_partition(part_header, end - start);
-
-    // free partition
-    start = end;
-    part_header = (struct OpenBIOS_nvpart_v1 *)&image[start];
-    part_header->signature = OPENBIOS_PART_FREE;
-    pstrcpy(part_header->name, sizeof(part_header->name), "free");
-
-    end = 0x1fd0;
-    OpenBIOS_finish_partition(part_header, end - start);
-
-    Sun_init_header((struct Sun_nvram *)&image[0x1fd8], macaddr, 0x80);
-
-    for (i = 0; i < sizeof(image); i++)
-        m48t59_write(nvram, i, image[i]);
-
-    return 0;
-}
-
-static uint64_t sun4u_load_kernel(const char *kernel_filename,
-                                  const char *initrd_filename,
-                                  ram_addr_t RAM_size, uint64_t *initrd_size,
-                                  uint64_t *initrd_addr, uint64_t *kernel_addr,
-                                  uint64_t *kernel_entry)
-{
-    int linux_boot;
-    unsigned int i;
-    long kernel_size;
-    uint8_t *ptr;
-    uint64_t kernel_top;
-
-    linux_boot = (kernel_filename != NULL);
-
-    kernel_size = 0;
-    if (linux_boot) {
-        int bswap_needed;
-
-#ifdef BSWAP_NEEDED
-        bswap_needed = 1;
-#else
-        bswap_needed = 0;
-#endif
-        kernel_size = load_elf(kernel_filename, NULL, NULL, kernel_entry,
-                               kernel_addr, &kernel_top, 1, ELF_MACHINE, 0);
-        if (kernel_size < 0) {
-            *kernel_addr = KERNEL_LOAD_ADDR;
-            *kernel_entry = KERNEL_LOAD_ADDR;
-            kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
-                                    RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
-                                    TARGET_PAGE_SIZE);
-        }
-        if (kernel_size < 0) {
-            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",
-                    kernel_filename);
-            exit(1);
-        }
-        /* load initrd above kernel */
-        *initrd_size = 0;
-        if (initrd_filename) {
-            *initrd_addr = TARGET_PAGE_ALIGN(kernel_top);
-
-            *initrd_size = load_image_targphys(initrd_filename,
-                                               *initrd_addr,
-                                               RAM_size - *initrd_addr);
-            if ((int)*initrd_size < 0) {
-                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
-                        initrd_filename);
-                exit(1);
-            }
-        }
-        if (*initrd_size > 0) {
-            for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) {
-                ptr = rom_ptr(*kernel_addr + i);
-                if (ldl_p(ptr + 8) == 0x48647253) { /* HdrS */
-                    stl_p(ptr + 24, *initrd_addr + *kernel_addr);
-                    stl_p(ptr + 28, *initrd_size);
-                    break;
-                }
-            }
-        }
-    }
-    return kernel_size;
-}
-
-void cpu_check_irqs(CPUSPARCState *env)
-{
-    uint32_t pil = env->pil_in |
-                  (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));
-
-    /* TT_IVEC has a higher priority (16) than TT_EXTINT (31..17) */
-    if (env->ivec_status & 0x20) {
-        return;
-    }
-    /* check if TM or SM in SOFTINT are set
-       setting these also causes interrupt 14 */
-    if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) {
-        pil |= 1 << 14;
-    }
-
-    /* The bit corresponding to psrpil is (1<< psrpil), the next bit
-       is (2 << psrpil). */
-    if (pil < (2 << env->psrpil)){
-        if (env->interrupt_request & CPU_INTERRUPT_HARD) {
-            CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n",
-                           env->interrupt_index);
-            env->interrupt_index = 0;
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-        }
-        return;
-    }
-
-    if (cpu_interrupts_enabled(env)) {
-
-        unsigned int i;
-
-        for (i = 15; i > env->psrpil; i--) {
-            if (pil & (1 << i)) {
-                int old_interrupt = env->interrupt_index;
-                int new_interrupt = TT_EXTINT | i;
-
-                if (unlikely(env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt
-                  && ((cpu_tsptr(env)->tt & 0x1f0) == TT_EXTINT))) {
-                    CPUIRQ_DPRINTF("Not setting CPU IRQ: TL=%d "
-                                   "current %x >= pending %x\n",
-                                   env->tl, cpu_tsptr(env)->tt, new_interrupt);
-                } else if (old_interrupt != new_interrupt) {
-                    env->interrupt_index = new_interrupt;
-                    CPUIRQ_DPRINTF("Set CPU IRQ %d old=%x new=%x\n", i,
-                                   old_interrupt, new_interrupt);
-                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
-                }
-                break;
-            }
-        }
-    } else if (env->interrupt_request & CPU_INTERRUPT_HARD) {
-        CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x "
-                       "current interrupt %x\n",
-                       pil, env->pil_in, env->softint, env->interrupt_index);
-        env->interrupt_index = 0;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-}
-
-static void cpu_kick_irq(SPARCCPU *cpu)
-{
-    CPUSPARCState *env = &cpu->env;
-
-    env->halted = 0;
-    cpu_check_irqs(env);
-    qemu_cpu_kick(CPU(cpu));
-}
-
-static void cpu_set_ivec_irq(void *opaque, int irq, int level)
-{
-    SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
-
-    if (level) {
-        if (!(env->ivec_status & 0x20)) {
-            CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
-            env->halted = 0;
-            env->interrupt_index = TT_IVEC;
-            env->ivec_status |= 0x20;
-            env->ivec_data[0] = (0x1f << 6) | irq;
-            env->ivec_data[1] = 0;
-            env->ivec_data[2] = 0;
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
-        }
-    } else {
-        if (env->ivec_status & 0x20) {
-            CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq);
-            env->ivec_status &= ~0x20;
-            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-        }
-    }
-}
-
-typedef struct ResetData {
-    SPARCCPU *cpu;
-    uint64_t prom_addr;
-} ResetData;
-
-void cpu_put_timer(QEMUFile *f, CPUTimer *s)
-{
-    qemu_put_be32s(f, &s->frequency);
-    qemu_put_be32s(f, &s->disabled);
-    qemu_put_be64s(f, &s->disabled_mask);
-    qemu_put_sbe64s(f, &s->clock_offset);
-
-    qemu_put_timer(f, s->qtimer);
-}
-
-void cpu_get_timer(QEMUFile *f, CPUTimer *s)
-{
-    qemu_get_be32s(f, &s->frequency);
-    qemu_get_be32s(f, &s->disabled);
-    qemu_get_be64s(f, &s->disabled_mask);
-    qemu_get_sbe64s(f, &s->clock_offset);
-
-    qemu_get_timer(f, s->qtimer);
-}
-
-static CPUTimer *cpu_timer_create(const char *name, SPARCCPU *cpu,
-                                  QEMUBHFunc *cb, uint32_t frequency,
-                                  uint64_t disabled_mask)
-{
-    CPUTimer *timer = g_malloc0(sizeof (CPUTimer));
-
-    timer->name = name;
-    timer->frequency = frequency;
-    timer->disabled_mask = disabled_mask;
-
-    timer->disabled = 1;
-    timer->clock_offset = qemu_get_clock_ns(vm_clock);
-
-    timer->qtimer = qemu_new_timer_ns(vm_clock, cb, cpu);
-
-    return timer;
-}
-
-static void cpu_timer_reset(CPUTimer *timer)
-{
-    timer->disabled = 1;
-    timer->clock_offset = qemu_get_clock_ns(vm_clock);
-
-    qemu_del_timer(timer->qtimer);
-}
-
-static void main_cpu_reset(void *opaque)
-{
-    ResetData *s = (ResetData *)opaque;
-    CPUSPARCState *env = &s->cpu->env;
-    static unsigned int nr_resets;
-
-    cpu_reset(CPU(s->cpu));
-
-    cpu_timer_reset(env->tick);
-    cpu_timer_reset(env->stick);
-    cpu_timer_reset(env->hstick);
-
-    env->gregs[1] = 0; // Memory start
-    env->gregs[2] = ram_size; // Memory size
-    env->gregs[3] = 0; // Machine description XXX
-    if (nr_resets++ == 0) {
-        /* Power on reset */
-        env->pc = s->prom_addr + 0x20ULL;
-    } else {
-        env->pc = s->prom_addr + 0x40ULL;
-    }
-    env->npc = env->pc + 4;
-}
-
-static void tick_irq(void *opaque)
-{
-    SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
-
-    CPUTimer* timer = env->tick;
-
-    if (timer->disabled) {
-        CPUIRQ_DPRINTF("tick_irq: softint disabled\n");
-        return;
-    } else {
-        CPUIRQ_DPRINTF("tick: fire\n");
-    }
-
-    env->softint |= SOFTINT_TIMER;
-    cpu_kick_irq(cpu);
-}
-
-static void stick_irq(void *opaque)
-{
-    SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
-
-    CPUTimer* timer = env->stick;
-
-    if (timer->disabled) {
-        CPUIRQ_DPRINTF("stick_irq: softint disabled\n");
-        return;
-    } else {
-        CPUIRQ_DPRINTF("stick: fire\n");
-    }
-
-    env->softint |= SOFTINT_STIMER;
-    cpu_kick_irq(cpu);
-}
-
-static void hstick_irq(void *opaque)
-{
-    SPARCCPU *cpu = opaque;
-    CPUSPARCState *env = &cpu->env;
-
-    CPUTimer* timer = env->hstick;
-
-    if (timer->disabled) {
-        CPUIRQ_DPRINTF("hstick_irq: softint disabled\n");
-        return;
-    } else {
-        CPUIRQ_DPRINTF("hstick: fire\n");
-    }
-
-    env->softint |= SOFTINT_STIMER;
-    cpu_kick_irq(cpu);
-}
-
-static int64_t cpu_to_timer_ticks(int64_t cpu_ticks, uint32_t frequency)
-{
-    return muldiv64(cpu_ticks, get_ticks_per_sec(), frequency);
-}
-
-static uint64_t timer_to_cpu_ticks(int64_t timer_ticks, uint32_t frequency)
-{
-    return muldiv64(timer_ticks, frequency, get_ticks_per_sec());
-}
-
-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_ns(vm_clock) -
-                    cpu_to_timer_ticks(real_count, timer->frequency);
-
-    TIMER_DPRINTF("%s set_count count=0x%016lx (%s) p=%p\n",
-                  timer->name, real_count,
-                  timer->disabled?"disabled":"enabled", timer);
-
-    timer->disabled = disabled_bit ? 1 : 0;
-    timer->clock_offset = vm_clock_offset;
-}
-
-uint64_t cpu_tick_get_count(CPUTimer *timer)
-{
-    uint64_t real_count = timer_to_cpu_ticks(
-                    qemu_get_clock_ns(vm_clock) - timer->clock_offset,
-                    timer->frequency);
-
-    TIMER_DPRINTF("%s get_count count=0x%016lx (%s) p=%p\n",
-           timer->name, real_count,
-           timer->disabled?"disabled":"enabled", timer);
-
-    if (timer->disabled)
-        real_count |= timer->disabled_mask;
-
-    return real_count;
-}
-
-void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit)
-{
-    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;
-
-    int64_t expires = cpu_to_timer_ticks(real_limit, timer->frequency) +
-                    timer->clock_offset;
-
-    if (expires < now) {
-        expires = now + 1;
-    }
-
-    TIMER_DPRINTF("%s set_limit limit=0x%016lx (%s) p=%p "
-                  "called with limit=0x%016lx at 0x%016lx (delta=0x%016lx)\n",
-                  timer->name, real_limit,
-                  timer->disabled?"disabled":"enabled",
-                  timer, limit,
-                  timer_to_cpu_ticks(now - timer->clock_offset,
-                                     timer->frequency),
-                  timer_to_cpu_ticks(expires - now, timer->frequency));
-
-    if (!real_limit) {
-        TIMER_DPRINTF("%s set_limit limit=ZERO - not starting timer\n",
-                timer->name);
-        qemu_del_timer(timer->qtimer);
-    } else if (timer->disabled) {
-        qemu_del_timer(timer->qtimer);
-    } else {
-        qemu_mod_timer(timer->qtimer, expires);
-    }
-}
-
-static void isa_irq_handler(void *opaque, int n, int level)
-{
-    static const int isa_irq_to_ivec[16] = {
-        [1] = 0x29, /* keyboard */
-        [4] = 0x2b, /* serial */
-        [6] = 0x27, /* floppy */
-        [7] = 0x22, /* parallel */
-        [12] = 0x2a, /* mouse */
-    };
-    qemu_irq *irqs = opaque;
-    int ivec;
-
-    assert(n < 16);
-    ivec = isa_irq_to_ivec[n];
-    EBUS_DPRINTF("Set ISA IRQ %d level %d -> ivec 0x%x\n", n, level, ivec);
-    if (ivec) {
-        qemu_set_irq(irqs[ivec], level);
-    }
-}
-
-/* EBUS (Eight bit bus) bridge */
-static ISABus *
-pci_ebus_init(PCIBus *bus, int devfn, qemu_irq *irqs)
-{
-    qemu_irq *isa_irq;
-    PCIDevice *pci_dev;
-    ISABus *isa_bus;
-
-    pci_dev = pci_create_simple(bus, devfn, "ebus");
-    isa_bus = DO_UPCAST(ISABus, qbus,
-                        qdev_get_child_bus(&pci_dev->qdev, "isa.0"));
-    isa_irq = qemu_allocate_irqs(isa_irq_handler, irqs, 16);
-    isa_bus_irqs(isa_bus, isa_irq);
-    return isa_bus;
-}
-
-static int
-pci_ebus_init1(PCIDevice *pci_dev)
-{
-    EbusState *s = DO_UPCAST(EbusState, pci_dev, pci_dev);
-
-    isa_bus_new(&pci_dev->qdev, pci_address_space_io(pci_dev));
-
-    pci_dev->config[0x04] = 0x06; // command = bus master, pci mem
-    pci_dev->config[0x05] = 0x00;
-    pci_dev->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
-    pci_dev->config[0x07] = 0x03; // status = medium devsel
-    pci_dev->config[0x09] = 0x00; // programming i/f
-    pci_dev->config[0x0D] = 0x0a; // latency_timer
-
-    isa_mmio_setup(&s->bar0, 0x1000000);
-    pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0);
-    isa_mmio_setup(&s->bar1, 0x800000);
-    pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar1);
-    return 0;
-}
-
-static void ebus_class_init(ObjectClass *klass, void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = pci_ebus_init1;
-    k->vendor_id = PCI_VENDOR_ID_SUN;
-    k->device_id = PCI_DEVICE_ID_SUN_EBUS;
-    k->revision = 0x01;
-    k->class_id = PCI_CLASS_BRIDGE_OTHER;
-}
-
-static const TypeInfo ebus_info = {
-    .name          = "ebus",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(EbusState),
-    .class_init    = ebus_class_init,
-};
-
-typedef struct PROMState {
-    SysBusDevice busdev;
-    MemoryRegion prom;
-} PROMState;
-
-static uint64_t translate_prom_address(void *opaque, uint64_t addr)
-{
-    hwaddr *base_addr = (hwaddr *)opaque;
-    return addr + *base_addr - PROM_VADDR;
-}
-
-/* Boot PROM (OpenBIOS) */
-static void prom_init(hwaddr addr, const char *bios_name)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    char *filename;
-    int ret;
-
-    dev = qdev_create(NULL, "openprom");
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-
-    sysbus_mmio_map(s, 0, addr);
-
-    /* load boot prom */
-    if (bios_name == NULL) {
-        bios_name = PROM_FILENAME;
-    }
-    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-    if (filename) {
-        ret = load_elf(filename, translate_prom_address, &addr,
-                       NULL, NULL, NULL, 1, ELF_MACHINE, 0);
-        if (ret < 0 || ret > PROM_SIZE_MAX) {
-            ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
-        }
-        g_free(filename);
-    } else {
-        ret = -1;
-    }
-    if (ret < 0 || ret > PROM_SIZE_MAX) {
-        fprintf(stderr, "qemu: could not load prom '%s'\n", bios_name);
-        exit(1);
-    }
-}
-
-static int prom_init1(SysBusDevice *dev)
-{
-    PROMState *s = FROM_SYSBUS(PROMState, dev);
-
-    memory_region_init_ram(&s->prom, "sun4u.prom", PROM_SIZE_MAX);
-    vmstate_register_ram_global(&s->prom);
-    memory_region_set_readonly(&s->prom, true);
-    sysbus_init_mmio(dev, &s->prom);
-    return 0;
-}
-
-static Property prom_properties[] = {
-    {/* end of property list */},
-};
-
-static void prom_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = prom_init1;
-    dc->props = prom_properties;
-}
-
-static const TypeInfo prom_info = {
-    .name          = "openprom",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(PROMState),
-    .class_init    = prom_class_init,
-};
-
-
-typedef struct RamDevice
-{
-    SysBusDevice busdev;
-    MemoryRegion ram;
-    uint64_t size;
-} RamDevice;
-
-/* System RAM */
-static int ram_init1(SysBusDevice *dev)
-{
-    RamDevice *d = FROM_SYSBUS(RamDevice, dev);
-
-    memory_region_init_ram(&d->ram, "sun4u.ram", d->size);
-    vmstate_register_ram_global(&d->ram);
-    sysbus_init_mmio(dev, &d->ram);
-    return 0;
-}
-
-static void ram_init(hwaddr addr, ram_addr_t RAM_size)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    RamDevice *d;
-
-    /* allocate RAM */
-    dev = qdev_create(NULL, "memory");
-    s = SYS_BUS_DEVICE(dev);
-
-    d = FROM_SYSBUS(RamDevice, s);
-    d->size = RAM_size;
-    qdev_init_nofail(dev);
-
-    sysbus_mmio_map(s, 0, addr);
-}
-
-static Property ram_properties[] = {
-    DEFINE_PROP_UINT64("size", RamDevice, size, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void ram_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = ram_init1;
-    dc->props = ram_properties;
-}
-
-static const TypeInfo ram_info = {
-    .name          = "memory",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(RamDevice),
-    .class_init    = ram_class_init,
-};
-
-static SPARCCPU *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
-{
-    SPARCCPU *cpu;
-    CPUSPARCState *env;
-    ResetData *reset_info;
-
-    uint32_t   tick_frequency = 100*1000000;
-    uint32_t  stick_frequency = 100*1000000;
-    uint32_t hstick_frequency = 100*1000000;
-
-    if (cpu_model == NULL) {
-        cpu_model = hwdef->default_cpu_model;
-    }
-    cpu = cpu_sparc_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to find Sparc CPU definition\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    env->tick = cpu_timer_create("tick", cpu, tick_irq,
-                                  tick_frequency, TICK_NPT_MASK);
-
-    env->stick = cpu_timer_create("stick", cpu, stick_irq,
-                                   stick_frequency, TICK_INT_DIS);
-
-    env->hstick = cpu_timer_create("hstick", cpu, hstick_irq,
-                                    hstick_frequency, TICK_INT_DIS);
-
-    reset_info = g_malloc0(sizeof(ResetData));
-    reset_info->cpu = cpu;
-    reset_info->prom_addr = hwdef->prom_addr;
-    qemu_register_reset(main_cpu_reset, reset_info);
-
-    return cpu;
-}
-
-static void sun4uv_init(MemoryRegion *address_space_mem,
-                        ram_addr_t RAM_size,
-                        const char *boot_devices,
-                        const char *kernel_filename, const char *kernel_cmdline,
-                        const char *initrd_filename, const char *cpu_model,
-                        const struct hwdef *hwdef)
-{
-    SPARCCPU *cpu;
-    M48t59State *nvram;
-    unsigned int i;
-    uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry;
-    PCIBus *pci_bus, *pci_bus2, *pci_bus3;
-    ISABus *isa_bus;
-    qemu_irq *ivec_irqs, *pbm_irqs;
-    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    DriveInfo *fd[MAX_FD];
-    void *fw_cfg;
-
-    /* init CPUs */
-    cpu = cpu_devinit(cpu_model, hwdef);
-
-    /* set up devices */
-    ram_init(0, RAM_size);
-
-    prom_init(hwdef->prom_addr, bios_name);
-
-    ivec_irqs = qemu_allocate_irqs(cpu_set_ivec_irq, cpu, IVEC_MAX);
-    pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_bus2,
-                           &pci_bus3, &pbm_irqs);
-    pci_vga_init(pci_bus);
-
-    // XXX Should be pci_bus3
-    isa_bus = pci_ebus_init(pci_bus, -1, pbm_irqs);
-
-    i = 0;
-    if (hwdef->console_serial_base) {
-        serial_mm_init(address_space_mem, hwdef->console_serial_base, 0,
-                       NULL, 115200, serial_hds[i], DEVICE_BIG_ENDIAN);
-        i++;
-    }
-    for(; i < MAX_SERIAL_PORTS; i++) {
-        if (serial_hds[i]) {
-            serial_isa_init(isa_bus, i, serial_hds[i]);
-        }
-    }
-
-    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
-        if (parallel_hds[i]) {
-            parallel_init(isa_bus, i, parallel_hds[i]);
-        }
-    }
-
-    for(i = 0; i < nb_nics; i++)
-        pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
-
-    ide_drive_get(hd, MAX_IDE_BUS);
-
-    pci_cmd646_ide_init(pci_bus, hd, 1);
-
-    isa_create_simple(isa_bus, "i8042");
-    for(i = 0; i < MAX_FD; i++) {
-        fd[i] = drive_get(IF_FLOPPY, 0, i);
-    }
-    fdctrl_init_isa(isa_bus, fd);
-    nvram = m48t59_init_isa(isa_bus, 0x0074, NVRAM_SIZE, 59);
-
-    initrd_size = 0;
-    initrd_addr = 0;
-    kernel_size = sun4u_load_kernel(kernel_filename, initrd_filename,
-                                    ram_size, &initrd_size, &initrd_addr,
-                                    &kernel_addr, &kernel_entry);
-
-    sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", RAM_size, boot_devices,
-                           kernel_addr, kernel_size,
-                           kernel_cmdline,
-                           initrd_addr, initrd_size,
-                           /* XXX: need an option to load a NVRAM image */
-                           0,
-                           graphic_width, graphic_height, graphic_depth,
-                           (uint8_t *)&nd_table[0].macaddr);
-
-    fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
-    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
-    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
-    fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_entry);
-    fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
-    if (kernel_cmdline) {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
-                       strlen(kernel_cmdline) + 1);
-        fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
-    } else {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
-    }
-    fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
-    fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_devices[0]);
-
-    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_WIDTH, graphic_width);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_HEIGHT, graphic_height);
-    fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_DEPTH, graphic_depth);
-
-    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
-}
-
-enum {
-    sun4u_id = 0,
-    sun4v_id = 64,
-    niagara_id,
-};
-
-static const struct hwdef hwdefs[] = {
-    /* Sun4u generic PC-like machine */
-    {
-        .default_cpu_model = "TI UltraSparc IIi",
-        .machine_id = sun4u_id,
-        .prom_addr = 0x1fff0000000ULL,
-        .console_serial_base = 0,
-    },
-    /* Sun4v generic PC-like machine */
-    {
-        .default_cpu_model = "Sun UltraSparc T1",
-        .machine_id = sun4v_id,
-        .prom_addr = 0x1fff0000000ULL,
-        .console_serial_base = 0,
-    },
-    /* Sun4v generic Niagara machine */
-    {
-        .default_cpu_model = "Sun UltraSparc T1",
-        .machine_id = niagara_id,
-        .prom_addr = 0xfff0000000ULL,
-        .console_serial_base = 0xfff0c2c000ULL,
-    },
-};
-
-/* Sun4u hardware initialisation */
-static void sun4u_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_devices = args->boot_device;
-    sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
-                kernel_cmdline, initrd_filename, cpu_model, &hwdefs[0]);
-}
-
-/* Sun4v hardware initialisation */
-static void sun4v_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_devices = args->boot_device;
-    sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
-                kernel_cmdline, initrd_filename, cpu_model, &hwdefs[1]);
-}
-
-/* Niagara hardware initialisation */
-static void niagara_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t RAM_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    const char *boot_devices = args->boot_device;
-    sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
-                kernel_cmdline, initrd_filename, cpu_model, &hwdefs[2]);
-}
-
-static QEMUMachine sun4u_machine = {
-    .name = "sun4u",
-    .desc = "Sun4u platform",
-    .init = sun4u_init,
-    .max_cpus = 1, // XXX for now
-    .is_default = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine sun4v_machine = {
-    .name = "sun4v",
-    .desc = "Sun4v platform",
-    .init = sun4v_init,
-    .max_cpus = 1, // XXX for now
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine niagara_machine = {
-    .name = "Niagara",
-    .desc = "Sun4v platform, Niagara",
-    .init = niagara_init,
-    .max_cpus = 1, // XXX for now
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void sun4u_register_types(void)
-{
-    type_register_static(&ebus_info);
-    type_register_static(&prom_info);
-    type_register_static(&ram_info);
-}
-
-static void sun4u_machine_init(void)
-{
-    qemu_register_machine(&sun4u_machine);
-    qemu_register_machine(&sun4v_machine);
-    qemu_register_machine(&niagara_machine);
-}
-
-type_init(sun4u_register_types)
-machine_init(sun4u_machine_init);
diff --git a/hw/tosa.c b/hw/tosa.c
deleted file mode 100644
index 747888c..0000000
--- a/hw/tosa.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/* vim:set shiftwidth=4 ts=4 et: */
-/*
- * PXA255 Sharp Zaurus SL-6000 PDA platform
- *
- * Copyright (c) 2008 Dmitry Baryshkov
- *
- * Code based on spitz platform by Andrzej Zaborowski <balrog at zabor.org>
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "hw/hw.h"
-#include "hw/pxa.h"
-#include "hw/arm-misc.h"
-#include "hw/devices.h"
-#include "hw/sharpsl.h"
-#include "hw/pcmcia.h"
-#include "block/block.h"
-#include "hw/boards.h"
-#include "hw/i2c.h"
-#include "hw/ssi.h"
-#include "sysemu/blockdev.h"
-#include "hw/sysbus.h"
-#include "exec/address-spaces.h"
-
-#define TOSA_RAM    0x04000000
-#define TOSA_ROM	0x00800000
-
-#define TOSA_GPIO_USB_IN		(5)
-#define TOSA_GPIO_nSD_DETECT	(9)
-#define TOSA_GPIO_ON_RESET		(19)
-#define TOSA_GPIO_CF_IRQ		(21)	/* CF slot0 Ready */
-#define TOSA_GPIO_CF_CD			(13)
-#define TOSA_GPIO_TC6393XB_INT  (15)
-#define TOSA_GPIO_JC_CF_IRQ		(36)	/* CF slot1 Ready */
-
-#define TOSA_SCOOP_GPIO_BASE	1
-#define TOSA_GPIO_IR_POWERDWN	(TOSA_SCOOP_GPIO_BASE + 2)
-#define TOSA_GPIO_SD_WP			(TOSA_SCOOP_GPIO_BASE + 3)
-#define TOSA_GPIO_PWR_ON		(TOSA_SCOOP_GPIO_BASE + 4)
-
-#define TOSA_SCOOP_JC_GPIO_BASE		1
-#define TOSA_GPIO_BT_LED		(TOSA_SCOOP_JC_GPIO_BASE + 0)
-#define TOSA_GPIO_NOTE_LED		(TOSA_SCOOP_JC_GPIO_BASE + 1)
-#define TOSA_GPIO_CHRG_ERR_LED		(TOSA_SCOOP_JC_GPIO_BASE + 2)
-#define TOSA_GPIO_TC6393XB_L3V_ON	(TOSA_SCOOP_JC_GPIO_BASE + 5)
-#define TOSA_GPIO_WLAN_LED		(TOSA_SCOOP_JC_GPIO_BASE + 7)
-
-#define	DAC_BASE	0x4e
-#define DAC_CH1		0
-#define DAC_CH2		1
-
-static void tosa_microdrive_attach(PXA2xxState *cpu)
-{
-    PCMCIACardState *md;
-    DriveInfo *dinfo;
-
-    dinfo = drive_get(IF_IDE, 0, 0);
-    if (!dinfo || dinfo->media_cd)
-        return;
-    md = dscm1xxxx_init(dinfo);
-    pxa2xx_pcmcia_attach(cpu->pcmcia[0], md);
-}
-
-static void tosa_out_switch(void *opaque, int line, int level)
-{
-    switch (line) {
-        case 0:
-            fprintf(stderr, "blue LED %s.\n", level ? "on" : "off");
-            break;
-        case 1:
-            fprintf(stderr, "green LED %s.\n", level ? "on" : "off");
-            break;
-        case 2:
-            fprintf(stderr, "amber LED %s.\n", level ? "on" : "off");
-            break;
-        case 3:
-            fprintf(stderr, "wlan LED %s.\n", level ? "on" : "off");
-            break;
-        default:
-            fprintf(stderr, "Uhandled out event: %d = %d\n", line, level);
-            break;
-    }
-}
-
-
-static void tosa_gpio_setup(PXA2xxState *cpu,
-                DeviceState *scp0,
-                DeviceState *scp1,
-                TC6393xbState *tmio)
-{
-    qemu_irq *outsignals = qemu_allocate_irqs(tosa_out_switch, cpu, 4);
-    /* MMC/SD host */
-    pxa2xx_mmci_handlers(cpu->mmc,
-                    qdev_get_gpio_in(scp0, TOSA_GPIO_SD_WP),
-                    qemu_irq_invert(qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_nSD_DETECT)));
-
-    /* Handle reset */
-    qdev_connect_gpio_out(cpu->gpio, TOSA_GPIO_ON_RESET, cpu->reset);
-
-    /* PCMCIA signals: card's IRQ and Card-Detect */
-    pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
-                        qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_CF_IRQ),
-                        qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_CF_CD));
-
-    pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
-                        qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_JC_CF_IRQ),
-                        NULL);
-
-    qdev_connect_gpio_out(scp1, TOSA_GPIO_BT_LED, outsignals[0]);
-    qdev_connect_gpio_out(scp1, TOSA_GPIO_NOTE_LED, outsignals[1]);
-    qdev_connect_gpio_out(scp1, TOSA_GPIO_CHRG_ERR_LED, outsignals[2]);
-    qdev_connect_gpio_out(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]);
-
-    qdev_connect_gpio_out(scp1, TOSA_GPIO_TC6393XB_L3V_ON, tc6393xb_l3v_get(tmio));
-
-    /* UDC Vbus */
-    qemu_irq_raise(qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_USB_IN));
-}
-
-static uint32_t tosa_ssp_tansfer(SSISlave *dev, uint32_t value)
-{
-    fprintf(stderr, "TG: %d %02x\n", value >> 5, value & 0x1f);
-    return 0;
-}
-
-static int tosa_ssp_init(SSISlave *dev)
-{
-    /* Nothing to do.  */
-    return 0;
-}
-
-typedef struct {
-    I2CSlave i2c;
-    int len;
-    char buf[3];
-} TosaDACState;
-
-static int tosa_dac_send(I2CSlave *i2c, uint8_t data)
-{
-    TosaDACState *s = FROM_I2C_SLAVE(TosaDACState, i2c);
-    s->buf[s->len] = data;
-    if (s->len ++ > 2) {
-#ifdef VERBOSE
-        fprintf(stderr, "%s: message too long (%i bytes)\n", __FUNCTION__, s->len);
-#endif
-        return 1;
-    }
-
-    if (s->len == 2) {
-        fprintf(stderr, "dac: channel %d value 0x%02x\n",
-                s->buf[0], s->buf[1]);
-    }
-
-    return 0;
-}
-
-static void tosa_dac_event(I2CSlave *i2c, enum i2c_event event)
-{
-    TosaDACState *s = FROM_I2C_SLAVE(TosaDACState, i2c);
-    s->len = 0;
-    switch (event) {
-    case I2C_START_SEND:
-        break;
-    case I2C_START_RECV:
-        printf("%s: recv not supported!!!\n", __FUNCTION__);
-        break;
-    case I2C_FINISH:
-#ifdef VERBOSE
-        if (s->len < 2)
-            printf("%s: message too short (%i bytes)\n", __FUNCTION__, s->len);
-        if (s->len > 2)
-            printf("%s: message too long\n", __FUNCTION__);
-#endif
-        break;
-    default:
-        break;
-    }
-}
-
-static int tosa_dac_recv(I2CSlave *s)
-{
-    printf("%s: recv not supported!!!\n", __FUNCTION__);
-    return -1;
-}
-
-static int tosa_dac_init(I2CSlave *i2c)
-{
-    /* Nothing to do.  */
-    return 0;
-}
-
-static void tosa_tg_init(PXA2xxState *cpu)
-{
-    i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]);
-    i2c_create_slave(bus, "tosa_dac", DAC_BASE);
-    ssi_create_slave(cpu->ssp[1], "tosa-ssp");
-}
-
-
-static struct arm_boot_info tosa_binfo = {
-    .loader_start = PXA2XX_SDRAM_BASE,
-    .ram_size = 0x04000000,
-};
-
-static void tosa_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *rom = g_new(MemoryRegion, 1);
-    PXA2xxState *mpu;
-    TC6393xbState *tmio;
-    DeviceState *scp0, *scp1;
-
-    if (!cpu_model)
-        cpu_model = "pxa255";
-
-    mpu = pxa255_init(address_space_mem, tosa_binfo.ram_size);
-
-    memory_region_init_ram(rom, "tosa.rom", TOSA_ROM);
-    vmstate_register_ram_global(rom);
-    memory_region_set_readonly(rom, true);
-    memory_region_add_subregion(address_space_mem, 0, rom);
-
-    tmio = tc6393xb_init(address_space_mem, 0x10000000,
-            qdev_get_gpio_in(mpu->gpio, TOSA_GPIO_TC6393XB_INT));
-
-    scp0 = sysbus_create_simple("scoop", 0x08800000, NULL);
-    scp1 = sysbus_create_simple("scoop", 0x14800040, NULL);
-
-    tosa_gpio_setup(mpu, scp0, scp1, tmio);
-
-    tosa_microdrive_attach(mpu);
-
-    tosa_tg_init(mpu);
-
-    tosa_binfo.kernel_filename = kernel_filename;
-    tosa_binfo.kernel_cmdline = kernel_cmdline;
-    tosa_binfo.initrd_filename = initrd_filename;
-    tosa_binfo.board_id = 0x208;
-    arm_load_kernel(mpu->cpu, &tosa_binfo);
-    sl_bootparam_write(SL_PXA_PARAM_BASE);
-}
-
-static QEMUMachine tosapda_machine = {
-    .name = "tosa",
-    .desc = "Tosa PDA (PXA255)",
-    .init = tosa_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void tosapda_machine_init(void)
-{
-    qemu_register_machine(&tosapda_machine);
-}
-
-machine_init(tosapda_machine_init);
-
-static void tosa_dac_class_init(ObjectClass *klass, void *data)
-{
-    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
-
-    k->init = tosa_dac_init;
-    k->event = tosa_dac_event;
-    k->recv = tosa_dac_recv;
-    k->send = tosa_dac_send;
-}
-
-static const TypeInfo tosa_dac_info = {
-    .name          = "tosa_dac",
-    .parent        = TYPE_I2C_SLAVE,
-    .instance_size = sizeof(TosaDACState),
-    .class_init    = tosa_dac_class_init,
-};
-
-static void tosa_ssp_class_init(ObjectClass *klass, void *data)
-{
-    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
-
-    k->init = tosa_ssp_init;
-    k->transfer = tosa_ssp_tansfer;
-}
-
-static const TypeInfo tosa_ssp_info = {
-    .name          = "tosa-ssp",
-    .parent        = TYPE_SSI_SLAVE,
-    .instance_size = sizeof(SSISlave),
-    .class_init    = tosa_ssp_class_init,
-};
-
-static void tosa_register_types(void)
-{
-    type_register_static(&tosa_dac_info);
-    type_register_static(&tosa_ssp_info);
-}
-
-type_init(tosa_register_types)
diff --git a/hw/unicore32/Makefile.objs b/hw/unicore32/Makefile.objs
index 0725ce3..e0fd628 100644
--- a/hw/unicore32/Makefile.objs
+++ b/hw/unicore32/Makefile.objs
@@ -2,5 +2,3 @@
 
 # PKUnity-v3 SoC and board information
 obj-${CONFIG_PUV3} += puv3.o
-
-obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/unicore32/puv3.c b/hw/unicore32/puv3.c
new file mode 100644
index 0000000..f9d0c2b
--- /dev/null
+++ b/hw/unicore32/puv3.c
@@ -0,0 +1,135 @@
+/*
+ * Generic PKUnity SoC machine and board descriptor
+ *
+ * Copyright (C) 2010-2012 Guan Xuetao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation, or any later version.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu-common.h"
+#include "ui/console.h"
+#include "elf.h"
+#include "exec/address-spaces.h"
+#include "hw/sysbus.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/pc.h"
+
+#undef DEBUG_PUV3
+#include "hw/puv3.h"
+
+#define KERNEL_LOAD_ADDR        0x03000000
+#define KERNEL_MAX_SIZE         0x00800000 /* Just a guess */
+
+static void puv3_intc_cpu_handler(void *opaque, int irq, int level)
+{
+    CPUUniCore32State *env = opaque;
+
+    assert(irq == 0);
+    if (level) {
+        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    } else {
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+static void puv3_soc_init(CPUUniCore32State *env)
+{
+    qemu_irq *cpu_intc, irqs[PUV3_IRQS_NR];
+    DeviceState *dev;
+    MemoryRegion *i8042 = g_new(MemoryRegion, 1);
+    int i;
+
+    /* Initialize interrupt controller */
+    cpu_intc = qemu_allocate_irqs(puv3_intc_cpu_handler, env, 1);
+    dev = sysbus_create_simple("puv3_intc", PUV3_INTC_BASE, *cpu_intc);
+    for (i = 0; i < PUV3_IRQS_NR; i++) {
+        irqs[i] = qdev_get_gpio_in(dev, i);
+    }
+
+    /* Initialize minimal necessary devices for kernel booting */
+    sysbus_create_simple("puv3_pm", PUV3_PM_BASE, NULL);
+    sysbus_create_simple("puv3_dma", PUV3_DMA_BASE, NULL);
+    sysbus_create_simple("puv3_ost", PUV3_OST_BASE, irqs[PUV3_IRQS_OST0]);
+    sysbus_create_varargs("puv3_gpio", PUV3_GPIO_BASE,
+            irqs[PUV3_IRQS_GPIOLOW0], irqs[PUV3_IRQS_GPIOLOW1],
+            irqs[PUV3_IRQS_GPIOLOW2], irqs[PUV3_IRQS_GPIOLOW3],
+            irqs[PUV3_IRQS_GPIOLOW4], irqs[PUV3_IRQS_GPIOLOW5],
+            irqs[PUV3_IRQS_GPIOLOW6], irqs[PUV3_IRQS_GPIOLOW7],
+            irqs[PUV3_IRQS_GPIOHIGH], NULL);
+
+    /* Keyboard (i8042), mouse disabled for nographic */
+    i8042_mm_init(irqs[PUV3_IRQS_PS2_KBD], NULL, i8042, PUV3_REGS_OFFSET, 4);
+    memory_region_add_subregion(get_system_memory(), PUV3_PS2_BASE, i8042);
+}
+
+static void puv3_board_init(CPUUniCore32State *env, ram_addr_t ram_size)
+{
+    MemoryRegion *ram_memory = g_new(MemoryRegion, 1);
+
+    /* SDRAM at address zero.  */
+    memory_region_init_ram(ram_memory, "puv3.ram", ram_size);
+    vmstate_register_ram_global(ram_memory);
+    memory_region_add_subregion(get_system_memory(), 0, ram_memory);
+}
+
+static void puv3_load_kernel(const char *kernel_filename)
+{
+    int size;
+
+    assert(kernel_filename != NULL);
+
+    /* only zImage format supported */
+    size = load_image_targphys(kernel_filename, KERNEL_LOAD_ADDR,
+            KERNEL_MAX_SIZE);
+    if (size < 0) {
+        hw_error("Load kernel error: '%s'\n", kernel_filename);
+    }
+
+    /* cheat curses that we have a graphic console, only under ocd console */
+    graphic_console_init(NULL, NULL, NULL, NULL, NULL);
+}
+
+static void puv3_init(QEMUMachineInitArgs *args)
+{
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *initrd_filename = args->initrd_filename;
+    CPUUniCore32State *env;
+
+    if (initrd_filename) {
+        hw_error("Please use kernel built-in initramdisk.\n");
+    }
+
+    if (!cpu_model) {
+        cpu_model = "UniCore-II";
+    }
+
+    env = cpu_init(cpu_model);
+    if (!env) {
+        hw_error("Unable to find CPU definition\n");
+    }
+
+    puv3_soc_init(env);
+    puv3_board_init(env, ram_size);
+    puv3_load_kernel(kernel_filename);
+}
+
+static QEMUMachine puv3_machine = {
+    .name = "puv3",
+    .desc = "PKUnity Version-3 based on UniCore32",
+    .init = puv3_init,
+    .is_default = 1,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void puv3_machine_init(void)
+{
+    qemu_register_machine(&puv3_machine);
+}
+
+machine_init(puv3_machine_init)
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
deleted file mode 100644
index baaa265..0000000
--- a/hw/versatilepb.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * ARM Versatile Platform/Application Baseboard System emulation.
- *
- * Copyright (c) 2005-2007 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GPL.
- */
-
-#include "hw/sysbus.h"
-#include "hw/arm-misc.h"
-#include "hw/devices.h"
-#include "net/net.h"
-#include "sysemu/sysemu.h"
-#include "hw/pci/pci.h"
-#include "hw/i2c.h"
-#include "hw/boards.h"
-#include "sysemu/blockdev.h"
-#include "exec/address-spaces.h"
-#include "hw/flash.h"
-
-#define VERSATILE_FLASH_ADDR 0x34000000
-#define VERSATILE_FLASH_SIZE (64 * 1024 * 1024)
-#define VERSATILE_FLASH_SECT_SIZE (256 * 1024)
-
-/* Primary interrupt controller.  */
-
-typedef struct vpb_sic_state
-{
-  SysBusDevice busdev;
-  MemoryRegion iomem;
-  uint32_t level;
-  uint32_t mask;
-  uint32_t pic_enable;
-  qemu_irq parent[32];
-  int irq;
-} vpb_sic_state;
-
-static const VMStateDescription vmstate_vpb_sic = {
-    .name = "versatilepb_sic",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(level, vpb_sic_state),
-        VMSTATE_UINT32(mask, vpb_sic_state),
-        VMSTATE_UINT32(pic_enable, vpb_sic_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void vpb_sic_update(vpb_sic_state *s)
-{
-    uint32_t flags;
-
-    flags = s->level & s->mask;
-    qemu_set_irq(s->parent[s->irq], flags != 0);
-}
-
-static void vpb_sic_update_pic(vpb_sic_state *s)
-{
-    int i;
-    uint32_t mask;
-
-    for (i = 21; i <= 30; i++) {
-        mask = 1u << i;
-        if (!(s->pic_enable & mask))
-            continue;
-        qemu_set_irq(s->parent[i], (s->level & mask) != 0);
-    }
-}
-
-static void vpb_sic_set_irq(void *opaque, int irq, int level)
-{
-    vpb_sic_state *s = (vpb_sic_state *)opaque;
-    if (level)
-        s->level |= 1u << irq;
-    else
-        s->level &= ~(1u << irq);
-    if (s->pic_enable & (1u << irq))
-        qemu_set_irq(s->parent[irq], level);
-    vpb_sic_update(s);
-}
-
-static uint64_t vpb_sic_read(void *opaque, hwaddr offset,
-                             unsigned size)
-{
-    vpb_sic_state *s = (vpb_sic_state *)opaque;
-
-    switch (offset >> 2) {
-    case 0: /* STATUS */
-        return s->level & s->mask;
-    case 1: /* RAWSTAT */
-        return s->level;
-    case 2: /* ENABLE */
-        return s->mask;
-    case 4: /* SOFTINT */
-        return s->level & 1;
-    case 8: /* PICENABLE */
-        return s->pic_enable;
-    default:
-        printf ("vpb_sic_read: Bad register offset 0x%x\n", (int)offset);
-        return 0;
-    }
-}
-
-static void vpb_sic_write(void *opaque, hwaddr offset,
-                          uint64_t value, unsigned size)
-{
-    vpb_sic_state *s = (vpb_sic_state *)opaque;
-
-    switch (offset >> 2) {
-    case 2: /* ENSET */
-        s->mask |= value;
-        break;
-    case 3: /* ENCLR */
-        s->mask &= ~value;
-        break;
-    case 4: /* SOFTINTSET */
-        if (value)
-            s->mask |= 1;
-        break;
-    case 5: /* SOFTINTCLR */
-        if (value)
-            s->mask &= ~1u;
-        break;
-    case 8: /* PICENSET */
-        s->pic_enable |= (value & 0x7fe00000);
-        vpb_sic_update_pic(s);
-        break;
-    case 9: /* PICENCLR */
-        s->pic_enable &= ~value;
-        vpb_sic_update_pic(s);
-        break;
-    default:
-        printf ("vpb_sic_write: Bad register offset 0x%x\n", (int)offset);
-        return;
-    }
-    vpb_sic_update(s);
-}
-
-static const MemoryRegionOps vpb_sic_ops = {
-    .read = vpb_sic_read,
-    .write = vpb_sic_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int vpb_sic_init(SysBusDevice *dev)
-{
-    vpb_sic_state *s = FROM_SYSBUS(vpb_sic_state, dev);
-    int i;
-
-    qdev_init_gpio_in(&dev->qdev, vpb_sic_set_irq, 32);
-    for (i = 0; i < 32; i++) {
-        sysbus_init_irq(dev, &s->parent[i]);
-    }
-    s->irq = 31;
-    memory_region_init_io(&s->iomem, &vpb_sic_ops, s, "vpb-sic", 0x1000);
-    sysbus_init_mmio(dev, &s->iomem);
-    return 0;
-}
-
-/* Board init.  */
-
-/* The AB and PB boards both use the same core, just with different
-   peripherals and expansion busses.  For now we emulate a subset of the
-   PB peripherals and just change the board ID.  */
-
-static struct arm_boot_info versatile_binfo;
-
-static void versatile_init(QEMUMachineInitArgs *args, int board_id)
-{
-    ARMCPU *cpu;
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    qemu_irq *cpu_pic;
-    qemu_irq pic[32];
-    qemu_irq sic[32];
-    DeviceState *dev, *sysctl;
-    SysBusDevice *busdev;
-    DeviceState *pl041;
-    PCIBus *pci_bus;
-    NICInfo *nd;
-    i2c_bus *i2c;
-    int n;
-    int done_smc = 0;
-    DriveInfo *dinfo;
-
-    if (!args->cpu_model) {
-        args->cpu_model = "arm926";
-    }
-    cpu = cpu_arm_init(args->cpu_model);
-    if (!cpu) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    memory_region_init_ram(ram, "versatile.ram", args->ram_size);
-    vmstate_register_ram_global(ram);
-    /* ??? RAM should repeat to fill physical memory space.  */
-    /* SDRAM at address zero.  */
-    memory_region_add_subregion(sysmem, 0, ram);
-
-    sysctl = qdev_create(NULL, "realview_sysctl");
-    qdev_prop_set_uint32(sysctl, "sys_id", 0x41007004);
-    qdev_prop_set_uint32(sysctl, "proc_id", 0x02000000);
-    qdev_init_nofail(sysctl);
-    sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
-
-    cpu_pic = arm_pic_init_cpu(cpu);
-    dev = sysbus_create_varargs("pl190", 0x10140000,
-                                cpu_pic[ARM_PIC_CPU_IRQ],
-                                cpu_pic[ARM_PIC_CPU_FIQ], NULL);
-    for (n = 0; n < 32; n++) {
-        pic[n] = qdev_get_gpio_in(dev, n);
-    }
-    dev = sysbus_create_simple("versatilepb_sic", 0x10003000, NULL);
-    for (n = 0; n < 32; n++) {
-        sysbus_connect_irq(SYS_BUS_DEVICE(dev), n, pic[n]);
-        sic[n] = qdev_get_gpio_in(dev, n);
-    }
-
-    sysbus_create_simple("pl050_keyboard", 0x10006000, sic[3]);
-    sysbus_create_simple("pl050_mouse", 0x10007000, sic[4]);
-
-    dev = qdev_create(NULL, "versatile_pci");
-    busdev = SYS_BUS_DEVICE(dev);
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(busdev, 0, 0x41000000); /* PCI self-config */
-    sysbus_mmio_map(busdev, 1, 0x42000000); /* PCI config */
-    sysbus_connect_irq(busdev, 0, sic[27]);
-    sysbus_connect_irq(busdev, 1, sic[28]);
-    sysbus_connect_irq(busdev, 2, sic[29]);
-    sysbus_connect_irq(busdev, 3, sic[30]);
-    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
-
-    /* The Versatile PCI bridge does not provide access to PCI IO space,
-       so many of the qemu PCI devices are not useable.  */
-    for(n = 0; n < nb_nics; n++) {
-        nd = &nd_table[n];
-
-        if (!done_smc && (!nd->model || strcmp(nd->model, "smc91c111") == 0)) {
-            smc91c111_init(nd, 0x10010000, sic[25]);
-            done_smc = 1;
-        } else {
-            pci_nic_init_nofail(nd, "rtl8139", NULL);
-        }
-    }
-    if (usb_enabled(false)) {
-        pci_create_simple(pci_bus, -1, "pci-ohci");
-    }
-    n = drive_get_max_bus(IF_SCSI);
-    while (n >= 0) {
-        pci_create_simple(pci_bus, -1, "lsi53c895a");
-        n--;
-    }
-
-    sysbus_create_simple("pl011", 0x101f1000, pic[12]);
-    sysbus_create_simple("pl011", 0x101f2000, pic[13]);
-    sysbus_create_simple("pl011", 0x101f3000, pic[14]);
-    sysbus_create_simple("pl011", 0x10009000, sic[6]);
-
-    sysbus_create_simple("pl080", 0x10130000, pic[17]);
-    sysbus_create_simple("sp804", 0x101e2000, pic[4]);
-    sysbus_create_simple("sp804", 0x101e3000, pic[5]);
-
-    sysbus_create_simple("pl061", 0x101e4000, pic[6]);
-    sysbus_create_simple("pl061", 0x101e5000, pic[7]);
-    sysbus_create_simple("pl061", 0x101e6000, pic[8]);
-    sysbus_create_simple("pl061", 0x101e7000, pic[9]);
-
-    /* The versatile/PB actually has a modified Color LCD controller
-       that includes hardware cursor support from the PL111.  */
-    dev = sysbus_create_simple("pl110_versatile", 0x10120000, pic[16]);
-    /* Wire up the mux control signals from the SYS_CLCD register */
-    qdev_connect_gpio_out(sysctl, 0, qdev_get_gpio_in(dev, 0));
-
-    sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL);
-    sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL);
-
-    /* Add PL031 Real Time Clock. */
-    sysbus_create_simple("pl031", 0x101e8000, pic[10]);
-
-    dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL);
-    i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
-    i2c_create_slave(i2c, "ds1338", 0x68);
-
-    /* Add PL041 AACI Interface to the LM4549 codec */
-    pl041 = qdev_create(NULL, "pl041");
-    qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
-    qdev_init_nofail(pl041);
-    sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000);
-    sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, sic[24]);
-
-    /* Memory map for Versatile/PB:  */
-    /* 0x10000000 System registers.  */
-    /* 0x10001000 PCI controller config registers.  */
-    /* 0x10002000 Serial bus interface.  */
-    /*  0x10003000 Secondary interrupt controller.  */
-    /* 0x10004000 AACI (audio).  */
-    /*  0x10005000 MMCI0.  */
-    /*  0x10006000 KMI0 (keyboard).  */
-    /*  0x10007000 KMI1 (mouse).  */
-    /* 0x10008000 Character LCD Interface.  */
-    /*  0x10009000 UART3.  */
-    /* 0x1000a000 Smart card 1.  */
-    /*  0x1000b000 MMCI1.  */
-    /*  0x10010000 Ethernet.  */
-    /* 0x10020000 USB.  */
-    /* 0x10100000 SSMC.  */
-    /* 0x10110000 MPMC.  */
-    /*  0x10120000 CLCD Controller.  */
-    /*  0x10130000 DMA Controller.  */
-    /*  0x10140000 Vectored interrupt controller.  */
-    /* 0x101d0000 AHB Monitor Interface.  */
-    /* 0x101e0000 System Controller.  */
-    /* 0x101e1000 Watchdog Interface.  */
-    /* 0x101e2000 Timer 0/1.  */
-    /* 0x101e3000 Timer 2/3.  */
-    /* 0x101e4000 GPIO port 0.  */
-    /* 0x101e5000 GPIO port 1.  */
-    /* 0x101e6000 GPIO port 2.  */
-    /* 0x101e7000 GPIO port 3.  */
-    /* 0x101e8000 RTC.  */
-    /* 0x101f0000 Smart card 0.  */
-    /*  0x101f1000 UART0.  */
-    /*  0x101f2000 UART1.  */
-    /*  0x101f3000 UART2.  */
-    /* 0x101f4000 SSPI.  */
-    /* 0x34000000 NOR Flash */
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, NULL, "versatile.flash",
-                          VERSATILE_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL,
-                          VERSATILE_FLASH_SECT_SIZE,
-                          VERSATILE_FLASH_SIZE / VERSATILE_FLASH_SECT_SIZE,
-                          4, 0x0089, 0x0018, 0x0000, 0x0, 0)) {
-        fprintf(stderr, "qemu: Error registering flash memory.\n");
-    }
-
-    versatile_binfo.ram_size = args->ram_size;
-    versatile_binfo.kernel_filename = args->kernel_filename;
-    versatile_binfo.kernel_cmdline = args->kernel_cmdline;
-    versatile_binfo.initrd_filename = args->initrd_filename;
-    versatile_binfo.board_id = board_id;
-    arm_load_kernel(cpu, &versatile_binfo);
-}
-
-static void vpb_init(QEMUMachineInitArgs *args)
-{
-    versatile_init(args, 0x183);
-}
-
-static void vab_init(QEMUMachineInitArgs *args)
-{
-    versatile_init(args, 0x25e);
-}
-
-static QEMUMachine versatilepb_machine = {
-    .name = "versatilepb",
-    .desc = "ARM Versatile/PB (ARM926EJ-S)",
-    .init = vpb_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine versatileab_machine = {
-    .name = "versatileab",
-    .desc = "ARM Versatile/AB (ARM926EJ-S)",
-    .init = vab_init,
-    .block_default_type = IF_SCSI,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void versatile_machine_init(void)
-{
-    qemu_register_machine(&versatilepb_machine);
-    qemu_register_machine(&versatileab_machine);
-}
-
-machine_init(versatile_machine_init);
-
-static void vpb_sic_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = vpb_sic_init;
-    dc->no_user = 1;
-    dc->vmsd = &vmstate_vpb_sic;
-}
-
-static const TypeInfo vpb_sic_info = {
-    .name          = "versatilepb_sic",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(vpb_sic_state),
-    .class_init    = vpb_sic_class_init,
-};
-
-static void versatilepb_register_types(void)
-{
-    type_register_static(&vpb_sic_info);
-}
-
-type_init(versatilepb_register_types)
diff --git a/hw/vexpress.c b/hw/vexpress.c
deleted file mode 100644
index 02922c3..0000000
--- a/hw/vexpress.c
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * 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/>.
- *
- *  Contributions after 2012-01-13 are licensed under the terms of the
- *  GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "hw/sysbus.h"
-#include "hw/arm-misc.h"
-#include "hw/primecell.h"
-#include "hw/devices.h"
-#include "net/net.h"
-#include "sysemu/sysemu.h"
-#include "hw/boards.h"
-#include "exec/address-spaces.h"
-#include "sysemu/blockdev.h"
-#include "hw/flash.h"
-
-#define VEXPRESS_BOARD_ID 0x8e0
-#define VEXPRESS_FLASH_SIZE (64 * 1024 * 1024)
-#define VEXPRESS_FLASH_SECT_SIZE (256 * 1024)
-
-static struct arm_boot_info vexpress_binfo;
-
-/* Address maps for peripherals:
- * the Versatile Express motherboard has two possible maps,
- * the "legacy" one (used for A9) and the "Cortex-A Series"
- * map (used for newer cores).
- * Individual daughterboards can also have different maps for
- * their peripherals.
- */
-
-enum {
-    VE_SYSREGS,
-    VE_SP810,
-    VE_SERIALPCI,
-    VE_PL041,
-    VE_MMCI,
-    VE_KMI0,
-    VE_KMI1,
-    VE_UART0,
-    VE_UART1,
-    VE_UART2,
-    VE_UART3,
-    VE_WDT,
-    VE_TIMER01,
-    VE_TIMER23,
-    VE_SERIALDVI,
-    VE_RTC,
-    VE_COMPACTFLASH,
-    VE_CLCD,
-    VE_NORFLASH0,
-    VE_NORFLASH1,
-    VE_SRAM,
-    VE_VIDEORAM,
-    VE_ETHERNET,
-    VE_USB,
-    VE_DAPROM,
-};
-
-static hwaddr motherboard_legacy_map[] = {
-    /* CS7: 0x10000000 .. 0x10020000 */
-    [VE_SYSREGS] = 0x10000000,
-    [VE_SP810] = 0x10001000,
-    [VE_SERIALPCI] = 0x10002000,
-    [VE_PL041] = 0x10004000,
-    [VE_MMCI] = 0x10005000,
-    [VE_KMI0] = 0x10006000,
-    [VE_KMI1] = 0x10007000,
-    [VE_UART0] = 0x10009000,
-    [VE_UART1] = 0x1000a000,
-    [VE_UART2] = 0x1000b000,
-    [VE_UART3] = 0x1000c000,
-    [VE_WDT] = 0x1000f000,
-    [VE_TIMER01] = 0x10011000,
-    [VE_TIMER23] = 0x10012000,
-    [VE_SERIALDVI] = 0x10016000,
-    [VE_RTC] = 0x10017000,
-    [VE_COMPACTFLASH] = 0x1001a000,
-    [VE_CLCD] = 0x1001f000,
-    /* CS0: 0x40000000 .. 0x44000000 */
-    [VE_NORFLASH0] = 0x40000000,
-    /* CS1: 0x44000000 .. 0x48000000 */
-    [VE_NORFLASH1] = 0x44000000,
-    /* CS2: 0x48000000 .. 0x4a000000 */
-    [VE_SRAM] = 0x48000000,
-    /* CS3: 0x4c000000 .. 0x50000000 */
-    [VE_VIDEORAM] = 0x4c000000,
-    [VE_ETHERNET] = 0x4e000000,
-    [VE_USB] = 0x4f000000,
-};
-
-static hwaddr motherboard_aseries_map[] = {
-    /* CS0: 0x08000000 .. 0x0c000000 */
-    [VE_NORFLASH0] = 0x08000000,
-    /* CS4: 0x0c000000 .. 0x10000000 */
-    [VE_NORFLASH1] = 0x0c000000,
-    /* CS5: 0x10000000 .. 0x14000000 */
-    /* CS1: 0x14000000 .. 0x18000000 */
-    [VE_SRAM] = 0x14000000,
-    /* CS2: 0x18000000 .. 0x1c000000 */
-    [VE_VIDEORAM] = 0x18000000,
-    [VE_ETHERNET] = 0x1a000000,
-    [VE_USB] = 0x1b000000,
-    /* CS3: 0x1c000000 .. 0x20000000 */
-    [VE_DAPROM] = 0x1c000000,
-    [VE_SYSREGS] = 0x1c010000,
-    [VE_SP810] = 0x1c020000,
-    [VE_SERIALPCI] = 0x1c030000,
-    [VE_PL041] = 0x1c040000,
-    [VE_MMCI] = 0x1c050000,
-    [VE_KMI0] = 0x1c060000,
-    [VE_KMI1] = 0x1c070000,
-    [VE_UART0] = 0x1c090000,
-    [VE_UART1] = 0x1c0a0000,
-    [VE_UART2] = 0x1c0b0000,
-    [VE_UART3] = 0x1c0c0000,
-    [VE_WDT] = 0x1c0f0000,
-    [VE_TIMER01] = 0x1c110000,
-    [VE_TIMER23] = 0x1c120000,
-    [VE_SERIALDVI] = 0x1c160000,
-    [VE_RTC] = 0x1c170000,
-    [VE_COMPACTFLASH] = 0x1c1a0000,
-    [VE_CLCD] = 0x1c1f0000,
-};
-
-/* Structure defining the peculiarities of a specific daughterboard */
-
-typedef struct VEDBoardInfo VEDBoardInfo;
-
-typedef void DBoardInitFn(const VEDBoardInfo *daughterboard,
-                          ram_addr_t ram_size,
-                          const char *cpu_model,
-                          qemu_irq *pic, uint32_t *proc_id);
-
-struct VEDBoardInfo {
-    const hwaddr *motherboard_map;
-    hwaddr loader_start;
-    const hwaddr gic_cpu_if_addr;
-    DBoardInitFn *init;
-};
-
-static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
-                                  ram_addr_t ram_size,
-                                  const char *cpu_model,
-                                  qemu_irq *pic, uint32_t *proc_id)
-{
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *lowram = g_new(MemoryRegion, 1);
-    DeviceState *dev;
-    SysBusDevice *busdev;
-    qemu_irq *irqp;
-    int n;
-    qemu_irq cpu_irq[4];
-    ram_addr_t low_ram_size;
-
-    if (!cpu_model) {
-        cpu_model = "cortex-a9";
-    }
-
-    *proc_id = 0x0c000191;
-
-    for (n = 0; n < smp_cpus; n++) {
-        ARMCPU *cpu = cpu_arm_init(cpu_model);
-        if (!cpu) {
-            fprintf(stderr, "Unable to find CPU definition\n");
-            exit(1);
-        }
-        irqp = arm_pic_init_cpu(cpu);
-        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
-    }
-
-    if (ram_size > 0x40000000) {
-        /* 1GB is the maximum the address space permits */
-        fprintf(stderr, "vexpress-a9: cannot model more than 1GB RAM\n");
-        exit(1);
-    }
-
-    memory_region_init_ram(ram, "vexpress.highmem", ram_size);
-    vmstate_register_ram_global(ram);
-    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.
-     */
-    memory_region_init_alias(lowram, "vexpress.lowmem", ram, 0, low_ram_size);
-    memory_region_add_subregion(sysmem, 0x0, lowram);
-    memory_region_add_subregion(sysmem, 0x60000000, 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 = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(busdev, 0, 0x1e000000);
-    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);
-    }
-
-    /* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
-
-    /* 0x10020000 PL111 CLCD (daughterboard) */
-    sysbus_create_simple("pl111", 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 */
-    sysbus_create_varargs("l2x0", 0x1e00a000, NULL);
-}
-
-static const VEDBoardInfo a9_daughterboard = {
-    .motherboard_map = motherboard_legacy_map,
-    .loader_start = 0x60000000,
-    .gic_cpu_if_addr = 0x1e000100,
-    .init = a9_daughterboard_init,
-};
-
-static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
-                                   ram_addr_t ram_size,
-                                   const char *cpu_model,
-                                   qemu_irq *pic, uint32_t *proc_id)
-{
-    int n;
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *ram = g_new(MemoryRegion, 1);
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-    qemu_irq cpu_irq[4];
-    DeviceState *dev;
-    SysBusDevice *busdev;
-
-    if (!cpu_model) {
-        cpu_model = "cortex-a15";
-    }
-
-    *proc_id = 0x14000237;
-
-    for (n = 0; n < smp_cpus; n++) {
-        ARMCPU *cpu;
-        qemu_irq *irqp;
-
-        cpu = cpu_arm_init(cpu_model);
-        if (!cpu) {
-            fprintf(stderr, "Unable to find CPU definition\n");
-            exit(1);
-        }
-        irqp = arm_pic_init_cpu(cpu);
-        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
-    }
-
-    {
-        /* We have to use a separate 64 bit variable here to avoid the gcc
-         * "comparison is always false due to limited range of data type"
-         * warning if we are on a host where ram_addr_t is 32 bits.
-         */
-        uint64_t rsz = ram_size;
-        if (rsz > (30ULL * 1024 * 1024 * 1024)) {
-            fprintf(stderr, "vexpress-a15: cannot model more than 30GB RAM\n");
-            exit(1);
-        }
-    }
-
-    memory_region_init_ram(ram, "vexpress.highmem", ram_size);
-    vmstate_register_ram_global(ram);
-    /* RAM is from 0x80000000 upwards; there is no low-memory alias for it. */
-    memory_region_add_subregion(sysmem, 0x80000000, ram);
-
-    /* 0x2c000000 A15MPCore private memory region (GIC) */
-    dev = qdev_create(NULL, "a15mpcore_priv");
-    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(busdev, 0, 0x2c000000);
-    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 there
-     * are internal interrupts 0..31).
-     */
-    for (n = 0; n < 64; n++) {
-        pic[n] = qdev_get_gpio_in(dev, n);
-    }
-
-    /* A15 daughterboard peripherals: */
-
-    /* 0x20000000: CoreSight interfaces: not modelled */
-    /* 0x2a000000: PL301 AXI interconnect: not modelled */
-    /* 0x2a420000: SCC: not modelled */
-    /* 0x2a430000: system counter: not modelled */
-    /* 0x2b000000: HDLCD controller: not modelled */
-    /* 0x2b060000: SP805 watchdog: not modelled */
-    /* 0x2b0a0000: PL341 dynamic memory controller: not modelled */
-    /* 0x2e000000: system SRAM */
-    memory_region_init_ram(sram, "vexpress.a15sram", 0x10000);
-    vmstate_register_ram_global(sram);
-    memory_region_add_subregion(sysmem, 0x2e000000, sram);
-
-    /* 0x7ffb0000: DMA330 DMA controller: not modelled */
-    /* 0x7ffd0000: PL354 static memory controller: not modelled */
-}
-
-static const VEDBoardInfo a15_daughterboard = {
-    .motherboard_map = motherboard_aseries_map,
-    .loader_start = 0x80000000,
-    .gic_cpu_if_addr = 0x2c002000,
-    .init = a15_daughterboard_init,
-};
-
-static void vexpress_common_init(const VEDBoardInfo *daughterboard,
-                                 QEMUMachineInitArgs *args)
-{
-    DeviceState *dev, *sysctl, *pl041;
-    qemu_irq pic[64];
-    uint32_t proc_id;
-    uint32_t sys_id;
-    DriveInfo *dinfo;
-    ram_addr_t vram_size, sram_size;
-    MemoryRegion *sysmem = get_system_memory();
-    MemoryRegion *vram = g_new(MemoryRegion, 1);
-    MemoryRegion *sram = g_new(MemoryRegion, 1);
-    const hwaddr *map = daughterboard->motherboard_map;
-
-    daughterboard->init(daughterboard, args->ram_size, args->cpu_model,
-                        pic, &proc_id);
-
-    /* Motherboard peripherals: the wiring is the same but the
-     * addresses vary between the legacy and A-Series memory maps.
-     */
-
-    sys_id = 0x1190f500;
-
-    sysctl = qdev_create(NULL, "realview_sysctl");
-    qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
-    qdev_prop_set_uint32(sysctl, "proc_id", proc_id);
-    qdev_init_nofail(sysctl);
-    sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, map[VE_SYSREGS]);
-
-    /* VE_SP810: not modelled */
-    /* VE_SERIALPCI: not modelled */
-
-    pl041 = qdev_create(NULL, "pl041");
-    qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
-    qdev_init_nofail(pl041);
-    sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, map[VE_PL041]);
-    sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, pic[11]);
-
-    dev = sysbus_create_varargs("pl181", map[VE_MMCI], 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", map[VE_KMI0], pic[12]);
-    sysbus_create_simple("pl050_mouse", map[VE_KMI1], pic[13]);
-
-    sysbus_create_simple("pl011", map[VE_UART0], pic[5]);
-    sysbus_create_simple("pl011", map[VE_UART1], pic[6]);
-    sysbus_create_simple("pl011", map[VE_UART2], pic[7]);
-    sysbus_create_simple("pl011", map[VE_UART3], pic[8]);
-
-    sysbus_create_simple("sp804", map[VE_TIMER01], pic[2]);
-    sysbus_create_simple("sp804", map[VE_TIMER23], pic[3]);
-
-    /* VE_SERIALDVI: not modelled */
-
-    sysbus_create_simple("pl031", map[VE_RTC], pic[4]); /* RTC */
-
-    /* VE_COMPACTFLASH: not modelled */
-
-    sysbus_create_simple("pl111", map[VE_CLCD], pic[14]);
-
-    dinfo = drive_get_next(IF_PFLASH);
-    if (!pflash_cfi01_register(map[VE_NORFLASH0], NULL, "vexpress.flash0",
-            VEXPRESS_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL,
-            VEXPRESS_FLASH_SECT_SIZE,
-            VEXPRESS_FLASH_SIZE / VEXPRESS_FLASH_SECT_SIZE, 4,
-            0x00, 0x89, 0x00, 0x18, 0)) {
-        fprintf(stderr, "vexpress: error registering flash 0.\n");
-        exit(1);
-    }
-
-    dinfo = drive_get_next(IF_PFLASH);
-    if (!pflash_cfi01_register(map[VE_NORFLASH1], NULL, "vexpress.flash1",
-            VEXPRESS_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL,
-            VEXPRESS_FLASH_SECT_SIZE,
-            VEXPRESS_FLASH_SIZE / VEXPRESS_FLASH_SECT_SIZE, 4,
-            0x00, 0x89, 0x00, 0x18, 0)) {
-        fprintf(stderr, "vexpress: error registering flash 1.\n");
-        exit(1);
-    }
-
-    sram_size = 0x2000000;
-    memory_region_init_ram(sram, "vexpress.sram", sram_size);
-    vmstate_register_ram_global(sram);
-    memory_region_add_subregion(sysmem, map[VE_SRAM], sram);
-
-    vram_size = 0x800000;
-    memory_region_init_ram(vram, "vexpress.vram", vram_size);
-    vmstate_register_ram_global(vram);
-    memory_region_add_subregion(sysmem, map[VE_VIDEORAM], vram);
-
-    /* 0x4e000000 LAN9118 Ethernet */
-    if (nd_table[0].used) {
-        lan9118_init(&nd_table[0], map[VE_ETHERNET], pic[15]);
-    }
-
-    /* VE_USB: not modelled */
-
-    /* VE_DAPROM: not modelled */
-
-    vexpress_binfo.ram_size = args->ram_size;
-    vexpress_binfo.kernel_filename = args->kernel_filename;
-    vexpress_binfo.kernel_cmdline = args->kernel_cmdline;
-    vexpress_binfo.initrd_filename = args->initrd_filename;
-    vexpress_binfo.nb_cpus = smp_cpus;
-    vexpress_binfo.board_id = VEXPRESS_BOARD_ID;
-    vexpress_binfo.loader_start = daughterboard->loader_start;
-    vexpress_binfo.smp_loader_start = map[VE_SRAM];
-    vexpress_binfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30;
-    vexpress_binfo.gic_cpu_if_addr = daughterboard->gic_cpu_if_addr;
-    arm_load_kernel(arm_env_get_cpu(first_cpu), &vexpress_binfo);
-}
-
-static void vexpress_a9_init(QEMUMachineInitArgs *args)
-{
-    vexpress_common_init(&a9_daughterboard, args);
-}
-
-static void vexpress_a15_init(QEMUMachineInitArgs *args)
-{
-    vexpress_common_init(&a15_daughterboard, args);
-}
-
-static QEMUMachine vexpress_a9_machine = {
-    .name = "vexpress-a9",
-    .desc = "ARM Versatile Express for Cortex-A9",
-    .init = vexpress_a9_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine vexpress_a15_machine = {
-    .name = "vexpress-a15",
-    .desc = "ARM Versatile Express for Cortex-A15",
-    .init = vexpress_a15_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void vexpress_machine_init(void)
-{
-    qemu_register_machine(&vexpress_a9_machine);
-    qemu_register_machine(&vexpress_a15_machine);
-}
-
-machine_init(vexpress_machine_init);
diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
deleted file mode 100644
index 41eab16..0000000
--- a/hw/virtex_ml507.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Model of Xilinx Virtex5 ML507 PPC-440 refdesign.
- *
- * Copyright (c) 2010 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 "hw/sysbus.h"
-#include "hw/hw.h"
-#include "hw/serial.h"
-#include "hw/flash.h"
-#include "sysemu/sysemu.h"
-#include "hw/devices.h"
-#include "hw/boards.h"
-#include "sysemu/device_tree.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "qemu/log.h"
-#include "exec/address-spaces.h"
-
-#include "hw/ppc.h"
-#include "hw/ppc4xx.h"
-#include "hw/ppc405.h"
-
-#include "sysemu/blockdev.h"
-#include "hw/xilinx.h"
-
-#define EPAPR_MAGIC    (0x45504150)
-#define FLASH_SIZE     (16 * 1024 * 1024)
-
-static struct boot_info
-{
-    uint32_t bootstrap_pc;
-    uint32_t cmdline;
-    uint32_t fdt;
-    uint32_t ima_size;
-    void *vfdt;
-} boot_info;
-
-/* Create reset TLB entries for BookE, spanning the 32bit addr space.  */
-static void mmubooke_create_initial_mapping(CPUPPCState *env,
-                                     target_ulong va,
-                                     hwaddr pa)
-{
-    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
-
-    tlb->attr = 0;
-    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
-    tlb->size = 1 << 31; /* up to 0x80000000  */
-    tlb->EPN = va & TARGET_PAGE_MASK;
-    tlb->RPN = pa & TARGET_PAGE_MASK;
-    tlb->PID = 0;
-
-    tlb = &env->tlb.tlbe[1];
-    tlb->attr = 0;
-    tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
-    tlb->size = 1 << 31; /* up to 0xffffffff  */
-    tlb->EPN = 0x80000000 & TARGET_PAGE_MASK;
-    tlb->RPN = 0x80000000 & TARGET_PAGE_MASK;
-    tlb->PID = 0;
-}
-
-static PowerPCCPU *ppc440_init_xilinx(ram_addr_t *ram_size,
-                                      int do_init,
-                                      const char *cpu_model,
-                                      uint32_t sysclk)
-{
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    qemu_irq *irqs;
-
-    cpu = cpu_ppc_init(cpu_model);
-    if (cpu == NULL) {
-        fprintf(stderr, "Unable to initialize CPU!\n");
-        exit(1);
-    }
-    env = &cpu->env;
-
-    ppc_booke_timers_init(cpu, sysclk, 0/* no flags */);
-
-    ppc_dcr_init(env, NULL, NULL);
-
-    /* interrupt controller */
-    irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
-    irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
-    irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
-    ppcuic_init(env, irqs, 0x0C0, 0, 1);
-    return cpu;
-}
-
-static void main_cpu_reset(void *opaque)
-{
-    PowerPCCPU *cpu = opaque;
-    CPUPPCState *env = &cpu->env;
-    struct boot_info *bi = env->load_info;
-
-    cpu_reset(CPU(cpu));
-    /* Linux Kernel Parameters (passing device tree):
-       *   r3: pointer to the fdt
-       *   r4: 0
-       *   r5: 0
-       *   r6: epapr magic
-       *   r7: size of IMA in bytes
-       *   r8: 0
-       *   r9: 0
-    */
-    env->gpr[1] = (16<<20) - 8;
-    /* Provide a device-tree.  */
-    env->gpr[3] = bi->fdt;
-    env->nip = bi->bootstrap_pc;
-
-    /* Create a mapping for the kernel.  */
-    mmubooke_create_initial_mapping(env, 0, 0);
-    env->gpr[6] = tswap32(EPAPR_MAGIC);
-    env->gpr[7] = bi->ima_size;
-}
-
-#define BINARY_DEVICE_TREE_FILE "virtex-ml507.dtb"
-static int xilinx_load_device_tree(hwaddr addr,
-                                      uint32_t ramsize,
-                                      hwaddr initrd_base,
-                                      hwaddr initrd_size,
-                                      const char *kernel_cmdline)
-{
-    char *path;
-    int fdt_size;
-#ifdef CONFIG_FDT
-    void *fdt;
-    int r;
-
-    /* Try the local "ppc.dtb" override.  */
-    fdt = load_device_tree("ppc.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);
-            g_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("ppc.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);
-            g_free(path);
-        }
-    }
-
-    if (kernel_cmdline) {
-        fprintf(stderr,
-                "Warning: missing libfdt, cannot pass cmdline to kernel!\n");
-    }
-#endif
-    return fdt_size;
-}
-
-static void virtex_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    MemoryRegion *address_space_mem = get_system_memory();
-    DeviceState *dev;
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    hwaddr ram_base = 0;
-    DriveInfo *dinfo;
-    MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
-    qemu_irq irq[32], *cpu_irq;
-    int kernel_size;
-    int i;
-
-    /* init CPUs */
-    if (cpu_model == NULL) {
-        cpu_model = "440-Xilinx";
-    }
-
-    cpu = ppc440_init_xilinx(&ram_size, 1, cpu_model, 400000000);
-    env = &cpu->env;
-    qemu_register_reset(main_cpu_reset, cpu);
-
-    memory_region_init_ram(phys_ram, "ram", ram_size);
-    vmstate_register_ram_global(phys_ram);
-    memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    pflash_cfi01_register(0xfc000000, NULL, "virtex.flash", FLASH_SIZE,
-                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
-                          FLASH_SIZE >> 16,
-                          1, 0x89, 0x18, 0x0000, 0x0, 1);
-
-    cpu_irq = (qemu_irq *) &env->irq_inputs[PPC40x_INPUT_INT];
-    dev = xilinx_intc_create(0x81800000, cpu_irq[0], 0);
-    for (i = 0; i < 32; i++) {
-        irq[i] = qdev_get_gpio_in(dev, i);
-    }
-
-    serial_mm_init(address_space_mem, 0x83e01003ULL, 2, irq[9], 115200,
-                   serial_hds[0], DEVICE_LITTLE_ENDIAN);
-
-    /* 2 timers at irq 2 @ 62 Mhz.  */
-    xilinx_timer_create(0x83c00000, irq[3], 0, 62 * 1000000);
-
-    if (kernel_filename) {
-        uint64_t entry, low, high;
-        hwaddr boot_offset;
-
-        /* Boots a kernel elf binary.  */
-        kernel_size = load_elf(kernel_filename, NULL, NULL,
-                               &entry, &low, &high, 1, ELF_MACHINE, 0);
-        boot_info.bootstrap_pc = entry & 0x00ffffff;
-
-        if (kernel_size < 0) {
-            boot_offset = 0x1200000;
-            /* If we failed loading ELF's try a raw image.  */
-            kernel_size = load_image_targphys(kernel_filename,
-                                              boot_offset,
-                                              ram_size);
-            boot_info.bootstrap_pc = boot_offset;
-            high = boot_info.bootstrap_pc + kernel_size + 8192;
-        }
-
-        boot_info.ima_size = kernel_size;
-
-        /* Provide a device-tree.  */
-        boot_info.fdt = high + (8192 * 2);
-        boot_info.fdt &= ~8191;
-        xilinx_load_device_tree(boot_info.fdt, ram_size, 0, 0, kernel_cmdline);
-    }
-    env->load_info = &boot_info;
-}
-
-static QEMUMachine virtex_machine = {
-    .name = "virtex-ml507",
-    .desc = "Xilinx Virtex ML507 reference design",
-    .init = virtex_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void virtex_machine_init(void)
-{
-    qemu_register_machine(&virtex_machine);
-}
-
-machine_init(virtex_machine_init);
diff --git a/hw/xen_domainbuild.c b/hw/xen_domainbuild.c
deleted file mode 100644
index d477061..0000000
--- a/hw/xen_domainbuild.c
+++ /dev/null
@@ -1,299 +0,0 @@
-#include <signal.h>
-#include "hw/xen_backend.h"
-#include "hw/xen_domainbuild.h"
-#include "qemu/timer.h"
-#include "qemu/log.h"
-
-#include <xenguest.h>
-
-static int xenstore_domain_mkdir(char *path)
-{
-    struct xs_permissions perms_ro[] = {{
-            .id    = 0, /* set owner: dom0 */
-        },{
-            .id    = xen_domid,
-            .perms = XS_PERM_READ,
-        }};
-    struct xs_permissions perms_rw[] = {{
-            .id    = 0, /* set owner: dom0 */
-        },{
-            .id    = xen_domid,
-            .perms = XS_PERM_READ | XS_PERM_WRITE,
-        }};
-    const char *writable[] = { "device", "control", "error", NULL };
-    char subpath[256];
-    int i;
-
-    if (!xs_mkdir(xenstore, 0, path)) {
-        fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, path);
-	return -1;
-    }
-    if (!xs_set_permissions(xenstore, 0, path, perms_ro, 2)) {
-        fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
-	return -1;
-    }
-
-    for (i = 0; writable[i]; i++) {
-        snprintf(subpath, sizeof(subpath), "%s/%s", path, writable[i]);
-        if (!xs_mkdir(xenstore, 0, subpath)) {
-            fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, subpath);
-            return -1;
-        }
-        if (!xs_set_permissions(xenstore, 0, subpath, perms_rw, 2)) {
-            fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
-            return -1;
-        }
-    }
-    return 0;
-}
-
-int xenstore_domain_init1(const char *kernel, const char *ramdisk,
-                          const char *cmdline)
-{
-    char *dom, uuid_string[42], vm[256], path[256];
-    int i;
-
-    snprintf(uuid_string, sizeof(uuid_string), UUID_FMT,
-             qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], qemu_uuid[3],
-             qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
-             qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], qemu_uuid[11],
-             qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], qemu_uuid[15]);
-    dom = xs_get_domain_path(xenstore, xen_domid);
-    snprintf(vm,  sizeof(vm),  "/vm/%s", uuid_string);
-
-    xenstore_domain_mkdir(dom);
-
-    xenstore_write_str(vm, "image/ostype",  "linux");
-    if (kernel)
-        xenstore_write_str(vm, "image/kernel",  kernel);
-    if (ramdisk)
-        xenstore_write_str(vm, "image/ramdisk", ramdisk);
-    if (cmdline)
-        xenstore_write_str(vm, "image/cmdline", cmdline);
-
-    /* name + id */
-    xenstore_write_str(vm,  "name",   qemu_name ? qemu_name : "no-name");
-    xenstore_write_str(vm,  "uuid",   uuid_string);
-    xenstore_write_str(dom, "name",   qemu_name ? qemu_name : "no-name");
-    xenstore_write_int(dom, "domid",  xen_domid);
-    xenstore_write_str(dom, "vm",     vm);
-
-    /* memory */
-    xenstore_write_int(dom, "memory/target", ram_size >> 10);  // kB
-    xenstore_write_int(vm, "memory",         ram_size >> 20);  // MB
-    xenstore_write_int(vm, "maxmem",         ram_size >> 20);  // MB
-
-    /* cpus */
-    for (i = 0; i < smp_cpus; i++) {
-	snprintf(path, sizeof(path), "cpu/%d/availability",i);
-	xenstore_write_str(dom, path, "online");
-    }
-    xenstore_write_int(vm, "vcpu_avail",  smp_cpus);
-    xenstore_write_int(vm, "vcpus",       smp_cpus);
-
-    /* vnc password */
-    xenstore_write_str(vm, "vncpassword", "" /* FIXME */);
-
-    free(dom);
-    return 0;
-}
-
-int xenstore_domain_init2(int xenstore_port, int xenstore_mfn,
-                          int console_port, int console_mfn)
-{
-    char *dom;
-
-    dom = xs_get_domain_path(xenstore, xen_domid);
-
-    /* signal new domain */
-    xs_introduce_domain(xenstore,
-                        xen_domid,
-                        xenstore_mfn,
-                        xenstore_port);
-
-    /* xenstore */
-    xenstore_write_int(dom, "store/ring-ref",   xenstore_mfn);
-    xenstore_write_int(dom, "store/port",       xenstore_port);
-
-    /* console */
-    xenstore_write_str(dom, "console/type",     "ioemu");
-    xenstore_write_int(dom, "console/limit",    128 * 1024);
-    xenstore_write_int(dom, "console/ring-ref", console_mfn);
-    xenstore_write_int(dom, "console/port",     console_port);
-    xen_config_dev_console(0);
-
-    free(dom);
-    return 0;
-}
-
-/* ------------------------------------------------------------- */
-
-static QEMUTimer *xen_poll;
-
-/* check domain state once per second */
-static void xen_domain_poll(void *opaque)
-{
-    struct xc_dominfo info;
-    int rc;
-
-    rc = xc_domain_getinfo(xen_xc, xen_domid, 1, &info);
-    if ((rc != 1) || (info.domid != xen_domid)) {
-        qemu_log("xen: domain %d is gone\n", xen_domid);
-        goto quit;
-    }
-    if (info.dying) {
-        qemu_log("xen: domain %d is dying (%s%s)\n", xen_domid,
-                 info.crashed  ? "crashed"  : "",
-                 info.shutdown ? "shutdown" : "");
-        goto quit;
-    }
-
-    qemu_mod_timer(xen_poll, qemu_get_clock_ms(rt_clock) + 1000);
-    return;
-
-quit:
-    qemu_system_shutdown_request();
-}
-
-static int xen_domain_watcher(void)
-{
-    int qemu_running = 1;
-    int fd[2], i, n, rc;
-    char byte;
-
-    if (pipe(fd) != 0) {
-        qemu_log("%s: Huh? pipe error: %s\n", __FUNCTION__, strerror(errno));
-        return -1;
-    }
-    if (fork() != 0)
-        return 0; /* not child */
-
-    /* close all file handles, except stdio/out/err,
-     * our watch pipe and the xen interface handle */
-    n = getdtablesize();
-    for (i = 3; i < n; i++) {
-        if (i == fd[0])
-            continue;
-        if (i == xc_fd(xen_xc)) {
-            continue;
-        }
-        close(i);
-    }
-
-    /* ignore term signals */
-    signal(SIGINT,  SIG_IGN);
-    signal(SIGTERM, SIG_IGN);
-
-    /* wait for qemu exiting */
-    while (qemu_running) {
-        rc = read(fd[0], &byte, 1);
-        switch (rc) {
-        case -1:
-            if (errno == EINTR)
-                continue;
-            qemu_log("%s: Huh? read error: %s\n", __FUNCTION__, strerror(errno));
-            qemu_running = 0;
-            break;
-        case 0:
-            /* EOF -> qemu exited */
-            qemu_running = 0;
-            break;
-        default:
-            qemu_log("%s: Huh? data on the watch pipe?\n", __FUNCTION__);
-            break;
-        }
-    }
-
-    /* cleanup */
-    qemu_log("%s: destroy domain %d\n", __FUNCTION__, xen_domid);
-    xc_domain_destroy(xen_xc, xen_domid);
-    _exit(0);
-}
-
-/* normal cleanup */
-static void xen_domain_cleanup(void)
-{
-    char *dom;
-
-    dom = xs_get_domain_path(xenstore, xen_domid);
-    if (dom) {
-        xs_rm(xenstore, 0, dom);
-        free(dom);
-    }
-    xs_release_domain(xenstore, xen_domid);
-}
-
-int xen_domain_build_pv(const char *kernel, const char *ramdisk,
-                        const char *cmdline)
-{
-    uint32_t ssidref = 0;
-    uint32_t flags = 0;
-    xen_domain_handle_t uuid;
-    unsigned int xenstore_port = 0, console_port = 0;
-    unsigned long xenstore_mfn = 0, console_mfn = 0;
-    int rc;
-
-    memcpy(uuid, qemu_uuid, sizeof(uuid));
-    rc = xc_domain_create(xen_xc, ssidref, uuid, flags, &xen_domid);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_create() failed\n");
-        goto err;
-    }
-    qemu_log("xen: created domain %d\n", xen_domid);
-    atexit(xen_domain_cleanup);
-    if (xen_domain_watcher() == -1) {
-        goto err;
-    }
-
-    xenstore_domain_init1(kernel, ramdisk, cmdline);
-
-    rc = xc_domain_max_vcpus(xen_xc, xen_domid, smp_cpus);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_max_vcpus() failed\n");
-        goto err;
-    }
-
-#if 0
-    rc = xc_domain_setcpuweight(xen_xc, xen_domid, 256);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_setcpuweight() failed\n");
-        goto err;
-    }
-#endif
-
-    rc = xc_domain_setmaxmem(xen_xc, xen_domid, ram_size >> 10);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_setmaxmem() failed\n");
-        goto err;
-    }
-
-    xenstore_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
-    console_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
-
-    rc = xc_linux_build(xen_xc, xen_domid, ram_size >> 20,
-                        kernel, ramdisk, cmdline,
-                        0, flags,
-                        xenstore_port, &xenstore_mfn,
-                        console_port, &console_mfn);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_linux_build() failed\n");
-        goto err;
-    }
-
-    xenstore_domain_init2(xenstore_port, xenstore_mfn,
-                          console_port, console_mfn);
-
-    qemu_log("xen: unpausing domain %d\n", xen_domid);
-    rc = xc_domain_unpause(xen_xc, xen_domid);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_unpause() failed\n");
-        goto err;
-    }
-
-    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:
-    return -1;
-}
diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c
deleted file mode 100644
index a8177b6..0000000
--- a/hw/xen_machine_pv.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * QEMU Xen PV Machine
- *
- * Copyright (c) 2007 Red Hat
- *
- * 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/hw.h"
-#include "hw/pc.h"
-#include "hw/boards.h"
-#include "hw/xen_backend.h"
-#include "hw/xen_domainbuild.h"
-#include "sysemu/blockdev.h"
-
-static void xen_init_pv(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    X86CPU *cpu;
-    CPUX86State *env;
-    DriveInfo *dinfo;
-    int i;
-
-    /* Initialize a dummy CPU */
-    if (cpu_model == NULL) {
-#ifdef TARGET_X86_64
-        cpu_model = "qemu64";
-#else
-        cpu_model = "qemu32";
-#endif
-    }
-    cpu = cpu_x86_init(cpu_model);
-    env = &cpu->env;
-    env->halted = 1;
-
-    /* Initialize backend core & drivers */
-    if (xen_be_init() != 0) {
-        fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__);
-        exit(1);
-    }
-
-    switch (xen_mode) {
-    case XEN_ATTACH:
-        /* nothing to do, xend handles everything */
-        break;
-    case XEN_CREATE:
-        if (xen_domain_build_pv(kernel_filename, initrd_filename,
-                                kernel_cmdline) < 0) {
-            fprintf(stderr, "xen pv domain creation failed\n");
-            exit(1);
-        }
-        break;
-    case XEN_EMULATE:
-        fprintf(stderr, "xen emulation not implemented (yet)\n");
-        exit(1);
-        break;
-    }
-
-    xen_be_register("console", &xen_console_ops);
-    xen_be_register("vkbd", &xen_kbdmouse_ops);
-    xen_be_register("vfb", &xen_framebuffer_ops);
-    xen_be_register("qdisk", &xen_blkdev_ops);
-    xen_be_register("qnic", &xen_netdev_ops);
-
-    /* configure framebuffer */
-    if (xenfb_enabled) {
-        xen_config_dev_vfb(0, "vnc");
-        xen_config_dev_vkbd(0);
-    }
-
-    /* configure disks */
-    for (i = 0; i < 16; i++) {
-        dinfo = drive_get(IF_XEN, 0, i);
-        if (!dinfo)
-            continue;
-        xen_config_dev_blk(dinfo);
-    }
-
-    /* configure nics */
-    for (i = 0; i < nb_nics; i++) {
-        if (!nd_table[i].model || 0 != strcmp(nd_table[i].model, "xen"))
-            continue;
-        xen_config_dev_nic(nd_table + i);
-    }
-
-    /* config cleanup hook */
-    atexit(xen_config_cleanup);
-
-    /* setup framebuffer */
-    xen_init_display(xen_domid);
-}
-
-static QEMUMachine xenpv_machine = {
-    .name = "xenpv",
-    .desc = "Xen Para-virtualized PC",
-    .init = xen_init_pv,
-    .max_cpus = 1,
-    .default_machine_opts = "accel=xen",
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void xenpv_machine_init(void)
-{
-    qemu_register_machine(&xenpv_machine);
-}
-
-machine_init(xenpv_machine_init);
diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
deleted file mode 100644
index f78c47e..0000000
--- a/hw/xilinx_zynq.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Xilinx Zynq Baseboard System emulation.
- *
- * Copyright (c) 2010 Xilinx.
- * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.croshtwaite at petalogix.com)
- * Copyright (c) 2012 Petalogix Pty Ltd.
- * Written by Haibing Ma
- *
- * 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.
- *
- * 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/sysbus.h"
-#include "hw/arm-misc.h"
-#include "net/net.h"
-#include "exec/address-spaces.h"
-#include "sysemu/sysemu.h"
-#include "hw/boards.h"
-#include "hw/flash.h"
-#include "sysemu/blockdev.h"
-#include "hw/loader.h"
-#include "hw/ssi.h"
-
-#define NUM_SPI_FLASHES 4
-#define NUM_QSPI_FLASHES 2
-#define NUM_QSPI_BUSSES 2
-
-#define FLASH_SIZE (64 * 1024 * 1024)
-#define FLASH_SECTOR_SIZE (128 * 1024)
-
-#define IRQ_OFFSET 32 /* pic interrupts start from index 32 */
-
-static struct arm_boot_info zynq_binfo = {};
-
-static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-
-    qemu_check_nic_model(nd, "cadence_gem");
-    dev = qdev_create(NULL, "cadence_gem");
-    qdev_set_nic_properties(dev, nd);
-    qdev_init_nofail(dev);
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(s, 0, base);
-    sysbus_connect_irq(s, 0, irq);
-}
-
-static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
-                                         bool is_qspi)
-{
-    DeviceState *dev;
-    SysBusDevice *busdev;
-    SSIBus *spi;
-    DeviceState *flash_dev;
-    int i, j;
-    int num_busses =  is_qspi ? NUM_QSPI_BUSSES : 1;
-    int num_ss = is_qspi ? NUM_QSPI_FLASHES : NUM_SPI_FLASHES;
-
-    dev = qdev_create(NULL, "xilinx,spips");
-    qdev_prop_set_uint8(dev, "num-txrx-bytes", is_qspi ? 4 : 1);
-    qdev_prop_set_uint8(dev, "num-ss-bits", num_ss);
-    qdev_prop_set_uint8(dev, "num-busses", num_busses);
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(busdev, 0, base_addr);
-    if (is_qspi) {
-        sysbus_mmio_map(busdev, 1, 0xFC000000);
-    }
-    sysbus_connect_irq(busdev, 0, irq);
-
-    for (i = 0; i < num_busses; ++i) {
-        char bus_name[16];
-        qemu_irq cs_line;
-
-        snprintf(bus_name, 16, "spi%d", i);
-        spi = (SSIBus *)qdev_get_child_bus(dev, bus_name);
-
-        for (j = 0; j < num_ss; ++j) {
-            flash_dev = ssi_create_slave_no_init(spi, "n25q128");
-            qdev_init_nofail(flash_dev);
-
-            cs_line = qdev_get_gpio_in(flash_dev, 0);
-            sysbus_connect_irq(busdev, i * num_ss + j + 1, cs_line);
-        }
-    }
-
-}
-
-static void zynq_init(QEMUMachineInitArgs *args)
-{
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    ARMCPU *cpu;
-    MemoryRegion *address_space_mem = get_system_memory();
-    MemoryRegion *ext_ram = g_new(MemoryRegion, 1);
-    MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
-    DeviceState *dev;
-    SysBusDevice *busdev;
-    qemu_irq *irqp;
-    qemu_irq pic[64];
-    NICInfo *nd;
-    int n;
-    qemu_irq cpu_irq;
-
-    if (!cpu_model) {
-        cpu_model = "cortex-a9";
-    }
-
-    cpu = cpu_arm_init(cpu_model);
-    if (!cpu) {
-        fprintf(stderr, "Unable to find CPU definition\n");
-        exit(1);
-    }
-    irqp = arm_pic_init_cpu(cpu);
-    cpu_irq = irqp[ARM_PIC_CPU_IRQ];
-
-    /* max 2GB ram */
-    if (ram_size > 0x80000000) {
-        ram_size = 0x80000000;
-    }
-
-    /* DDR remapped to address zero.  */
-    memory_region_init_ram(ext_ram, "zynq.ext_ram", ram_size);
-    vmstate_register_ram_global(ext_ram);
-    memory_region_add_subregion(address_space_mem, 0, ext_ram);
-
-    /* 256K of on-chip memory */
-    memory_region_init_ram(ocm_ram, "zynq.ocm_ram", 256 << 10);
-    vmstate_register_ram_global(ocm_ram);
-    memory_region_add_subregion(address_space_mem, 0xFFFC0000, ocm_ram);
-
-    DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
-
-    /* AMD */
-    pflash_cfi02_register(0xe2000000, NULL, "zynq.pflash", FLASH_SIZE,
-                          dinfo ? dinfo->bdrv : NULL, FLASH_SECTOR_SIZE,
-                          FLASH_SIZE/FLASH_SECTOR_SIZE, 1,
-                          1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa,
-                              0);
-
-    dev = qdev_create(NULL, "xilinx,zynq_slcr");
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xF8000000);
-
-    dev = qdev_create(NULL, "a9mpcore_priv");
-    qdev_prop_set_uint32(dev, "num-cpu", 1);
-    qdev_init_nofail(dev);
-    busdev = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(busdev, 0, 0xF8F00000);
-    sysbus_connect_irq(busdev, 0, cpu_irq);
-
-    for (n = 0; n < 64; n++) {
-        pic[n] = qdev_get_gpio_in(dev, n);
-    }
-
-    zynq_init_spi_flashes(0xE0006000, pic[58-IRQ_OFFSET], false);
-    zynq_init_spi_flashes(0xE0007000, pic[81-IRQ_OFFSET], false);
-    zynq_init_spi_flashes(0xE000D000, pic[51-IRQ_OFFSET], true);
-
-    sysbus_create_simple("xlnx,ps7-usb", 0xE0002000, pic[53-IRQ_OFFSET]);
-    sysbus_create_simple("xlnx,ps7-usb", 0xE0003000, pic[76-IRQ_OFFSET]);
-
-    sysbus_create_simple("cadence_uart", 0xE0000000, pic[59-IRQ_OFFSET]);
-    sysbus_create_simple("cadence_uart", 0xE0001000, pic[82-IRQ_OFFSET]);
-
-    sysbus_create_varargs("cadence_ttc", 0xF8001000,
-            pic[42-IRQ_OFFSET], pic[43-IRQ_OFFSET], pic[44-IRQ_OFFSET], NULL);
-    sysbus_create_varargs("cadence_ttc", 0xF8002000,
-            pic[69-IRQ_OFFSET], pic[70-IRQ_OFFSET], pic[71-IRQ_OFFSET], NULL);
-
-    for (n = 0; n < nb_nics; n++) {
-        nd = &nd_table[n];
-        if (n == 0) {
-            gem_init(nd, 0xE000B000, pic[54-IRQ_OFFSET]);
-        } else if (n == 1) {
-            gem_init(nd, 0xE000C000, pic[77-IRQ_OFFSET]);
-        }
-    }
-
-    dev = qdev_create(NULL, "generic-sdhci");
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0100000);
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[56-IRQ_OFFSET]);
-
-    dev = qdev_create(NULL, "generic-sdhci");
-    qdev_init_nofail(dev);
-    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000);
-    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]);
-
-    zynq_binfo.ram_size = ram_size;
-    zynq_binfo.kernel_filename = kernel_filename;
-    zynq_binfo.kernel_cmdline = kernel_cmdline;
-    zynq_binfo.initrd_filename = initrd_filename;
-    zynq_binfo.nb_cpus = 1;
-    zynq_binfo.board_id = 0xd32;
-    zynq_binfo.loader_start = 0;
-    arm_load_kernel(arm_env_get_cpu(first_cpu), &zynq_binfo);
-}
-
-static QEMUMachine zynq_machine = {
-    .name = "xilinx-zynq-a9",
-    .desc = "Xilinx Zynq Platform Baseboard for Cortex-A9",
-    .init = zynq_init,
-    .block_default_type = IF_SCSI,
-    .max_cpus = 1,
-    .no_sdcard = 1,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void zynq_machine_init(void)
-{
-    qemu_register_machine(&zynq_machine);
-}
-
-machine_init(zynq_machine_init);
diff --git a/hw/xtensa/Makefile.objs b/hw/xtensa/Makefile.objs
index 79698e9..6ead782 100644
--- a/hw/xtensa/Makefile.objs
+++ b/hw/xtensa/Makefile.objs
@@ -1,5 +1,3 @@
-obj-y += xtensa_pic.o
+obj-y += pic_cpu.o
 obj-y += xtensa_sim.o
 obj-y += xtensa_lx60.o
-
-obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/xtensa/pic_cpu.c b/hw/xtensa/pic_cpu.c
new file mode 100644
index 0000000..f485a14
--- /dev/null
+++ b/hw/xtensa/pic_cpu.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab 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 AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "hw/hw.h"
+#include "qemu/log.h"
+#include "qemu/timer.h"
+
+void xtensa_advance_ccount(CPUXtensaState *env, uint32_t d)
+{
+    uint32_t old_ccount = env->sregs[CCOUNT];
+
+    env->sregs[CCOUNT] += d;
+
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
+        int i;
+        for (i = 0; i < env->config->nccompare; ++i) {
+            if (env->sregs[CCOMPARE + i] - old_ccount <= d) {
+                xtensa_timer_irq(env, i, 1);
+            }
+        }
+    }
+}
+
+void check_interrupts(CPUXtensaState *env)
+{
+    int minlevel = xtensa_get_cintlevel(env);
+    uint32_t int_set_enabled = env->sregs[INTSET] & env->sregs[INTENABLE];
+    int level;
+
+    /* If the CPU is halted advance CCOUNT according to the vm_clock time
+     * elapsed since the moment when it was advanced last time.
+     */
+    if (env->halted) {
+        int64_t now = qemu_get_clock_ns(vm_clock);
+
+        xtensa_advance_ccount(env,
+                muldiv64(now - env->halt_clock,
+                    env->config->clock_freq_khz, 1000000));
+        env->halt_clock = now;
+    }
+    for (level = env->config->nlevel; level > minlevel; --level) {
+        if (env->config->level_mask[level] & int_set_enabled) {
+            env->pending_irq_level = level;
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+            qemu_log_mask(CPU_LOG_INT,
+                    "%s level = %d, cintlevel = %d, "
+                    "pc = %08x, a0 = %08x, ps = %08x, "
+                    "intset = %08x, intenable = %08x, "
+                    "ccount = %08x\n",
+                    __func__, level, xtensa_get_cintlevel(env),
+                    env->pc, env->regs[0], env->sregs[PS],
+                    env->sregs[INTSET], env->sregs[INTENABLE],
+                    env->sregs[CCOUNT]);
+            return;
+        }
+    }
+    env->pending_irq_level = 0;
+    cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+}
+
+static void xtensa_set_irq(void *opaque, int irq, int active)
+{
+    CPUXtensaState *env = opaque;
+
+    if (irq >= env->config->ninterrupt) {
+        qemu_log("%s: bad IRQ %d\n", __func__, irq);
+    } else {
+        uint32_t irq_bit = 1 << irq;
+
+        if (active) {
+            env->sregs[INTSET] |= irq_bit;
+        } else if (env->config->interrupt[irq].inttype == INTTYPE_LEVEL) {
+            env->sregs[INTSET] &= ~irq_bit;
+        }
+
+        check_interrupts(env);
+    }
+}
+
+void xtensa_timer_irq(CPUXtensaState *env, uint32_t id, uint32_t active)
+{
+    qemu_set_irq(env->irq_inputs[env->config->timerint[id]], active);
+}
+
+void xtensa_rearm_ccompare_timer(CPUXtensaState *env)
+{
+    int i;
+    uint32_t wake_ccount = env->sregs[CCOUNT] - 1;
+
+    for (i = 0; i < env->config->nccompare; ++i) {
+        if (env->sregs[CCOMPARE + i] - env->sregs[CCOUNT] <
+                wake_ccount - env->sregs[CCOUNT]) {
+            wake_ccount = env->sregs[CCOMPARE + i];
+        }
+    }
+    env->wake_ccount = wake_ccount;
+    qemu_mod_timer(env->ccompare_timer, env->halt_clock +
+            muldiv64(wake_ccount - env->sregs[CCOUNT],
+                1000000, env->config->clock_freq_khz));
+}
+
+static void xtensa_ccompare_cb(void *opaque)
+{
+    XtensaCPU *cpu = opaque;
+    CPUXtensaState *env = &cpu->env;
+
+    if (env->halted) {
+        env->halt_clock = qemu_get_clock_ns(vm_clock);
+        xtensa_advance_ccount(env, env->wake_ccount - env->sregs[CCOUNT]);
+        if (!cpu_has_work(CPU(cpu))) {
+            env->sregs[CCOUNT] = env->wake_ccount + 1;
+            xtensa_rearm_ccompare_timer(env);
+        }
+    }
+}
+
+void xtensa_irq_init(CPUXtensaState *env)
+{
+    XtensaCPU *cpu = xtensa_env_get_cpu(env);
+
+    env->irq_inputs = (void **)qemu_allocate_irqs(
+            xtensa_set_irq, env, env->config->ninterrupt);
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT) &&
+            env->config->nccompare > 0) {
+        env->ccompare_timer =
+            qemu_new_timer_ns(vm_clock, &xtensa_ccompare_cb, cpu);
+    }
+}
+
+void *xtensa_get_extint(CPUXtensaState *env, unsigned extint)
+{
+    if (extint < env->config->nextint) {
+        unsigned irq = env->config->extint[extint];
+        return env->irq_inputs[irq];
+    } else {
+        qemu_log("%s: trying to acquire invalid external interrupt %d\n",
+                __func__, extint);
+        return NULL;
+    }
+}
diff --git a/hw/xtensa/xtensa_lx60.c b/hw/xtensa/xtensa_lx60.c
new file mode 100644
index 0000000..f2a63d8
--- /dev/null
+++ b/hw/xtensa/xtensa_lx60.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab 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 AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "hw/serial.h"
+#include "net/net.h"
+#include "hw/sysbus.h"
+#include "hw/flash.h"
+#include "sysemu/blockdev.h"
+#include "char/char.h"
+#include "hw/xtensa_bootparam.h"
+
+typedef struct LxBoardDesc {
+    size_t flash_size;
+    size_t flash_sector_size;
+    size_t sram_size;
+} LxBoardDesc;
+
+typedef struct Lx60FpgaState {
+    MemoryRegion iomem;
+    uint32_t leds;
+    uint32_t switches;
+} Lx60FpgaState;
+
+static void lx60_fpga_reset(void *opaque)
+{
+    Lx60FpgaState *s = opaque;
+
+    s->leds = 0;
+    s->switches = 0;
+}
+
+static uint64_t lx60_fpga_read(void *opaque, hwaddr addr,
+        unsigned size)
+{
+    Lx60FpgaState *s = opaque;
+
+    switch (addr) {
+    case 0x0: /*build date code*/
+        return 0x09272011;
+
+    case 0x4: /*processor clock frequency, Hz*/
+        return 10000000;
+
+    case 0x8: /*LEDs (off = 0, on = 1)*/
+        return s->leds;
+
+    case 0xc: /*DIP switches (off = 0, on = 1)*/
+        return s->switches;
+    }
+    return 0;
+}
+
+static void lx60_fpga_write(void *opaque, hwaddr addr,
+        uint64_t val, unsigned size)
+{
+    Lx60FpgaState *s = opaque;
+
+    switch (addr) {
+    case 0x8: /*LEDs (off = 0, on = 1)*/
+        s->leds = val;
+        break;
+
+    case 0x10: /*board reset*/
+        if (val == 0xdead) {
+            qemu_system_reset_request();
+        }
+        break;
+    }
+}
+
+static const MemoryRegionOps lx60_fpga_ops = {
+    .read = lx60_fpga_read,
+    .write = lx60_fpga_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static Lx60FpgaState *lx60_fpga_init(MemoryRegion *address_space,
+        hwaddr base)
+{
+    Lx60FpgaState *s = g_malloc(sizeof(Lx60FpgaState));
+
+    memory_region_init_io(&s->iomem, &lx60_fpga_ops, s,
+            "lx60.fpga", 0x10000);
+    memory_region_add_subregion(address_space, base, &s->iomem);
+    lx60_fpga_reset(s);
+    qemu_register_reset(lx60_fpga_reset, s);
+    return s;
+}
+
+static void lx60_net_init(MemoryRegion *address_space,
+        hwaddr base,
+        hwaddr descriptors,
+        hwaddr buffers,
+        qemu_irq irq, NICInfo *nd)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+    MemoryRegion *ram;
+
+    dev = qdev_create(NULL, "open_eth");
+    qdev_set_nic_properties(dev, nd);
+    qdev_init_nofail(dev);
+
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(s, 0, irq);
+    memory_region_add_subregion(address_space, base,
+            sysbus_mmio_get_region(s, 0));
+    memory_region_add_subregion(address_space, descriptors,
+            sysbus_mmio_get_region(s, 1));
+
+    ram = g_malloc(sizeof(*ram));
+    memory_region_init_ram(ram, "open_eth.ram", 16384);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(address_space, buffers, ram);
+}
+
+static uint64_t translate_phys_addr(void *env, uint64_t addr)
+{
+    return cpu_get_phys_page_debug(env, addr);
+}
+
+static void lx60_reset(void *opaque)
+{
+    XtensaCPU *cpu = opaque;
+
+    cpu_reset(CPU(cpu));
+}
+
+static void lx_init(const LxBoardDesc *board, QEMUMachineInitArgs *args)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+    int be = 1;
+#else
+    int be = 0;
+#endif
+    MemoryRegion *system_memory = get_system_memory();
+    XtensaCPU *cpu = NULL;
+    CPUXtensaState *env = NULL;
+    MemoryRegion *ram, *rom, *system_io;
+    DriveInfo *dinfo;
+    pflash_t *flash = NULL;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    int n;
+
+    if (!cpu_model) {
+        cpu_model = XTENSA_DEFAULT_CPU_MODEL;
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        cpu = cpu_xtensa_init(cpu_model);
+        if (cpu == NULL) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        env = &cpu->env;
+
+        env->sregs[PRID] = n;
+        qemu_register_reset(lx60_reset, cpu);
+        /* Need MMU initialized prior to ELF loading,
+         * so that ELF gets loaded into virtual addresses
+         */
+        cpu_reset(CPU(cpu));
+    }
+
+    ram = g_malloc(sizeof(*ram));
+    memory_region_init_ram(ram, "lx60.dram", args->ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(system_memory, 0, ram);
+
+    system_io = g_malloc(sizeof(*system_io));
+    memory_region_init(system_io, "lx60.io", 224 * 1024 * 1024);
+    memory_region_add_subregion(system_memory, 0xf0000000, system_io);
+    lx60_fpga_init(system_io, 0x0d020000);
+    if (nd_table[0].used) {
+        lx60_net_init(system_io, 0x0d030000, 0x0d030400, 0x0d800000,
+                xtensa_get_extint(env, 1), nd_table);
+    }
+
+    if (!serial_hds[0]) {
+        serial_hds[0] = qemu_chr_new("serial0", "null", NULL);
+    }
+
+    serial_mm_init(system_io, 0x0d050020, 2, xtensa_get_extint(env, 0),
+            115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
+
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (dinfo) {
+        flash = pflash_cfi01_register(0xf8000000,
+                NULL, "lx60.io.flash", board->flash_size,
+                dinfo->bdrv, board->flash_sector_size,
+                board->flash_size / board->flash_sector_size,
+                4, 0x0000, 0x0000, 0x0000, 0x0000, be);
+        if (flash == NULL) {
+            fprintf(stderr, "Unable to mount pflash\n");
+            exit(1);
+        }
+    }
+
+    /* Use presence of kernel file name as 'boot from SRAM' switch. */
+    if (kernel_filename) {
+        rom = g_malloc(sizeof(*rom));
+        memory_region_init_ram(rom, "lx60.sram", board->sram_size);
+        vmstate_register_ram_global(rom);
+        memory_region_add_subregion(system_memory, 0xfe000000, rom);
+
+        /* Put kernel bootparameters to the end of that SRAM */
+        if (kernel_cmdline) {
+            size_t cmdline_size = strlen(kernel_cmdline) + 1;
+            size_t bp_size = sizeof(BpTag[4]) + cmdline_size;
+            uint32_t tagptr = (0xfe000000 + board->sram_size - bp_size) & ~0xff;
+
+            env->regs[2] = tagptr;
+
+            tagptr = put_tag(tagptr, 0x7b0b, 0, NULL);
+            if (cmdline_size > 1) {
+                tagptr = put_tag(tagptr, 0x1001,
+                        cmdline_size, kernel_cmdline);
+            }
+            tagptr = put_tag(tagptr, 0x7e0b, 0, NULL);
+        }
+        uint64_t elf_entry;
+        uint64_t elf_lowaddr;
+        int success = load_elf(kernel_filename, translate_phys_addr, env,
+                &elf_entry, &elf_lowaddr, NULL, be, ELF_MACHINE, 0);
+        if (success > 0) {
+            env->pc = elf_entry;
+        }
+    } else {
+        if (flash) {
+            MemoryRegion *flash_mr = pflash_cfi01_get_memory(flash);
+            MemoryRegion *flash_io = g_malloc(sizeof(*flash_io));
+
+            memory_region_init_alias(flash_io, "lx60.flash",
+                    flash_mr, 0, board->flash_size);
+            memory_region_add_subregion(system_memory, 0xfe000000,
+                    flash_io);
+        }
+    }
+}
+
+static void xtensa_lx60_init(QEMUMachineInitArgs *args)
+{
+    static const LxBoardDesc lx60_board = {
+        .flash_size = 0x400000,
+        .flash_sector_size = 0x10000,
+        .sram_size = 0x20000,
+    };
+    lx_init(&lx60_board, args);
+}
+
+static void xtensa_lx200_init(QEMUMachineInitArgs *args)
+{
+    static const LxBoardDesc lx200_board = {
+        .flash_size = 0x1000000,
+        .flash_sector_size = 0x20000,
+        .sram_size = 0x2000000,
+    };
+    lx_init(&lx200_board, args);
+}
+
+static QEMUMachine xtensa_lx60_machine = {
+    .name = "lx60",
+    .desc = "lx60 EVB (" XTENSA_DEFAULT_CPU_MODEL ")",
+    .init = xtensa_lx60_init,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static QEMUMachine xtensa_lx200_machine = {
+    .name = "lx200",
+    .desc = "lx200 EVB (" XTENSA_DEFAULT_CPU_MODEL ")",
+    .init = xtensa_lx200_init,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void xtensa_lx_machines_init(void)
+{
+    qemu_register_machine(&xtensa_lx60_machine);
+    qemu_register_machine(&xtensa_lx200_machine);
+}
+
+machine_init(xtensa_lx_machines_init);
diff --git a/hw/xtensa/xtensa_sim.c b/hw/xtensa/xtensa_sim.c
new file mode 100644
index 0000000..5241f8d
--- /dev/null
+++ b/hw/xtensa/xtensa_sim.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Open Source and Linux Lab 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 AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sysemu/sysemu.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+
+static uint64_t translate_phys_addr(void *env, uint64_t addr)
+{
+    return cpu_get_phys_page_debug(env, addr);
+}
+
+static void sim_reset(void *opaque)
+{
+    XtensaCPU *cpu = opaque;
+
+    cpu_reset(CPU(cpu));
+}
+
+static void xtensa_sim_init(QEMUMachineInitArgs *args)
+{
+    XtensaCPU *cpu = NULL;
+    CPUXtensaState *env = NULL;
+    MemoryRegion *ram, *rom;
+    ram_addr_t ram_size = args->ram_size;
+    const char *cpu_model = args->cpu_model;
+    const char *kernel_filename = args->kernel_filename;
+    int n;
+
+    if (!cpu_model) {
+        cpu_model = XTENSA_DEFAULT_CPU_MODEL;
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        cpu = cpu_xtensa_init(cpu_model);
+        if (cpu == NULL) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        env = &cpu->env;
+
+        env->sregs[PRID] = n;
+        qemu_register_reset(sim_reset, cpu);
+        /* Need MMU initialized prior to ELF loading,
+         * so that ELF gets loaded into virtual addresses
+         */
+        sim_reset(cpu);
+    }
+
+    ram = g_malloc(sizeof(*ram));
+    memory_region_init_ram(ram, "xtensa.sram", ram_size);
+    vmstate_register_ram_global(ram);
+    memory_region_add_subregion(get_system_memory(), 0, ram);
+
+    rom = g_malloc(sizeof(*rom));
+    memory_region_init_ram(rom, "xtensa.rom", 0x1000);
+    vmstate_register_ram_global(rom);
+    memory_region_add_subregion(get_system_memory(), 0xfe000000, rom);
+
+    if (kernel_filename) {
+        uint64_t elf_entry;
+        uint64_t elf_lowaddr;
+#ifdef TARGET_WORDS_BIGENDIAN
+        int success = load_elf(kernel_filename, translate_phys_addr, env,
+                &elf_entry, &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
+#else
+        int success = load_elf(kernel_filename, translate_phys_addr, env,
+                &elf_entry, &elf_lowaddr, NULL, 0, ELF_MACHINE, 0);
+#endif
+        if (success > 0) {
+            env->pc = elf_entry;
+        }
+    }
+}
+
+static QEMUMachine xtensa_sim_machine = {
+    .name = "sim",
+    .desc = "sim machine (" XTENSA_DEFAULT_CPU_MODEL ")",
+    .is_default = true,
+    .init = xtensa_sim_init,
+    .max_cpus = 4,
+    DEFAULT_MACHINE_OPTIONS,
+};
+
+static void xtensa_sim_machine_init(void)
+{
+    qemu_register_machine(&xtensa_sim_machine);
+}
+
+machine_init(xtensa_sim_machine_init);
diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c
deleted file mode 100644
index f2a63d8..0000000
--- a/hw/xtensa_lx60.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the Open Source and Linux Lab 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 AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "sysemu/sysemu.h"
-#include "hw/boards.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "exec/memory.h"
-#include "exec/address-spaces.h"
-#include "hw/serial.h"
-#include "net/net.h"
-#include "hw/sysbus.h"
-#include "hw/flash.h"
-#include "sysemu/blockdev.h"
-#include "char/char.h"
-#include "hw/xtensa_bootparam.h"
-
-typedef struct LxBoardDesc {
-    size_t flash_size;
-    size_t flash_sector_size;
-    size_t sram_size;
-} LxBoardDesc;
-
-typedef struct Lx60FpgaState {
-    MemoryRegion iomem;
-    uint32_t leds;
-    uint32_t switches;
-} Lx60FpgaState;
-
-static void lx60_fpga_reset(void *opaque)
-{
-    Lx60FpgaState *s = opaque;
-
-    s->leds = 0;
-    s->switches = 0;
-}
-
-static uint64_t lx60_fpga_read(void *opaque, hwaddr addr,
-        unsigned size)
-{
-    Lx60FpgaState *s = opaque;
-
-    switch (addr) {
-    case 0x0: /*build date code*/
-        return 0x09272011;
-
-    case 0x4: /*processor clock frequency, Hz*/
-        return 10000000;
-
-    case 0x8: /*LEDs (off = 0, on = 1)*/
-        return s->leds;
-
-    case 0xc: /*DIP switches (off = 0, on = 1)*/
-        return s->switches;
-    }
-    return 0;
-}
-
-static void lx60_fpga_write(void *opaque, hwaddr addr,
-        uint64_t val, unsigned size)
-{
-    Lx60FpgaState *s = opaque;
-
-    switch (addr) {
-    case 0x8: /*LEDs (off = 0, on = 1)*/
-        s->leds = val;
-        break;
-
-    case 0x10: /*board reset*/
-        if (val == 0xdead) {
-            qemu_system_reset_request();
-        }
-        break;
-    }
-}
-
-static const MemoryRegionOps lx60_fpga_ops = {
-    .read = lx60_fpga_read,
-    .write = lx60_fpga_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static Lx60FpgaState *lx60_fpga_init(MemoryRegion *address_space,
-        hwaddr base)
-{
-    Lx60FpgaState *s = g_malloc(sizeof(Lx60FpgaState));
-
-    memory_region_init_io(&s->iomem, &lx60_fpga_ops, s,
-            "lx60.fpga", 0x10000);
-    memory_region_add_subregion(address_space, base, &s->iomem);
-    lx60_fpga_reset(s);
-    qemu_register_reset(lx60_fpga_reset, s);
-    return s;
-}
-
-static void lx60_net_init(MemoryRegion *address_space,
-        hwaddr base,
-        hwaddr descriptors,
-        hwaddr buffers,
-        qemu_irq irq, NICInfo *nd)
-{
-    DeviceState *dev;
-    SysBusDevice *s;
-    MemoryRegion *ram;
-
-    dev = qdev_create(NULL, "open_eth");
-    qdev_set_nic_properties(dev, nd);
-    qdev_init_nofail(dev);
-
-    s = SYS_BUS_DEVICE(dev);
-    sysbus_connect_irq(s, 0, irq);
-    memory_region_add_subregion(address_space, base,
-            sysbus_mmio_get_region(s, 0));
-    memory_region_add_subregion(address_space, descriptors,
-            sysbus_mmio_get_region(s, 1));
-
-    ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, "open_eth.ram", 16384);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(address_space, buffers, ram);
-}
-
-static uint64_t translate_phys_addr(void *env, uint64_t addr)
-{
-    return cpu_get_phys_page_debug(env, addr);
-}
-
-static void lx60_reset(void *opaque)
-{
-    XtensaCPU *cpu = opaque;
-
-    cpu_reset(CPU(cpu));
-}
-
-static void lx_init(const LxBoardDesc *board, QEMUMachineInitArgs *args)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
-    int be = 1;
-#else
-    int be = 0;
-#endif
-    MemoryRegion *system_memory = get_system_memory();
-    XtensaCPU *cpu = NULL;
-    CPUXtensaState *env = NULL;
-    MemoryRegion *ram, *rom, *system_io;
-    DriveInfo *dinfo;
-    pflash_t *flash = NULL;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    int n;
-
-    if (!cpu_model) {
-        cpu_model = XTENSA_DEFAULT_CPU_MODEL;
-    }
-
-    for (n = 0; n < smp_cpus; n++) {
-        cpu = cpu_xtensa_init(cpu_model);
-        if (cpu == NULL) {
-            fprintf(stderr, "Unable to find CPU definition\n");
-            exit(1);
-        }
-        env = &cpu->env;
-
-        env->sregs[PRID] = n;
-        qemu_register_reset(lx60_reset, cpu);
-        /* Need MMU initialized prior to ELF loading,
-         * so that ELF gets loaded into virtual addresses
-         */
-        cpu_reset(CPU(cpu));
-    }
-
-    ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, "lx60.dram", args->ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(system_memory, 0, ram);
-
-    system_io = g_malloc(sizeof(*system_io));
-    memory_region_init(system_io, "lx60.io", 224 * 1024 * 1024);
-    memory_region_add_subregion(system_memory, 0xf0000000, system_io);
-    lx60_fpga_init(system_io, 0x0d020000);
-    if (nd_table[0].used) {
-        lx60_net_init(system_io, 0x0d030000, 0x0d030400, 0x0d800000,
-                xtensa_get_extint(env, 1), nd_table);
-    }
-
-    if (!serial_hds[0]) {
-        serial_hds[0] = qemu_chr_new("serial0", "null", NULL);
-    }
-
-    serial_mm_init(system_io, 0x0d050020, 2, xtensa_get_extint(env, 0),
-            115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
-
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (dinfo) {
-        flash = pflash_cfi01_register(0xf8000000,
-                NULL, "lx60.io.flash", board->flash_size,
-                dinfo->bdrv, board->flash_sector_size,
-                board->flash_size / board->flash_sector_size,
-                4, 0x0000, 0x0000, 0x0000, 0x0000, be);
-        if (flash == NULL) {
-            fprintf(stderr, "Unable to mount pflash\n");
-            exit(1);
-        }
-    }
-
-    /* Use presence of kernel file name as 'boot from SRAM' switch. */
-    if (kernel_filename) {
-        rom = g_malloc(sizeof(*rom));
-        memory_region_init_ram(rom, "lx60.sram", board->sram_size);
-        vmstate_register_ram_global(rom);
-        memory_region_add_subregion(system_memory, 0xfe000000, rom);
-
-        /* Put kernel bootparameters to the end of that SRAM */
-        if (kernel_cmdline) {
-            size_t cmdline_size = strlen(kernel_cmdline) + 1;
-            size_t bp_size = sizeof(BpTag[4]) + cmdline_size;
-            uint32_t tagptr = (0xfe000000 + board->sram_size - bp_size) & ~0xff;
-
-            env->regs[2] = tagptr;
-
-            tagptr = put_tag(tagptr, 0x7b0b, 0, NULL);
-            if (cmdline_size > 1) {
-                tagptr = put_tag(tagptr, 0x1001,
-                        cmdline_size, kernel_cmdline);
-            }
-            tagptr = put_tag(tagptr, 0x7e0b, 0, NULL);
-        }
-        uint64_t elf_entry;
-        uint64_t elf_lowaddr;
-        int success = load_elf(kernel_filename, translate_phys_addr, env,
-                &elf_entry, &elf_lowaddr, NULL, be, ELF_MACHINE, 0);
-        if (success > 0) {
-            env->pc = elf_entry;
-        }
-    } else {
-        if (flash) {
-            MemoryRegion *flash_mr = pflash_cfi01_get_memory(flash);
-            MemoryRegion *flash_io = g_malloc(sizeof(*flash_io));
-
-            memory_region_init_alias(flash_io, "lx60.flash",
-                    flash_mr, 0, board->flash_size);
-            memory_region_add_subregion(system_memory, 0xfe000000,
-                    flash_io);
-        }
-    }
-}
-
-static void xtensa_lx60_init(QEMUMachineInitArgs *args)
-{
-    static const LxBoardDesc lx60_board = {
-        .flash_size = 0x400000,
-        .flash_sector_size = 0x10000,
-        .sram_size = 0x20000,
-    };
-    lx_init(&lx60_board, args);
-}
-
-static void xtensa_lx200_init(QEMUMachineInitArgs *args)
-{
-    static const LxBoardDesc lx200_board = {
-        .flash_size = 0x1000000,
-        .flash_sector_size = 0x20000,
-        .sram_size = 0x2000000,
-    };
-    lx_init(&lx200_board, args);
-}
-
-static QEMUMachine xtensa_lx60_machine = {
-    .name = "lx60",
-    .desc = "lx60 EVB (" XTENSA_DEFAULT_CPU_MODEL ")",
-    .init = xtensa_lx60_init,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static QEMUMachine xtensa_lx200_machine = {
-    .name = "lx200",
-    .desc = "lx200 EVB (" XTENSA_DEFAULT_CPU_MODEL ")",
-    .init = xtensa_lx200_init,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void xtensa_lx_machines_init(void)
-{
-    qemu_register_machine(&xtensa_lx60_machine);
-    qemu_register_machine(&xtensa_lx200_machine);
-}
-
-machine_init(xtensa_lx_machines_init);
diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c
deleted file mode 100644
index f485a14..0000000
--- a/hw/xtensa_pic.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the Open Source and Linux Lab 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 AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "hw/hw.h"
-#include "qemu/log.h"
-#include "qemu/timer.h"
-
-void xtensa_advance_ccount(CPUXtensaState *env, uint32_t d)
-{
-    uint32_t old_ccount = env->sregs[CCOUNT];
-
-    env->sregs[CCOUNT] += d;
-
-    if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
-        int i;
-        for (i = 0; i < env->config->nccompare; ++i) {
-            if (env->sregs[CCOMPARE + i] - old_ccount <= d) {
-                xtensa_timer_irq(env, i, 1);
-            }
-        }
-    }
-}
-
-void check_interrupts(CPUXtensaState *env)
-{
-    int minlevel = xtensa_get_cintlevel(env);
-    uint32_t int_set_enabled = env->sregs[INTSET] & env->sregs[INTENABLE];
-    int level;
-
-    /* If the CPU is halted advance CCOUNT according to the vm_clock time
-     * elapsed since the moment when it was advanced last time.
-     */
-    if (env->halted) {
-        int64_t now = qemu_get_clock_ns(vm_clock);
-
-        xtensa_advance_ccount(env,
-                muldiv64(now - env->halt_clock,
-                    env->config->clock_freq_khz, 1000000));
-        env->halt_clock = now;
-    }
-    for (level = env->config->nlevel; level > minlevel; --level) {
-        if (env->config->level_mask[level] & int_set_enabled) {
-            env->pending_irq_level = level;
-            cpu_interrupt(env, CPU_INTERRUPT_HARD);
-            qemu_log_mask(CPU_LOG_INT,
-                    "%s level = %d, cintlevel = %d, "
-                    "pc = %08x, a0 = %08x, ps = %08x, "
-                    "intset = %08x, intenable = %08x, "
-                    "ccount = %08x\n",
-                    __func__, level, xtensa_get_cintlevel(env),
-                    env->pc, env->regs[0], env->sregs[PS],
-                    env->sregs[INTSET], env->sregs[INTENABLE],
-                    env->sregs[CCOUNT]);
-            return;
-        }
-    }
-    env->pending_irq_level = 0;
-    cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-}
-
-static void xtensa_set_irq(void *opaque, int irq, int active)
-{
-    CPUXtensaState *env = opaque;
-
-    if (irq >= env->config->ninterrupt) {
-        qemu_log("%s: bad IRQ %d\n", __func__, irq);
-    } else {
-        uint32_t irq_bit = 1 << irq;
-
-        if (active) {
-            env->sregs[INTSET] |= irq_bit;
-        } else if (env->config->interrupt[irq].inttype == INTTYPE_LEVEL) {
-            env->sregs[INTSET] &= ~irq_bit;
-        }
-
-        check_interrupts(env);
-    }
-}
-
-void xtensa_timer_irq(CPUXtensaState *env, uint32_t id, uint32_t active)
-{
-    qemu_set_irq(env->irq_inputs[env->config->timerint[id]], active);
-}
-
-void xtensa_rearm_ccompare_timer(CPUXtensaState *env)
-{
-    int i;
-    uint32_t wake_ccount = env->sregs[CCOUNT] - 1;
-
-    for (i = 0; i < env->config->nccompare; ++i) {
-        if (env->sregs[CCOMPARE + i] - env->sregs[CCOUNT] <
-                wake_ccount - env->sregs[CCOUNT]) {
-            wake_ccount = env->sregs[CCOMPARE + i];
-        }
-    }
-    env->wake_ccount = wake_ccount;
-    qemu_mod_timer(env->ccompare_timer, env->halt_clock +
-            muldiv64(wake_ccount - env->sregs[CCOUNT],
-                1000000, env->config->clock_freq_khz));
-}
-
-static void xtensa_ccompare_cb(void *opaque)
-{
-    XtensaCPU *cpu = opaque;
-    CPUXtensaState *env = &cpu->env;
-
-    if (env->halted) {
-        env->halt_clock = qemu_get_clock_ns(vm_clock);
-        xtensa_advance_ccount(env, env->wake_ccount - env->sregs[CCOUNT]);
-        if (!cpu_has_work(CPU(cpu))) {
-            env->sregs[CCOUNT] = env->wake_ccount + 1;
-            xtensa_rearm_ccompare_timer(env);
-        }
-    }
-}
-
-void xtensa_irq_init(CPUXtensaState *env)
-{
-    XtensaCPU *cpu = xtensa_env_get_cpu(env);
-
-    env->irq_inputs = (void **)qemu_allocate_irqs(
-            xtensa_set_irq, env, env->config->ninterrupt);
-    if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT) &&
-            env->config->nccompare > 0) {
-        env->ccompare_timer =
-            qemu_new_timer_ns(vm_clock, &xtensa_ccompare_cb, cpu);
-    }
-}
-
-void *xtensa_get_extint(CPUXtensaState *env, unsigned extint)
-{
-    if (extint < env->config->nextint) {
-        unsigned irq = env->config->extint[extint];
-        return env->irq_inputs[irq];
-    } else {
-        qemu_log("%s: trying to acquire invalid external interrupt %d\n",
-                __func__, extint);
-        return NULL;
-    }
-}
diff --git a/hw/xtensa_sim.c b/hw/xtensa_sim.c
deleted file mode 100644
index 5241f8d..0000000
--- a/hw/xtensa_sim.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the Open Source and Linux Lab 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 AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "sysemu/sysemu.h"
-#include "hw/boards.h"
-#include "hw/loader.h"
-#include "elf.h"
-#include "exec/memory.h"
-#include "exec/address-spaces.h"
-
-static uint64_t translate_phys_addr(void *env, uint64_t addr)
-{
-    return cpu_get_phys_page_debug(env, addr);
-}
-
-static void sim_reset(void *opaque)
-{
-    XtensaCPU *cpu = opaque;
-
-    cpu_reset(CPU(cpu));
-}
-
-static void xtensa_sim_init(QEMUMachineInitArgs *args)
-{
-    XtensaCPU *cpu = NULL;
-    CPUXtensaState *env = NULL;
-    MemoryRegion *ram, *rom;
-    ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    int n;
-
-    if (!cpu_model) {
-        cpu_model = XTENSA_DEFAULT_CPU_MODEL;
-    }
-
-    for (n = 0; n < smp_cpus; n++) {
-        cpu = cpu_xtensa_init(cpu_model);
-        if (cpu == NULL) {
-            fprintf(stderr, "Unable to find CPU definition\n");
-            exit(1);
-        }
-        env = &cpu->env;
-
-        env->sregs[PRID] = n;
-        qemu_register_reset(sim_reset, cpu);
-        /* Need MMU initialized prior to ELF loading,
-         * so that ELF gets loaded into virtual addresses
-         */
-        sim_reset(cpu);
-    }
-
-    ram = g_malloc(sizeof(*ram));
-    memory_region_init_ram(ram, "xtensa.sram", ram_size);
-    vmstate_register_ram_global(ram);
-    memory_region_add_subregion(get_system_memory(), 0, ram);
-
-    rom = g_malloc(sizeof(*rom));
-    memory_region_init_ram(rom, "xtensa.rom", 0x1000);
-    vmstate_register_ram_global(rom);
-    memory_region_add_subregion(get_system_memory(), 0xfe000000, rom);
-
-    if (kernel_filename) {
-        uint64_t elf_entry;
-        uint64_t elf_lowaddr;
-#ifdef TARGET_WORDS_BIGENDIAN
-        int success = load_elf(kernel_filename, translate_phys_addr, env,
-                &elf_entry, &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
-#else
-        int success = load_elf(kernel_filename, translate_phys_addr, env,
-                &elf_entry, &elf_lowaddr, NULL, 0, ELF_MACHINE, 0);
-#endif
-        if (success > 0) {
-            env->pc = elf_entry;
-        }
-    }
-}
-
-static QEMUMachine xtensa_sim_machine = {
-    .name = "sim",
-    .desc = "sim machine (" XTENSA_DEFAULT_CPU_MODEL ")",
-    .is_default = true,
-    .init = xtensa_sim_init,
-    .max_cpus = 4,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void xtensa_sim_machine_init(void)
-{
-    qemu_register_machine(&xtensa_sim_machine);
-}
-
-machine_init(xtensa_sim_machine_init);
diff --git a/hw/z2.c b/hw/z2.c
deleted file mode 100644
index cbb6d80..0000000
--- a/hw/z2.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * PXA270-based Zipit Z2 device
- *
- * Copyright (c) 2011 by Vasily Khoruzhick <anarsoul at gmail.com>
- *
- * Code is based on mainstone platform.
- *
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "hw/hw.h"
-#include "hw/pxa.h"
-#include "hw/arm-misc.h"
-#include "hw/devices.h"
-#include "hw/i2c.h"
-#include "hw/ssi.h"
-#include "hw/boards.h"
-#include "sysemu/sysemu.h"
-#include "hw/flash.h"
-#include "sysemu/blockdev.h"
-#include "ui/console.h"
-#include "audio/audio.h"
-#include "exec/address-spaces.h"
-
-#ifdef DEBUG_Z2
-#define DPRINTF(fmt, ...) \
-        printf(fmt, ## __VA_ARGS__)
-#else
-#define DPRINTF(fmt, ...)
-#endif
-
-static struct keymap map[0x100] = {
-    [0 ... 0xff] = { -1, -1 },
-    [0x3b] = {0, 0}, /* Option = F1 */
-    [0xc8] = {0, 1}, /* Up */
-    [0xd0] = {0, 2}, /* Down */
-    [0xcb] = {0, 3}, /* Left */
-    [0xcd] = {0, 4}, /* Right */
-    [0xcf] = {0, 5}, /* End */
-    [0x0d] = {0, 6}, /* KPPLUS */
-    [0xc7] = {1, 0}, /* Home */
-    [0x10] = {1, 1}, /* Q */
-    [0x17] = {1, 2}, /* I */
-    [0x22] = {1, 3}, /* G */
-    [0x2d] = {1, 4}, /* X */
-    [0x1c] = {1, 5}, /* Enter */
-    [0x0c] = {1, 6}, /* KPMINUS */
-    [0xc9] = {2, 0}, /* PageUp */
-    [0x11] = {2, 1}, /* W */
-    [0x18] = {2, 2}, /* O */
-    [0x23] = {2, 3}, /* H */
-    [0x2e] = {2, 4}, /* C */
-    [0x38] = {2, 5}, /* LeftAlt */
-    [0xd1] = {3, 0}, /* PageDown */
-    [0x12] = {3, 1}, /* E */
-    [0x19] = {3, 2}, /* P */
-    [0x24] = {3, 3}, /* J */
-    [0x2f] = {3, 4}, /* V */
-    [0x2a] = {3, 5}, /* LeftShift */
-    [0x01] = {4, 0}, /* Esc */
-    [0x13] = {4, 1}, /* R */
-    [0x1e] = {4, 2}, /* A */
-    [0x25] = {4, 3}, /* K */
-    [0x30] = {4, 4}, /* B */
-    [0x1d] = {4, 5}, /* LeftCtrl */
-    [0x0f] = {5, 0}, /* Tab */
-    [0x14] = {5, 1}, /* T */
-    [0x1f] = {5, 2}, /* S */
-    [0x26] = {5, 3}, /* L */
-    [0x31] = {5, 4}, /* N */
-    [0x39] = {5, 5}, /* Space */
-    [0x3c] = {6, 0}, /* Stop = F2 */
-    [0x15] = {6, 1}, /* Y */
-    [0x20] = {6, 2}, /* D */
-    [0x0e] = {6, 3}, /* Backspace */
-    [0x32] = {6, 4}, /* M */
-    [0x33] = {6, 5}, /* Comma */
-    [0x3d] = {7, 0}, /* Play = F3 */
-    [0x16] = {7, 1}, /* U */
-    [0x21] = {7, 2}, /* F */
-    [0x2c] = {7, 3}, /* Z */
-    [0x27] = {7, 4}, /* Semicolon */
-    [0x34] = {7, 5}, /* Dot */
-};
-
-#define Z2_RAM_SIZE     0x02000000
-#define Z2_FLASH_BASE   0x00000000
-#define Z2_FLASH_SIZE   0x00800000
-
-static struct arm_boot_info z2_binfo = {
-    .loader_start   = PXA2XX_SDRAM_BASE,
-    .ram_size       = Z2_RAM_SIZE,
-};
-
-#define Z2_GPIO_SD_DETECT   96
-#define Z2_GPIO_AC_IN       0
-#define Z2_GPIO_KEY_ON      1
-#define Z2_GPIO_LCD_CS      88
-
-typedef struct {
-    SSISlave ssidev;
-    int32_t selected;
-    int32_t enabled;
-    uint8_t buf[3];
-    uint32_t cur_reg;
-    int pos;
-} ZipitLCD;
-
-static uint32_t zipit_lcd_transfer(SSISlave *dev, uint32_t value)
-{
-    ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev);
-    uint16_t val;
-    if (z->selected) {
-        z->buf[z->pos] = value & 0xff;
-        z->pos++;
-    }
-    if (z->pos == 3) {
-        switch (z->buf[0]) {
-        case 0x74:
-            DPRINTF("%s: reg: 0x%.2x\n", __func__, z->buf[2]);
-            z->cur_reg = z->buf[2];
-            break;
-        case 0x76:
-            val = z->buf[1] << 8 | z->buf[2];
-            DPRINTF("%s: value: 0x%.4x\n", __func__, val);
-            if (z->cur_reg == 0x22 && val == 0x0000) {
-                z->enabled = 1;
-                printf("%s: LCD enabled\n", __func__);
-            } else if (z->cur_reg == 0x10 && val == 0x0000) {
-                z->enabled = 0;
-                printf("%s: LCD disabled\n", __func__);
-            }
-            break;
-        default:
-            DPRINTF("%s: unknown command!\n", __func__);
-            break;
-        }
-        z->pos = 0;
-    }
-    return 0;
-}
-
-static void z2_lcd_cs(void *opaque, int line, int level)
-{
-    ZipitLCD *z2_lcd = opaque;
-    z2_lcd->selected = !level;
-}
-
-static int zipit_lcd_init(SSISlave *dev)
-{
-    ZipitLCD *z = FROM_SSI_SLAVE(ZipitLCD, dev);
-    z->selected = 0;
-    z->enabled = 0;
-    z->pos = 0;
-
-    return 0;
-}
-
-static VMStateDescription vmstate_zipit_lcd_state = {
-    .name = "zipit-lcd",
-    .version_id = 2,
-    .minimum_version_id = 2,
-    .minimum_version_id_old = 2,
-    .fields = (VMStateField[]) {
-        VMSTATE_SSI_SLAVE(ssidev, ZipitLCD),
-        VMSTATE_INT32(selected, ZipitLCD),
-        VMSTATE_INT32(enabled, ZipitLCD),
-        VMSTATE_BUFFER(buf, ZipitLCD),
-        VMSTATE_UINT32(cur_reg, ZipitLCD),
-        VMSTATE_INT32(pos, ZipitLCD),
-        VMSTATE_END_OF_LIST(),
-    }
-};
-
-static void zipit_lcd_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
-
-    k->init = zipit_lcd_init;
-    k->transfer = zipit_lcd_transfer;
-    dc->vmsd = &vmstate_zipit_lcd_state;
-}
-
-static const TypeInfo zipit_lcd_info = {
-    .name          = "zipit-lcd",
-    .parent        = TYPE_SSI_SLAVE,
-    .instance_size = sizeof(ZipitLCD),
-    .class_init    = zipit_lcd_class_init,
-};
-
-typedef struct {
-    I2CSlave i2c;
-    int len;
-    uint8_t buf[3];
-} AER915State;
-
-static int aer915_send(I2CSlave *i2c, uint8_t data)
-{
-    AER915State *s = FROM_I2C_SLAVE(AER915State, i2c);
-    s->buf[s->len] = data;
-    if (s->len++ > 2) {
-        DPRINTF("%s: message too long (%i bytes)\n",
-            __func__, s->len);
-        return 1;
-    }
-
-    if (s->len == 2) {
-        DPRINTF("%s: reg %d value 0x%02x\n", __func__,
-                s->buf[0], s->buf[1]);
-    }
-
-    return 0;
-}
-
-static void aer915_event(I2CSlave *i2c, enum i2c_event event)
-{
-    AER915State *s = FROM_I2C_SLAVE(AER915State, i2c);
-    switch (event) {
-    case I2C_START_SEND:
-        s->len = 0;
-        break;
-    case I2C_START_RECV:
-        if (s->len != 1) {
-            DPRINTF("%s: short message!?\n", __func__);
-        }
-        break;
-    case I2C_FINISH:
-        break;
-    default:
-        break;
-    }
-}
-
-static int aer915_recv(I2CSlave *slave)
-{
-    int retval = 0x00;
-    AER915State *s = FROM_I2C_SLAVE(AER915State, slave);
-
-    switch (s->buf[0]) {
-    /* Return hardcoded battery voltage,
-     * 0xf0 means ~4.1V
-     */
-    case 0x02:
-        retval = 0xf0;
-        break;
-    /* Return 0x00 for other regs,
-     * we don't know what they are for,
-     * anyway they return 0x00 on real hardware.
-     */
-    default:
-        break;
-    }
-
-    return retval;
-}
-
-static int aer915_init(I2CSlave *i2c)
-{
-    /* Nothing to do.  */
-    return 0;
-}
-
-static VMStateDescription vmstate_aer915_state = {
-    .name = "aer915",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_INT32(len, AER915State),
-        VMSTATE_BUFFER(buf, AER915State),
-        VMSTATE_END_OF_LIST(),
-    }
-};
-
-static void aer915_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
-
-    k->init = aer915_init;
-    k->event = aer915_event;
-    k->recv = aer915_recv;
-    k->send = aer915_send;
-    dc->vmsd = &vmstate_aer915_state;
-}
-
-static const TypeInfo aer915_info = {
-    .name          = "aer915",
-    .parent        = TYPE_I2C_SLAVE,
-    .instance_size = sizeof(AER915State),
-    .class_init    = aer915_class_init,
-};
-
-static void z2_init(QEMUMachineInitArgs *args)
-{
-    const char *cpu_model = args->cpu_model;
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    MemoryRegion *address_space_mem = get_system_memory();
-    uint32_t sector_len = 0x10000;
-    PXA2xxState *mpu;
-    DriveInfo *dinfo;
-    int be;
-    void *z2_lcd;
-    i2c_bus *bus;
-    DeviceState *wm;
-
-    if (!cpu_model) {
-        cpu_model = "pxa270-c5";
-    }
-
-    /* Setup CPU & memory */
-    mpu = pxa270_init(address_space_mem, z2_binfo.ram_size, cpu_model);
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    be = 1;
-#else
-    be = 0;
-#endif
-    dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (!dinfo) {
-        fprintf(stderr, "Flash image must be given with the "
-                "'pflash' parameter\n");
-        exit(1);
-    }
-
-    if (!pflash_cfi01_register(Z2_FLASH_BASE,
-                               NULL, "z2.flash0", Z2_FLASH_SIZE,
-                               dinfo->bdrv, sector_len,
-                               Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0,
-                               be)) {
-        fprintf(stderr, "qemu: Error registering flash memory.\n");
-        exit(1);
-    }
-
-    /* setup keypad */
-    pxa27x_register_keypad(mpu->kp, map, 0x100);
-
-    /* MMC/SD host */
-    pxa2xx_mmci_handlers(mpu->mmc,
-        NULL,
-        qdev_get_gpio_in(mpu->gpio, Z2_GPIO_SD_DETECT));
-
-    type_register_static(&zipit_lcd_info);
-    type_register_static(&aer915_info);
-    z2_lcd = ssi_create_slave(mpu->ssp[1], "zipit-lcd");
-    bus = pxa2xx_i2c_bus(mpu->i2c[0]);
-    i2c_create_slave(bus, "aer915", 0x55);
-    wm = i2c_create_slave(bus, "wm8750", 0x1b);
-    mpu->i2s->opaque = wm;
-    mpu->i2s->codec_out = wm8750_dac_dat;
-    mpu->i2s->codec_in = wm8750_adc_dat;
-    wm8750_data_req_set(wm, mpu->i2s->data_req, mpu->i2s);
-
-    qdev_connect_gpio_out(mpu->gpio, Z2_GPIO_LCD_CS,
-        qemu_allocate_irqs(z2_lcd_cs, z2_lcd, 1)[0]);
-
-    if (kernel_filename) {
-        z2_binfo.kernel_filename = kernel_filename;
-        z2_binfo.kernel_cmdline = kernel_cmdline;
-        z2_binfo.initrd_filename = initrd_filename;
-        z2_binfo.board_id = 0x6dd;
-        arm_load_kernel(mpu->cpu, &z2_binfo);
-    }
-}
-
-static QEMUMachine z2_machine = {
-    .name = "z2",
-    .desc = "Zipit Z2 (PXA27x)",
-    .init = z2_init,
-    DEFAULT_MACHINE_OPTIONS,
-};
-
-static void z2_machine_init(void)
-{
-    qemu_register_machine(&z2_machine);
-}
-
-machine_init(z2_machine_init);
commit e4c8b28cde12d01ada8fe869567dc5717a2dfcb7
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Feb 5 12:52:23 2013 +0100

    ppc: express FDT dependency of pSeries and e500 boards via default-configs/
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/configure b/configure
index 8fdc2cf..ae3d9c5 100755
--- a/configure
+++ b/configure
@@ -4144,9 +4144,6 @@ case "$target_arch2" in
   i386|x86_64)
     echo "CONFIG_HAVE_GET_MEMORY_MAPPING=y" >> $config_target_mak
 esac
-if test "$target_arch2" = "ppc64" -a "$fdt" = "yes"; then
-  echo "CONFIG_PSERIES=y" >> $config_target_mak
-fi
 if test "$target_bigendian" = "yes" ; then
   echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak
 fi
diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index f9f8a81..c209a8d 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -40,3 +40,4 @@ CONFIG_PFLASH_CFI02=y
 CONFIG_PTIMER=y
 CONFIG_I8259=y
 CONFIG_XILINX=y
+CONFIG_E500=$(CONFIG_FDT)
diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index dc44294..8d490bd 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -40,3 +40,5 @@ CONFIG_PFLASH_CFI02=y
 CONFIG_PTIMER=y
 CONFIG_I8259=y
 CONFIG_XILINX=y
+CONFIG_PSERIES=$(CONFIG_FDT)
+CONFIG_E500=$(CONFIG_FDT)
diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
index 1c6bcf9..7f13421 100644
--- a/default-configs/ppcemb-softmmu.mak
+++ b/default-configs/ppcemb-softmmu.mak
@@ -35,3 +35,4 @@ CONFIG_PFLASH_CFI02=y
 CONFIG_PTIMER=y
 CONFIG_I8259=y
 CONFIG_XILINX=y
+CONFIG_E500=$(CONFIG_FDT)
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index bbbe78e..9141373 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -11,7 +11,7 @@ obj-$(CONFIG_PSERIES) += spapr_events.o spapr_nvram.o
 obj-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
 obj-y += ppc440_bamboo.o
 # PowerPC E500 boards
-obj-$(CONFIG_FDT) += mpc8544_guts.o ppce500_spin.o
+obj-$(CONFIG_E500) += mpc8544_guts.o ppce500_spin.o
 # PowerPC 440 Xilinx ML507 reference board.
 obj-y += virtex_ml507.o
 # PowerPC OpenPIC
@@ -29,4 +29,4 @@ obj-y += mac_oldworld.o
 # NewWorld PowerMac
 obj-y += mac_newworld.o
 # e500
-obj-$(CONFIG_FDT) += e500.o mpc8544ds.o e500plat.o
+obj-$(CONFIG_E500) += e500.o mpc8544ds.o e500plat.o
commit 320ba5fe494c0ef59080eac33801ec1e453663fa
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Feb 5 12:36:30 2013 +0100

    build: always link device_tree.o into emulators if libfdt available
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.target b/Makefile.target
index ca657b3..2bd6d14 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -111,6 +111,7 @@ CONFIG_NO_CORE_DUMP = $(if $(subst n,,$(CONFIG_HAVE_CORE_DUMP)),n,y)
 obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o
 obj-y += qtest.o
 obj-y += hw/
+obj-$(CONFIG_FDT) += device_tree.o
 obj-$(CONFIG_KVM) += kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
 obj-y += memory.o savevm.o cputlb.o
diff --git a/configure b/configure
index 19738ac..8fdc2cf 100755
--- a/configure
+++ b/configure
@@ -2416,6 +2416,7 @@ int main(void) { return 0; }
 EOF
   if compile_prog "" "$fdt_libs" ; then
     fdt=yes
+    libs_softmmu="$libs_softmmu $fdt_libs"
   else
     if test "$fdt" = "yes" ; then
       feature_not_found "fdt"
@@ -3981,7 +3982,6 @@ case "$target_arch2" in
     target_nptl="yes"
     gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
     target_llong_alignment=4
-    target_libs_softmmu="$fdt_libs"
   ;;
   cris)
     target_nptl="yes"
@@ -4000,7 +4000,6 @@ case "$target_arch2" in
     TARGET_ARCH=microblaze
     bflt="yes"
     target_nptl="yes"
-    target_libs_softmmu="$fdt_libs"
   ;;
   mips|mipsel)
     TARGET_ARCH=mips
@@ -4025,21 +4024,18 @@ case "$target_arch2" in
   ppc)
     gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
     target_nptl="yes"
-    target_libs_softmmu="$fdt_libs"
   ;;
   ppcemb)
     TARGET_BASE_ARCH=ppc
     TARGET_ABI_DIR=ppc
     gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
     target_nptl="yes"
-    target_libs_softmmu="$fdt_libs"
   ;;
   ppc64)
     TARGET_BASE_ARCH=ppc
     TARGET_ABI_DIR=ppc
     gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
     target_long_alignment=8
-    target_libs_softmmu="$fdt_libs"
   ;;
   ppc64abi32)
     TARGET_ARCH=ppc64
@@ -4047,7 +4043,6 @@ case "$target_arch2" in
     TARGET_ABI_DIR=ppc
     echo "TARGET_ABI32=y" >> $config_target_mak
     gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
-    target_libs_softmmu="$fdt_libs"
   ;;
   sh4|sh4eb)
     TARGET_ARCH=sh4
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 4c10985..3eb1366 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -31,6 +31,5 @@ obj-y += strongarm.o
 obj-y += collie.o
 obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-y += kzm.o
-obj-$(CONFIG_FDT) += ../device_tree.o
 
 obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/microblaze/Makefile.objs b/hw/microblaze/Makefile.objs
index 3028e65..2ff8048 100644
--- a/hw/microblaze/Makefile.objs
+++ b/hw/microblaze/Makefile.objs
@@ -5,6 +5,5 @@ obj-y += xilinx_spi.o
 
 obj-y += microblaze_pic_cpu.o
 obj-y += xilinx_ethlite.o
-obj-$(CONFIG_FDT) += ../device_tree.o
 
 obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index f762050..bbbe78e 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -16,7 +16,6 @@ obj-$(CONFIG_FDT) += mpc8544_guts.o ppce500_spin.o
 obj-y += virtex_ml507.o
 # PowerPC OpenPIC
 obj-y += openpic.o
-obj-$(CONFIG_FDT) += ../device_tree.o
 
 # Xilinx PPC peripherals
 obj-y += xilinx_ethlite.o
commit 83c9f4ca794ec3b6fa7e5a5bb055d378916503e0
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Feb 4 15:40:22 2013 +0100

    hw: include hw header files with full paths
    
    Done with this script:
    
    cd hw
    for i in `find . -name '*.h' | sed 's/^..//'`; do
      echo '\,^#.*include.*["<]'$i'[">], s,'$i',hw/&,'
    done | sed -i -f - `find . -type f`
    
    This is so that paths remain valid as files are moved.
    
    Instead, files in hw/dataplane are referenced with the relative path.
    We know they are not going to move to include/, and they are the only
    include files that are in subdirectories _and_ move.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/a15mpcore.c b/hw/a15mpcore.c
index fe6c34c..d973d53 100644
--- a/hw/a15mpcore.c
+++ b/hw/a15mpcore.c
@@ -18,7 +18,7 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 /* A15MP private memory region.  */
 
diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 01aee02..0a1a10f 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -8,7 +8,7 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 typedef struct A9MPPrivState {
     SysBusDevice busdev;
diff --git a/hw/a9scu.c b/hw/a9scu.c
index 0e9e54d..05897c2 100644
--- a/hw/a9scu.c
+++ b/hw/a9scu.c
@@ -8,7 +8,7 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 /* A9MP private memory region.  */
 
diff --git a/hw/ac97.c b/hw/ac97.c
index 6c565e7..c7d601f 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -17,10 +17,10 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
-#include "audiodev.h"
+#include "hw/hw.h"
+#include "hw/audiodev.h"
 #include "audio/audio.h"
-#include "pci/pci.h"
+#include "hw/pci/pci.h"
 #include "sysemu/dma.h"
 
 enum {
diff --git a/hw/acpi.c b/hw/acpi.c
index 8c9dcc5..53e47d5 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -19,9 +19,9 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 #include "sysemu/sysemu.h"
-#include "hw.h"
-#include "pc.h"
-#include "acpi.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/acpi.h"
 #include "monitor/monitor.h"
 
 struct acpi_table_header {
diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index d2f9808..29f84ff 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -23,16 +23,16 @@
  * Contributions after 2012-01-13 are licensed under the terms of the
  * GNU GPL, version 2 or (at your option) any later version.
  */
-#include "hw.h"
-#include "pc.h"
-#include "pci/pci.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/pci/pci.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
-#include "acpi.h"
+#include "hw/acpi.h"
 #include "sysemu/kvm.h"
 #include "exec/address-spaces.h"
 
-#include "ich9.h"
+#include "hw/ich9.h"
 
 //#define DEBUG
 
diff --git a/hw/acpi_ich9.h b/hw/acpi_ich9.h
index ecb82ab..91c3aeb 100644
--- a/hw/acpi_ich9.h
+++ b/hw/acpi_ich9.h
@@ -21,7 +21,7 @@
 #ifndef HW_ACPI_ICH9_H
 #define HW_ACPI_ICH9_H
 
-#include "acpi.h"
+#include "hw/acpi.h"
 
 typedef struct ICH9LPCPMRegs {
     /*
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 65b2601..7a4b712 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -18,16 +18,16 @@
  * Contributions after 2012-01-13 are licensed under the terms of the
  * GNU GPL, version 2 or (at your option) any later version.
  */
-#include "hw.h"
-#include "pc.h"
-#include "apm.h"
-#include "pm_smbus.h"
-#include "pci/pci.h"
-#include "acpi.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/apm.h"
+#include "hw/pm_smbus.h"
+#include "hw/pci/pci.h"
+#include "hw/acpi.h"
 #include "sysemu/sysemu.h"
 #include "qemu/range.h"
 #include "exec/ioport.h"
-#include "fw_cfg.h"
+#include "hw/fw_cfg.h"
 #include "exec/address-spaces.h"
 
 //#define DEBUG
diff --git a/hw/adb.c b/hw/adb.c
index 6cf5465..fd9052c 100644
--- a/hw/adb.c
+++ b/hw/adb.c
@@ -21,8 +21,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "adb.h"
+#include "hw/hw.h"
+#include "hw/adb.h"
 #include "ui/console.h"
 
 /* debug ADB */
diff --git a/hw/adb.h b/hw/adb.h
index 721f1ac..bdfccd4 100644
--- a/hw/adb.h
+++ b/hw/adb.h
@@ -26,7 +26,7 @@
 #if !defined(__ADB_H__)
 #define __ADB_H__
 
-#include "qdev.h"
+#include "hw/qdev.h"
 
 #define MAX_ADB_DEVICES 16
 
diff --git a/hw/adlib.c b/hw/adlib.c
index 07c69fc..e6bce59 100644
--- a/hw/adlib.c
+++ b/hw/adlib.c
@@ -22,10 +22,10 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "audiodev.h"
+#include "hw/hw.h"
+#include "hw/audiodev.h"
 #include "audio/audio.h"
-#include "isa.h"
+#include "hw/isa.h"
 
 //#define DEBUG
 
@@ -47,7 +47,7 @@
 void YMF262UpdateOneQEMU (int which, INT16 *dst, int length);
 #define SHIFT 2
 #else
-#include "fmopl.h"
+#include "hw/fmopl.h"
 #define SHIFT 1
 #endif
 
diff --git a/hw/ads7846.c b/hw/ads7846.c
index 29e5585..5da3dc5 100644
--- a/hw/ads7846.c
+++ b/hw/ads7846.c
@@ -10,7 +10,7 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "ssi.h"
+#include "hw/ssi.h"
 #include "ui/console.h"
 
 typedef struct {
diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c
index 1cd549c..13aaa57 100644
--- a/hw/alpha_dp264.c
+++ b/hw/alpha_dp264.c
@@ -6,16 +6,16 @@
  * that we need to emulate as well.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "elf.h"
-#include "loader.h"
-#include "boards.h"
-#include "alpha_sys.h"
+#include "hw/loader.h"
+#include "hw/boards.h"
+#include "hw/alpha_sys.h"
 #include "sysemu/sysemu.h"
-#include "mc146818rtc.h"
-#include "ide.h"
-#include "i8254.h"
-#include "serial.h"
+#include "hw/mc146818rtc.h"
+#include "hw/ide.h"
+#include "hw/i8254.h"
+#include "hw/serial.h"
 
 #define MAX_IDE_BUS 2
 
diff --git a/hw/alpha_pci.c b/hw/alpha_pci.c
index 7327d48..8462868 100644
--- a/hw/alpha_pci.c
+++ b/hw/alpha_pci.c
@@ -7,7 +7,7 @@
  */
 
 #include "config.h"
-#include "alpha_sys.h"
+#include "hw/alpha_sys.h"
 #include "qemu/log.h"
 #include "sysemu/sysemu.h"
 
diff --git a/hw/alpha_sys.h b/hw/alpha_sys.h
index 233a71e..b4ebd2a 100644
--- a/hw/alpha_sys.h
+++ b/hw/alpha_sys.h
@@ -3,11 +3,11 @@
 #ifndef HW_ALPHA_H
 #define HW_ALPHA_H 1
 
-#include "pci/pci.h"
-#include "pci/pci_host.h"
-#include "ide.h"
-#include "pc.h"
-#include "irq.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/ide.h"
+#include "hw/pc.h"
+#include "hw/irq.h"
 
 
 PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, AlphaCPU *[4],
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index bf9aabf..95571ff 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -8,10 +8,10 @@
 
 #include "cpu.h"
 #include "exec/exec-all.h"
-#include "hw.h"
-#include "devices.h"
+#include "hw/hw.h"
+#include "hw/devices.h"
 #include "sysemu/sysemu.h"
-#include "alpha_sys.h"
+#include "hw/alpha_sys.h"
 #include "exec/address-spaces.h"
 
 
diff --git a/hw/an5206.c b/hw/an5206.c
index 924be81..7c21c66 100644
--- a/hw/an5206.c
+++ b/hw/an5206.c
@@ -6,10 +6,10 @@
  * This code is licensed under the GPL
  */
 
-#include "hw.h"
-#include "mcf.h"
-#include "boards.h"
-#include "loader.h"
+#include "hw/hw.h"
+#include "hw/mcf.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
 #include "elf.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 7eb0c2b..7992d6f 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -26,12 +26,12 @@
    Ultrasparc PCI host is called the PCI Bus Module (PBM).  The APB is
    the secondary PCI bridge.  */
 
-#include "sysbus.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
-#include "pci/pci_bridge.h"
-#include "pci/pci_bus.h"
-#include "apb_pci.h"
+#include "hw/sysbus.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/apb_pci.h"
 #include "sysemu/sysemu.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/apic.c b/hw/apic.c
index fd14b73..8eddba0 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -17,14 +17,14 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>
  */
 #include "qemu/thread.h"
-#include "apic_internal.h"
-#include "apic.h"
-#include "ioapic.h"
-#include "pci/msi.h"
+#include "hw/apic_internal.h"
+#include "hw/apic.h"
+#include "hw/ioapic.h"
+#include "hw/pci/msi.h"
 #include "qemu/host-utils.h"
 #include "trace.h"
-#include "pc.h"
-#include "apic-msidef.h"
+#include "hw/pc.h"
+#include "hw/apic-msidef.h"
 
 #define MAX_APIC_WORDS 8
 
diff --git a/hw/apic_common.c b/hw/apic_common.c
index d8c9810..d0c2616 100644
--- a/hw/apic_common.c
+++ b/hw/apic_common.c
@@ -17,8 +17,8 @@
  * 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 "apic.h"
-#include "apic_internal.h"
+#include "hw/apic.h"
+#include "hw/apic_internal.h"
 #include "trace.h"
 #include "sysemu/kvm.h"
 
diff --git a/hw/apic_internal.h b/hw/apic_internal.h
index 9265e52..578241f 100644
--- a/hw/apic_internal.h
+++ b/hw/apic_internal.h
@@ -21,7 +21,7 @@
 #define QEMU_APIC_INTERNAL_H
 
 #include "exec/memory.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 
 /* APIC Local Vector Table */
diff --git a/hw/apm.c b/hw/apm.c
index 2e1b137..e2846f9 100644
--- a/hw/apm.c
+++ b/hw/apm.c
@@ -20,9 +20,9 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "apm.h"
-#include "hw.h"
-#include "pci/pci.h"
+#include "hw/apm.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
 
 //#define DEBUG
 
diff --git a/hw/apm.h b/hw/apm.h
index 9abb47f..3edea5f 100644
--- a/hw/apm.h
+++ b/hw/apm.h
@@ -3,7 +3,7 @@
 
 #include <stdint.h>
 #include "qemu-common.h"
-#include "hw.h"
+#include "hw/hw.h"
 #include "exec/memory.h"
 
 typedef void (*apm_ctrl_changed_t)(uint32_t val, void *arg);
diff --git a/hw/applesmc.c b/hw/applesmc.c
index 5a8c4ff..44b9bac 100644
--- a/hw/applesmc.c
+++ b/hw/applesmc.c
@@ -30,8 +30,8 @@
  *
  */
 
-#include "hw.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
 #include "ui/console.h"
 #include "qemu/timer.h"
 
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index ca49948..90dcead 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -7,7 +7,7 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 
 /* MPCore private memory region.  */
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index 4065424..43253fd 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -8,11 +8,11 @@
  */
 
 #include "config.h"
-#include "hw.h"
-#include "arm-misc.h"
+#include "hw/hw.h"
+#include "hw/arm-misc.h"
 #include "sysemu/sysemu.h"
-#include "boards.h"
-#include "loader.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
 #include "elf.h"
 #include "sysemu/device_tree.h"
 #include "qemu/config-file.h"
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 90e43d0..6b30e0b 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -18,8 +18,8 @@
  *  armv7m_nvic device.
  */
 
-#include "sysbus.h"
-#include "arm_gic_internal.h"
+#include "hw/sysbus.h"
+#include "hw/arm_gic_internal.h"
 
 //#define DEBUG_GIC
 
diff --git a/hw/arm_gic_common.c b/hw/arm_gic_common.c
index 40e8dd7..745b4b2 100644
--- a/hw/arm_gic_common.c
+++ b/hw/arm_gic_common.c
@@ -18,7 +18,7 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "arm_gic_internal.h"
+#include "hw/arm_gic_internal.h"
 
 static void gic_save(QEMUFile *f, void *opaque)
 {
diff --git a/hw/arm_gic_internal.h b/hw/arm_gic_internal.h
index 699352c..b10ac5e 100644
--- a/hw/arm_gic_internal.h
+++ b/hw/arm_gic_internal.h
@@ -21,7 +21,7 @@
 #ifndef QEMU_ARM_GIC_INTERNAL_H
 #define QEMU_ARM_GIC_INTERNAL_H
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 /* Maximum number of possible interrupts, determined by the GIC architecture */
 #define GIC_MAXIRQ 1020
diff --git a/hw/arm_l2x0.c b/hw/arm_l2x0.c
index ae1e51d..eb4427d 100644
--- a/hw/arm_l2x0.c
+++ b/hw/arm_l2x0.c
@@ -18,7 +18,7 @@
  *
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 /* L2C-310 r3p2 */
 #define CACHE_ID 0x410000c8
diff --git a/hw/arm_mptimer.c b/hw/arm_mptimer.c
index 7b08aa3..f59a9f1 100644
--- a/hw/arm_mptimer.c
+++ b/hw/arm_mptimer.c
@@ -19,7 +19,7 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 
 /* This device implements the per-cpu private timer and watchdog block
diff --git a/hw/arm_pic.c b/hw/arm_pic.c
index ffb4d41..a7ad893 100644
--- a/hw/arm_pic.c
+++ b/hw/arm_pic.c
@@ -7,8 +7,8 @@
  * This code is licensed under the LGPL
  */
 
-#include "hw.h"
-#include "arm-misc.h"
+#include "hw/hw.h"
+#include "hw/arm-misc.h"
 
 /* Input 0 is IRQ and input 1 is FIQ.  */
 static void arm_pic_cpu_handler(void *opaque, int irq, int level)
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index 7ecb7da..a46f8d4 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -7,10 +7,10 @@
  * This code is licensed under the GPL.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
-#include "sysbus.h"
-#include "primecell.h"
+#include "hw/sysbus.h"
+#include "hw/primecell.h"
 #include "sysemu/sysemu.h"
 
 #define LOCK_VALUE 0xa05f
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index c1e56be..6449870 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -7,11 +7,11 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "qemu-common.h"
-#include "qdev.h"
-#include "ptimer.h"
+#include "hw/qdev.h"
+#include "hw/ptimer.h"
 
 /* Common timer implementation.  */
 
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 904696c..1d5bb59 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -7,9 +7,9 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
-#include "arm-misc.h"
-#include "loader.h"
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/loader.h"
 #include "elf.h"
 
 /* Bitbanded IO.  Each word corresponds to a single bit.  */
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index d5798d0..4d30423 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -10,11 +10,11 @@
  * NVIC.  Much of that is also implemented here.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
-#include "arm-misc.h"
+#include "hw/arm-misc.h"
 #include "exec/address-spaces.h"
-#include "arm_gic_internal.h"
+#include "hw/arm_gic_internal.h"
 
 typedef struct {
     GICState gic;
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index dd37fa1..eccd423 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -22,14 +22,14 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "net/net.h"
-#include "flash.h"
-#include "boards.h"
-#include "etraxfs.h"
-#include "loader.h"
+#include "hw/flash.h"
+#include "hw/boards.h"
+#include "hw/etraxfs.h"
+#include "hw/loader.h"
 #include "elf.h"
-#include "cris-boot.h"
+#include "hw/cris-boot.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/bitbang_i2c.c b/hw/bitbang_i2c.c
index 114508f..b8e6d3a 100644
--- a/hw/bitbang_i2c.c
+++ b/hw/bitbang_i2c.c
@@ -9,9 +9,9 @@
  * Contributions after 2012-01-13 are licensed under the terms of the
  * GNU GPL, version 2 or (at your option) any later version.
  */
-#include "hw.h"
-#include "bitbang_i2c.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/bitbang_i2c.h"
+#include "hw/sysbus.h"
 
 //#define DEBUG_BITBANG_I2C
 
diff --git a/hw/bitbang_i2c.h b/hw/bitbang_i2c.h
index 519d2dc..e860627 100644
--- a/hw/bitbang_i2c.h
+++ b/hw/bitbang_i2c.h
@@ -1,7 +1,7 @@
 #ifndef BITBANG_I2C_H
 #define BITBANG_I2C_H
 
-#include "i2c.h"
+#include "hw/i2c.h"
 
 typedef struct bitbang_i2c_interface bitbang_i2c_interface;
 
diff --git a/hw/blizzard.c b/hw/blizzard.c
index 24bde32..805f4d5 100644
--- a/hw/blizzard.c
+++ b/hw/blizzard.c
@@ -20,8 +20,8 @@
 
 #include "qemu-common.h"
 #include "ui/console.h"
-#include "devices.h"
-#include "vga_int.h"
+#include "hw/devices.h"
+#include "hw/vga_int.h"
 #include "ui/pixel_ops.h"
 
 typedef void (*blizzard_fn_t)(uint8_t *, const uint8_t *, unsigned int);
@@ -941,15 +941,15 @@ static void blizzard_screen_dump(void *opaque, const char *filename,
 }
 
 #define DEPTH 8
-#include "blizzard_template.h"
+#include "hw/blizzard_template.h"
 #define DEPTH 15
-#include "blizzard_template.h"
+#include "hw/blizzard_template.h"
 #define DEPTH 16
-#include "blizzard_template.h"
+#include "hw/blizzard_template.h"
 #define DEPTH 24
-#include "blizzard_template.h"
+#include "hw/blizzard_template.h"
 #define DEPTH 32
-#include "blizzard_template.h"
+#include "hw/blizzard_template.h"
 
 void *s1d13745_init(qemu_irq gpio_int)
 {
diff --git a/hw/boards.h b/hw/boards.h
index 3813d4e..425bdc7 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -4,7 +4,7 @@
 #define HW_BOARDS_H
 
 #include "sysemu/blockdev.h"
-#include "qdev.h"
+#include "hw/qdev.h"
 
 #define DEFAULT_MACHINE_OPTIONS \
     .boot_order = "cad"
diff --git a/hw/bonito.c b/hw/bonito.c
index 0498c9b..3456e78 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -39,11 +39,11 @@
 
 #include <assert.h>
 
-#include "hw.h"
-#include "pci/pci.h"
-#include "pc.h"
-#include "mips.h"
-#include "pci/pci_host.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/pc.h"
+#include "hw/mips.h"
+#include "hw/pci/pci_host.h"
 #include "sysemu/sysemu.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/bt-hci-csr.c b/hw/bt-hci-csr.c
index 2070bb9..e4ada3c 100644
--- a/hw/bt-hci-csr.c
+++ b/hw/bt-hci-csr.c
@@ -21,9 +21,9 @@
 #include "qemu-common.h"
 #include "char/char.h"
 #include "qemu/timer.h"
-#include "irq.h"
+#include "hw/irq.h"
 #include "bt/bt.h"
-#include "bt.h"
+#include "hw/bt.h"
 
 struct csrhci_s {
     int enable;
diff --git a/hw/bt-hci.c b/hw/bt-hci.c
index 69d2c73..a76edea 100644
--- a/hw/bt-hci.c
+++ b/hw/bt-hci.c
@@ -20,9 +20,9 @@
 
 #include "qemu-common.h"
 #include "qemu/timer.h"
-#include "usb.h"
+#include "hw/usb.h"
 #include "bt/bt.h"
-#include "bt.h"
+#include "hw/bt.h"
 
 struct bt_hci_s {
     uint8_t *(*evt_packet)(void *opaque);
diff --git a/hw/bt-hid.c b/hw/bt-hid.c
index cfa7c14..69ccf9b 100644
--- a/hw/bt-hid.c
+++ b/hw/bt-hid.c
@@ -21,8 +21,8 @@
 #include "qemu-common.h"
 #include "qemu/timer.h"
 #include "ui/console.h"
-#include "hid.h"
-#include "bt.h"
+#include "hw/hid.h"
+#include "hw/bt.h"
 
 enum hid_transaction_req {
     BT_HANDSHAKE			= 0x0,
diff --git a/hw/bt-l2cap.c b/hw/bt-l2cap.c
index ba061c0..521587a 100644
--- a/hw/bt-l2cap.c
+++ b/hw/bt-l2cap.c
@@ -19,7 +19,7 @@
 
 #include "qemu-common.h"
 #include "qemu/timer.h"
-#include "bt.h"
+#include "hw/bt.h"
 
 #define L2CAP_CID_MAX	0x100	/* Between 0x40 and 0x10000 */
 
diff --git a/hw/bt-sdp.c b/hw/bt-sdp.c
index c0431d1..218e075 100644
--- a/hw/bt-sdp.c
+++ b/hw/bt-sdp.c
@@ -18,7 +18,7 @@
  */
 
 #include "qemu-common.h"
-#include "bt.h"
+#include "hw/bt.h"
 
 struct bt_l2cap_sdp_state_s {
     struct bt_l2cap_conn_params_s *channel;
diff --git a/hw/bt.c b/hw/bt.c
index 4f2372d..24ef4de 100644
--- a/hw/bt.c
+++ b/hw/bt.c
@@ -19,7 +19,7 @@
 
 #include "qemu-common.h"
 #include "bt/bt.h"
-#include "bt.h"
+#include "hw/bt.h"
 
 /* Slave implementations can ignore this */
 static void bt_dummy_lmp_mode_change(struct bt_link_s *link)
diff --git a/hw/cadence_gem.c b/hw/cadence_gem.c
index de7d15a..e177057 100644
--- a/hw/cadence_gem.c
+++ b/hw/cadence_gem.c
@@ -24,7 +24,7 @@
 
 #include <zlib.h> /* For crc32 */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "net/net.h"
 #include "net/checksum.h"
 
diff --git a/hw/cadence_ttc.c b/hw/cadence_ttc.c
index 67028a3..ba584f4 100644
--- a/hw/cadence_ttc.c
+++ b/hw/cadence_ttc.c
@@ -16,7 +16,7 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 
 #ifdef CADENCE_TTC_ERR_DEBUG
diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c
index 5766d38..5426f10 100644
--- a/hw/cadence_uart.c
+++ b/hw/cadence_uart.c
@@ -16,7 +16,7 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "char/char.h"
 #include "qemu/timer.h"
 
diff --git a/hw/cbus.c b/hw/cbus.c
index 6fd3905..29b467b 100644
--- a/hw/cbus.c
+++ b/hw/cbus.c
@@ -21,8 +21,8 @@
  */
 
 #include "qemu-common.h"
-#include "irq.h"
-#include "devices.h"
+#include "hw/irq.h"
+#include "hw/devices.h"
 #include "sysemu/sysemu.h"
 
 //#define DEBUG
diff --git a/hw/ccid.h b/hw/ccid.h
index 6adc745..9334da8 100644
--- a/hw/ccid.h
+++ b/hw/ccid.h
@@ -10,7 +10,7 @@
 #ifndef CCID_H
 #define CCID_H
 
-#include "qdev.h"
+#include "hw/qdev.h"
 
 typedef struct CCIDCardState CCIDCardState;
 typedef struct CCIDCardInfo CCIDCardInfo;
diff --git a/hw/cdrom.c b/hw/cdrom.c
index 3b99535..a018eec 100644
--- a/hw/cdrom.c
+++ b/hw/cdrom.c
@@ -26,7 +26,7 @@
    here.  */
 
 #include "qemu-common.h"
-#include "scsi.h"
+#include "hw/scsi.h"
 
 static void lba_to_msf(uint8_t *buf, int lba)
 {
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 2a2c8da..7babcb6 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -26,11 +26,11 @@
  * Reference: Finn Thogersons' VGADOC4b
  *   available at http://home.worldonline.dk/~finth/
  */
-#include "hw.h"
-#include "pci/pci.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
 #include "ui/console.h"
-#include "vga_int.h"
-#include "loader.h"
+#include "hw/vga_int.h"
+#include "hw/loader.h"
 
 /*
  * TODO:
@@ -288,63 +288,63 @@ static void cirrus_bitblt_fill_nop(CirrusVGAState *s,
 
 #define ROP_NAME 0
 #define ROP_FN(d, s) 0
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME src_and_dst
 #define ROP_FN(d, s) (s) & (d)
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME src_and_notdst
 #define ROP_FN(d, s) (s) & (~(d))
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME notdst
 #define ROP_FN(d, s) ~(d)
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME src
 #define ROP_FN(d, s) s
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME 1
 #define ROP_FN(d, s) ~0
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME notsrc_and_dst
 #define ROP_FN(d, s) (~(s)) & (d)
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME src_xor_dst
 #define ROP_FN(d, s) (s) ^ (d)
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME src_or_dst
 #define ROP_FN(d, s) (s) | (d)
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME notsrc_or_notdst
 #define ROP_FN(d, s) (~(s)) | (~(d))
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME src_notxor_dst
 #define ROP_FN(d, s) ~((s) ^ (d))
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME src_or_notdst
 #define ROP_FN(d, s) (s) | (~(d))
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME notsrc
 #define ROP_FN(d, s) (~(s))
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME notsrc_or_dst
 #define ROP_FN(d, s) (~(s)) | (d)
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 #define ROP_NAME notsrc_and_notdst
 #define ROP_FN(d, s) (~(s)) & (~(d))
-#include "cirrus_vga_rop.h"
+#include "hw/cirrus_vga_rop.h"
 
 static const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = {
     cirrus_bitblt_rop_fwd_0,
@@ -2165,13 +2165,13 @@ static void cirrus_cursor_invalidate(VGACommonState *s1)
 }
 
 #define DEPTH 8
-#include "cirrus_vga_template.h"
+#include "hw/cirrus_vga_template.h"
 
 #define DEPTH 16
-#include "cirrus_vga_template.h"
+#include "hw/cirrus_vga_template.h"
 
 #define DEPTH 32
-#include "cirrus_vga_template.h"
+#include "hw/cirrus_vga_template.h"
 
 static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y)
 {
diff --git a/hw/cirrus_vga_rop.h b/hw/cirrus_vga_rop.h
index 9c7bb09..894610c 100644
--- a/hw/cirrus_vga_rop.h
+++ b/hw/cirrus_vga_rop.h
@@ -191,16 +191,16 @@ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
 }
 
 #define DEPTH 8
-#include "cirrus_vga_rop2.h"
+#include "hw/cirrus_vga_rop2.h"
 
 #define DEPTH 16
-#include "cirrus_vga_rop2.h"
+#include "hw/cirrus_vga_rop2.h"
 
 #define DEPTH 24
-#include "cirrus_vga_rop2.h"
+#include "hw/cirrus_vga_rop2.h"
 
 #define DEPTH 32
-#include "cirrus_vga_rop2.h"
+#include "hw/cirrus_vga_rop2.h"
 
 #undef ROP_NAME
 #undef ROP_OP
diff --git a/hw/collie.c b/hw/collie.c
index d19db59..17fddc8 100644
--- a/hw/collie.c
+++ b/hw/collie.c
@@ -8,13 +8,13 @@
  * Contributions after 2012-01-13 are licensed under the terms of the
  * GNU GPL, version 2 or (at your option) any later version.
  */
-#include "hw.h"
-#include "sysbus.h"
-#include "boards.h"
-#include "devices.h"
-#include "strongarm.h"
-#include "arm-misc.h"
-#include "flash.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
+#include "hw/boards.h"
+#include "hw/devices.h"
+#include "hw/strongarm.h"
+#include "hw/arm-misc.h"
+#include "hw/flash.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/cris-boot.c b/hw/cris-boot.c
index b21326f..c330e22 100644
--- a/hw/cris-boot.c
+++ b/hw/cris-boot.c
@@ -22,10 +22,10 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "loader.h"
+#include "hw/hw.h"
+#include "hw/loader.h"
 #include "elf.h"
-#include "cris-boot.h"
+#include "hw/cris-boot.h"
 
 static void main_cpu_reset(void *opaque)
 {
diff --git a/hw/cris_pic_cpu.c b/hw/cris_pic_cpu.c
index 3da0e86..7f50471 100644
--- a/hw/cris_pic_cpu.c
+++ b/hw/cris_pic_cpu.c
@@ -22,9 +22,9 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
-#include "hw.h"
-#include "etraxfs.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/etraxfs.h"
 
 #define D(x)
 
diff --git a/hw/cs4231.c b/hw/cs4231.c
index ae384b9..2975336 100644
--- a/hw/cs4231.c
+++ b/hw/cs4231.c
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 
 /*
diff --git a/hw/cs4231a.c b/hw/cs4231a.c
index 73f0859..f005f25 100644
--- a/hw/cs4231a.c
+++ b/hw/cs4231a.c
@@ -21,11 +21,11 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "audiodev.h"
+#include "hw/hw.h"
+#include "hw/audiodev.h"
 #include "audio/audio.h"
-#include "isa.h"
-#include "qdev.h"
+#include "hw/isa.h"
+#include "hw/qdev.h"
 #include "qemu/timer.h"
 
 /*
diff --git a/hw/cuda.c b/hw/cuda.c
index b36c535..2ae430d 100644
--- a/hw/cuda.c
+++ b/hw/cuda.c
@@ -22,9 +22,9 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "ppc/mac.h"
-#include "adb.h"
+#include "hw/hw.h"
+#include "hw/ppc/mac.h"
+#include "hw/adb.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
 
diff --git a/hw/dataplane/event-poll.c b/hw/dataplane/event-poll.c
index 2b55c6e..b98acf9 100644
--- a/hw/dataplane/event-poll.c
+++ b/hw/dataplane/event-poll.c
@@ -13,7 +13,7 @@
  */
 
 #include <sys/epoll.h>
-#include "hw/dataplane/event-poll.h"
+#include "event-poll.h"
 
 /* Add an event notifier and its callback for polling */
 void event_poll_add(EventPoll *poll, EventHandler *handler,
diff --git a/hw/dataplane/ioq.c b/hw/dataplane/ioq.c
index 0c9f5c4..f709f87 100644
--- a/hw/dataplane/ioq.c
+++ b/hw/dataplane/ioq.c
@@ -12,7 +12,7 @@
  *
  */
 
-#include "hw/dataplane/ioq.h"
+#include "ioq.h"
 
 void ioq_init(IOQueue *ioq, int fd, unsigned int max_reqs)
 {
diff --git a/hw/dataplane/virtio-blk.c b/hw/dataplane/virtio-blk.c
index 8588f93..8319c94 100644
--- a/hw/dataplane/virtio-blk.c
+++ b/hw/dataplane/virtio-blk.c
@@ -22,7 +22,7 @@
 #include "migration/migration.h"
 #include "block/block.h"
 #include "hw/virtio-blk.h"
-#include "hw/dataplane/virtio-blk.h"
+#include "virtio-blk.h"
 
 enum {
     SEG_MAX = 126,                  /* maximum number of I/O segments */
diff --git a/hw/dataplane/vring.c b/hw/dataplane/vring.c
index eff5ad8..e3b2253 100644
--- a/hw/dataplane/vring.c
+++ b/hw/dataplane/vring.c
@@ -15,7 +15,7 @@
  */
 
 #include "trace.h"
-#include "hw/dataplane/vring.h"
+#include "vring.h"
 #include "qemu/error-report.h"
 
 /* Map the guest's vring to host memory */
diff --git a/hw/dataplane/vring.h b/hw/dataplane/vring.h
index 3274f62..defb1ef 100644
--- a/hw/dataplane/vring.h
+++ b/hw/dataplane/vring.h
@@ -19,7 +19,7 @@
 
 #include <linux/virtio_ring.h>
 #include "qemu-common.h"
-#include "hw/dataplane/hostmem.h"
+#include "hostmem.h"
 #include "hw/virtio.h"
 
 typedef struct {
diff --git a/hw/debugcon.c b/hw/debugcon.c
index 81b2bb0..cab7691 100644
--- a/hw/debugcon.c
+++ b/hw/debugcon.c
@@ -24,10 +24,10 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "char/char.h"
-#include "isa.h"
-#include "pc.h"
+#include "hw/isa.h"
+#include "hw/pc.h"
 
 #define TYPE_ISA_DEBUGCON_DEVICE "isa-debugcon"
 #define ISA_DEBUGCON_DEVICE(obj) \
diff --git a/hw/debugexit.c b/hw/debugexit.c
index c1b489d..ba67a8f 100644
--- a/hw/debugexit.c
+++ b/hw/debugexit.c
@@ -7,8 +7,8 @@
  * (at your option) any later version.
  */
 
-#include "hw.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
 
 #define TYPE_ISA_DEBUG_EXIT_DEVICE "isa-debug-exit"
 #define ISA_DEBUG_EXIT_DEVICE(obj) \
diff --git a/hw/dec_pci.c b/hw/dec_pci.c
index ee3f4ca..64a5092 100644
--- a/hw/dec_pci.c
+++ b/hw/dec_pci.c
@@ -23,12 +23,12 @@
  * THE SOFTWARE.
  */
 
-#include "dec_pci.h"
-#include "sysbus.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
-#include "pci/pci_bridge.h"
-#include "pci/pci_bus.h"
+#include "hw/dec_pci.h"
+#include "hw/sysbus.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/pci_bus.h"
 
 /* debug DEC */
 //#define DEBUG_DEC
diff --git a/hw/dma.c b/hw/dma.c
index 5bdf435..fd1161c 100644
--- a/hw/dma.c
+++ b/hw/dma.c
@@ -21,8 +21,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
 #include "qemu/main-loop.h"
 
 /* #define DEBUG_DMA */
diff --git a/hw/dp8393x.c b/hw/dp8393x.c
index 808157b..8b5ca6a 100644
--- a/hw/dp8393x.c
+++ b/hw/dp8393x.c
@@ -17,10 +17,10 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
 #include "net/net.h"
-#include "mips.h"
+#include "hw/mips.h"
 
 //#define DEBUG_SONIC
 
diff --git a/hw/ds1225y.c b/hw/ds1225y.c
index a6219a7..488f1d7 100644
--- a/hw/ds1225y.c
+++ b/hw/ds1225y.c
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 
 typedef struct {
diff --git a/hw/ds1338.c b/hw/ds1338.c
index 1da0f96..ae7ca9f 100644
--- a/hw/ds1338.c
+++ b/hw/ds1338.c
@@ -10,7 +10,7 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "i2c.h"
+#include "hw/i2c.h"
 
 /* Size of NVRAM including both the user-accessible area and the
  * secondary register area.
diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c
index 3a88805..544d56b 100644
--- a/hw/dummy_m68k.c
+++ b/hw/dummy_m68k.c
@@ -6,9 +6,9 @@
  * This code is licensed under the GPL
  */
 
-#include "hw.h"
-#include "boards.h"
-#include "loader.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
 #include "elf.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/e1000.c b/hw/e1000.c
index d6fe815..ed37061 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -25,15 +25,15 @@
  */
 
 
-#include "hw.h"
-#include "pci/pci.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
 #include "net/net.h"
 #include "net/checksum.h"
-#include "loader.h"
+#include "hw/loader.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/dma.h"
 
-#include "e1000_hw.h"
+#include "hw/e1000_hw.h"
 
 #define E1000_DEBUG
 
diff --git a/hw/ecc.c b/hw/ecc.c
index 60d1f1d..8c97c33 100644
--- a/hw/ecc.c
+++ b/hw/ecc.c
@@ -11,8 +11,8 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
-#include "flash.h"
+#include "hw/hw.h"
+#include "hw/flash.h"
 
 /*
  * Pre-calculated 256-way 1 byte column parity.  Table borrowed from Linux.
diff --git a/hw/eccmemctl.c b/hw/eccmemctl.c
index dbac2c2..6f4a407 100644
--- a/hw/eccmemctl.c
+++ b/hw/eccmemctl.c
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 
 /* There are 3 versions of this chip used in SMP sun4m systems:
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 5d23796..68d729c 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -41,10 +41,10 @@
  */
 
 #include <stddef.h>             /* offsetof */
-#include "hw.h"
-#include "pci/pci.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
 #include "net/net.h"
-#include "eeprom93xx.h"
+#include "hw/eeprom93xx.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/dma.h"
 
diff --git a/hw/eeprom93xx.c b/hw/eeprom93xx.c
index 4c7158d..39f5605 100644
--- a/hw/eeprom93xx.c
+++ b/hw/eeprom93xx.c
@@ -35,8 +35,8 @@
  * - No emulation of EEPROM timings.
  */
 
-#include "hw.h"
-#include "eeprom93xx.h"
+#include "hw/hw.h"
+#include "hw/eeprom93xx.h"
 
 /* Debug EEPROM emulation. */
 //~ #define DEBUG_EEPROM
diff --git a/hw/empty_slot.c b/hw/empty_slot.c
index d7b5497..5234a4d 100644
--- a/hw/empty_slot.c
+++ b/hw/empty_slot.c
@@ -9,9 +9,9 @@
  * version.
  */
 
-#include "hw.h"
-#include "sysbus.h"
-#include "empty_slot.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
+#include "hw/empty_slot.h"
 
 //#define DEBUG_EMPTY_SLOT
 
diff --git a/hw/es1370.c b/hw/es1370.c
index 977d2e3..e64cf23 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -26,10 +26,10 @@
 /* #define VERBOSE_ES1370 */
 #define SILENT_ES1370
 
-#include "hw.h"
-#include "audiodev.h"
+#include "hw/hw.h"
+#include "hw/audiodev.h"
 #include "audio/audio.h"
-#include "pci/pci.h"
+#include "hw/pci/pci.h"
 #include "sysemu/dma.h"
 
 /* Missing stuff:
diff --git a/hw/escc.c b/hw/escc.c
index 18c0292..baf0219 100644
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -22,9 +22,9 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "sysbus.h"
-#include "escc.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
+#include "hw/escc.h"
 #include "char/char.h"
 #include "ui/console.h"
 #include "trace.h"
diff --git a/hw/esp-pci.c b/hw/esp-pci.c
index c949e6e..7599b39 100644
--- a/hw/esp-pci.c
+++ b/hw/esp-pci.c
@@ -23,9 +23,9 @@
  * THE SOFTWARE.
  */
 
-#include "pci/pci.h"
-#include "eeprom93xx.h"
-#include "esp.h"
+#include "hw/pci/pci.h"
+#include "hw/eeprom93xx.h"
+#include "hw/esp.h"
 #include "trace.h"
 #include "qemu/log.h"
 
diff --git a/hw/esp.c b/hw/esp.c
index 2af48aa..5365eac 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -23,8 +23,8 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
-#include "esp.h"
+#include "hw/sysbus.h"
+#include "hw/esp.h"
 #include "trace.h"
 #include "qemu/log.h"
 
diff --git a/hw/esp.h b/hw/esp.h
index f15cc7b..830673b 100644
--- a/hw/esp.h
+++ b/hw/esp.h
@@ -1,7 +1,7 @@
 #ifndef QEMU_HW_ESP_H
 #define QEMU_HW_ESP_H
 
-#include "scsi.h"
+#include "hw/scsi.h"
 
 /* esp.c */
 #define ESP_MAX_DEVS 7
diff --git a/hw/etraxfs.h b/hw/etraxfs.h
index 180de5a..0df4fdd 100644
--- a/hw/etraxfs.h
+++ b/hw/etraxfs.h
@@ -26,7 +26,7 @@
 #define HW_EXTRAXFS_H 1
 
 #include "net/net.h"
-#include "etraxfs_dma.h"
+#include "hw/etraxfs_dma.h"
 
 qemu_irq *cris_pic_init_cpu(CPUCRISState *env);
 
diff --git a/hw/etraxfs_dma.c b/hw/etraxfs_dma.c
index d415003..a84ec1f 100644
--- a/hw/etraxfs_dma.c
+++ b/hw/etraxfs_dma.c
@@ -23,12 +23,12 @@
  */
 #include <stdio.h>
 #include <sys/time.h>
-#include "hw.h"
+#include "hw/hw.h"
 #include "exec/address-spaces.h"
 #include "qemu-common.h"
 #include "sysemu/sysemu.h"
 
-#include "etraxfs_dma.h"
+#include "hw/etraxfs_dma.h"
 
 #define D(x)
 
diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c
index ad36411..591bee2 100644
--- a/hw/etraxfs_eth.c
+++ b/hw/etraxfs_eth.c
@@ -23,9 +23,9 @@
  */
 
 #include <stdio.h>
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "net/net.h"
-#include "etraxfs.h"
+#include "hw/etraxfs.h"
 
 #define D(x)
 
diff --git a/hw/etraxfs_pic.c b/hw/etraxfs_pic.c
index 64af31c..635103c 100644
--- a/hw/etraxfs_pic.c
+++ b/hw/etraxfs_pic.c
@@ -22,8 +22,8 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
-#include "hw.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
 //#include "pc.h"
 //#include "etraxfs.h"
 
diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
index 72c8868..7e24d34 100644
--- a/hw/etraxfs_ser.c
+++ b/hw/etraxfs_ser.c
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "char/char.h"
 #include "qemu/log.h"
 
diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c
index d3dac52..3cd9476 100644
--- a/hw/etraxfs_timer.c
+++ b/hw/etraxfs_timer.c
@@ -21,10 +21,10 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 
 #define D(x)
 
diff --git a/hw/exynos4210.c b/hw/exynos4210.c
index fa54e42..4592514 100644
--- a/hw/exynos4210.c
+++ b/hw/exynos4210.c
@@ -21,13 +21,13 @@
  *
  */
 
-#include "boards.h"
+#include "hw/boards.h"
 #include "sysemu/sysemu.h"
-#include "sysbus.h"
-#include "arm-misc.h"
-#include "loader.h"
-#include "exynos4210.h"
-#include "usb/hcd-ehci.h"
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/loader.h"
+#include "hw/exynos4210.h"
+#include "hw/usb/hcd-ehci.h"
 
 #define EXYNOS4210_CHIPID_ADDR         0x10000000
 
diff --git a/hw/exynos4210_combiner.c b/hw/exynos4210_combiner.c
index ba644b4..5818f10 100644
--- a/hw/exynos4210_combiner.c
+++ b/hw/exynos4210_combiner.c
@@ -27,9 +27,9 @@
  * IRQs are passed to GIC through Combiner.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
-#include "exynos4210.h"
+#include "hw/exynos4210.h"
 
 //#define DEBUG_COMBINER
 
diff --git a/hw/exynos4210_fimd.c b/hw/exynos4210_fimd.c
index 3d498b7..6b31ae3 100644
--- a/hw/exynos4210_fimd.c
+++ b/hw/exynos4210_fimd.c
@@ -24,7 +24,7 @@
 
 #include "qemu-common.h"
 #include "exec/cpu-all.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "ui/console.h"
 #include "ui/pixel_ops.h"
 #include "qemu/bswap.h"
diff --git a/hw/exynos4210_gic.c b/hw/exynos4210_gic.c
index 94b138f..807849c 100644
--- a/hw/exynos4210_gic.c
+++ b/hw/exynos4210_gic.c
@@ -20,10 +20,10 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu-common.h"
-#include "irq.h"
-#include "exynos4210.h"
+#include "hw/irq.h"
+#include "hw/exynos4210.h"
 
 enum ExtGicId {
     EXT_GIC_ID_MDMA_LCD0 = 66,
diff --git a/hw/exynos4210_i2c.c b/hw/exynos4210_i2c.c
index cefd736..9e42875 100644
--- a/hw/exynos4210_i2c.c
+++ b/hw/exynos4210_i2c.c
@@ -21,8 +21,8 @@
  */
 
 #include "qemu/timer.h"
-#include "sysbus.h"
-#include "i2c.h"
+#include "hw/sysbus.h"
+#include "hw/i2c.h"
 
 #ifndef EXYNOS4_I2C_DEBUG
 #define EXYNOS4_I2C_DEBUG                 0
diff --git a/hw/exynos4210_mct.c b/hw/exynos4210_mct.c
index d7d5904..862c962 100644
--- a/hw/exynos4210_mct.c
+++ b/hw/exynos4210_mct.c
@@ -52,12 +52,12 @@
  * there is no way to avoid frequently events).
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "qemu-common.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 
-#include "exynos4210.h"
+#include "hw/exynos4210.h"
 
 //#define DEBUG_MCT
 
diff --git a/hw/exynos4210_pmu.c b/hw/exynos4210_pmu.c
index 7c81a1b..ba5aa8d 100644
--- a/hw/exynos4210_pmu.c
+++ b/hw/exynos4210_pmu.c
@@ -24,7 +24,7 @@
  * uses PMU INFORM5 register as a holding pen.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 #ifndef DEBUG_PMU
 #define DEBUG_PMU           0
diff --git a/hw/exynos4210_pwm.c b/hw/exynos4210_pwm.c
index c865624..6d74cd4 100644
--- a/hw/exynos4210_pwm.c
+++ b/hw/exynos4210_pwm.c
@@ -20,12 +20,12 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "qemu-common.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 
-#include "exynos4210.h"
+#include "hw/exynos4210.h"
 
 //#define DEBUG_PWM
 
diff --git a/hw/exynos4210_rtc.c b/hw/exynos4210_rtc.c
index 5694a62..d170ca7 100644
--- a/hw/exynos4210_rtc.c
+++ b/hw/exynos4210_rtc.c
@@ -25,16 +25,16 @@
  *  CLKOUTEN Bit[9] not used
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "qemu-common.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
 
-#include "exynos4210.h"
+#include "hw/exynos4210.h"
 
 #define DEBUG_RTC 0
 
diff --git a/hw/exynos4210_uart.c b/hw/exynos4210_uart.c
index bdf797a..006f3d4 100644
--- a/hw/exynos4210_uart.c
+++ b/hw/exynos4210_uart.c
@@ -19,11 +19,11 @@
  *
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "char/char.h"
 
-#include "exynos4210.h"
+#include "hw/exynos4210.h"
 
 #undef DEBUG_UART
 #undef DEBUG_UART_EXTEND
diff --git a/hw/exynos4_boards.c b/hw/exynos4_boards.c
index b59e6aa..473da34 100644
--- a/hw/exynos4_boards.c
+++ b/hw/exynos4_boards.c
@@ -22,12 +22,12 @@
  */
 
 #include "sysemu/sysemu.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "net/net.h"
-#include "arm-misc.h"
+#include "hw/arm-misc.h"
 #include "exec/address-spaces.h"
-#include "exynos4210.h"
-#include "boards.h"
+#include "hw/exynos4210.h"
+#include "hw/boards.h"
 
 #undef DEBUG
 
diff --git a/hw/fdc.c b/hw/fdc.c
index 976a587..a4bb129 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -27,13 +27,13 @@
  * way. There are changes in DOR register and DMA is not available.
  */
 
-#include "hw.h"
-#include "fdc.h"
+#include "hw/hw.h"
+#include "hw/fdc.h"
 #include "qemu/error-report.h"
 #include "qemu/timer.h"
-#include "isa.h"
-#include "sysbus.h"
-#include "qdev-addr.h"
+#include "hw/isa.h"
+#include "hw/sysbus.h"
+#include "hw/qdev-addr.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/sysemu.h"
 #include "qemu/log.h"
diff --git a/hw/fmopl.c b/hw/fmopl.c
index f0a0234..e50ba6c 100644
--- a/hw/fmopl.c
+++ b/hw/fmopl.c
@@ -39,7 +39,7 @@
 #include <stdarg.h>
 #include <math.h>
 //#include "driver.h"		/* use M.A.M.E. */
-#include "fmopl.h"
+#include "hw/fmopl.h"
 
 #ifndef PI
 #define PI 3.14159265358979323846
diff --git a/hw/framebuffer.c b/hw/framebuffer.c
index 2a87096..d341aa0 100644
--- a/hw/framebuffer.c
+++ b/hw/framebuffer.c
@@ -17,9 +17,9 @@
    - Remove all DisplayState knowledge from devices.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
-#include "framebuffer.h"
+#include "hw/framebuffer.h"
 
 /* Render an image from a shared memory framebuffer.  */
    
diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
index 02618f2..63a1998 100644
--- a/hw/fw_cfg.c
+++ b/hw/fw_cfg.c
@@ -21,11 +21,11 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "sysemu/sysemu.h"
-#include "isa.h"
-#include "fw_cfg.h"
-#include "sysbus.h"
+#include "hw/isa.h"
+#include "hw/fw_cfg.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "qemu/error-report.h"
 #include "qemu/config-file.h"
diff --git a/hw/g364fb.c b/hw/g364fb.c
index 0c0c8ba..7b69815 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -17,11 +17,11 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
 #include "ui/pixel_ops.h"
 #include "trace.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 typedef struct G364State {
     /* hardware */
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index 95639d5..11e47d5 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -23,9 +23,9 @@
  * THE SOFTWARE.
  */
 
-#include "pci/pci_host.h"
-#include "ppc/mac.h"
-#include "pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/ppc/mac.h"
+#include "hw/pci/pci.h"
 
 /* debug Grackle */
 //#define DEBUG_GRACKLE
diff --git a/hw/grlib.h b/hw/grlib.h
index afd5389..470ce72 100644
--- a/hw/grlib.h
+++ b/hw/grlib.h
@@ -25,8 +25,8 @@
 #ifndef _GRLIB_H_
 #define _GRLIB_H_
 
-#include "qdev.h"
-#include "sysbus.h"
+#include "hw/qdev.h"
+#include "hw/sysbus.h"
 
 /* Emulation of GrLib device is base on the GRLIB IP Core User's Manual:
  * http://www.gaisler.com/products/grlib/grip.pdf
diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
index ba1685a..62f7990 100644
--- a/hw/grlib_apbuart.c
+++ b/hw/grlib_apbuart.c
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "char/char.h"
 
 #include "trace.h"
diff --git a/hw/grlib_gptimer.c b/hw/grlib_gptimer.c
index 7962b74..7043a34 100644
--- a/hw/grlib_gptimer.c
+++ b/hw/grlib_gptimer.c
@@ -22,9 +22,9 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 
 #include "trace.h"
 
diff --git a/hw/grlib_irqmp.c b/hw/grlib_irqmp.c
index ef8dd95..7ee469d 100644
--- a/hw/grlib_irqmp.c
+++ b/hw/grlib_irqmp.c
@@ -24,10 +24,10 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "cpu.h"
 
-#include "grlib.h"
+#include "hw/grlib.h"
 
 #include "trace.h"
 
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 977a2c5..c73a58a 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -22,11 +22,11 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "mips.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
-#include "pc.h"
+#include "hw/hw.h"
+#include "hw/mips.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pc.h"
 #include "exec/address-spaces.h"
 
 //#define DEBUG
diff --git a/hw/gumstix.c b/hw/gumstix.c
index bea1605..8859b73 100644
--- a/hw/gumstix.c
+++ b/hw/gumstix.c
@@ -34,12 +34,12 @@
  * # qemu-system-arm -M verdex -pflash flash -monitor null -nographic -m 289
  */
 
-#include "hw.h"
-#include "pxa.h"
+#include "hw/hw.h"
+#include "hw/pxa.h"
 #include "net/net.h"
-#include "flash.h"
-#include "devices.h"
-#include "boards.h"
+#include "hw/flash.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/gus.c b/hw/gus.c
index aa13fcc..d268224 100644
--- a/hw/gus.c
+++ b/hw/gus.c
@@ -21,12 +21,12 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "audiodev.h"
+#include "hw/hw.h"
+#include "hw/audiodev.h"
 #include "audio/audio.h"
-#include "isa.h"
-#include "gusemu.h"
-#include "gustate.h"
+#include "hw/isa.h"
+#include "hw/gusemu.h"
+#include "hw/gustate.h"
 
 #define dolog(...) AUD_log ("audio", __VA_ARGS__)
 #ifdef DEBUG
diff --git a/hw/gusemu_hal.c b/hw/gusemu_hal.c
index 6096690..0eee617 100644
--- a/hw/gusemu_hal.c
+++ b/hw/gusemu_hal.c
@@ -26,8 +26,8 @@
  * TODO: check mixer: see 7.20 of sdk for panning pos (applies to all gus models?)?
  */
 
-#include "gustate.h"
-#include "gusemu.h"
+#include "hw/gustate.h"
+#include "hw/gusemu.h"
 
 #define GUSregb(position) (*            (gusptr+(position)))
 #define GUSregw(position) (*(GUSword *) (gusptr+(position)))
diff --git a/hw/gusemu_mixer.c b/hw/gusemu_mixer.c
index 6d8d9ce..816c58a 100644
--- a/hw/gusemu_mixer.c
+++ b/hw/gusemu_mixer.c
@@ -22,8 +22,8 @@
  * THE SOFTWARE.
  */
 
-#include "gusemu.h"
-#include "gustate.h"
+#include "hw/gusemu.h"
+#include "hw/gustate.h"
 
 #define GUSregb(position)  (*            (gusptr+(position)))
 #define GUSregw(position)  (*(GUSword *) (gusptr+(position)))
diff --git a/hw/hda-audio.c b/hw/hda-audio.c
index 3190bd1..6bdd820 100644
--- a/hw/hda-audio.c
+++ b/hw/hda-audio.c
@@ -17,10 +17,10 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "pci/pci.h"
-#include "intel-hda.h"
-#include "intel-hda-defs.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/intel-hda.h"
+#include "hw/intel-hda-defs.h"
 #include "audio/audio.h"
 
 /* -------------------------------------------------------------------------- */
diff --git a/hw/heathrow_pic.c b/hw/heathrow_pic.c
index c0a71c3..beb9661 100644
--- a/hw/heathrow_pic.c
+++ b/hw/heathrow_pic.c
@@ -22,8 +22,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "ppc/mac.h"
+#include "hw/hw.h"
+#include "hw/ppc/mac.h"
 
 /* debug PIC */
 //#define DEBUG_PIC
diff --git a/hw/hid.c b/hw/hid.c
index 89b5415..28b3474 100644
--- a/hw/hid.c
+++ b/hw/hid.c
@@ -22,10 +22,10 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
 #include "qemu/timer.h"
-#include "hid.h"
+#include "hw/hid.h"
 
 #define HID_USAGE_ERROR_ROLLOVER        0x01
 #define HID_USAGE_POSTFAIL              0x02
diff --git a/hw/highbank.c b/hw/highbank.c
index defcc09..a622224 100644
--- a/hw/highbank.c
+++ b/hw/highbank.c
@@ -17,14 +17,14 @@
  *
  */
 
-#include "sysbus.h"
-#include "arm-misc.h"
-#include "devices.h"
-#include "loader.h"
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "hw/loader.h"
 #include "net/net.h"
 #include "sysemu/sysemu.h"
-#include "boards.h"
-#include "sysbus.h"
+#include "hw/boards.h"
+#include "hw/sysbus.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/hpet.c b/hw/hpet.c
index 97eaa2f..6bfbf3a 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -24,14 +24,14 @@
  * This driver attempts to emulate an HPET device in software.
  */
 
-#include "hw.h"
-#include "pc.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
 #include "ui/console.h"
 #include "qemu/timer.h"
-#include "hpet_emul.h"
-#include "sysbus.h"
-#include "mc146818rtc.h"
-#include "i8254.h"
+#include "hw/hpet_emul.h"
+#include "hw/sysbus.h"
+#include "hw/mc146818rtc.h"
+#include "hw/i8254.h"
 
 //#define HPET_DEBUG
 #ifdef HPET_DEBUG
diff --git a/hw/hw.h b/hw/hw.h
index dfced97..1553e54 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -9,7 +9,7 @@
 #endif
 
 #include "exec/ioport.h"
-#include "irq.h"
+#include "hw/irq.h"
 #include "block/aio.h"
 #include "migration/qemu-file.h"
 #include "migration/vmstate.h"
diff --git a/hw/i2c.c b/hw/i2c.c
index ec314a4..ad361cc 100644
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -7,7 +7,7 @@
  * This code is licensed under the LGPL.
  */
 
-#include "i2c.h"
+#include "hw/i2c.h"
 
 struct i2c_bus
 {
diff --git a/hw/i2c.h b/hw/i2c.h
index 0e80d5a..461392f 100644
--- a/hw/i2c.h
+++ b/hw/i2c.h
@@ -1,7 +1,7 @@
 #ifndef QEMU_I2C_H
 #define QEMU_I2C_H
 
-#include "qdev.h"
+#include "hw/qdev.h"
 
 /* The QEMU I2C implementation only supports simple transfers that complete
    immediately.  It does not support slave devices that need to be able to
diff --git a/hw/i82374.c b/hw/i82374.c
index 6a62ba2..22115e4 100644
--- a/hw/i82374.c
+++ b/hw/i82374.c
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 
-#include "isa.h"
+#include "hw/isa.h"
 
 //#define DEBUG_I82374
 
diff --git a/hw/i82378.c b/hw/i82378.c
index 0914d7b..6f8c48b 100644
--- a/hw/i82378.c
+++ b/hw/i82378.c
@@ -17,10 +17,10 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "pci/pci.h"
-#include "pc.h"
-#include "i8254.h"
-#include "pcspk.h"
+#include "hw/pci/pci.h"
+#include "hw/pc.h"
+#include "hw/i8254.h"
+#include "hw/pcspk.h"
 
 //#define DEBUG_I82378
 
diff --git a/hw/i8254.c b/hw/i8254.c
index 394b2e8..67bfc6a 100644
--- a/hw/i8254.c
+++ b/hw/i8254.c
@@ -21,12 +21,12 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "pc.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
 #include "qemu/timer.h"
-#include "i8254.h"
-#include "i8254_internal.h"
+#include "hw/i8254.h"
+#include "hw/i8254_internal.h"
 
 //#define DEBUG_PIT
 
diff --git a/hw/i8254.h b/hw/i8254.h
index ba6b598..7d4432e 100644
--- a/hw/i8254.h
+++ b/hw/i8254.h
@@ -25,8 +25,8 @@
 #ifndef HW_I8254_H
 #define HW_I8254_H
 
-#include "hw.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
 
 #define PIT_FREQ 1193182
 
diff --git a/hw/i8254_common.c b/hw/i8254_common.c
index 8c2e45a..c6c0c80 100644
--- a/hw/i8254_common.c
+++ b/hw/i8254_common.c
@@ -22,12 +22,12 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "pc.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
 #include "qemu/timer.h"
-#include "i8254.h"
-#include "i8254_internal.h"
+#include "hw/i8254.h"
+#include "hw/i8254_internal.h"
 
 /* val must be 0 or 1 */
 void pit_set_gate(ISADevice *dev, int channel, int val)
diff --git a/hw/i8254_internal.h b/hw/i8254_internal.h
index 686f0c2..30d5b1b 100644
--- a/hw/i8254_internal.h
+++ b/hw/i8254_internal.h
@@ -25,9 +25,9 @@
 #ifndef QEMU_I8254_INTERNAL_H
 #define QEMU_I8254_INTERNAL_H
 
-#include "hw.h"
-#include "pc.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
 
 typedef struct PITChannelState {
     int count; /* can be 65536 */
diff --git a/hw/i8259.c b/hw/i8259.c
index 54fe144..1d82752 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -21,12 +21,12 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "pc.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
 #include "monitor/monitor.h"
 #include "qemu/timer.h"
-#include "i8259_internal.h"
+#include "hw/i8259_internal.h"
 
 /* debug PIC */
 //#define DEBUG_PIC
diff --git a/hw/i8259_common.c b/hw/i8259_common.c
index fc91056..98052db 100644
--- a/hw/i8259_common.c
+++ b/hw/i8259_common.c
@@ -22,8 +22,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "pc.h"
-#include "i8259_internal.h"
+#include "hw/pc.h"
+#include "hw/i8259_internal.h"
 
 void pic_reset_common(PICCommonState *s)
 {
diff --git a/hw/i8259_internal.h b/hw/i8259_internal.h
index 8785b1d..2813ec1 100644
--- a/hw/i8259_internal.h
+++ b/hw/i8259_internal.h
@@ -25,9 +25,9 @@
 #ifndef QEMU_I8259_INTERNAL_H
 #define QEMU_I8259_INTERNAL_H
 
-#include "hw.h"
-#include "pc.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
 
 typedef struct PICCommonState PICCommonState;
 
diff --git a/hw/i82801b11.c b/hw/i82801b11.c
index 3dc1000..992095c 100644
--- a/hw/i82801b11.c
+++ b/hw/i82801b11.c
@@ -41,8 +41,8 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>
  */
 
-#include "pci/pci.h"
-#include "ich9.h"
+#include "hw/pci/pci.h"
+#include "hw/ich9.h"
 
 
 /*****************************************************************************/
diff --git a/hw/ich9.h b/hw/ich9.h
index d4509bb..59c25e9 100644
--- a/hw/ich9.h
+++ b/hw/ich9.h
@@ -1,20 +1,20 @@
 #ifndef HW_ICH9_H
 #define HW_ICH9_H
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/range.h"
-#include "isa.h"
-#include "sysbus.h"
-#include "pc.h"
-#include "apm.h"
-#include "ioapic.h"
-#include "pci/pci.h"
-#include "pci/pcie_host.h"
-#include "pci/pci_bridge.h"
-#include "acpi.h"
-#include "acpi_ich9.h"
-#include "pam.h"
-#include "pci/pci_bus.h"
+#include "hw/isa.h"
+#include "hw/sysbus.h"
+#include "hw/pc.h"
+#include "hw/apm.h"
+#include "hw/ioapic.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pcie_host.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/acpi.h"
+#include "hw/acpi_ich9.h"
+#include "hw/pam.h"
+#include "hw/pci/pci_bus.h"
 
 void ich9_lpc_set_irq(void *opaque, int irq_num, int level);
 int ich9_lpc_map_irq(PCIDevice *pci_dev, int intx);
diff --git a/hw/ide.h b/hw/ide.h
index 0eb3a74..35444a3 100644
--- a/hw/ide.h
+++ b/hw/ide.h
@@ -1,8 +1,8 @@
 #ifndef HW_IDE_H
 #define HW_IDE_H
 
-#include "isa.h"
-#include "pci/pci.h"
+#include "hw/isa.h"
+#include "hw/pci/pci.h"
 #include "exec/memory.h"
 
 #define MAX_IDE_DEVS	2
diff --git a/hw/imx_avic.c b/hw/imx_avic.c
index f1f066c..4e280b6 100644
--- a/hw/imx_avic.c
+++ b/hw/imx_avic.c
@@ -14,8 +14,8 @@
  * TODO: implement vectors.
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "qemu/host-utils.h"
 
 #define DEBUG_INT 1
diff --git a/hw/imx_ccm.c b/hw/imx_ccm.c
index 477903a..ad7aad3 100644
--- a/hw/imx_ccm.c
+++ b/hw/imx_ccm.c
@@ -10,10 +10,10 @@
  * the CCM.
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
-#include "imx.h"
+#include "hw/imx.h"
 
 #define CKIH_FREQ 26000000 /* 26MHz crystal input */
 #define CKIL_FREQ    32768 /* nominal 32khz clock */
diff --git a/hw/imx_serial.c b/hw/imx_serial.c
index 2d8253e..746723c 100644
--- a/hw/imx_serial.c
+++ b/hw/imx_serial.c
@@ -17,11 +17,11 @@
  *     is a real serial device.
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "char/char.h"
-#include "imx.h"
+#include "hw/imx.h"
 
 //#define DEBUG_SERIAL 1
 #ifdef DEBUG_SERIAL
diff --git a/hw/imx_timer.c b/hw/imx_timer.c
index e924c74..a8c3111 100644
--- a/hw/imx_timer.c
+++ b/hw/imx_timer.c
@@ -11,11 +11,11 @@
  *
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
-#include "sysbus.h"
-#include "imx.h"
+#include "hw/ptimer.h"
+#include "hw/sysbus.h"
+#include "hw/imx.h"
 
 //#define DEBUG_TIMER 1
 #ifdef DEBUG_TIMER
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index 9e3630a..e0ba327 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -7,10 +7,10 @@
  * This code is licensed under the GPL
  */
 
-#include "sysbus.h"
-#include "devices.h"
-#include "boards.h"
-#include "arm-misc.h"
+#include "hw/sysbus.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/arm-misc.h"
 #include "net/net.h"
 #include "exec/address-spaces.h"
 #include "sysemu/sysemu.h"
diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index 784c229..728b60f 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -17,13 +17,13 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "pci/pci.h"
-#include "pci/msi.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/msi.h"
 #include "qemu/timer.h"
-#include "audiodev.h"
-#include "intel-hda.h"
-#include "intel-hda-defs.h"
+#include "hw/audiodev.h"
+#include "hw/intel-hda.h"
+#include "hw/intel-hda-defs.h"
 #include "sysemu/dma.h"
 
 /* --------------------------------------------------------------------- */
diff --git a/hw/intel-hda.h b/hw/intel-hda.h
index 22e0968..2544f0a 100644
--- a/hw/intel-hda.h
+++ b/hw/intel-hda.h
@@ -1,7 +1,7 @@
 #ifndef HW_INTEL_HDA_H
 #define HW_INTEL_HDA_H
 
-#include "qdev.h"
+#include "hw/qdev.h"
 
 /* --------------------------------------------------------------------- */
 /* hda bus                                                               */
diff --git a/hw/ioapic.c b/hw/ioapic.c
index f06c2dc..78629fa 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -20,11 +20,11 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "pc.h"
-#include "apic.h"
-#include "ioapic.h"
-#include "ioapic_internal.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/apic.h"
+#include "hw/ioapic.h"
+#include "hw/ioapic_internal.h"
 
 //#define DEBUG_IOAPIC
 
diff --git a/hw/ioapic_common.c b/hw/ioapic_common.c
index 7dc552f..d4aff29 100644
--- a/hw/ioapic_common.c
+++ b/hw/ioapic_common.c
@@ -19,9 +19,9 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "ioapic.h"
-#include "ioapic_internal.h"
-#include "sysbus.h"
+#include "hw/ioapic.h"
+#include "hw/ioapic_internal.h"
+#include "hw/sysbus.h"
 
 void ioapic_reset_common(DeviceState *dev)
 {
diff --git a/hw/ioapic_internal.h b/hw/ioapic_internal.h
index c8447d7..25576c8 100644
--- a/hw/ioapic_internal.h
+++ b/hw/ioapic_internal.h
@@ -22,9 +22,9 @@
 #ifndef QEMU_IOAPIC_INTERNAL_H
 #define QEMU_IOAPIC_INTERNAL_H
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "exec/memory.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 #define MAX_IOAPICS                     1
 
diff --git a/hw/ioh3420.c b/hw/ioh3420.c
index 95bceb5..43f8554 100644
--- a/hw/ioh3420.c
+++ b/hw/ioh3420.c
@@ -20,10 +20,10 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "pci/pci_ids.h"
-#include "pci/msi.h"
-#include "pci/pcie.h"
-#include "ioh3420.h"
+#include "hw/pci/pci_ids.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/pcie.h"
+#include "hw/ioh3420.h"
 
 #define PCI_DEVICE_ID_IOH_EPORT         0x3420  /* D0:F0 express mode */
 #define PCI_DEVICE_ID_IOH_REV           0x2
diff --git a/hw/ioh3420.h b/hw/ioh3420.h
index 046cf2c..7776e5b 100644
--- a/hw/ioh3420.h
+++ b/hw/ioh3420.h
@@ -1,7 +1,7 @@
 #ifndef QEMU_IOH3420_H
 #define QEMU_IOH3420_H
 
-#include "pci/pcie_port.h"
+#include "hw/pci/pcie_port.h"
 
 PCIESlot *ioh3420_init(PCIBus *bus, int devfn, bool multifunction,
                        const char *bus_name, pci_map_irq_fn map_irq,
diff --git a/hw/ipack.c b/hw/ipack.c
index e15540d..b1f46c1 100644
--- a/hw/ipack.c
+++ b/hw/ipack.c
@@ -8,7 +8,7 @@
  * later version.
  */
 
-#include "ipack.h"
+#include "hw/ipack.h"
 
 IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot)
 {
diff --git a/hw/ipack.h b/hw/ipack.h
index 69e2628..f2b7a12 100644
--- a/hw/ipack.h
+++ b/hw/ipack.h
@@ -11,7 +11,7 @@
 #ifndef QEMU_IPACK_H
 #define QEMU_IPACK_H
 
-#include "qdev.h"
+#include "hw/qdev.h"
 
 typedef struct IPackBus IPackBus;
 
diff --git a/hw/ipoctal232.c b/hw/ipoctal232.c
index c1e3b19..1da6a99 100644
--- a/hw/ipoctal232.c
+++ b/hw/ipoctal232.c
@@ -8,7 +8,7 @@
  * later version.
  */
 
-#include "ipack.h"
+#include "hw/ipack.h"
 #include "qemu/bitops.h"
 #include "char/char.h"
 
diff --git a/hw/irq.c b/hw/irq.c
index f4e2a78..2078542 100644
--- a/hw/irq.c
+++ b/hw/irq.c
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 #include "qemu-common.h"
-#include "irq.h"
+#include "hw/irq.h"
 
 struct IRQState {
     qemu_irq_handler handler;
diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index 6dc34f0..67ff8fd 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -16,11 +16,11 @@
  * 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 "hw/hw.h"
 #include "monitor/monitor.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
-#include "isa.h"
+#include "hw/isa.h"
 #include "exec/address-spaces.h"
 
 static ISABus *isabus;
diff --git a/hw/isa.h b/hw/isa.h
index 7a8874a..82da37c 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -5,7 +5,7 @@
 
 #include "exec/ioport.h"
 #include "exec/memory.h"
-#include "qdev.h"
+#include "hw/qdev.h"
 
 #define ISA_NUM_IRQS 16
 
diff --git a/hw/isa_mmio.c b/hw/isa_mmio.c
index 487cf6a..a7860e7 100644
--- a/hw/isa_mmio.c
+++ b/hw/isa_mmio.c
@@ -22,8 +22,8 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
 #include "exec/address-spaces.h"
 
 static void isa_mmio_writeb (void *opaque, hwaddr addr,
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index afaf9b3..68a2cf2 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -16,10 +16,10 @@
  * Contributions after 2012-01-13 are licensed under the terms of the
  * GNU GPL, version 2 or (at your option) any later version.
  */
-#include "hw.h"
-#include "pc.h"
-#include "pci/pci.h"
-#include "pci/msix.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/msix.h"
 #include "sysemu/kvm.h"
 #include "migration/migration.h"
 #include "qapi/qmp/qerror.h"
diff --git a/hw/jazz_led.c b/hw/jazz_led.c
index 4822c48..a418a7d 100644
--- a/hw/jazz_led.c
+++ b/hw/jazz_led.c
@@ -26,7 +26,7 @@
 #include "ui/console.h"
 #include "ui/pixel_ops.h"
 #include "trace.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 typedef enum {
     REDRAW_NONE = 0, REDRAW_SEGMENTS = 1, REDRAW_BACKGROUND = 2,
diff --git a/hw/kvmvapic.c b/hw/kvmvapic.c
index 9265baf..c151c95 100644
--- a/hw/kvmvapic.c
+++ b/hw/kvmvapic.c
@@ -11,7 +11,7 @@
 #include "sysemu/sysemu.h"
 #include "sysemu/cpus.h"
 #include "sysemu/kvm.h"
-#include "apic_internal.h"
+#include "hw/apic_internal.h"
 
 #define APIC_DEFAULT_ADDRESS    0xfee00000
 
diff --git a/hw/kzm.c b/hw/kzm.c
index fb33165..ec50a31 100644
--- a/hw/kzm.c
+++ b/hw/kzm.c
@@ -13,16 +13,16 @@
  * i.MX31 SoC
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "exec/address-spaces.h"
-#include "hw.h"
-#include "arm-misc.h"
-#include "devices.h"
+#include "hw/hw.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
 #include "net/net.h"
 #include "sysemu/sysemu.h"
-#include "boards.h"
-#include "serial.h"
-#include "imx.h"
+#include "hw/boards.h"
+#include "hw/serial.h"
+#include "hw/imx.h"
 
     /* Memory map for Kzm Emulation Baseboard:
      * 0x00000000-0x00003fff 16k secure ROM       IGNORED
diff --git a/hw/lan9118.c b/hw/lan9118.c
index 0e844e5..403fb86 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -10,11 +10,11 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "net/net.h"
-#include "devices.h"
+#include "hw/devices.h"
 #include "sysemu/sysemu.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 /* For crc32 */
 #include <zlib.h>
 
diff --git a/hw/lance.c b/hw/lance.c
index 4b92425..acfffae 100644
--- a/hw/lance.c
+++ b/hw/lance.c
@@ -35,12 +35,12 @@
  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR92C990.txt
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "net/net.h"
 #include "qemu/timer.h"
 #include "qemu/sockets.h"
-#include "sun4m.h"
-#include "pcnet.h"
+#include "hw/sun4m.h"
+#include "hw/pcnet.h"
 #include "trace.h"
 
 typedef struct {
diff --git a/hw/leon3.c b/hw/leon3.c
index f16a8bb..f58061f 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -21,18 +21,18 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 #include "char/char.h"
 #include "sysemu/sysemu.h"
-#include "boards.h"
-#include "loader.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
 #include "elf.h"
 #include "trace.h"
 #include "exec/address-spaces.h"
 
-#include "grlib.h"
+#include "hw/grlib.h"
 
 /* Default system clock.  */
 #define CPU_CLK (40 * 1000 * 1000)
diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c
index 2bc06d7..1ce466a 100644
--- a/hw/lm32_boards.c
+++ b/hw/lm32_boards.c
@@ -17,16 +17,16 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysbus.h"
-#include "hw.h"
-#include "flash.h"
-#include "devices.h"
-#include "boards.h"
-#include "loader.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/flash.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
 #include "sysemu/blockdev.h"
 #include "elf.h"
-#include "lm32_hwsetup.h"
-#include "lm32.h"
+#include "hw/lm32_hwsetup.h"
+#include "hw/lm32.h"
 #include "exec/address-spaces.h"
 
 typedef struct {
diff --git a/hw/lm32_hwsetup.h b/hw/lm32_hwsetup.h
index 853e9ab..3449bd8 100644
--- a/hw/lm32_hwsetup.h
+++ b/hw/lm32_hwsetup.h
@@ -26,7 +26,7 @@
 #define QEMU_HW_LM32_HWSETUP_H
 
 #include "qemu-common.h"
-#include "loader.h"
+#include "hw/loader.h"
 
 typedef struct {
     void *data;
diff --git a/hw/lm32_juart.c b/hw/lm32_juart.c
index 8c82c85..472e9c2 100644
--- a/hw/lm32_juart.c
+++ b/hw/lm32_juart.c
@@ -17,12 +17,12 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "char/char.h"
 
-#include "lm32_juart.h"
+#include "hw/lm32_juart.h"
 
 enum {
     LM32_JUART_MIN_SAVE_VERSION = 0,
diff --git a/hw/lm32_pic.c b/hw/lm32_pic.c
index 42f298a..d17c310 100644
--- a/hw/lm32_pic.c
+++ b/hw/lm32_pic.c
@@ -19,12 +19,12 @@
 
 #include <assert.h>
 
-#include "hw.h"
-#include "pc.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
 #include "monitor/monitor.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "trace.h"
-#include "lm32_pic.h"
+#include "hw/lm32_pic.h"
 
 struct LM32PicState {
     SysBusDevice busdev;
diff --git a/hw/lm32_sys.c b/hw/lm32_sys.c
index 187ef6d..33a3b80 100644
--- a/hw/lm32_sys.c
+++ b/hw/lm32_sys.c
@@ -28,8 +28,8 @@
  * the test is passed or any non-zero value to it if the test is failed.
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "qemu/log.h"
 #include "qemu/error-report.h"
diff --git a/hw/lm32_timer.c b/hw/lm32_timer.c
index db527e9..e06fac7 100644
--- a/hw/lm32_timer.c
+++ b/hw/lm32_timer.c
@@ -21,11 +21,11 @@
  *   http://www.latticesemi.com/documents/mico32timer.pdf
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 #include "qemu/error-report.h"
 
 #define DEFAULT_FREQUENCY (50*1000000)
diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c
index 9c89cca..02f6f89 100644
--- a/hw/lm32_uart.c
+++ b/hw/lm32_uart.c
@@ -22,8 +22,8 @@
  */
 
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "char/char.h"
 #include "qemu/error-report.h"
diff --git a/hw/lm4549.c b/hw/lm4549.c
index b3c2d5f..67335cb 100644
--- a/hw/lm4549.c
+++ b/hw/lm4549.c
@@ -13,9 +13,9 @@
  * It supports only one playback voice and no record voice.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "audio/audio.h"
-#include "lm4549.h"
+#include "hw/lm4549.h"
 
 #if 0
 #define LM4549_DEBUG  1
diff --git a/hw/lm832x.c b/hw/lm832x.c
index 94b8ae0..a064dfd 100644
--- a/hw/lm832x.c
+++ b/hw/lm832x.c
@@ -18,8 +18,8 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "i2c.h"
+#include "hw/hw.h"
+#include "hw/i2c.h"
 #include "qemu/timer.h"
 #include "ui/console.h"
 
diff --git a/hw/loader.c b/hw/loader.c
index 995edc3..d2a974b 100644
--- a/hw/loader.c
+++ b/hw/loader.c
@@ -42,13 +42,13 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "disas/disas.h"
 #include "monitor/monitor.h"
 #include "sysemu/sysemu.h"
-#include "uboot_image.h"
-#include "loader.h"
-#include "fw_cfg.h"
+#include "hw/uboot_image.h"
+#include "hw/loader.h"
+#include "hw/fw_cfg.h"
 #include "exec/memory.h"
 #include "exec/address-spaces.h"
 
@@ -260,7 +260,7 @@ static void *load_at(int fd, int offset, int size)
 #define elf_word        uint32_t
 #define elf_sword        int32_t
 #define bswapSZs	bswap32s
-#include "elf_ops.h"
+#include "hw/elf_ops.h"
 
 #undef elfhdr
 #undef elf_phdr
@@ -280,7 +280,7 @@ static void *load_at(int fd, int offset, int size)
 #define elf_sword        int64_t
 #define bswapSZs	bswap64s
 #define SZ		64
-#include "elf_ops.h"
+#include "hw/elf_ops.h"
 
 /* return < 0 if error, otherwise the number of bytes loaded in memory */
 int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
index e25689b..e55d66a 100644
--- a/hw/lpc_ich9.c
+++ b/hw/lpc_ich9.c
@@ -28,21 +28,21 @@
  * THE SOFTWARE.
  */
 #include "qemu-common.h"
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/range.h"
-#include "isa.h"
-#include "sysbus.h"
-#include "pc.h"
-#include "apm.h"
-#include "ioapic.h"
-#include "pci/pci.h"
-#include "pci/pcie_host.h"
-#include "pci/pci_bridge.h"
-#include "ich9.h"
-#include "acpi.h"
-#include "acpi_ich9.h"
-#include "pam.h"
-#include "pci/pci_bus.h"
+#include "hw/isa.h"
+#include "hw/sysbus.h"
+#include "hw/pc.h"
+#include "hw/apm.h"
+#include "hw/ioapic.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pcie_host.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/ich9.h"
+#include "hw/acpi.h"
+#include "hw/acpi_ich9.h"
+#include "hw/pam.h"
+#include "hw/pci/pci_bus.h"
 #include "exec/address-spaces.h"
 #include "sysemu/sysemu.h"
 
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 860df32..5a8bf4d 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -12,9 +12,9 @@
 
 #include <assert.h>
 
-#include "hw.h"
-#include "pci/pci.h"
-#include "scsi.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/scsi.h"
 #include "sysemu/dma.h"
 
 //#define DEBUG_LSI
diff --git a/hw/m25p80.c b/hw/m25p80.c
index 1372d06..55e9d0d 100644
--- a/hw/m25p80.c
+++ b/hw/m25p80.c
@@ -21,10 +21,10 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "sysemu/blockdev.h"
-#include "ssi.h"
-#include "devices.h"
+#include "hw/ssi.h"
+#include "hw/devices.h"
 
 #ifdef M25P80_ERR_DEBUG
 #define DB_PRINT(...) do { \
diff --git a/hw/m48t59.c b/hw/m48t59.c
index 427d95b..39a9d80 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -21,12 +21,12 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "nvram.h"
+#include "hw/hw.h"
+#include "hw/nvram.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
-#include "sysbus.h"
-#include "isa.h"
+#include "hw/sysbus.h"
+#include "hw/isa.h"
 #include "exec/address-spaces.h"
 
 //#define DEBUG_NVRAM
diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c
index b894ab2..a151470 100644
--- a/hw/mac_dbdma.c
+++ b/hw/mac_dbdma.c
@@ -36,9 +36,9 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "isa.h"
-#include "mac_dbdma.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
+#include "hw/mac_dbdma.h"
 #include "qemu/main-loop.h"
 
 /* debug DBDMA */
diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c
index 25121fa..ed32bde 100644
--- a/hw/mac_nvram.c
+++ b/hw/mac_nvram.c
@@ -22,10 +22,10 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "firmware_abi.h"
+#include "hw/hw.h"
+#include "hw/firmware_abi.h"
 #include "sysemu/sysemu.h"
-#include "ppc/mac.h"
+#include "hw/ppc/mac.h"
 
 /* debug NVR */
 //#define DEBUG_NVR
diff --git a/hw/macio.c b/hw/macio.c
index 74bdcd1..792fa39 100644
--- a/hw/macio.c
+++ b/hw/macio.c
@@ -22,11 +22,11 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "ppc/mac.h"
-#include "pci/pci.h"
-#include "mac_dbdma.h"
-#include "escc.h"
+#include "hw/hw.h"
+#include "hw/ppc/mac.h"
+#include "hw/pci/pci.h"
+#include "hw/mac_dbdma.h"
+#include "hw/escc.h"
 
 #define TYPE_MACIO "macio"
 #define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO)
diff --git a/hw/mainstone.c b/hw/mainstone.c
index d1ff6e7..aea908f 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -11,15 +11,15 @@
  * Contributions after 2012-01-13 are licensed under the terms of the
  * GNU GPL, version 2 or (at your option) any later version.
  */
-#include "hw.h"
-#include "pxa.h"
-#include "arm-misc.h"
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/arm-misc.h"
 #include "net/net.h"
-#include "devices.h"
-#include "boards.h"
-#include "flash.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/flash.h"
 #include "sysemu/blockdev.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "exec/address-spaces.h"
 
 /* Device addresses */
diff --git a/hw/marvell_88w8618_audio.c b/hw/marvell_88w8618_audio.c
index c792caf..e042046 100644
--- a/hw/marvell_88w8618_audio.c
+++ b/hw/marvell_88w8618_audio.c
@@ -9,10 +9,10 @@
  * Contributions after 2012-01-13 are licensed under the terms of the
  * GNU GPL, version 2 or (at your option) any later version.
  */
-#include "sysbus.h"
-#include "hw.h"
-#include "i2c.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/i2c.h"
+#include "hw/sysbus.h"
 #include "audio/audio.h"
 
 #define MP_AUDIO_SIZE           0x00001000
diff --git a/hw/max111x.c b/hw/max111x.c
index de1be4d..d477ecd 100644
--- a/hw/max111x.c
+++ b/hw/max111x.c
@@ -10,7 +10,7 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "ssi.h"
+#include "hw/ssi.h"
 
 typedef struct {
     SSISlave ssidev;
diff --git a/hw/max7310.c b/hw/max7310.c
index c2df0b4..e5cb810 100644
--- a/hw/max7310.c
+++ b/hw/max7310.c
@@ -7,7 +7,7 @@
  * This file is licensed under GNU GPL.
  */
 
-#include "i2c.h"
+#include "hw/i2c.h"
 
 typedef struct {
     I2CSlave i2c;
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 2fb11f6..a2119ad 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -21,14 +21,14 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
-#include "mc146818rtc.h"
+#include "hw/mc146818rtc.h"
 #include "qapi/visitor.h"
 
 #ifdef TARGET_I386
-#include "apic.h"
+#include "hw/apic.h"
 #endif
 
 //#define DEBUG_CMOS
diff --git a/hw/mc146818rtc.h b/hw/mc146818rtc.h
index f286b6a..967403e 100644
--- a/hw/mc146818rtc.h
+++ b/hw/mc146818rtc.h
@@ -1,8 +1,8 @@
 #ifndef MC146818RTC_H
 #define MC146818RTC_H
 
-#include "isa.h"
-#include "mc146818rtc_regs.h"
+#include "hw/isa.h"
+#include "hw/mc146818rtc_regs.h"
 
 ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq);
 void rtc_set_memory(ISADevice *dev, int addr, int val);
diff --git a/hw/mcf5206.c b/hw/mcf5206.c
index ea2db23..58cd8d4 100644
--- a/hw/mcf5206.c
+++ b/hw/mcf5206.c
@@ -5,10 +5,10 @@
  *
  * This code is licensed under the GPL
  */
-#include "hw.h"
-#include "mcf.h"
+#include "hw/hw.h"
+#include "hw/mcf.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 #include "sysemu/sysemu.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index 86402d3..748bf56 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -5,14 +5,14 @@
  *
  * This code is licensed under the GPL
  */
-#include "hw.h"
-#include "mcf.h"
+#include "hw/hw.h"
+#include "hw/mcf.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 #include "sysemu/sysemu.h"
 #include "net/net.h"
-#include "boards.h"
-#include "loader.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
 #include "elf.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c
index 8e60f09..0227bd8 100644
--- a/hw/mcf_fec.c
+++ b/hw/mcf_fec.c
@@ -5,9 +5,9 @@
  *
  * This code is licensed under the GPL
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "net/net.h"
-#include "mcf.h"
+#include "hw/mcf.h"
 /* For crc32 */
 #include <zlib.h>
 #include "exec/address-spaces.h"
diff --git a/hw/mcf_intc.c b/hw/mcf_intc.c
index b213656..fff27b3 100644
--- a/hw/mcf_intc.c
+++ b/hw/mcf_intc.c
@@ -5,8 +5,8 @@
  *
  * This code is licensed under the GPL
  */
-#include "hw.h"
-#include "mcf.h"
+#include "hw/hw.h"
+#include "hw/mcf.h"
 #include "exec/address-spaces.h"
 
 typedef struct {
diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
index c443443..aacf0f0 100644
--- a/hw/mcf_uart.c
+++ b/hw/mcf_uart.c
@@ -5,8 +5,8 @@
  *
  * This code is licensed under the GPL
  */
-#include "hw.h"
-#include "mcf.h"
+#include "hw/hw.h"
+#include "hw/mcf.h"
 #include "char/char.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/megasas.c b/hw/megasas.c
index eb191f5..9b815d4 100644
--- a/hw/megasas.c
+++ b/hw/megasas.c
@@ -18,16 +18,16 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "pci/pci.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
 #include "sysemu/dma.h"
-#include "pci/msix.h"
+#include "hw/pci/msix.h"
 #include "qemu/iov.h"
-#include "scsi.h"
-#include "scsi-defs.h"
+#include "hw/scsi.h"
+#include "hw/scsi-defs.h"
 #include "trace.h"
 
-#include "mfi.h"
+#include "hw/mfi.h"
 
 #define MEGASAS_VERSION "1.70"
 #define MEGASAS_MAX_FRAMES 2048         /* Firmware limit at 65535 */
diff --git a/hw/microblaze_boot.c b/hw/microblaze_boot.c
index 3ec5c0f..e13b3e1 100644
--- a/hw/microblaze_boot.c
+++ b/hw/microblaze_boot.c
@@ -28,10 +28,10 @@
 #include "qemu/config-file.h"
 #include "qemu-common.h"
 #include "sysemu/device_tree.h"
-#include "loader.h"
+#include "hw/loader.h"
 #include "elf.h"
 
-#include "microblaze_boot.h"
+#include "hw/microblaze_boot.h"
 
 static struct
 {
diff --git a/hw/microblaze_boot.h b/hw/microblaze_boot.h
index c1cf836..b14ef2b 100644
--- a/hw/microblaze_boot.h
+++ b/hw/microblaze_boot.h
@@ -1,7 +1,7 @@
 #ifndef __MICROBLAZE_BOOT__
 #define __MICROBLAZE_BOOT__
 
-#include "hw.h"
+#include "hw/hw.h"
 
 void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
                             uint32_t ramsize, const char *dtb_filename,
diff --git a/hw/microblaze_pic_cpu.c b/hw/microblaze_pic_cpu.c
index ff36a52..d4743ab 100644
--- a/hw/microblaze_pic_cpu.c
+++ b/hw/microblaze_pic_cpu.c
@@ -22,8 +22,8 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "microblaze_pic_cpu.h"
+#include "hw/hw.h"
+#include "hw/microblaze_pic_cpu.h"
 
 #define D(x)
 
diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c
index d51d1ac..e08e9dc 100644
--- a/hw/milkymist-ac97.c
+++ b/hw/milkymist-ac97.c
@@ -21,8 +21,8 @@
  *   http://www.milkymist.org/socdoc/ac97.pdf
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "audio/audio.h"
 #include "qemu/error-report.h"
diff --git a/hw/milkymist-hpdmc.c b/hw/milkymist-hpdmc.c
index ea4d210..d922f6f 100644
--- a/hw/milkymist-hpdmc.c
+++ b/hw/milkymist-hpdmc.c
@@ -21,8 +21,8 @@
  *   http://www.milkymist.org/socdoc/hpdmc.pdf
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "qemu/error-report.h"
 
diff --git a/hw/milkymist-hw.h b/hw/milkymist-hw.h
index c8bd7e9..d49f96b 100644
--- a/hw/milkymist-hw.h
+++ b/hw/milkymist-hw.h
@@ -1,8 +1,8 @@
 #ifndef QEMU_HW_MILKYMIST_H
 #define QEMU_HW_MILKYMIST_H
 
-#include "qdev.h"
-#include "qdev-addr.h"
+#include "hw/qdev.h"
+#include "hw/qdev-addr.h"
 #include "net/net.h"
 
 static inline DeviceState *milkymist_uart_create(hwaddr base,
diff --git a/hw/milkymist-memcard.c b/hw/milkymist-memcard.c
index 9d15309..d5944bc 100644
--- a/hw/milkymist-memcard.c
+++ b/hw/milkymist-memcard.c
@@ -21,13 +21,13 @@
  *   http://www.milkymist.org/socdoc/memcard.pdf
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "trace.h"
 #include "qemu/error-report.h"
 #include "sysemu/blockdev.h"
-#include "sd.h"
+#include "hw/sd.h"
 
 enum {
     ENABLE_CMD_TX   = (1<<0),
diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c
index 9992dcc..c20ff90 100644
--- a/hw/milkymist-minimac2.c
+++ b/hw/milkymist-minimac2.c
@@ -22,12 +22,12 @@
  *
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "net/net.h"
 #include "qemu/error-report.h"
-#include "qdev-addr.h"
+#include "hw/qdev-addr.h"
 
 #include <zlib.h>
 
diff --git a/hw/milkymist-pfpu.c b/hw/milkymist-pfpu.c
index c347680..ad44b4d 100644
--- a/hw/milkymist-pfpu.c
+++ b/hw/milkymist-pfpu.c
@@ -22,8 +22,8 @@
  *
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "qemu/log.h"
 #include "qemu/error-report.h"
diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c
index 01660be..d911686 100644
--- a/hw/milkymist-softusb.c
+++ b/hw/milkymist-softusb.c
@@ -21,11 +21,11 @@
  *   not available yet
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "ui/console.h"
-#include "hid.h"
+#include "hw/hid.h"
 #include "qemu/error-report.h"
 
 enum {
diff --git a/hw/milkymist-sysctl.c b/hw/milkymist-sysctl.c
index e69ac6f..e083a28 100644
--- a/hw/milkymist-sysctl.c
+++ b/hw/milkymist-sysctl.c
@@ -21,12 +21,12 @@
  *   http://www.milkymist.org/socdoc/sysctl.pdf
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "trace.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 #include "qemu/error-report.h"
 
 enum {
diff --git a/hw/milkymist-tmu2.c b/hw/milkymist-tmu2.c
index 42de10a..b723a04 100644
--- a/hw/milkymist-tmu2.c
+++ b/hw/milkymist-tmu2.c
@@ -24,8 +24,8 @@
  *
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "qemu/error-report.h"
 
diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c
index e73eb84..ac6f537 100644
--- a/hw/milkymist-uart.c
+++ b/hw/milkymist-uart.c
@@ -21,8 +21,8 @@
  *   http://www.milkymist.org/socdoc/uart.pdf
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "char/char.h"
 #include "qemu/error-report.h"
diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c
index 4d0a5df..85ebb85 100644
--- a/hw/milkymist-vgafb.c
+++ b/hw/milkymist-vgafb.c
@@ -22,24 +22,24 @@
  *   http://www.milkymist.org/socdoc/vgafb.pdf
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 #include "ui/console.h"
-#include "framebuffer.h"
+#include "hw/framebuffer.h"
 #include "ui/pixel_ops.h"
 #include "qemu/error-report.h"
 
 #define BITS 8
-#include "milkymist-vgafb_template.h"
+#include "hw/milkymist-vgafb_template.h"
 #define BITS 15
-#include "milkymist-vgafb_template.h"
+#include "hw/milkymist-vgafb_template.h"
 #define BITS 16
-#include "milkymist-vgafb_template.h"
+#include "hw/milkymist-vgafb_template.h"
 #define BITS 24
-#include "milkymist-vgafb_template.h"
+#include "hw/milkymist-vgafb_template.h"
 #define BITS 32
-#include "milkymist-vgafb_template.h"
+#include "hw/milkymist-vgafb_template.h"
 
 enum {
     R_CTRL = 0,
diff --git a/hw/milkymist.c b/hw/milkymist.c
index c04eb35..fd36de5 100644
--- a/hw/milkymist.c
+++ b/hw/milkymist.c
@@ -17,17 +17,17 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysbus.h"
-#include "hw.h"
-#include "flash.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/flash.h"
 #include "sysemu/sysemu.h"
-#include "devices.h"
-#include "boards.h"
-#include "loader.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
 #include "elf.h"
 #include "sysemu/blockdev.h"
-#include "milkymist-hw.h"
-#include "lm32.h"
+#include "hw/milkymist-hw.h"
+#include "hw/lm32.h"
 #include "exec/address-spaces.h"
 
 #define BIOS_FILENAME    "mmone-bios.bin"
diff --git a/hw/mips_addr.c b/hw/mips_addr.c
index aa1c7d8..cddc25c 100644
--- a/hw/mips_addr.c
+++ b/hw/mips_addr.c
@@ -20,8 +20,8 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "mips_cpudevs.h"
+#include "hw/hw.h"
+#include "hw/mips_cpudevs.h"
 
 uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr)
 {
diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index 8b532e1..766aa9d 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -18,29 +18,29 @@
  * http://www.loongsondeveloper.com/doc/Loongson2EUserGuide.pdf
  */
 
-#include "hw.h"
-#include "pc.h"
-#include "serial.h"
-#include "fdc.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/fdc.h"
 #include "net/net.h"
-#include "boards.h"
-#include "smbus.h"
+#include "hw/boards.h"
+#include "hw/smbus.h"
 #include "block/block.h"
-#include "flash.h"
-#include "mips.h"
-#include "mips_cpudevs.h"
-#include "pci/pci.h"
+#include "hw/flash.h"
+#include "hw/mips.h"
+#include "hw/mips_cpudevs.h"
+#include "hw/pci/pci.h"
 #include "char/char.h"
 #include "sysemu/sysemu.h"
 #include "audio/audio.h"
 #include "qemu/log.h"
-#include "loader.h"
-#include "mips-bios.h"
-#include "ide.h"
+#include "hw/loader.h"
+#include "hw/mips-bios.h"
+#include "hw/ide.h"
 #include "elf.h"
-#include "vt82c686.h"
-#include "mc146818rtc.h"
-#include "i8254.h"
+#include "hw/vt82c686.h"
+#include "hw/mc146818rtc.h"
+#include "hw/i8254.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/mips_int.c b/hw/mips_int.c
index 6423fd0..ddd3b1b 100644
--- a/hw/mips_int.c
+++ b/hw/mips_int.c
@@ -20,8 +20,8 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "mips_cpudevs.h"
+#include "hw/hw.h"
+#include "hw/mips_cpudevs.h"
 #include "cpu.h"
 
 static void cpu_mips_irq_request(void *opaque, int irq, int level)
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 17fbdde..daeb985 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -22,25 +22,25 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "mips.h"
-#include "mips_cpudevs.h"
-#include "pc.h"
-#include "serial.h"
-#include "isa.h"
-#include "fdc.h"
+#include "hw/hw.h"
+#include "hw/mips.h"
+#include "hw/mips_cpudevs.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/isa.h"
+#include "hw/fdc.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/arch_init.h"
-#include "boards.h"
+#include "hw/boards.h"
 #include "net/net.h"
-#include "esp.h"
-#include "mips-bios.h"
-#include "loader.h"
-#include "mc146818rtc.h"
-#include "i8254.h"
-#include "pcspk.h"
+#include "hw/esp.h"
+#include "hw/mips-bios.h"
+#include "hw/loader.h"
+#include "hw/mc146818rtc.h"
+#include "hw/i8254.h"
+#include "hw/pcspk.h"
 #include "sysemu/blockdev.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "exec/address-spaces.h"
 
 enum jazz_model_e
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 2a150df..9a67dce 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -22,32 +22,32 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "pc.h"
-#include "serial.h"
-#include "fdc.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/fdc.h"
 #include "net/net.h"
-#include "boards.h"
-#include "smbus.h"
+#include "hw/boards.h"
+#include "hw/smbus.h"
 #include "block/block.h"
-#include "flash.h"
-#include "mips.h"
-#include "mips_cpudevs.h"
-#include "pci/pci.h"
+#include "hw/flash.h"
+#include "hw/mips.h"
+#include "hw/mips_cpudevs.h"
+#include "hw/pci/pci.h"
 #include "char/char.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/arch_init.h"
-#include "boards.h"
+#include "hw/boards.h"
 #include "qemu/log.h"
-#include "mips-bios.h"
-#include "ide.h"
-#include "loader.h"
+#include "hw/mips-bios.h"
+#include "hw/ide.h"
+#include "hw/loader.h"
 #include "elf.h"
-#include "mc146818rtc.h"
-#include "i8254.h"
+#include "hw/mc146818rtc.h"
+#include "hw/i8254.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
-#include "sysbus.h"             /* SysBusDevice */
+#include "hw/sysbus.h"             /* SysBusDevice */
 
 //#define DEBUG_BOARD_INIT
 
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index b0ab8f6..4935c78 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -24,18 +24,18 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "mips.h"
-#include "mips_cpudevs.h"
-#include "serial.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/mips.h"
+#include "hw/mips_cpudevs.h"
+#include "hw/serial.h"
+#include "hw/isa.h"
 #include "net/net.h"
 #include "sysemu/sysemu.h"
-#include "boards.h"
-#include "mips-bios.h"
-#include "loader.h"
+#include "hw/boards.h"
+#include "hw/mips-bios.h"
+#include "hw/loader.h"
 #include "elf.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "exec/address-spaces.h"
 
 static struct _loaderparams {
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index 5df7eb4..539a562 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -7,23 +7,23 @@
  * All peripherial devices are attached to this "bus" with
  * the standard PC ISA addresses.
 */
-#include "hw.h"
-#include "mips.h"
-#include "mips_cpudevs.h"
-#include "pc.h"
-#include "serial.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/mips.h"
+#include "hw/mips_cpudevs.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/isa.h"
 #include "net/net.h"
 #include "sysemu/sysemu.h"
-#include "boards.h"
-#include "flash.h"
+#include "hw/boards.h"
+#include "hw/flash.h"
 #include "qemu/log.h"
-#include "mips-bios.h"
-#include "ide.h"
-#include "loader.h"
+#include "hw/mips-bios.h"
+#include "hw/ide.h"
+#include "hw/loader.h"
 #include "elf.h"
-#include "mc146818rtc.h"
-#include "i8254.h"
+#include "hw/mc146818rtc.h"
+#include "hw/i8254.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/mips_timer.c b/hw/mips_timer.c
index 83c400c..9ad13f3 100644
--- a/hw/mips_timer.c
+++ b/hw/mips_timer.c
@@ -20,8 +20,8 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "mips_cpudevs.h"
+#include "hw/hw.h"
+#include "hw/mips_cpudevs.h"
 #include "qemu/timer.h"
 
 #define TIMER_FREQ	100 * 1000 * 1000
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index ff6bf7f..ac6193a 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -1,7 +1,7 @@
-#include "hw.h"
+#include "hw/hw.h"
 #include "net/net.h"
 #include "trace.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 /* MIPSnet register offsets */
 
diff --git a/hw/mpc8544_guts.c b/hw/mpc8544_guts.c
index 728723c..193beab 100644
--- a/hw/mpc8544_guts.c
+++ b/hw/mpc8544_guts.c
@@ -17,9 +17,9 @@
  *
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "sysemu/sysemu.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 #define MPC8544_GUTS_MMIO_SIZE        0x1000
 #define MPC8544_GUTS_RSTCR_RESET      0x02
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index 7ae05e3..1dd1505 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -10,8 +10,8 @@
  * Contributions after 2012-01-13 are licensed under the terms of the
  * GNU GPL, version 2 or (at your option) any later version.
  */
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 
 /* Mainstone FPGA for extern irqs */
 #define FPGA_GPIO_PIN	0
diff --git a/hw/multiboot.c b/hw/multiboot.c
index c4ec2e3..3cb228f 100644
--- a/hw/multiboot.c
+++ b/hw/multiboot.c
@@ -22,10 +22,10 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "fw_cfg.h"
-#include "multiboot.h"
-#include "loader.h"
+#include "hw/hw.h"
+#include "hw/fw_cfg.h"
+#include "hw/multiboot.h"
+#include "hw/loader.h"
 #include "elf.h"
 #include "sysemu/sysemu.h"
 
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 272cb80..a37dbd7 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -9,19 +9,19 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "sysbus.h"
-#include "arm-misc.h"
-#include "devices.h"
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
 #include "net/net.h"
 #include "sysemu/sysemu.h"
-#include "boards.h"
-#include "serial.h"
+#include "hw/boards.h"
+#include "hw/serial.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 #include "block/block.h"
-#include "flash.h"
+#include "hw/flash.h"
 #include "ui/console.h"
-#include "i2c.h"
+#include "hw/i2c.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 #include "ui/pixel_ops.h"
diff --git a/hw/nand.c b/hw/nand.c
index 4a71265..4176272 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -18,10 +18,10 @@
 
 #ifndef NAND_IO
 
-# include "hw.h"
-# include "flash.h"
+# include "hw/hw.h"
+# include "hw/flash.h"
 # include "sysemu/blockdev.h"
-# include "sysbus.h"
+# include "hw/sysbus.h"
 #include "qemu/error-report.h"
 
 # define NAND_CMD_READ0		0x00
diff --git a/hw/ne2000-isa.c b/hw/ne2000-isa.c
index 342c6bd..47c00c3 100644
--- a/hw/ne2000-isa.c
+++ b/hw/ne2000-isa.c
@@ -21,12 +21,12 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "pc.h"
-#include "isa.h"
-#include "qdev.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
+#include "hw/qdev.h"
 #include "net/net.h"
-#include "ne2000.h"
+#include "hw/ne2000.h"
 #include "exec/address-spaces.h"
 
 typedef struct ISANE2000State {
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 3dd1c84..7dadc1c 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -21,11 +21,11 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "pci/pci.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
 #include "net/net.h"
-#include "ne2000.h"
-#include "loader.h"
+#include "hw/ne2000.h"
+#include "hw/loader.h"
 #include "sysemu/sysemu.h"
 
 /* debug NE2000 card */
diff --git a/hw/nseries.c b/hw/nseries.c
index 99d353a..c5bf9f9 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -20,19 +20,19 @@
 
 #include "qemu-common.h"
 #include "sysemu/sysemu.h"
-#include "omap.h"
-#include "arm-misc.h"
-#include "irq.h"
+#include "hw/omap.h"
+#include "hw/arm-misc.h"
+#include "hw/irq.h"
 #include "ui/console.h"
-#include "boards.h"
-#include "i2c.h"
-#include "devices.h"
-#include "flash.h"
-#include "hw.h"
-#include "bt.h"
-#include "loader.h"
+#include "hw/boards.h"
+#include "hw/i2c.h"
+#include "hw/devices.h"
+#include "hw/flash.h"
+#include "hw/hw.h"
+#include "hw/bt.h"
+#include "hw/loader.h"
 #include "sysemu/blockdev.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "exec/address-spaces.h"
 
 /* Nokia N8x0 support */
diff --git a/hw/omap1.c b/hw/omap1.c
index 623b101..6f0a8ca 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -16,14 +16,14 @@
  * 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.h"
-#include "arm-misc.h"
-#include "omap.h"
+#include "hw/hw.h"
+#include "hw/arm-misc.h"
+#include "hw/omap.h"
 #include "sysemu/sysemu.h"
-#include "soc_dma.h"
+#include "hw/soc_dma.h"
 #include "sysemu/blockdev.h"
 #include "qemu/range.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 /* Should signal the TCMI/GPMC */
 uint32_t omap_badwidth_read8(void *opaque, hwaddr addr)
diff --git a/hw/omap2.c b/hw/omap2.c
index 038a82a..0a2cd7b 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -19,15 +19,15 @@
  */
 
 #include "sysemu/blockdev.h"
-#include "hw.h"
-#include "arm-misc.h"
-#include "omap.h"
+#include "hw/hw.h"
+#include "hw/arm-misc.h"
+#include "hw/omap.h"
 #include "sysemu/sysemu.h"
 #include "qemu/timer.h"
 #include "char/char.h"
-#include "flash.h"
-#include "soc_dma.h"
-#include "sysbus.h"
+#include "hw/flash.h"
+#include "hw/soc_dma.h"
+#include "hw/sysbus.h"
 #include "audio/audio.h"
 
 /* Enhanced Audio Controller (CODEC only) */
diff --git a/hw/omap_clk.c b/hw/omap_clk.c
index 8448006..c7b5c11 100644
--- a/hw/omap_clk.c
+++ b/hw/omap_clk.c
@@ -18,8 +18,8 @@
  * 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.h"
-#include "omap.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
 
 struct clk {
     const char *name;
diff --git a/hw/omap_dma.c b/hw/omap_dma.c
index 0c878b6..0c5902f 100644
--- a/hw/omap_dma.c
+++ b/hw/omap_dma.c
@@ -19,9 +19,9 @@
  */
 #include "qemu-common.h"
 #include "qemu/timer.h"
-#include "omap.h"
-#include "irq.h"
-#include "soc_dma.h"
+#include "hw/omap.h"
+#include "hw/irq.h"
+#include "hw/soc_dma.h"
 
 struct omap_dma_channel_s {
     /* transfer data */
diff --git a/hw/omap_dss.c b/hw/omap_dss.c
index ae51bdf..948ad8f 100644
--- a/hw/omap_dss.c
+++ b/hw/omap_dss.c
@@ -17,9 +17,9 @@
  * 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.h"
+#include "hw/hw.h"
 #include "ui/console.h"
-#include "omap.h"
+#include "hw/omap.h"
 
 struct omap_dss_s {
     qemu_irq irq;
diff --git a/hw/omap_gpio.c b/hw/omap_gpio.c
index aadf1cc..c79f61c 100644
--- a/hw/omap_gpio.c
+++ b/hw/omap_gpio.c
@@ -18,9 +18,9 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "omap.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
+#include "hw/sysbus.h"
 
 struct omap_gpio_s {
     qemu_irq irq;
diff --git a/hw/omap_gpmc.c b/hw/omap_gpmc.c
index 02ab0ab..ebb259c 100644
--- a/hw/omap_gpmc.c
+++ b/hw/omap_gpmc.c
@@ -18,9 +18,9 @@
  * 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.h"
-#include "flash.h"
-#include "omap.h"
+#include "hw/hw.h"
+#include "hw/flash.h"
+#include "hw/omap.h"
 #include "exec/memory.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/omap_gptimer.c b/hw/omap_gptimer.c
index a5db710..8485ee8 100644
--- a/hw/omap_gptimer.c
+++ b/hw/omap_gptimer.c
@@ -17,9 +17,9 @@
  * 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.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
-#include "omap.h"
+#include "hw/omap.h"
 
 /* GP timers */
 struct omap_gp_timer_s {
diff --git a/hw/omap_i2c.c b/hw/omap_i2c.c
index 143b198..92f7b37 100644
--- a/hw/omap_i2c.c
+++ b/hw/omap_i2c.c
@@ -16,10 +16,10 @@
  * 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.h"
-#include "i2c.h"
-#include "omap.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/i2c.h"
+#include "hw/omap.h"
+#include "hw/sysbus.h"
 
 
 typedef struct OMAPI2CState {
diff --git a/hw/omap_intc.c b/hw/omap_intc.c
index 4b0acd0..7da9c35 100644
--- a/hw/omap_intc.c
+++ b/hw/omap_intc.c
@@ -17,9 +17,9 @@
  * 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.h"
-#include "omap.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
+#include "hw/sysbus.h"
 
 /* Interrupt Handlers */
 struct omap_intr_handler_bank_s {
diff --git a/hw/omap_l4.c b/hw/omap_l4.c
index 09e983f..cbe8a06 100644
--- a/hw/omap_l4.c
+++ b/hw/omap_l4.c
@@ -17,8 +17,8 @@
  * 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.h"
-#include "omap.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
 
 struct omap_l4_s {
     MemoryRegion *address_space;
diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c
index 936850a..c426f3a 100644
--- a/hw/omap_lcdc.c
+++ b/hw/omap_lcdc.c
@@ -16,10 +16,10 @@
  * 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.h"
+#include "hw/hw.h"
 #include "ui/console.h"
-#include "omap.h"
-#include "framebuffer.h"
+#include "hw/omap.h"
+#include "hw/framebuffer.h"
 #include "ui/pixel_ops.h"
 
 struct omap_lcd_panel_s {
@@ -70,13 +70,13 @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s)
 #define draw_line_func drawfn
 
 #define DEPTH 8
-#include "omap_lcd_template.h"
+#include "hw/omap_lcd_template.h"
 #define DEPTH 15
-#include "omap_lcd_template.h"
+#include "hw/omap_lcd_template.h"
 #define DEPTH 16
-#include "omap_lcd_template.h"
+#include "hw/omap_lcd_template.h"
 #define DEPTH 32
-#include "omap_lcd_template.h"
+#include "hw/omap_lcd_template.h"
 
 static draw_line_func draw_line_table2[33] = {
     [0 ... 32]	= NULL,
diff --git a/hw/omap_mmc.c b/hw/omap_mmc.c
index 7ecd9bd..6e48110 100644
--- a/hw/omap_mmc.c
+++ b/hw/omap_mmc.c
@@ -16,9 +16,9 @@
  * 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.h"
-#include "omap.h"
-#include "sd.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
+#include "hw/sd.h"
 
 struct omap_mmc_s {
     qemu_irq irq;
diff --git a/hw/omap_sdrc.c b/hw/omap_sdrc.c
index b0f3b8e..510e6cc 100644
--- a/hw/omap_sdrc.c
+++ b/hw/omap_sdrc.c
@@ -17,8 +17,8 @@
  * 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.h"
-#include "omap.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
 
 /* SDRAM Controller Subsystem */
 struct omap_sdrc_s {
diff --git a/hw/omap_spi.c b/hw/omap_spi.c
index 8ff01ed..1cbd98d 100644
--- a/hw/omap_spi.c
+++ b/hw/omap_spi.c
@@ -19,8 +19,8 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
-#include "hw.h"
-#include "omap.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
 
 /* Multichannel SPI */
 struct omap_mcspi_s {
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index 30998c5..8598233 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -25,12 +25,12 @@
  * 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.h"
+#include "hw/hw.h"
 #include "ui/console.h"
-#include "omap.h"
-#include "boards.h"
-#include "arm-misc.h"
-#include "flash.h"
+#include "hw/omap.h"
+#include "hw/boards.h"
+#include "hw/arm-misc.h"
+#include "hw/flash.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/omap_synctimer.c b/hw/omap_synctimer.c
index 945711e..13e7280 100644
--- a/hw/omap_synctimer.c
+++ b/hw/omap_synctimer.c
@@ -17,9 +17,9 @@
  * 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.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
-#include "omap.h"
+#include "hw/omap.h"
 struct omap_synctimer_s {
     MemoryRegion iomem;
     uint32_t val;
diff --git a/hw/omap_tap.c b/hw/omap_tap.c
index e273e97..181ecee 100644
--- a/hw/omap_tap.c
+++ b/hw/omap_tap.c
@@ -18,8 +18,8 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "omap.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
 
 /* TEST-Chip-level TAP */
 static uint64_t omap_tap_read(void *opaque, hwaddr addr,
diff --git a/hw/omap_uart.c b/hw/omap_uart.c
index 0ebfbf8..af51ce7 100644
--- a/hw/omap_uart.c
+++ b/hw/omap_uart.c
@@ -18,9 +18,9 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "char/char.h"
-#include "hw.h"
-#include "omap.h"
-#include "serial.h"
+#include "hw/hw.h"
+#include "hw/omap.h"
+#include "hw/serial.h"
 #include "exec/address-spaces.h"
 
 /* UARTs */
diff --git a/hw/onenand.c b/hw/onenand.c
index 00a8738..ddba366 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -19,13 +19,13 @@
  */
 
 #include "qemu-common.h"
-#include "hw.h"
-#include "flash.h"
-#include "irq.h"
+#include "hw/hw.h"
+#include "hw/flash.h"
+#include "hw/irq.h"
 #include "sysemu/blockdev.h"
 #include "exec/memory.h"
 #include "exec/address-spaces.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/error-report.h"
 
 /* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c
index f9ba5ee..be64bf2 100644
--- a/hw/opencores_eth.c
+++ b/hw/opencores_eth.c
@@ -31,8 +31,8 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 #include "net/net.h"
 #include "sysemu/sysemu.h"
 #include "trace.h"
diff --git a/hw/openpic.c b/hw/openpic.c
index 20a479c..03a7075 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -33,14 +33,14 @@
  * Serial interrupts, as implemented in Raven chipset are not supported yet.
  *
  */
-#include "hw.h"
-#include "ppc/mac.h"
-#include "pci/pci.h"
-#include "openpic.h"
-#include "sysbus.h"
-#include "pci/msi.h"
+#include "hw/hw.h"
+#include "hw/ppc/mac.h"
+#include "hw/pci/pci.h"
+#include "hw/openpic.h"
+#include "hw/sysbus.h"
+#include "hw/pci/msi.h"
 #include "qemu/bitops.h"
-#include "ppc.h"
+#include "hw/ppc.h"
 
 //#define DEBUG_OPENPIC
 
diff --git a/hw/openrisc_pic.c b/hw/openrisc_pic.c
index aaeb9a9..931511e 100644
--- a/hw/openrisc_pic.c
+++ b/hw/openrisc_pic.c
@@ -18,7 +18,7 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "cpu.h"
 
 /* OpenRISC pic handler */
diff --git a/hw/openrisc_sim.c b/hw/openrisc_sim.c
index 30947de..db2aac8 100644
--- a/hw/openrisc_sim.c
+++ b/hw/openrisc_sim.c
@@ -18,15 +18,15 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "boards.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
 #include "elf.h"
-#include "serial.h"
+#include "hw/serial.h"
 #include "net/net.h"
-#include "loader.h"
+#include "hw/loader.h"
 #include "exec/address-spaces.h"
 #include "sysemu/sysemu.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "sysemu/qtest.h"
 
 #define KERNEL_LOAD_ADDR 0x100
diff --git a/hw/openrisc_timer.c b/hw/openrisc_timer.c
index d965be7..f6c877f 100644
--- a/hw/openrisc_timer.c
+++ b/hw/openrisc_timer.c
@@ -19,7 +19,7 @@
  */
 
 #include "cpu.h"
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
 
 #define TIMER_FREQ    (20 * 1000 * 1000)    /* 20MHz */
diff --git a/hw/palm.c b/hw/palm.c
index a633dfc..91bc74a 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -16,15 +16,15 @@
  * 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.h"
+#include "hw/hw.h"
 #include "audio/audio.h"
 #include "sysemu/sysemu.h"
 #include "ui/console.h"
-#include "omap.h"
-#include "boards.h"
-#include "arm-misc.h"
-#include "devices.h"
-#include "loader.h"
+#include "hw/omap.h"
+#include "hw/boards.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "hw/loader.h"
 #include "exec/address-spaces.h"
 
 static uint32_t static_readb(void *opaque, hwaddr offset)
diff --git a/hw/pam.c b/hw/pam.c
index 1d72e88..6c0061e 100644
--- a/hw/pam.c
+++ b/hw/pam.c
@@ -27,7 +27,7 @@
  * THE SOFTWARE.
  */
 #include "sysemu/sysemu.h"
-#include "pam.h"
+#include "hw/pam.h"
 
 void smram_update(MemoryRegion *smram_region, uint8_t smram,
                   uint8_t smm_enabled)
diff --git a/hw/parallel.c b/hw/parallel.c
index 3a4e06b..0b9af43 100644
--- a/hw/parallel.c
+++ b/hw/parallel.c
@@ -22,10 +22,10 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "char/char.h"
-#include "isa.h"
-#include "pc.h"
+#include "hw/isa.h"
+#include "hw/pc.h"
 #include "sysemu/sysemu.h"
 
 //#define DEBUG_PARALLEL
diff --git a/hw/pc-testdev.c b/hw/pc-testdev.c
index cf64a1f..8236bce 100644
--- a/hw/pc-testdev.c
+++ b/hw/pc-testdev.c
@@ -39,9 +39,9 @@
 #if defined(CONFIG_POSIX)
 #include <sys/mman.h>
 #endif
-#include "hw.h"
-#include "qdev.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/qdev.h"
+#include "hw/isa.h"
 
 #define IOMEM_LEN    0x10000
 
diff --git a/hw/pc.c b/hw/pc.c
index 07caba7..309bb83 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -21,29 +21,29 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "pc.h"
-#include "serial.h"
-#include "apic.h"
-#include "fdc.h"
-#include "ide.h"
-#include "pci/pci.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/apic.h"
+#include "hw/fdc.h"
+#include "hw/ide.h"
+#include "hw/pci/pci.h"
 #include "monitor/monitor.h"
-#include "fw_cfg.h"
-#include "hpet_emul.h"
-#include "smbios.h"
-#include "loader.h"
+#include "hw/fw_cfg.h"
+#include "hw/hpet_emul.h"
+#include "hw/smbios.h"
+#include "hw/loader.h"
 #include "elf.h"
-#include "multiboot.h"
-#include "mc146818rtc.h"
-#include "i8254.h"
-#include "pcspk.h"
-#include "pci/msi.h"
-#include "sysbus.h"
+#include "hw/multiboot.h"
+#include "hw/mc146818rtc.h"
+#include "hw/i8254.h"
+#include "hw/pcspk.h"
+#include "hw/pci/msi.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/kvm.h"
 #include "kvm_i386.h"
-#include "xen.h"
+#include "hw/xen.h"
 #include "sysemu/blockdev.h"
 #include "hw/block-common.h"
 #include "ui/qemu-spice.h"
diff --git a/hw/pc.h b/hw/pc.h
index da1b102..03a0277 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -4,11 +4,11 @@
 #include "qemu-common.h"
 #include "exec/memory.h"
 #include "exec/ioport.h"
-#include "isa.h"
-#include "fdc.h"
+#include "hw/isa.h"
+#include "hw/fdc.h"
 #include "net/net.h"
 #include "exec/memory.h"
-#include "ioapic.h"
+#include "hw/ioapic.h"
 
 /* PC-style peripherals (also used by other machines).  */
 
diff --git a/hw/pc87312.c b/hw/pc87312.c
index 0e9760e..c4e4c62 100644
--- a/hw/pc87312.c
+++ b/hw/pc87312.c
@@ -23,7 +23,7 @@
  * THE SOFTWARE.
  */
 
-#include "pc87312.h"
+#include "hw/pc87312.h"
 #include "qemu/error-report.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/sysemu.h"
diff --git a/hw/pc87312.h b/hw/pc87312.h
index 7b9e6f6..ad087c7 100644
--- a/hw/pc87312.h
+++ b/hw/pc87312.h
@@ -25,7 +25,7 @@
 #ifndef QEMU_PC87312_H
 #define QEMU_PC87312_H
 
-#include "isa.h"
+#include "hw/isa.h"
 
 
 #define TYPE_PC87312 "pc87312"
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index aa9cc81..73a8656 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -24,23 +24,23 @@
 
 #include <glib.h>
 
-#include "hw.h"
-#include "pc.h"
-#include "apic.h"
-#include "pci/pci.h"
-#include "pci/pci_ids.h"
-#include "usb.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/apic.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_ids.h"
+#include "hw/usb.h"
 #include "net/net.h"
-#include "boards.h"
-#include "ide.h"
+#include "hw/boards.h"
+#include "hw/ide.h"
 #include "sysemu/kvm.h"
-#include "kvm/clock.h"
+#include "hw/kvm/clock.h"
 #include "sysemu/sysemu.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "sysemu/arch_init.h"
 #include "sysemu/blockdev.h"
-#include "smbus.h"
-#include "xen.h"
+#include "hw/smbus.h"
+#include "hw/xen.h"
 #include "exec/memory.h"
 #include "exec/address-spaces.h"
 #include "cpu.h"
diff --git a/hw/pc_q35.c b/hw/pc_q35.c
index e22fb98..4f5f347 100644
--- a/hw/pc_q35.c
+++ b/hw/pc_q35.c
@@ -27,17 +27,17 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "sysemu/arch_init.h"
-#include "smbus.h"
-#include "boards.h"
-#include "mc146818rtc.h"
-#include "xen.h"
+#include "hw/smbus.h"
+#include "hw/boards.h"
+#include "hw/mc146818rtc.h"
+#include "hw/xen.h"
 #include "sysemu/kvm.h"
-#include "kvm/clock.h"
-#include "q35.h"
+#include "hw/kvm/clock.h"
+#include "hw/q35.h"
 #include "exec/address-spaces.h"
-#include "ich9.h"
+#include "hw/ich9.h"
 #include "hw/ide/pci.h"
 #include "hw/ide/ahci.h"
 #include "hw/usb.h"
diff --git a/hw/pc_sysfw.c b/hw/pc_sysfw.c
index 8b65a7a..3e01528 100644
--- a/hw/pc_sysfw.c
+++ b/hw/pc_sysfw.c
@@ -25,13 +25,13 @@
 
 #include "sysemu/blockdev.h"
 #include "qemu/error-report.h"
-#include "sysbus.h"
-#include "hw.h"
-#include "pc.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
 #include "hw/boards.h"
-#include "loader.h"
+#include "hw/loader.h"
 #include "sysemu/sysemu.h"
-#include "flash.h"
+#include "hw/flash.h"
 #include "sysemu/kvm.h"
 
 #define BIOS_FILENAME "bios.bin"
diff --git a/hw/pci_bridge_dev.c b/hw/pci_bridge_dev.c
index 1124c53..9cc6a40 100644
--- a/hw/pci_bridge_dev.c
+++ b/hw/pci_bridge_dev.c
@@ -19,13 +19,13 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "pci/pci_bridge.h"
-#include "pci/pci_ids.h"
-#include "pci/msi.h"
-#include "pci/shpc.h"
-#include "pci/slotid_cap.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/pci_ids.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/shpc.h"
+#include "hw/pci/slotid_cap.h"
 #include "exec/memory.h"
-#include "pci/pci_bus.h"
+#include "hw/pci/pci_bus.h"
 
 struct PCIBridgeDev {
     PCIBridge bridge;
diff --git a/hw/pckbd.c b/hw/pckbd.c
index 3bad09b..cc63df0 100644
--- a/hw/pckbd.c
+++ b/hw/pckbd.c
@@ -21,10 +21,10 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "isa.h"
-#include "pc.h"
-#include "ps2.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
+#include "hw/pc.h"
+#include "hw/ps2.h"
 #include "sysemu/sysemu.h"
 
 /* debug PC keyboard */
diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c
index df63b22..55f80ca 100644
--- a/hw/pcnet-pci.c
+++ b/hw/pcnet-pci.c
@@ -27,13 +27,13 @@
  * AMD Publication# 19436  Rev:E  Amendment/0  Issue Date: June 2000
  */
 
-#include "pci/pci.h"
+#include "hw/pci/pci.h"
 #include "net/net.h"
-#include "loader.h"
+#include "hw/loader.h"
 #include "qemu/timer.h"
 #include "sysemu/dma.h"
 
-#include "pcnet.h"
+#include "hw/pcnet.h"
 
 //#define PCNET_DEBUG
 //#define PCNET_DEBUG_IO
diff --git a/hw/pcnet.c b/hw/pcnet.c
index e0de1e3..b0b462b 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -35,13 +35,13 @@
  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR92C990.txt
  */
 
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "net/net.h"
 #include "qemu/timer.h"
 #include "qemu/sockets.h"
 #include "sysemu/sysemu.h"
 
-#include "pcnet.h"
+#include "hw/pcnet.h"
 
 //#define PCNET_DEBUG
 //#define PCNET_DEBUG_IO
diff --git a/hw/pcspk.c b/hw/pcspk.c
index dfab955..d533415 100644
--- a/hw/pcspk.c
+++ b/hw/pcspk.c
@@ -22,13 +22,13 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "pc.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
 #include "audio/audio.h"
 #include "qemu/timer.h"
-#include "i8254.h"
-#include "pcspk.h"
+#include "hw/i8254.h"
+#include "hw/pcspk.h"
 
 #define PCSPK_BUF_LEN 1792
 #define PCSPK_SAMPLE_RATE 32000
diff --git a/hw/pcspk.h b/hw/pcspk.h
index 7f42bac..f448d22 100644
--- a/hw/pcspk.h
+++ b/hw/pcspk.h
@@ -25,8 +25,8 @@
 #ifndef HW_PCSPK_H
 #define HW_PCSPK_H
 
-#include "hw.h"
-#include "isa.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
 
 static inline ISADevice *pcspk_init(ISABus *bus, ISADevice *pit)
 {
diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c
index fe7a932..cfc0220 100644
--- a/hw/petalogix_ml605_mmu.c
+++ b/hw/petalogix_ml605_mmu.c
@@ -25,23 +25,23 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
-#include "hw.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
 #include "net/net.h"
-#include "flash.h"
+#include "hw/flash.h"
 #include "sysemu/sysemu.h"
-#include "devices.h"
-#include "boards.h"
-#include "xilinx.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/xilinx.h"
 #include "sysemu/blockdev.h"
-#include "serial.h"
+#include "hw/serial.h"
 #include "exec/address-spaces.h"
-#include "ssi.h"
+#include "hw/ssi.h"
 
-#include "microblaze_boot.h"
-#include "microblaze_pic_cpu.h"
+#include "hw/microblaze_boot.h"
+#include "hw/microblaze_pic_cpu.h"
 
-#include "stream.h"
+#include "hw/stream.h"
 
 #define LMB_BRAM_SIZE  (128 * 1024)
 #define FLASH_SIZE     (32 * 1024 * 1024)
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index 8605fb8..2498362 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -23,19 +23,19 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
-#include "hw.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
 #include "net/net.h"
-#include "flash.h"
+#include "hw/flash.h"
 #include "sysemu/sysemu.h"
-#include "devices.h"
-#include "boards.h"
-#include "xilinx.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/xilinx.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
-#include "microblaze_boot.h"
-#include "microblaze_pic_cpu.h"
+#include "hw/microblaze_boot.h"
+#include "hw/microblaze_pic_cpu.h"
 
 #define LMB_BRAM_SIZE  (128 * 1024)
 #define FLASH_SIZE     (16 * 1024 * 1024)
diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index 123b006..5d57bab 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -36,13 +36,13 @@
  * It does not implement much more ...
  */
 
-#include "hw.h"
-#include "flash.h"
+#include "hw/hw.h"
+#include "hw/flash.h"
 #include "block/block.h"
 #include "qemu/timer.h"
 #include "exec/address-spaces.h"
 #include "qemu/host-utils.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 #define PFLASH_BUG(fmt, ...) \
 do { \
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c
index 44bd465..37b4fcc 100644
--- a/hw/pflash_cfi02.c
+++ b/hw/pflash_cfi02.c
@@ -35,13 +35,13 @@
  * It does not implement multiple sectors erase
  */
 
-#include "hw.h"
-#include "flash.h"
+#include "hw/hw.h"
+#include "hw/flash.h"
 #include "qemu/timer.h"
 #include "block/block.h"
 #include "exec/address-spaces.h"
 #include "qemu/host-utils.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 //#define PFLASH_DEBUG
 #ifdef PFLASH_DEBUG
diff --git a/hw/piix4.c b/hw/piix4.c
index c1cb94d..0f5cd01 100644
--- a/hw/piix4.c
+++ b/hw/piix4.c
@@ -22,11 +22,11 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "pc.h"
-#include "pci/pci.h"
-#include "isa.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/pci/pci.h"
+#include "hw/isa.h"
+#include "hw/sysbus.h"
 
 PCIDevice *piix4_dev;
 
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 6c77e49..ac33db5 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -22,15 +22,15 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "pc.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
-#include "isa.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/isa.h"
+#include "hw/sysbus.h"
 #include "qemu/range.h"
-#include "xen.h"
-#include "pam.h"
+#include "hw/xen.h"
+#include "hw/pam.h"
 #include "sysemu/sysemu.h"
 
 /*
diff --git a/hw/pl011.c b/hw/pl011.c
index 002a50e..332d5b9 100644
--- a/hw/pl011.c
+++ b/hw/pl011.c
@@ -7,7 +7,7 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "char/char.h"
 
 typedef struct {
diff --git a/hw/pl022.c b/hw/pl022.c
index c160e90..536c216 100644
--- a/hw/pl022.c
+++ b/hw/pl022.c
@@ -7,8 +7,8 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
-#include "ssi.h"
+#include "hw/sysbus.h"
+#include "hw/ssi.h"
 
 //#define DEBUG_PL022 1
 
diff --git a/hw/pl031.c b/hw/pl031.c
index 757867f..764940b 100644
--- a/hw/pl031.c
+++ b/hw/pl031.c
@@ -11,7 +11,7 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
 
diff --git a/hw/pl041.c b/hw/pl041.c
index 0b71c45..92dddc2 100644
--- a/hw/pl041.c
+++ b/hw/pl041.c
@@ -20,10 +20,10 @@
  *
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
-#include "pl041.h"
-#include "lm4549.h"
+#include "hw/pl041.h"
+#include "hw/lm4549.h"
 
 #if 0
 #define PL041_DEBUG_LEVEL 1
diff --git a/hw/pl050.c b/hw/pl050.c
index 5d06bc9..bc31ab6 100644
--- a/hw/pl050.c
+++ b/hw/pl050.c
@@ -7,8 +7,8 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
-#include "ps2.h"
+#include "hw/sysbus.h"
+#include "hw/ps2.h"
 
 typedef struct {
     SysBusDevice busdev;
diff --git a/hw/pl061.c b/hw/pl061.c
index a78e819..74bc109 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -8,7 +8,7 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 //#define DEBUG_PL061 1
 
diff --git a/hw/pl080.c b/hw/pl080.c
index f6bbf98..00b66b4 100644
--- a/hw/pl080.c
+++ b/hw/pl080.c
@@ -7,7 +7,7 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 #define PL080_MAX_CHANNELS 8
 #define PL080_CONF_E    0x1
diff --git a/hw/pl110.c b/hw/pl110.c
index 3d0ac00..924642d 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -7,9 +7,9 @@
  * This code is licensed under the GNU LGPL
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "ui/console.h"
-#include "framebuffer.h"
+#include "hw/framebuffer.h"
 #include "ui/pixel_ops.h"
 
 #define PL110_CR_EN   0x001
@@ -111,15 +111,15 @@ static const unsigned char *idregs[] = {
 };
 
 #define BITS 8
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #define BITS 15
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #define BITS 16
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #define BITS 24
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #define BITS 32
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 
 static int pl110_enabled(pl110_state *s)
 {
diff --git a/hw/pl110_template.h b/hw/pl110_template.h
index e738e4a..ec4bfd6 100644
--- a/hw/pl110_template.h
+++ b/hw/pl110_template.h
@@ -27,20 +27,20 @@
 #undef RGB
 #define BORDER bgr
 #define ORDER 0
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #define ORDER 1
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #define ORDER 2
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #undef BORDER
 #define RGB
 #define BORDER rgb
 #define ORDER 0
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #define ORDER 1
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #define ORDER 2
-#include "pl110_template.h"
+#include "hw/pl110_template.h"
 #undef BORDER
 
 static drawfn glue(pl110_draw_fn_,BITS)[48] =
diff --git a/hw/pl181.c b/hw/pl181.c
index 98529f7..2527296 100644
--- a/hw/pl181.c
+++ b/hw/pl181.c
@@ -8,8 +8,8 @@
  */
 
 #include "sysemu/blockdev.h"
-#include "sysbus.h"
-#include "sd.h"
+#include "hw/sysbus.h"
+#include "hw/sd.h"
 
 //#define DEBUG_PL181 1
 
diff --git a/hw/pl190.c b/hw/pl190.c
index 76ac159..9610673 100644
--- a/hw/pl190.c
+++ b/hw/pl190.c
@@ -7,7 +7,7 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 /* The number of virtual priority levels.  16 user vectors plus the
    unvectored IRQ.  Chained interrupts would require an additional level
diff --git a/hw/pm_smbus.c b/hw/pm_smbus.c
index ea1380c..7900610 100644
--- a/hw/pm_smbus.c
+++ b/hw/pm_smbus.c
@@ -17,10 +17,10 @@
  * License along with this library; if not, see
  * <http://www.gnu.org/licenses/>.
  */
-#include "hw.h"
-#include "pc.h"
-#include "pm_smbus.h"
-#include "smbus.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/pm_smbus.h"
+#include "hw/smbus.h"
 
 /* no save/load? */
 
diff --git a/hw/ppc.c b/hw/ppc.c
index 8cfb84f..c9437fc 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -21,13 +21,13 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "ppc.h"
+#include "hw/hw.h"
+#include "hw/ppc.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
-#include "nvram.h"
+#include "hw/nvram.h"
 #include "qemu/log.h"
-#include "loader.h"
+#include "hw/loader.h"
 #include "sysemu/kvm.h"
 #include "kvm_ppc.h"
 
diff --git a/hw/ppc405.h b/hw/ppc405.h
index 535cbfb..45c2159 100644
--- a/hw/ppc405.h
+++ b/hw/ppc405.h
@@ -25,7 +25,7 @@
 #if !defined(PPC_405_H)
 #define PPC_405_H
 
-#include "ppc4xx.h"
+#include "hw/ppc4xx.h"
 
 /* Bootinfo as set-up by u-boot */
 typedef struct ppc4xx_bd_info_t ppc4xx_bd_info_t;
diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c
index cf371db..ba443cf 100644
--- a/hw/ppc405_boards.c
+++ b/hw/ppc405_boards.c
@@ -21,16 +21,16 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "ppc.h"
-#include "ppc405.h"
-#include "nvram.h"
-#include "flash.h"
+#include "hw/hw.h"
+#include "hw/ppc.h"
+#include "hw/ppc405.h"
+#include "hw/nvram.h"
+#include "hw/flash.h"
 #include "sysemu/sysemu.h"
 #include "block/block.h"
-#include "boards.h"
+#include "hw/boards.h"
 #include "qemu/log.h"
-#include "loader.h"
+#include "hw/loader.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index d8cbe87..8465f6d 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -21,10 +21,10 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "ppc.h"
-#include "ppc405.h"
-#include "serial.h"
+#include "hw/hw.h"
+#include "hw/ppc.h"
+#include "hw/ppc405.h"
+#include "hw/serial.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
 #include "qemu/log.h"
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index 73b5ac7..66911b5 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -14,20 +14,20 @@
 #include "config.h"
 #include "qemu-common.h"
 #include "net/net.h"
-#include "hw.h"
-#include "pci/pci.h"
-#include "boards.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/boards.h"
 #include "sysemu/kvm.h"
 #include "kvm_ppc.h"
 #include "sysemu/device_tree.h"
-#include "loader.h"
+#include "hw/loader.h"
 #include "elf.h"
 #include "exec/address-spaces.h"
-#include "serial.h"
-#include "ppc.h"
-#include "ppc405.h"
+#include "hw/serial.h"
+#include "hw/ppc.h"
+#include "hw/ppc405.h"
 #include "sysemu/sysemu.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 #define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
 
diff --git a/hw/ppc4xx.h b/hw/ppc4xx.h
index 59dba9e..91d84ba 100644
--- a/hw/ppc4xx.h
+++ b/hw/ppc4xx.h
@@ -25,7 +25,7 @@
 #if !defined(PPC_4XX_H)
 #define PPC_4XX_H
 
-#include "pci/pci.h"
+#include "hw/pci/pci.h"
 
 /* PowerPC 4xx core initialization */
 PowerPCCPU *ppc4xx_init(const char *cpu_model,
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index b6bb0e1..49ec728 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -21,9 +21,9 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "ppc.h"
-#include "ppc4xx.h"
+#include "hw/hw.h"
+#include "hw/ppc.h"
+#include "hw/ppc4xx.h"
 #include "qemu/log.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index ba2d669..f3bbe88 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -19,11 +19,11 @@
 /* This file implements emulation of the 32-bit PCI controller found in some
  * 4xx SoCs, such as the 440EP. */
 
-#include "hw.h"
-#include "ppc.h"
-#include "ppc4xx.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
+#include "hw/hw.h"
+#include "hw/ppc.h"
+#include "hw/ppc4xx.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
 #include "exec/address-spaces.h"
 
 #undef DEBUG
diff --git a/hw/ppc_booke.c b/hw/ppc_booke.c
index 25a4e91..30375c0 100644
--- a/hw/ppc_booke.c
+++ b/hw/ppc_booke.c
@@ -21,13 +21,13 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "ppc.h"
+#include "hw/hw.h"
+#include "hw/ppc.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
-#include "nvram.h"
+#include "hw/nvram.h"
 #include "qemu/log.h"
-#include "loader.h"
+#include "hw/loader.h"
 
 
 /* Timer Control Register */
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 1e1ade3..310ae1c 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -14,12 +14,12 @@
  * (at your option) any later version.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "hw/ppc/e500-ccsr.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
 #include "qemu/bswap.h"
-#include "ppce500_pci.h"
+#include "hw/ppce500_pci.h"
 
 #ifdef DEBUG_PCI
 #define pci_debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c
index 5bdce52..d904fbe 100644
--- a/hw/ppce500_spin.c
+++ b/hw/ppce500_spin.c
@@ -27,9 +27,9 @@
  *
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "sysemu/sysemu.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "sysemu/kvm.h"
 
 #define MAX_CPUS 32
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index 52ee5d9..d21e876 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -23,11 +23,11 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "pci/pci.h"
-#include "pci/pci_bus.h"
-#include "pci/pci_host.h"
-#include "pc.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pc.h"
 #include "exec/address-spaces.h"
 
 #define TYPE_RAVEN_PCI_DEVICE "raven"
diff --git a/hw/ps2.c b/hw/ps2.c
index 15cfd5b..233a087 100644
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -21,8 +21,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "ps2.h"
+#include "hw/hw.h"
+#include "hw/ps2.h"
 #include "ui/console.h"
 #include "sysemu/sysemu.h"
 
diff --git a/hw/ptimer.c b/hw/ptimer.c
index 24af6a2..4bc96c9 100644
--- a/hw/ptimer.c
+++ b/hw/ptimer.c
@@ -5,9 +5,9 @@
  *
  * This code is licensed under the GNU LGPL.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 #include "qemu/host-utils.h"
 
 struct ptimer_state
diff --git a/hw/puv3.c b/hw/puv3.c
index c722510..f9d0c2b 100644
--- a/hw/puv3.c
+++ b/hw/puv3.c
@@ -13,13 +13,13 @@
 #include "ui/console.h"
 #include "elf.h"
 #include "exec/address-spaces.h"
-#include "sysbus.h"
-#include "boards.h"
-#include "loader.h"
-#include "pc.h"
+#include "hw/sysbus.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/pc.h"
 
 #undef DEBUG_PUV3
-#include "puv3.h"
+#include "hw/puv3.h"
 
 #define KERNEL_LOAD_ADDR        0x03000000
 #define KERNEL_MAX_SIZE         0x00800000 /* Just a guess */
diff --git a/hw/puv3_dma.c b/hw/puv3_dma.c
index 9de63b4..c05a14e 100644
--- a/hw/puv3_dma.c
+++ b/hw/puv3_dma.c
@@ -8,11 +8,11 @@
  * published by the Free Software Foundation, or any later version.
  * See the COPYING file in the top-level directory.
  */
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 
 #undef DEBUG_PUV3
-#include "puv3.h"
+#include "hw/puv3.h"
 
 #define PUV3_DMA_CH_NR          (6)
 #define PUV3_DMA_CH_MASK        (0xff)
diff --git a/hw/puv3_gpio.c b/hw/puv3_gpio.c
index 152248d..b2a790b 100644
--- a/hw/puv3_gpio.c
+++ b/hw/puv3_gpio.c
@@ -8,11 +8,11 @@
  * published by the Free Software Foundation, or any later version.
  * See the COPYING file in the top-level directory.
  */
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 
 #undef DEBUG_PUV3
-#include "puv3.h"
+#include "hw/puv3.h"
 
 typedef struct {
     SysBusDevice busdev;
diff --git a/hw/puv3_intc.c b/hw/puv3_intc.c
index 07f5649..6bc9e1a 100644
--- a/hw/puv3_intc.c
+++ b/hw/puv3_intc.c
@@ -8,10 +8,10 @@
  * published by the Free Software Foundation, or any later version.
  * See the COPYING file in the top-level directory.
  */
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 #undef DEBUG_PUV3
-#include "puv3.h"
+#include "hw/puv3.h"
 
 typedef struct {
     SysBusDevice busdev;
diff --git a/hw/puv3_ost.c b/hw/puv3_ost.c
index 14c6f21..10a522a 100644
--- a/hw/puv3_ost.c
+++ b/hw/puv3_ost.c
@@ -8,11 +8,11 @@
  * published by the Free Software Foundation, or any later version.
  * See the COPYING file in the top-level directory.
  */
-#include "sysbus.h"
-#include "ptimer.h"
+#include "hw/sysbus.h"
+#include "hw/ptimer.h"
 
 #undef DEBUG_PUV3
-#include "puv3.h"
+#include "hw/puv3.h"
 
 /* puv3 ostimer implementation. */
 typedef struct {
diff --git a/hw/puv3_pm.c b/hw/puv3_pm.c
index 87a687a..6b8d94d 100644
--- a/hw/puv3_pm.c
+++ b/hw/puv3_pm.c
@@ -8,11 +8,11 @@
  * published by the Free Software Foundation, or any later version.
  * See the COPYING file in the top-level directory.
  */
-#include "hw.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
 
 #undef DEBUG_PUV3
-#include "puv3.h"
+#include "hw/puv3.h"
 
 typedef struct {
     SysBusDevice busdev;
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index d303320..c0f50c9 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -7,12 +7,12 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
-#include "pxa.h"
+#include "hw/sysbus.h"
+#include "hw/pxa.h"
 #include "sysemu/sysemu.h"
-#include "serial.h"
-#include "i2c.h"
-#include "ssi.h"
+#include "hw/serial.h"
+#include "hw/i2c.h"
+#include "hw/ssi.h"
 #include "char/char.h"
 #include "sysemu/blockdev.h"
 
diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c
index c0dba45..1db21c9 100644
--- a/hw/pxa2xx_dma.c
+++ b/hw/pxa2xx_dma.c
@@ -8,9 +8,9 @@
  * This code is licensed under the GPL.
  */
 
-#include "hw.h"
-#include "pxa.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/sysbus.h"
 
 #define PXA255_DMA_NUM_CHANNELS 16
 #define PXA27X_DMA_NUM_CHANNELS 32
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index 05d2ad2..eef8411 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -7,9 +7,9 @@
  * This code is licensed under the GPL.
  */
 
-#include "hw.h"
-#include "sysbus.h"
-#include "pxa.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
+#include "hw/pxa.h"
 
 #define PXA2XX_GPIO_BANKS	4
 
diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c
index 4ff04ad..32ea7a5 100644
--- a/hw/pxa2xx_keypad.c
+++ b/hw/pxa2xx_keypad.c
@@ -11,8 +11,8 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
-#include "pxa.h"
+#include "hw/hw.h"
+#include "hw/pxa.h"
 #include "ui/console.h"
 
 /*
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 512a27e..6484d27 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -10,13 +10,13 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
-#include "pxa.h"
+#include "hw/pxa.h"
 #include "ui/pixel_ops.h"
 /* FIXME: For graphic_rotate. Should probably be done in common code.  */
 #include "sysemu/sysemu.h"
-#include "framebuffer.h"
+#include "hw/framebuffer.h"
 
 struct DMAChannel {
     uint32_t branch;
@@ -976,15 +976,15 @@ static const VMStateDescription vmstate_pxa2xx_lcdc = {
 };
 
 #define BITS 8
-#include "pxa2xx_template.h"
+#include "hw/pxa2xx_template.h"
 #define BITS 15
-#include "pxa2xx_template.h"
+#include "hw/pxa2xx_template.h"
 #define BITS 16
-#include "pxa2xx_template.h"
+#include "hw/pxa2xx_template.h"
 #define BITS 24
-#include "pxa2xx_template.h"
+#include "hw/pxa2xx_template.h"
 #define BITS 32
-#include "pxa2xx_template.h"
+#include "hw/pxa2xx_template.h"
 
 PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem,
                                  hwaddr base, qemu_irq irq)
diff --git a/hw/pxa2xx_mmci.c b/hw/pxa2xx_mmci.c
index 3589968..0df83cc 100644
--- a/hw/pxa2xx_mmci.c
+++ b/hw/pxa2xx_mmci.c
@@ -10,10 +10,10 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
-#include "pxa.h"
-#include "sd.h"
-#include "qdev.h"
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/sd.h"
+#include "hw/qdev.h"
 
 struct PXA2xxMMCIState {
     MemoryRegion iomem;
diff --git a/hw/pxa2xx_pcmcia.c b/hw/pxa2xx_pcmcia.c
index 3a79c72..66fefba 100644
--- a/hw/pxa2xx_pcmcia.c
+++ b/hw/pxa2xx_pcmcia.c
@@ -10,9 +10,9 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
-#include "pcmcia.h"
-#include "pxa.h"
+#include "hw/hw.h"
+#include "hw/pcmcia.h"
+#include "hw/pxa.h"
 
 
 struct PXA2xxPCMCIAState {
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 90b8fef..145fc78 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -8,9 +8,9 @@
  * This code is licensed under the GPL.
  */
 
-#include "hw.h"
-#include "pxa.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/sysbus.h"
 
 #define ICIP	0x00	/* Interrupt Controller IRQ Pending register */
 #define ICMR	0x04	/* Interrupt Controller Mask register */
diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index 5c9d2e8..c173fe4 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -7,11 +7,11 @@
  * This code is licensed under the GPL.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
-#include "pxa.h"
-#include "sysbus.h"
+#include "hw/pxa.h"
+#include "hw/sysbus.h"
 
 #define OSMR0	0x00
 #define OSMR1	0x04
diff --git a/hw/q35.c b/hw/q35.c
index efebc27..0a25b8b 100644
--- a/hw/q35.c
+++ b/hw/q35.c
@@ -27,8 +27,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "q35.h"
+#include "hw/hw.h"
+#include "hw/q35.h"
 
 /****************************************************************************
  * Q35 host
diff --git a/hw/q35.h b/hw/q35.h
index 246c12c..d766bb7 100644
--- a/hw/q35.h
+++ b/hw/q35.h
@@ -22,18 +22,18 @@
 #ifndef HW_Q35_H
 #define HW_Q35_H
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/range.h"
-#include "isa.h"
-#include "sysbus.h"
-#include "pc.h"
-#include "apm.h"
-#include "apic.h"
-#include "pci/pci.h"
-#include "pci/pcie_host.h"
-#include "acpi.h"
-#include "acpi_ich9.h"
-#include "pam.h"
+#include "hw/isa.h"
+#include "hw/sysbus.h"
+#include "hw/pc.h"
+#include "hw/apm.h"
+#include "hw/apic.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pcie_host.h"
+#include "hw/acpi.h"
+#include "hw/acpi_ich9.h"
+#include "hw/pam.h"
 
 #define TYPE_Q35_HOST_DEVICE "q35-pcihost"
 #define Q35_HOST_DEVICE(obj) \
diff --git a/hw/qdev-addr.c b/hw/qdev-addr.c
index fc2c437..2398b4a 100644
--- a/hw/qdev-addr.c
+++ b/hw/qdev-addr.c
@@ -1,5 +1,5 @@
-#include "qdev.h"
-#include "qdev-addr.h"
+#include "hw/qdev.h"
+#include "hw/qdev-addr.h"
 #include "exec/hwaddr.h"
 #include "qapi/qmp/qerror.h"
 #include "qapi/visitor.h"
diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c
index ce3af22..8795144 100644
--- a/hw/qdev-properties-system.c
+++ b/hw/qdev-properties-system.c
@@ -11,7 +11,7 @@
  */
 
 #include "net/net.h"
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "qapi/qmp/qerror.h"
 #include "sysemu/blockdev.h"
 #include "hw/block-common.h"
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index a8a31f5..0307a78 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -1,5 +1,5 @@
 #include "net/net.h"
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "qapi/qmp/qerror.h"
 #include "sysemu/blockdev.h"
 #include "hw/block-common.h"
diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h
index 20c67f3..0b0465c 100644
--- a/hw/qdev-properties.h
+++ b/hw/qdev-properties.h
@@ -1,7 +1,7 @@
 #ifndef QEMU_QDEV_PROPERTIES_H
 #define QEMU_QDEV_PROPERTIES_H
 
-#include "qdev-core.h"
+#include "hw/qdev-core.h"
 
 /*** qdev-properties.c ***/
 
diff --git a/hw/qdev.c b/hw/qdev.c
index 62bc899..0b20280 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -25,7 +25,7 @@
    inherit from a particular bus (e.g. PCI or I2C) rather than
    this API directly.  */
 
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "sysemu/sysemu.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
diff --git a/hw/qdev.h b/hw/qdev.h
index f814656..5cb8b08 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -2,7 +2,7 @@
 #define QDEV_H
 
 #include "hw/hw.h"
-#include "qdev-core.h"
-#include "qdev-properties.h"
+#include "hw/qdev-core.h"
+#include "hw/qdev-properties.h"
 
 #endif
diff --git a/hw/qxl-logger.c b/hw/qxl-logger.c
index 3cd85d9..84f9aa1 100644
--- a/hw/qxl-logger.c
+++ b/hw/qxl-logger.c
@@ -20,7 +20,7 @@
  */
 
 #include "qemu/timer.h"
-#include "qxl.h"
+#include "hw/qxl.h"
 
 static const char *qxl_type[] = {
     [ QXL_CMD_NOP ]     = "nop",
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 455fb91..d77df42 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -19,7 +19,7 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "qxl.h"
+#include "hw/qxl.h"
 
 static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
 {
diff --git a/hw/qxl.c b/hw/qxl.c
index 2e1c5e2..ef69348 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -27,7 +27,7 @@
 #include "sysemu/sysemu.h"
 #include "trace.h"
 
-#include "qxl.h"
+#include "hw/qxl.h"
 
 /*
  * NOTE: SPICE_RING_PROD_ITEM accesses memory on the pci bar and as
diff --git a/hw/qxl.h b/hw/qxl.h
index f867a1d..36f1a25 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -4,9 +4,9 @@
 #include "qemu-common.h"
 
 #include "ui/console.h"
-#include "hw.h"
-#include "pci/pci.h"
-#include "vga_int.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/vga_int.h"
 #include "qemu/thread.h"
 
 #include "ui/qemu-spice.h"
diff --git a/hw/r2d.c b/hw/r2d.c
index 2d0dd1f..faa03d2 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -23,19 +23,19 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
-#include "hw.h"
-#include "sh.h"
-#include "devices.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/sh.h"
+#include "hw/devices.h"
 #include "sysemu/sysemu.h"
-#include "boards.h"
-#include "pci/pci.h"
+#include "hw/boards.h"
+#include "hw/pci/pci.h"
 #include "net/net.h"
-#include "sh7750_regs.h"
-#include "ide.h"
-#include "loader.h"
-#include "usb.h"
-#include "flash.h"
+#include "hw/sh7750_regs.h"
+#include "hw/ide.h"
+#include "hw/loader.h"
+#include "hw/usb.h"
+#include "hw/flash.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/rc4030.c b/hw/rc4030.c
index a0358a3..b065515 100644
--- a/hw/rc4030.c
+++ b/hw/rc4030.c
@@ -22,8 +22,8 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "mips.h"
+#include "hw/hw.h"
+#include "hw/mips.h"
 #include "qemu/timer.h"
 
 /********************************************************/
diff --git a/hw/realview.c b/hw/realview.c
index 78da767..5fb490c 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -7,15 +7,15 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
-#include "arm-misc.h"
-#include "primecell.h"
-#include "devices.h"
-#include "pci/pci.h"
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/primecell.h"
+#include "hw/devices.h"
+#include "hw/pci/pci.h"
 #include "net/net.h"
 #include "sysemu/sysemu.h"
-#include "boards.h"
-#include "i2c.h"
+#include "hw/boards.h"
+#include "hw/i2c.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 8f2a7e2..0ec30ca 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -7,7 +7,7 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 typedef struct {
     SysBusDevice busdev;
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index d7716be..786b875 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -51,12 +51,12 @@
 /* For crc32 */
 #include <zlib.h>
 
-#include "hw.h"
-#include "pci/pci.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
 #include "sysemu/dma.h"
 #include "qemu/timer.h"
 #include "net/net.h"
-#include "loader.h"
+#include "hw/loader.h"
 #include "sysemu/sysemu.h"
 #include "qemu/iov.h"
 
diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c
index 6b56995..0faade0 100644
--- a/hw/s390x/event-facility.c
+++ b/hw/s390x/event-facility.c
@@ -18,8 +18,8 @@
 #include "monitor/monitor.h"
 #include "sysemu/sysemu.h"
 
-#include "sclp.h"
-#include "event-facility.h"
+#include "hw/s390x/sclp.h"
+#include "hw/s390x/event-facility.h"
 
 typedef struct EventTypesBus {
     BusState qbus;
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 6549211..d436414 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -12,7 +12,7 @@
 #include "hw/boards.h"
 #include "exec/address-spaces.h"
 #include "s390-virtio.h"
-#include "sclp.h"
+#include "hw/s390x/sclp.h"
 #include "ioinst.h"
 #include "css.h"
 #include "virtio-ccw.h"
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index a9d3a6a..86d6ae0 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -16,7 +16,7 @@
 #include "sysemu/kvm.h"
 #include "exec/memory.h"
 
-#include "sclp.h"
+#include "hw/s390x/sclp.h"
 
 static inline S390SCLPDevice *get_event_facility(void)
 {
diff --git a/hw/s390x/sclpconsole.c b/hw/s390x/sclpconsole.c
index 475d7ba..5c881e5 100644
--- a/hw/s390x/sclpconsole.c
+++ b/hw/s390x/sclpconsole.c
@@ -16,8 +16,8 @@
 #include "qemu/thread.h"
 #include "qemu/error-report.h"
 
-#include "sclp.h"
-#include "event-facility.h"
+#include "hw/s390x/sclp.h"
+#include "hw/s390x/event-facility.h"
 #include "char/char.h"
 
 typedef struct ASCIIConsoleData {
diff --git a/hw/s390x/sclpquiesce.c b/hw/s390x/sclpquiesce.c
index 2538498..5fadc86 100644
--- a/hw/s390x/sclpquiesce.c
+++ b/hw/s390x/sclpquiesce.c
@@ -13,8 +13,8 @@
  */
 #include <hw/qdev.h>
 #include "sysemu/sysemu.h"
-#include "sclp.h"
-#include "event-facility.h"
+#include "hw/s390x/sclp.h"
+#include "hw/s390x/event-facility.h"
 
 typedef struct SignalQuiesce {
     EventBufferHeader ebh;
diff --git a/hw/sb16.c b/hw/sb16.c
index 52dfedf..bd51ceb 100644
--- a/hw/sb16.c
+++ b/hw/sb16.c
@@ -21,11 +21,11 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "audiodev.h"
+#include "hw/hw.h"
+#include "hw/audiodev.h"
 #include "audio/audio.h"
-#include "isa.h"
-#include "qdev.h"
+#include "hw/isa.h"
+#include "hw/qdev.h"
 #include "qemu/timer.h"
 #include "qemu/host-utils.h"
 
diff --git a/hw/sbi.c b/hw/sbi.c
index d58184a..8795749 100644
--- a/hw/sbi.c
+++ b/hw/sbi.c
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 //#define DEBUG_IRQ
 
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index a97f1cd..163d7a1 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -1,8 +1,8 @@
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/error-report.h"
-#include "scsi.h"
-#include "scsi-defs.h"
-#include "qdev.h"
+#include "hw/scsi.h"
+#include "hw/scsi-defs.h"
+#include "hw/qdev.h"
 #include "sysemu/blockdev.h"
 #include "trace.h"
 #include "sysemu/dma.h"
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index d411586..1e12818 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -30,8 +30,8 @@ do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
 
 #include "qemu-common.h"
 #include "qemu/error-report.h"
-#include "scsi.h"
-#include "scsi-defs.h"
+#include "hw/scsi.h"
+#include "hw/scsi-defs.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/blockdev.h"
 #include "hw/block-common.h"
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 8175474..4d04cac 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -13,7 +13,7 @@
 
 #include "qemu-common.h"
 #include "qemu/error-report.h"
-#include "scsi.h"
+#include "hw/scsi.h"
 #include "sysemu/blockdev.h"
 
 #ifdef __linux__
@@ -35,7 +35,7 @@ do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
 #include <sys/stat.h>
 #include <unistd.h>
 #include <scsi/sg.h>
-#include "scsi-defs.h"
+#include "hw/scsi-defs.h"
 
 #define SCSI_SENSE_BUF_SIZE 96
 
diff --git a/hw/scsi.h b/hw/scsi.h
index a5b5b2e..33e2e0b 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -1,7 +1,7 @@
 #ifndef QEMU_HW_SCSI_H
 #define QEMU_HW_SCSI_H
 
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "block/block.h"
 #include "hw/block-common.h"
 #include "sysemu/sysemu.h"
diff --git a/hw/sd.c b/hw/sd.c
index 428bd78..a895123 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -29,9 +29,9 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "block/block.h"
-#include "sd.h"
+#include "hw/sd.h"
 #include "qemu/bitmap.h"
 
 //#define DEBUG_SD 1
diff --git a/hw/sdhci.c b/hw/sdhci.c
index e535df9..93feada 100644
--- a/hw/sdhci.c
+++ b/hw/sdhci.c
@@ -22,14 +22,14 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/dma.h"
 #include "qemu/timer.h"
 #include "block/block_int.h"
 #include "qemu/bitops.h"
 
-#include "sdhci.h"
+#include "hw/sdhci.h"
 
 /* host controller debug messages */
 #ifndef SDHC_DEBUG
diff --git a/hw/sdhci.h b/hw/sdhci.h
index 931d740..a560c3c 100644
--- a/hw/sdhci.h
+++ b/hw/sdhci.h
@@ -26,8 +26,8 @@
 #define SDHCI_H
 
 #include "qemu-common.h"
-#include "sysbus.h"
-#include "sd.h"
+#include "hw/sysbus.h"
+#include "hw/sd.h"
 
 /* R/W SDMA System Address register 0x0 */
 #define SDHC_SYSAD                     0x00
diff --git a/hw/serial-isa.c b/hw/serial-isa.c
index 5a6f51f..a630a7d 100644
--- a/hw/serial-isa.c
+++ b/hw/serial-isa.c
@@ -23,8 +23,8 @@
  * THE SOFTWARE.
  */
 
-#include "serial.h"
-#include "isa.h"
+#include "hw/serial.h"
+#include "hw/isa.h"
 
 typedef struct ISASerialState {
     ISADevice dev;
diff --git a/hw/serial-pci.c b/hw/serial-pci.c
index 1c31353..954657b 100644
--- a/hw/serial-pci.c
+++ b/hw/serial-pci.c
@@ -25,8 +25,8 @@
 
 /* see docs/specs/pci-serial.txt */
 
-#include "serial.h"
-#include "pci/pci.h"
+#include "hw/serial.h"
+#include "hw/pci/pci.h"
 
 #define PCI_SERIAL_MAX_PORTS 4
 
diff --git a/hw/serial.c b/hw/serial.c
index f0ce9b0..6a83543 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -23,7 +23,7 @@
  * THE SOFTWARE.
  */
 
-#include "serial.h"
+#include "hw/serial.h"
 #include "char/char.h"
 #include "qemu/timer.h"
 #include "exec/address-spaces.h"
diff --git a/hw/serial.h b/hw/serial.h
index 98ee424..814b8c6 100644
--- a/hw/serial.h
+++ b/hw/serial.h
@@ -25,7 +25,7 @@
 #ifndef HW_SERIAL_H
 #define HW_SERIAL_H 1
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "sysemu/sysemu.h"
 #include "exec/memory.h"
 
diff --git a/hw/sga.c b/hw/sga.c
index 29bc3e0..4b1d4e5 100644
--- a/hw/sga.c
+++ b/hw/sga.c
@@ -24,9 +24,9 @@
  * sgabios code originally available at code.google.com/p/sgabios
  *
  */
-#include "pci/pci.h"
-#include "pc.h"
-#include "loader.h"
+#include "hw/pci/pci.h"
+#include "hw/pc.h"
+#include "hw/loader.h"
 #include "sysemu/sysemu.h"
 
 #define SGABIOS_FILENAME "sgabios.bin"
diff --git a/hw/sh.h b/hw/sh.h
index 77bf8aa..6230954 100644
--- a/hw/sh.h
+++ b/hw/sh.h
@@ -2,7 +2,7 @@
 #define QEMU_SH_H
 /* Definitions for SH board emulation.  */
 
-#include "sh_intc.h"
+#include "hw/sh_intc.h"
 
 #define A7ADDR(x) ((x) & 0x1fffffff)
 #define P4ADDR(x) ((x) | 0xe0000000)
diff --git a/hw/sh7750.c b/hw/sh7750.c
index 666f865..6778c94 100644
--- a/hw/sh7750.c
+++ b/hw/sh7750.c
@@ -23,12 +23,12 @@
  * THE SOFTWARE.
  */
 #include <stdio.h>
-#include "hw.h"
-#include "sh.h"
+#include "hw/hw.h"
+#include "hw/sh.h"
 #include "sysemu/sysemu.h"
-#include "sh7750_regs.h"
-#include "sh7750_regnames.h"
-#include "sh_intc.h"
+#include "hw/sh7750_regs.h"
+#include "hw/sh7750_regnames.h"
+#include "hw/sh_intc.h"
 #include "cpu.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/sh7750_regnames.c b/hw/sh7750_regnames.c
index 5a5a2d8..389698d 100644
--- a/hw/sh7750_regnames.c
+++ b/hw/sh7750_regnames.c
@@ -1,7 +1,7 @@
-#include "hw.h"
-#include "sh.h"
-#include "sh7750_regs.h"
-#include "sh7750_regnames.h"
+#include "hw/hw.h"
+#include "hw/sh.h"
+#include "hw/sh7750_regs.h"
+#include "hw/sh7750_regnames.h"
 
 #define REGNAME(r) {r, #r},
 
diff --git a/hw/sh_intc.c b/hw/sh_intc.c
index c3f77d5..9e64e4d 100644
--- a/hw/sh_intc.c
+++ b/hw/sh_intc.c
@@ -8,9 +8,9 @@
  * This code is licensed under the GPL.
  */
 
-#include "sh_intc.h"
-#include "hw.h"
-#include "sh.h"
+#include "hw/sh_intc.h"
+#include "hw/hw.h"
+#include "hw/sh.h"
 
 //#define DEBUG_INTC
 //#define DEBUG_INTC_SOURCES
diff --git a/hw/sh_intc.h b/hw/sh_intc.h
index 6f11bee..b7ddcb0 100644
--- a/hw/sh_intc.h
+++ b/hw/sh_intc.h
@@ -2,7 +2,7 @@
 #define __SH_INTC_H__
 
 #include "qemu-common.h"
-#include "irq.h"
+#include "hw/irq.h"
 #include "exec/address-spaces.h"
 
 typedef unsigned char intc_enum;
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index 077d957..96535db 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -21,10 +21,10 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "sysbus.h"
-#include "sh.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
+#include "hw/sysbus.h"
+#include "hw/sh.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
 #include "qemu/bswap.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/sh_serial.c b/hw/sh_serial.c
index 21c5b13..40e797c 100644
--- a/hw/sh_serial.c
+++ b/hw/sh_serial.c
@@ -24,8 +24,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "sh.h"
+#include "hw/hw.h"
+#include "hw/sh.h"
 #include "char/char.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/sh_timer.c b/hw/sh_timer.c
index 64ea23f..b450323 100644
--- a/hw/sh_timer.c
+++ b/hw/sh_timer.c
@@ -8,11 +8,11 @@
  * This code is licensed under the GPL.
  */
 
-#include "hw.h"
-#include "sh.h"
+#include "hw/hw.h"
+#include "hw/sh.h"
 #include "qemu/timer.h"
 #include "exec/address-spaces.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 
 //#define DEBUG_TIMER
 
diff --git a/hw/shix.c b/hw/shix.c
index 6f2d55a..192579d 100644
--- a/hw/shix.c
+++ b/hw/shix.c
@@ -27,11 +27,11 @@
 
    More information in target-sh4/README.sh4
 */
-#include "hw.h"
-#include "sh.h"
+#include "hw/hw.h"
+#include "hw/sh.h"
 #include "sysemu/sysemu.h"
-#include "boards.h"
-#include "loader.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
 #include "exec/address-spaces.h"
 
 #define BIOS_FILENAME "shix_bios.bin"
diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index 136ceeb..b60592b 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -22,9 +22,9 @@
  * THE SOFTWARE.
  */
 
-#include "sun4m.h"
+#include "hw/sun4m.h"
 #include "monitor/monitor.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 
 //#define DEBUG_IRQ_COUNT
diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index af24cc1..a7a9368 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -23,7 +23,7 @@
  */
 
 #include "sysemu/sysemu.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 
 /*
diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c
index 68a4c0c..83f22a0 100644
--- a/hw/slavio_timer.c
+++ b/hw/slavio_timer.c
@@ -22,10 +22,10 @@
  * THE SOFTWARE.
  */
 
-#include "sun4m.h"
+#include "hw/sun4m.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
-#include "sysbus.h"
+#include "hw/ptimer.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 
 /*
diff --git a/hw/sm501.c b/hw/sm501.c
index b7ac7f9..0e01911 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -23,12 +23,12 @@
  */
 
 #include <stdio.h>
-#include "hw.h"
-#include "serial.h"
+#include "hw/hw.h"
+#include "hw/serial.h"
 #include "ui/console.h"
-#include "devices.h"
-#include "sysbus.h"
-#include "qdev-addr.h"
+#include "hw/devices.h"
+#include "hw/sysbus.h"
+#include "hw/qdev-addr.h"
 #include "qemu/range.h"
 #include "ui/pixel_ops.h"
 
@@ -1171,28 +1171,28 @@ typedef void draw_hwc_line_func(SM501State * s, int crt, uint8_t * palette,
                                 int c_y, uint8_t *d, int width);
 
 #define DEPTH 8
-#include "sm501_template.h"
+#include "hw/sm501_template.h"
 
 #define DEPTH 15
-#include "sm501_template.h"
+#include "hw/sm501_template.h"
 
 #define BGR_FORMAT
 #define DEPTH 15
-#include "sm501_template.h"
+#include "hw/sm501_template.h"
 
 #define DEPTH 16
-#include "sm501_template.h"
+#include "hw/sm501_template.h"
 
 #define BGR_FORMAT
 #define DEPTH 16
-#include "sm501_template.h"
+#include "hw/sm501_template.h"
 
 #define DEPTH 32
-#include "sm501_template.h"
+#include "hw/sm501_template.h"
 
 #define BGR_FORMAT
 #define DEPTH 32
-#include "sm501_template.h"
+#include "hw/sm501_template.h"
 
 static draw_line_func * draw_line8_funcs[] = {
     draw_line8_8,
diff --git a/hw/smbios.c b/hw/smbios.c
index a7b8bfc..672ee9b 100644
--- a/hw/smbios.c
+++ b/hw/smbios.c
@@ -14,8 +14,8 @@
  */
 
 #include "sysemu/sysemu.h"
-#include "smbios.h"
-#include "loader.h"
+#include "hw/smbios.h"
+#include "hw/loader.h"
 
 /*
  * Structures shared with the BIOS
diff --git a/hw/smbus.c b/hw/smbus.c
index a908591..9626415 100644
--- a/hw/smbus.c
+++ b/hw/smbus.c
@@ -9,9 +9,9 @@
 
 /* TODO: Implement PEC.  */
 
-#include "hw.h"
-#include "i2c.h"
-#include "smbus.h"
+#include "hw/hw.h"
+#include "hw/i2c.h"
+#include "hw/smbus.h"
 
 //#define DEBUG_SMBUS 1
 
diff --git a/hw/smbus.h b/hw/smbus.h
index 6ed45bd..c3db620 100644
--- a/hw/smbus.h
+++ b/hw/smbus.h
@@ -25,7 +25,7 @@
  * THE SOFTWARE.
  */
 
-#include "i2c.h"
+#include "hw/i2c.h"
 
 #define TYPE_SMBUS_DEVICE "smbus-device"
 #define SMBUS_DEVICE(obj) \
diff --git a/hw/smbus_eeprom.c b/hw/smbus_eeprom.c
index d36dc7b..dff8403d 100644
--- a/hw/smbus_eeprom.c
+++ b/hw/smbus_eeprom.c
@@ -22,9 +22,9 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "i2c.h"
-#include "smbus.h"
+#include "hw/hw.h"
+#include "hw/i2c.h"
+#include "hw/smbus.h"
 
 //#define DEBUG
 
diff --git a/hw/smbus_ich9.c b/hw/smbus_ich9.c
index 16db3a7..732ebd3 100644
--- a/hw/smbus_ich9.c
+++ b/hw/smbus_ich9.c
@@ -24,15 +24,15 @@
  * GNU GPL, version 2 or (at your option) any later version.
  *
  */
-#include "hw.h"
-#include "pc.h"
-#include "pm_smbus.h"
-#include "pci/pci.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/pm_smbus.h"
+#include "hw/pci/pci.h"
 #include "sysemu/sysemu.h"
-#include "i2c.h"
-#include "smbus.h"
+#include "hw/i2c.h"
+#include "hw/smbus.h"
 
-#include "ich9.h"
+#include "hw/ich9.h"
 
 #define TYPE_ICH9_SMB_DEVICE "ICH9 SMB"
 #define ICH9_SMB_DEVICE(obj) \
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index 67fd074..c2feae6 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -7,9 +7,9 @@
  * This code is licensed under the GPL
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "net/net.h"
-#include "devices.h"
+#include "hw/devices.h"
 /* For crc32 */
 #include <zlib.h>
 
diff --git a/hw/soc_dma.c b/hw/soc_dma.c
index 64e8ee1..db5d609 100644
--- a/hw/soc_dma.c
+++ b/hw/soc_dma.c
@@ -19,7 +19,7 @@
  */
 #include "qemu-common.h"
 #include "qemu/timer.h"
-#include "soc_dma.h"
+#include "hw/soc_dma.h"
 
 static void transfer_mem2mem(struct soc_dma_ch_s *ch)
 {
diff --git a/hw/spapr.c b/hw/spapr.c
index e88a27a..2709c66 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -25,7 +25,7 @@
  *
  */
 #include "sysemu/sysemu.h"
-#include "hw.h"
+#include "hw/hw.h"
 #include "elf.h"
 #include "net/net.h"
 #include "sysemu/blockdev.h"
@@ -45,7 +45,7 @@
 
 #include "sysemu/kvm.h"
 #include "kvm_ppc.h"
-#include "pci/pci.h"
+#include "hw/pci/pci.h"
 
 #include "exec/address-spaces.h"
 #include "hw/usb.h"
diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c
index d8a098c..8d500bf 100644
--- a/hw/spapr_iommu.c
+++ b/hw/spapr_iommu.c
@@ -16,9 +16,9 @@
  * 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 "hw/hw.h"
 #include "sysemu/kvm.h"
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "kvm_ppc.h"
 #include "sysemu/dma.h"
 #include "exec/address-spaces.h"
diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c
index 6ef2936..5d2565b 100644
--- a/hw/spapr_llan.c
+++ b/hw/spapr_llan.c
@@ -24,7 +24,7 @@
  * THE SOFTWARE.
  *
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "net/net.h"
 #include "hw/qdev.h"
 #include "hw/spapr.h"
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 4eacbcf..36adbc5 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -22,11 +22,11 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "pci/pci.h"
-#include "pci/msi.h"
-#include "pci/msix.h"
-#include "pci/pci_host.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/msix.h"
+#include "hw/pci/pci_host.h"
 #include "hw/spapr.h"
 #include "hw/spapr_pci.h"
 #include "exec/address-spaces.h"
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 34c9ca6..6eb3ab5 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -19,11 +19,11 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "sysemu/sysemu.h"
-#include "boards.h"
+#include "hw/boards.h"
 #include "monitor/monitor.h"
-#include "loader.h"
+#include "hw/loader.h"
 #include "elf.h"
 #include "hw/sysbus.h"
 #include "sysemu/kvm.h"
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index 7fc0e13..2794094 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -31,10 +31,10 @@
  *  - 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 "srp.h"
+#include "hw/hw.h"
+#include "hw/scsi.h"
+#include "hw/scsi-defs.h"
+#include "hw/srp.h"
 #include "hw/qdev.h"
 #include "hw/spapr.h"
 #include "hw/spapr_vio.h"
diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
index 5c63eaa..be08571 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -1,4 +1,4 @@
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "char/char.h"
 #include "hw/spapr.h"
 #include "hw/spapr_vio.h"
diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c
index 6d0df51..18e368e 100644
--- a/hw/sparc32_dma.c
+++ b/hw/sparc32_dma.c
@@ -25,10 +25,10 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "sparc32_dma.h"
-#include "sun4m.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sparc32_dma.h"
+#include "hw/sun4m.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 
 /*
diff --git a/hw/spitz.c b/hw/spitz.c
index 5bc49fc..f5832be 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -10,23 +10,23 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
-#include "pxa.h"
-#include "arm-misc.h"
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/arm-misc.h"
 #include "sysemu/sysemu.h"
-#include "pcmcia.h"
-#include "i2c.h"
-#include "ssi.h"
-#include "flash.h"
+#include "hw/pcmcia.h"
+#include "hw/i2c.h"
+#include "hw/ssi.h"
+#include "hw/flash.h"
 #include "qemu/timer.h"
-#include "devices.h"
-#include "sharpsl.h"
+#include "hw/devices.h"
+#include "hw/sharpsl.h"
 #include "ui/console.h"
 #include "block/block.h"
 #include "audio/audio.h"
-#include "boards.h"
+#include "hw/boards.h"
 #include "sysemu/blockdev.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "exec/address-spaces.h"
 
 #undef REG_FMT
diff --git a/hw/ssd0303.c b/hw/ssd0303.c
index 8777b16..db50909 100644
--- a/hw/ssd0303.c
+++ b/hw/ssd0303.c
@@ -10,7 +10,7 @@
 /* The controller can support a variety of different displays, but we only
    implement one.  Most of the commends relating to brightness and geometry
    setup are ignored. */
-#include "i2c.h"
+#include "hw/i2c.h"
 #include "ui/console.h"
 
 //#define DEBUG_SSD0303 1
diff --git a/hw/ssd0323.c b/hw/ssd0323.c
index 84c86a5..27b4151 100644
--- a/hw/ssd0323.c
+++ b/hw/ssd0323.c
@@ -10,7 +10,7 @@
 /* The controller can support a variety of different displays, but we only
    implement one.  Most of the commends relating to brightness and geometry
    setup are ignored. */
-#include "ssi.h"
+#include "hw/ssi.h"
 #include "ui/console.h"
 
 //#define DEBUG_SSD0323 1
diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c
index dca8906..4d3c4f6 100644
--- a/hw/ssi-sd.c
+++ b/hw/ssi-sd.c
@@ -11,8 +11,8 @@
  */
 
 #include "sysemu/blockdev.h"
-#include "ssi.h"
-#include "sd.h"
+#include "hw/ssi.h"
+#include "hw/sd.h"
 
 //#define DEBUG_SSI_SD 1
 
diff --git a/hw/ssi.c b/hw/ssi.c
index 0b18176..1264d9d 100644
--- a/hw/ssi.c
+++ b/hw/ssi.c
@@ -12,7 +12,7 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "ssi.h"
+#include "hw/ssi.h"
 
 struct SSIBus {
     BusState qbus;
diff --git a/hw/ssi.h b/hw/ssi.h
index a05d60b..fdae317 100644
--- a/hw/ssi.h
+++ b/hw/ssi.h
@@ -11,7 +11,7 @@
 #ifndef QEMU_SSI_H
 #define QEMU_SSI_H
 
-#include "qdev.h"
+#include "hw/qdev.h"
 
 typedef struct SSISlave SSISlave;
 
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 9b8f203..f4ce794 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -7,14 +7,14 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
-#include "ssi.h"
-#include "arm-misc.h"
-#include "devices.h"
+#include "hw/sysbus.h"
+#include "hw/ssi.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
 #include "qemu/timer.h"
-#include "i2c.h"
+#include "hw/i2c.h"
 #include "net/net.h"
-#include "boards.h"
+#include "hw/boards.h"
 #include "exec/address-spaces.h"
 
 #define GPIO_A 0
diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c
index 6c701fb..59b8456 100644
--- a/hw/stellaris_enet.c
+++ b/hw/stellaris_enet.c
@@ -6,7 +6,7 @@
  *
  * This code is licensed under the GPL.
  */
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "net/net.h"
 #include <zlib.h>
 
diff --git a/hw/stellaris_input.c b/hw/stellaris_input.c
index 7a95c3f..4e40792 100644
--- a/hw/stellaris_input.c
+++ b/hw/stellaris_input.c
@@ -6,8 +6,8 @@
  *
  * This code is licensed under the GPL.
  */
-#include "hw.h"
-#include "devices.h"
+#include "hw/hw.h"
+#include "hw/devices.h"
 #include "ui/console.h"
 
 typedef struct {
diff --git a/hw/stream.c b/hw/stream.c
index d4cf84d..a07d6a5 100644
--- a/hw/stream.c
+++ b/hw/stream.c
@@ -1,4 +1,4 @@
-#include "stream.h"
+#include "hw/stream.h"
 
 void
 stream_push(StreamSlave *sink, uint8_t *buf, size_t len, uint32_t *app)
diff --git a/hw/strongarm.c b/hw/strongarm.c
index ab736e3..49f9577 100644
--- a/hw/strongarm.c
+++ b/hw/strongarm.c
@@ -26,13 +26,13 @@
  *  Contributions after 2012-01-13 are licensed under the terms of the
  *  GNU GPL, version 2 or (at your option) any later version.
  */
-#include "sysbus.h"
-#include "strongarm.h"
+#include "hw/sysbus.h"
+#include "hw/strongarm.h"
 #include "qemu/error-report.h"
-#include "arm-misc.h"
+#include "hw/arm-misc.h"
 #include "char/char.h"
 #include "sysemu/sysemu.h"
-#include "ssi.h"
+#include "hw/ssi.h"
 
 //#define DEBUG
 
diff --git a/hw/sun4c_intctl.c b/hw/sun4c_intctl.c
index f8f4d02..9d443d1 100644
--- a/hw/sun4c_intctl.c
+++ b/hw/sun4c_intctl.c
@@ -22,10 +22,10 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "sun4m.h"
+#include "hw/hw.h"
+#include "hw/sun4m.h"
 #include "monitor/monitor.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 
 //#define DEBUG_IRQ_COUNT
 //#define DEBUG_IRQ
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 9903f44..37bd041 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -21,24 +21,24 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
-#include "sun4m.h"
-#include "nvram.h"
-#include "sparc32_dma.h"
-#include "fdc.h"
+#include "hw/sun4m.h"
+#include "hw/nvram.h"
+#include "hw/sparc32_dma.h"
+#include "hw/fdc.h"
 #include "sysemu/sysemu.h"
 #include "net/net.h"
-#include "boards.h"
-#include "firmware_abi.h"
-#include "esp.h"
-#include "pc.h"
-#include "isa.h"
-#include "fw_cfg.h"
-#include "escc.h"
-#include "empty_slot.h"
-#include "qdev-addr.h"
-#include "loader.h"
+#include "hw/boards.h"
+#include "hw/firmware_abi.h"
+#include "hw/esp.h"
+#include "hw/pc.h"
+#include "hw/isa.h"
+#include "hw/fw_cfg.h"
+#include "hw/escc.h"
+#include "hw/empty_slot.h"
+#include "hw/qdev-addr.h"
+#include "hw/loader.h"
 #include "elf.h"
 #include "sysemu/blockdev.h"
 #include "trace.h"
diff --git a/hw/sun4m.h b/hw/sun4m.h
index 0361eee..0d2cfb8 100644
--- a/hw/sun4m.h
+++ b/hw/sun4m.h
@@ -31,6 +31,6 @@ void sun4m_pic_info(Monitor *mon, const QDict *qdict);
 void sun4m_irq_info(Monitor *mon, const QDict *qdict);
 
 /* sparc32_dma.c */
-#include "sparc32_dma.h"
+#include "hw/sparc32_dma.h"
 
 #endif
diff --git a/hw/sun4m_iommu.c b/hw/sun4m_iommu.c
index 8f9635f..33e77b0 100644
--- a/hw/sun4m_iommu.c
+++ b/hw/sun4m_iommu.c
@@ -22,8 +22,8 @@
  * THE SOFTWARE.
  */
 
-#include "sun4m.h"
-#include "sysbus.h"
+#include "hw/sun4m.h"
+#include "hw/sysbus.h"
 #include "trace.h"
 
 /*
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 9fbda29..51ffa1c 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -21,22 +21,22 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "pci/pci.h"
-#include "apb_pci.h"
-#include "pc.h"
-#include "serial.h"
-#include "nvram.h"
-#include "fdc.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/apb_pci.h"
+#include "hw/pc.h"
+#include "hw/serial.h"
+#include "hw/nvram.h"
+#include "hw/fdc.h"
 #include "net/net.h"
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
-#include "boards.h"
-#include "firmware_abi.h"
-#include "fw_cfg.h"
-#include "sysbus.h"
-#include "ide.h"
-#include "loader.h"
+#include "hw/boards.h"
+#include "hw/firmware_abi.h"
+#include "hw/fw_cfg.h"
+#include "hw/sysbus.h"
+#include "hw/ide.h"
+#include "hw/loader.h"
 #include "elf.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
diff --git a/hw/sysbus.c b/hw/sysbus.c
index 6d9d1df..74bb4b8 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -17,7 +17,7 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "monitor/monitor.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/sysbus.h b/hw/sysbus.h
index a7fcded..17de506 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -3,7 +3,7 @@
 
 /* Devices attached directly to the main system bus.  */
 
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "exec/memory.h"
 
 #define QDEV_MAX_MMIO 32
diff --git a/hw/tc58128.c b/hw/tc58128.c
index 4ce80b1..f76f96d 100644
--- a/hw/tc58128.c
+++ b/hw/tc58128.c
@@ -1,6 +1,6 @@
-#include "hw.h"
-#include "sh.h"
-#include "loader.h"
+#include "hw/hw.h"
+#include "hw/sh.h"
+#include "hw/loader.h"
 
 #define CE1  0x0100
 #define CE2  0x0200
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index e815f83..0755463 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -10,9 +10,9 @@
  * Contributions after 2012-01-13 are licensed under the terms of the
  * GNU GPL, version 2 or (at your option) any later version.
  */
-#include "hw.h"
-#include "devices.h"
-#include "flash.h"
+#include "hw/hw.h"
+#include "hw/devices.h"
+#include "hw/flash.h"
 #include "ui/console.h"
 #include "ui/pixel_ops.h"
 #include "sysemu/blockdev.h"
@@ -421,15 +421,15 @@ static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value)
 }
 
 #define BITS 8
-#include "tc6393xb_template.h"
+#include "hw/tc6393xb_template.h"
 #define BITS 15
-#include "tc6393xb_template.h"
+#include "hw/tc6393xb_template.h"
 #define BITS 16
-#include "tc6393xb_template.h"
+#include "hw/tc6393xb_template.h"
 #define BITS 24
-#include "tc6393xb_template.h"
+#include "hw/tc6393xb_template.h"
 #define BITS 32
-#include "tc6393xb_template.h"
+#include "hw/tc6393xb_template.h"
 
 static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
 {
diff --git a/hw/tcx.c b/hw/tcx.c
index 0ce2952..896407d 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -25,8 +25,8 @@
 #include "qemu-common.h"
 #include "ui/console.h"
 #include "ui/pixel_ops.h"
-#include "sysbus.h"
-#include "qdev-addr.h"
+#include "hw/sysbus.h"
+#include "hw/qdev-addr.h"
 
 #define MAXX 1024
 #define MAXY 768
diff --git a/hw/tmp105.c b/hw/tmp105.c
index 3ad2d2f..47e5437 100644
--- a/hw/tmp105.c
+++ b/hw/tmp105.c
@@ -18,9 +18,9 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
-#include "i2c.h"
-#include "tmp105.h"
+#include "hw/hw.h"
+#include "hw/i2c.h"
+#include "hw/tmp105.h"
 #include "qapi/visitor.h"
 
 static void tmp105_interrupt_update(TMP105State *s)
diff --git a/hw/tmp105.h b/hw/tmp105.h
index d218919..9a9632c 100644
--- a/hw/tmp105.h
+++ b/hw/tmp105.h
@@ -14,8 +14,8 @@
 #ifndef QEMU_TMP105_H
 #define QEMU_TMP105_H
 
-#include "i2c.h"
-#include "tmp105_regs.h"
+#include "hw/i2c.h"
+#include "hw/tmp105_regs.h"
 
 #define TYPE_TMP105 "tmp105"
 #define TMP105(obj) OBJECT_CHECK(TMP105State, (obj), TYPE_TMP105)
diff --git a/hw/tosa.c b/hw/tosa.c
index efea109..747888c 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -11,18 +11,18 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
-#include "pxa.h"
-#include "arm-misc.h"
-#include "devices.h"
-#include "sharpsl.h"
-#include "pcmcia.h"
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "hw/sharpsl.h"
+#include "hw/pcmcia.h"
 #include "block/block.h"
-#include "boards.h"
-#include "i2c.h"
-#include "ssi.h"
+#include "hw/boards.h"
+#include "hw/i2c.h"
+#include "hw/ssi.h"
 #include "sysemu/blockdev.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "exec/address-spaces.h"
 
 #define TOSA_RAM    0x04000000
diff --git a/hw/tpci200.c b/hw/tpci200.c
index a4823fb..e3408ef 100644
--- a/hw/tpci200.c
+++ b/hw/tpci200.c
@@ -8,8 +8,8 @@
  * later version.
  */
 
-#include "ipack.h"
-#include "pci/pci.h"
+#include "hw/ipack.h"
+#include "hw/pci/pci.h"
 #include "qemu/bitops.h"
 #include <stdio.h>
 
diff --git a/hw/tsc2005.c b/hw/tsc2005.c
index 740ff86..a771cd5 100644
--- a/hw/tsc2005.c
+++ b/hw/tsc2005.c
@@ -18,10 +18,10 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
 #include "ui/console.h"
-#include "devices.h"
+#include "hw/devices.h"
 
 #define TSC_CUT_RESOLUTION(value, p)	((value) >> (16 - (p ? 12 : 10)))
 
diff --git a/hw/tsc210x.c b/hw/tsc210x.c
index 2076c35..b93e502 100644
--- a/hw/tsc210x.c
+++ b/hw/tsc210x.c
@@ -19,12 +19,12 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "audio/audio.h"
 #include "qemu/timer.h"
 #include "ui/console.h"
-#include "omap.h"	/* For I2SCodec and uWireSlave */
-#include "devices.h"
+#include "hw/omap.h"	/* For I2SCodec and uWireSlave */
+#include "hw/devices.h"
 
 #define TSC_DATA_REGISTERS_PAGE		0x0
 #define TSC_CONTROL_REGISTERS_PAGE	0x1
diff --git a/hw/tusb6010.c b/hw/tusb6010.c
index 2c7d033..a5251a3 100644
--- a/hw/tusb6010.c
+++ b/hw/tusb6010.c
@@ -20,11 +20,11 @@
  */
 #include "qemu-common.h"
 #include "qemu/timer.h"
-#include "usb.h"
-#include "omap.h"
-#include "irq.h"
-#include "devices.h"
-#include "sysbus.h"
+#include "hw/usb.h"
+#include "hw/omap.h"
+#include "hw/irq.h"
+#include "hw/devices.h"
+#include "hw/sysbus.h"
 
 typedef struct TUSBState {
     SysBusDevice busdev;
diff --git a/hw/twl92230.c b/hw/twl92230.c
index 70d9b03..7d020c4 100644
--- a/hw/twl92230.c
+++ b/hw/twl92230.c
@@ -19,9 +19,9 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
-#include "i2c.h"
+#include "hw/i2c.h"
 #include "sysemu/sysemu.h"
 #include "ui/console.h"
 
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index f1c3c20..cb95ad1 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -21,10 +21,10 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "ppc/mac.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
+#include "hw/hw.h"
+#include "hw/ppc/mac.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
 
 /* debug UniNorth */
 //#define DEBUG_UNIN
diff --git a/hw/usb.h b/hw/usb.h
index 382496c..1b10684 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -25,7 +25,7 @@
  * THE SOFTWARE.
  */
 
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "qemu/queue.h"
 
 /* Constants related to the USB / PCI interaction */
diff --git a/hw/versatile_i2c.c b/hw/versatile_i2c.c
index ad71e9d..d0444ae 100644
--- a/hw/versatile_i2c.c
+++ b/hw/versatile_i2c.c
@@ -21,8 +21,8 @@
  *
  */
 
-#include "sysbus.h"
-#include "bitbang_i2c.h"
+#include "hw/sysbus.h"
+#include "hw/bitbang_i2c.h"
 
 typedef struct {
     SysBusDevice busdev;
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index 9d99159..0b97a40 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -7,9 +7,9 @@
  * This code is licensed under the LGPL.
  */
 
-#include "sysbus.h"
-#include "pci/pci.h"
-#include "pci/pci_host.h"
+#include "hw/sysbus.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
 #include "exec/address-spaces.h"
 
 typedef struct {
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index e0a28f0..baaa265 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -7,17 +7,17 @@
  * This code is licensed under the GPL.
  */
 
-#include "sysbus.h"
-#include "arm-misc.h"
-#include "devices.h"
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
 #include "net/net.h"
 #include "sysemu/sysemu.h"
-#include "pci/pci.h"
-#include "i2c.h"
-#include "boards.h"
+#include "hw/pci/pci.h"
+#include "hw/i2c.h"
+#include "hw/boards.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
-#include "flash.h"
+#include "hw/flash.h"
 
 #define VERSATILE_FLASH_ADDR 0x34000000
 #define VERSATILE_FLASH_SIZE (64 * 1024 * 1024)
diff --git a/hw/vexpress.c b/hw/vexpress.c
index 741b044..02922c3 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -21,16 +21,16 @@
  *  GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "sysbus.h"
-#include "arm-misc.h"
-#include "primecell.h"
-#include "devices.h"
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
+#include "hw/primecell.h"
+#include "hw/devices.h"
 #include "net/net.h"
 #include "sysemu/sysemu.h"
-#include "boards.h"
+#include "hw/boards.h"
 #include "exec/address-spaces.h"
 #include "sysemu/blockdev.h"
-#include "flash.h"
+#include "hw/flash.h"
 
 #define VEXPRESS_BOARD_ID 0x8e0
 #define VEXPRESS_FLASH_SIZE (64 * 1024 * 1024)
diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index ad9ae36..288361d 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -31,9 +31,9 @@
 #include "exec/address-spaces.h"
 #include "sysemu/kvm.h"
 #include "exec/memory.h"
-#include "pci/msi.h"
-#include "pci/msix.h"
-#include "pci/pci.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/msix.h"
+#include "hw/pci/pci.h"
 #include "qemu-common.h"
 #include "qemu/error-report.h"
 #include "qemu/queue.h"
diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c
index 311c966..4aa62bf 100644
--- a/hw/vga-isa-mm.c
+++ b/hw/vga-isa-mm.c
@@ -21,10 +21,10 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
-#include "pc.h"
-#include "vga_int.h"
+#include "hw/pc.h"
+#include "hw/vga_int.h"
 #include "ui/pixel_ops.h"
 #include "qemu/timer.h"
 
diff --git a/hw/vga-isa.c b/hw/vga-isa.c
index 762e45a..ffad522 100644
--- a/hw/vga-isa.c
+++ b/hw/vga-isa.c
@@ -23,13 +23,13 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
-#include "pc.h"
-#include "vga_int.h"
+#include "hw/pc.h"
+#include "hw/vga_int.h"
 #include "ui/pixel_ops.h"
 #include "qemu/timer.h"
-#include "loader.h"
+#include "hw/loader.h"
 
 typedef struct ISAVGAState {
     ISADevice dev;
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index c491af2..18018ff 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -23,13 +23,13 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
-#include "pci/pci.h"
-#include "vga_int.h"
+#include "hw/pci/pci.h"
+#include "hw/vga_int.h"
 #include "ui/pixel_ops.h"
 #include "qemu/timer.h"
-#include "loader.h"
+#include "hw/loader.h"
 
 #define PCI_VGA_IOPORT_OFFSET 0x400
 #define PCI_VGA_IOPORT_SIZE   (0x3e0 - 0x3c0)
diff --git a/hw/vga.c b/hw/vga.c
index 1caf23d..2213bc1 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -21,15 +21,15 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "vga.h"
+#include "hw/hw.h"
+#include "hw/vga.h"
 #include "ui/console.h"
-#include "pc.h"
-#include "pci/pci.h"
-#include "vga_int.h"
+#include "hw/pc.h"
+#include "hw/pci/pci.h"
+#include "hw/vga_int.h"
 #include "ui/pixel_ops.h"
 #include "qemu/timer.h"
-#include "xen.h"
+#include "hw/xen.h"
 #include "trace.h"
 
 //#define DEBUG_VGA
@@ -986,28 +986,28 @@ typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
                                 const uint8_t *s, int width);
 
 #define DEPTH 8
-#include "vga_template.h"
+#include "hw/vga_template.h"
 
 #define DEPTH 15
-#include "vga_template.h"
+#include "hw/vga_template.h"
 
 #define BGR_FORMAT
 #define DEPTH 15
-#include "vga_template.h"
+#include "hw/vga_template.h"
 
 #define DEPTH 16
-#include "vga_template.h"
+#include "hw/vga_template.h"
 
 #define BGR_FORMAT
 #define DEPTH 16
-#include "vga_template.h"
+#include "hw/vga_template.h"
 
 #define DEPTH 32
-#include "vga_template.h"
+#include "hw/vga_template.h"
 
 #define BGR_FORMAT
 #define DEPTH 32
-#include "vga_template.h"
+#include "hw/vga_template.h"
 
 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
 {
diff --git a/hw/vhost.c b/hw/vhost.c
index 8d41fdb..2d25d7e 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -14,7 +14,7 @@
  */
 
 #include <sys/ioctl.h>
-#include "vhost.h"
+#include "hw/vhost.h"
 #include "hw/hw.h"
 #include "qemu/range.h"
 #include <linux/vhost.h>
diff --git a/hw/vhost_net.c b/hw/vhost_net.c
index d1df0e2..d3218a0 100644
--- a/hw/vhost_net.c
+++ b/hw/vhost_net.c
@@ -16,8 +16,8 @@
 #include "net/net.h"
 #include "net/tap.h"
 
-#include "virtio-net.h"
-#include "vhost_net.h"
+#include "hw/virtio-net.h"
+#include "hw/vhost_net.h"
 #include "qemu/error-report.h"
 
 #include "config.h"
@@ -36,7 +36,7 @@
 
 #include <stdio.h>
 
-#include "vhost.h"
+#include "hw/vhost.h"
 
 struct vhost_net {
     struct vhost_dev dev;
diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
index 8c4e8e4..41eab16 100644
--- a/hw/virtex_ml507.c
+++ b/hw/virtex_ml507.c
@@ -22,25 +22,25 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
-#include "hw.h"
-#include "serial.h"
-#include "flash.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/serial.h"
+#include "hw/flash.h"
 #include "sysemu/sysemu.h"
-#include "devices.h"
-#include "boards.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
 #include "sysemu/device_tree.h"
-#include "loader.h"
+#include "hw/loader.h"
 #include "elf.h"
 #include "qemu/log.h"
 #include "exec/address-spaces.h"
 
-#include "ppc.h"
-#include "ppc4xx.h"
-#include "ppc405.h"
+#include "hw/ppc.h"
+#include "hw/ppc4xx.h"
+#include "hw/ppc405.h"
 
 #include "sysemu/blockdev.h"
-#include "xilinx.h"
+#include "hw/xilinx.h"
 
 #define EPAPR_MAGIC    (0x45504150)
 #define FLASH_SIZE     (16 * 1024 * 1024)
diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index c0a7902..6bfcddc 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -16,11 +16,11 @@
 #include "qemu/iov.h"
 #include "qemu/timer.h"
 #include "qemu-common.h"
-#include "virtio.h"
-#include "pc.h"
+#include "hw/virtio.h"
+#include "hw/pc.h"
 #include "cpu.h"
 #include "sysemu/balloon.h"
-#include "virtio-balloon.h"
+#include "hw/virtio-balloon.h"
 #include "sysemu/kvm.h"
 #include "exec/address-spaces.h"
 #include "qapi/visitor.h"
diff --git a/hw/virtio-balloon.h b/hw/virtio-balloon.h
index b1828f4..f37f31b 100644
--- a/hw/virtio-balloon.h
+++ b/hw/virtio-balloon.h
@@ -15,8 +15,8 @@
 #ifndef _QEMU_VIRTIO_BALLOON_H
 #define _QEMU_VIRTIO_BALLOON_H
 
-#include "virtio.h"
-#include "pci/pci.h"
+#include "hw/virtio.h"
+#include "hw/pci/pci.h"
 
 /* from Linux's linux/virtio_balloon.h */
 
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 34913ee..248a966 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -16,11 +16,11 @@
 #include "trace.h"
 #include "hw/block-common.h"
 #include "sysemu/blockdev.h"
-#include "virtio-blk.h"
+#include "hw/virtio-blk.h"
 #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
-#include "hw/dataplane/virtio-blk.h"
+#include "dataplane/virtio-blk.h"
 #endif
-#include "scsi-defs.h"
+#include "hw/scsi-defs.h"
 #ifdef __linux__
 # include <scsi/sg.h>
 #endif
diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h
index 43ca492..7ef2f35 100644
--- a/hw/virtio-blk.h
+++ b/hw/virtio-blk.h
@@ -14,7 +14,7 @@
 #ifndef _QEMU_VIRTIO_BLK_H
 #define _QEMU_VIRTIO_BLK_H
 
-#include "virtio.h"
+#include "hw/virtio.h"
 #include "hw/block-common.h"
 
 /* from Linux's linux/virtio_blk.h */
diff --git a/hw/virtio-bus.c b/hw/virtio-bus.c
index 6045d8a..6c2aab0 100644
--- a/hw/virtio-bus.c
+++ b/hw/virtio-bus.c
@@ -22,11 +22,11 @@
  *
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/error-report.h"
-#include "qdev.h"
-#include "virtio-bus.h"
-#include "virtio.h"
+#include "hw/qdev.h"
+#include "hw/virtio-bus.h"
+#include "hw/virtio.h"
 
 /* #define DEBUG_VIRTIO_BUS */
 
diff --git a/hw/virtio-bus.h b/hw/virtio-bus.h
index 7584a0e..ae0f707 100644
--- a/hw/virtio-bus.h
+++ b/hw/virtio-bus.h
@@ -25,9 +25,9 @@
 #ifndef VIRTIO_BUS_H
 #define VIRTIO_BUS_H
 
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "sysemu/sysemu.h"
-#include "virtio.h"
+#include "hw/virtio.h"
 
 #define TYPE_VIRTIO_BUS "virtio-bus"
 #define VIRTIO_BUS_GET_CLASS(obj) \
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index 46072a0..b10f5f0 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -13,7 +13,7 @@
 #include "char/char.h"
 #include "qemu/error-report.h"
 #include "trace.h"
-#include "virtio-serial.h"
+#include "hw/virtio-serial.h"
 
 typedef struct VirtConsole {
     VirtIOSerialPort port;
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 573c669..0ad96ee 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -12,14 +12,14 @@
  */
 
 #include "qemu/iov.h"
-#include "virtio.h"
+#include "hw/virtio.h"
 #include "net/net.h"
 #include "net/checksum.h"
 #include "net/tap.h"
 #include "qemu/error-report.h"
 #include "qemu/timer.h"
-#include "virtio-net.h"
-#include "vhost_net.h"
+#include "hw/virtio-net.h"
+#include "hw/vhost_net.h"
 
 #define VIRTIO_NET_VM_VERSION    11
 
diff --git a/hw/virtio-net.h b/hw/virtio-net.h
index e654c13..0c83ca5 100644
--- a/hw/virtio-net.h
+++ b/hw/virtio-net.h
@@ -14,8 +14,8 @@
 #ifndef _QEMU_VIRTIO_NET_H
 #define _QEMU_VIRTIO_NET_H
 
-#include "virtio.h"
-#include "pci/pci.h"
+#include "hw/virtio.h"
+#include "hw/pci/pci.h"
 
 #define ETH_ALEN    6
 
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index df1dd77..ba4d7d5 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -17,21 +17,21 @@
 
 #include <inttypes.h>
 
-#include "virtio.h"
-#include "virtio-blk.h"
-#include "virtio-net.h"
-#include "virtio-serial.h"
-#include "virtio-scsi.h"
-#include "pci/pci.h"
+#include "hw/virtio.h"
+#include "hw/virtio-blk.h"
+#include "hw/virtio-net.h"
+#include "hw/virtio-serial.h"
+#include "hw/virtio-scsi.h"
+#include "hw/pci/pci.h"
 #include "qemu/error-report.h"
-#include "pci/msi.h"
-#include "pci/msix.h"
-#include "loader.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/msix.h"
+#include "hw/loader.h"
 #include "sysemu/kvm.h"
 #include "sysemu/blockdev.h"
-#include "virtio-pci.h"
+#include "hw/virtio-pci.h"
 #include "qemu/range.h"
-#include "virtio-bus.h"
+#include "hw/virtio-bus.h"
 
 /* from Linux's linux/virtio_pci.h */
 
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index d01db97..2ae96f8 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -16,13 +16,13 @@
 #define QEMU_VIRTIO_PCI_H
 
 #include "hw/pci/msi.h"
-#include "virtio-blk.h"
-#include "virtio-net.h"
-#include "virtio-rng.h"
-#include "virtio-serial.h"
-#include "virtio-scsi.h"
-#include "virtio-bus.h"
-#include "9pfs/virtio-9p-device.h"
+#include "hw/virtio-blk.h"
+#include "hw/virtio-net.h"
+#include "hw/virtio-rng.h"
+#include "hw/virtio-serial.h"
+#include "hw/virtio-scsi.h"
+#include "hw/virtio-bus.h"
+#include "hw/9pfs/virtio-9p-device.h"
 
 typedef struct VirtIOPCIProxy VirtIOPCIProxy;
 
diff --git a/hw/virtio-rng.c b/hw/virtio-rng.c
index 2cdf4ec..54c1421 100644
--- a/hw/virtio-rng.c
+++ b/hw/virtio-rng.c
@@ -10,10 +10,10 @@
  */
 
 #include "qemu/iov.h"
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "qapi/qmp/qerror.h"
-#include "virtio.h"
-#include "virtio-rng.h"
+#include "hw/virtio.h"
+#include "hw/virtio-rng.h"
 #include "qemu/rng.h"
 
 typedef struct VirtIORNG {
diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 27070d1..72cc519 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -13,7 +13,7 @@
  *
  */
 
-#include "virtio-scsi.h"
+#include "hw/virtio-scsi.h"
 #include "qemu/error-report.h"
 #include <hw/scsi.h>
 #include <hw/scsi-defs.h>
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
index 8d9d15f..81b3279 100644
--- a/hw/virtio-scsi.h
+++ b/hw/virtio-scsi.h
@@ -14,8 +14,8 @@
 #ifndef _QEMU_VIRTIO_SCSI_H
 #define _QEMU_VIRTIO_SCSI_H
 
-#include "virtio.h"
-#include "pci/pci.h"
+#include "hw/virtio.h"
+#include "hw/pci/pci.h"
 
 /* The ID for virtio_scsi */
 #define VIRTIO_ID_SCSI  8
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index aa7d0d7..ada1d01 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -21,9 +21,9 @@
 #include "qemu/iov.h"
 #include "monitor/monitor.h"
 #include "qemu/queue.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "trace.h"
-#include "virtio-serial.h"
+#include "hw/virtio-serial.h"
 
 /* The virtio-serial bus on top of which the ports will ride as devices */
 struct VirtIOSerialBus {
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
index 16e3982..d2d9fb7 100644
--- a/hw/virtio-serial.h
+++ b/hw/virtio-serial.h
@@ -15,8 +15,8 @@
 #ifndef _QEMU_VIRTIO_SERIAL_H
 #define _QEMU_VIRTIO_SERIAL_H
 
-#include "qdev.h"
-#include "virtio.h"
+#include "hw/qdev.h"
+#include "hw/virtio.h"
 
 /* == Interface shared between the guest kernel and qemu == */
 
diff --git a/hw/virtio.c b/hw/virtio.c
index e259348..26fbc79 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -15,9 +15,9 @@
 
 #include "trace.h"
 #include "qemu/error-report.h"
-#include "virtio.h"
+#include "hw/virtio.h"
 #include "qemu/atomic.h"
-#include "virtio-bus.h"
+#include "hw/virtio-bus.h"
 
 /* The alignment to use between consumer and producer parts of vring.
  * x86 pagesize again. */
diff --git a/hw/virtio.h b/hw/virtio.h
index 8cc71e9..ca43fd7 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -14,13 +14,13 @@
 #ifndef _QEMU_VIRTIO_H
 #define _QEMU_VIRTIO_H
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "net/net.h"
-#include "qdev.h"
+#include "hw/qdev.h"
 #include "sysemu/sysemu.h"
 #include "qemu/event_notifier.h"
 #ifdef CONFIG_VIRTFS
-#include "9pfs/virtio-9p-device.h"
+#include "hw/9pfs/virtio-9p-device.h"
 #endif
 
 /* from Linux's linux/virtio_config.h */
diff --git a/hw/vmmouse.c b/hw/vmmouse.c
index b9afc2c..a9d227e 100644
--- a/hw/vmmouse.c
+++ b/hw/vmmouse.c
@@ -21,11 +21,11 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
-#include "ps2.h"
-#include "pc.h"
-#include "qdev.h"
+#include "hw/ps2.h"
+#include "hw/pc.h"
+#include "hw/qdev.h"
 
 /* debug only vmmouse */
 //#define DEBUG_VMMOUSE
diff --git a/hw/vmport.c b/hw/vmport.c
index faead3a..cc1466a 100644
--- a/hw/vmport.c
+++ b/hw/vmport.c
@@ -21,11 +21,11 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "isa.h"
-#include "pc.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
+#include "hw/pc.h"
 #include "sysemu/kvm.h"
-#include "qdev.h"
+#include "hw/qdev.h"
 
 //#define VMPORT_DEBUG
 
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 8fc201b..db2f187 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -21,17 +21,17 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "loader.h"
+#include "hw/hw.h"
+#include "hw/loader.h"
 #include "ui/console.h"
-#include "pci/pci.h"
+#include "hw/pci/pci.h"
 
 #undef VERBOSE
 #define HW_RECT_ACCEL
 #define HW_FILL_ACCEL
 #define HW_MOUSE_ACCEL
 
-#include "vga_int.h"
+#include "hw/vga_int.h"
 
 /* See http://vmware-svga.sf.net/ for some documentation on VMWare SVGA */
 
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index c2b1bfc..4529508 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -10,18 +10,18 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
-#include "pc.h"
-#include "vt82c686.h"
-#include "i2c.h"
-#include "smbus.h"
-#include "pci/pci.h"
-#include "isa.h"
-#include "sysbus.h"
-#include "mips.h"
-#include "apm.h"
-#include "acpi.h"
-#include "pm_smbus.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/vt82c686.h"
+#include "hw/i2c.h"
+#include "hw/smbus.h"
+#include "hw/pci/pci.h"
+#include "hw/isa.h"
+#include "hw/sysbus.h"
+#include "hw/mips.h"
+#include "hw/apm.h"
+#include "hw/acpi.h"
+#include "hw/pm_smbus.h"
 #include "sysemu/sysemu.h"
 #include "qemu/timer.h"
 #include "exec/address-spaces.h"
diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c
index 37ce362..f13e507 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -23,9 +23,9 @@
 
 #include "qemu-common.h"
 #include "qemu/timer.h"
-#include "watchdog.h"
-#include "hw.h"
-#include "pci/pci.h"
+#include "hw/watchdog.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
 
 /*#define I6300ESB_DEBUG 1*/
 
diff --git a/hw/wdt_ib700.c b/hw/wdt_ib700.c
index 599a86f..6c52808 100644
--- a/hw/wdt_ib700.c
+++ b/hw/wdt_ib700.c
@@ -21,10 +21,10 @@
 
 #include "qemu-common.h"
 #include "qemu/timer.h"
-#include "watchdog.h"
-#include "hw.h"
-#include "isa.h"
-#include "pc.h"
+#include "hw/watchdog.h"
+#include "hw/hw.h"
+#include "hw/isa.h"
+#include "hw/pc.h"
 
 /*#define IB700_DEBUG 1*/
 
diff --git a/hw/wm8750.c b/hw/wm8750.c
index d3ea5ba..0904cf4 100644
--- a/hw/wm8750.c
+++ b/hw/wm8750.c
@@ -7,8 +7,8 @@
  * This file is licensed under GNU GPL.
  */
 
-#include "hw.h"
-#include "i2c.h"
+#include "hw/hw.h"
+#include "hw/i2c.h"
 #include "audio/audio.h"
 
 #define IN_PORT_N	3
diff --git a/hw/xen-host-pci-device.c b/hw/xen-host-pci-device.c
index 743b37b..ff2e876 100644
--- a/hw/xen-host-pci-device.c
+++ b/hw/xen-host-pci-device.c
@@ -7,7 +7,7 @@
  */
 
 #include "qemu-common.h"
-#include "xen-host-pci-device.h"
+#include "hw/xen-host-pci-device.h"
 
 #define XEN_HOST_PCI_MAX_EXT_CAP \
     ((PCIE_CONFIG_SPACE_SIZE - PCI_CONFIG_SPACE_SIZE) / (PCI_CAP_SIZEOF + 4))
diff --git a/hw/xen-host-pci-device.h b/hw/xen-host-pci-device.h
index 942b24d..c2486f0 100644
--- a/hw/xen-host-pci-device.h
+++ b/hw/xen-host-pci-device.h
@@ -1,7 +1,7 @@
 #ifndef XEN_HOST_PCI_DEVICE_H
 #define XEN_HOST_PCI_DEVICE_H
 
-#include "pci/pci.h"
+#include "hw/pci/pci.h"
 
 enum {
     XEN_HOST_PCI_REGION_TYPE_IO = 1 << 1,
diff --git a/hw/xen_apic.c b/hw/xen_apic.c
index 1d1d15c..8f387b6 100644
--- a/hw/xen_apic.c
+++ b/hw/xen_apic.c
@@ -11,7 +11,7 @@
  */
 #include "hw/apic_internal.h"
 #include "hw/pci/msi.h"
-#include "xen.h"
+#include "hw/xen.h"
 
 static uint64_t xen_apic_mem_read(void *opaque, hwaddr addr,
                                   unsigned size)
diff --git a/hw/xen_backend.c b/hw/xen_backend.c
index 3fa3009..24381b5 100644
--- a/hw/xen_backend.c
+++ b/hw/xen_backend.c
@@ -34,10 +34,10 @@
 #include <sys/mman.h>
 #include <sys/signal.h>
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "char/char.h"
 #include "qemu/log.h"
-#include "xen_backend.h"
+#include "hw/xen_backend.h"
 
 #include <xen/grant_table.h>
 
diff --git a/hw/xen_backend.h b/hw/xen_backend.h
index f37afb1..6d5c699 100644
--- a/hw/xen_backend.h
+++ b/hw/xen_backend.h
@@ -1,7 +1,7 @@
 #ifndef QEMU_HW_XEN_BACKEND_H
 #define QEMU_HW_XEN_BACKEND_H 1
 
-#include "xen_common.h"
+#include "hw/xen_common.h"
 #include "sysemu/sysemu.h"
 #include "net/net.h"
 
diff --git a/hw/xen_common.h b/hw/xen_common.h
index 95bc9a7..c37bde3 100644
--- a/hw/xen_common.h
+++ b/hw/xen_common.h
@@ -14,8 +14,8 @@
 #endif
 #include <xen/io/xenbus.h>
 
-#include "hw.h"
-#include "xen.h"
+#include "hw/hw.h"
+#include "hw/xen.h"
 #include "qemu/queue.h"
 
 /*
diff --git a/hw/xen_console.c b/hw/xen_console.c
index 44141f8..a8db6f8 100644
--- a/hw/xen_console.c
+++ b/hw/xen_console.c
@@ -29,9 +29,9 @@
 #include <stdarg.h>
 #include <sys/mman.h>
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "char/char.h"
-#include "xen_backend.h"
+#include "hw/xen_backend.h"
 
 #include <xen/io/console.h>
 
diff --git a/hw/xen_devconfig.c b/hw/xen_devconfig.c
index e2ba741..cdcaf62 100644
--- a/hw/xen_devconfig.c
+++ b/hw/xen_devconfig.c
@@ -1,4 +1,4 @@
-#include "xen_backend.h"
+#include "hw/xen_backend.h"
 #include "sysemu/blockdev.h"
 
 /* ------------------------------------------------------------- */
diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 7fea871..cc09a2f 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -35,9 +35,9 @@
 #include <sys/mman.h>
 #include <sys/uio.h>
 
-#include "hw.h"
-#include "xen_backend.h"
-#include "xen_blkif.h"
+#include "hw/hw.h"
+#include "hw/xen_backend.h"
+#include "hw/xen_blkif.h"
 #include "sysemu/blockdev.h"
 
 /* ------------------------------------------------------------- */
diff --git a/hw/xen_domainbuild.c b/hw/xen_domainbuild.c
index a4272f0..d477061 100644
--- a/hw/xen_domainbuild.c
+++ b/hw/xen_domainbuild.c
@@ -1,6 +1,6 @@
 #include <signal.h>
-#include "xen_backend.h"
-#include "xen_domainbuild.h"
+#include "hw/xen_backend.h"
+#include "hw/xen_domainbuild.h"
 #include "qemu/timer.h"
 #include "qemu/log.h"
 
diff --git a/hw/xen_domainbuild.h b/hw/xen_domainbuild.h
index dea0121..681cbe5 100644
--- a/hw/xen_domainbuild.h
+++ b/hw/xen_domainbuild.h
@@ -1,7 +1,7 @@
 #ifndef QEMU_HW_XEN_DOMAINBUILD_H
 #define QEMU_HW_XEN_DOMAINBUILD_H 1
 
-#include "xen_common.h"
+#include "hw/xen_common.h"
 
 int xenstore_domain_init1(const char *kernel, const char *ramdisk,
                           const char *cmdline);
diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c
index 66e8981..a8177b6 100644
--- a/hw/xen_machine_pv.c
+++ b/hw/xen_machine_pv.c
@@ -22,11 +22,11 @@
  * THE SOFTWARE.
  */
 
-#include "hw.h"
-#include "pc.h"
-#include "boards.h"
-#include "xen_backend.h"
-#include "xen_domainbuild.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/boards.h"
+#include "hw/xen_backend.h"
+#include "hw/xen_domainbuild.h"
 #include "sysemu/blockdev.h"
 
 static void xen_init_pv(QEMUMachineInitArgs *args)
diff --git a/hw/xen_nic.c b/hw/xen_nic.c
index 34961c2..b6d3679 100644
--- a/hw/xen_nic.c
+++ b/hw/xen_nic.c
@@ -35,11 +35,11 @@
 #include <sys/mman.h>
 #include <sys/wait.h>
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "net/net.h"
 #include "net/checksum.h"
 #include "net/util.h"
-#include "xen_backend.h"
+#include "hw/xen_backend.h"
 
 #include <xen/io/netif.h>
 
diff --git a/hw/xen_platform.c b/hw/xen_platform.c
index 8866468..5e11c95 100644
--- a/hw/xen_platform.c
+++ b/hw/xen_platform.c
@@ -25,12 +25,12 @@
 
 #include <assert.h>
 
-#include "hw.h"
-#include "pc.h"
-#include "pci/pci.h"
-#include "irq.h"
-#include "xen_common.h"
-#include "xen_backend.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/pci/pci.h"
+#include "hw/irq.h"
+#include "hw/xen_common.h"
+#include "hw/xen_backend.h"
 #include "trace.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/xen_pt.c b/hw/xen_pt.c
index 9db5f6e..ce695d0 100644
--- a/hw/xen_pt.c
+++ b/hw/xen_pt.c
@@ -54,10 +54,10 @@
 
 #include <sys/ioctl.h>
 
-#include "pci/pci.h"
-#include "xen.h"
-#include "xen_backend.h"
-#include "xen_pt.h"
+#include "hw/pci/pci.h"
+#include "hw/xen.h"
+#include "hw/xen_backend.h"
+#include "hw/xen_pt.h"
 #include "qemu/range.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/xen_pt.h b/hw/xen_pt.h
index e349730..1cd9f44 100644
--- a/hw/xen_pt.h
+++ b/hw/xen_pt.h
@@ -2,9 +2,9 @@
 #define XEN_PT_H
 
 #include "qemu-common.h"
-#include "xen_common.h"
-#include "pci/pci.h"
-#include "xen-host-pci-device.h"
+#include "hw/xen_common.h"
+#include "hw/pci/pci.h"
+#include "hw/xen-host-pci-device.h"
 
 void xen_pt_log(const PCIDevice *d, const char *f, ...) GCC_FMT_ATTR(2, 3);
 
diff --git a/hw/xen_pt_config_init.c b/hw/xen_pt_config_init.c
index 54a179a..5583821 100644
--- a/hw/xen_pt_config_init.c
+++ b/hw/xen_pt_config_init.c
@@ -13,8 +13,8 @@
  */
 
 #include "qemu/timer.h"
-#include "xen_backend.h"
-#include "xen_pt.h"
+#include "hw/xen_backend.h"
+#include "hw/xen_pt.h"
 
 #define XEN_PT_MERGE_VALUE(value, data, val_mask) \
     (((value) & (val_mask)) | ((data) & ~(val_mask)))
diff --git a/hw/xen_pt_msi.c b/hw/xen_pt_msi.c
index db757cd..a54ee2b 100644
--- a/hw/xen_pt_msi.c
+++ b/hw/xen_pt_msi.c
@@ -11,9 +11,9 @@
 
 #include <sys/mman.h>
 
-#include "xen_backend.h"
-#include "xen_pt.h"
-#include "apic-msidef.h"
+#include "hw/xen_backend.h"
+#include "hw/xen_pt.h"
+#include "hw/apic-msidef.h"
 
 
 #define XEN_PT_AUTO_ASSIGN -1
diff --git a/hw/xenfb.c b/hw/xenfb.c
index 7f1f6b4..3462ded 100644
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -35,10 +35,10 @@
 #include <string.h>
 #include <time.h>
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "ui/console.h"
 #include "char/char.h"
-#include "xen_backend.h"
+#include "hw/xen_backend.h"
 
 #include <xen/event_channel.h>
 #include <xen/io/fbif.h>
diff --git a/hw/xgmac.c b/hw/xgmac.c
index 5072298..5275f48 100644
--- a/hw/xgmac.c
+++ b/hw/xgmac.c
@@ -24,7 +24,7 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "char/char.h"
 #include "qemu/log.h"
 #include "net/net.h"
diff --git a/hw/xics.c b/hw/xics.c
index 9ef0d61..c3ef12f 100644
--- a/hw/xics.c
+++ b/hw/xics.c
@@ -25,7 +25,7 @@
  *
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "trace.h"
 #include "hw/spapr.h"
 #include "hw/xics.h"
diff --git a/hw/xilinx.h b/hw/xilinx.h
index a78281f..6c1ee21 100644
--- a/hw/xilinx.h
+++ b/hw/xilinx.h
@@ -4,7 +4,7 @@
 
 #include "qemu-common.h"
 #include "qapi/qmp/qerror.h"
-#include "stream.h"
+#include "hw/stream.h"
 #include "net/net.h"
 
 static inline DeviceState *
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index cc51584..8db1a74 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -22,13 +22,13 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/timer.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 #include "qemu/log.h"
-#include "qdev-addr.h"
+#include "hw/qdev-addr.h"
 
-#include "stream.h"
+#include "hw/stream.h"
 
 #define D(x)
 
diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index 66b9ec1..5785290 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -22,13 +22,13 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "qemu/log.h"
 #include "net/net.h"
 #include "net/checksum.h"
 #include "qapi/qmp/qerror.h"
 
-#include "stream.h"
+#include "hw/stream.h"
 
 #define DPHY(x)
 
diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c
index 21c6f8c..b2e3523 100644
--- a/hw/xilinx_ethlite.c
+++ b/hw/xilinx_ethlite.c
@@ -22,8 +22,8 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
-#include "hw.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
 #include "net/net.h"
 
 #define D(x)
diff --git a/hw/xilinx_intc.c b/hw/xilinx_intc.c
index 0c34149..b106e72 100644
--- a/hw/xilinx_intc.c
+++ b/hw/xilinx_intc.c
@@ -22,8 +22,8 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
-#include "hw.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
 
 #define D(x)
 
diff --git a/hw/xilinx_spi.c b/hw/xilinx_spi.c
index e73c9bd..f6bd3ba 100644
--- a/hw/xilinx_spi.c
+++ b/hw/xilinx_spi.c
@@ -24,12 +24,12 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "qemu/log.h"
 #include "qemu/fifo8.h"
 
-#include "ssi.h"
+#include "hw/ssi.h"
 
 #ifdef XILINX_SPI_ERR_DEBUG
 #define DB_PRINT(...) do { \
diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c
index 915eb96..6c21b96 100644
--- a/hw/xilinx_spips.c
+++ b/hw/xilinx_spips.c
@@ -22,12 +22,12 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
-#include "ptimer.h"
+#include "hw/ptimer.h"
 #include "qemu/log.h"
 #include "qemu/fifo8.h"
-#include "ssi.h"
+#include "hw/ssi.h"
 #include "qemu/bitops.h"
 
 #ifdef XILINX_SPIPS_ERR_DEBUG
diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c
index aa162ef..0c39cff 100644
--- a/hw/xilinx_timer.c
+++ b/hw/xilinx_timer.c
@@ -22,8 +22,8 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
-#include "ptimer.h"
+#include "hw/sysbus.h"
+#include "hw/ptimer.h"
 #include "qemu/log.h"
 
 #define D(x)
diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
index 9963982..079f4d4 100644
--- a/hw/xilinx_uartlite.c
+++ b/hw/xilinx_uartlite.c
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "char/char.h"
 
 #define DUART(x)
diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
index 2f67d90..f78c47e 100644
--- a/hw/xilinx_zynq.c
+++ b/hw/xilinx_zynq.c
@@ -15,16 +15,16 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "sysbus.h"
-#include "arm-misc.h"
+#include "hw/sysbus.h"
+#include "hw/arm-misc.h"
 #include "net/net.h"
 #include "exec/address-spaces.h"
 #include "sysemu/sysemu.h"
-#include "boards.h"
-#include "flash.h"
+#include "hw/boards.h"
+#include "hw/flash.h"
 #include "sysemu/blockdev.h"
-#include "loader.h"
-#include "ssi.h"
+#include "hw/loader.h"
+#include "hw/ssi.h"
 
 #define NUM_SPI_FLASHES 4
 #define NUM_QSPI_FLASHES 2
diff --git a/hw/xio3130_downstream.c b/hw/xio3130_downstream.c
index 7f00bc8..4bccd0d 100644
--- a/hw/xio3130_downstream.c
+++ b/hw/xio3130_downstream.c
@@ -19,10 +19,10 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "pci/pci_ids.h"
-#include "pci/msi.h"
-#include "pci/pcie.h"
-#include "xio3130_downstream.h"
+#include "hw/pci/pci_ids.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/pcie.h"
+#include "hw/xio3130_downstream.h"
 
 #define PCI_DEVICE_ID_TI_XIO3130D       0x8233  /* downstream port */
 #define XIO3130_REVISION                0x1
diff --git a/hw/xio3130_downstream.h b/hw/xio3130_downstream.h
index 559dff6..8426d9f 100644
--- a/hw/xio3130_downstream.h
+++ b/hw/xio3130_downstream.h
@@ -1,7 +1,7 @@
 #ifndef QEMU_XIO3130_DOWNSTREAM_H
 #define QEMU_XIO3130_DOWNSTREAM_H
 
-#include "pci/pcie_port.h"
+#include "hw/pci/pcie_port.h"
 
 PCIESlot *xio3130_downstream_init(PCIBus *bus, int devfn, bool multifunction,
                                   const char *bus_name, pci_map_irq_fn map_irq,
diff --git a/hw/xio3130_upstream.c b/hw/xio3130_upstream.c
index 70b15d3..82556aa 100644
--- a/hw/xio3130_upstream.c
+++ b/hw/xio3130_upstream.c
@@ -19,10 +19,10 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "pci/pci_ids.h"
-#include "pci/msi.h"
-#include "pci/pcie.h"
-#include "xio3130_upstream.h"
+#include "hw/pci/pci_ids.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/pcie.h"
+#include "hw/xio3130_upstream.h"
 
 #define PCI_DEVICE_ID_TI_XIO3130U       0x8232  /* upstream port */
 #define XIO3130_REVISION                0x2
diff --git a/hw/xio3130_upstream.h b/hw/xio3130_upstream.h
index fa09656..08c1d5f 100644
--- a/hw/xio3130_upstream.h
+++ b/hw/xio3130_upstream.h
@@ -1,7 +1,7 @@
 #ifndef QEMU_XIO3130_UPSTREAM_H
 #define QEMU_XIO3130_UPSTREAM_H
 
-#include "pci/pcie_port.h"
+#include "hw/pci/pcie_port.h"
 
 PCIEPort *xio3130_upstream_init(PCIBus *bus, int devfn, bool multifunction,
                                 const char *bus_name, pci_map_irq_fn map_irq,
diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c
index a810b9e..f2a63d8 100644
--- a/hw/xtensa_lx60.c
+++ b/hw/xtensa_lx60.c
@@ -26,18 +26,18 @@
  */
 
 #include "sysemu/sysemu.h"
-#include "boards.h"
-#include "loader.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
 #include "elf.h"
 #include "exec/memory.h"
 #include "exec/address-spaces.h"
-#include "serial.h"
+#include "hw/serial.h"
 #include "net/net.h"
-#include "sysbus.h"
-#include "flash.h"
+#include "hw/sysbus.h"
+#include "hw/flash.h"
 #include "sysemu/blockdev.h"
 #include "char/char.h"
-#include "xtensa_bootparam.h"
+#include "hw/xtensa_bootparam.h"
 
 typedef struct LxBoardDesc {
     size_t flash_size;
diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c
index 97d36be..f485a14 100644
--- a/hw/xtensa_pic.c
+++ b/hw/xtensa_pic.c
@@ -25,7 +25,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/log.h"
 #include "qemu/timer.h"
 
diff --git a/hw/xtensa_sim.c b/hw/xtensa_sim.c
index 864e57c..5241f8d 100644
--- a/hw/xtensa_sim.c
+++ b/hw/xtensa_sim.c
@@ -26,8 +26,8 @@
  */
 
 #include "sysemu/sysemu.h"
-#include "boards.h"
-#include "loader.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
 #include "elf.h"
 #include "exec/memory.h"
 #include "exec/address-spaces.h"
diff --git a/hw/z2.c b/hw/z2.c
index 731550f..cbb6d80 100644
--- a/hw/z2.c
+++ b/hw/z2.c
@@ -11,15 +11,15 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
-#include "hw.h"
-#include "pxa.h"
-#include "arm-misc.h"
-#include "devices.h"
-#include "i2c.h"
-#include "ssi.h"
-#include "boards.h"
+#include "hw/hw.h"
+#include "hw/pxa.h"
+#include "hw/arm-misc.h"
+#include "hw/devices.h"
+#include "hw/i2c.h"
+#include "hw/ssi.h"
+#include "hw/boards.h"
 #include "sysemu/sysemu.h"
-#include "flash.h"
+#include "hw/flash.h"
 #include "sysemu/blockdev.h"
 #include "ui/console.h"
 #include "audio/audio.h"
diff --git a/hw/zaurus.c b/hw/zaurus.c
index 2defe3b..7d3258c 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -15,9 +15,9 @@
  * 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.h"
-#include "sharpsl.h"
-#include "sysbus.h"
+#include "hw/hw.h"
+#include "hw/sharpsl.h"
+#include "hw/sysbus.h"
 
 #undef REG_FMT
 #define REG_FMT			"0x%02lx"
diff --git a/hw/zynq_slcr.c b/hw/zynq_slcr.c
index 27b00f0..8418327 100644
--- a/hw/zynq_slcr.c
+++ b/hw/zynq_slcr.c
@@ -14,9 +14,9 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hw.h"
+#include "hw/hw.h"
 #include "qemu/timer.h"
-#include "sysbus.h"
+#include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 
 #ifdef ZYNQ_ARM_SLCR_ERR_DEBUG
commit 7948b4b009b60c6e3b21daad29088b204ddb1966
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sun Feb 3 20:18:28 2013 +0100

    ppc: do not use ../ in include files
    
    This simplifies the scripted execution of the next patch.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/ppc/e500-ccsr.h b/hw/ppc/e500-ccsr.h
index f20f51b..12a2ba4 100644
--- a/hw/ppc/e500-ccsr.h
+++ b/hw/ppc/e500-ccsr.h
@@ -1,7 +1,7 @@
 #ifndef E500_CCSR_H
 #define E500_CCSR_H
 
-#include "../sysbus.h"
+#include "hw/sysbus.h"
 
 typedef struct PPCE500CCSRState {
     /*< private >*/
diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c
index 25ac4b1..4b30575 100644
--- a/hw/ppc/e500plat.c
+++ b/hw/ppc/e500plat.c
@@ -12,7 +12,7 @@
 #include "config.h"
 #include "qemu-common.h"
 #include "e500.h"
-#include "../boards.h"
+#include "hw/boards.h"
 #include "sysemu/device_tree.h"
 #include "hw/pci/pci.h"
 #include "hw/openpic.h"
diff --git a/hw/ppc/mpc8544ds.c b/hw/ppc/mpc8544ds.c
index e25c70b..cf29788 100644
--- a/hw/ppc/mpc8544ds.c
+++ b/hw/ppc/mpc8544ds.c
@@ -12,7 +12,7 @@
 #include "config.h"
 #include "qemu-common.h"
 #include "e500.h"
-#include "../boards.h"
+#include "hw/boards.h"
 #include "sysemu/device_tree.h"
 #include "hw/openpic.h"
 
commit eac7ec7f6a5c9e1a0a082ea8525f31549b1f0cb4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Feb 4 15:00:38 2013 +0100

    vt82c686: vt82c686 is not a PCI host bridge
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 2d8e398..c2b1bfc 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -26,8 +26,6 @@
 #include "qemu/timer.h"
 #include "exec/address-spaces.h"
 
-typedef uint32_t pci_addr_t;
-#include "pci/pci_host.h"
 //#define DEBUG_VT82C686B
 
 #ifdef DEBUG_VT82C686B
commit 60653b28f505288689d0b44218de4bb9fd254519
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Feb 4 15:37:49 2013 +0100

    virtio-9p: remove PCI dependencies from hw/9pfs/
    
    Also move the 9p.h file to 9pfs/virtio-9p-device.h, for consistency
    with the corresponding .c file.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/9p.h b/hw/9p.h
deleted file mode 100644
index d9951d6..0000000
--- a/hw/9p.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Virtio 9p
- *
- * Copyright IBM, Corp. 2010
- *
- * Authors:
- *  Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
- *
- */
-
-#ifndef QEMU_9P_H
-#define QEMU_9P_H
-
-typedef struct V9fsConf
-{
-    /* tag name for the device */
-    char *tag;
-    char *fsdev_id;
-} V9fsConf;
-
-#endif
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 74155fb..d321c80 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -14,9 +14,9 @@
 #include "hw/virtio.h"
 #include "hw/pc.h"
 #include "qemu/sockets.h"
-#include "hw/virtio-pci.h"
 #include "virtio-9p.h"
 #include "fsdev/qemu-fsdev.h"
+#include "virtio-9p-device.h"
 #include "virtio-9p-xattr.h"
 #include "virtio-9p-coth.h"
 
@@ -136,54 +136,3 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
 
     return &s->vdev;
 }
-
-static int virtio_9p_init_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-    VirtIODevice *vdev;
-
-    vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
-    vdev->nvectors = proxy->nvectors;
-    virtio_init_pci(proxy, vdev);
-    /* make the actual value visible */
-    proxy->nvectors = vdev->nvectors;
-    return 0;
-}
-
-static Property virtio_9p_properties[] = {
-    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
-    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
-    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
-    DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
-    DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void virtio_9p_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = virtio_9p_init_pci;
-    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
-    k->device_id = PCI_DEVICE_ID_VIRTIO_9P;
-    k->revision = VIRTIO_PCI_ABI_VERSION;
-    k->class_id = 0x2;
-    dc->props = virtio_9p_properties;
-    dc->reset = virtio_pci_reset;
-}
-
-static const TypeInfo virtio_9p_info = {
-    .name          = "virtio-9p-pci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(VirtIOPCIProxy),
-    .class_init    = virtio_9p_class_init,
-};
-
-static void virtio_9p_register_types(void)
-{
-    type_register_static(&virtio_9p_info);
-    virtio_9p_set_fd_limit();
-}
-
-type_init(virtio_9p_register_types)
diff --git a/hw/9pfs/virtio-9p-device.h b/hw/9pfs/virtio-9p-device.h
new file mode 100644
index 0000000..65789db
--- /dev/null
+++ b/hw/9pfs/virtio-9p-device.h
@@ -0,0 +1,24 @@
+/*
+ * Virtio 9p
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Aneesh Kumar K.V <aneesh.kumar at linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_VIRTIO_9P_DEVICE_H
+#define QEMU_VIRTIO_9P_DEVICE_H
+
+typedef struct V9fsConf
+{
+    /* tag name for the device */
+    char *tag;
+    char *fsdev_id;
+} V9fsConf;
+
+#endif
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index d3ea820..5cc4c92 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -14,7 +14,6 @@
 #include "hw/virtio.h"
 #include "hw/pc.h"
 #include "qemu/sockets.h"
-#include "hw/virtio-pci.h"
 #include "virtio-9p.h"
 #include "fsdev/qemu-fsdev.h"
 #include "virtio-9p-xattr.h"
@@ -3269,7 +3268,7 @@ void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
     free_pdu(s, pdu);
 }
 
-void virtio_9p_set_fd_limit(void)
+static void __attribute__((__constructor__)) virtio_9p_set_fd_limit(void)
 {
     struct rlimit rlim;
     if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 406fe52..52b1c69 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -389,7 +389,6 @@ static inline uint8_t v9fs_request_cancelled(V9fsPDU *pdu)
 }
 
 extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq);
-extern void virtio_9p_set_fd_limit(void);
 extern void v9fs_reclaim_fd(V9fsPDU *pdu);
 extern void v9fs_path_init(V9fsPath *path);
 extern void v9fs_path_free(V9fsPath *path);
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index a869f53..df1dd77 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -255,7 +255,7 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
     proxy->ioeventfd_started = false;
 }
 
-void virtio_pci_reset(DeviceState *d)
+static void virtio_pci_reset(DeviceState *d)
 {
     VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
     virtio_pci_stop_ioeventfd(proxy);
@@ -1313,6 +1313,51 @@ static const TypeInfo virtio_scsi_info = {
     .class_init    = virtio_scsi_class_init,
 };
 
+#ifdef CONFIG_VIRTFS
+static int virtio_9p_init_pci(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+    VirtIODevice *vdev;
+
+    vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
+    vdev->nvectors = proxy->nvectors;
+    virtio_init_pci(proxy, vdev);
+    /* make the actual value visible */
+    proxy->nvectors = vdev->nvectors;
+    return 0;
+}
+
+static Property virtio_9p_properties[] = {
+    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
+    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
+    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
+    DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_9p_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = virtio_9p_init_pci;
+    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    k->device_id = PCI_DEVICE_ID_VIRTIO_9P;
+    k->revision = VIRTIO_PCI_ABI_VERSION;
+    k->class_id = 0x2;
+    dc->props = virtio_9p_properties;
+    dc->reset = virtio_pci_reset;
+}
+
+static const TypeInfo virtio_9p_info = {
+    .name          = "virtio-9p-pci",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(VirtIOPCIProxy),
+    .class_init    = virtio_9p_class_init,
+};
+#endif
+
 /*
  * virtio-pci: This is the PCIDevice which has a virtio-pci-bus.
  */
@@ -1475,6 +1520,9 @@ static void virtio_pci_register_types(void)
     type_register_static(&virtio_rng_info);
     type_register_static(&virtio_pci_bus_info);
     type_register_static(&virtio_pci_info);
+#ifdef CONFIG_VIRTFS
+    type_register_static(&virtio_9p_info);
+#endif
 }
 
 type_init(virtio_pci_register_types)
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index e775525..d01db97 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -22,6 +22,7 @@
 #include "virtio-serial.h"
 #include "virtio-scsi.h"
 #include "virtio-bus.h"
+#include "9pfs/virtio-9p-device.h"
 
 typedef struct VirtIOPCIProxy VirtIOPCIProxy;
 
@@ -90,7 +91,6 @@ struct VirtIOPCIProxy {
 };
 
 void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
-void virtio_pci_reset(DeviceState *d);
 void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev);
 
 /* Virtio ABI version, if we increment this, we break the guest driver. */
diff --git a/hw/virtio.h b/hw/virtio.h
index ae43d25..8cc71e9 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -20,7 +20,7 @@
 #include "sysemu/sysemu.h"
 #include "qemu/event_notifier.h"
 #ifdef CONFIG_VIRTFS
-#include "9p.h"
+#include "9pfs/virtio-9p-device.h"
 #endif
 
 /* from Linux's linux/virtio_config.h */
commit 7e6b14dfb575a687cb26be9995c96e5bbf5cba2e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Feb 4 15:32:02 2013 +0100

    virtio-9p: use CONFIG_VIRTFS, not CONFIG_LINUX
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index d24957c..e775525 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -75,7 +75,7 @@ struct VirtIOPCIProxy {
     VirtIOBlkConf blk;
     NICConf nic;
     uint32_t host_features;
-#ifdef CONFIG_LINUX
+#ifdef CONFIG_VIRTFS
     V9fsConf fsconf;
 #endif
     virtio_serial_conf serial;
diff --git a/hw/virtio.h b/hw/virtio.h
index 1e206b8..ae43d25 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -19,7 +19,7 @@
 #include "qdev.h"
 #include "sysemu/sysemu.h"
 #include "qemu/event_notifier.h"
-#ifdef CONFIG_LINUX
+#ifdef CONFIG_VIRTFS
 #include "9p.h"
 #endif
 
@@ -252,7 +252,7 @@ typedef struct VirtIOSCSIConf VirtIOSCSIConf;
 VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *conf);
 typedef struct VirtIORNGConf VirtIORNGConf;
 VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf);
-#ifdef CONFIG_LINUX
+#ifdef CONFIG_VIRTFS
 VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
 #endif
 
commit 1559e0d4b54d1b0744983b57da893617ceae8b94
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Feb 4 17:20:47 2013 +0100

    hw: move device-hotplug.o to toplevel, compile it once
    
    The situation with device-hotplug.c is similar to qdev-monitor.c.
    Add a stub for pci_drive_hot_add, so that it can be compiled once,
    and move it out of hw/.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 2a8174d..8c90b92 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -51,7 +51,7 @@ ifeq ($(CONFIG_SOFTMMU),y)
 common-obj-y = $(block-obj-y) blockdev.o blockdev-nbd.o block/
 common-obj-y += net/
 common-obj-y += readline.o
-common-obj-y += qdev-monitor.o
+common-obj-y += qdev-monitor.o device-hotplug.o
 common-obj-$(CONFIG_WIN32) += os-win32.o
 common-obj-$(CONFIG_POSIX) += os-posix.o
 
diff --git a/device-hotplug.c b/device-hotplug.c
new file mode 100644
index 0000000..103d34a
--- /dev/null
+++ b/device-hotplug.c
@@ -0,0 +1,79 @@
+/*
+ * QEMU device hotplug helpers
+ *
+ * Copyright (c) 2004 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 "hw/hw.h"
+#include "hw/boards.h"
+#include "sysemu/blockdev.h"
+#include "qemu/config-file.h"
+#include "sysemu/sysemu.h"
+#include "monitor/monitor.h"
+
+DriveInfo *add_init_drive(const char *optstr)
+{
+    DriveInfo *dinfo;
+    QemuOpts *opts;
+
+    opts = drive_def(optstr);
+    if (!opts)
+        return NULL;
+
+    dinfo = drive_init(opts, current_machine->block_default_type);
+    if (!dinfo) {
+        qemu_opts_del(opts);
+        return NULL;
+    }
+
+    return dinfo;
+}
+
+void drive_hot_add(Monitor *mon, const QDict *qdict)
+{
+    DriveInfo *dinfo = NULL;
+    const char *opts = qdict_get_str(qdict, "opts");
+
+    dinfo = add_init_drive(opts);
+    if (!dinfo) {
+        goto err;
+    }
+    if (dinfo->devaddr) {
+        monitor_printf(mon, "Parameter addr not supported\n");
+        goto err;
+    }
+
+    switch (dinfo->type) {
+    case IF_NONE:
+        monitor_printf(mon, "OK\n");
+        break;
+    default:
+        if (pci_drive_hot_add(mon, qdict, dinfo)) {
+            goto err;
+        }
+    }
+    return;
+
+err:
+    if (dinfo) {
+        drive_put_ref(dinfo);
+    }
+}
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index f7ee133..43f467a 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -206,7 +206,6 @@ obj-$(CONFIG_SOFTMMU) += vhost_net.o
 obj-$(CONFIG_VHOST_NET) += vhost.o
 obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/
 obj-$(CONFIG_VGA) += vga.o
-obj-$(CONFIG_SOFTMMU) += device-hotplug.o
 obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
 
 # Inter-VM PCI shared memory & VFIO PCI device assignment
diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
deleted file mode 100644
index 88da145..0000000
--- a/hw/device-hotplug.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * QEMU device hotplug helpers
- *
- * Copyright (c) 2004 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 "hw.h"
-#include "boards.h"
-#include "sysemu/blockdev.h"
-#include "qemu/config-file.h"
-#include "sysemu/sysemu.h"
-#include "monitor/monitor.h"
-
-DriveInfo *add_init_drive(const char *optstr)
-{
-    DriveInfo *dinfo;
-    QemuOpts *opts;
-
-    opts = drive_def(optstr);
-    if (!opts)
-        return NULL;
-
-    dinfo = drive_init(opts, current_machine->block_default_type);
-    if (!dinfo) {
-        qemu_opts_del(opts);
-        return NULL;
-    }
-
-    return dinfo;
-}
-
-#if !defined(TARGET_I386)
-int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo)
-{
-    /* On non-x86 we don't do PCI hotplug */
-    monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type);
-    return -1;
-}
-#endif
-
-void drive_hot_add(Monitor *mon, const QDict *qdict)
-{
-    DriveInfo *dinfo = NULL;
-    const char *opts = qdict_get_str(qdict, "opts");
-
-    dinfo = add_init_drive(opts);
-    if (!dinfo) {
-        goto err;
-    }
-    if (dinfo->devaddr) {
-        monitor_printf(mon, "Parameter addr not supported\n");
-        goto err;
-    }
-
-    switch (dinfo->type) {
-    case IF_NONE:
-        monitor_printf(mon, "OK\n");
-        break;
-    default:
-        if (pci_drive_hot_add(mon, qdict, dinfo)) {
-            goto err;
-        }
-    }
-    return;
-
-err:
-    if (dinfo) {
-        drive_put_ref(dinfo);
-    }
-}
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index a260394..9c55b34 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -15,6 +15,7 @@ stub-obj-y += mon-printf.o
 stub-obj-y += mon-print-filename.o
 stub-obj-y += mon-protocol-event.o
 stub-obj-y += mon-set-error.o
+stub-obj-y += pci-drive-hot-add.o
 stub-obj-y += reset.o
 stub-obj-y += set-fd-handler.o
 stub-obj-y += slirp.o
diff --git a/stubs/pci-drive-hot-add.c b/stubs/pci-drive-hot-add.c
new file mode 100644
index 0000000..1d98145
--- /dev/null
+++ b/stubs/pci-drive-hot-add.c
@@ -0,0 +1,10 @@
+#include <monitor/monitor.h>
+#include <sysemu/sysemu.h>
+#include <sysemu/blockdev.h>
+
+int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo)
+{
+    /* On non-x86 we don't do PCI hotplug */
+    monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type);
+    return -1;
+}
commit b4a42f81383d60900aae09513f42eb857a5a7c7c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Feb 4 11:37:52 2013 +0100

    hw: move qdev-monitor.o to toplevel directory
    
    qdev-monitor.c is the only "core qdev" file that is not used in
    user-mode emulation, and it does not define anything that is used
    by hardware models.  Remove it from the hw/ directory and
    remove hw/qdev-monitor.h from hw/qdev.h too; this requires
    some files to have some new explicitly includes.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index a68cdac..2a8174d 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -51,6 +51,7 @@ ifeq ($(CONFIG_SOFTMMU),y)
 common-obj-y = $(block-obj-y) blockdev.o blockdev-nbd.o block/
 common-obj-y += net/
 common-obj-y += readline.o
+common-obj-y += qdev-monitor.o
 common-obj-$(CONFIG_WIN32) += os-win32.o
 common-obj-$(CONFIG_POSIX) += os-posix.o
 
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 54e9875..7300279 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -13,6 +13,7 @@
 #include <sys/un.h>
 #include "hw/virtio.h"
 #include "virtio-9p.h"
+#include "qemu/error-report.h"
 #include "fsdev/qemu-fsdev.h"
 #include "virtio-9p-proxy.h"
 
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 6e2275b..f7ee133 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -190,7 +190,6 @@ common-obj-$(CONFIG_SD) += sd.o
 common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o
 common-obj-y += bt-hci-csr.o
 common-obj-y += ps2.o
-common-obj-y += qdev-monitor.o
 common-obj-y += qdev-properties-system.o
 
 # xen backend driver support
diff --git a/hw/dataplane/virtio-blk.c b/hw/dataplane/virtio-blk.c
index 3f2da22..8588f93 100644
--- a/hw/dataplane/virtio-blk.c
+++ b/hw/dataplane/virtio-blk.c
@@ -16,9 +16,11 @@
 #include "qemu/iov.h"
 #include "event-poll.h"
 #include "qemu/thread.h"
+#include "qemu/error-report.h"
 #include "vring.h"
 #include "ioq.h"
 #include "migration/migration.h"
+#include "block/block.h"
 #include "hw/virtio-blk.h"
 #include "hw/dataplane/virtio-blk.h"
 
diff --git a/hw/dataplane/vring.c b/hw/dataplane/vring.c
index d5d4ef4..eff5ad8 100644
--- a/hw/dataplane/vring.c
+++ b/hw/dataplane/vring.c
@@ -16,6 +16,7 @@
 
 #include "trace.h"
 #include "hw/dataplane/vring.h"
+#include "qemu/error-report.h"
 
 /* Map the guest's vring to host memory */
 bool vring_setup(Vring *vring, VirtIODevice *vdev, int n)
diff --git a/hw/pc87312.c b/hw/pc87312.c
index 38af4c1..0e9760e 100644
--- a/hw/pc87312.c
+++ b/hw/pc87312.c
@@ -24,6 +24,7 @@
  */
 
 #include "pc87312.h"
+#include "qemu/error-report.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/sysemu.h"
 #include "char/char.h"
diff --git a/hw/pc_sysfw.c b/hw/pc_sysfw.c
index 7f6c12c..8b65a7a 100644
--- a/hw/pc_sysfw.c
+++ b/hw/pc_sysfw.c
@@ -24,6 +24,7 @@
  */
 
 #include "sysemu/blockdev.h"
+#include "qemu/error-report.h"
 #include "sysbus.h"
 #include "hw.h"
 #include "pc.h"
diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
index f07266d..d35c2ee 100644
--- a/hw/pci/shpc.c
+++ b/hw/pci/shpc.c
@@ -1,7 +1,8 @@
+#include "qemu-common.h"
 #include <strings.h>
 #include <stdint.h>
 #include "qemu/range.h"
-#include "qemu/range.h"
+#include "qemu/error-report.h"
 #include "hw/pci/shpc.h"
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_bus.h"
diff --git a/hw/pci/slotid_cap.c b/hw/pci/slotid_cap.c
index 99a30f4..62f7bae 100644
--- a/hw/pci/slotid_cap.c
+++ b/hw/pci/slotid_cap.c
@@ -1,5 +1,6 @@
 #include "hw/pci/slotid_cap.h"
 #include "hw/pci/pci.h"
+#include "qemu/error-report.h"
 
 #define SLOTID_CAP_LENGTH 4
 #define SLOTID_NSLOTS_SHIFT (ffs(PCI_SID_ESR_NSLOTS) - 1)
diff --git a/hw/qdev-addr.c b/hw/qdev-addr.c
index b4388f6..fc2c437 100644
--- a/hw/qdev-addr.c
+++ b/hw/qdev-addr.c
@@ -1,6 +1,7 @@
 #include "qdev.h"
 #include "qdev-addr.h"
 #include "exec/hwaddr.h"
+#include "qapi/qmp/qerror.h"
 #include "qapi/visitor.h"
 
 /* --- target physical address --- */
diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c
deleted file mode 100644
index 4f9a6eb..0000000
--- a/hw/qdev-monitor.c
+++ /dev/null
@@ -1,683 +0,0 @@
-/*
- *  Dynamic device configuration and creation.
- *
- *  Copyright (c) 2009 CodeSourcery
- *
- * 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 "qdev.h"
-#include "monitor/monitor.h"
-#include "qmp-commands.h"
-#include "sysemu/arch_init.h"
-#include "qemu/config-file.h"
-
-/*
- * Aliases were a bad idea from the start.  Let's keep them
- * from spreading further.
- */
-typedef struct QDevAlias
-{
-    const char *typename;
-    const char *alias;
-    uint32_t arch_mask;
-} QDevAlias;
-
-static const QDevAlias qdev_alias_table[] = {
-    { "virtio-blk-pci", "virtio-blk", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
-    { "virtio-net-pci", "virtio-net", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
-    { "virtio-serial-pci", "virtio-serial", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
-    { "virtio-balloon-pci", "virtio-balloon",
-            QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
-    { "virtio-blk-s390", "virtio-blk", QEMU_ARCH_S390X },
-    { "virtio-net-s390", "virtio-net", QEMU_ARCH_S390X },
-    { "virtio-serial-s390", "virtio-serial", QEMU_ARCH_S390X },
-    { "lsi53c895a", "lsi" },
-    { "ich9-ahci", "ahci" },
-    { "kvm-pci-assign", "pci-assign" },
-    { }
-};
-
-static const char *qdev_class_get_alias(DeviceClass *dc)
-{
-    const char *typename = object_class_get_name(OBJECT_CLASS(dc));
-    int i;
-
-    for (i = 0; qdev_alias_table[i].typename; i++) {
-        if (qdev_alias_table[i].arch_mask &&
-            !(qdev_alias_table[i].arch_mask & arch_type)) {
-            continue;
-        }
-
-        if (strcmp(qdev_alias_table[i].typename, typename) == 0) {
-            return qdev_alias_table[i].alias;
-        }
-    }
-
-    return NULL;
-}
-
-static bool qdev_class_has_alias(DeviceClass *dc)
-{
-    return (qdev_class_get_alias(dc) != NULL);
-}
-
-static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
-{
-    DeviceClass *dc;
-    bool *show_no_user = opaque;
-
-    dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE);
-
-    if (!dc || (show_no_user && !*show_no_user && dc->no_user)) {
-        return;
-    }
-
-    error_printf("name \"%s\"", object_class_get_name(klass));
-    if (dc->bus_type) {
-        error_printf(", bus %s", dc->bus_type);
-    }
-    if (qdev_class_has_alias(dc)) {
-        error_printf(", alias \"%s\"", qdev_class_get_alias(dc));
-    }
-    if (dc->desc) {
-        error_printf(", desc \"%s\"", dc->desc);
-    }
-    if (dc->no_user) {
-        error_printf(", no-user");
-    }
-    error_printf("\n");
-}
-
-static int set_property(const char *name, const char *value, void *opaque)
-{
-    DeviceState *dev = opaque;
-
-    if (strcmp(name, "driver") == 0)
-        return 0;
-    if (strcmp(name, "bus") == 0)
-        return 0;
-
-    if (qdev_prop_parse(dev, name, value) == -1) {
-        return -1;
-    }
-    return 0;
-}
-
-static const char *find_typename_by_alias(const char *alias)
-{
-    int i;
-
-    for (i = 0; qdev_alias_table[i].alias; i++) {
-        if (qdev_alias_table[i].arch_mask &&
-            !(qdev_alias_table[i].arch_mask & arch_type)) {
-            continue;
-        }
-
-        if (strcmp(qdev_alias_table[i].alias, alias) == 0) {
-            return qdev_alias_table[i].typename;
-        }
-    }
-
-    return NULL;
-}
-
-int qdev_device_help(QemuOpts *opts)
-{
-    const char *driver;
-    Property *prop;
-    ObjectClass *klass;
-
-    driver = qemu_opt_get(opts, "driver");
-    if (driver && is_help_option(driver)) {
-        bool show_no_user = false;
-        object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user);
-        return 1;
-    }
-
-    if (!driver || !qemu_opt_has_help_opt(opts)) {
-        return 0;
-    }
-
-    klass = object_class_by_name(driver);
-    if (!klass) {
-        const char *typename = find_typename_by_alias(driver);
-
-        if (typename) {
-            driver = typename;
-            klass = object_class_by_name(driver);
-        }
-    }
-
-    if (!klass) {
-        return 0;
-    }
-    do {
-        for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) {
-            /*
-             * TODO Properties without a parser are just for dirty hacks.
-             * qdev_prop_ptr is the only such PropertyInfo.  It's marked
-             * for removal.  This conditional should be removed along with
-             * it.
-             */
-            if (!prop->info->set) {
-                continue;           /* no way to set it, don't show */
-            }
-            error_printf("%s.%s=%s\n", driver, prop->name,
-                         prop->info->legacy_name ?: prop->info->name);
-        }
-        klass = object_class_get_parent(klass);
-    } while (klass != object_class_by_name(TYPE_DEVICE));
-    return 1;
-}
-
-static Object *qdev_get_peripheral(void)
-{
-    static Object *dev;
-
-    if (dev == NULL) {
-        dev = container_get(qdev_get_machine(), "/peripheral");
-    }
-
-    return dev;
-}
-
-static Object *qdev_get_peripheral_anon(void)
-{
-    static Object *dev;
-
-    if (dev == NULL) {
-        dev = container_get(qdev_get_machine(), "/peripheral-anon");
-    }
-
-    return dev;
-}
-
-static void qbus_list_bus(DeviceState *dev)
-{
-    BusState *child;
-    const char *sep = " ";
-
-    error_printf("child busses at \"%s\":",
-                 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
-    QLIST_FOREACH(child, &dev->child_bus, sibling) {
-        error_printf("%s\"%s\"", sep, child->name);
-        sep = ", ";
-    }
-    error_printf("\n");
-}
-
-static void qbus_list_dev(BusState *bus)
-{
-    BusChild *kid;
-    const char *sep = " ";
-
-    error_printf("devices at \"%s\":", bus->name);
-    QTAILQ_FOREACH(kid, &bus->children, sibling) {
-        DeviceState *dev = kid->child;
-        error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
-        if (dev->id)
-            error_printf("/\"%s\"", dev->id);
-        sep = ", ";
-    }
-    error_printf("\n");
-}
-
-static BusState *qbus_find_bus(DeviceState *dev, char *elem)
-{
-    BusState *child;
-
-    QLIST_FOREACH(child, &dev->child_bus, sibling) {
-        if (strcmp(child->name, elem) == 0) {
-            return child;
-        }
-    }
-    return NULL;
-}
-
-static DeviceState *qbus_find_dev(BusState *bus, char *elem)
-{
-    BusChild *kid;
-
-    /*
-     * try to match in order:
-     *   (1) instance id, if present
-     *   (2) driver name
-     *   (3) driver alias, if present
-     */
-    QTAILQ_FOREACH(kid, &bus->children, sibling) {
-        DeviceState *dev = kid->child;
-        if (dev->id  &&  strcmp(dev->id, elem) == 0) {
-            return dev;
-        }
-    }
-    QTAILQ_FOREACH(kid, &bus->children, sibling) {
-        DeviceState *dev = kid->child;
-        if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
-            return dev;
-        }
-    }
-    QTAILQ_FOREACH(kid, &bus->children, sibling) {
-        DeviceState *dev = kid->child;
-        DeviceClass *dc = DEVICE_GET_CLASS(dev);
-
-        if (qdev_class_has_alias(dc) &&
-            strcmp(qdev_class_get_alias(dc), elem) == 0) {
-            return dev;
-        }
-    }
-    return NULL;
-}
-
-static BusState *qbus_find_recursive(BusState *bus, const char *name,
-                                     const char *bus_typename)
-{
-    BusClass *bus_class = BUS_GET_CLASS(bus);
-    BusChild *kid;
-    BusState *child, *ret;
-    int match = 1;
-
-    if (name && (strcmp(bus->name, name) != 0)) {
-        match = 0;
-    }
-    if (bus_typename && !object_dynamic_cast(OBJECT(bus), bus_typename)) {
-        match = 0;
-    }
-    if ((bus_class->max_dev != 0) && (bus_class->max_dev <= bus->max_index)) {
-        if (name != NULL) {
-            /* bus was explicitly specified: return an error. */
-            qerror_report(ERROR_CLASS_GENERIC_ERROR, "Bus '%s' is full",
-                          bus->name);
-            return NULL;
-        } else {
-            /* bus was not specified: try to find another one. */
-            match = 0;
-        }
-    }
-    if (match) {
-        return bus;
-    }
-
-    QTAILQ_FOREACH(kid, &bus->children, sibling) {
-        DeviceState *dev = kid->child;
-        QLIST_FOREACH(child, &dev->child_bus, sibling) {
-            ret = qbus_find_recursive(child, name, bus_typename);
-            if (ret) {
-                return ret;
-            }
-        }
-    }
-    return NULL;
-}
-
-static BusState *qbus_find(const char *path)
-{
-    DeviceState *dev;
-    BusState *bus;
-    char elem[128];
-    int pos, len;
-
-    /* find start element */
-    if (path[0] == '/') {
-        bus = sysbus_get_default();
-        pos = 0;
-    } else {
-        if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
-            assert(!path[0]);
-            elem[0] = len = 0;
-        }
-        bus = qbus_find_recursive(sysbus_get_default(), elem, NULL);
-        if (!bus) {
-            qerror_report(QERR_BUS_NOT_FOUND, elem);
-            return NULL;
-        }
-        pos = len;
-    }
-
-    for (;;) {
-        assert(path[pos] == '/' || !path[pos]);
-        while (path[pos] == '/') {
-            pos++;
-        }
-        if (path[pos] == '\0') {
-            return bus;
-        }
-
-        /* find device */
-        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
-            assert(0);
-            elem[0] = len = 0;
-        }
-        pos += len;
-        dev = qbus_find_dev(bus, elem);
-        if (!dev) {
-            qerror_report(QERR_DEVICE_NOT_FOUND, elem);
-            if (!monitor_cur_is_qmp()) {
-                qbus_list_dev(bus);
-            }
-            return NULL;
-        }
-
-        assert(path[pos] == '/' || !path[pos]);
-        while (path[pos] == '/') {
-            pos++;
-        }
-        if (path[pos] == '\0') {
-            /* last specified element is a device.  If it has exactly
-             * one child bus accept it nevertheless */
-            switch (dev->num_child_bus) {
-            case 0:
-                qerror_report(QERR_DEVICE_NO_BUS, elem);
-                return NULL;
-            case 1:
-                return QLIST_FIRST(&dev->child_bus);
-            default:
-                qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
-                if (!monitor_cur_is_qmp()) {
-                    qbus_list_bus(dev);
-                }
-                return NULL;
-            }
-        }
-
-        /* find bus */
-        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
-            assert(0);
-            elem[0] = len = 0;
-        }
-        pos += len;
-        bus = qbus_find_bus(dev, elem);
-        if (!bus) {
-            qerror_report(QERR_BUS_NOT_FOUND, elem);
-            if (!monitor_cur_is_qmp()) {
-                qbus_list_bus(dev);
-            }
-            return NULL;
-        }
-    }
-}
-
-DeviceState *qdev_device_add(QemuOpts *opts)
-{
-    ObjectClass *obj;
-    DeviceClass *k;
-    const char *driver, *path, *id;
-    DeviceState *qdev;
-    BusState *bus;
-
-    driver = qemu_opt_get(opts, "driver");
-    if (!driver) {
-        qerror_report(QERR_MISSING_PARAMETER, "driver");
-        return NULL;
-    }
-
-    /* find driver */
-    obj = object_class_by_name(driver);
-    if (!obj) {
-        const char *typename = find_typename_by_alias(driver);
-
-        if (typename) {
-            driver = typename;
-            obj = object_class_by_name(driver);
-        }
-    }
-
-    if (!obj) {
-        qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
-        return NULL;
-    }
-
-    k = DEVICE_CLASS(obj);
-
-    /* find bus */
-    path = qemu_opt_get(opts, "bus");
-    if (path != NULL) {
-        bus = qbus_find(path);
-        if (!bus) {
-            return NULL;
-        }
-        if (!object_dynamic_cast(OBJECT(bus), k->bus_type)) {
-            qerror_report(QERR_BAD_BUS_FOR_DEVICE,
-                          driver, object_get_typename(OBJECT(bus)));
-            return NULL;
-        }
-    } else {
-        bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_type);
-        if (!bus) {
-            qerror_report(QERR_NO_BUS_FOR_DEVICE,
-                          k->bus_type, driver);
-            return NULL;
-        }
-    }
-    if (qdev_hotplug && !bus->allow_hotplug) {
-        qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
-        return NULL;
-    }
-
-    if (!bus) {
-        bus = sysbus_get_default();
-    }
-
-    /* create device, set properties */
-    qdev = DEVICE(object_new(driver));
-    qdev_set_parent_bus(qdev, bus);
-
-    id = qemu_opts_id(opts);
-    if (id) {
-        qdev->id = id;
-    }
-    if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
-        qdev_free(qdev);
-        return NULL;
-    }
-    if (qdev->id) {
-        object_property_add_child(qdev_get_peripheral(), qdev->id,
-                                  OBJECT(qdev), NULL);
-    } else {
-        static int anon_count;
-        gchar *name = g_strdup_printf("device[%d]", anon_count++);
-        object_property_add_child(qdev_get_peripheral_anon(), name,
-                                  OBJECT(qdev), NULL);
-        g_free(name);
-    }        
-    if (qdev_init(qdev) < 0) {
-        qerror_report(QERR_DEVICE_INIT_FAILED, driver);
-        return NULL;
-    }
-    qdev->opts = opts;
-    return qdev;
-}
-
-
-#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
-static void qbus_print(Monitor *mon, BusState *bus, int indent);
-
-static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
-                             int indent)
-{
-    if (!props)
-        return;
-    for (; props->name; props++) {
-        Error *err = NULL;
-        char *value;
-        char *legacy_name = g_strdup_printf("legacy-%s", props->name);
-        if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
-            value = object_property_get_str(OBJECT(dev), legacy_name, &err);
-        } else {
-            value = object_property_print(OBJECT(dev), props->name, &err);
-        }
-        g_free(legacy_name);
-
-        if (err) {
-            error_free(err);
-            continue;
-        }
-        qdev_printf("%s = %s\n", props->name,
-                    value && *value ? value : "<null>");
-        g_free(value);
-    }
-}
-
-static void bus_print_dev(BusState *bus, Monitor *mon, DeviceState *dev, int indent)
-{
-    BusClass *bc = BUS_GET_CLASS(bus);
-
-    if (bc->print_dev) {
-        bc->print_dev(mon, dev, indent);
-    }
-}
-
-static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
-{
-    ObjectClass *class;
-    BusState *child;
-    qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
-                dev->id ? dev->id : "");
-    indent += 2;
-    if (dev->num_gpio_in) {
-        qdev_printf("gpio-in %d\n", dev->num_gpio_in);
-    }
-    if (dev->num_gpio_out) {
-        qdev_printf("gpio-out %d\n", dev->num_gpio_out);
-    }
-    class = object_get_class(OBJECT(dev));
-    do {
-        qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent);
-        class = object_class_get_parent(class);
-    } while (class != object_class_by_name(TYPE_DEVICE));
-    bus_print_dev(dev->parent_bus, mon, dev, indent);
-    QLIST_FOREACH(child, &dev->child_bus, sibling) {
-        qbus_print(mon, child, indent);
-    }
-}
-
-static void qbus_print(Monitor *mon, BusState *bus, int indent)
-{
-    BusChild *kid;
-
-    qdev_printf("bus: %s\n", bus->name);
-    indent += 2;
-    qdev_printf("type %s\n", object_get_typename(OBJECT(bus)));
-    QTAILQ_FOREACH(kid, &bus->children, sibling) {
-        DeviceState *dev = kid->child;
-        qdev_print(mon, dev, indent);
-    }
-}
-#undef qdev_printf
-
-void do_info_qtree(Monitor *mon, const QDict *qdict)
-{
-    if (sysbus_get_default())
-        qbus_print(mon, sysbus_get_default(), 0);
-}
-
-void do_info_qdm(Monitor *mon, const QDict *qdict)
-{
-    object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, NULL);
-}
-
-int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    Error *local_err = NULL;
-    QemuOpts *opts;
-    DeviceState *dev;
-
-    opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_err);
-    if (error_is_set(&local_err)) {
-        qerror_report_err(local_err);
-        error_free(local_err);
-        return -1;
-    }
-    if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
-        qemu_opts_del(opts);
-        return 0;
-    }
-    dev = qdev_device_add(opts);
-    if (!dev) {
-        qemu_opts_del(opts);
-        return -1;
-    }
-    object_unref(OBJECT(dev));
-    return 0;
-}
-
-void qmp_device_del(const char *id, Error **errp)
-{
-    DeviceState *dev;
-
-    dev = qdev_find_recursive(sysbus_get_default(), id);
-    if (NULL == dev) {
-        error_set(errp, QERR_DEVICE_NOT_FOUND, id);
-        return;
-    }
-
-    qdev_unplug(dev, errp);
-}
-
-void qdev_machine_init(void)
-{
-    qdev_get_peripheral_anon();
-    qdev_get_peripheral();
-}
-
-QemuOptsList qemu_device_opts = {
-    .name = "device",
-    .implied_opt_name = "driver",
-    .head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head),
-    .desc = {
-        /*
-         * no elements => accept any
-         * sanity checking will happen later
-         * when setting device properties
-         */
-        { /* end of list */ }
-    },
-};
-
-QemuOptsList qemu_global_opts = {
-    .name = "global",
-    .head = QTAILQ_HEAD_INITIALIZER(qemu_global_opts.head),
-    .desc = {
-        {
-            .name = "driver",
-            .type = QEMU_OPT_STRING,
-        },{
-            .name = "property",
-            .type = QEMU_OPT_STRING,
-        },{
-            .name = "value",
-            .type = QEMU_OPT_STRING,
-        },
-        { /* end of list */ }
-    },
-};
-
-int qemu_global_option(const char *str)
-{
-    char driver[64], property[64];
-    QemuOpts *opts;
-    int rc, offset;
-
-    rc = sscanf(str, "%63[^.].%63[^=]%n", driver, property, &offset);
-    if (rc < 2 || str[offset] != '=') {
-        error_report("can't parse: \"%s\"", str);
-        return -1;
-    }
-
-    opts = qemu_opts_create_nofail(&qemu_global_opts);
-    qemu_opt_set(opts, "driver", driver);
-    qemu_opt_set(opts, "property", property);
-    qemu_opt_set(opts, "value", str+offset+1);
-    return 0;
-}
diff --git a/hw/qdev-monitor.h b/hw/qdev-monitor.h
deleted file mode 100644
index 9ec4850..0000000
--- a/hw/qdev-monitor.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef QEMU_QDEV_MONITOR_H
-#define QEMU_QDEV_MONITOR_H
-
-#include "qdev-core.h"
-#include "monitor/monitor.h"
-
-/*** monitor commands ***/
-
-void do_info_qtree(Monitor *mon, const QDict *qdict);
-void do_info_qdm(Monitor *mon, const QDict *qdict);
-int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
-int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
-int qdev_device_help(QemuOpts *opts);
-DeviceState *qdev_device_add(QemuOpts *opts);
-
-#endif
diff --git a/hw/qdev.c b/hw/qdev.c
index 689cd54..62bc899 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -28,6 +28,7 @@
 #include "qdev.h"
 #include "sysemu/sysemu.h"
 #include "qapi/error.h"
+#include "qapi/qmp/qerror.h"
 #include "qapi/visitor.h"
 
 int qdev_hotplug = 0;
diff --git a/hw/qdev.h b/hw/qdev.h
index 365b8d6..f814656 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -4,6 +4,5 @@
 #include "hw/hw.h"
 #include "qdev-core.h"
 #include "qdev-properties.h"
-#include "qdev-monitor.h"
 
 #endif
diff --git a/hw/s390x/sclpconsole.c b/hw/s390x/sclpconsole.c
index effe511..475d7ba 100644
--- a/hw/s390x/sclpconsole.c
+++ b/hw/s390x/sclpconsole.c
@@ -14,6 +14,7 @@
 
 #include <hw/qdev.h>
 #include "qemu/thread.h"
+#include "qemu/error-report.h"
 
 #include "sclp.h"
 #include "event-facility.h"
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index c08718b..5473ac2 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -27,6 +27,7 @@
 #include "hw/usb.h"
 #include "hw/usb/desc.h"
 #include "net/net.h"
+#include "qapi/qmp/qerror.h"
 #include "qemu/queue.h"
 #include "qemu/config-file.h"
 #include "sysemu/sysemu.h"
diff --git a/hw/virtio-rng.c b/hw/virtio-rng.c
index e063127..2cdf4ec 100644
--- a/hw/virtio-rng.c
+++ b/hw/virtio-rng.c
@@ -11,6 +11,7 @@
 
 #include "qemu/iov.h"
 #include "qdev.h"
+#include "qapi/qmp/qerror.h"
 #include "virtio.h"
 #include "virtio-rng.h"
 #include "qemu/rng.h"
diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 0715865..27070d1 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -14,6 +14,7 @@
  */
 
 #include "virtio-scsi.h"
+#include "qemu/error-report.h"
 #include <hw/scsi.h>
 #include <hw/scsi-defs.h>
 
diff --git a/hw/xilinx.h b/hw/xilinx.h
index 09bc2e4..a78281f 100644
--- a/hw/xilinx.h
+++ b/hw/xilinx.h
@@ -2,8 +2,9 @@
 #define HW_XILINX_H 1
 
 
-#include "stream.h"
 #include "qemu-common.h"
+#include "qapi/qmp/qerror.h"
+#include "stream.h"
 #include "net/net.h"
 
 static inline DeviceState *
diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index e5d9251..66b9ec1 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -26,6 +26,7 @@
 #include "qemu/log.h"
 #include "net/net.h"
 #include "net/checksum.h"
+#include "qapi/qmp/qerror.h"
 
 #include "stream.h"
 
diff --git a/include/monitor/qdev.h b/include/monitor/qdev.h
new file mode 100644
index 0000000..8d16e11
--- /dev/null
+++ b/include/monitor/qdev.h
@@ -0,0 +1,15 @@
+#ifndef QEMU_QDEV_MONITOR_H
+#define QEMU_QDEV_MONITOR_H
+
+#include "hw/qdev-core.h"
+#include "monitor/monitor.h"
+
+/*** monitor commands ***/
+
+void do_info_qtree(Monitor *mon, const QDict *qdict);
+void do_info_qdm(Monitor *mon, const QDict *qdict);
+int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int qdev_device_help(QemuOpts *opts);
+DeviceState *qdev_device_add(QemuOpts *opts);
+
+#endif
diff --git a/monitor.c b/monitor.c
index 32a6e74..c48530b 100644
--- a/monitor.c
+++ b/monitor.c
@@ -23,7 +23,7 @@
  */
 #include <dirent.h>
 #include "hw/hw.h"
-#include "hw/qdev.h"
+#include "monitor/qdev.h"
 #include "hw/usb.h"
 #include "hw/pcmcia.h"
 #include "hw/pc.h"
diff --git a/qdev-monitor.c b/qdev-monitor.c
new file mode 100644
index 0000000..9a78ccf
--- /dev/null
+++ b/qdev-monitor.c
@@ -0,0 +1,684 @@
+/*
+ *  Dynamic device configuration and creation.
+ *
+ *  Copyright (c) 2009 CodeSourcery
+ *
+ * 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/qdev.h"
+#include "monitor/monitor.h"
+#include "monitor/qdev.h"
+#include "qmp-commands.h"
+#include "sysemu/arch_init.h"
+#include "qemu/config-file.h"
+
+/*
+ * Aliases were a bad idea from the start.  Let's keep them
+ * from spreading further.
+ */
+typedef struct QDevAlias
+{
+    const char *typename;
+    const char *alias;
+    uint32_t arch_mask;
+} QDevAlias;
+
+static const QDevAlias qdev_alias_table[] = {
+    { "virtio-blk-pci", "virtio-blk", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
+    { "virtio-net-pci", "virtio-net", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
+    { "virtio-serial-pci", "virtio-serial", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
+    { "virtio-balloon-pci", "virtio-balloon",
+            QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
+    { "virtio-blk-s390", "virtio-blk", QEMU_ARCH_S390X },
+    { "virtio-net-s390", "virtio-net", QEMU_ARCH_S390X },
+    { "virtio-serial-s390", "virtio-serial", QEMU_ARCH_S390X },
+    { "lsi53c895a", "lsi" },
+    { "ich9-ahci", "ahci" },
+    { "kvm-pci-assign", "pci-assign" },
+    { }
+};
+
+static const char *qdev_class_get_alias(DeviceClass *dc)
+{
+    const char *typename = object_class_get_name(OBJECT_CLASS(dc));
+    int i;
+
+    for (i = 0; qdev_alias_table[i].typename; i++) {
+        if (qdev_alias_table[i].arch_mask &&
+            !(qdev_alias_table[i].arch_mask & arch_type)) {
+            continue;
+        }
+
+        if (strcmp(qdev_alias_table[i].typename, typename) == 0) {
+            return qdev_alias_table[i].alias;
+        }
+    }
+
+    return NULL;
+}
+
+static bool qdev_class_has_alias(DeviceClass *dc)
+{
+    return (qdev_class_get_alias(dc) != NULL);
+}
+
+static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
+{
+    DeviceClass *dc;
+    bool *show_no_user = opaque;
+
+    dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE);
+
+    if (!dc || (show_no_user && !*show_no_user && dc->no_user)) {
+        return;
+    }
+
+    error_printf("name \"%s\"", object_class_get_name(klass));
+    if (dc->bus_type) {
+        error_printf(", bus %s", dc->bus_type);
+    }
+    if (qdev_class_has_alias(dc)) {
+        error_printf(", alias \"%s\"", qdev_class_get_alias(dc));
+    }
+    if (dc->desc) {
+        error_printf(", desc \"%s\"", dc->desc);
+    }
+    if (dc->no_user) {
+        error_printf(", no-user");
+    }
+    error_printf("\n");
+}
+
+static int set_property(const char *name, const char *value, void *opaque)
+{
+    DeviceState *dev = opaque;
+
+    if (strcmp(name, "driver") == 0)
+        return 0;
+    if (strcmp(name, "bus") == 0)
+        return 0;
+
+    if (qdev_prop_parse(dev, name, value) == -1) {
+        return -1;
+    }
+    return 0;
+}
+
+static const char *find_typename_by_alias(const char *alias)
+{
+    int i;
+
+    for (i = 0; qdev_alias_table[i].alias; i++) {
+        if (qdev_alias_table[i].arch_mask &&
+            !(qdev_alias_table[i].arch_mask & arch_type)) {
+            continue;
+        }
+
+        if (strcmp(qdev_alias_table[i].alias, alias) == 0) {
+            return qdev_alias_table[i].typename;
+        }
+    }
+
+    return NULL;
+}
+
+int qdev_device_help(QemuOpts *opts)
+{
+    const char *driver;
+    Property *prop;
+    ObjectClass *klass;
+
+    driver = qemu_opt_get(opts, "driver");
+    if (driver && is_help_option(driver)) {
+        bool show_no_user = false;
+        object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user);
+        return 1;
+    }
+
+    if (!driver || !qemu_opt_has_help_opt(opts)) {
+        return 0;
+    }
+
+    klass = object_class_by_name(driver);
+    if (!klass) {
+        const char *typename = find_typename_by_alias(driver);
+
+        if (typename) {
+            driver = typename;
+            klass = object_class_by_name(driver);
+        }
+    }
+
+    if (!klass) {
+        return 0;
+    }
+    do {
+        for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) {
+            /*
+             * TODO Properties without a parser are just for dirty hacks.
+             * qdev_prop_ptr is the only such PropertyInfo.  It's marked
+             * for removal.  This conditional should be removed along with
+             * it.
+             */
+            if (!prop->info->set) {
+                continue;           /* no way to set it, don't show */
+            }
+            error_printf("%s.%s=%s\n", driver, prop->name,
+                         prop->info->legacy_name ?: prop->info->name);
+        }
+        klass = object_class_get_parent(klass);
+    } while (klass != object_class_by_name(TYPE_DEVICE));
+    return 1;
+}
+
+static Object *qdev_get_peripheral(void)
+{
+    static Object *dev;
+
+    if (dev == NULL) {
+        dev = container_get(qdev_get_machine(), "/peripheral");
+    }
+
+    return dev;
+}
+
+static Object *qdev_get_peripheral_anon(void)
+{
+    static Object *dev;
+
+    if (dev == NULL) {
+        dev = container_get(qdev_get_machine(), "/peripheral-anon");
+    }
+
+    return dev;
+}
+
+static void qbus_list_bus(DeviceState *dev)
+{
+    BusState *child;
+    const char *sep = " ";
+
+    error_printf("child busses at \"%s\":",
+                 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
+    QLIST_FOREACH(child, &dev->child_bus, sibling) {
+        error_printf("%s\"%s\"", sep, child->name);
+        sep = ", ";
+    }
+    error_printf("\n");
+}
+
+static void qbus_list_dev(BusState *bus)
+{
+    BusChild *kid;
+    const char *sep = " ";
+
+    error_printf("devices at \"%s\":", bus->name);
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
+        error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
+        if (dev->id)
+            error_printf("/\"%s\"", dev->id);
+        sep = ", ";
+    }
+    error_printf("\n");
+}
+
+static BusState *qbus_find_bus(DeviceState *dev, char *elem)
+{
+    BusState *child;
+
+    QLIST_FOREACH(child, &dev->child_bus, sibling) {
+        if (strcmp(child->name, elem) == 0) {
+            return child;
+        }
+    }
+    return NULL;
+}
+
+static DeviceState *qbus_find_dev(BusState *bus, char *elem)
+{
+    BusChild *kid;
+
+    /*
+     * try to match in order:
+     *   (1) instance id, if present
+     *   (2) driver name
+     *   (3) driver alias, if present
+     */
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
+        if (dev->id  &&  strcmp(dev->id, elem) == 0) {
+            return dev;
+        }
+    }
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
+        if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
+            return dev;
+        }
+    }
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
+        DeviceClass *dc = DEVICE_GET_CLASS(dev);
+
+        if (qdev_class_has_alias(dc) &&
+            strcmp(qdev_class_get_alias(dc), elem) == 0) {
+            return dev;
+        }
+    }
+    return NULL;
+}
+
+static BusState *qbus_find_recursive(BusState *bus, const char *name,
+                                     const char *bus_typename)
+{
+    BusClass *bus_class = BUS_GET_CLASS(bus);
+    BusChild *kid;
+    BusState *child, *ret;
+    int match = 1;
+
+    if (name && (strcmp(bus->name, name) != 0)) {
+        match = 0;
+    }
+    if (bus_typename && !object_dynamic_cast(OBJECT(bus), bus_typename)) {
+        match = 0;
+    }
+    if ((bus_class->max_dev != 0) && (bus_class->max_dev <= bus->max_index)) {
+        if (name != NULL) {
+            /* bus was explicitly specified: return an error. */
+            qerror_report(ERROR_CLASS_GENERIC_ERROR, "Bus '%s' is full",
+                          bus->name);
+            return NULL;
+        } else {
+            /* bus was not specified: try to find another one. */
+            match = 0;
+        }
+    }
+    if (match) {
+        return bus;
+    }
+
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
+        QLIST_FOREACH(child, &dev->child_bus, sibling) {
+            ret = qbus_find_recursive(child, name, bus_typename);
+            if (ret) {
+                return ret;
+            }
+        }
+    }
+    return NULL;
+}
+
+static BusState *qbus_find(const char *path)
+{
+    DeviceState *dev;
+    BusState *bus;
+    char elem[128];
+    int pos, len;
+
+    /* find start element */
+    if (path[0] == '/') {
+        bus = sysbus_get_default();
+        pos = 0;
+    } else {
+        if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
+            assert(!path[0]);
+            elem[0] = len = 0;
+        }
+        bus = qbus_find_recursive(sysbus_get_default(), elem, NULL);
+        if (!bus) {
+            qerror_report(QERR_BUS_NOT_FOUND, elem);
+            return NULL;
+        }
+        pos = len;
+    }
+
+    for (;;) {
+        assert(path[pos] == '/' || !path[pos]);
+        while (path[pos] == '/') {
+            pos++;
+        }
+        if (path[pos] == '\0') {
+            return bus;
+        }
+
+        /* find device */
+        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
+            assert(0);
+            elem[0] = len = 0;
+        }
+        pos += len;
+        dev = qbus_find_dev(bus, elem);
+        if (!dev) {
+            qerror_report(QERR_DEVICE_NOT_FOUND, elem);
+            if (!monitor_cur_is_qmp()) {
+                qbus_list_dev(bus);
+            }
+            return NULL;
+        }
+
+        assert(path[pos] == '/' || !path[pos]);
+        while (path[pos] == '/') {
+            pos++;
+        }
+        if (path[pos] == '\0') {
+            /* last specified element is a device.  If it has exactly
+             * one child bus accept it nevertheless */
+            switch (dev->num_child_bus) {
+            case 0:
+                qerror_report(QERR_DEVICE_NO_BUS, elem);
+                return NULL;
+            case 1:
+                return QLIST_FIRST(&dev->child_bus);
+            default:
+                qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
+                if (!monitor_cur_is_qmp()) {
+                    qbus_list_bus(dev);
+                }
+                return NULL;
+            }
+        }
+
+        /* find bus */
+        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
+            assert(0);
+            elem[0] = len = 0;
+        }
+        pos += len;
+        bus = qbus_find_bus(dev, elem);
+        if (!bus) {
+            qerror_report(QERR_BUS_NOT_FOUND, elem);
+            if (!monitor_cur_is_qmp()) {
+                qbus_list_bus(dev);
+            }
+            return NULL;
+        }
+    }
+}
+
+DeviceState *qdev_device_add(QemuOpts *opts)
+{
+    ObjectClass *obj;
+    DeviceClass *k;
+    const char *driver, *path, *id;
+    DeviceState *qdev;
+    BusState *bus;
+
+    driver = qemu_opt_get(opts, "driver");
+    if (!driver) {
+        qerror_report(QERR_MISSING_PARAMETER, "driver");
+        return NULL;
+    }
+
+    /* find driver */
+    obj = object_class_by_name(driver);
+    if (!obj) {
+        const char *typename = find_typename_by_alias(driver);
+
+        if (typename) {
+            driver = typename;
+            obj = object_class_by_name(driver);
+        }
+    }
+
+    if (!obj) {
+        qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
+        return NULL;
+    }
+
+    k = DEVICE_CLASS(obj);
+
+    /* find bus */
+    path = qemu_opt_get(opts, "bus");
+    if (path != NULL) {
+        bus = qbus_find(path);
+        if (!bus) {
+            return NULL;
+        }
+        if (!object_dynamic_cast(OBJECT(bus), k->bus_type)) {
+            qerror_report(QERR_BAD_BUS_FOR_DEVICE,
+                          driver, object_get_typename(OBJECT(bus)));
+            return NULL;
+        }
+    } else {
+        bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_type);
+        if (!bus) {
+            qerror_report(QERR_NO_BUS_FOR_DEVICE,
+                          k->bus_type, driver);
+            return NULL;
+        }
+    }
+    if (qdev_hotplug && !bus->allow_hotplug) {
+        qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
+        return NULL;
+    }
+
+    if (!bus) {
+        bus = sysbus_get_default();
+    }
+
+    /* create device, set properties */
+    qdev = DEVICE(object_new(driver));
+    qdev_set_parent_bus(qdev, bus);
+
+    id = qemu_opts_id(opts);
+    if (id) {
+        qdev->id = id;
+    }
+    if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
+        qdev_free(qdev);
+        return NULL;
+    }
+    if (qdev->id) {
+        object_property_add_child(qdev_get_peripheral(), qdev->id,
+                                  OBJECT(qdev), NULL);
+    } else {
+        static int anon_count;
+        gchar *name = g_strdup_printf("device[%d]", anon_count++);
+        object_property_add_child(qdev_get_peripheral_anon(), name,
+                                  OBJECT(qdev), NULL);
+        g_free(name);
+    }        
+    if (qdev_init(qdev) < 0) {
+        qerror_report(QERR_DEVICE_INIT_FAILED, driver);
+        return NULL;
+    }
+    qdev->opts = opts;
+    return qdev;
+}
+
+
+#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
+static void qbus_print(Monitor *mon, BusState *bus, int indent);
+
+static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
+                             int indent)
+{
+    if (!props)
+        return;
+    for (; props->name; props++) {
+        Error *err = NULL;
+        char *value;
+        char *legacy_name = g_strdup_printf("legacy-%s", props->name);
+        if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
+            value = object_property_get_str(OBJECT(dev), legacy_name, &err);
+        } else {
+            value = object_property_print(OBJECT(dev), props->name, &err);
+        }
+        g_free(legacy_name);
+
+        if (err) {
+            error_free(err);
+            continue;
+        }
+        qdev_printf("%s = %s\n", props->name,
+                    value && *value ? value : "<null>");
+        g_free(value);
+    }
+}
+
+static void bus_print_dev(BusState *bus, Monitor *mon, DeviceState *dev, int indent)
+{
+    BusClass *bc = BUS_GET_CLASS(bus);
+
+    if (bc->print_dev) {
+        bc->print_dev(mon, dev, indent);
+    }
+}
+
+static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
+{
+    ObjectClass *class;
+    BusState *child;
+    qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
+                dev->id ? dev->id : "");
+    indent += 2;
+    if (dev->num_gpio_in) {
+        qdev_printf("gpio-in %d\n", dev->num_gpio_in);
+    }
+    if (dev->num_gpio_out) {
+        qdev_printf("gpio-out %d\n", dev->num_gpio_out);
+    }
+    class = object_get_class(OBJECT(dev));
+    do {
+        qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent);
+        class = object_class_get_parent(class);
+    } while (class != object_class_by_name(TYPE_DEVICE));
+    bus_print_dev(dev->parent_bus, mon, dev, indent);
+    QLIST_FOREACH(child, &dev->child_bus, sibling) {
+        qbus_print(mon, child, indent);
+    }
+}
+
+static void qbus_print(Monitor *mon, BusState *bus, int indent)
+{
+    BusChild *kid;
+
+    qdev_printf("bus: %s\n", bus->name);
+    indent += 2;
+    qdev_printf("type %s\n", object_get_typename(OBJECT(bus)));
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
+        qdev_print(mon, dev, indent);
+    }
+}
+#undef qdev_printf
+
+void do_info_qtree(Monitor *mon, const QDict *qdict)
+{
+    if (sysbus_get_default())
+        qbus_print(mon, sysbus_get_default(), 0);
+}
+
+void do_info_qdm(Monitor *mon, const QDict *qdict)
+{
+    object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, NULL);
+}
+
+int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+    Error *local_err = NULL;
+    QemuOpts *opts;
+    DeviceState *dev;
+
+    opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -1;
+    }
+    if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
+        qemu_opts_del(opts);
+        return 0;
+    }
+    dev = qdev_device_add(opts);
+    if (!dev) {
+        qemu_opts_del(opts);
+        return -1;
+    }
+    object_unref(OBJECT(dev));
+    return 0;
+}
+
+void qmp_device_del(const char *id, Error **errp)
+{
+    DeviceState *dev;
+
+    dev = qdev_find_recursive(sysbus_get_default(), id);
+    if (NULL == dev) {
+        error_set(errp, QERR_DEVICE_NOT_FOUND, id);
+        return;
+    }
+
+    qdev_unplug(dev, errp);
+}
+
+void qdev_machine_init(void)
+{
+    qdev_get_peripheral_anon();
+    qdev_get_peripheral();
+}
+
+QemuOptsList qemu_device_opts = {
+    .name = "device",
+    .implied_opt_name = "driver",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head),
+    .desc = {
+        /*
+         * no elements => accept any
+         * sanity checking will happen later
+         * when setting device properties
+         */
+        { /* end of list */ }
+    },
+};
+
+QemuOptsList qemu_global_opts = {
+    .name = "global",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_global_opts.head),
+    .desc = {
+        {
+            .name = "driver",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "property",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "value",
+            .type = QEMU_OPT_STRING,
+        },
+        { /* end of list */ }
+    },
+};
+
+int qemu_global_option(const char *str)
+{
+    char driver[64], property[64];
+    QemuOpts *opts;
+    int rc, offset;
+
+    rc = sscanf(str, "%63[^.].%63[^=]%n", driver, property, &offset);
+    if (rc < 2 || str[offset] != '=') {
+        error_report("can't parse: \"%s\"", str);
+        return -1;
+    }
+
+    opts = qemu_opts_create_nofail(&qemu_global_opts);
+    qemu_opt_set(opts, "driver", driver);
+    qemu_opt_set(opts, "property", property);
+    qemu_opt_set(opts, "value", str+offset+1);
+    return 0;
+}
diff --git a/util/qemu-config.c b/util/qemu-config.c
index db6ec03..01ca890 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -2,6 +2,7 @@
 #include "qemu/error-report.h"
 #include "qemu/option.h"
 #include "qemu/config-file.h"
+#include "qapi/qmp/qerror.h"
 #include "hw/qdev.h"
 #include "qapi/error.h"
 
diff --git a/vl.c b/vl.c
index e0a8eeb..bbdbafd 100644
--- a/vl.c
+++ b/vl.c
@@ -126,6 +126,7 @@ int main(int argc, char **argv)
 #include "hw/xen.h"
 #include "hw/qdev.h"
 #include "hw/loader.h"
+#include "monitor/qdev.h"
 #include "bt/bt.h"
 #include "net/net.h"
 #include "net/slirp.h"
commit fd7f0d66177ec1058a2a256856ff38fc9ceae5af
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Feb 4 10:57:50 2013 +0100

    hw: move fifo.[ch] to libqemuutil
    
    fifo.c is generic code that can be easily unit tested.  So it
    belongs in libqemuutil.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 5750332..6e2275b 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -44,7 +44,6 @@ common-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
 endif
 common-obj-$(CONFIG_I8259) += i8259_common.o i8259.o
 common-obj-$(CONFIG_SDHCI) += sdhci.o
-common-obj-y += fifo.o
 common-obj-y += pam.o
 
 # PPC devices
diff --git a/hw/fifo.c b/hw/fifo.c
deleted file mode 100644
index 68a955a..0000000
--- a/hw/fifo.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Generic FIFO component, implemented as a circular buffer.
- *
- * Copyright (c) 2012 Peter A. G. Crosthwaite
- *
- * 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.
- *
- * 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 "fifo.h"
-
-void fifo8_create(Fifo8 *fifo, uint32_t capacity)
-{
-    fifo->data = g_new(uint8_t, capacity);
-    fifo->capacity = capacity;
-    fifo->head = 0;
-    fifo->num = 0;
-}
-
-void fifo8_destroy(Fifo8 *fifo)
-{
-    g_free(fifo->data);
-}
-
-void fifo8_push(Fifo8 *fifo, uint8_t data)
-{
-    if (fifo->num == fifo->capacity) {
-        abort();
-    }
-    fifo->data[(fifo->head + fifo->num) % fifo->capacity] = data;
-    fifo->num++;
-}
-
-uint8_t fifo8_pop(Fifo8 *fifo)
-{
-    uint8_t ret;
-
-    if (fifo->num == 0) {
-        abort();
-    }
-    ret = fifo->data[fifo->head++];
-    fifo->head %= fifo->capacity;
-    fifo->num--;
-    return ret;
-}
-
-void fifo8_reset(Fifo8 *fifo)
-{
-    fifo->num = 0;
-}
-
-bool fifo8_is_empty(Fifo8 *fifo)
-{
-    return (fifo->num == 0);
-}
-
-bool fifo8_is_full(Fifo8 *fifo)
-{
-    return (fifo->num == fifo->capacity);
-}
-
-const VMStateDescription vmstate_fifo8 = {
-    .name = "Fifo8",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField[]) {
-        VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
-        VMSTATE_UINT32(head, Fifo8),
-        VMSTATE_UINT32(num, Fifo8),
-        VMSTATE_END_OF_LIST()
-    }
-};
diff --git a/hw/fifo.h b/hw/fifo.h
deleted file mode 100644
index f23890a..0000000
--- a/hw/fifo.h
+++ /dev/null
@@ -1,99 +0,0 @@
-#ifndef FIFO_H
-#define FIFO_H
-
-#include "hw.h"
-
-typedef struct {
-    /* All fields are private */
-    uint8_t *data;
-    uint32_t capacity;
-    uint32_t head;
-    uint32_t num;
-} Fifo8;
-
-/**
- * fifo8_create:
- * @fifo: struct Fifo8 to initialise with new FIFO
- * @capacity: capacity of the newly created FIFO
- *
- * Create a FIFO of the specified size. Clients should call fifo8_destroy()
- * when finished using the fifo. The FIFO is initially empty.
- */
-
-void fifo8_create(Fifo8 *fifo, uint32_t capacity);
-
-/**
- * fifo8_destroy:
- * @fifo: FIFO to cleanup
- *
- * Cleanup a FIFO created with fifo8_create(). Frees memory created for FIFO
-  *storage. The FIFO is no longer usable after this has been called.
- */
-
-void fifo8_destroy(Fifo8 *fifo);
-
-/**
- * fifo8_push:
- * @fifo: FIFO to push to
- * @data: data byte to push
- *
- * Push a data byte to the FIFO. Behaviour is undefined if the FIFO is full.
- * Clients are responsible for checking for fullness using fifo8_is_full().
- */
-
-void fifo8_push(Fifo8 *fifo, uint8_t data);
-
-/**
- * fifo8_pop:
- * @fifo: fifo to pop from
- *
- * Pop a data byte from the FIFO. Behaviour is undefined if the FIFO is empty.
- * Clients are responsible for checking for emptyness using fifo8_is_empty().
- *
- * Returns: The popped data byte.
- */
-
-uint8_t fifo8_pop(Fifo8 *fifo);
-
-/**
- * fifo8_reset:
- * @fifo: FIFO to reset
- *
- * Reset a FIFO. All data is discarded and the FIFO is emptied.
- */
-
-void fifo8_reset(Fifo8 *fifo);
-
-/**
- * fifo8_is_empty:
- * @fifo: FIFO to check
- *
- * Check if a FIFO is empty.
- *
- * Returns: True if the fifo is empty, false otherwise.
- */
-
-bool fifo8_is_empty(Fifo8 *fifo);
-
-/**
- * fifo8_is_full:
- * @fifo: FIFO to check
- *
- * Check if a FIFO is full.
- *
- * Returns: True if the fifo is full, false otherwise.
- */
-
-bool fifo8_is_full(Fifo8 *fifo);
-
-extern const VMStateDescription vmstate_fifo8;
-
-#define VMSTATE_FIFO8(_field, _state) {                              \
-    .name       = (stringify(_field)),                               \
-    .size       = sizeof(Fifo8),                                     \
-    .vmsd       = &vmstate_fifo8,                                    \
-    .flags      = VMS_STRUCT,                                        \
-    .offset     = vmstate_offset_value(_state, _field, Fifo8),       \
-}
-
-#endif /* FIFO_H */
diff --git a/hw/xilinx_spi.c b/hw/xilinx_spi.c
index be581c2..e73c9bd 100644
--- a/hw/xilinx_spi.c
+++ b/hw/xilinx_spi.c
@@ -27,7 +27,7 @@
 #include "sysbus.h"
 #include "sysemu/sysemu.h"
 #include "qemu/log.h"
-#include "fifo.h"
+#include "qemu/fifo8.h"
 
 #include "ssi.h"
 
diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c
index 42e019d..915eb96 100644
--- a/hw/xilinx_spips.c
+++ b/hw/xilinx_spips.c
@@ -26,7 +26,7 @@
 #include "sysemu/sysemu.h"
 #include "ptimer.h"
 #include "qemu/log.h"
-#include "fifo.h"
+#include "qemu/fifo8.h"
 #include "ssi.h"
 #include "qemu/bitops.h"
 
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index f27276c..94a409b 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -26,6 +26,8 @@
 #ifndef QEMU_VMSTATE_H
 #define QEMU_VMSTATE_H 1
 
+#include <migration/qemu-file.h>
+
 typedef void SaveStateHandler(QEMUFile *f, void *opaque);
 typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
 
diff --git a/include/qemu/fifo8.h b/include/qemu/fifo8.h
new file mode 100644
index 0000000..d318f71
--- /dev/null
+++ b/include/qemu/fifo8.h
@@ -0,0 +1,99 @@
+#ifndef FIFO_H
+#define FIFO_H
+
+#include "migration/vmstate.h"
+
+typedef struct {
+    /* All fields are private */
+    uint8_t *data;
+    uint32_t capacity;
+    uint32_t head;
+    uint32_t num;
+} Fifo8;
+
+/**
+ * fifo8_create:
+ * @fifo: struct Fifo8 to initialise with new FIFO
+ * @capacity: capacity of the newly created FIFO
+ *
+ * Create a FIFO of the specified size. Clients should call fifo8_destroy()
+ * when finished using the fifo. The FIFO is initially empty.
+ */
+
+void fifo8_create(Fifo8 *fifo, uint32_t capacity);
+
+/**
+ * fifo8_destroy:
+ * @fifo: FIFO to cleanup
+ *
+ * Cleanup a FIFO created with fifo8_create(). Frees memory created for FIFO
+  *storage. The FIFO is no longer usable after this has been called.
+ */
+
+void fifo8_destroy(Fifo8 *fifo);
+
+/**
+ * fifo8_push:
+ * @fifo: FIFO to push to
+ * @data: data byte to push
+ *
+ * Push a data byte to the FIFO. Behaviour is undefined if the FIFO is full.
+ * Clients are responsible for checking for fullness using fifo8_is_full().
+ */
+
+void fifo8_push(Fifo8 *fifo, uint8_t data);
+
+/**
+ * fifo8_pop:
+ * @fifo: fifo to pop from
+ *
+ * Pop a data byte from the FIFO. Behaviour is undefined if the FIFO is empty.
+ * Clients are responsible for checking for emptyness using fifo8_is_empty().
+ *
+ * Returns: The popped data byte.
+ */
+
+uint8_t fifo8_pop(Fifo8 *fifo);
+
+/**
+ * fifo8_reset:
+ * @fifo: FIFO to reset
+ *
+ * Reset a FIFO. All data is discarded and the FIFO is emptied.
+ */
+
+void fifo8_reset(Fifo8 *fifo);
+
+/**
+ * fifo8_is_empty:
+ * @fifo: FIFO to check
+ *
+ * Check if a FIFO is empty.
+ *
+ * Returns: True if the fifo is empty, false otherwise.
+ */
+
+bool fifo8_is_empty(Fifo8 *fifo);
+
+/**
+ * fifo8_is_full:
+ * @fifo: FIFO to check
+ *
+ * Check if a FIFO is full.
+ *
+ * Returns: True if the fifo is full, false otherwise.
+ */
+
+bool fifo8_is_full(Fifo8 *fifo);
+
+extern const VMStateDescription vmstate_fifo8;
+
+#define VMSTATE_FIFO8(_field, _state) {                              \
+    .name       = (stringify(_field)),                               \
+    .size       = sizeof(Fifo8),                                     \
+    .vmsd       = &vmstate_fifo8,                                    \
+    .flags      = VMS_STRUCT,                                        \
+    .offset     = vmstate_offset_value(_state, _field, Fifo8),       \
+}
+
+#endif /* FIFO_H */
diff --git a/util/Makefile.objs b/util/Makefile.objs
index 495a178..cad5ce8 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -3,6 +3,7 @@ util-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o event_notifier-win
 util-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o event_notifier-posix.o
 util-obj-y += envlist.o path.o host-utils.o cache-utils.o module.o
 util-obj-y += bitmap.o bitops.o hbitmap.o
+util-obj-y += fifo8.o
 util-obj-y += acl.o
 util-obj-y += error.o qemu-error.o
 util-obj-$(CONFIG_POSIX) += compatfd.o
diff --git a/util/fifo8.c b/util/fifo8.c
new file mode 100644
index 0000000..013e903
--- /dev/null
+++ b/util/fifo8.c
@@ -0,0 +1,79 @@
+/*
+ * Generic FIFO component, implemented as a circular buffer.
+ *
+ * Copyright (c) 2012 Peter A. G. Crosthwaite
+ *
+ * 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.
+ *
+ * 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 "qemu-common.h"
+#include "qemu/fifo8.h"
+
+void fifo8_create(Fifo8 *fifo, uint32_t capacity)
+{
+    fifo->data = g_new(uint8_t, capacity);
+    fifo->capacity = capacity;
+    fifo->head = 0;
+    fifo->num = 0;
+}
+
+void fifo8_destroy(Fifo8 *fifo)
+{
+    g_free(fifo->data);
+}
+
+void fifo8_push(Fifo8 *fifo, uint8_t data)
+{
+    if (fifo->num == fifo->capacity) {
+        abort();
+    }
+    fifo->data[(fifo->head + fifo->num) % fifo->capacity] = data;
+    fifo->num++;
+}
+
+uint8_t fifo8_pop(Fifo8 *fifo)
+{
+    uint8_t ret;
+
+    if (fifo->num == 0) {
+        abort();
+    }
+    ret = fifo->data[fifo->head++];
+    fifo->head %= fifo->capacity;
+    fifo->num--;
+    return ret;
+}
+
+void fifo8_reset(Fifo8 *fifo)
+{
+    fifo->num = 0;
+}
+
+bool fifo8_is_empty(Fifo8 *fifo)
+{
+    return (fifo->num == 0);
+}
+
+bool fifo8_is_full(Fifo8 *fifo)
+{
+    return (fifo->num == fifo->capacity);
+}
+
+const VMStateDescription vmstate_fifo8 = {
+    .name = "Fifo8",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
+        VMSTATE_UINT32(head, Fifo8),
+        VMSTATE_UINT32(num, Fifo8),
+        VMSTATE_END_OF_LIST()
+    }
+};
commit 159b6e9f144c7afdf3ad95c29d1fede9626fa8b1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sun Feb 3 20:21:00 2013 +0100

    hw: move char backends to backends/
    
    Braille and msmouse support is in hw/, but it is not hardware.
    Move it to the backends/ directory.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index 8836761..464bc3e 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -1,2 +1,6 @@
 common-obj-y += rng.o rng-egd.o
 common-obj-$(CONFIG_POSIX) += rng-random.o
+
+common-obj-y += msmouse.o
+common-obj-$(CONFIG_BRLAPI) += baum.o
+$(obj)/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS) 
diff --git a/backends/baum.c b/backends/baum.c
new file mode 100644
index 0000000..37ccca8
--- /dev/null
+++ b/backends/baum.c
@@ -0,0 +1,627 @@
+/*
+ * QEMU Baum Braille Device
+ *
+ * Copyright (c) 2008 Samuel Thibault
+ *
+ * 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 "char/char.h"
+#include "qemu/timer.h"
+#include "hw/usb.h"
+#include "char/baum.h"
+#include <brlapi.h>
+#include <brlapi_constants.h>
+#include <brlapi_keycodes.h>
+#ifdef CONFIG_SDL
+#include <SDL_syswm.h>
+#endif
+
+#if 0
+#define DPRINTF(fmt, ...) \
+        printf(fmt, ## __VA_ARGS__)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+#define ESC 0x1B
+
+#define BAUM_REQ_DisplayData		0x01
+#define BAUM_REQ_GetVersionNumber	0x05
+#define BAUM_REQ_GetKeys		0x08
+#define BAUM_REQ_SetMode		0x12
+#define BAUM_REQ_SetProtocol		0x15
+#define BAUM_REQ_GetDeviceIdentity	0x84
+#define BAUM_REQ_GetSerialNumber	0x8A
+
+#define BAUM_RSP_CellCount		0x01
+#define BAUM_RSP_VersionNumber		0x05
+#define BAUM_RSP_ModeSetting		0x11
+#define BAUM_RSP_CommunicationChannel	0x16
+#define BAUM_RSP_PowerdownSignal	0x17
+#define BAUM_RSP_HorizontalSensors	0x20
+#define BAUM_RSP_VerticalSensors	0x21
+#define BAUM_RSP_RoutingKeys		0x22
+#define BAUM_RSP_Switches		0x23
+#define BAUM_RSP_TopKeys		0x24
+#define BAUM_RSP_HorizontalSensor	0x25
+#define BAUM_RSP_VerticalSensor		0x26
+#define BAUM_RSP_RoutingKey		0x27
+#define BAUM_RSP_FrontKeys6		0x28
+#define BAUM_RSP_BackKeys6		0x29
+#define BAUM_RSP_CommandKeys		0x2B
+#define BAUM_RSP_FrontKeys10		0x2C
+#define BAUM_RSP_BackKeys10		0x2D
+#define BAUM_RSP_EntryKeys		0x33
+#define BAUM_RSP_JoyStick		0x34
+#define BAUM_RSP_ErrorCode		0x40
+#define BAUM_RSP_InfoBlock		0x42
+#define BAUM_RSP_DeviceIdentity		0x84
+#define BAUM_RSP_SerialNumber		0x8A
+#define BAUM_RSP_BluetoothName		0x8C
+
+#define BAUM_TL1 0x01
+#define BAUM_TL2 0x02
+#define BAUM_TL3 0x04
+#define BAUM_TR1 0x08
+#define BAUM_TR2 0x10
+#define BAUM_TR3 0x20
+
+#define BUF_SIZE 256
+
+typedef struct {
+    CharDriverState *chr;
+
+    brlapi_handle_t *brlapi;
+    int brlapi_fd;
+    unsigned int x, y;
+
+    uint8_t in_buf[BUF_SIZE];
+    uint8_t in_buf_used;
+    uint8_t out_buf[BUF_SIZE];
+    uint8_t out_buf_used, out_buf_ptr;
+
+    QEMUTimer *cellCount_timer;
+} BaumDriverState;
+
+/* Let's assume NABCC by default */
+static const uint8_t nabcc_translation[256] = {
+    [0] = ' ',
+#ifndef BRLAPI_DOTS
+#define BRLAPI_DOTS(d1,d2,d3,d4,d5,d6,d7,d8) \
+    ((d1?BRLAPI_DOT1:0)|\
+     (d2?BRLAPI_DOT2:0)|\
+     (d3?BRLAPI_DOT3:0)|\
+     (d4?BRLAPI_DOT4:0)|\
+     (d5?BRLAPI_DOT5:0)|\
+     (d6?BRLAPI_DOT6:0)|\
+     (d7?BRLAPI_DOT7:0)|\
+     (d8?BRLAPI_DOT8:0))
+#endif
+    [BRLAPI_DOTS(1,0,0,0,0,0,0,0)] = 'a',
+    [BRLAPI_DOTS(1,1,0,0,0,0,0,0)] = 'b',
+    [BRLAPI_DOTS(1,0,0,1,0,0,0,0)] = 'c',
+    [BRLAPI_DOTS(1,0,0,1,1,0,0,0)] = 'd',
+    [BRLAPI_DOTS(1,0,0,0,1,0,0,0)] = 'e',
+    [BRLAPI_DOTS(1,1,0,1,0,0,0,0)] = 'f',
+    [BRLAPI_DOTS(1,1,0,1,1,0,0,0)] = 'g',
+    [BRLAPI_DOTS(1,1,0,0,1,0,0,0)] = 'h',
+    [BRLAPI_DOTS(0,1,0,1,0,0,0,0)] = 'i',
+    [BRLAPI_DOTS(0,1,0,1,1,0,0,0)] = 'j',
+    [BRLAPI_DOTS(1,0,1,0,0,0,0,0)] = 'k',
+    [BRLAPI_DOTS(1,1,1,0,0,0,0,0)] = 'l',
+    [BRLAPI_DOTS(1,0,1,1,0,0,0,0)] = 'm',
+    [BRLAPI_DOTS(1,0,1,1,1,0,0,0)] = 'n',
+    [BRLAPI_DOTS(1,0,1,0,1,0,0,0)] = 'o',
+    [BRLAPI_DOTS(1,1,1,1,0,0,0,0)] = 'p',
+    [BRLAPI_DOTS(1,1,1,1,1,0,0,0)] = 'q',
+    [BRLAPI_DOTS(1,1,1,0,1,0,0,0)] = 'r',
+    [BRLAPI_DOTS(0,1,1,1,0,0,0,0)] = 's',
+    [BRLAPI_DOTS(0,1,1,1,1,0,0,0)] = 't',
+    [BRLAPI_DOTS(1,0,1,0,0,1,0,0)] = 'u',
+    [BRLAPI_DOTS(1,1,1,0,0,1,0,0)] = 'v',
+    [BRLAPI_DOTS(0,1,0,1,1,1,0,0)] = 'w',
+    [BRLAPI_DOTS(1,0,1,1,0,1,0,0)] = 'x',
+    [BRLAPI_DOTS(1,0,1,1,1,1,0,0)] = 'y',
+    [BRLAPI_DOTS(1,0,1,0,1,1,0,0)] = 'z',
+
+    [BRLAPI_DOTS(1,0,0,0,0,0,1,0)] = 'A',
+    [BRLAPI_DOTS(1,1,0,0,0,0,1,0)] = 'B',
+    [BRLAPI_DOTS(1,0,0,1,0,0,1,0)] = 'C',
+    [BRLAPI_DOTS(1,0,0,1,1,0,1,0)] = 'D',
+    [BRLAPI_DOTS(1,0,0,0,1,0,1,0)] = 'E',
+    [BRLAPI_DOTS(1,1,0,1,0,0,1,0)] = 'F',
+    [BRLAPI_DOTS(1,1,0,1,1,0,1,0)] = 'G',
+    [BRLAPI_DOTS(1,1,0,0,1,0,1,0)] = 'H',
+    [BRLAPI_DOTS(0,1,0,1,0,0,1,0)] = 'I',
+    [BRLAPI_DOTS(0,1,0,1,1,0,1,0)] = 'J',
+    [BRLAPI_DOTS(1,0,1,0,0,0,1,0)] = 'K',
+    [BRLAPI_DOTS(1,1,1,0,0,0,1,0)] = 'L',
+    [BRLAPI_DOTS(1,0,1,1,0,0,1,0)] = 'M',
+    [BRLAPI_DOTS(1,0,1,1,1,0,1,0)] = 'N',
+    [BRLAPI_DOTS(1,0,1,0,1,0,1,0)] = 'O',
+    [BRLAPI_DOTS(1,1,1,1,0,0,1,0)] = 'P',
+    [BRLAPI_DOTS(1,1,1,1,1,0,1,0)] = 'Q',
+    [BRLAPI_DOTS(1,1,1,0,1,0,1,0)] = 'R',
+    [BRLAPI_DOTS(0,1,1,1,0,0,1,0)] = 'S',
+    [BRLAPI_DOTS(0,1,1,1,1,0,1,0)] = 'T',
+    [BRLAPI_DOTS(1,0,1,0,0,1,1,0)] = 'U',
+    [BRLAPI_DOTS(1,1,1,0,0,1,1,0)] = 'V',
+    [BRLAPI_DOTS(0,1,0,1,1,1,1,0)] = 'W',
+    [BRLAPI_DOTS(1,0,1,1,0,1,1,0)] = 'X',
+    [BRLAPI_DOTS(1,0,1,1,1,1,1,0)] = 'Y',
+    [BRLAPI_DOTS(1,0,1,0,1,1,1,0)] = 'Z',
+
+    [BRLAPI_DOTS(0,0,1,0,1,1,0,0)] = '0',
+    [BRLAPI_DOTS(0,1,0,0,0,0,0,0)] = '1',
+    [BRLAPI_DOTS(0,1,1,0,0,0,0,0)] = '2',
+    [BRLAPI_DOTS(0,1,0,0,1,0,0,0)] = '3',
+    [BRLAPI_DOTS(0,1,0,0,1,1,0,0)] = '4',
+    [BRLAPI_DOTS(0,1,0,0,0,1,0,0)] = '5',
+    [BRLAPI_DOTS(0,1,1,0,1,0,0,0)] = '6',
+    [BRLAPI_DOTS(0,1,1,0,1,1,0,0)] = '7',
+    [BRLAPI_DOTS(0,1,1,0,0,1,0,0)] = '8',
+    [BRLAPI_DOTS(0,0,1,0,1,0,0,0)] = '9',
+
+    [BRLAPI_DOTS(0,0,0,1,0,1,0,0)] = '.',
+    [BRLAPI_DOTS(0,0,1,1,0,1,0,0)] = '+',
+    [BRLAPI_DOTS(0,0,1,0,0,1,0,0)] = '-',
+    [BRLAPI_DOTS(1,0,0,0,0,1,0,0)] = '*',
+    [BRLAPI_DOTS(0,0,1,1,0,0,0,0)] = '/',
+    [BRLAPI_DOTS(1,1,1,0,1,1,0,0)] = '(',
+    [BRLAPI_DOTS(0,1,1,1,1,1,0,0)] = ')',
+
+    [BRLAPI_DOTS(1,1,1,1,0,1,0,0)] = '&',
+    [BRLAPI_DOTS(0,0,1,1,1,1,0,0)] = '#',
+
+    [BRLAPI_DOTS(0,0,0,0,0,1,0,0)] = ',',
+    [BRLAPI_DOTS(0,0,0,0,1,1,0,0)] = ';',
+    [BRLAPI_DOTS(1,0,0,0,1,1,0,0)] = ':',
+    [BRLAPI_DOTS(0,1,1,1,0,1,0,0)] = '!',
+    [BRLAPI_DOTS(1,0,0,1,1,1,0,0)] = '?',
+    [BRLAPI_DOTS(0,0,0,0,1,0,0,0)] = '"',
+    [BRLAPI_DOTS(0,0,1,0,0,0,0,0)] ='\'',
+    [BRLAPI_DOTS(0,0,0,1,0,0,0,0)] = '`',
+    [BRLAPI_DOTS(0,0,0,1,1,0,1,0)] = '^',
+    [BRLAPI_DOTS(0,0,0,1,1,0,0,0)] = '~',
+    [BRLAPI_DOTS(0,1,0,1,0,1,1,0)] = '[',
+    [BRLAPI_DOTS(1,1,0,1,1,1,1,0)] = ']',
+    [BRLAPI_DOTS(0,1,0,1,0,1,0,0)] = '{',
+    [BRLAPI_DOTS(1,1,0,1,1,1,0,0)] = '}',
+    [BRLAPI_DOTS(1,1,1,1,1,1,0,0)] = '=',
+    [BRLAPI_DOTS(1,1,0,0,0,1,0,0)] = '<',
+    [BRLAPI_DOTS(0,0,1,1,1,0,0,0)] = '>',
+    [BRLAPI_DOTS(1,1,0,1,0,1,0,0)] = '$',
+    [BRLAPI_DOTS(1,0,0,1,0,1,0,0)] = '%',
+    [BRLAPI_DOTS(0,0,0,1,0,0,1,0)] = '@',
+    [BRLAPI_DOTS(1,1,0,0,1,1,0,0)] = '|',
+    [BRLAPI_DOTS(1,1,0,0,1,1,1,0)] ='\\',
+    [BRLAPI_DOTS(0,0,0,1,1,1,0,0)] = '_',
+};
+
+/* The serial port can receive more of our data */
+static void baum_accept_input(struct CharDriverState *chr)
+{
+    BaumDriverState *baum = chr->opaque;
+    int room, first;
+
+    if (!baum->out_buf_used)
+        return;
+    room = qemu_chr_be_can_write(chr);
+    if (!room)
+        return;
+    if (room > baum->out_buf_used)
+        room = baum->out_buf_used;
+
+    first = BUF_SIZE - baum->out_buf_ptr;
+    if (room > first) {
+        qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, first);
+        baum->out_buf_ptr = 0;
+        baum->out_buf_used -= first;
+        room -= first;
+    }
+    qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, room);
+    baum->out_buf_ptr += room;
+    baum->out_buf_used -= room;
+}
+
+/* We want to send a packet */
+static void baum_write_packet(BaumDriverState *baum, const uint8_t *buf, int len)
+{
+    uint8_t io_buf[1 + 2 * len], *cur = io_buf;
+    int room;
+    *cur++ = ESC;
+    while (len--)
+        if ((*cur++ = *buf++) == ESC)
+            *cur++ = ESC;
+    room = qemu_chr_be_can_write(baum->chr);
+    len = cur - io_buf;
+    if (len <= room) {
+        /* Fits */
+        qemu_chr_be_write(baum->chr, io_buf, len);
+    } else {
+        int first;
+        uint8_t out;
+        /* Can't fit all, send what can be, and store the rest. */
+        qemu_chr_be_write(baum->chr, io_buf, room);
+        len -= room;
+        cur = io_buf + room;
+        if (len > BUF_SIZE - baum->out_buf_used) {
+            /* Can't even store it, drop the previous data... */
+            assert(len <= BUF_SIZE);
+            baum->out_buf_used = 0;
+            baum->out_buf_ptr = 0;
+        }
+        out = baum->out_buf_ptr;
+        baum->out_buf_used += len;
+        first = BUF_SIZE - baum->out_buf_ptr;
+        if (len > first) {
+            memcpy(baum->out_buf + out, cur, first);
+            out = 0;
+            len -= first;
+            cur += first;
+        }
+        memcpy(baum->out_buf + out, cur, len);
+    }
+}
+
+/* Called when the other end seems to have a wrong idea of our display size */
+static void baum_cellCount_timer_cb(void *opaque)
+{
+    BaumDriverState *baum = opaque;
+    uint8_t cell_count[] = { BAUM_RSP_CellCount, baum->x * baum->y };
+    DPRINTF("Timeout waiting for DisplayData, sending cell count\n");
+    baum_write_packet(baum, cell_count, sizeof(cell_count));
+}
+
+/* Try to interpret a whole incoming packet */
+static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len)
+{
+    const uint8_t *cur = buf;
+    uint8_t req = 0;
+
+    if (!len--)
+        return 0;
+    if (*cur++ != ESC) {
+        while (*cur != ESC) {
+            if (!len--)
+                return 0;
+            cur++;
+        }
+        DPRINTF("Dropped %d bytes!\n", cur - buf);
+    }
+
+#define EAT(c) do {\
+    if (!len--) \
+        return 0; \
+    if ((c = *cur++) == ESC) { \
+        if (!len--) \
+            return 0; \
+        if (*cur++ != ESC) { \
+            DPRINTF("Broken packet %#2x, tossing\n", req); \
+		if (qemu_timer_pending(baum->cellCount_timer)) { \
+                qemu_del_timer(baum->cellCount_timer); \
+                baum_cellCount_timer_cb(baum); \
+            } \
+            return (cur - 2 - buf); \
+        } \
+    } \
+} while (0)
+
+    EAT(req);
+    switch (req) {
+    case BAUM_REQ_DisplayData:
+    {
+        uint8_t cells[baum->x * baum->y], c;
+        uint8_t text[baum->x * baum->y];
+        uint8_t zero[baum->x * baum->y];
+        int cursor = BRLAPI_CURSOR_OFF;
+        int i;
+
+        /* Allow 100ms to complete the DisplayData packet */
+        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);
+            cells[i] = c;
+            if ((c & (BRLAPI_DOT7|BRLAPI_DOT8))
+                    == (BRLAPI_DOT7|BRLAPI_DOT8)) {
+                cursor = i + 1;
+                c &= ~(BRLAPI_DOT7|BRLAPI_DOT8);
+            }
+            if (!(c = nabcc_translation[c]))
+                c = '?';
+            text[i] = c;
+        }
+        qemu_del_timer(baum->cellCount_timer);
+
+        memset(zero, 0, sizeof(zero));
+
+        brlapi_writeArguments_t wa = {
+            .displayNumber = BRLAPI_DISPLAY_DEFAULT,
+            .regionBegin = 1,
+            .regionSize = baum->x * baum->y,
+            .text = (char *)text,
+            .textSize = baum->x * baum->y,
+            .andMask = zero,
+            .orMask = cells,
+            .cursor = cursor,
+            .charset = (char *)"ISO-8859-1",
+        };
+
+        if (brlapi__write(baum->brlapi, &wa) == -1)
+            brlapi_perror("baum brlapi_write");
+        break;
+    }
+    case BAUM_REQ_SetMode:
+    {
+        uint8_t mode, setting;
+        DPRINTF("SetMode\n");
+        EAT(mode);
+        EAT(setting);
+        /* ignore */
+        break;
+    }
+    case BAUM_REQ_SetProtocol:
+    {
+        uint8_t protocol;
+        DPRINTF("SetProtocol\n");
+        EAT(protocol);
+        /* ignore */
+        break;
+    }
+    case BAUM_REQ_GetDeviceIdentity:
+    {
+        uint8_t identity[17] = { BAUM_RSP_DeviceIdentity,
+            'B','a','u','m',' ','V','a','r','i','o' };
+        DPRINTF("GetDeviceIdentity\n");
+        identity[11] = '0' + baum->x / 10;
+        identity[12] = '0' + baum->x % 10;
+        baum_write_packet(baum, identity, sizeof(identity));
+        break;
+    }
+    case BAUM_REQ_GetVersionNumber:
+    {
+        uint8_t version[] = { BAUM_RSP_VersionNumber, 1 }; /* ? */
+        DPRINTF("GetVersionNumber\n");
+        baum_write_packet(baum, version, sizeof(version));
+        break;
+    }
+    case BAUM_REQ_GetSerialNumber:
+    {
+        uint8_t serial[] = { BAUM_RSP_SerialNumber,
+            '0','0','0','0','0','0','0','0' };
+        DPRINTF("GetSerialNumber\n");
+        baum_write_packet(baum, serial, sizeof(serial));
+        break;
+    }
+    case BAUM_REQ_GetKeys:
+    {
+        DPRINTF("Get%0#2x\n", req);
+        /* ignore */
+        break;
+    }
+    default:
+        DPRINTF("unrecognized request %0#2x\n", req);
+        do
+            if (!len--)
+                return 0;
+        while (*cur++ != ESC);
+        cur--;
+        break;
+    }
+    return cur - buf;
+}
+
+/* The other end is writing some data.  Store it and try to interpret */
+static int baum_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+    BaumDriverState *baum = chr->opaque;
+    int tocopy, cur, eaten, orig_len = len;
+
+    if (!len)
+        return 0;
+    if (!baum->brlapi)
+        return len;
+
+    while (len) {
+        /* Complete our buffer as much as possible */
+        tocopy = len;
+        if (tocopy > BUF_SIZE - baum->in_buf_used)
+            tocopy = BUF_SIZE - baum->in_buf_used;
+
+        memcpy(baum->in_buf + baum->in_buf_used, buf, tocopy);
+        baum->in_buf_used += tocopy;
+        buf += tocopy;
+        len -= tocopy;
+
+        /* Interpret it as much as possible */
+        cur = 0;
+        while (cur < baum->in_buf_used &&
+                (eaten = baum_eat_packet(baum, baum->in_buf + cur, baum->in_buf_used - cur)))
+            cur += eaten;
+
+        /* Shift the remainder */
+        if (cur) {
+            memmove(baum->in_buf, baum->in_buf + cur, baum->in_buf_used - cur);
+            baum->in_buf_used -= cur;
+        }
+
+        /* And continue if any data left */
+    }
+    return orig_len;
+}
+
+/* Send the key code to the other end */
+static void baum_send_key(BaumDriverState *baum, uint8_t type, uint8_t value) {
+    uint8_t packet[] = { type, value };
+    DPRINTF("writing key %x %x\n", type, value);
+    baum_write_packet(baum, packet, sizeof(packet));
+}
+
+/* We got some data on the BrlAPI socket */
+static void baum_chr_read(void *opaque)
+{
+    BaumDriverState *baum = opaque;
+    brlapi_keyCode_t code;
+    int ret;
+    if (!baum->brlapi)
+        return;
+    while ((ret = brlapi__readKey(baum->brlapi, 0, &code)) == 1) {
+        DPRINTF("got key %"BRLAPI_PRIxKEYCODE"\n", code);
+        /* Emulate */
+        switch (code & BRLAPI_KEY_TYPE_MASK) {
+        case BRLAPI_KEY_TYPE_CMD:
+            switch (code & BRLAPI_KEY_CMD_BLK_MASK) {
+            case BRLAPI_KEY_CMD_ROUTE:
+                baum_send_key(baum, BAUM_RSP_RoutingKey, (code & BRLAPI_KEY_CMD_ARG_MASK)+1);
+                baum_send_key(baum, BAUM_RSP_RoutingKey, 0);
+                break;
+            case 0:
+                switch (code & BRLAPI_KEY_CMD_ARG_MASK) {
+                case BRLAPI_KEY_CMD_FWINLT:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_FWINRT:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR2);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_LNUP:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR1);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_LNDN:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR3);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_TOP:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TR1);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_BOT:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL3|BAUM_TR3);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_TOP_LEFT:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_BOT_LEFT:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR3);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_HOME:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1|BAUM_TR3);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                case BRLAPI_KEY_CMD_PREFMENU:
+                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TL3|BAUM_TR1);
+                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
+                    break;
+                }
+            }
+            break;
+        case BRLAPI_KEY_TYPE_SYM:
+            break;
+        }
+    }
+    if (ret == -1 && (brlapi_errno != BRLAPI_ERROR_LIBCERR || errno != EINTR)) {
+        brlapi_perror("baum: brlapi_readKey");
+        brlapi__closeConnection(baum->brlapi);
+        g_free(baum->brlapi);
+        baum->brlapi = NULL;
+    }
+}
+
+static void baum_close(struct CharDriverState *chr)
+{
+    BaumDriverState *baum = chr->opaque;
+
+    qemu_free_timer(baum->cellCount_timer);
+    if (baum->brlapi) {
+        brlapi__closeConnection(baum->brlapi);
+        g_free(baum->brlapi);
+    }
+    g_free(baum);
+}
+
+CharDriverState *chr_baum_init(QemuOpts *opts)
+{
+    BaumDriverState *baum;
+    CharDriverState *chr;
+    brlapi_handle_t *handle;
+#ifdef CONFIG_SDL
+    SDL_SysWMinfo info;
+#endif
+    int tty;
+
+    baum = g_malloc0(sizeof(BaumDriverState));
+    baum->chr = chr = g_malloc0(sizeof(CharDriverState));
+
+    chr->opaque = baum;
+    chr->chr_write = baum_write;
+    chr->chr_accept_input = baum_accept_input;
+    chr->chr_close = baum_close;
+
+    handle = g_malloc0(brlapi_getHandleSize());
+    baum->brlapi = handle;
+
+    baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL);
+    if (baum->brlapi_fd == -1) {
+        brlapi_perror("baum_init: brlapi_openConnection");
+        goto fail_handle;
+    }
+
+    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");
+        goto fail;
+    }
+
+#ifdef CONFIG_SDL
+    memset(&info, 0, sizeof(info));
+    SDL_VERSION(&info.version);
+    if (SDL_GetWMInfo(&info))
+        tty = info.info.x11.wmwindow;
+    else
+#endif
+        tty = BRLAPI_TTY_DEFAULT;
+
+    if (brlapi__enterTtyMode(handle, tty, NULL) == -1) {
+        brlapi_perror("baum_init: brlapi_enterTtyMode");
+        goto fail;
+    }
+
+    qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
+
+    qemu_chr_generic_open(chr);
+
+    return chr;
+
+fail:
+    qemu_free_timer(baum->cellCount_timer);
+    brlapi__closeConnection(handle);
+fail_handle:
+    g_free(handle);
+    g_free(chr);
+    g_free(baum);
+    return NULL;
+}
diff --git a/backends/msmouse.c b/backends/msmouse.c
new file mode 100644
index 0000000..bf2ff2a
--- /dev/null
+++ b/backends/msmouse.c
@@ -0,0 +1,78 @@
+/*
+ * QEMU Microsoft serial mouse emulation
+ *
+ * Copyright (c) 2008 Lubomir Rintel
+ *
+ * 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 <stdlib.h>
+#include "qemu-common.h"
+#include "char/char.h"
+#include "ui/console.h"
+#include "char/msmouse.h"
+
+#define MSMOUSE_LO6(n) ((n) & 0x3f)
+#define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6)
+
+static void msmouse_event(void *opaque,
+                          int dx, int dy, int dz, int buttons_state)
+{
+    CharDriverState *chr = (CharDriverState *)opaque;
+
+    unsigned char bytes[4] = { 0x40, 0x00, 0x00, 0x00 };
+
+    /* Movement deltas */
+    bytes[0] |= (MSMOUSE_HI2(dy) << 2) | MSMOUSE_HI2(dx);
+    bytes[1] |= MSMOUSE_LO6(dx);
+    bytes[2] |= MSMOUSE_LO6(dy);
+
+    /* Buttons */
+    bytes[0] |= (buttons_state & 0x01 ? 0x20 : 0x00);
+    bytes[0] |= (buttons_state & 0x02 ? 0x10 : 0x00);
+    bytes[3] |= (buttons_state & 0x04 ? 0x20 : 0x00);
+
+    /* We always send the packet of, so that we do not have to keep track
+       of previous state of the middle button. This can potentially confuse
+       some very old drivers for two button mice though. */
+    qemu_chr_be_write(chr, bytes, 4);
+}
+
+static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf, int len)
+{
+    /* Ignore writes to mouse port */
+    return len;
+}
+
+static void msmouse_chr_close (struct CharDriverState *chr)
+{
+    g_free (chr);
+}
+
+CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts)
+{
+    CharDriverState *chr;
+
+    chr = g_malloc0(sizeof(CharDriverState));
+    chr->chr_write = msmouse_chr_write;
+    chr->chr_close = msmouse_chr_close;
+
+    qemu_add_mouse_event_handler(msmouse_event, chr, 0, "QEMU Microsoft Mouse");
+
+    return chr;
+}
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 40ebe46..5750332 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -190,10 +190,9 @@ common-obj-$(CONFIG_SSI_SD) += ssi-sd.o
 common-obj-$(CONFIG_SD) += sd.o
 common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o
 common-obj-y += bt-hci-csr.o
-common-obj-y += msmouse.o ps2.o
+common-obj-y += ps2.o
 common-obj-y += qdev-monitor.o
 common-obj-y += qdev-properties-system.o
-common-obj-$(CONFIG_BRLAPI) += baum.o
 
 # xen backend driver support
 common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
@@ -218,5 +217,4 @@ obj-$(CONFIG_KVM) += ivshmem.o
 obj-$(CONFIG_LINUX) += vfio_pci.o
 endif
 
-$(obj)/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS) 
 endif
diff --git a/hw/baum.c b/hw/baum.c
deleted file mode 100644
index 09dcb9c..0000000
--- a/hw/baum.c
+++ /dev/null
@@ -1,627 +0,0 @@
-/*
- * QEMU Baum Braille Device
- *
- * Copyright (c) 2008 Samuel Thibault
- *
- * 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 "char/char.h"
-#include "qemu/timer.h"
-#include "usb.h"
-#include "baum.h"
-#include <brlapi.h>
-#include <brlapi_constants.h>
-#include <brlapi_keycodes.h>
-#ifdef CONFIG_SDL
-#include <SDL_syswm.h>
-#endif
-
-#if 0
-#define DPRINTF(fmt, ...) \
-        printf(fmt, ## __VA_ARGS__)
-#else
-#define DPRINTF(fmt, ...)
-#endif
-
-#define ESC 0x1B
-
-#define BAUM_REQ_DisplayData		0x01
-#define BAUM_REQ_GetVersionNumber	0x05
-#define BAUM_REQ_GetKeys		0x08
-#define BAUM_REQ_SetMode		0x12
-#define BAUM_REQ_SetProtocol		0x15
-#define BAUM_REQ_GetDeviceIdentity	0x84
-#define BAUM_REQ_GetSerialNumber	0x8A
-
-#define BAUM_RSP_CellCount		0x01
-#define BAUM_RSP_VersionNumber		0x05
-#define BAUM_RSP_ModeSetting		0x11
-#define BAUM_RSP_CommunicationChannel	0x16
-#define BAUM_RSP_PowerdownSignal	0x17
-#define BAUM_RSP_HorizontalSensors	0x20
-#define BAUM_RSP_VerticalSensors	0x21
-#define BAUM_RSP_RoutingKeys		0x22
-#define BAUM_RSP_Switches		0x23
-#define BAUM_RSP_TopKeys		0x24
-#define BAUM_RSP_HorizontalSensor	0x25
-#define BAUM_RSP_VerticalSensor		0x26
-#define BAUM_RSP_RoutingKey		0x27
-#define BAUM_RSP_FrontKeys6		0x28
-#define BAUM_RSP_BackKeys6		0x29
-#define BAUM_RSP_CommandKeys		0x2B
-#define BAUM_RSP_FrontKeys10		0x2C
-#define BAUM_RSP_BackKeys10		0x2D
-#define BAUM_RSP_EntryKeys		0x33
-#define BAUM_RSP_JoyStick		0x34
-#define BAUM_RSP_ErrorCode		0x40
-#define BAUM_RSP_InfoBlock		0x42
-#define BAUM_RSP_DeviceIdentity		0x84
-#define BAUM_RSP_SerialNumber		0x8A
-#define BAUM_RSP_BluetoothName		0x8C
-
-#define BAUM_TL1 0x01
-#define BAUM_TL2 0x02
-#define BAUM_TL3 0x04
-#define BAUM_TR1 0x08
-#define BAUM_TR2 0x10
-#define BAUM_TR3 0x20
-
-#define BUF_SIZE 256
-
-typedef struct {
-    CharDriverState *chr;
-
-    brlapi_handle_t *brlapi;
-    int brlapi_fd;
-    unsigned int x, y;
-
-    uint8_t in_buf[BUF_SIZE];
-    uint8_t in_buf_used;
-    uint8_t out_buf[BUF_SIZE];
-    uint8_t out_buf_used, out_buf_ptr;
-
-    QEMUTimer *cellCount_timer;
-} BaumDriverState;
-
-/* Let's assume NABCC by default */
-static const uint8_t nabcc_translation[256] = {
-    [0] = ' ',
-#ifndef BRLAPI_DOTS
-#define BRLAPI_DOTS(d1,d2,d3,d4,d5,d6,d7,d8) \
-    ((d1?BRLAPI_DOT1:0)|\
-     (d2?BRLAPI_DOT2:0)|\
-     (d3?BRLAPI_DOT3:0)|\
-     (d4?BRLAPI_DOT4:0)|\
-     (d5?BRLAPI_DOT5:0)|\
-     (d6?BRLAPI_DOT6:0)|\
-     (d7?BRLAPI_DOT7:0)|\
-     (d8?BRLAPI_DOT8:0))
-#endif
-    [BRLAPI_DOTS(1,0,0,0,0,0,0,0)] = 'a',
-    [BRLAPI_DOTS(1,1,0,0,0,0,0,0)] = 'b',
-    [BRLAPI_DOTS(1,0,0,1,0,0,0,0)] = 'c',
-    [BRLAPI_DOTS(1,0,0,1,1,0,0,0)] = 'd',
-    [BRLAPI_DOTS(1,0,0,0,1,0,0,0)] = 'e',
-    [BRLAPI_DOTS(1,1,0,1,0,0,0,0)] = 'f',
-    [BRLAPI_DOTS(1,1,0,1,1,0,0,0)] = 'g',
-    [BRLAPI_DOTS(1,1,0,0,1,0,0,0)] = 'h',
-    [BRLAPI_DOTS(0,1,0,1,0,0,0,0)] = 'i',
-    [BRLAPI_DOTS(0,1,0,1,1,0,0,0)] = 'j',
-    [BRLAPI_DOTS(1,0,1,0,0,0,0,0)] = 'k',
-    [BRLAPI_DOTS(1,1,1,0,0,0,0,0)] = 'l',
-    [BRLAPI_DOTS(1,0,1,1,0,0,0,0)] = 'm',
-    [BRLAPI_DOTS(1,0,1,1,1,0,0,0)] = 'n',
-    [BRLAPI_DOTS(1,0,1,0,1,0,0,0)] = 'o',
-    [BRLAPI_DOTS(1,1,1,1,0,0,0,0)] = 'p',
-    [BRLAPI_DOTS(1,1,1,1,1,0,0,0)] = 'q',
-    [BRLAPI_DOTS(1,1,1,0,1,0,0,0)] = 'r',
-    [BRLAPI_DOTS(0,1,1,1,0,0,0,0)] = 's',
-    [BRLAPI_DOTS(0,1,1,1,1,0,0,0)] = 't',
-    [BRLAPI_DOTS(1,0,1,0,0,1,0,0)] = 'u',
-    [BRLAPI_DOTS(1,1,1,0,0,1,0,0)] = 'v',
-    [BRLAPI_DOTS(0,1,0,1,1,1,0,0)] = 'w',
-    [BRLAPI_DOTS(1,0,1,1,0,1,0,0)] = 'x',
-    [BRLAPI_DOTS(1,0,1,1,1,1,0,0)] = 'y',
-    [BRLAPI_DOTS(1,0,1,0,1,1,0,0)] = 'z',
-
-    [BRLAPI_DOTS(1,0,0,0,0,0,1,0)] = 'A',
-    [BRLAPI_DOTS(1,1,0,0,0,0,1,0)] = 'B',
-    [BRLAPI_DOTS(1,0,0,1,0,0,1,0)] = 'C',
-    [BRLAPI_DOTS(1,0,0,1,1,0,1,0)] = 'D',
-    [BRLAPI_DOTS(1,0,0,0,1,0,1,0)] = 'E',
-    [BRLAPI_DOTS(1,1,0,1,0,0,1,0)] = 'F',
-    [BRLAPI_DOTS(1,1,0,1,1,0,1,0)] = 'G',
-    [BRLAPI_DOTS(1,1,0,0,1,0,1,0)] = 'H',
-    [BRLAPI_DOTS(0,1,0,1,0,0,1,0)] = 'I',
-    [BRLAPI_DOTS(0,1,0,1,1,0,1,0)] = 'J',
-    [BRLAPI_DOTS(1,0,1,0,0,0,1,0)] = 'K',
-    [BRLAPI_DOTS(1,1,1,0,0,0,1,0)] = 'L',
-    [BRLAPI_DOTS(1,0,1,1,0,0,1,0)] = 'M',
-    [BRLAPI_DOTS(1,0,1,1,1,0,1,0)] = 'N',
-    [BRLAPI_DOTS(1,0,1,0,1,0,1,0)] = 'O',
-    [BRLAPI_DOTS(1,1,1,1,0,0,1,0)] = 'P',
-    [BRLAPI_DOTS(1,1,1,1,1,0,1,0)] = 'Q',
-    [BRLAPI_DOTS(1,1,1,0,1,0,1,0)] = 'R',
-    [BRLAPI_DOTS(0,1,1,1,0,0,1,0)] = 'S',
-    [BRLAPI_DOTS(0,1,1,1,1,0,1,0)] = 'T',
-    [BRLAPI_DOTS(1,0,1,0,0,1,1,0)] = 'U',
-    [BRLAPI_DOTS(1,1,1,0,0,1,1,0)] = 'V',
-    [BRLAPI_DOTS(0,1,0,1,1,1,1,0)] = 'W',
-    [BRLAPI_DOTS(1,0,1,1,0,1,1,0)] = 'X',
-    [BRLAPI_DOTS(1,0,1,1,1,1,1,0)] = 'Y',
-    [BRLAPI_DOTS(1,0,1,0,1,1,1,0)] = 'Z',
-
-    [BRLAPI_DOTS(0,0,1,0,1,1,0,0)] = '0',
-    [BRLAPI_DOTS(0,1,0,0,0,0,0,0)] = '1',
-    [BRLAPI_DOTS(0,1,1,0,0,0,0,0)] = '2',
-    [BRLAPI_DOTS(0,1,0,0,1,0,0,0)] = '3',
-    [BRLAPI_DOTS(0,1,0,0,1,1,0,0)] = '4',
-    [BRLAPI_DOTS(0,1,0,0,0,1,0,0)] = '5',
-    [BRLAPI_DOTS(0,1,1,0,1,0,0,0)] = '6',
-    [BRLAPI_DOTS(0,1,1,0,1,1,0,0)] = '7',
-    [BRLAPI_DOTS(0,1,1,0,0,1,0,0)] = '8',
-    [BRLAPI_DOTS(0,0,1,0,1,0,0,0)] = '9',
-
-    [BRLAPI_DOTS(0,0,0,1,0,1,0,0)] = '.',
-    [BRLAPI_DOTS(0,0,1,1,0,1,0,0)] = '+',
-    [BRLAPI_DOTS(0,0,1,0,0,1,0,0)] = '-',
-    [BRLAPI_DOTS(1,0,0,0,0,1,0,0)] = '*',
-    [BRLAPI_DOTS(0,0,1,1,0,0,0,0)] = '/',
-    [BRLAPI_DOTS(1,1,1,0,1,1,0,0)] = '(',
-    [BRLAPI_DOTS(0,1,1,1,1,1,0,0)] = ')',
-
-    [BRLAPI_DOTS(1,1,1,1,0,1,0,0)] = '&',
-    [BRLAPI_DOTS(0,0,1,1,1,1,0,0)] = '#',
-
-    [BRLAPI_DOTS(0,0,0,0,0,1,0,0)] = ',',
-    [BRLAPI_DOTS(0,0,0,0,1,1,0,0)] = ';',
-    [BRLAPI_DOTS(1,0,0,0,1,1,0,0)] = ':',
-    [BRLAPI_DOTS(0,1,1,1,0,1,0,0)] = '!',
-    [BRLAPI_DOTS(1,0,0,1,1,1,0,0)] = '?',
-    [BRLAPI_DOTS(0,0,0,0,1,0,0,0)] = '"',
-    [BRLAPI_DOTS(0,0,1,0,0,0,0,0)] ='\'',
-    [BRLAPI_DOTS(0,0,0,1,0,0,0,0)] = '`',
-    [BRLAPI_DOTS(0,0,0,1,1,0,1,0)] = '^',
-    [BRLAPI_DOTS(0,0,0,1,1,0,0,0)] = '~',
-    [BRLAPI_DOTS(0,1,0,1,0,1,1,0)] = '[',
-    [BRLAPI_DOTS(1,1,0,1,1,1,1,0)] = ']',
-    [BRLAPI_DOTS(0,1,0,1,0,1,0,0)] = '{',
-    [BRLAPI_DOTS(1,1,0,1,1,1,0,0)] = '}',
-    [BRLAPI_DOTS(1,1,1,1,1,1,0,0)] = '=',
-    [BRLAPI_DOTS(1,1,0,0,0,1,0,0)] = '<',
-    [BRLAPI_DOTS(0,0,1,1,1,0,0,0)] = '>',
-    [BRLAPI_DOTS(1,1,0,1,0,1,0,0)] = '$',
-    [BRLAPI_DOTS(1,0,0,1,0,1,0,0)] = '%',
-    [BRLAPI_DOTS(0,0,0,1,0,0,1,0)] = '@',
-    [BRLAPI_DOTS(1,1,0,0,1,1,0,0)] = '|',
-    [BRLAPI_DOTS(1,1,0,0,1,1,1,0)] ='\\',
-    [BRLAPI_DOTS(0,0,0,1,1,1,0,0)] = '_',
-};
-
-/* The serial port can receive more of our data */
-static void baum_accept_input(struct CharDriverState *chr)
-{
-    BaumDriverState *baum = chr->opaque;
-    int room, first;
-
-    if (!baum->out_buf_used)
-        return;
-    room = qemu_chr_be_can_write(chr);
-    if (!room)
-        return;
-    if (room > baum->out_buf_used)
-        room = baum->out_buf_used;
-
-    first = BUF_SIZE - baum->out_buf_ptr;
-    if (room > first) {
-        qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, first);
-        baum->out_buf_ptr = 0;
-        baum->out_buf_used -= first;
-        room -= first;
-    }
-    qemu_chr_be_write(chr, baum->out_buf + baum->out_buf_ptr, room);
-    baum->out_buf_ptr += room;
-    baum->out_buf_used -= room;
-}
-
-/* We want to send a packet */
-static void baum_write_packet(BaumDriverState *baum, const uint8_t *buf, int len)
-{
-    uint8_t io_buf[1 + 2 * len], *cur = io_buf;
-    int room;
-    *cur++ = ESC;
-    while (len--)
-        if ((*cur++ = *buf++) == ESC)
-            *cur++ = ESC;
-    room = qemu_chr_be_can_write(baum->chr);
-    len = cur - io_buf;
-    if (len <= room) {
-        /* Fits */
-        qemu_chr_be_write(baum->chr, io_buf, len);
-    } else {
-        int first;
-        uint8_t out;
-        /* Can't fit all, send what can be, and store the rest. */
-        qemu_chr_be_write(baum->chr, io_buf, room);
-        len -= room;
-        cur = io_buf + room;
-        if (len > BUF_SIZE - baum->out_buf_used) {
-            /* Can't even store it, drop the previous data... */
-            assert(len <= BUF_SIZE);
-            baum->out_buf_used = 0;
-            baum->out_buf_ptr = 0;
-        }
-        out = baum->out_buf_ptr;
-        baum->out_buf_used += len;
-        first = BUF_SIZE - baum->out_buf_ptr;
-        if (len > first) {
-            memcpy(baum->out_buf + out, cur, first);
-            out = 0;
-            len -= first;
-            cur += first;
-        }
-        memcpy(baum->out_buf + out, cur, len);
-    }
-}
-
-/* Called when the other end seems to have a wrong idea of our display size */
-static void baum_cellCount_timer_cb(void *opaque)
-{
-    BaumDriverState *baum = opaque;
-    uint8_t cell_count[] = { BAUM_RSP_CellCount, baum->x * baum->y };
-    DPRINTF("Timeout waiting for DisplayData, sending cell count\n");
-    baum_write_packet(baum, cell_count, sizeof(cell_count));
-}
-
-/* Try to interpret a whole incoming packet */
-static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len)
-{
-    const uint8_t *cur = buf;
-    uint8_t req = 0;
-
-    if (!len--)
-        return 0;
-    if (*cur++ != ESC) {
-        while (*cur != ESC) {
-            if (!len--)
-                return 0;
-            cur++;
-        }
-        DPRINTF("Dropped %d bytes!\n", cur - buf);
-    }
-
-#define EAT(c) do {\
-    if (!len--) \
-        return 0; \
-    if ((c = *cur++) == ESC) { \
-        if (!len--) \
-            return 0; \
-        if (*cur++ != ESC) { \
-            DPRINTF("Broken packet %#2x, tossing\n", req); \
-		if (qemu_timer_pending(baum->cellCount_timer)) { \
-                qemu_del_timer(baum->cellCount_timer); \
-                baum_cellCount_timer_cb(baum); \
-            } \
-            return (cur - 2 - buf); \
-        } \
-    } \
-} while (0)
-
-    EAT(req);
-    switch (req) {
-    case BAUM_REQ_DisplayData:
-    {
-        uint8_t cells[baum->x * baum->y], c;
-        uint8_t text[baum->x * baum->y];
-        uint8_t zero[baum->x * baum->y];
-        int cursor = BRLAPI_CURSOR_OFF;
-        int i;
-
-        /* Allow 100ms to complete the DisplayData packet */
-        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);
-            cells[i] = c;
-            if ((c & (BRLAPI_DOT7|BRLAPI_DOT8))
-                    == (BRLAPI_DOT7|BRLAPI_DOT8)) {
-                cursor = i + 1;
-                c &= ~(BRLAPI_DOT7|BRLAPI_DOT8);
-            }
-            if (!(c = nabcc_translation[c]))
-                c = '?';
-            text[i] = c;
-        }
-        qemu_del_timer(baum->cellCount_timer);
-
-        memset(zero, 0, sizeof(zero));
-
-        brlapi_writeArguments_t wa = {
-            .displayNumber = BRLAPI_DISPLAY_DEFAULT,
-            .regionBegin = 1,
-            .regionSize = baum->x * baum->y,
-            .text = (char *)text,
-            .textSize = baum->x * baum->y,
-            .andMask = zero,
-            .orMask = cells,
-            .cursor = cursor,
-            .charset = (char *)"ISO-8859-1",
-        };
-
-        if (brlapi__write(baum->brlapi, &wa) == -1)
-            brlapi_perror("baum brlapi_write");
-        break;
-    }
-    case BAUM_REQ_SetMode:
-    {
-        uint8_t mode, setting;
-        DPRINTF("SetMode\n");
-        EAT(mode);
-        EAT(setting);
-        /* ignore */
-        break;
-    }
-    case BAUM_REQ_SetProtocol:
-    {
-        uint8_t protocol;
-        DPRINTF("SetProtocol\n");
-        EAT(protocol);
-        /* ignore */
-        break;
-    }
-    case BAUM_REQ_GetDeviceIdentity:
-    {
-        uint8_t identity[17] = { BAUM_RSP_DeviceIdentity,
-            'B','a','u','m',' ','V','a','r','i','o' };
-        DPRINTF("GetDeviceIdentity\n");
-        identity[11] = '0' + baum->x / 10;
-        identity[12] = '0' + baum->x % 10;
-        baum_write_packet(baum, identity, sizeof(identity));
-        break;
-    }
-    case BAUM_REQ_GetVersionNumber:
-    {
-        uint8_t version[] = { BAUM_RSP_VersionNumber, 1 }; /* ? */
-        DPRINTF("GetVersionNumber\n");
-        baum_write_packet(baum, version, sizeof(version));
-        break;
-    }
-    case BAUM_REQ_GetSerialNumber:
-    {
-        uint8_t serial[] = { BAUM_RSP_SerialNumber,
-            '0','0','0','0','0','0','0','0' };
-        DPRINTF("GetSerialNumber\n");
-        baum_write_packet(baum, serial, sizeof(serial));
-        break;
-    }
-    case BAUM_REQ_GetKeys:
-    {
-        DPRINTF("Get%0#2x\n", req);
-        /* ignore */
-        break;
-    }
-    default:
-        DPRINTF("unrecognized request %0#2x\n", req);
-        do
-            if (!len--)
-                return 0;
-        while (*cur++ != ESC);
-        cur--;
-        break;
-    }
-    return cur - buf;
-}
-
-/* The other end is writing some data.  Store it and try to interpret */
-static int baum_write(CharDriverState *chr, const uint8_t *buf, int len)
-{
-    BaumDriverState *baum = chr->opaque;
-    int tocopy, cur, eaten, orig_len = len;
-
-    if (!len)
-        return 0;
-    if (!baum->brlapi)
-        return len;
-
-    while (len) {
-        /* Complete our buffer as much as possible */
-        tocopy = len;
-        if (tocopy > BUF_SIZE - baum->in_buf_used)
-            tocopy = BUF_SIZE - baum->in_buf_used;
-
-        memcpy(baum->in_buf + baum->in_buf_used, buf, tocopy);
-        baum->in_buf_used += tocopy;
-        buf += tocopy;
-        len -= tocopy;
-
-        /* Interpret it as much as possible */
-        cur = 0;
-        while (cur < baum->in_buf_used &&
-                (eaten = baum_eat_packet(baum, baum->in_buf + cur, baum->in_buf_used - cur)))
-            cur += eaten;
-
-        /* Shift the remainder */
-        if (cur) {
-            memmove(baum->in_buf, baum->in_buf + cur, baum->in_buf_used - cur);
-            baum->in_buf_used -= cur;
-        }
-
-        /* And continue if any data left */
-    }
-    return orig_len;
-}
-
-/* Send the key code to the other end */
-static void baum_send_key(BaumDriverState *baum, uint8_t type, uint8_t value) {
-    uint8_t packet[] = { type, value };
-    DPRINTF("writing key %x %x\n", type, value);
-    baum_write_packet(baum, packet, sizeof(packet));
-}
-
-/* We got some data on the BrlAPI socket */
-static void baum_chr_read(void *opaque)
-{
-    BaumDriverState *baum = opaque;
-    brlapi_keyCode_t code;
-    int ret;
-    if (!baum->brlapi)
-        return;
-    while ((ret = brlapi__readKey(baum->brlapi, 0, &code)) == 1) {
-        DPRINTF("got key %"BRLAPI_PRIxKEYCODE"\n", code);
-        /* Emulate */
-        switch (code & BRLAPI_KEY_TYPE_MASK) {
-        case BRLAPI_KEY_TYPE_CMD:
-            switch (code & BRLAPI_KEY_CMD_BLK_MASK) {
-            case BRLAPI_KEY_CMD_ROUTE:
-                baum_send_key(baum, BAUM_RSP_RoutingKey, (code & BRLAPI_KEY_CMD_ARG_MASK)+1);
-                baum_send_key(baum, BAUM_RSP_RoutingKey, 0);
-                break;
-            case 0:
-                switch (code & BRLAPI_KEY_CMD_ARG_MASK) {
-                case BRLAPI_KEY_CMD_FWINLT:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_FWINRT:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR2);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_LNUP:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR1);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_LNDN:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TR3);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_TOP:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TR1);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_BOT:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL3|BAUM_TR3);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_TOP_LEFT:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_BOT_LEFT:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR3);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_HOME:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL2|BAUM_TR1|BAUM_TR3);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                case BRLAPI_KEY_CMD_PREFMENU:
-                    baum_send_key(baum, BAUM_RSP_TopKeys, BAUM_TL1|BAUM_TL3|BAUM_TR1);
-                    baum_send_key(baum, BAUM_RSP_TopKeys, 0);
-                    break;
-                }
-            }
-            break;
-        case BRLAPI_KEY_TYPE_SYM:
-            break;
-        }
-    }
-    if (ret == -1 && (brlapi_errno != BRLAPI_ERROR_LIBCERR || errno != EINTR)) {
-        brlapi_perror("baum: brlapi_readKey");
-        brlapi__closeConnection(baum->brlapi);
-        g_free(baum->brlapi);
-        baum->brlapi = NULL;
-    }
-}
-
-static void baum_close(struct CharDriverState *chr)
-{
-    BaumDriverState *baum = chr->opaque;
-
-    qemu_free_timer(baum->cellCount_timer);
-    if (baum->brlapi) {
-        brlapi__closeConnection(baum->brlapi);
-        g_free(baum->brlapi);
-    }
-    g_free(baum);
-}
-
-CharDriverState *chr_baum_init(QemuOpts *opts)
-{
-    BaumDriverState *baum;
-    CharDriverState *chr;
-    brlapi_handle_t *handle;
-#ifdef CONFIG_SDL
-    SDL_SysWMinfo info;
-#endif
-    int tty;
-
-    baum = g_malloc0(sizeof(BaumDriverState));
-    baum->chr = chr = g_malloc0(sizeof(CharDriverState));
-
-    chr->opaque = baum;
-    chr->chr_write = baum_write;
-    chr->chr_accept_input = baum_accept_input;
-    chr->chr_close = baum_close;
-
-    handle = g_malloc0(brlapi_getHandleSize());
-    baum->brlapi = handle;
-
-    baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL);
-    if (baum->brlapi_fd == -1) {
-        brlapi_perror("baum_init: brlapi_openConnection");
-        goto fail_handle;
-    }
-
-    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");
-        goto fail;
-    }
-
-#ifdef CONFIG_SDL
-    memset(&info, 0, sizeof(info));
-    SDL_VERSION(&info.version);
-    if (SDL_GetWMInfo(&info))
-        tty = info.info.x11.wmwindow;
-    else
-#endif
-        tty = BRLAPI_TTY_DEFAULT;
-
-    if (brlapi__enterTtyMode(handle, tty, NULL) == -1) {
-        brlapi_perror("baum_init: brlapi_enterTtyMode");
-        goto fail;
-    }
-
-    qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
-
-    qemu_chr_generic_open(chr);
-
-    return chr;
-
-fail:
-    qemu_free_timer(baum->cellCount_timer);
-    brlapi__closeConnection(handle);
-fail_handle:
-    g_free(handle);
-    g_free(chr);
-    g_free(baum);
-    return NULL;
-}
diff --git a/hw/baum.h b/hw/baum.h
deleted file mode 100644
index 7635884..0000000
--- a/hw/baum.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * QEMU Baum
- *
- * Copyright (c) 2008 Samuel Thibault
- *
- * 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 HW_BAUM_H
-#define HW_BAUM_H 1
-
-/* char device */
-CharDriverState *chr_baum_init(QemuOpts *opts);
-
-#endif
diff --git a/hw/msmouse.c b/hw/msmouse.c
deleted file mode 100644
index ef47aed..0000000
--- a/hw/msmouse.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * QEMU Microsoft serial mouse emulation
- *
- * Copyright (c) 2008 Lubomir Rintel
- *
- * 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 <stdlib.h>
-#include "qemu-common.h"
-#include "char/char.h"
-#include "ui/console.h"
-#include "msmouse.h"
-
-#define MSMOUSE_LO6(n) ((n) & 0x3f)
-#define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6)
-
-static void msmouse_event(void *opaque,
-                          int dx, int dy, int dz, int buttons_state)
-{
-    CharDriverState *chr = (CharDriverState *)opaque;
-
-    unsigned char bytes[4] = { 0x40, 0x00, 0x00, 0x00 };
-
-    /* Movement deltas */
-    bytes[0] |= (MSMOUSE_HI2(dy) << 2) | MSMOUSE_HI2(dx);
-    bytes[1] |= MSMOUSE_LO6(dx);
-    bytes[2] |= MSMOUSE_LO6(dy);
-
-    /* Buttons */
-    bytes[0] |= (buttons_state & 0x01 ? 0x20 : 0x00);
-    bytes[0] |= (buttons_state & 0x02 ? 0x10 : 0x00);
-    bytes[3] |= (buttons_state & 0x04 ? 0x20 : 0x00);
-
-    /* We always send the packet of, so that we do not have to keep track
-       of previous state of the middle button. This can potentially confuse
-       some very old drivers for two button mice though. */
-    qemu_chr_be_write(chr, bytes, 4);
-}
-
-static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf, int len)
-{
-    /* Ignore writes to mouse port */
-    return len;
-}
-
-static void msmouse_chr_close (struct CharDriverState *chr)
-{
-    g_free (chr);
-}
-
-CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts)
-{
-    CharDriverState *chr;
-
-    chr = g_malloc0(sizeof(CharDriverState));
-    chr->chr_write = msmouse_chr_write;
-    chr->chr_close = msmouse_chr_close;
-
-    qemu_add_mouse_event_handler(msmouse_event, chr, 0, "QEMU Microsoft Mouse");
-
-    return chr;
-}
diff --git a/hw/msmouse.h b/hw/msmouse.h
deleted file mode 100644
index 8cff3a7..0000000
--- a/hw/msmouse.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef HW_MSMOUSE_H
-#define HW_MSMOUSE_H 1
-
-/* msmouse.c */
-CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts);
-
-#endif
diff --git a/include/char/baum.h b/include/char/baum.h
new file mode 100644
index 0000000..7635884
--- /dev/null
+++ b/include/char/baum.h
@@ -0,0 +1,30 @@
+/*
+ * QEMU Baum
+ *
+ * Copyright (c) 2008 Samuel Thibault
+ *
+ * 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 HW_BAUM_H
+#define HW_BAUM_H 1
+
+/* char device */
+CharDriverState *chr_baum_init(QemuOpts *opts);
+
+#endif
diff --git a/include/char/msmouse.h b/include/char/msmouse.h
new file mode 100644
index 0000000..8cff3a7
--- /dev/null
+++ b/include/char/msmouse.h
@@ -0,0 +1,7 @@
+#ifndef HW_MSMOUSE_H
+#define HW_MSMOUSE_H 1
+
+/* msmouse.c */
+CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts);
+
+#endif
diff --git a/qemu-char.c b/qemu-char.c
index 160decc..6dc1474 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -28,8 +28,8 @@
 #include "qemu/timer.h"
 #include "char/char.h"
 #include "hw/usb.h"
-#include "hw/baum.h"
-#include "hw/msmouse.h"
+#include "char/baum.h"
+#include "char/msmouse.h"
 #include "qmp-commands.h"
 
 #include <unistd.h>
diff --git a/vl.c b/vl.c
index c03edf1..e0a8eeb 100644
--- a/vl.c
+++ b/vl.c
@@ -119,7 +119,7 @@ int main(int argc, char **argv)
 #include "hw/pcmcia.h"
 #include "hw/pc.h"
 #include "hw/isa.h"
-#include "hw/baum.h"
+#include "char/baum.h"
 #include "hw/bt.h"
 #include "hw/watchdog.h"
 #include "hw/smbios.h"
commit 288f1e3f87ec24abeac38399f175fe74243f7bc5
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Feb 28 18:23:16 2013 +0000

    cadence_gem: Add debug msgs for rx desc movement
    
    Add some helpful messages that show the rx descriptor pointer moving as packets
    are rxed.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 1ef2eb34dade64d589a69a2bcfd5aaddb7d50164.1360901435.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/cadence_gem.c b/hw/cadence_gem.c
index 61f1801..de7d15a 100644
--- a/hw/cadence_gem.c
+++ b/hw/cadence_gem.c
@@ -724,7 +724,9 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
     s->rx_desc_addr = last_desc_addr;
     if (rx_desc_get_wrap(desc)) {
         s->rx_desc_addr = s->regs[GEM_RXQBASE];
+        DB_PRINT("wrapping RX descriptor list\n");
     } else {
+        DB_PRINT("incrementing RX descriptor list\n");
         s->rx_desc_addr += 8;
     }
 
commit 5025388b5083f199b05cc252c2b031d9fc230391
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Feb 28 18:23:16 2013 +0000

    cadence_gem: Don't reset rx desc pointer on rx_en
    
    This doesn't happen in the real hardware. The Zynq TRM explicitly states that
    this bit has no effect on the rx descriptor pointer ("The receive queue
    pointer register is unaffected").
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 06fdf92b78ee62d8965779bafd29c8df1a5d2718.1360901435.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/cadence_gem.c b/hw/cadence_gem.c
index a1ac069..61f1801 100644
--- a/hw/cadence_gem.c
+++ b/hw/cadence_gem.c
@@ -1083,10 +1083,6 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
             /* Reset to start of Q when transmit disabled. */
             s->tx_desc_addr = s->regs[GEM_TXQBASE];
         }
-        if (!(val & GEM_NWCTRL_RXENA)) {
-            /* Reset to start of Q when receive disabled. */
-            s->rx_desc_addr = s->regs[GEM_RXQBASE];
-        }
         if (val & GEM_NWCTRL_RXENA) {
             qemu_flush_queued_packets(qemu_get_queue(s->nic));
         }
commit ae80a3546f412c407199b9b7ebd52ac604361e10
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Feb 28 18:23:15 2013 +0000

    cadence_gem: fix interrupt events
    
    Bits in the ISR were continually mirroring their corresponding TX/RX SR bits.
    This is incorrect. The ISR bits are only ever set at the time their
    corresponding event occurs.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: cedfb6d108318846480b416a6041023ea5a353d6.1360901435.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/cadence_gem.c b/hw/cadence_gem.c
index 966ab4f..a1ac069 100644
--- a/hw/cadence_gem.c
+++ b/hw/cadence_gem.c
@@ -427,32 +427,9 @@ static int gem_can_receive(NetClientState *nc)
  */
 static void gem_update_int_status(GemState *s)
 {
-    uint32_t new_interrupts = 0;
-    /* Packet transmitted ? */
-    if (s->regs[GEM_TXSTATUS] & GEM_TXSTATUS_TXCMPL) {
-        new_interrupts |= GEM_INT_TXCMPL;
-    }
-    /* End of TX ring ? */
-    if (s->regs[GEM_TXSTATUS] & GEM_TXSTATUS_USED) {
-        new_interrupts |= GEM_INT_TXUSED;
-    }
-
-    /* Frame received ? */
-    if (s->regs[GEM_RXSTATUS] & GEM_RXSTATUS_FRMRCVD) {
-        new_interrupts |= GEM_INT_RXCMPL;
-    }
-    /* RX ring full ? */
-    if (s->regs[GEM_RXSTATUS] & GEM_RXSTATUS_NOBUF) {
-        new_interrupts |= GEM_INT_RXUSED;
-    }
-
-    s->regs[GEM_ISR] |= new_interrupts & ~(s->regs[GEM_IMR]);
-
     if (s->regs[GEM_ISR]) {
         DB_PRINT("asserting int. (0x%08x)\n", s->regs[GEM_ISR]);
         qemu_set_irq(s->irq, 1);
-    } else {
-        qemu_set_irq(s->irq, 0);
     }
 }
 
@@ -697,6 +674,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
             DB_PRINT("descriptor 0x%x owned by sw.\n",
                      (unsigned)packet_desc_addr);
             s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_NOBUF;
+            s->regs[GEM_ISR] |= GEM_INT_RXUSED & ~(s->regs[GEM_IMR]);
             /* Handle interrupt consequences */
             gem_update_int_status(s);
             return -1;
@@ -765,6 +743,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
                               (uint8_t *)&desc[0], sizeof(desc));
 
     s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_FRMRCVD;
+    s->regs[GEM_ISR] |= GEM_INT_RXCMPL & ~(s->regs[GEM_IMR]);
 
     /* Handle interrupt consequences */
     gem_update_int_status(s);
@@ -894,6 +873,7 @@ static void gem_transmit(GemState *s)
             DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr);
 
             s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_TXCMPL;
+            s->regs[GEM_ISR] |= GEM_INT_TXCMPL & ~(s->regs[GEM_IMR]);
 
             /* Handle interrupt consequences */
             gem_update_int_status(s);
@@ -931,6 +911,7 @@ static void gem_transmit(GemState *s)
 
     if (tx_desc_get_used(desc)) {
         s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_USED;
+        s->regs[GEM_ISR] |= GEM_INT_TXUSED & ~(s->regs[GEM_IMR]);
         gem_update_int_status(s);
     }
 }
commit 1c5d07909aea7657c7c6b24223460150526369ba
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Feb 28 18:23:15 2013 +0000

    cadence_gem: factor out can_rx() logic replication
    
    The gem_receive() function replicates the logic for whether or not the device
    can rx. Just call the actual gem_can_receive() function in place.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: bf7f93969f3e01fbc76d68d2955307fdbad11bb1.1360901435.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/cadence_gem.c b/hw/cadence_gem.c
index e6032ea..966ab4f 100644
--- a/hw/cadence_gem.c
+++ b/hw/cadence_gem.c
@@ -615,7 +615,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
     s = qemu_get_nic_opaque(nc);
 
     /* Do nothing if receive is not enabled. */
-    if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_RXENA)) {
+    if (!gem_can_receive(nc)) {
         return -1;
     }
 
commit e3f9d31c9899cc94e124b042d7d5353dbfd812ca
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Feb 28 18:23:15 2013 +0000

    cadence_gem: Flush queued packets
    
    The device needs to check for queued RX packets when the RX path is re-enabled.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 1fa8c88a3b7c654886d0a7484c2463cd4c2a2781.1360901435.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/cadence_gem.c b/hw/cadence_gem.c
index ab86c17..e6032ea 100644
--- a/hw/cadence_gem.c
+++ b/hw/cadence_gem.c
@@ -1106,6 +1106,9 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
             /* Reset to start of Q when receive disabled. */
             s->rx_desc_addr = s->regs[GEM_RXQBASE];
         }
+        if (val & GEM_NWCTRL_RXENA) {
+            qemu_flush_queued_packets(qemu_get_queue(s->nic));
+        }
         break;
 
     case GEM_TXSTATUS:
commit a7fd6915d84b20d5ff9ae287ddfabb9b222e7067
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Feb 28 18:23:15 2013 +0000

    m25p80.c: Use QOM classes for part differentiation
    
    Currently, M25P80 uses an object property to differentiate between flash parts.
    Changed this over to use QOM sub-classes - the actual names of the different parts
    are used to create a set of dynamic classes which passes the part info as class
    data. The object no longer needs to search the known_devices table for itself,
    instead it just gets its info from its own class.
    
    Kept the intermediate class definition private to m25p80.c for the moment, as
    the expectation is parts will only be added as new entries in the table. We can
    factor out the TYPE_M25P80 abstraction into a header on a demand basis.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: e24e156d-ff96-4901-997a-e31178b08bee at VA3EHSMHS021.ehs.local
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/m25p80.c b/hw/m25p80.c
index 461b41c..1372d06 100644
--- a/hw/m25p80.c
+++ b/hw/m25p80.c
@@ -178,8 +178,6 @@ static const FlashPartInfo known_devices[] = {
 
     /* Numonyx -- n25q128 */
     { INFO("n25q128",      0x20ba18,      0,  64 << 10, 256, 0) },
-
-    { },
 };
 
 typedef enum {
@@ -236,11 +234,23 @@ typedef struct Flash {
 
     int64_t dirty_page;
 
-    char *part_name;
     const FlashPartInfo *pi;
 
 } Flash;
 
+typedef struct M25P80Class {
+    SSISlaveClass parent_class;
+    FlashPartInfo *pi;
+} M25P80Class;
+
+#define TYPE_M25P80 "m25p80-generic"
+#define M25P80(obj) \
+     OBJECT_CHECK(Flash, (obj), TYPE_M25P80)
+#define M25P80_CLASS(klass) \
+     OBJECT_CLASS_CHECK(M25P80Class, (klass), TYPE_M25P80)
+#define M25P80_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(M25P80Class, (obj), TYPE_M25P80)
+
 static void bdrv_sync_complete(void *opaque, int ret)
 {
     /* do nothing. Masters do not directly interact with the backing store,
@@ -571,23 +581,9 @@ static int m25p80_init(SSISlave *ss)
 {
     DriveInfo *dinfo;
     Flash *s = FROM_SSI_SLAVE(Flash, ss);
-    const FlashPartInfo *i;
+    M25P80Class *mc = M25P80_GET_CLASS(s);
 
-    if (!s->part_name) { /* default to actual m25p80 if no partname given */
-        s->part_name = (char *)"m25p80";
-    }
-
-    i = known_devices;
-    for (i = known_devices;; i++) {
-        assert(i);
-        if (!i->part_name) {
-            fprintf(stderr, "Unknown SPI flash part: \"%s\"\n", s->part_name);
-            return 1;
-        } else if (!strcmp(i->part_name, s->part_name)) {
-            s->pi = i;
-            break;
-        }
-    }
+    s->pi = mc->pi;
 
     s->size = s->pi->sector_size * s->pi->n_sectors;
     s->dirty_page = -1;
@@ -635,34 +631,42 @@ static const VMStateDescription vmstate_m25p80 = {
     }
 };
 
-static Property m25p80_properties[] = {
-    DEFINE_PROP_STRING("partname", Flash, part_name),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
 static void m25p80_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
+    M25P80Class *mc = M25P80_CLASS(klass);
 
     k->init = m25p80_init;
     k->transfer = m25p80_transfer8;
     k->set_cs = m25p80_cs;
     k->cs_polarity = SSI_CS_LOW;
-    dc->props = m25p80_properties;
     dc->vmsd = &vmstate_m25p80;
+    mc->pi = data;
 }
 
 static const TypeInfo m25p80_info = {
-    .name           = "m25p80",
+    .name           = TYPE_M25P80,
     .parent         = TYPE_SSI_SLAVE,
     .instance_size  = sizeof(Flash),
-    .class_init     = m25p80_class_init,
+    .class_size     = sizeof(M25P80Class),
+    .abstract       = true,
 };
 
 static void m25p80_register_types(void)
 {
+    int i;
+
     type_register_static(&m25p80_info);
+    for (i = 0; i < ARRAY_SIZE(known_devices); ++i) {
+        TypeInfo ti = {
+            .name       = known_devices[i].part_name,
+            .parent     = TYPE_M25P80,
+            .class_init = m25p80_class_init,
+            .class_data = (void *)&known_devices[i],
+        };
+        type_register(&ti);
+    }
 }
 
 type_init(m25p80_register_types)
diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c
index 82d7183..fe7a932 100644
--- a/hw/petalogix_ml605_mmu.c
+++ b/hw/petalogix_ml605_mmu.c
@@ -158,8 +158,7 @@ petalogix_ml605_init(QEMUMachineInitArgs *args)
         for (i = 0; i < NUM_SPI_FLASHES; i++) {
             qemu_irq cs_line;
 
-            dev = ssi_create_slave_no_init(spi, "m25p80");
-            qdev_prop_set_string(dev, "partname", "n25q128");
+            dev = ssi_create_slave_no_init(spi, "n25q128");
             qdev_init_nofail(dev);
             cs_line = qdev_get_gpio_in(dev, 0);
             sysbus_connect_irq(busdev, i+1, cs_line);
diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
index 39d9fb3..2f67d90 100644
--- a/hw/xilinx_zynq.c
+++ b/hw/xilinx_zynq.c
@@ -82,8 +82,7 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
         spi = (SSIBus *)qdev_get_child_bus(dev, bus_name);
 
         for (j = 0; j < num_ss; ++j) {
-            flash_dev = ssi_create_slave_no_init(spi, "m25p80");
-            qdev_prop_set_string(flash_dev, "partname", "n25q128");
+            flash_dev = ssi_create_slave_no_init(spi, "n25q128");
             qdev_init_nofail(flash_dev);
 
             cs_line = qdev_get_gpio_in(flash_dev, 0);
commit b972b4e25340abdd23238bc8f3bdacbef533bd5a
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Feb 28 18:23:14 2013 +0000

    xilinx_zynq: Added SD controllers
    
    The Xilinx Zynq device has two SDHCI controllers. Added to the machine model.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
index 311f791..39d9fb3 100644
--- a/hw/xilinx_zynq.c
+++ b/hw/xilinx_zynq.c
@@ -187,6 +187,16 @@ static void zynq_init(QEMUMachineInitArgs *args)
         }
     }
 
+    dev = qdev_create(NULL, "generic-sdhci");
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0100000);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[56-IRQ_OFFSET]);
+
+    dev = qdev_create(NULL, "generic-sdhci");
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]);
+
     zynq_binfo.ram_size = ram_size;
     zynq_binfo.kernel_filename = kernel_filename;
     zynq_binfo.kernel_cmdline = kernel_cmdline;
commit 80f4d9fcea86aeb3071750c199416cab9abd5c28
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Feb 28 18:23:14 2013 +0000

    vl.c: allow for repeated -sd arguments
    
    Allows for repeating of -sd arguments in the same way as -pflash and -mtdblock.
    
    Acked-by: Igor Mitsyanko <i.mitsyanko at samsung.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/vl.c b/vl.c
index febd2ea..c03edf1 100644
--- a/vl.c
+++ b/vl.c
@@ -2994,7 +2994,7 @@ int main(int argc, char **argv, char **envp)
                 drive_add(IF_MTD, -1, optarg, MTD_OPTS);
                 break;
             case QEMU_OPTION_sd:
-                drive_add(IF_SD, 0, optarg, SD_OPTS);
+                drive_add(IF_SD, -1, optarg, SD_OPTS);
                 break;
             case QEMU_OPTION_pflash:
                 drive_add(IF_PFLASH, -1, optarg, PFLASH_OPTS);
commit d7dfca0807a0f579d3ec985bf1220519420c4dfe
Author: Igor Mitsyanko <i.mitsyanko at samsung.com>
Date:   Thu Feb 28 18:23:14 2013 +0000

    hw/sdhci: introduce standard SD host controller
    
    Device model for standard SD Host Controller Interface (SDHCI) compliant with
    version 2.00 of SD association specification.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Igor Mitsyanko <i.mitsyanko at samsung.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index b40f7b0..68b2045 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -47,3 +47,5 @@ CONFIG_XGMAC=y
 
 CONFIG_VERSATILE_PCI=y
 CONFIG_VERSATILE_I2C=y
+
+CONFIG_SDHCI=y
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index a1f3a80..40ebe46 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -43,6 +43,7 @@ common-obj-y += ccid-card-passthru.o
 common-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
 endif
 common-obj-$(CONFIG_I8259) += i8259_common.o i8259.o
+common-obj-$(CONFIG_SDHCI) += sdhci.o
 common-obj-y += fifo.o
 common-obj-y += pam.o
 
diff --git a/hw/sdhci.c b/hw/sdhci.c
new file mode 100644
index 0000000..e535df9
--- /dev/null
+++ b/hw/sdhci.c
@@ -0,0 +1,1300 @@
+/*
+ * SD Association Host Standard Specification v2.0 controller emulation
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Mitsyanko Igor <i.mitsyanko at samsung.com>
+ * Peter A.G. Crosthwaite <peter.crosthwaite at petalogix.com>
+ *
+ * Based on MMC controller for Samsung S5PC1xx-based board emulation
+ * by Alexey Merkulov and Vladimir Monakhov.
+ *
+ * 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/>.
+ */
+
+#include "hw.h"
+#include "sysemu/blockdev.h"
+#include "sysemu/dma.h"
+#include "qemu/timer.h"
+#include "block/block_int.h"
+#include "qemu/bitops.h"
+
+#include "sdhci.h"
+
+/* host controller debug messages */
+#ifndef SDHC_DEBUG
+#define SDHC_DEBUG                        0
+#endif
+
+#if SDHC_DEBUG == 0
+    #define DPRINT_L1(fmt, args...)       do { } while (0)
+    #define DPRINT_L2(fmt, args...)       do { } while (0)
+    #define ERRPRINT(fmt, args...)        do { } while (0)
+#elif SDHC_DEBUG == 1
+    #define DPRINT_L1(fmt, args...)       \
+        do {fprintf(stderr, "QEMU SDHC: "fmt, ## args); } while (0)
+    #define DPRINT_L2(fmt, args...)       do { } while (0)
+    #define ERRPRINT(fmt, args...)        \
+        do {fprintf(stderr, "QEMU SDHC ERROR: "fmt, ## args); } while (0)
+#else
+    #define DPRINT_L1(fmt, args...)       \
+        do {fprintf(stderr, "QEMU SDHC: "fmt, ## args); } while (0)
+    #define DPRINT_L2(fmt, args...)       \
+        do {fprintf(stderr, "QEMU SDHC: "fmt, ## args); } while (0)
+    #define ERRPRINT(fmt, args...)        \
+        do {fprintf(stderr, "QEMU SDHC ERROR: "fmt, ## args); } while (0)
+#endif
+
+/* Default SD/MMC host controller features information, which will be
+ * presented in CAPABILITIES register of generic SD host controller at reset.
+ * If not stated otherwise:
+ * 0 - not supported, 1 - supported, other - prohibited.
+ */
+#define SDHC_CAPAB_64BITBUS       0ul        /* 64-bit System Bus Support */
+#define SDHC_CAPAB_18V            1ul        /* Voltage support 1.8v */
+#define SDHC_CAPAB_30V            0ul        /* Voltage support 3.0v */
+#define SDHC_CAPAB_33V            1ul        /* Voltage support 3.3v */
+#define SDHC_CAPAB_SUSPRESUME     0ul        /* Suspend/resume support */
+#define SDHC_CAPAB_SDMA           1ul        /* SDMA support */
+#define SDHC_CAPAB_HIGHSPEED      1ul        /* High speed support */
+#define SDHC_CAPAB_ADMA1          1ul        /* ADMA1 support */
+#define SDHC_CAPAB_ADMA2          1ul        /* ADMA2 support */
+/* Maximum host controller R/W buffers size
+ * Possible values: 512, 1024, 2048 bytes */
+#define SDHC_CAPAB_MAXBLOCKLENGTH 512ul
+/* Maximum clock frequency for SDclock in MHz
+ * value in range 10-63 MHz, 0 - not defined */
+#define SDHC_CAPAB_BASECLKFREQ    0ul
+#define SDHC_CAPAB_TOUNIT         1ul  /* Timeout clock unit 0 - kHz, 1 - MHz */
+/* Timeout clock frequency 1-63, 0 - not defined */
+#define SDHC_CAPAB_TOCLKFREQ      0ul
+
+/* Now check all parameters and calculate CAPABILITIES REGISTER value */
+#if SDHC_CAPAB_64BITBUS > 1 || SDHC_CAPAB_18V > 1 || SDHC_CAPAB_30V > 1 ||     \
+    SDHC_CAPAB_33V > 1 || SDHC_CAPAB_SUSPRESUME > 1 || SDHC_CAPAB_SDMA > 1 ||  \
+    SDHC_CAPAB_HIGHSPEED > 1 || SDHC_CAPAB_ADMA2 > 1 || SDHC_CAPAB_ADMA1 > 1 ||\
+    SDHC_CAPAB_TOUNIT > 1
+#error Capabilities features can have value 0 or 1 only!
+#endif
+
+#if SDHC_CAPAB_MAXBLOCKLENGTH == 512
+#define MAX_BLOCK_LENGTH 0ul
+#elif SDHC_CAPAB_MAXBLOCKLENGTH == 1024
+#define MAX_BLOCK_LENGTH 1ul
+#elif SDHC_CAPAB_MAXBLOCKLENGTH == 2048
+#define MAX_BLOCK_LENGTH 2ul
+#else
+#error Max host controller block size can have value 512, 1024 or 2048 only!
+#endif
+
+#if (SDHC_CAPAB_BASECLKFREQ > 0 && SDHC_CAPAB_BASECLKFREQ < 10) || \
+    SDHC_CAPAB_BASECLKFREQ > 63
+#error SDclock frequency can have value in range 0, 10-63 only!
+#endif
+
+#if SDHC_CAPAB_TOCLKFREQ > 63
+#error Timeout clock frequency can have value in range 0-63 only!
+#endif
+
+#define SDHC_CAPAB_REG_DEFAULT                                 \
+   ((SDHC_CAPAB_64BITBUS << 28) | (SDHC_CAPAB_18V << 26) |     \
+    (SDHC_CAPAB_30V << 25) | (SDHC_CAPAB_33V << 24) |          \
+    (SDHC_CAPAB_SUSPRESUME << 23) | (SDHC_CAPAB_SDMA << 22) |  \
+    (SDHC_CAPAB_HIGHSPEED << 21) | (SDHC_CAPAB_ADMA1 << 20) |  \
+    (SDHC_CAPAB_ADMA2 << 19) | (MAX_BLOCK_LENGTH << 16) |      \
+    (SDHC_CAPAB_BASECLKFREQ << 8) | (SDHC_CAPAB_TOUNIT << 7) | \
+    (SDHC_CAPAB_TOCLKFREQ))
+
+#define MASKED_WRITE(reg, mask, val)  (reg = (reg & (mask)) | (val))
+
+static uint8_t sdhci_slotint(SDHCIState *s)
+{
+    return (s->norintsts & s->norintsigen) || (s->errintsts & s->errintsigen) ||
+         ((s->norintsts & SDHC_NIS_INSERT) && (s->wakcon & SDHC_WKUP_ON_INS)) ||
+         ((s->norintsts & SDHC_NIS_REMOVE) && (s->wakcon & SDHC_WKUP_ON_RMV));
+}
+
+static inline void sdhci_update_irq(SDHCIState *s)
+{
+    qemu_set_irq(s->irq, sdhci_slotint(s));
+}
+
+static void sdhci_raise_insertion_irq(void *opaque)
+{
+    SDHCIState *s = (SDHCIState *)opaque;
+
+    if (s->norintsts & SDHC_NIS_REMOVE) {
+        qemu_mod_timer(s->insert_timer,
+                       qemu_get_clock_ns(vm_clock) + SDHC_INSERTION_DELAY);
+    } else {
+        s->prnsts = 0x1ff0000;
+        if (s->norintstsen & SDHC_NISEN_INSERT) {
+            s->norintsts |= SDHC_NIS_INSERT;
+        }
+        sdhci_update_irq(s);
+    }
+}
+
+static void sdhci_insert_eject_cb(void *opaque, int irq, int level)
+{
+    SDHCIState *s = (SDHCIState *)opaque;
+    DPRINT_L1("Card state changed: %s!\n", level ? "insert" : "eject");
+
+    if ((s->norintsts & SDHC_NIS_REMOVE) && level) {
+        /* Give target some time to notice card ejection */
+        qemu_mod_timer(s->insert_timer,
+                       qemu_get_clock_ns(vm_clock) + SDHC_INSERTION_DELAY);
+    } else {
+        if (level) {
+            s->prnsts = 0x1ff0000;
+            if (s->norintstsen & SDHC_NISEN_INSERT) {
+                s->norintsts |= SDHC_NIS_INSERT;
+            }
+        } else {
+            s->prnsts = 0x1fa0000;
+            s->pwrcon &= ~SDHC_POWER_ON;
+            s->clkcon &= ~SDHC_CLOCK_SDCLK_EN;
+            if (s->norintstsen & SDHC_NISEN_REMOVE) {
+                s->norintsts |= SDHC_NIS_REMOVE;
+            }
+        }
+        sdhci_update_irq(s);
+    }
+}
+
+static void sdhci_card_readonly_cb(void *opaque, int irq, int level)
+{
+    SDHCIState *s = (SDHCIState *)opaque;
+
+    if (level) {
+        s->prnsts &= ~SDHC_WRITE_PROTECT;
+    } else {
+        /* Write enabled */
+        s->prnsts |= SDHC_WRITE_PROTECT;
+    }
+}
+
+static void sdhci_reset(SDHCIState *s)
+{
+    qemu_del_timer(s->insert_timer);
+    qemu_del_timer(s->transfer_timer);
+    /* Set all registers to 0. Capabilities registers are not cleared
+     * and assumed to always preserve their value, given to them during
+     * initialization */
+    memset(&s->sdmasysad, 0, (uintptr_t)&s->capareg - (uintptr_t)&s->sdmasysad);
+
+    sd_set_cb(s->card, s->ro_cb, s->eject_cb);
+    s->data_count = 0;
+    s->stopped_state = sdhc_not_stopped;
+}
+
+static void sdhci_do_data_transfer(void *opaque)
+{
+    SDHCIState *s = (SDHCIState *)opaque;
+
+    SDHCI_GET_CLASS(s)->data_transfer(s);
+}
+
+static void sdhci_send_command(SDHCIState *s)
+{
+    SDRequest request;
+    uint8_t response[16];
+    int rlen;
+
+    s->errintsts = 0;
+    s->acmd12errsts = 0;
+    request.cmd = s->cmdreg >> 8;
+    request.arg = s->argument;
+    DPRINT_L1("sending CMD%u ARG[0x%08x]\n", request.cmd, request.arg);
+    rlen = sd_do_command(s->card, &request, response);
+
+    if (s->cmdreg & SDHC_CMD_RESPONSE) {
+        if (rlen == 4) {
+            s->rspreg[0] = (response[0] << 24) | (response[1] << 16) |
+                           (response[2] << 8)  |  response[3];
+            s->rspreg[1] = s->rspreg[2] = s->rspreg[3] = 0;
+            DPRINT_L1("Response: RSPREG[31..0]=0x%08x\n", s->rspreg[0]);
+        } else if (rlen == 16) {
+            s->rspreg[0] = (response[11] << 24) | (response[12] << 16) |
+                           (response[13] << 8) |  response[14];
+            s->rspreg[1] = (response[7] << 24) | (response[8] << 16) |
+                           (response[9] << 8)  |  response[10];
+            s->rspreg[2] = (response[3] << 24) | (response[4] << 16) |
+                           (response[5] << 8)  |  response[6];
+            s->rspreg[3] = (response[0] << 16) | (response[1] << 8) |
+                            response[2];
+            DPRINT_L1("Response received:\n RSPREG[127..96]=0x%08x, RSPREG[95.."
+                  "64]=0x%08x,\n RSPREG[63..32]=0x%08x, RSPREG[31..0]=0x%08x\n",
+                  s->rspreg[3], s->rspreg[2], s->rspreg[1], s->rspreg[0]);
+        } else {
+            ERRPRINT("Timeout waiting for command response\n");
+            if (s->errintstsen & SDHC_EISEN_CMDTIMEOUT) {
+                s->errintsts |= SDHC_EIS_CMDTIMEOUT;
+                s->norintsts |= SDHC_NIS_ERR;
+            }
+        }
+
+        if ((s->norintstsen & SDHC_NISEN_TRSCMP) &&
+            (s->cmdreg & SDHC_CMD_RESPONSE) == SDHC_CMD_RSP_WITH_BUSY) {
+            s->norintsts |= SDHC_NIS_TRSCMP;
+        }
+    } else if (rlen != 0 && (s->errintstsen & SDHC_EISEN_CMDIDX)) {
+        s->errintsts |= SDHC_EIS_CMDIDX;
+        s->norintsts |= SDHC_NIS_ERR;
+    }
+
+    if (s->norintstsen & SDHC_NISEN_CMDCMP) {
+        s->norintsts |= SDHC_NIS_CMDCMP;
+    }
+
+    sdhci_update_irq(s);
+
+    if (s->blksize && (s->cmdreg & SDHC_CMD_DATA_PRESENT)) {
+        sdhci_do_data_transfer(s);
+    }
+}
+
+static void sdhci_end_transfer(SDHCIState *s)
+{
+    /* Automatically send CMD12 to stop transfer if AutoCMD12 enabled */
+    if ((s->trnmod & SDHC_TRNS_ACMD12) != 0) {
+        SDRequest request;
+        uint8_t response[16];
+
+        request.cmd = 0x0C;
+        request.arg = 0;
+        DPRINT_L1("Automatically issue CMD%d %08x\n", request.cmd, request.arg);
+        sd_do_command(s->card, &request, response);
+        /* Auto CMD12 response goes to the upper Response register */
+        s->rspreg[3] = (response[0] << 24) | (response[1] << 16) |
+                (response[2] << 8) | response[3];
+    }
+
+    s->prnsts &= ~(SDHC_DOING_READ | SDHC_DOING_WRITE |
+            SDHC_DAT_LINE_ACTIVE | SDHC_DATA_INHIBIT |
+            SDHC_SPACE_AVAILABLE | SDHC_DATA_AVAILABLE);
+
+    if (s->norintstsen & SDHC_NISEN_TRSCMP) {
+        s->norintsts |= SDHC_NIS_TRSCMP;
+    }
+
+    sdhci_update_irq(s);
+}
+
+/*
+ * Programmed i/o data transfer
+ */
+
+/* Fill host controller's read buffer with BLKSIZE bytes of data from card */
+static void sdhci_read_block_from_card(SDHCIState *s)
+{
+    int index = 0;
+
+    if ((s->trnmod & SDHC_TRNS_MULTI) &&
+            (s->trnmod & SDHC_TRNS_BLK_CNT_EN) && (s->blkcnt == 0)) {
+        return;
+    }
+
+    for (index = 0; index < (s->blksize & 0x0fff); index++) {
+        s->fifo_buffer[index] = sd_read_data(s->card);
+    }
+
+    /* New data now available for READ through Buffer Port Register */
+    s->prnsts |= SDHC_DATA_AVAILABLE;
+    if (s->norintstsen & SDHC_NISEN_RBUFRDY) {
+        s->norintsts |= SDHC_NIS_RBUFRDY;
+    }
+
+    /* Clear DAT line active status if that was the last block */
+    if ((s->trnmod & SDHC_TRNS_MULTI) == 0 ||
+            ((s->trnmod & SDHC_TRNS_MULTI) && s->blkcnt == 1)) {
+        s->prnsts &= ~SDHC_DAT_LINE_ACTIVE;
+    }
+
+    /* If stop at block gap request was set and it's not the last block of
+     * data - generate Block Event interrupt */
+    if (s->stopped_state == sdhc_gap_read && (s->trnmod & SDHC_TRNS_MULTI) &&
+            s->blkcnt != 1)    {
+        s->prnsts &= ~SDHC_DAT_LINE_ACTIVE;
+        if (s->norintstsen & SDHC_EISEN_BLKGAP) {
+            s->norintsts |= SDHC_EIS_BLKGAP;
+        }
+    }
+
+    sdhci_update_irq(s);
+}
+
+/* Read @size byte of data from host controller @s BUFFER DATA PORT register */
+static uint32_t sdhci_read_dataport(SDHCIState *s, unsigned size)
+{
+    uint32_t value = 0;
+    int i;
+
+    /* first check that a valid data exists in host controller input buffer */
+    if ((s->prnsts & SDHC_DATA_AVAILABLE) == 0) {
+        ERRPRINT("Trying to read from empty buffer\n");
+        return 0;
+    }
+
+    for (i = 0; i < size; i++) {
+        value |= s->fifo_buffer[s->data_count] << i * 8;
+        s->data_count++;
+        /* check if we've read all valid data (blksize bytes) from buffer */
+        if ((s->data_count) >= (s->blksize & 0x0fff)) {
+            DPRINT_L2("All %u bytes of data have been read from input buffer\n",
+                    s->data_count);
+            s->prnsts &= ~SDHC_DATA_AVAILABLE; /* no more data in a buffer */
+            s->data_count = 0;  /* next buff read must start at position [0] */
+
+            if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) {
+                s->blkcnt--;
+            }
+
+            /* if that was the last block of data */
+            if ((s->trnmod & SDHC_TRNS_MULTI) == 0 ||
+                ((s->trnmod & SDHC_TRNS_BLK_CNT_EN) && (s->blkcnt == 0)) ||
+                 /* stop at gap request */
+                (s->stopped_state == sdhc_gap_read &&
+                 !(s->prnsts & SDHC_DAT_LINE_ACTIVE))) {
+                SDHCI_GET_CLASS(s)->end_data_transfer(s);
+            } else { /* if there are more data, read next block from card */
+                SDHCI_GET_CLASS(s)->read_block_from_card(s);
+            }
+            break;
+        }
+    }
+
+    return value;
+}
+
+/* Write data from host controller FIFO to card */
+static void sdhci_write_block_to_card(SDHCIState *s)
+{
+    int index = 0;
+
+    if (s->prnsts & SDHC_SPACE_AVAILABLE) {
+        if (s->norintstsen & SDHC_NISEN_WBUFRDY) {
+            s->norintsts |= SDHC_NIS_WBUFRDY;
+        }
+        sdhci_update_irq(s);
+        return;
+    }
+
+    if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) {
+        if (s->blkcnt == 0) {
+            return;
+        } else {
+            s->blkcnt--;
+        }
+    }
+
+    for (index = 0; index < (s->blksize & 0x0fff); index++) {
+        sd_write_data(s->card, s->fifo_buffer[index]);
+    }
+
+    /* Next data can be written through BUFFER DATORT register */
+    s->prnsts |= SDHC_SPACE_AVAILABLE;
+    if (s->norintstsen & SDHC_NISEN_WBUFRDY) {
+        s->norintsts |= SDHC_NIS_WBUFRDY;
+    }
+
+    /* Finish transfer if that was the last block of data */
+    if ((s->trnmod & SDHC_TRNS_MULTI) == 0 ||
+            ((s->trnmod & SDHC_TRNS_MULTI) &&
+            (s->trnmod & SDHC_TRNS_BLK_CNT_EN) && (s->blkcnt == 0))) {
+        SDHCI_GET_CLASS(s)->end_data_transfer(s);
+    }
+
+    /* Generate Block Gap Event if requested and if not the last block */
+    if (s->stopped_state == sdhc_gap_write && (s->trnmod & SDHC_TRNS_MULTI) &&
+            s->blkcnt > 0) {
+        s->prnsts &= ~SDHC_DOING_WRITE;
+        if (s->norintstsen & SDHC_EISEN_BLKGAP) {
+            s->norintsts |= SDHC_EIS_BLKGAP;
+        }
+        SDHCI_GET_CLASS(s)->end_data_transfer(s);
+    }
+
+    sdhci_update_irq(s);
+}
+
+/* Write @size bytes of @value data to host controller @s Buffer Data Port
+ * register */
+static void sdhci_write_dataport(SDHCIState *s, uint32_t value, unsigned size)
+{
+    unsigned i;
+
+    /* Check that there is free space left in a buffer */
+    if (!(s->prnsts & SDHC_SPACE_AVAILABLE)) {
+        ERRPRINT("Can't write to data buffer: buffer full\n");
+        return;
+    }
+
+    for (i = 0; i < size; i++) {
+        s->fifo_buffer[s->data_count] = value & 0xFF;
+        s->data_count++;
+        value >>= 8;
+        if (s->data_count >= (s->blksize & 0x0fff)) {
+            DPRINT_L2("write buffer filled with %u bytes of data\n",
+                    s->data_count);
+            s->data_count = 0;
+            s->prnsts &= ~SDHC_SPACE_AVAILABLE;
+            if (s->prnsts & SDHC_DOING_WRITE) {
+                SDHCI_GET_CLASS(s)->write_block_to_card(s);
+            }
+        }
+    }
+}
+
+/*
+ * Single DMA data transfer
+ */
+
+/* Multi block SDMA transfer */
+static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
+{
+    bool page_aligned = false;
+    unsigned int n, begin;
+    const uint16_t block_size = s->blksize & 0x0fff;
+    uint32_t boundary_chk = 1 << (((s->blksize & 0xf000) >> 12) + 12);
+    uint32_t boundary_count = boundary_chk - (s->sdmasysad % boundary_chk);
+
+    /* XXX: Some sd/mmc drivers (for example, u-boot-slp) do not account for
+     * possible stop at page boundary if initial address is not page aligned,
+     * allow them to work properly */
+    if ((s->sdmasysad % boundary_chk) == 0) {
+        page_aligned = true;
+    }
+
+    if (s->trnmod & SDHC_TRNS_READ) {
+        s->prnsts |= SDHC_DOING_READ | SDHC_DATA_INHIBIT |
+                SDHC_DAT_LINE_ACTIVE;
+        while (s->blkcnt) {
+            if (s->data_count == 0) {
+                for (n = 0; n < block_size; n++) {
+                    s->fifo_buffer[n] = sd_read_data(s->card);
+                }
+            }
+            begin = s->data_count;
+            if (((boundary_count + begin) < block_size) && page_aligned) {
+                s->data_count = boundary_count + begin;
+                boundary_count = 0;
+             } else {
+                s->data_count = block_size;
+                boundary_count -= block_size - begin;
+                if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) {
+                    s->blkcnt--;
+                }
+            }
+            dma_memory_write(&dma_context_memory, s->sdmasysad,
+                             &s->fifo_buffer[begin], s->data_count - begin);
+            s->sdmasysad += s->data_count - begin;
+            if (s->data_count == block_size) {
+                s->data_count = 0;
+            }
+            if (page_aligned && boundary_count == 0) {
+                break;
+            }
+        }
+    } else {
+        s->prnsts |= SDHC_DOING_WRITE | SDHC_DATA_INHIBIT |
+                SDHC_DAT_LINE_ACTIVE;
+        while (s->blkcnt) {
+            begin = s->data_count;
+            if (((boundary_count + begin) < block_size) && page_aligned) {
+                s->data_count = boundary_count + begin;
+                boundary_count = 0;
+             } else {
+                s->data_count = block_size;
+                boundary_count -= block_size - begin;
+            }
+            dma_memory_read(&dma_context_memory, s->sdmasysad,
+                            &s->fifo_buffer[begin], s->data_count);
+            s->sdmasysad += s->data_count - begin;
+            if (s->data_count == block_size) {
+                for (n = 0; n < block_size; n++) {
+                    sd_write_data(s->card, s->fifo_buffer[n]);
+                }
+                s->data_count = 0;
+                if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) {
+                    s->blkcnt--;
+                }
+            }
+            if (page_aligned && boundary_count == 0) {
+                break;
+            }
+        }
+    }
+
+    if (s->blkcnt == 0) {
+        SDHCI_GET_CLASS(s)->end_data_transfer(s);
+    } else {
+        if (s->norintstsen & SDHC_NISEN_DMA) {
+            s->norintsts |= SDHC_NIS_DMA;
+        }
+        sdhci_update_irq(s);
+    }
+}
+
+/* single block SDMA transfer */
+
+static void sdhci_sdma_transfer_single_block(SDHCIState *s)
+{
+    int n;
+    uint32_t datacnt = s->blksize & 0x0fff;
+
+    if (s->trnmod & SDHC_TRNS_READ) {
+        for (n = 0; n < datacnt; n++) {
+            s->fifo_buffer[n] = sd_read_data(s->card);
+        }
+        dma_memory_write(&dma_context_memory, s->sdmasysad, s->fifo_buffer,
+                         datacnt);
+    } else {
+        dma_memory_read(&dma_context_memory, s->sdmasysad, s->fifo_buffer,
+                        datacnt);
+        for (n = 0; n < datacnt; n++) {
+            sd_write_data(s->card, s->fifo_buffer[n]);
+        }
+    }
+
+    if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) {
+        s->blkcnt--;
+    }
+
+    SDHCI_GET_CLASS(s)->end_data_transfer(s);
+}
+
+typedef struct ADMADescr {
+    hwaddr addr;
+    uint16_t length;
+    uint8_t attr;
+    uint8_t incr;
+} ADMADescr;
+
+static void get_adma_description(SDHCIState *s, ADMADescr *dscr)
+{
+    uint32_t adma1 = 0;
+    uint64_t adma2 = 0;
+    hwaddr entry_addr = (hwaddr)s->admasysaddr;
+    switch (SDHC_DMA_TYPE(s->hostctl)) {
+    case SDHC_CTRL_ADMA2_32:
+        dma_memory_read(&dma_context_memory, entry_addr, (uint8_t *)&adma2,
+                        sizeof(adma2));
+        adma2 = le64_to_cpu(adma2);
+        /* The spec does not specify endianness of descriptor table.
+         * We currently assume that it is LE.
+         */
+        dscr->addr = (hwaddr)extract64(adma2, 32, 32) & ~0x3ull;
+        dscr->length = (uint16_t)extract64(adma2, 16, 16);
+        dscr->attr = (uint8_t)extract64(adma2, 0, 7);
+        dscr->incr = 8;
+        break;
+    case SDHC_CTRL_ADMA1_32:
+        dma_memory_read(&dma_context_memory, entry_addr, (uint8_t *)&adma1,
+                        sizeof(adma1));
+        adma1 = le32_to_cpu(adma1);
+        dscr->addr = (hwaddr)(adma1 & 0xFFFFF000);
+        dscr->attr = (uint8_t)extract32(adma1, 0, 7);
+        dscr->incr = 4;
+        if ((dscr->attr & SDHC_ADMA_ATTR_ACT_MASK) == SDHC_ADMA_ATTR_SET_LEN) {
+            dscr->length = (uint16_t)extract32(adma1, 12, 16);
+        } else {
+            dscr->length = 4096;
+        }
+        break;
+    case SDHC_CTRL_ADMA2_64:
+        dma_memory_read(&dma_context_memory, entry_addr,
+                        (uint8_t *)(&dscr->attr), 1);
+        dma_memory_read(&dma_context_memory, entry_addr + 2,
+                        (uint8_t *)(&dscr->length), 2);
+        dscr->length = le16_to_cpu(dscr->length);
+        dma_memory_read(&dma_context_memory, entry_addr + 4,
+                        (uint8_t *)(&dscr->addr), 8);
+        dscr->attr = le64_to_cpu(dscr->attr);
+        dscr->attr &= 0xfffffff8;
+        dscr->incr = 12;
+        break;
+    }
+}
+
+/* Advanced DMA data transfer */
+
+static void sdhci_do_adma(SDHCIState *s)
+{
+    unsigned int n, begin, length;
+    const uint16_t block_size = s->blksize & 0x0fff;
+    ADMADescr dscr;
+    int i;
+
+    for (i = 0; i < SDHC_ADMA_DESCS_PER_DELAY; ++i) {
+        s->admaerr &= ~SDHC_ADMAERR_LENGTH_MISMATCH;
+
+        get_adma_description(s, &dscr);
+        DPRINT_L2("ADMA loop: addr=" TARGET_FMT_plx ", len=%d, attr=%x\n",
+                dscr.addr, dscr.length, dscr.attr);
+
+        if ((dscr.attr & SDHC_ADMA_ATTR_VALID) == 0) {
+            /* Indicate that error occurred in ST_FDS state */
+            s->admaerr &= ~SDHC_ADMAERR_STATE_MASK;
+            s->admaerr |= SDHC_ADMAERR_STATE_ST_FDS;
+
+            /* Generate ADMA error interrupt */
+            if (s->errintstsen & SDHC_EISEN_ADMAERR) {
+                s->errintsts |= SDHC_EIS_ADMAERR;
+                s->norintsts |= SDHC_NIS_ERR;
+            }
+
+            sdhci_update_irq(s);
+            return;
+        }
+
+        length = dscr.length ? dscr.length : 65536;
+
+        switch (dscr.attr & SDHC_ADMA_ATTR_ACT_MASK) {
+        case SDHC_ADMA_ATTR_ACT_TRAN:  /* data transfer */
+
+            if (s->trnmod & SDHC_TRNS_READ) {
+                while (length) {
+                    if (s->data_count == 0) {
+                        for (n = 0; n < block_size; n++) {
+                            s->fifo_buffer[n] = sd_read_data(s->card);
+                        }
+                    }
+                    begin = s->data_count;
+                    if ((length + begin) < block_size) {
+                        s->data_count = length + begin;
+                        length = 0;
+                     } else {
+                        s->data_count = block_size;
+                        length -= block_size - begin;
+                    }
+                    dma_memory_write(&dma_context_memory, dscr.addr,
+                                     &s->fifo_buffer[begin],
+                                     s->data_count - begin);
+                    dscr.addr += s->data_count - begin;
+                    if (s->data_count == block_size) {
+                        s->data_count = 0;
+                        if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) {
+                            s->blkcnt--;
+                            if (s->blkcnt == 0) {
+                                break;
+                            }
+                        }
+                    }
+                }
+            } else {
+                while (length) {
+                    begin = s->data_count;
+                    if ((length + begin) < block_size) {
+                        s->data_count = length + begin;
+                        length = 0;
+                     } else {
+                        s->data_count = block_size;
+                        length -= block_size - begin;
+                    }
+                    dma_memory_read(&dma_context_memory, dscr.addr,
+                                    &s->fifo_buffer[begin], s->data_count);
+                    dscr.addr += s->data_count - begin;
+                    if (s->data_count == block_size) {
+                        for (n = 0; n < block_size; n++) {
+                            sd_write_data(s->card, s->fifo_buffer[n]);
+                        }
+                        s->data_count = 0;
+                        if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) {
+                            s->blkcnt--;
+                            if (s->blkcnt == 0) {
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+            s->admasysaddr += dscr.incr;
+            break;
+        case SDHC_ADMA_ATTR_ACT_LINK:   /* link to next descriptor table */
+            s->admasysaddr = dscr.addr;
+            DPRINT_L1("ADMA link: admasysaddr=0x%lx\n", s->admasysaddr);
+            break;
+        default:
+            s->admasysaddr += dscr.incr;
+            break;
+        }
+
+        /* ADMA transfer terminates if blkcnt == 0 or by END attribute */
+        if (((s->trnmod & SDHC_TRNS_BLK_CNT_EN) &&
+                    (s->blkcnt == 0)) || (dscr.attr & SDHC_ADMA_ATTR_END)) {
+            DPRINT_L2("ADMA transfer completed\n");
+            if (length || ((dscr.attr & SDHC_ADMA_ATTR_END) &&
+                (s->trnmod & SDHC_TRNS_BLK_CNT_EN) &&
+                s->blkcnt != 0)) {
+                ERRPRINT("SD/MMC host ADMA length mismatch\n");
+                s->admaerr |= SDHC_ADMAERR_LENGTH_MISMATCH |
+                        SDHC_ADMAERR_STATE_ST_TFR;
+                if (s->errintstsen & SDHC_EISEN_ADMAERR) {
+                    ERRPRINT("Set ADMA error flag\n");
+                    s->errintsts |= SDHC_EIS_ADMAERR;
+                    s->norintsts |= SDHC_NIS_ERR;
+                }
+
+                sdhci_update_irq(s);
+            }
+            SDHCI_GET_CLASS(s)->end_data_transfer(s);
+            return;
+        }
+
+        if (dscr.attr & SDHC_ADMA_ATTR_INT) {
+            DPRINT_L1("ADMA interrupt: admasysaddr=0x%lx\n", s->admasysaddr);
+            if (s->norintstsen & SDHC_NISEN_DMA) {
+                s->norintsts |= SDHC_NIS_DMA;
+            }
+
+            sdhci_update_irq(s);
+            return;
+        }
+    }
+
+    /* we have unfinished bussiness - reschedule to continue ADMA */
+    qemu_mod_timer(s->transfer_timer,
+                   qemu_get_clock_ns(vm_clock) + SDHC_TRANSFER_DELAY);
+}
+
+/* Perform data transfer according to controller configuration */
+
+static void sdhci_data_transfer(SDHCIState *s)
+{
+    SDHCIClass *k = SDHCI_GET_CLASS(s);
+    s->data_count = 0;
+
+    if (s->trnmod & SDHC_TRNS_DMA) {
+        switch (SDHC_DMA_TYPE(s->hostctl)) {
+        case SDHC_CTRL_SDMA:
+            if ((s->trnmod & SDHC_TRNS_MULTI) &&
+                    (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || s->blkcnt == 0)) {
+                break;
+            }
+
+            if ((s->blkcnt == 1) || !(s->trnmod & SDHC_TRNS_MULTI)) {
+                k->do_sdma_single(s);
+            } else {
+                k->do_sdma_multi(s);
+            }
+
+            break;
+        case SDHC_CTRL_ADMA1_32:
+            if (!(s->capareg & SDHC_CAN_DO_ADMA1)) {
+                ERRPRINT("ADMA1 not supported\n");
+                break;
+            }
+
+            k->do_adma(s);
+            break;
+        case SDHC_CTRL_ADMA2_32:
+            if (!(s->capareg & SDHC_CAN_DO_ADMA2)) {
+                ERRPRINT("ADMA2 not supported\n");
+                break;
+            }
+
+            k->do_adma(s);
+            break;
+        case SDHC_CTRL_ADMA2_64:
+            if (!(s->capareg & SDHC_CAN_DO_ADMA2) ||
+                    !(s->capareg & SDHC_64_BIT_BUS_SUPPORT)) {
+                ERRPRINT("64 bit ADMA not supported\n");
+                break;
+            }
+
+            k->do_adma(s);
+            break;
+        default:
+            ERRPRINT("Unsupported DMA type\n");
+            break;
+        }
+    } else {
+        if ((s->trnmod & SDHC_TRNS_READ) && sd_data_ready(s->card)) {
+            s->prnsts |= SDHC_DOING_READ | SDHC_DATA_INHIBIT |
+                    SDHC_DAT_LINE_ACTIVE;
+            SDHCI_GET_CLASS(s)->read_block_from_card(s);
+        } else {
+            s->prnsts |= SDHC_DOING_WRITE | SDHC_DAT_LINE_ACTIVE |
+                    SDHC_SPACE_AVAILABLE | SDHC_DATA_INHIBIT;
+            SDHCI_GET_CLASS(s)->write_block_to_card(s);
+        }
+    }
+}
+
+static bool sdhci_can_issue_command(SDHCIState *s)
+{
+    if (!SDHC_CLOCK_IS_ON(s->clkcon) || !(s->pwrcon & SDHC_POWER_ON) ||
+        (((s->prnsts & SDHC_DATA_INHIBIT) || s->stopped_state) &&
+        ((s->cmdreg & SDHC_CMD_DATA_PRESENT) ||
+        ((s->cmdreg & SDHC_CMD_RESPONSE) == SDHC_CMD_RSP_WITH_BUSY &&
+        !(SDHC_COMMAND_TYPE(s->cmdreg) == SDHC_CMD_ABORT))))) {
+        return false;
+    }
+
+    return true;
+}
+
+/* The Buffer Data Port register must be accessed in sequential and
+ * continuous manner */
+static inline bool
+sdhci_buff_access_is_sequential(SDHCIState *s, unsigned byte_num)
+{
+    if ((s->data_count & 0x3) != byte_num) {
+        ERRPRINT("Non-sequential access to Buffer Data Port register"
+                "is prohibited\n");
+        return false;
+    }
+    return true;
+}
+
+static uint32_t sdhci_read(SDHCIState *s, unsigned int offset, unsigned size)
+{
+    uint32_t ret = 0;
+
+    switch (offset & ~0x3) {
+    case SDHC_SYSAD:
+        ret = s->sdmasysad;
+        break;
+    case SDHC_BLKSIZE:
+        ret = s->blksize | (s->blkcnt << 16);
+        break;
+    case SDHC_ARGUMENT:
+        ret = s->argument;
+        break;
+    case SDHC_TRNMOD:
+        ret = s->trnmod | (s->cmdreg << 16);
+        break;
+    case SDHC_RSPREG0 ... SDHC_RSPREG3:
+        ret = s->rspreg[((offset & ~0x3) - SDHC_RSPREG0) >> 2];
+        break;
+    case  SDHC_BDATA:
+        if (sdhci_buff_access_is_sequential(s, offset - SDHC_BDATA)) {
+            ret = SDHCI_GET_CLASS(s)->bdata_read(s, size);
+            DPRINT_L2("read %ub: addr[0x%04x] -> %u\n", size, offset, ret);
+            return ret;
+        }
+        break;
+    case SDHC_PRNSTS:
+        ret = s->prnsts;
+        break;
+    case SDHC_HOSTCTL:
+        ret = s->hostctl | (s->pwrcon << 8) | (s->blkgap << 16) |
+              (s->wakcon << 24);
+        break;
+    case SDHC_CLKCON:
+        ret = s->clkcon | (s->timeoutcon << 16);
+        break;
+    case SDHC_NORINTSTS:
+        ret = s->norintsts | (s->errintsts << 16);
+        break;
+    case SDHC_NORINTSTSEN:
+        ret = s->norintstsen | (s->errintstsen << 16);
+        break;
+    case SDHC_NORINTSIGEN:
+        ret = s->norintsigen | (s->errintsigen << 16);
+        break;
+    case SDHC_ACMD12ERRSTS:
+        ret = s->acmd12errsts;
+        break;
+    case SDHC_CAPAREG:
+        ret = s->capareg;
+        break;
+    case SDHC_MAXCURR:
+        ret = s->maxcurr;
+        break;
+    case SDHC_ADMAERR:
+        ret =  s->admaerr;
+        break;
+    case SDHC_ADMASYSADDR:
+        ret = (uint32_t)s->admasysaddr;
+        break;
+    case SDHC_ADMASYSADDR + 4:
+        ret = (uint32_t)(s->admasysaddr >> 32);
+        break;
+    case SDHC_SLOT_INT_STATUS:
+        ret = (SD_HOST_SPECv2_VERS << 16) | sdhci_slotint(s);
+        break;
+    default:
+        ERRPRINT("bad %ub read: addr[0x%04x]\n", size, offset);
+        break;
+    }
+
+    ret >>= (offset & 0x3) * 8;
+    ret &= (1ULL << (size * 8)) - 1;
+    DPRINT_L2("read %ub: addr[0x%04x] -> %u(0x%x)\n", size, offset, ret, ret);
+    return ret;
+}
+
+static inline void sdhci_blkgap_write(SDHCIState *s, uint8_t value)
+{
+    if ((value & SDHC_STOP_AT_GAP_REQ) && (s->blkgap & SDHC_STOP_AT_GAP_REQ)) {
+        return;
+    }
+    s->blkgap = value & SDHC_STOP_AT_GAP_REQ;
+
+    if ((value & SDHC_CONTINUE_REQ) && s->stopped_state &&
+            (s->blkgap & SDHC_STOP_AT_GAP_REQ) == 0) {
+        if (s->stopped_state == sdhc_gap_read) {
+            s->prnsts |= SDHC_DAT_LINE_ACTIVE | SDHC_DOING_READ;
+            SDHCI_GET_CLASS(s)->read_block_from_card(s);
+        } else {
+            s->prnsts |= SDHC_DAT_LINE_ACTIVE | SDHC_DOING_WRITE;
+            SDHCI_GET_CLASS(s)->write_block_to_card(s);
+        }
+        s->stopped_state = sdhc_not_stopped;
+    } else if (!s->stopped_state && (value & SDHC_STOP_AT_GAP_REQ)) {
+        if (s->prnsts & SDHC_DOING_READ) {
+            s->stopped_state = sdhc_gap_read;
+        } else if (s->prnsts & SDHC_DOING_WRITE) {
+            s->stopped_state = sdhc_gap_write;
+        }
+    }
+}
+
+static inline void sdhci_reset_write(SDHCIState *s, uint8_t value)
+{
+    switch (value) {
+    case SDHC_RESET_ALL:
+        DEVICE_GET_CLASS(s)->reset(DEVICE(s));
+        break;
+    case SDHC_RESET_CMD:
+        s->prnsts &= ~SDHC_CMD_INHIBIT;
+        s->norintsts &= ~SDHC_NIS_CMDCMP;
+        break;
+    case SDHC_RESET_DATA:
+        s->data_count = 0;
+        s->prnsts &= ~(SDHC_SPACE_AVAILABLE | SDHC_DATA_AVAILABLE |
+                SDHC_DOING_READ | SDHC_DOING_WRITE |
+                SDHC_DATA_INHIBIT | SDHC_DAT_LINE_ACTIVE);
+        s->blkgap &= ~(SDHC_STOP_AT_GAP_REQ | SDHC_CONTINUE_REQ);
+        s->stopped_state = sdhc_not_stopped;
+        s->norintsts &= ~(SDHC_NIS_WBUFRDY | SDHC_NIS_RBUFRDY |
+                SDHC_NIS_DMA | SDHC_NIS_TRSCMP | SDHC_NIS_BLKGAP);
+        break;
+    }
+}
+
+static void
+sdhci_write(SDHCIState *s, unsigned int offset, uint32_t value, unsigned size)
+{
+    unsigned shift =  8 * (offset & 0x3);
+    uint32_t mask = ~(((1ULL << (size * 8)) - 1) << shift);
+    value <<= shift;
+
+    switch (offset & ~0x3) {
+    case SDHC_SYSAD:
+        s->sdmasysad = (s->sdmasysad & mask) | value;
+        MASKED_WRITE(s->sdmasysad, mask, value);
+        /* Writing to last byte of sdmasysad might trigger transfer */
+        if (!(mask & 0xFF000000) && TRANSFERRING_DATA(s->prnsts) && s->blkcnt &&
+                s->blksize && SDHC_DMA_TYPE(s->hostctl) == SDHC_CTRL_SDMA) {
+            SDHCI_GET_CLASS(s)->do_sdma_multi(s);
+        }
+        break;
+    case SDHC_BLKSIZE:
+        if (!TRANSFERRING_DATA(s->prnsts)) {
+            MASKED_WRITE(s->blksize, mask, value);
+            MASKED_WRITE(s->blkcnt, mask >> 16, value >> 16);
+        }
+        break;
+    case SDHC_ARGUMENT:
+        MASKED_WRITE(s->argument, mask, value);
+        break;
+    case SDHC_TRNMOD:
+        /* DMA can be enabled only if it is supported as indicated by
+         * capabilities register */
+        if (!(s->capareg & SDHC_CAN_DO_DMA)) {
+            value &= ~SDHC_TRNS_DMA;
+        }
+        MASKED_WRITE(s->trnmod, mask, value);
+        MASKED_WRITE(s->cmdreg, mask >> 16, value >> 16);
+
+        /* Writing to the upper byte of CMDREG triggers SD command generation */
+        if ((mask & 0xFF000000) || !SDHCI_GET_CLASS(s)->can_issue_command(s)) {
+            break;
+        }
+
+        SDHCI_GET_CLASS(s)->send_command(s);
+        break;
+    case  SDHC_BDATA:
+        if (sdhci_buff_access_is_sequential(s, offset - SDHC_BDATA)) {
+            SDHCI_GET_CLASS(s)->bdata_write(s, value >> shift, size);
+        }
+        break;
+    case SDHC_HOSTCTL:
+        if (!(mask & 0xFF0000)) {
+            sdhci_blkgap_write(s, value >> 16);
+        }
+        MASKED_WRITE(s->hostctl, mask, value);
+        MASKED_WRITE(s->pwrcon, mask >> 8, value >> 8);
+        MASKED_WRITE(s->wakcon, mask >> 24, value >> 24);
+        if (!(s->prnsts & SDHC_CARD_PRESENT) || ((s->pwrcon >> 1) & 0x7) < 5 ||
+                !(s->capareg & (1 << (31 - ((s->pwrcon >> 1) & 0x7))))) {
+            s->pwrcon &= ~SDHC_POWER_ON;
+        }
+        break;
+    case SDHC_CLKCON:
+        if (!(mask & 0xFF000000)) {
+            sdhci_reset_write(s, value >> 24);
+        }
+        MASKED_WRITE(s->clkcon, mask, value);
+        MASKED_WRITE(s->timeoutcon, mask >> 16, value >> 16);
+        if (s->clkcon & SDHC_CLOCK_INT_EN) {
+            s->clkcon |= SDHC_CLOCK_INT_STABLE;
+        } else {
+            s->clkcon &= ~SDHC_CLOCK_INT_STABLE;
+        }
+        break;
+    case SDHC_NORINTSTS:
+        if (s->norintstsen & SDHC_NISEN_CARDINT) {
+            value &= ~SDHC_NIS_CARDINT;
+        }
+        s->norintsts &= mask | ~value;
+        s->errintsts &= (mask >> 16) | ~(value >> 16);
+        if (s->errintsts) {
+            s->norintsts |= SDHC_NIS_ERR;
+        } else {
+            s->norintsts &= ~SDHC_NIS_ERR;
+        }
+        sdhci_update_irq(s);
+        break;
+    case SDHC_NORINTSTSEN:
+        MASKED_WRITE(s->norintstsen, mask, value);
+        MASKED_WRITE(s->errintstsen, mask >> 16, value >> 16);
+        s->norintsts &= s->norintstsen;
+        s->errintsts &= s->errintstsen;
+        if (s->errintsts) {
+            s->norintsts |= SDHC_NIS_ERR;
+        } else {
+            s->norintsts &= ~SDHC_NIS_ERR;
+        }
+        sdhci_update_irq(s);
+        break;
+    case SDHC_NORINTSIGEN:
+        MASKED_WRITE(s->norintsigen, mask, value);
+        MASKED_WRITE(s->errintsigen, mask >> 16, value >> 16);
+        sdhci_update_irq(s);
+        break;
+    case SDHC_ADMAERR:
+        MASKED_WRITE(s->admaerr, mask, value);
+        break;
+    case SDHC_ADMASYSADDR:
+        s->admasysaddr = (s->admasysaddr & (0xFFFFFFFF00000000ULL |
+                (uint64_t)mask)) | (uint64_t)value;
+        break;
+    case SDHC_ADMASYSADDR + 4:
+        s->admasysaddr = (s->admasysaddr & (0x00000000FFFFFFFFULL |
+                ((uint64_t)mask << 32))) | ((uint64_t)value << 32);
+        break;
+    case SDHC_FEAER:
+        s->acmd12errsts |= value;
+        s->errintsts |= (value >> 16) & s->errintstsen;
+        if (s->acmd12errsts) {
+            s->errintsts |= SDHC_EIS_CMD12ERR;
+        }
+        if (s->errintsts) {
+            s->norintsts |= SDHC_NIS_ERR;
+        }
+        sdhci_update_irq(s);
+        break;
+    default:
+        ERRPRINT("bad %ub write offset: addr[0x%04x] <- %u(0x%x)\n",
+                size, offset, value >> shift, value >> shift);
+        break;
+    }
+    DPRINT_L2("write %ub: addr[0x%04x] <- %u(0x%x)\n",
+            size, offset, value >> shift, value >> shift);
+}
+
+static uint64_t
+sdhci_readfn(void *opaque, hwaddr offset, unsigned size)
+{
+    SDHCIState *s = (SDHCIState *)opaque;
+
+    return SDHCI_GET_CLASS(s)->mem_read(s, offset, size);
+}
+
+static void
+sdhci_writefn(void *opaque, hwaddr off, uint64_t val, unsigned sz)
+{
+    SDHCIState *s = (SDHCIState *)opaque;
+
+    SDHCI_GET_CLASS(s)->mem_write(s, off, val, sz);
+}
+
+static const MemoryRegionOps sdhci_mmio_ops = {
+    .read = sdhci_readfn,
+    .write = sdhci_writefn,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+        .unaligned = false
+    },
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static inline unsigned int sdhci_get_fifolen(SDHCIState *s)
+{
+    switch (SDHC_CAPAB_BLOCKSIZE(s->capareg)) {
+    case 0:
+        return 512;
+    case 1:
+        return 1024;
+    case 2:
+        return 2048;
+    default:
+        hw_error("SDHC: unsupported value for maximum block size\n");
+        return 0;
+    }
+}
+
+static void sdhci_initfn(Object *obj)
+{
+    SDHCIState *s = SDHCI(obj);
+    DriveInfo *di;
+
+    di = drive_get_next(IF_SD);
+    s->card = sd_init(di ? di->bdrv : NULL, 0);
+    s->eject_cb = qemu_allocate_irqs(sdhci_insert_eject_cb, s, 1)[0];
+    s->ro_cb = qemu_allocate_irqs(sdhci_card_readonly_cb, s, 1)[0];
+    sd_set_cb(s->card, s->ro_cb, s->eject_cb);
+
+    s->insert_timer = qemu_new_timer_ns(vm_clock, sdhci_raise_insertion_irq, s);
+    s->transfer_timer = qemu_new_timer_ns(vm_clock, sdhci_do_data_transfer, s);
+}
+
+static void sdhci_uninitfn(Object *obj)
+{
+    SDHCIState *s = SDHCI(obj);
+
+    qemu_del_timer(s->insert_timer);
+    qemu_free_timer(s->insert_timer);
+    qemu_del_timer(s->transfer_timer);
+    qemu_free_timer(s->transfer_timer);
+    qemu_free_irqs(&s->eject_cb);
+    qemu_free_irqs(&s->ro_cb);
+
+    if (s->fifo_buffer) {
+        g_free(s->fifo_buffer);
+        s->fifo_buffer = NULL;
+    }
+}
+
+const VMStateDescription sdhci_vmstate = {
+    .name = "sdhci",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(sdmasysad, SDHCIState),
+        VMSTATE_UINT16(blksize, SDHCIState),
+        VMSTATE_UINT16(blkcnt, SDHCIState),
+        VMSTATE_UINT32(argument, SDHCIState),
+        VMSTATE_UINT16(trnmod, SDHCIState),
+        VMSTATE_UINT16(cmdreg, SDHCIState),
+        VMSTATE_UINT32_ARRAY(rspreg, SDHCIState, 4),
+        VMSTATE_UINT32(prnsts, SDHCIState),
+        VMSTATE_UINT8(hostctl, SDHCIState),
+        VMSTATE_UINT8(pwrcon, SDHCIState),
+        VMSTATE_UINT8(blkgap, SDHCIState),
+        VMSTATE_UINT8(wakcon, SDHCIState),
+        VMSTATE_UINT16(clkcon, SDHCIState),
+        VMSTATE_UINT8(timeoutcon, SDHCIState),
+        VMSTATE_UINT8(admaerr, SDHCIState),
+        VMSTATE_UINT16(norintsts, SDHCIState),
+        VMSTATE_UINT16(errintsts, SDHCIState),
+        VMSTATE_UINT16(norintstsen, SDHCIState),
+        VMSTATE_UINT16(errintstsen, SDHCIState),
+        VMSTATE_UINT16(norintsigen, SDHCIState),
+        VMSTATE_UINT16(errintsigen, SDHCIState),
+        VMSTATE_UINT16(acmd12errsts, SDHCIState),
+        VMSTATE_UINT16(data_count, SDHCIState),
+        VMSTATE_UINT64(admasysaddr, SDHCIState),
+        VMSTATE_UINT8(stopped_state, SDHCIState),
+        VMSTATE_VBUFFER_UINT32(fifo_buffer, SDHCIState, 1, NULL, 0, buf_maxsz),
+        VMSTATE_TIMER(insert_timer, SDHCIState),
+        VMSTATE_TIMER(transfer_timer, SDHCIState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+/* Capabilities registers provide information on supported features of this
+ * specific host controller implementation */
+static Property sdhci_properties[] = {
+    DEFINE_PROP_HEX32("capareg", SDHCIState, capareg,
+            SDHC_CAPAB_REG_DEFAULT),
+    DEFINE_PROP_HEX32("maxcurr", SDHCIState, maxcurr, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void sdhci_realize(DeviceState *dev, Error ** errp)
+{
+    SDHCIState *s = SDHCI(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+    s->buf_maxsz = sdhci_get_fifolen(s);
+    s->fifo_buffer = g_malloc0(s->buf_maxsz);
+    sysbus_init_irq(sbd, &s->irq);
+    memory_region_init_io(&s->iomem, &sdhci_mmio_ops, s, "sdhci",
+            SDHC_REGISTERS_MAP_SIZE);
+    sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static void sdhci_generic_reset(DeviceState *ds)
+{
+    SDHCIState *s = SDHCI(ds);
+    SDHCI_GET_CLASS(s)->reset(s);
+}
+
+static void sdhci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SDHCIClass *k = SDHCI_CLASS(klass);
+
+    dc->vmsd = &sdhci_vmstate;
+    dc->props = sdhci_properties;
+    dc->reset = sdhci_generic_reset;
+    dc->realize = sdhci_realize;
+
+    k->reset = sdhci_reset;
+    k->mem_read = sdhci_read;
+    k->mem_write = sdhci_write;
+    k->send_command = sdhci_send_command;
+    k->can_issue_command = sdhci_can_issue_command;
+    k->data_transfer = sdhci_data_transfer;
+    k->end_data_transfer = sdhci_end_transfer;
+    k->do_sdma_single = sdhci_sdma_transfer_single_block;
+    k->do_sdma_multi = sdhci_sdma_transfer_multi_blocks;
+    k->do_adma = sdhci_do_adma;
+    k->read_block_from_card = sdhci_read_block_from_card;
+    k->write_block_to_card = sdhci_write_block_to_card;
+    k->bdata_read = sdhci_read_dataport;
+    k->bdata_write = sdhci_write_dataport;
+}
+
+static const TypeInfo sdhci_type_info = {
+    .name = TYPE_SDHCI,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(SDHCIState),
+    .instance_init = sdhci_initfn,
+    .instance_finalize = sdhci_uninitfn,
+    .class_init = sdhci_class_init,
+    .class_size = sizeof(SDHCIClass)
+};
+
+static void sdhci_register_types(void)
+{
+    type_register_static(&sdhci_type_info);
+}
+
+type_init(sdhci_register_types)
diff --git a/hw/sdhci.h b/hw/sdhci.h
new file mode 100644
index 0000000..931d740
--- /dev/null
+++ b/hw/sdhci.h
@@ -0,0 +1,312 @@
+/*
+ * SD Association Host Standard Specification v2.0 controller emulation
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Mitsyanko Igor <i.mitsyanko at samsung.com>
+ * Peter A.G. Crosthwaite <peter.crosthwaite at petalogix.com>
+ *
+ * Based on MMC controller for Samsung S5PC1xx-based board emulation
+ * by Alexey Merkulov and Vladimir Monakhov.
+ *
+ * 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/>.
+ */
+
+#ifndef SDHCI_H
+#define SDHCI_H
+
+#include "qemu-common.h"
+#include "sysbus.h"
+#include "sd.h"
+
+/* R/W SDMA System Address register 0x0 */
+#define SDHC_SYSAD                     0x00
+
+/* R/W Host DMA Buffer Boundary and Transfer Block Size Register 0x0 */
+#define SDHC_BLKSIZE                   0x04
+
+/* R/W Blocks count for current transfer 0x0 */
+#define SDHC_BLKCNT                    0x06
+
+/* R/W Command Argument Register 0x0 */
+#define SDHC_ARGUMENT                  0x08
+
+/* R/W Transfer Mode Setting Register 0x0 */
+#define SDHC_TRNMOD                    0x0C
+#define SDHC_TRNS_DMA                  0x0001
+#define SDHC_TRNS_BLK_CNT_EN           0x0002
+#define SDHC_TRNS_ACMD12               0x0004
+#define SDHC_TRNS_READ                 0x0010
+#define SDHC_TRNS_MULTI                0x0020
+
+/* R/W Command Register 0x0 */
+#define SDHC_CMDREG                    0x0E
+#define SDHC_CMD_RSP_WITH_BUSY         (3 << 0)
+#define SDHC_CMD_DATA_PRESENT          (1 << 5)
+#define SDHC_CMD_SUSPEND               (1 << 6)
+#define SDHC_CMD_RESUME                (1 << 7)
+#define SDHC_CMD_ABORT                 ((1 << 6)|(1 << 7))
+#define SDHC_CMD_TYPE_MASK             ((1 << 6)|(1 << 7))
+#define SDHC_COMMAND_TYPE(x)           ((x) & SDHC_CMD_TYPE_MASK)
+
+/* ROC Response Register 0 0x0 */
+#define SDHC_RSPREG0                   0x10
+/* ROC Response Register 1 0x0 */
+#define SDHC_RSPREG1                   0x14
+/* ROC Response Register 2 0x0 */
+#define SDHC_RSPREG2                   0x18
+/* ROC Response Register 3 0x0 */
+#define SDHC_RSPREG3                   0x1C
+
+/* R/W Buffer Data Register 0x0 */
+#define SDHC_BDATA                     0x20
+
+/* R/ROC Present State Register 0x000A0000 */
+#define SDHC_PRNSTS                    0x24
+#define SDHC_CMD_INHIBIT               0x00000001
+#define SDHC_DATA_INHIBIT              0x00000002
+#define SDHC_DAT_LINE_ACTIVE           0x00000004
+#define SDHC_DOING_WRITE               0x00000100
+#define SDHC_DOING_READ                0x00000200
+#define SDHC_SPACE_AVAILABLE           0x00000400
+#define SDHC_DATA_AVAILABLE            0x00000800
+#define SDHC_CARD_PRESENT              0x00010000
+#define SDHC_CARD_DETECT               0x00040000
+#define SDHC_WRITE_PROTECT             0x00080000
+#define TRANSFERRING_DATA(x)           \
+    ((x) & (SDHC_DOING_READ | SDHC_DOING_WRITE))
+
+/* R/W Host control Register 0x0 */
+#define SDHC_HOSTCTL                   0x28
+#define SDHC_CTRL_DMA_CHECK_MASK       0x18
+#define SDHC_CTRL_SDMA                 0x00
+#define SDHC_CTRL_ADMA1_32             0x08
+#define SDHC_CTRL_ADMA2_32             0x10
+#define SDHC_CTRL_ADMA2_64             0x18
+#define SDHC_DMA_TYPE(x)               ((x) & SDHC_CTRL_DMA_CHECK_MASK)
+
+/* R/W Power Control Register 0x0 */
+#define SDHC_PWRCON                    0x29
+#define SDHC_POWER_ON                  (1 << 0)
+
+/* R/W Block Gap Control Register 0x0 */
+#define SDHC_BLKGAP                    0x2A
+#define SDHC_STOP_AT_GAP_REQ           0x01
+#define SDHC_CONTINUE_REQ              0x02
+
+/* R/W WakeUp Control Register 0x0 */
+#define SDHC_WAKCON                    0x2B
+#define SDHC_WKUP_ON_INS               (1 << 1)
+#define SDHC_WKUP_ON_RMV               (1 << 2)
+
+/* CLKCON */
+#define SDHC_CLKCON                    0x2C
+#define SDHC_CLOCK_INT_STABLE          0x0002
+#define SDHC_CLOCK_INT_EN              0x0001
+#define SDHC_CLOCK_SDCLK_EN            (1 << 2)
+#define SDHC_CLOCK_CHK_MASK            0x0007
+#define SDHC_CLOCK_IS_ON(x)            \
+    (((x) & SDHC_CLOCK_CHK_MASK) == SDHC_CLOCK_CHK_MASK)
+
+/* R/W Timeout Control Register 0x0 */
+#define SDHC_TIMEOUTCON                0x2E
+
+/* R/W Software Reset Register 0x0 */
+#define SDHC_SWRST                     0x2F
+#define SDHC_RESET_ALL                 0x01
+#define SDHC_RESET_CMD                 0x02
+#define SDHC_RESET_DATA                0x04
+
+/* ROC/RW1C Normal Interrupt Status Register 0x0 */
+#define SDHC_NORINTSTS                 0x30
+#define SDHC_NIS_ERR                   0x8000
+#define SDHC_NIS_CMDCMP                0x0001
+#define SDHC_NIS_TRSCMP                0x0002
+#define SDHC_NIS_BLKGAP                0x0004
+#define SDHC_NIS_DMA                   0x0008
+#define SDHC_NIS_WBUFRDY               0x0010
+#define SDHC_NIS_RBUFRDY               0x0020
+#define SDHC_NIS_INSERT                0x0040
+#define SDHC_NIS_REMOVE                0x0080
+#define SDHC_NIS_CARDINT               0x0100
+
+/* ROC/RW1C Error Interrupt Status Register 0x0 */
+#define SDHC_ERRINTSTS                 0x32
+#define SDHC_EIS_CMDTIMEOUT            0x0001
+#define SDHC_EIS_BLKGAP                0x0004
+#define SDHC_EIS_CMDIDX                0x0008
+#define SDHC_EIS_CMD12ERR              0x0100
+#define SDHC_EIS_ADMAERR               0x0200
+
+/* R/W Normal Interrupt Status Enable Register 0x0 */
+#define SDHC_NORINTSTSEN               0x34
+#define SDHC_NISEN_CMDCMP              0x0001
+#define SDHC_NISEN_TRSCMP              0x0002
+#define SDHC_NISEN_DMA                 0x0008
+#define SDHC_NISEN_WBUFRDY             0x0010
+#define SDHC_NISEN_RBUFRDY             0x0020
+#define SDHC_NISEN_INSERT              0x0040
+#define SDHC_NISEN_REMOVE              0x0080
+#define SDHC_NISEN_CARDINT             0x0100
+
+/* R/W Error Interrupt Status Enable Register 0x0 */
+#define SDHC_ERRINTSTSEN               0x36
+#define SDHC_EISEN_CMDTIMEOUT          0x0001
+#define SDHC_EISEN_BLKGAP              0x0004
+#define SDHC_EISEN_CMDIDX              0x0008
+#define SDHC_EISEN_ADMAERR             0x0200
+
+/* R/W Normal Interrupt Signal Enable Register 0x0 */
+#define SDHC_NORINTSIGEN               0x38
+#define SDHC_NORINTSIG_INSERT          (1 << 6)
+#define SDHC_NORINTSIG_REMOVE          (1 << 7)
+
+/* R/W Error Interrupt Signal Enable Register 0x0 */
+#define SDHC_ERRINTSIGEN               0x3A
+
+/* ROC Auto CMD12 error status register 0x0 */
+#define SDHC_ACMD12ERRSTS              0x3C
+
+/* HWInit Capabilities Register 0x05E80080 */
+#define SDHC_CAPAREG                   0x40
+#define SDHC_CAN_DO_DMA                0x00400000
+#define SDHC_CAN_DO_ADMA2              0x00080000
+#define SDHC_CAN_DO_ADMA1              0x00100000
+#define SDHC_64_BIT_BUS_SUPPORT        (1 << 28)
+#define SDHC_CAPAB_BLOCKSIZE(x)        (((x) >> 16) & 0x3)
+
+/* HWInit Maximum Current Capabilities Register 0x0 */
+#define SDHC_MAXCURR                   0x48
+
+/* W Force Event Auto CMD12 Error Interrupt Register 0x0000 */
+#define SDHC_FEAER                     0x50
+/* W Force Event Error Interrupt Register Error Interrupt 0x0000 */
+#define SDHC_FEERR                     0x52
+
+/* R/W ADMA Error Status Register 0x00 */
+#define SDHC_ADMAERR                   0x54
+#define SDHC_ADMAERR_LENGTH_MISMATCH   (1 << 2)
+#define SDHC_ADMAERR_STATE_ST_STOP     (0 << 0)
+#define SDHC_ADMAERR_STATE_ST_FDS      (1 << 0)
+#define SDHC_ADMAERR_STATE_ST_TFR      (3 << 0)
+#define SDHC_ADMAERR_STATE_MASK        (3 << 0)
+
+/* R/W ADMA System Address Register 0x00 */
+#define SDHC_ADMASYSADDR               0x58
+#define SDHC_ADMA_ATTR_SET_LEN         (1 << 4)
+#define SDHC_ADMA_ATTR_ACT_TRAN        (1 << 5)
+#define SDHC_ADMA_ATTR_ACT_LINK        (3 << 4)
+#define SDHC_ADMA_ATTR_INT             (1 << 2)
+#define SDHC_ADMA_ATTR_END             (1 << 1)
+#define SDHC_ADMA_ATTR_VALID           (1 << 0)
+#define SDHC_ADMA_ATTR_ACT_MASK        ((1 << 4)|(1 << 5))
+
+/* Slot interrupt status */
+#define SDHC_SLOT_INT_STATUS            0xFC
+
+/* HWInit Host Controller Version Register 0x0401 */
+#define SDHC_HCVER                      0xFE
+#define SD_HOST_SPECv2_VERS             0x2401
+
+#define SDHC_REGISTERS_MAP_SIZE         0x100
+#define SDHC_INSERTION_DELAY            (get_ticks_per_sec())
+#define SDHC_TRANSFER_DELAY             100
+#define SDHC_ADMA_DESCS_PER_DELAY       5
+#define SDHC_CMD_RESPONSE               (3 << 0)
+
+enum {
+    sdhc_not_stopped = 0, /* normal SDHC state */
+    sdhc_gap_read   = 1,  /* SDHC stopped at block gap during read operation */
+    sdhc_gap_write  = 2   /* SDHC stopped at block gap during write operation */
+};
+
+/* SD/MMC host controller state */
+typedef struct SDHCIState {
+    SysBusDevice busdev;
+    SDState *card;
+    MemoryRegion iomem;
+
+    QEMUTimer *insert_timer;       /* timer for 'changing' sd card. */
+    QEMUTimer *transfer_timer;
+    qemu_irq eject_cb;
+    qemu_irq ro_cb;
+    qemu_irq irq;
+
+    uint32_t sdmasysad;    /* SDMA System Address register */
+    uint16_t blksize;      /* Host DMA Buff Boundary and Transfer BlkSize Reg */
+    uint16_t blkcnt;       /* Blocks count for current transfer */
+    uint32_t argument;     /* Command Argument Register */
+    uint16_t trnmod;       /* Transfer Mode Setting Register */
+    uint16_t cmdreg;       /* Command Register */
+    uint32_t rspreg[4];    /* Response Registers 0-3 */
+    uint32_t prnsts;       /* Present State Register */
+    uint8_t  hostctl;      /* Host Control Register */
+    uint8_t  pwrcon;       /* Power control Register */
+    uint8_t  blkgap;       /* Block Gap Control Register */
+    uint8_t  wakcon;       /* WakeUp Control Register */
+    uint16_t clkcon;       /* Clock control Register */
+    uint8_t  timeoutcon;   /* Timeout Control Register */
+    uint8_t  admaerr;      /* ADMA Error Status Register */
+    uint16_t norintsts;    /* Normal Interrupt Status Register */
+    uint16_t errintsts;    /* Error Interrupt Status Register */
+    uint16_t norintstsen;  /* Normal Interrupt Status Enable Register */
+    uint16_t errintstsen;  /* Error Interrupt Status Enable Register */
+    uint16_t norintsigen;  /* Normal Interrupt Signal Enable Register */
+    uint16_t errintsigen;  /* Error Interrupt Signal Enable Register */
+    uint16_t acmd12errsts; /* Auto CMD12 error status register */
+    uint64_t admasysaddr;  /* ADMA System Address Register */
+
+    uint32_t capareg;      /* Capabilities Register */
+    uint32_t maxcurr;      /* Maximum Current Capabilities Register */
+    uint8_t  *fifo_buffer; /* SD host i/o FIFO buffer */
+    uint32_t buf_maxsz;
+    uint16_t data_count;   /* current element in FIFO buffer */
+    uint8_t  stopped_state;/* Current SDHC state */
+    /* Buffer Data Port Register - virtual access point to R and W buffers */
+    /* Software Reset Register - always reads as 0 */
+    /* Force Event Auto CMD12 Error Interrupt Reg - write only */
+    /* Force Event Error Interrupt Register- write only */
+    /* RO Host Controller Version Register always reads as 0x2401 */
+} SDHCIState;
+
+typedef struct SDHCIClass {
+    SysBusDeviceClass busdev_class;
+
+    void (*reset)(SDHCIState *s);
+    uint32_t (*mem_read)(SDHCIState *s, unsigned int offset, unsigned size);
+    void (*mem_write)(SDHCIState *s, unsigned int offset, uint32_t value,
+            unsigned size);
+    void (*send_command)(SDHCIState *s);
+    bool (*can_issue_command)(SDHCIState *s);
+    void (*data_transfer)(SDHCIState *s);
+    void (*end_data_transfer)(SDHCIState *s);
+    void (*do_sdma_single)(SDHCIState *s);
+    void (*do_sdma_multi)(SDHCIState *s);
+    void (*do_adma)(SDHCIState *s);
+    void (*read_block_from_card)(SDHCIState *s);
+    void (*write_block_to_card)(SDHCIState *s);
+    uint32_t (*bdata_read)(SDHCIState *s, unsigned size);
+    void (*bdata_write)(SDHCIState *s, uint32_t value, unsigned size);
+} SDHCIClass;
+
+extern const VMStateDescription sdhci_vmstate;
+
+#define TYPE_SDHCI            "generic-sdhci"
+#define SDHCI(obj)            \
+     OBJECT_CHECK(SDHCIState, (obj), TYPE_SDHCI)
+#define SDHCI_CLASS(klass)    \
+     OBJECT_CLASS_CHECK(SDHCIClass, (klass), TYPE_SDHCI)
+#define SDHCI_GET_CLASS(obj)  \
+     OBJECT_GET_CLASS(SDHCIClass, (obj), TYPE_SDHCI)
+
+#endif /* SDHCI_H */
commit 353575f0959234e1680622f747e20308c94505b7
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Feb 28 18:23:14 2013 +0000

    arm: a9mpcore: Coreify the SCU
    
    Split the SCU in a9mpcore out into its own object definition. mpcore is now
    just a container for the mpcore components.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 23630af..01aee02 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -10,113 +10,17 @@
 
 #include "sysbus.h"
 
-/* A9MP private memory region.  */
-
 typedef struct A9MPPrivState {
     SysBusDevice busdev;
-    uint32_t scu_control;
-    uint32_t scu_status;
     uint32_t num_cpu;
-    MemoryRegion scu_iomem;
     MemoryRegion container;
     DeviceState *mptimer;
     DeviceState *wdt;
     DeviceState *gic;
+    DeviceState *scu;
     uint32_t num_irq;
 } A9MPPrivState;
 
-static uint64_t a9_scu_read(void *opaque, hwaddr offset,
-                            unsigned size)
-{
-    A9MPPrivState *s = (A9MPPrivState *)opaque;
-    switch (offset) {
-    case 0x00: /* Control */
-        return s->scu_control;
-    case 0x04: /* Configuration */
-        return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1);
-    case 0x08: /* CPU Power Status */
-        return s->scu_status;
-    case 0x09: /* CPU status.  */
-        return s->scu_status >> 8;
-    case 0x0a: /* CPU status.  */
-        return s->scu_status >> 16;
-    case 0x0b: /* CPU status.  */
-        return s->scu_status >> 24;
-    case 0x0c: /* Invalidate All Registers In Secure State */
-        return 0;
-    case 0x40: /* Filtering Start Address Register */
-    case 0x44: /* Filtering End Address Register */
-        /* RAZ/WI, like an implementation with only one AXI master */
-        return 0;
-    case 0x50: /* SCU Access Control Register */
-    case 0x54: /* SCU Non-secure Access Control Register */
-        /* unimplemented, fall through */
-    default:
-        return 0;
-    }
-}
-
-static void a9_scu_write(void *opaque, hwaddr offset,
-                         uint64_t value, unsigned size)
-{
-    A9MPPrivState *s = (A9MPPrivState *)opaque;
-    uint32_t mask;
-    uint32_t shift;
-    switch (size) {
-    case 1:
-        mask = 0xff;
-        break;
-    case 2:
-        mask = 0xffff;
-        break;
-    case 4:
-        mask = 0xffffffff;
-        break;
-    default:
-        fprintf(stderr, "Invalid size %u in write to a9 scu register %x\n",
-                size, (unsigned)offset);
-        return;
-    }
-
-    switch (offset) {
-    case 0x00: /* Control */
-        s->scu_control = value & 1;
-        break;
-    case 0x4: /* Configuration: RO */
-        break;
-    case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */
-        shift = (offset - 0x8) * 8;
-        s->scu_status &= ~(mask << shift);
-        s->scu_status |= ((value & mask) << shift);
-        break;
-    case 0x0c: /* Invalidate All Registers In Secure State */
-        /* no-op as we do not implement caches */
-        break;
-    case 0x40: /* Filtering Start Address Register */
-    case 0x44: /* Filtering End Address Register */
-        /* RAZ/WI, like an implementation with only one AXI master */
-        break;
-    case 0x50: /* SCU Access Control Register */
-    case 0x54: /* SCU Non-secure Access Control Register */
-        /* unimplemented, fall through */
-    default:
-        break;
-    }
-}
-
-static const MemoryRegionOps a9_scu_ops = {
-    .read = a9_scu_read,
-    .write = a9_scu_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void a9mp_priv_reset(DeviceState *dev)
-{
-    A9MPPrivState *s = FROM_SYSBUS(A9MPPrivState, SYS_BUS_DEVICE(dev));
-
-    s->scu_control = 0;
-}
-
 static void a9mp_priv_set_irq(void *opaque, int irq, int level)
 {
     A9MPPrivState *s = (A9MPPrivState *)opaque;
@@ -126,7 +30,7 @@ static void a9mp_priv_set_irq(void *opaque, int irq, int level)
 static int a9mp_priv_init(SysBusDevice *dev)
 {
     A9MPPrivState *s = FROM_SYSBUS(A9MPPrivState, dev);
-    SysBusDevice *timerbusdev, *wdtbusdev, *gicbusdev;
+    SysBusDevice *timerbusdev, *wdtbusdev, *gicbusdev, *scubusdev;
     int i;
 
     s->gic = qdev_create(NULL, "arm_gic");
@@ -141,6 +45,11 @@ static int a9mp_priv_init(SysBusDevice *dev)
     /* Pass through inbound GPIO lines to the GIC */
     qdev_init_gpio_in(&s->busdev.qdev, a9mp_priv_set_irq, s->num_irq - 32);
 
+    s->scu = qdev_create(NULL, "a9-scu");
+    qdev_prop_set_uint32(s->scu, "num-cpu", s->num_cpu);
+    qdev_init_nofail(s->scu);
+    scubusdev = SYS_BUS_DEVICE(s->scu);
+
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
     qdev_init_nofail(s->mptimer);
@@ -163,8 +72,8 @@ static int a9mp_priv_init(SysBusDevice *dev)
      * We should implement the global timer but don't currently do so.
      */
     memory_region_init(&s->container, "a9mp-priv-container", 0x2000);
-    memory_region_init_io(&s->scu_iomem, &a9_scu_ops, s, "a9mp-scu", 0x100);
-    memory_region_add_subregion(&s->container, 0, &s->scu_iomem);
+    memory_region_add_subregion(&s->container, 0,
+                                sysbus_mmio_get_region(scubusdev, 0));
     /* GIC CPU interface */
     memory_region_add_subregion(&s->container, 0x100,
                                 sysbus_mmio_get_region(gicbusdev, 1));
@@ -193,17 +102,6 @@ static int a9mp_priv_init(SysBusDevice *dev)
     return 0;
 }
 
-static const VMStateDescription vmstate_a9mp_priv = {
-    .name = "a9mpcore_priv",
-    .version_id = 3,
-    .minimum_version_id = 3,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(scu_control, A9MPPrivState),
-        VMSTATE_UINT32_V(scu_status, A9MPPrivState, 2),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
 static Property a9mp_priv_properties[] = {
     DEFINE_PROP_UINT32("num-cpu", A9MPPrivState, num_cpu, 1),
     /* The Cortex-A9MP may have anything from 0 to 224 external interrupt
@@ -223,8 +121,6 @@ static void a9mp_priv_class_init(ObjectClass *klass, void *data)
 
     k->init = a9mp_priv_init;
     dc->props = a9mp_priv_properties;
-    dc->vmsd = &vmstate_a9mp_priv;
-    dc->reset = a9mp_priv_reset;
 }
 
 static const TypeInfo a9mp_priv_info = {
diff --git a/hw/a9scu.c b/hw/a9scu.c
new file mode 100644
index 0000000..0e9e54d
--- /dev/null
+++ b/hw/a9scu.c
@@ -0,0 +1,164 @@
+/*
+ * Cortex-A9MPCore Snoop Control Unit (SCU) emulation.
+ *
+ * Copyright (c) 2009 CodeSourcery.
+ * Copyright (c) 2011 Linaro Limited.
+ * Written by Paul Brook, Peter Maydell.
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "sysbus.h"
+
+/* A9MP private memory region.  */
+
+typedef struct A9SCUState {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t control;
+    uint32_t status;
+    uint32_t num_cpu;
+} A9SCUState;
+
+#define TYPE_A9_SCU "a9-scu"
+#define A9_SCU(obj) OBJECT_CHECK(A9SCUState, (obj), TYPE_A9_SCU)
+
+static uint64_t a9_scu_read(void *opaque, hwaddr offset,
+                            unsigned size)
+{
+    A9SCUState *s = (A9SCUState *)opaque;
+    switch (offset) {
+    case 0x00: /* Control */
+        return s->control;
+    case 0x04: /* Configuration */
+        return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1);
+    case 0x08: /* CPU Power Status */
+        return s->status;
+    case 0x09: /* CPU status.  */
+        return s->status >> 8;
+    case 0x0a: /* CPU status.  */
+        return s->status >> 16;
+    case 0x0b: /* CPU status.  */
+        return s->status >> 24;
+    case 0x0c: /* Invalidate All Registers In Secure State */
+        return 0;
+    case 0x40: /* Filtering Start Address Register */
+    case 0x44: /* Filtering End Address Register */
+        /* RAZ/WI, like an implementation with only one AXI master */
+        return 0;
+    case 0x50: /* SCU Access Control Register */
+    case 0x54: /* SCU Non-secure Access Control Register */
+        /* unimplemented, fall through */
+    default:
+        return 0;
+    }
+}
+
+static void a9_scu_write(void *opaque, hwaddr offset,
+                         uint64_t value, unsigned size)
+{
+    A9SCUState *s = (A9SCUState *)opaque;
+    uint32_t mask;
+    uint32_t shift;
+    switch (size) {
+    case 1:
+        mask = 0xff;
+        break;
+    case 2:
+        mask = 0xffff;
+        break;
+    case 4:
+        mask = 0xffffffff;
+        break;
+    default:
+        fprintf(stderr, "Invalid size %u in write to a9 scu register %x\n",
+                size, (unsigned)offset);
+        return;
+    }
+
+    switch (offset) {
+    case 0x00: /* Control */
+        s->control = value & 1;
+        break;
+    case 0x4: /* Configuration: RO */
+        break;
+    case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */
+        shift = (offset - 0x8) * 8;
+        s->status &= ~(mask << shift);
+        s->status |= ((value & mask) << shift);
+        break;
+    case 0x0c: /* Invalidate All Registers In Secure State */
+        /* no-op as we do not implement caches */
+        break;
+    case 0x40: /* Filtering Start Address Register */
+    case 0x44: /* Filtering End Address Register */
+        /* RAZ/WI, like an implementation with only one AXI master */
+        break;
+    case 0x50: /* SCU Access Control Register */
+    case 0x54: /* SCU Non-secure Access Control Register */
+        /* unimplemented, fall through */
+    default:
+        break;
+    }
+}
+
+static const MemoryRegionOps a9_scu_ops = {
+    .read = a9_scu_read,
+    .write = a9_scu_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void a9_scu_reset(DeviceState *dev)
+{
+    A9SCUState *s = A9_SCU(dev);
+    s->control = 0;
+}
+
+static void a9_scu_realize(DeviceState *dev, Error ** errp)
+{
+    A9SCUState *s = A9_SCU(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+    memory_region_init_io(&s->iomem, &a9_scu_ops, s, "a9-scu", 0x100);
+    sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static const VMStateDescription vmstate_a9_scu = {
+    .name = "a9-scu",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(control, A9SCUState),
+        VMSTATE_UINT32(status, A9SCUState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property a9_scu_properties[] = {
+    DEFINE_PROP_UINT32("num-cpu", A9SCUState, num_cpu, 1),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void a9_scu_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = a9_scu_realize;
+    dc->props = a9_scu_properties;
+    dc->vmsd = &vmstate_a9_scu;
+    dc->reset = a9_scu_reset;
+}
+
+static const TypeInfo a9_scu_info = {
+    .name          = TYPE_A9_SCU,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(A9SCUState),
+    .class_init    = a9_scu_class_init,
+};
+
+static void a9mp_register_types(void)
+{
+    type_register_static(&a9_scu_info);
+}
+
+type_init(a9mp_register_types)
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 6d049e7..4c10985 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -3,6 +3,7 @@ obj-y += arm_boot.o
 obj-y += xilinx_zynq.o zynq_slcr.o
 obj-y += xilinx_spips.o
 obj-y += arm_gic.o arm_gic_common.o
+obj-y += a9scu.o
 obj-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
 obj-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o
commit 9595978292e9a5b5f0ec77a9f6a0e724c10bf3b4
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Feb 28 18:23:13 2013 +0000

    arm: a9mpcore: remove old_timer_status field
    
    This field was write only and thus unused. Removed.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 0032f53..23630af 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -16,7 +16,6 @@ typedef struct A9MPPrivState {
     SysBusDevice busdev;
     uint32_t scu_control;
     uint32_t scu_status;
-    uint32_t old_timer_status[8];
     uint32_t num_cpu;
     MemoryRegion scu_iomem;
     MemoryRegion container;
@@ -114,11 +113,8 @@ static const MemoryRegionOps a9_scu_ops = {
 static void a9mp_priv_reset(DeviceState *dev)
 {
     A9MPPrivState *s = FROM_SYSBUS(A9MPPrivState, SYS_BUS_DEVICE(dev));
-    int i;
+
     s->scu_control = 0;
-    for (i = 0; i < ARRAY_SIZE(s->old_timer_status); i++) {
-        s->old_timer_status[i] = 0;
-    }
 }
 
 static void a9mp_priv_set_irq(void *opaque, int irq, int level)
@@ -199,11 +195,10 @@ static int a9mp_priv_init(SysBusDevice *dev)
 
 static const VMStateDescription vmstate_a9mp_priv = {
     .name = "a9mpcore_priv",
-    .version_id = 2,
-    .minimum_version_id = 1,
+    .version_id = 3,
+    .minimum_version_id = 3,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(scu_control, A9MPPrivState),
-        VMSTATE_UINT32_ARRAY(old_timer_status, A9MPPrivState, 8),
         VMSTATE_UINT32_V(scu_status, A9MPPrivState, 2),
         VMSTATE_END_OF_LIST()
     }
commit cde4577f11cd557cfd48d752b7a0929d19eac9e9
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Feb 28 18:23:13 2013 +0000

    arm: mptimer: Remove WDT distinction
    
    In QEMU emulation, there is no functional difference between the ARM mpcore
    private timers and watchdogs. Removed all the distinction between the two from
    arm_mptimer.c and converted it to be just the mptimer. a9mpcore and arm11mpcore
    just instantiate the same mptimer object twice to get both timer and WDT.
    
    If in the future we want to make the WDT functionally different then we can use
    either QOM hierarchy to derive WDT from from mptimer, or we can add a property
    "is-wdt" or some such.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 33b9e07..0032f53 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -21,6 +21,7 @@ typedef struct A9MPPrivState {
     MemoryRegion scu_iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    DeviceState *wdt;
     DeviceState *gic;
     uint32_t num_irq;
 } A9MPPrivState;
@@ -129,7 +130,7 @@ static void a9mp_priv_set_irq(void *opaque, int irq, int level)
 static int a9mp_priv_init(SysBusDevice *dev)
 {
     A9MPPrivState *s = FROM_SYSBUS(A9MPPrivState, dev);
-    SysBusDevice *busdev, *gicbusdev;
+    SysBusDevice *timerbusdev, *wdtbusdev, *gicbusdev;
     int i;
 
     s->gic = qdev_create(NULL, "arm_gic");
@@ -147,7 +148,12 @@ static int a9mp_priv_init(SysBusDevice *dev)
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
     qdev_init_nofail(s->mptimer);
-    busdev = SYS_BUS_DEVICE(s->mptimer);
+    timerbusdev = SYS_BUS_DEVICE(s->mptimer);
+
+    s->wdt = qdev_create(NULL, "arm_mptimer");
+    qdev_prop_set_uint32(s->wdt, "num-cpu", s->num_cpu);
+    qdev_init_nofail(s->wdt);
+    wdtbusdev = SYS_BUS_DEVICE(s->wdt);
 
     /* Memory map (addresses are offsets from PERIPHBASE):
      *  0x0000-0x00ff -- Snoop Control Unit
@@ -170,9 +176,9 @@ static int a9mp_priv_init(SysBusDevice *dev)
      * memory region, not the "timer/watchdog for core X" ones 11MPcore has.
      */
     memory_region_add_subregion(&s->container, 0x600,
-                                sysbus_mmio_get_region(busdev, 0));
+                                sysbus_mmio_get_region(timerbusdev, 0));
     memory_region_add_subregion(&s->container, 0x620,
-                                sysbus_mmio_get_region(busdev, 1));
+                                sysbus_mmio_get_region(wdtbusdev, 0));
     memory_region_add_subregion(&s->container, 0x1000,
                                 sysbus_mmio_get_region(gicbusdev, 0));
 
@@ -183,9 +189,9 @@ static int a9mp_priv_init(SysBusDevice *dev)
      */
     for (i = 0; i < s->num_cpu; i++) {
         int ppibase = (s->num_irq - 32) + i * 32;
-        sysbus_connect_irq(busdev, i * 2,
+        sysbus_connect_irq(timerbusdev, i,
                            qdev_get_gpio_in(s->gic, ppibase + 29));
-        sysbus_connect_irq(busdev, i * 2 + 1,
+        sysbus_connect_irq(wdtbusdev, i,
                            qdev_get_gpio_in(s->gic, ppibase + 30));
     }
     return 0;
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index b900b35..ca49948 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -21,6 +21,7 @@ typedef struct ARM11MPCorePriveState {
     MemoryRegion iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    DeviceState *wdtimer;
     DeviceState *gic;
     uint32_t num_irq;
 } ARM11MPCorePriveState;
@@ -84,7 +85,8 @@ static void mpcore_priv_map_setup(ARM11MPCorePriveState *s)
 {
     int i;
     SysBusDevice *gicbusdev = SYS_BUS_DEVICE(s->gic);
-    SysBusDevice *busdev = SYS_BUS_DEVICE(s->mptimer);
+    SysBusDevice *timerbusdev = SYS_BUS_DEVICE(s->mptimer);
+    SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(s->wdtimer);
     memory_region_init(&s->container, "mpcode-priv-container", 0x2000);
     memory_region_init_io(&s->iomem, &mpcore_scu_ops, s, "mpcore-scu", 0x100);
     memory_region_add_subregion(&s->container, 0, &s->iomem);
@@ -99,11 +101,13 @@ static void mpcore_priv_map_setup(ARM11MPCorePriveState *s)
     /* Add the regions for timer and watchdog for "current CPU" and
      * for each specific CPU.
      */
-    for (i = 0; i < (s->num_cpu + 1) * 2; i++) {
+    for (i = 0; i < (s->num_cpu + 1); i++) {
         /* Timers at 0x600, 0x700, ...; watchdogs at 0x620, 0x720, ... */
-        hwaddr offset = 0x600 + (i >> 1) * 0x100 + (i & 1) * 0x20;
+        hwaddr offset = 0x600 + i * 0x100;
         memory_region_add_subregion(&s->container, offset,
-                                    sysbus_mmio_get_region(busdev, i));
+                                    sysbus_mmio_get_region(timerbusdev, i));
+        memory_region_add_subregion(&s->container, offset + 0x20,
+                                    sysbus_mmio_get_region(wdtbusdev, i));
     }
     memory_region_add_subregion(&s->container, 0x1000,
                                 sysbus_mmio_get_region(gicbusdev, 0));
@@ -112,9 +116,9 @@ static void mpcore_priv_map_setup(ARM11MPCorePriveState *s)
      */
     for (i = 0; i < s->num_cpu; i++) {
         int ppibase = (s->num_irq - 32) + i * 32;
-        sysbus_connect_irq(busdev, i * 2,
+        sysbus_connect_irq(timerbusdev, i,
                            qdev_get_gpio_in(s->gic, ppibase + 29));
-        sysbus_connect_irq(busdev, i * 2 + 1,
+        sysbus_connect_irq(wdtbusdev, i,
                            qdev_get_gpio_in(s->gic, ppibase + 30));
     }
 }
@@ -139,6 +143,11 @@ static int mpcore_priv_init(SysBusDevice *dev)
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
     qdev_init_nofail(s->mptimer);
+
+    s->wdtimer = qdev_create(NULL, "arm_mptimer");
+    qdev_prop_set_uint32(s->wdtimer, "num-cpu", s->num_cpu);
+    qdev_init_nofail(s->wdtimer);
+
     mpcore_priv_map_setup(s);
     sysbus_init_mmio(dev, &s->container);
     return 0;
diff --git a/hw/arm_mptimer.c b/hw/arm_mptimer.c
index de0ef36..7b08aa3 100644
--- a/hw/arm_mptimer.c
+++ b/hw/arm_mptimer.c
@@ -43,8 +43,8 @@ typedef struct {
 typedef struct {
     SysBusDevice busdev;
     uint32_t num_cpu;
-    TimerBlock timerblock[MAX_CPUS * 2];
-    MemoryRegion iomem[2];
+    TimerBlock timerblock[MAX_CPUS];
+    MemoryRegion iomem;
 } ARMMPTimerState;
 
 static inline int get_current_cpu(ARMMPTimerState *s)
@@ -166,7 +166,7 @@ static uint64_t arm_thistimer_read(void *opaque, hwaddr addr,
 {
     ARMMPTimerState *s = (ARMMPTimerState *)opaque;
     int id = get_current_cpu(s);
-    return timerblock_read(&s->timerblock[id * 2], addr, size);
+    return timerblock_read(&s->timerblock[id], addr, size);
 }
 
 static void arm_thistimer_write(void *opaque, hwaddr addr,
@@ -174,23 +174,7 @@ static void arm_thistimer_write(void *opaque, hwaddr addr,
 {
     ARMMPTimerState *s = (ARMMPTimerState *)opaque;
     int id = get_current_cpu(s);
-    timerblock_write(&s->timerblock[id * 2], addr, value, size);
-}
-
-static uint64_t arm_thiswdog_read(void *opaque, hwaddr addr,
-                                  unsigned size)
-{
-    ARMMPTimerState *s = (ARMMPTimerState *)opaque;
-    int id = get_current_cpu(s);
-    return timerblock_read(&s->timerblock[id * 2 + 1], addr, size);
-}
-
-static void arm_thiswdog_write(void *opaque, hwaddr addr,
-                               uint64_t value, unsigned size)
-{
-    ARMMPTimerState *s = (ARMMPTimerState *)opaque;
-    int id = get_current_cpu(s);
-    timerblock_write(&s->timerblock[id * 2 + 1], addr, value, size);
+    timerblock_write(&s->timerblock[id], addr, value, size);
 }
 
 static const MemoryRegionOps arm_thistimer_ops = {
@@ -203,16 +187,6 @@ static const MemoryRegionOps arm_thistimer_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static const MemoryRegionOps arm_thiswdog_ops = {
-    .read = arm_thiswdog_read,
-    .write = arm_thiswdog_write,
-    .valid = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
 static const MemoryRegionOps timerblock_ops = {
     .read = timerblock_read,
     .write = timerblock_write,
@@ -240,9 +214,6 @@ static void arm_mptimer_reset(DeviceState *dev)
     ARMMPTimerState *s =
         FROM_SYSBUS(ARMMPTimerState, SYS_BUS_DEVICE(dev));
     int i;
-    /* We reset every timer in the array, not just the ones we're using,
-     * because vmsave will look at every array element.
-     */
     for (i = 0; i < ARRAY_SIZE(s->timerblock); i++) {
         timerblock_reset(&s->timerblock[i]);
     }
@@ -255,29 +226,20 @@ static int arm_mptimer_init(SysBusDevice *dev)
     if (s->num_cpu < 1 || s->num_cpu > MAX_CPUS) {
         hw_error("%s: num-cpu must be between 1 and %d\n", __func__, MAX_CPUS);
     }
-    /* We implement one timer and one watchdog block per CPU, and
-     * expose multiple MMIO regions:
+    /* We implement one timer block per CPU, and expose multiple MMIO regions:
      *  * region 0 is "timer for this core"
-     *  * region 1 is "watchdog for this core"
-     *  * region 2 is "timer for core 0"
-     *  * region 3 is "watchdog for core 0"
-     *  * region 4 is "timer for core 1"
-     *  * region 5 is "watchdog for core 1"
+     *  * region 1 is "timer for core 0"
+     *  * region 2 is "timer for core 1"
      * and so on.
      * The outgoing interrupt lines are
      *  * timer for core 0
-     *  * watchdog for core 0
      *  * timer for core 1
-     *  * watchdog for core 1
      * and so on.
      */
-    memory_region_init_io(&s->iomem[0], &arm_thistimer_ops, s,
+    memory_region_init_io(&s->iomem, &arm_thistimer_ops, s,
                           "arm_mptimer_timer", 0x20);
-    sysbus_init_mmio(dev, &s->iomem[0]);
-    memory_region_init_io(&s->iomem[1], &arm_thiswdog_ops, s,
-                          "arm_mptimer_wdog", 0x20);
-    sysbus_init_mmio(dev, &s->iomem[1]);
-    for (i = 0; i < (s->num_cpu * 2); i++) {
+    sysbus_init_mmio(dev, &s->iomem);
+    for (i = 0; i < s->num_cpu; i++) {
         TimerBlock *tb = &s->timerblock[i];
         tb->timer = qemu_new_timer_ns(vm_clock, timerblock_tick, tb);
         sysbus_init_irq(dev, &tb->irq);
@@ -305,11 +267,11 @@ static const VMStateDescription vmstate_timerblock = {
 
 static const VMStateDescription vmstate_arm_mptimer = {
     .name = "arm_mptimer",
-    .version_id = 1,
-    .minimum_version_id = 1,
+    .version_id = 2,
+    .minimum_version_id = 2,
     .fields = (VMStateField[]) {
-        VMSTATE_STRUCT_ARRAY(timerblock, ARMMPTimerState, (MAX_CPUS * 2),
-                             1, vmstate_timerblock, TimerBlock),
+        VMSTATE_STRUCT_VARRAY_UINT32(timerblock, ARMMPTimerState, num_cpu,
+                                     2, vmstate_timerblock, TimerBlock),
         VMSTATE_END_OF_LIST()
     }
 };
commit 845769fc6319d308a39a78734c6dc03fa93ff2c5
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Feb 28 18:23:13 2013 +0000

    arm: arm11mpcore, a9mpcore: CamelCased type names
    
    To conform with QEMU coding style.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 673bbd8..33b9e07 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -12,7 +12,7 @@
 
 /* A9MP private memory region.  */
 
-typedef struct a9mp_priv_state {
+typedef struct A9MPPrivState {
     SysBusDevice busdev;
     uint32_t scu_control;
     uint32_t scu_status;
@@ -23,12 +23,12 @@ typedef struct a9mp_priv_state {
     DeviceState *mptimer;
     DeviceState *gic;
     uint32_t num_irq;
-} a9mp_priv_state;
+} A9MPPrivState;
 
 static uint64_t a9_scu_read(void *opaque, hwaddr offset,
                             unsigned size)
 {
-    a9mp_priv_state *s = (a9mp_priv_state *)opaque;
+    A9MPPrivState *s = (A9MPPrivState *)opaque;
     switch (offset) {
     case 0x00: /* Control */
         return s->scu_control;
@@ -59,7 +59,7 @@ static uint64_t a9_scu_read(void *opaque, hwaddr offset,
 static void a9_scu_write(void *opaque, hwaddr offset,
                          uint64_t value, unsigned size)
 {
-    a9mp_priv_state *s = (a9mp_priv_state *)opaque;
+    A9MPPrivState *s = (A9MPPrivState *)opaque;
     uint32_t mask;
     uint32_t shift;
     switch (size) {
@@ -112,7 +112,7 @@ static const MemoryRegionOps a9_scu_ops = {
 
 static void a9mp_priv_reset(DeviceState *dev)
 {
-    a9mp_priv_state *s = FROM_SYSBUS(a9mp_priv_state, SYS_BUS_DEVICE(dev));
+    A9MPPrivState *s = FROM_SYSBUS(A9MPPrivState, SYS_BUS_DEVICE(dev));
     int i;
     s->scu_control = 0;
     for (i = 0; i < ARRAY_SIZE(s->old_timer_status); i++) {
@@ -122,13 +122,13 @@ static void a9mp_priv_reset(DeviceState *dev)
 
 static void a9mp_priv_set_irq(void *opaque, int irq, int level)
 {
-    a9mp_priv_state *s = (a9mp_priv_state *)opaque;
+    A9MPPrivState *s = (A9MPPrivState *)opaque;
     qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
 }
 
 static int a9mp_priv_init(SysBusDevice *dev)
 {
-    a9mp_priv_state *s = FROM_SYSBUS(a9mp_priv_state, dev);
+    A9MPPrivState *s = FROM_SYSBUS(A9MPPrivState, dev);
     SysBusDevice *busdev, *gicbusdev;
     int i;
 
@@ -196,22 +196,22 @@ static const VMStateDescription vmstate_a9mp_priv = {
     .version_id = 2,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT32(scu_control, a9mp_priv_state),
-        VMSTATE_UINT32_ARRAY(old_timer_status, a9mp_priv_state, 8),
-        VMSTATE_UINT32_V(scu_status, a9mp_priv_state, 2),
+        VMSTATE_UINT32(scu_control, A9MPPrivState),
+        VMSTATE_UINT32_ARRAY(old_timer_status, A9MPPrivState, 8),
+        VMSTATE_UINT32_V(scu_status, A9MPPrivState, 2),
         VMSTATE_END_OF_LIST()
     }
 };
 
 static Property a9mp_priv_properties[] = {
-    DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
+    DEFINE_PROP_UINT32("num-cpu", A9MPPrivState, num_cpu, 1),
     /* The Cortex-A9MP may have anything from 0 to 224 external interrupt
      * IRQ lines (with another 32 internal). We default to 64+32, which
      * is the number provided by the Cortex-A9MP test chip in the
      * Realview PBX-A9 and Versatile Express A9 development boards.
      * Other boards may differ and should set this property appropriately.
      */
-    DEFINE_PROP_UINT32("num-irq", a9mp_priv_state, num_irq, 96),
+    DEFINE_PROP_UINT32("num-irq", A9MPPrivState, num_irq, 96),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -229,7 +229,7 @@ static void a9mp_priv_class_init(ObjectClass *klass, void *data)
 static const TypeInfo a9mp_priv_info = {
     .name          = "a9mpcore_priv",
     .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(a9mp_priv_state),
+    .instance_size = sizeof(A9MPPrivState),
     .class_init    = a9mp_priv_class_init,
 };
 
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index 324e503..b900b35 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -12,7 +12,7 @@
 
 /* MPCore private memory region.  */
 
-typedef struct mpcore_priv_state {
+typedef struct ARM11MPCorePriveState {
     SysBusDevice busdev;
     uint32_t scu_control;
     int iomemtype;
@@ -23,14 +23,14 @@ typedef struct mpcore_priv_state {
     DeviceState *mptimer;
     DeviceState *gic;
     uint32_t num_irq;
-} mpcore_priv_state;
+} ARM11MPCorePriveState;
 
 /* Per-CPU private memory mapped IO.  */
 
 static uint64_t mpcore_scu_read(void *opaque, hwaddr offset,
                                 unsigned size)
 {
-    mpcore_priv_state *s = (mpcore_priv_state *)opaque;
+    ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque;
     int id;
     /* SCU */
     switch (offset) {
@@ -53,7 +53,7 @@ static uint64_t mpcore_scu_read(void *opaque, hwaddr offset,
 static void mpcore_scu_write(void *opaque, hwaddr offset,
                              uint64_t value, unsigned size)
 {
-    mpcore_priv_state *s = (mpcore_priv_state *)opaque;
+    ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque;
     /* SCU */
     switch (offset) {
     case 0: /* Control register.  */
@@ -76,11 +76,11 @@ static const MemoryRegionOps mpcore_scu_ops = {
 
 static void mpcore_priv_set_irq(void *opaque, int irq, int level)
 {
-    mpcore_priv_state *s = (mpcore_priv_state *)opaque;
+    ARM11MPCorePriveState *s = (ARM11MPCorePriveState *)opaque;
     qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
 }
 
-static void mpcore_priv_map_setup(mpcore_priv_state *s)
+static void mpcore_priv_map_setup(ARM11MPCorePriveState *s)
 {
     int i;
     SysBusDevice *gicbusdev = SYS_BUS_DEVICE(s->gic);
@@ -121,7 +121,7 @@ static void mpcore_priv_map_setup(mpcore_priv_state *s)
 
 static int mpcore_priv_init(SysBusDevice *dev)
 {
-    mpcore_priv_state *s = FROM_SYSBUS(mpcore_priv_state, dev);
+    ARM11MPCorePriveState *s = FROM_SYSBUS(ARM11MPCorePriveState, dev);
 
     s->gic = qdev_create(NULL, "arm_gic");
     qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
@@ -230,7 +230,7 @@ static const TypeInfo mpcore_rirq_info = {
 };
 
 static Property mpcore_priv_properties[] = {
-    DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
+    DEFINE_PROP_UINT32("num-cpu", ARM11MPCorePriveState, num_cpu, 1),
     /* The ARM11 MPCORE TRM says the on-chip controller may have
      * anything from 0 to 224 external interrupt IRQ lines (with another
      * 32 internal). We default to 32+32, which is the number provided by
@@ -239,7 +239,7 @@ static Property mpcore_priv_properties[] = {
      * appropriately. Some Linux kernels may not boot if the hardware
      * has more IRQ lines than the kernel expects.
      */
-    DEFINE_PROP_UINT32("num-irq", mpcore_priv_state, num_irq, 64),
+    DEFINE_PROP_UINT32("num-irq", ARM11MPCorePriveState, num_irq, 64),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -255,7 +255,7 @@ static void mpcore_priv_class_init(ObjectClass *klass, void *data)
 static const TypeInfo mpcore_priv_info = {
     .name          = "arm11mpcore_priv",
     .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(mpcore_priv_state),
+    .instance_size = sizeof(ARM11MPCorePriveState),
     .class_init    = mpcore_priv_class_init,
 };
 
commit c6205ddf6cff202ac0ce6621987cd3de8b57adee
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Feb 28 18:23:13 2013 +0000

    arm: mptimer: CamelCased type names
    
    Trivial find replace on type names "timerblock" and "arm_mptimer_state" to
    conform with QEMU coding style.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm_mptimer.c b/hw/arm_mptimer.c
index 32817d3..de0ef36 100644
--- a/hw/arm_mptimer.c
+++ b/hw/arm_mptimer.c
@@ -38,16 +38,16 @@ typedef struct {
     QEMUTimer *timer;
     qemu_irq irq;
     MemoryRegion iomem;
-} timerblock;
+} TimerBlock;
 
 typedef struct {
     SysBusDevice busdev;
     uint32_t num_cpu;
-    timerblock timerblock[MAX_CPUS * 2];
+    TimerBlock timerblock[MAX_CPUS * 2];
     MemoryRegion iomem[2];
-} arm_mptimer_state;
+} ARMMPTimerState;
 
-static inline int get_current_cpu(arm_mptimer_state *s)
+static inline int get_current_cpu(ARMMPTimerState *s)
 {
     CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env);
 
@@ -58,18 +58,18 @@ static inline int get_current_cpu(arm_mptimer_state *s)
     return cpu_single_cpu->cpu_index;
 }
 
-static inline void timerblock_update_irq(timerblock *tb)
+static inline void timerblock_update_irq(TimerBlock *tb)
 {
     qemu_set_irq(tb->irq, tb->status);
 }
 
 /* Return conversion factor from mpcore timer ticks to qemu timer ticks.  */
-static inline uint32_t timerblock_scale(timerblock *tb)
+static inline uint32_t timerblock_scale(TimerBlock *tb)
 {
     return (((tb->control >> 8) & 0xff) + 1) * 10;
 }
 
-static void timerblock_reload(timerblock *tb, int restart)
+static void timerblock_reload(TimerBlock *tb, int restart)
 {
     if (tb->count == 0) {
         return;
@@ -83,7 +83,7 @@ static void timerblock_reload(timerblock *tb, int restart)
 
 static void timerblock_tick(void *opaque)
 {
-    timerblock *tb = (timerblock *)opaque;
+    TimerBlock *tb = (TimerBlock *)opaque;
     tb->status = 1;
     if (tb->control & 2) {
         tb->count = tb->load;
@@ -97,7 +97,7 @@ static void timerblock_tick(void *opaque)
 static uint64_t timerblock_read(void *opaque, hwaddr addr,
                                 unsigned size)
 {
-    timerblock *tb = (timerblock *)opaque;
+    TimerBlock *tb = (TimerBlock *)opaque;
     int64_t val;
     switch (addr) {
     case 0: /* Load */
@@ -125,7 +125,7 @@ static uint64_t timerblock_read(void *opaque, hwaddr addr,
 static void timerblock_write(void *opaque, hwaddr addr,
                              uint64_t value, unsigned size)
 {
-    timerblock *tb = (timerblock *)opaque;
+    TimerBlock *tb = (TimerBlock *)opaque;
     int64_t old;
     switch (addr) {
     case 0: /* Load */
@@ -164,7 +164,7 @@ static void timerblock_write(void *opaque, hwaddr addr,
 static uint64_t arm_thistimer_read(void *opaque, hwaddr addr,
                                    unsigned size)
 {
-    arm_mptimer_state *s = (arm_mptimer_state *)opaque;
+    ARMMPTimerState *s = (ARMMPTimerState *)opaque;
     int id = get_current_cpu(s);
     return timerblock_read(&s->timerblock[id * 2], addr, size);
 }
@@ -172,7 +172,7 @@ static uint64_t arm_thistimer_read(void *opaque, hwaddr addr,
 static void arm_thistimer_write(void *opaque, hwaddr addr,
                                 uint64_t value, unsigned size)
 {
-    arm_mptimer_state *s = (arm_mptimer_state *)opaque;
+    ARMMPTimerState *s = (ARMMPTimerState *)opaque;
     int id = get_current_cpu(s);
     timerblock_write(&s->timerblock[id * 2], addr, value, size);
 }
@@ -180,7 +180,7 @@ static void arm_thistimer_write(void *opaque, hwaddr addr,
 static uint64_t arm_thiswdog_read(void *opaque, hwaddr addr,
                                   unsigned size)
 {
-    arm_mptimer_state *s = (arm_mptimer_state *)opaque;
+    ARMMPTimerState *s = (ARMMPTimerState *)opaque;
     int id = get_current_cpu(s);
     return timerblock_read(&s->timerblock[id * 2 + 1], addr, size);
 }
@@ -188,7 +188,7 @@ static uint64_t arm_thiswdog_read(void *opaque, hwaddr addr,
 static void arm_thiswdog_write(void *opaque, hwaddr addr,
                                uint64_t value, unsigned size)
 {
-    arm_mptimer_state *s = (arm_mptimer_state *)opaque;
+    ARMMPTimerState *s = (ARMMPTimerState *)opaque;
     int id = get_current_cpu(s);
     timerblock_write(&s->timerblock[id * 2 + 1], addr, value, size);
 }
@@ -223,7 +223,7 @@ static const MemoryRegionOps timerblock_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void timerblock_reset(timerblock *tb)
+static void timerblock_reset(TimerBlock *tb)
 {
     tb->count = 0;
     tb->load = 0;
@@ -237,8 +237,8 @@ static void timerblock_reset(timerblock *tb)
 
 static void arm_mptimer_reset(DeviceState *dev)
 {
-    arm_mptimer_state *s =
-        FROM_SYSBUS(arm_mptimer_state, SYS_BUS_DEVICE(dev));
+    ARMMPTimerState *s =
+        FROM_SYSBUS(ARMMPTimerState, SYS_BUS_DEVICE(dev));
     int i;
     /* We reset every timer in the array, not just the ones we're using,
      * because vmsave will look at every array element.
@@ -250,7 +250,7 @@ static void arm_mptimer_reset(DeviceState *dev)
 
 static int arm_mptimer_init(SysBusDevice *dev)
 {
-    arm_mptimer_state *s = FROM_SYSBUS(arm_mptimer_state, dev);
+    ARMMPTimerState *s = FROM_SYSBUS(ARMMPTimerState, dev);
     int i;
     if (s->num_cpu < 1 || s->num_cpu > MAX_CPUS) {
         hw_error("%s: num-cpu must be between 1 and %d\n", __func__, MAX_CPUS);
@@ -278,7 +278,7 @@ static int arm_mptimer_init(SysBusDevice *dev)
                           "arm_mptimer_wdog", 0x20);
     sysbus_init_mmio(dev, &s->iomem[1]);
     for (i = 0; i < (s->num_cpu * 2); i++) {
-        timerblock *tb = &s->timerblock[i];
+        TimerBlock *tb = &s->timerblock[i];
         tb->timer = qemu_new_timer_ns(vm_clock, timerblock_tick, tb);
         sysbus_init_irq(dev, &tb->irq);
         memory_region_init_io(&tb->iomem, &timerblock_ops, tb,
@@ -294,11 +294,11 @@ static const VMStateDescription vmstate_timerblock = {
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT32(count, timerblock),
-        VMSTATE_UINT32(load, timerblock),
-        VMSTATE_UINT32(control, timerblock),
-        VMSTATE_UINT32(status, timerblock),
-        VMSTATE_INT64(tick, timerblock),
+        VMSTATE_UINT32(count, TimerBlock),
+        VMSTATE_UINT32(load, TimerBlock),
+        VMSTATE_UINT32(control, TimerBlock),
+        VMSTATE_UINT32(status, TimerBlock),
+        VMSTATE_INT64(tick, TimerBlock),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -308,14 +308,14 @@ static const VMStateDescription vmstate_arm_mptimer = {
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
-        VMSTATE_STRUCT_ARRAY(timerblock, arm_mptimer_state, (MAX_CPUS * 2),
-                             1, vmstate_timerblock, timerblock),
+        VMSTATE_STRUCT_ARRAY(timerblock, ARMMPTimerState, (MAX_CPUS * 2),
+                             1, vmstate_timerblock, TimerBlock),
         VMSTATE_END_OF_LIST()
     }
 };
 
 static Property arm_mptimer_properties[] = {
-    DEFINE_PROP_UINT32("num-cpu", arm_mptimer_state, num_cpu, 0),
+    DEFINE_PROP_UINT32("num-cpu", ARMMPTimerState, num_cpu, 0),
     DEFINE_PROP_END_OF_LIST()
 };
 
@@ -334,7 +334,7 @@ static void arm_mptimer_class_init(ObjectClass *klass, void *data)
 static const TypeInfo arm_mptimer_info = {
     .name          = "arm_mptimer",
     .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(arm_mptimer_state),
+    .instance_size = sizeof(ARMMPTimerState),
     .class_init    = arm_mptimer_class_init,
 };
 
commit 1be97bf22447088adebf23b1ca508d4bb00f853c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Feb 28 18:23:12 2013 +0000

    hw/pflash_cfi01: Treat read in unknown command state as read
    
    The code for handling the default "unknown command state" case in
    pflash_read in pflash_cfi01.c comments "reset state & treat it as
    a read". However the code doesn't actually do this. Moving the
    default case to the top of the switch so it can fall through into
    the read case brings this file into line with pflash_cfi02 and
    makes the code behave as the comments suggest.
    
    The pflash_cfi01 code has always had this bug -- it was presumably
    introduced when the original author copied the cfi02 code and
    rearranged the order of the switch statement without noticing
    that the default case relied on the fall-through.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Tested-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 1358777318-7579-3-git-send-email-peter.maydell at linaro.org

diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index c79e599..123b006 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -122,6 +122,12 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
             __func__, offset, pfl->cmd, width);
 #endif
     switch (pfl->cmd) {
+    default:
+        /* This should never happen : reset state & treat it as a read */
+        DPRINTF("%s: unknown command state: %x\n", __func__, pfl->cmd);
+        pfl->wcycle = 0;
+        pfl->cmd = 0;
+        /* fall through to read code */
     case 0x00:
         /* Flash area read */
         p = pfl->storage;
@@ -197,11 +203,6 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
         else
             ret = pfl->cfi_table[boff];
         break;
-    default:
-        /* This should never happen : reset state & treat it as a read */
-        DPRINTF("%s: unknown command state: %x\n", __func__, pfl->cmd);
-        pfl->wcycle = 0;
-        pfl->cmd = 0;
     }
     return ret;
 }
commit 6e392787c85809671033ec419d8e8ecf684d55da
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Feb 28 18:23:12 2013 +0000

    hw/pflash_cfi01: Make read after byte-write or erase return status
    
    The Intel flash command set requires that a read operation after
    doing a 'single byte write' command returns the status register;
    add this case to pflash_read() so we return the correct information.
    Similarly, the case for the 0x28 flavour of block erase was missing.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Tested-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 1358777318-7579-2-git-send-email-peter.maydell at linaro.org

diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index 9e6ff52..c79e599 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -162,7 +162,10 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
         }
 
         break;
+    case 0x10: /* Single byte program */
     case 0x20: /* Block erase */
+    case 0x28: /* Block erase */
+    case 0x40: /* single byte program */
     case 0x50: /* Clear status register */
     case 0x60: /* Block /un)lock */
     case 0x70: /* Status Register */
commit 5c78d6a84b504e831adc8f1917cde0c79061dff0
Author: Antoine Mathys <barsamin at gmail.com>
Date:   Thu Feb 28 18:23:12 2013 +0000

    hw/ds1338: Fix conversion between 12 hours and 24 hours modes.
    
    The proper mapping between 24 hours and 12 hours modes is:
    0       12 AM
    1-11    1-11 AM
    12      12 PM
    13-23   1-11 PM
    Fix code accordingly.
    
    Signed-off-by: Antoine Mathys <barsamin at gmail.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/ds1338.c b/hw/ds1338.c
index 6f70538..1da0f96 100644
--- a/hw/ds1338.c
+++ b/hw/ds1338.c
@@ -59,8 +59,8 @@ static void capture_current_time(DS1338State *s)
     s->nvram[1] = to_bcd(now.tm_min);
     if (s->nvram[2] & HOURS_12) {
         int tmp = now.tm_hour;
-        if (tmp == 0) {
-            tmp = 24;
+        if (tmp % 12 == 0) {
+            tmp += 12;
         }
         if (tmp <= 12) {
             s->nvram[2] = HOURS_12 | to_bcd(tmp);
@@ -145,8 +145,8 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data)
                 if (data & HOURS_PM) {
                     tmp += 12;
                 }
-                if (tmp == 24) {
-                    tmp = 0;
+                if (tmp % 12 == 0) {
+                    tmp -= 12;
                 }
                 now.tm_hour = tmp;
             } else {
commit 5c75fb10029c5fd1e705a6ef5d698fbea06c7a33
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Feb 28 09:18:56 2013 +0100

    update seabios to 1.7.2.1
    
    Alex Williamson (3):
          seabios q35: Enable all PIRQn IRQs at startup
          seabios q35: Add new PCI slot to irq routing function
          seabios: Add a dummy PCI slot to irq mapping function
    
    Avik Sil (1):
          USB-EHCI: Fix null pointer assignment
    
    Kevin O'Connor (4):
          Update tools/acpi_extract.py to handle iasl 20130117 release.
          Fix Makefile - don't reference "out/" directly, instead use "$(OUT)".
          build: Don't require $(OUT) to be a sub-directory of the main
    directory.
          Verify CC is valid during build tests.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index ab5dd9d..ec9eeb1 100644
Binary files a/pc-bios/bios.bin and b/pc-bios/bios.bin differ
diff --git a/roms/seabios b/roms/seabios
index 4bd8aeb..88cb66e 160000
--- a/roms/seabios
+++ b/roms/seabios
@@ -1 +1 @@
-Subproject commit 4bd8aebf3534e10d9aa21e820903f2cf9120708c
+Subproject commit 88cb66ea542906ffff8a80ef397b9e3adbb33116
commit 554f1997f0328bc259454239db64b20b3376d9a6
Author: Gal Hammer <ghammer at redhat.com>
Date:   Wed Feb 27 15:15:31 2013 +0200

    Set virtio-serial device to have a default of 2 MSI vectors.
    
    The virtio-serial device is expected to use 2 MSI vectors, one for
    control queue and a second shared for all queues.
    
    Signed-off-by: Gal Hammer <ghammer at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pc.h b/hw/pc.h
index da1b102..f2c1b1c 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -216,6 +216,11 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
             .driver   = "virtio-blk-pci",\
             .property = "discard_granularity",\
             .value    = stringify(0),\
+	},{\
+            .driver   = "virtio-serial-pci",\
+            .property = "vectors",\
+            /* DEV_NVECTORS_UNSPECIFIED as a uint32_t string */\
+            .value    = stringify(0xFFFFFFFF),\
 	}
 
 #endif
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index a869f53..ba56ab2 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -975,6 +975,9 @@ static int virtio_serial_init_pci(PCIDevice *pci_dev)
     if (!vdev) {
         return -1;
     }
+
+    /* backwards-compatibility with machines that were created with
+       DEV_NVECTORS_UNSPECIFIED */
     vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED
                                         ? proxy->serial.max_virtserial_ports + 1
                                         : proxy->nvectors;
@@ -1155,7 +1158,7 @@ static const TypeInfo virtio_net_info = {
 
 static Property virtio_serial_properties[] = {
     DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
-    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEV_NVECTORS_UNSPECIFIED),
+    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
     DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
     DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
     DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, serial.max_virtserial_ports, 31),
commit 0e98b436eceb9d31caad898f4983a369c76524e0
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Wed Feb 20 02:51:24 2013 +0100

    ICH9 LPC: Reset Control Register, basic implementation
    
    This commit does the same for the ICH9 LPC as commit 1ec4ba74 for the
    PIIX3. For the present we're ignoring the Full Reset (FULL_RST) and System
    Reset (SYS_RST) bits; the guest can read them back but that's it.
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/ich9.h b/hw/ich9.h
index d4509bb..dbc4495 100644
--- a/hw/ich9.h
+++ b/hw/ich9.h
@@ -49,6 +49,15 @@ typedef struct ICH9LPCState {
     /* 10.1 Chipset Configuration registers(Memory Space)
      which is pointed by RCBA */
     uint8_t chip_config[ICH9_CC_SIZE];
+
+    /*
+     * 13.7.5 RST_CNT---Reset Control Register (LPC I/F---D31:F0)
+     *
+     * register contents and IO memory region
+     */
+    uint8_t rst_cnt;
+    MemoryRegion rst_cnt_mem;
+
     /* isa bus */
     ISABus *isa_bus;
     MemoryRegion rbca_mem;
@@ -103,6 +112,8 @@ typedef struct ICH9LPCState {
 
 #define ICH9_D2P_A2_REVISION                    0x92
 
+/* D31:F0 LPC Processor Interface */
+#define ICH9_RST_CNT_IOPORT                     0xCF9
 
 /* D31:F1 LPC controller */
 #define ICH9_A2_LPC                             "ICH9 A2 LPC"
diff --git a/hw/lpc_ich9.c b/hw/lpc_ich9.c
index e25689b..eceb052 100644
--- a/hw/lpc_ich9.c
+++ b/hw/lpc_ich9.c
@@ -466,6 +466,7 @@ static void ich9_lpc_reset(DeviceState *qdev)
     ich9_lpc_rcba_update(lpc, rbca_old);
 
     lpc->sci_level = 0;
+    lpc->rst_cnt = 0;
 }
 
 static const MemoryRegionOps rbca_mmio_ops = {
@@ -498,6 +499,32 @@ static void ich9_lpc_machine_ready(Notifier *n, void *opaque)
     }
 }
 
+/* reset control */
+static void ich9_rst_cnt_write(void *opaque, hwaddr addr, uint64_t val,
+                               unsigned len)
+{
+    ICH9LPCState *lpc = opaque;
+
+    if (val & 4) {
+        qemu_system_reset_request();
+        return;
+    }
+    lpc->rst_cnt = val & 0xA; /* keep FULL_RST (bit 3) and SYS_RST (bit 1) */
+}
+
+static uint64_t ich9_rst_cnt_read(void *opaque, hwaddr addr, unsigned len)
+{
+    ICH9LPCState *lpc = opaque;
+
+    return lpc->rst_cnt;
+}
+
+static const MemoryRegionOps ich9_rst_cnt_ops = {
+    .read = ich9_rst_cnt_read,
+    .write = ich9_rst_cnt_write,
+    .endianness = DEVICE_LITTLE_ENDIAN
+};
+
 static int ich9_lpc_initfn(PCIDevice *d)
 {
     ICH9LPCState *lpc = ICH9_LPC_DEVICE(d);
@@ -519,9 +546,32 @@ static int ich9_lpc_initfn(PCIDevice *d)
     lpc->machine_ready.notify = ich9_lpc_machine_ready;
     qemu_add_machine_init_done_notifier(&lpc->machine_ready);
 
+    memory_region_init_io(&lpc->rst_cnt_mem, &ich9_rst_cnt_ops, lpc,
+                          "lpc-reset-control", 1);
+    memory_region_add_subregion_overlap(pci_address_space_io(d),
+                                        ICH9_RST_CNT_IOPORT, &lpc->rst_cnt_mem,
+                                        1);
+
     return 0;
 }
 
+static bool ich9_rst_cnt_needed(void *opaque)
+{
+    ICH9LPCState *lpc = opaque;
+
+    return (lpc->rst_cnt != 0);
+}
+
+static const VMStateDescription vmstate_ich9_rst_cnt = {
+    .name = "ICH9LPC/rst_cnt",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(rst_cnt, ICH9LPCState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static const VMStateDescription vmstate_ich9_lpc = {
     .name = "ICH9LPC",
     .version_id = 1,
@@ -535,6 +585,13 @@ static const VMStateDescription vmstate_ich9_lpc = {
         VMSTATE_UINT8_ARRAY(chip_config, ICH9LPCState, ICH9_CC_SIZE),
         VMSTATE_UINT32(sci_level, ICH9LPCState),
         VMSTATE_END_OF_LIST()
+    },
+    .subsections = (VMStateSubsection[]) {
+        {
+            .vmsd = &vmstate_ich9_rst_cnt,
+            .needed = ich9_rst_cnt_needed
+        },
+        { 0 }
     }
 };
 
commit 7feb640cf32d86f91f5a624136345eb6a63eab42
Author: Alexey Korolev <akorolex at gmail.com>
Date:   Fri Feb 22 16:58:44 2013 +1300

    Fix guest OS hang when 64bit PCI bar present
    
    This patch addresses the issue fully described here:
    http://lists.nongnu.org/archive/html/qemu-devel/2013-02/msg01804.html
    
    Linux kernels prior to 2.6.36 do not disable the PCI device during
    enumeration process. Since lower and higher parts of a 64bit BAR
    are programmed separately this leads to qemu receiving a request to occupy
    a completely wrong address region for a short period of time.
    We have found that the boot process screws up completely if kvm-apic range
    is overlapped even for a short period of time (it is fine for other
    regions though).
    
    This patch raises the priority of the kvm-apic memory region, so it is
    never pushed out by PCI devices. The patch is quite safe as it does not
    touch memory manager.
    
    Signed-off-by: Alexey Korolev <akorolex at gmail.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/sysbus.c b/hw/sysbus.c
index 6d9d1df..50c7232 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -48,7 +48,8 @@ void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
     }
 }
 
-void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr)
+static void sysbus_mmio_map_common(SysBusDevice *dev, int n, hwaddr addr,
+                                   bool may_overlap, unsigned priority)
 {
     assert(n >= 0 && n < dev->num_mmio);
 
@@ -61,11 +62,29 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr)
         memory_region_del_subregion(get_system_memory(), dev->mmio[n].memory);
     }
     dev->mmio[n].addr = addr;
-    memory_region_add_subregion(get_system_memory(),
-                                addr,
-                                dev->mmio[n].memory);
+    if (may_overlap) {
+        memory_region_add_subregion_overlap(get_system_memory(),
+                                            addr,
+                                            dev->mmio[n].memory,
+                                            priority);
+    }
+    else {
+        memory_region_add_subregion(get_system_memory(),
+                                    addr,
+                                    dev->mmio[n].memory);
+    }
 }
 
+void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr)
+{
+    sysbus_mmio_map_common(dev, n, addr, false, 0);
+}
+
+void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr,
+                             unsigned priority)
+{
+    sysbus_mmio_map_common(dev, n, addr, true, priority);
+}
 
 /* Request an IRQ source.  The actual IRQ object may be populated later.  */
 void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p)
diff --git a/hw/sysbus.h b/hw/sysbus.h
index a7fcded..2100bd7 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -56,6 +56,8 @@ void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size);
 
 void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq);
 void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr);
+void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr,
+                             unsigned priority);
 void sysbus_add_memory(SysBusDevice *dev, hwaddr addr,
                        MemoryRegion *mem);
 void sysbus_add_memory_overlap(SysBusDevice *dev, hwaddr addr,
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 5582e5f..8fb736a 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2088,7 +2088,8 @@ static void x86_cpu_apic_init(X86CPU *cpu, Error **errp)
         /* NOTE: the APIC is directly connected to the CPU - it is not
            on the global memory bus. */
         /* XXX: what if the base changes? */
-        sysbus_mmio_map(SYS_BUS_DEVICE(env->apic_state), 0, MSI_ADDR_BASE);
+        sysbus_mmio_map_overlap(SYS_BUS_DEVICE(env->apic_state), 0,
+                                MSI_ADDR_BASE, 0x1000);
         apic_mapped = 1;
     }
 }
commit 2af234e61d59f39ae16ba882271e7c4fef2c41c1
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Thu Feb 14 19:11:27 2013 +0200

    e1000: unbreak the guest network migration to 1.3
    
    QEMU 1.3 does not emulate the link auto negotiation, so if migrate to a
    1.3 machine during link auto negotiation, the guest link will be set to down.
    Fix this by just disabling auto negotiation for 1.3 and older.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/e1000.c b/hw/e1000.c
index d6fe815..45cc330 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -131,6 +131,11 @@ typedef struct E1000State_st {
     } eecd_state;
 
     QEMUTimer *autoneg_timer;
+
+/* Compatibility flags for migration to/from qemu 1.3.0 and older */
+#define E1000_FLAG_AUTONEG_BIT 0
+#define E1000_FLAG_AUTONEG (1 << E1000_FLAG_AUTONEG_BIT)
+    uint32_t compat_flags;
 } E1000State;
 
 #define	defreg(x)	x = (E1000_##x>>2)
@@ -165,6 +170,14 @@ e1000_link_up(E1000State *s)
 static void
 set_phy_ctrl(E1000State *s, int index, uint16_t val)
 {
+    /*
+     * QEMU 1.3 does not support link auto-negotiation emulation, so if we
+     * migrate during auto negotiation, after migration the link will be
+     * down.
+     */
+    if (!(s->compat_flags & E1000_FLAG_AUTONEG)) {
+        return;
+    }
     if ((val & MII_CR_AUTO_NEG_EN) && (val & MII_CR_RESTART_AUTO_NEG)) {
         e1000_link_down(s);
         s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE;
@@ -1120,6 +1133,11 @@ static void e1000_pre_save(void *opaque)
 {
     E1000State *s = opaque;
     NetClientState *nc = qemu_get_queue(s->nic);
+
+    if (!(s->compat_flags & E1000_FLAG_AUTONEG)) {
+        return;
+    }
+
     /*
      * If link is down and auto-negotiation is ongoing, complete
      * auto-negotiation immediately.  This allows is to look at
@@ -1141,6 +1159,11 @@ static int e1000_post_load(void *opaque, int version_id)
      * to link status bit in mac_reg[STATUS].
      * Alternatively, restart link negotiation if it was in progress. */
     nc->link_down = (s->mac_reg[STATUS] & E1000_STATUS_LU) == 0;
+
+    if (!(s->compat_flags & E1000_FLAG_AUTONEG)) {
+        return 0;
+    }
+
     if (s->phy_reg[PHY_CTRL] & MII_CR_AUTO_NEG_EN &&
         s->phy_reg[PHY_CTRL] & MII_CR_RESTART_AUTO_NEG &&
         !(s->phy_reg[PHY_STATUS] & MII_SR_AUTONEG_COMPLETE)) {
@@ -1343,6 +1366,8 @@ static void qdev_e1000_reset(DeviceState *dev)
 
 static Property e1000_properties[] = {
     DEFINE_NIC_PROPERTIES(E1000State, conf),
+    DEFINE_PROP_BIT("autonegotiation", E1000State,
+                    compat_flags, E1000_FLAG_AUTONEG_BIT, true),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index aa9cc81..a305e1f 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -330,6 +330,10 @@ static QEMUMachine pc_i440fx_machine_v1_4 = {
             .driver   = "virtio-net-pci", \
             .property = "mq", \
             .value    = "off", \
+        }, {\
+            .driver   = "e1000",\
+            .property = "autonegotiation",\
+            .value    = "off",\
         }
 
 static QEMUMachine pc_machine_v1_3 = {
commit af347aa5a521555f5342e67993eb717d4f542ba8
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Feb 22 18:31:51 2013 +0100

    qmp: netdev_add is like -netdev, not -net, fix documentation
    
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Laszlo Ersek <lersek at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/qmp-commands.hx b/qmp-commands.hx
index 799adea..95022e2 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -822,7 +822,7 @@ Example:
 -> { "execute": "netdev_add", "arguments": { "type": "user", "id": "netdev1" } }
 <- { "return": {} }
 
-Note: The supported device options are the same ones supported by the '-net'
+Note: The supported device options are the same ones supported by the '-netdev'
       command-line argument, which are listed in the '-help' output or QEMU's
       manual
 
commit 40e8c26d7b7e260cc3566c6b68cee969e816970e
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Tue Feb 26 11:07:16 2013 +0100

    doc: document -netdev hubport
    
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index cef7708..69c707d 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1169,7 +1169,7 @@ ETEXI
     {
         .name       = "netdev_add",
         .args_type  = "netdev:O",
-        .params     = "[user|tap|socket],id=str[,prop=value][,...]",
+        .params     = "[user|tap|socket|hubport],id=str[,prop=value][,...]",
         .help       = "add host network device",
         .mhandler.cmd = hmp_netdev_add,
     },
diff --git a/qemu-options.hx b/qemu-options.hx
index 797d992..863069f 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1408,7 +1408,8 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
 #ifdef CONFIG_VDE
     "vde|"
 #endif
-    "socket],id=str[,option][,option][,...]\n", QEMU_ARCH_ALL)
+    "socket|"
+    "hubport],id=str[,option][,option][,...]\n", QEMU_ARCH_ALL)
 STEXI
 @item -net nic[,vlan=@var{n}][,macaddr=@var{mac}][,model=@var{type}] [,name=@var{name}][,addr=@var{addr}][,vectors=@var{v}]
 @findex -net
@@ -1730,6 +1731,14 @@ vde_switch -F -sock /tmp/myswitch
 qemu-system-i386 linux.img -net nic -net vde,sock=/tmp/myswitch
 @end example
 
+ at item -netdev hubport,id=@var{id},hubid=@var{hubid}
+
+Create a hub port on QEMU "vlan" @var{hubid}.
+
+The hubport netdev lets you connect a NIC to a QEMU "vlan" instead of a single
+netdev.  @code{-net} and @code{-device} with parameter @option{vlan} create the
+required hub automatically.
+
 @item -net dump[,vlan=@var{n}][,file=@var{file}][,len=@var{len}]
 Dump network traffic on VLAN @var{n} to file @var{file} (@file{qemu-vlan0.pcap} by default).
 At most @var{len} bytes (64k by default) per packet are stored. The file format is
commit f6b26cf257232e5854c0e5c98a8685c625bf986e
Author: Jason Wang <jasowang at redhat.com>
Date:   Fri Feb 22 23:15:06 2013 +0800

    net: reduce the unnecessary memory allocation of multiqueue
    
    Edivaldo reports a problem that the array of NetClientState in NICState is too
    large - MAX_QUEUE_NUM(1024) which will wastes memory even if multiqueue is not
    used.
    
    Instead of static arrays, solving this issue by allocating the queues on demand
    for both the NetClientState array in NICState and VirtIONetQueue array in
    VirtIONet.
    
    Tested by myself, with single virtio-net-pci device. The memory allocation is
    almost the same as when multiqueue is not merged.
    
    Cc: Edivaldo de Araujo Pereira <edivaldoapereira at yahoo.com.br>
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 573c669..bb2c26c 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -44,7 +44,7 @@ typedef struct VirtIONet
     VirtIODevice vdev;
     uint8_t mac[ETH_ALEN];
     uint16_t status;
-    VirtIONetQueue vqs[MAX_QUEUE_NUM];
+    VirtIONetQueue *vqs;
     VirtQueue *ctrl_vq;
     NICState *nic;
     uint32_t tx_timeout;
@@ -1326,8 +1326,9 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
     n->vdev.set_status = virtio_net_set_status;
     n->vdev.guest_notifier_mask = virtio_net_guest_notifier_mask;
     n->vdev.guest_notifier_pending = virtio_net_guest_notifier_pending;
+    n->max_queues = MAX(conf->queues, 1);
+    n->vqs = g_malloc0(sizeof(VirtIONetQueue) * n->max_queues);
     n->vqs[0].rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
-    n->max_queues = conf->queues;
     n->curr_queues = 1;
     n->vqs[0].n = n;
     n->tx_timeout = net->txtimer;
@@ -1412,6 +1413,7 @@ void virtio_net_exit(VirtIODevice *vdev)
         }
     }
 
+    g_free(n->vqs);
     qemu_del_nic(n->nic);
     virtio_cleanup(&n->vdev);
 }
diff --git a/include/net/net.h b/include/net/net.h
index 43a045e..cb049a1 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -72,7 +72,7 @@ struct NetClientState {
 };
 
 typedef struct NICState {
-    NetClientState ncs[MAX_QUEUE_NUM];
+    NetClientState *ncs;
     NICConf *conf;
     void *opaque;
     bool peer_deleted;
diff --git a/net/net.c b/net/net.c
index a66aa02..f3d67f8 100644
--- a/net/net.c
+++ b/net/net.c
@@ -235,23 +235,20 @@ NICState *qemu_new_nic(NetClientInfo *info,
                        const char *name,
                        void *opaque)
 {
-    NetClientState *nc;
     NetClientState **peers = conf->peers.ncs;
     NICState *nic;
-    int i;
+    int i, queues = MAX(1, conf->queues);
 
     assert(info->type == NET_CLIENT_OPTIONS_KIND_NIC);
     assert(info->size >= sizeof(NICState));
 
-    nc = qemu_new_net_client(info, peers[0], model, name);
-    nc->queue_index = 0;
-
-    nic = qemu_get_nic(nc);
+    nic = g_malloc0(info->size + sizeof(NetClientState) * queues);
+    nic->ncs = (void *)nic + info->size;
     nic->conf = conf;
     nic->opaque = opaque;
 
-    for (i = 1; i < conf->queues; i++) {
-        qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, nc->name,
+    for (i = 0; i < queues; i++) {
+        qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, name,
                               NULL);
         nic->ncs[i].queue_index = i;
     }
@@ -261,7 +258,7 @@ NICState *qemu_new_nic(NetClientInfo *info,
 
 NetClientState *qemu_get_subqueue(NICState *nic, int queue_index)
 {
-    return &nic->ncs[queue_index];
+    return nic->ncs + queue_index;
 }
 
 NetClientState *qemu_get_queue(NICState *nic)
@@ -273,7 +270,7 @@ NICState *qemu_get_nic(NetClientState *nc)
 {
     NetClientState *nc0 = nc - nc->queue_index;
 
-    return DO_UPCAST(NICState, ncs[0], nc0);
+    return (NICState *)((void *)nc0 - nc->info->size);
 }
 
 void *qemu_get_nic_opaque(NetClientState *nc)
@@ -368,6 +365,8 @@ void qemu_del_nic(NICState *nic)
         qemu_cleanup_net_client(nc);
         qemu_free_net_client(nc);
     }
+
+    g_free(nic);
 }
 
 void qemu_foreach_nic(qemu_nic_foreach func, void *opaque)
commit d26e445c80fddcc7483b83f3115e5067fef28fe6
Author: Peter Lieven <pl at dlhnet.de>
Date:   Mon Feb 25 10:17:08 2013 +0100

    tap: set IFF_ONE_QUEUE per default
    
    historically the kernel queues packets two times. once
    at the device and second in qdisc. this is believed to cause
    interface stalls if one of these queues overruns.
    
    setting IFF_ONE_QUEUE is the default in kernels >= 3.8. the
    flag is ignored since then. see kernel commit
    5d097109257c03a71845729f8db6b5770c4bbedc
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Acked-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/net/tap-linux.c b/net/tap-linux.c
index a953189..36c09e2 100644
--- a/net/tap-linux.c
+++ b/net/tap-linux.c
@@ -42,6 +42,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
     struct ifreq ifr;
     int fd, ret;
     int len = sizeof(struct virtio_net_hdr);
+    unsigned int features;
 
     TFR(fd = open(PATH_NET_TUN, O_RDWR));
     if (fd < 0) {
@@ -51,9 +52,12 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
     memset(&ifr, 0, sizeof(ifr));
     ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
 
-    if (*vnet_hdr) {
-        unsigned int features;
+    if (ioctl(fd, TUNGETFEATURES, &features) == 0 &&
+        features & IFF_ONE_QUEUE) {
+        ifr.ifr_flags |= IFF_ONE_QUEUE;
+    }
 
+    if (*vnet_hdr) {
         if (ioctl(fd, TUNGETFEATURES, &features) == 0 &&
             features & IFF_VNET_HDR) {
             *vnet_hdr = 1;
@@ -78,8 +82,6 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
     }
 
     if (mq_required) {
-        unsigned int features;
-
         if ((ioctl(fd, TUNGETFEATURES, &features) != 0) ||
             !(features & IFF_MULTI_QUEUE)) {
             error_report("multiqueue required, but no kernel "
diff --git a/net/tap-linux.h b/net/tap-linux.h
index 65087e1..1cf35d4 100644
--- a/net/tap-linux.h
+++ b/net/tap-linux.h
@@ -34,10 +34,11 @@
 #endif
 
 /* TUNSETIFF ifr flags */
-#define IFF_TAP		0x0002
-#define IFF_NO_PI	0x1000
-#define IFF_VNET_HDR	0x4000
-#define IFF_MULTI_QUEUE 0x0100
+#define IFF_TAP          0x0002
+#define IFF_NO_PI        0x1000
+#define IFF_ONE_QUEUE    0x2000
+#define IFF_VNET_HDR     0x4000
+#define IFF_MULTI_QUEUE  0x0100
 #define IFF_ATTACH_QUEUE 0x0200
 #define IFF_DETACH_QUEUE 0x0400
 
commit ce675a7579fea498397c5d2da3c5367671e9f02a
Author: Jason Wang <jasowang at redhat.com>
Date:   Thu Feb 21 11:05:56 2013 +0800

    tap: forbid creating multiqueue tap when hub is used
    
    Obviously, hub does not support multiqueue tap. So this patch forbids creating
    multiple queue tap when hub is used to prevent the crash when command line such
    as "-net tap,queues=2" is used.
    
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/net/tap.c b/net/tap.c
index 48c254e..daab350 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -693,6 +693,13 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
     queues = tap->has_queues ? tap->queues : 1;
     vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL;
 
+    /* QEMU vlans does not support multiqueue tap, in this case peer is set.
+     * For -netdev, peer is always NULL. */
+    if (peer && (tap->has_queues || tap->has_fds || tap->has_vhostfds)) {
+        error_report("Multiqueue tap cannnot be used with QEMU vlans");
+        return -1;
+    }
+
     if (tap->has_fd) {
         if (tap->has_ifname || tap->has_script || tap->has_downscript ||
             tap->has_vnet_hdr || tap->has_helper || tap->has_queues ||
commit 7d91ddd25e3a4e5008a2ac16127d51a34fd56bf1
Author: Luigi Rizzo <rizzo at iet.unipi.it>
Date:   Tue Feb 5 18:29:09 2013 +0100

    net: fix unbounded NetQueue
    
    In the current implementation of qemu, running without a network
    backend will cause the queue to grow unbounded when the guest is
    transmitting traffic.
    
    This patch fixes the problem by implementing bounded size NetQueue,
    used with an arbitrary limit of 10000 packets, and dropping packets
    when the queue is full _and_ the sender does not pass a callback.
    
    The second condition makes sure that we never drop packets that
    contains a callback (which would be tricky, because the producer
    expects the callback to be run when all previous packets have been
    consumed; so we cannot run it when the packet is dropped).
    
    If documentation is correct, producers that submit a callback should
    stop sending when their packet is queued, so there is no real risk
    that the queue exceeds the max size by large values.
    
    Signed-off-by: Luigi Rizzo <rizzo at iet.unipi.it>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/net/queue.c b/net/queue.c
index 6eaf5b6..859d02a 100644
--- a/net/queue.c
+++ b/net/queue.c
@@ -50,6 +50,8 @@ struct NetPacket {
 
 struct NetQueue {
     void *opaque;
+    uint32_t nq_maxlen;
+    uint32_t nq_count;
 
     QTAILQ_HEAD(packets, NetPacket) packets;
 
@@ -63,6 +65,8 @@ NetQueue *qemu_new_net_queue(void *opaque)
     queue = g_malloc0(sizeof(NetQueue));
 
     queue->opaque = opaque;
+    queue->nq_maxlen = 10000;
+    queue->nq_count = 0;
 
     QTAILQ_INIT(&queue->packets);
 
@@ -92,6 +96,9 @@ static void qemu_net_queue_append(NetQueue *queue,
 {
     NetPacket *packet;
 
+    if (queue->nq_count >= queue->nq_maxlen && !sent_cb) {
+        return; /* drop if queue full and no callback */
+    }
     packet = g_malloc(sizeof(NetPacket) + size);
     packet->sender = sender;
     packet->flags = flags;
@@ -99,6 +106,7 @@ static void qemu_net_queue_append(NetQueue *queue,
     packet->sent_cb = sent_cb;
     memcpy(packet->data, buf, size);
 
+    queue->nq_count++;
     QTAILQ_INSERT_TAIL(&queue->packets, packet, entry);
 }
 
@@ -113,6 +121,9 @@ static void qemu_net_queue_append_iov(NetQueue *queue,
     size_t max_len = 0;
     int i;
 
+    if (queue->nq_count >= queue->nq_maxlen && !sent_cb) {
+        return; /* drop if queue full and no callback */
+    }
     for (i = 0; i < iovcnt; i++) {
         max_len += iov[i].iov_len;
     }
@@ -130,6 +141,7 @@ static void qemu_net_queue_append_iov(NetQueue *queue,
         packet->size += len;
     }
 
+    queue->nq_count++;
     QTAILQ_INSERT_TAIL(&queue->packets, packet, entry);
 }
 
@@ -220,6 +232,7 @@ void qemu_net_queue_purge(NetQueue *queue, NetClientState *from)
     QTAILQ_FOREACH_SAFE(packet, &queue->packets, entry, next) {
         if (packet->sender == from) {
             QTAILQ_REMOVE(&queue->packets, packet, entry);
+            queue->nq_count--;
             g_free(packet);
         }
     }
@@ -233,6 +246,7 @@ bool qemu_net_queue_flush(NetQueue *queue)
 
         packet = QTAILQ_FIRST(&queue->packets);
         QTAILQ_REMOVE(&queue->packets, packet, entry);
+        queue->nq_count--;
 
         ret = qemu_net_queue_deliver(queue,
                                      packet->sender,
@@ -240,6 +254,7 @@ bool qemu_net_queue_flush(NetQueue *queue)
                                      packet->data,
                                      packet->size);
         if (ret == 0) {
+            queue->nq_count++;
             QTAILQ_INSERT_HEAD(&queue->packets, packet, entry);
             return false;
         }
commit 199ee608f0d08510b5c6c37f31a7fbff211d63c4
Author: Luigi Rizzo <rizzo at iet.unipi.it>
Date:   Tue Feb 5 17:53:31 2013 +0100

    net: fix qemu_flush_queued_packets() in presence of a hub
    
    When frontend and backend are connected through a hub as below
    (showing only one direction), and the frontend (or in general, all
    output ports of the hub) cannot accept more traffic, the backend
    queues packets in queue-A.
    
    When the frontend (or in general, one output port) becomes ready again,
    quemu tries to flush packets from queue-B, which is unfortunately empty.
    
      e1000.0 <--[queue B]-- hub0port0(hub)hub0port1 <--[queue A]-- tap.0
    
    To fix this i propose to introduce a new function net_hub_flush()
    which is called when trying to flush a queue connected to a hub.
    
    Signed-off-by: Luigi Rizzo <rizzo at iet.unipi.it>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/net/hub.c b/net/hub.c
index a24c9d1..df32074 100644
--- a/net/hub.c
+++ b/net/hub.c
@@ -338,3 +338,17 @@ void net_hub_check_clients(void)
         }
     }
 }
+
+bool net_hub_flush(NetClientState *nc)
+{
+    NetHubPort *port;
+    NetHubPort *source_port = DO_UPCAST(NetHubPort, nc, nc);
+    int ret = 0;
+
+    QLIST_FOREACH(port, &source_port->hub->ports, next) {
+        if (port != source_port) {
+            ret += qemu_net_queue_flush(port->nc.send_queue);
+        }
+    }
+    return ret ? true : false;
+}
diff --git a/net/hub.h b/net/hub.h
index 583ada8..a625eff 100644
--- a/net/hub.h
+++ b/net/hub.h
@@ -21,5 +21,6 @@ NetClientState *net_hub_add_port(int hub_id, const char *name);
 NetClientState *net_hub_find_client_by_name(int hub_id, const char *name);
 void net_hub_info(Monitor *mon);
 void net_hub_check_clients(void);
+bool net_hub_flush(NetClientState *nc);
 
 #endif /* NET_HUB_H */
diff --git a/net/net.c b/net/net.c
index be03a8d..a66aa02 100644
--- a/net/net.c
+++ b/net/net.c
@@ -441,6 +441,12 @@ void qemu_flush_queued_packets(NetClientState *nc)
 {
     nc->receive_disabled = 0;
 
+    if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) {
+        if (net_hub_flush(nc->peer)) {
+            qemu_notify_event();
+        }
+        return;
+    }
     if (qemu_net_queue_flush(nc->send_queue)) {
         /* We emptied the queue successfully, signal to the IO thread to repoll
          * the file descriptor (for tap, for example).
commit 6b37a23df98faa26391a93373930bfb15b943e00
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Thu Feb 21 13:16:06 2013 +0200

    vhost: memory sync fixes
    
    This fixes two bugs related to memory sync during
    migration:
        - ram address calculation was missing the chunk
          address, so the wrong page was dirtied
        - one after last was used instead of the
          end address of a region, which might overflow to 0
          and cause us to skip the region when the region ends at
          ~0x0ull.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Tested-by: Jason Wang <jasowang at redhat.com>

diff --git a/hw/vhost.c b/hw/vhost.c
index 8d41fdb..37777c2 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -53,10 +53,14 @@ 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;
+            hwaddr page_addr;
+            hwaddr section_offset;
+            hwaddr mr_offset;
             bit -= 1;
-            ram_addr = section->offset_within_region + bit * VHOST_LOG_PAGE;
-            memory_region_set_dirty(section->mr, ram_addr, VHOST_LOG_PAGE);
+            page_addr = addr + bit * VHOST_LOG_PAGE;
+            section_offset = page_addr - section->offset_within_address_space;
+            mr_offset = section_offset + section->offset_within_region;
+            memory_region_set_dirty(section->mr, mr_offset, VHOST_LOG_PAGE);
             log &= ~(0x1ull << bit);
         }
         addr += VHOST_LOG_CHUNK;
@@ -65,14 +69,21 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
 
 static int vhost_sync_dirty_bitmap(struct vhost_dev *dev,
                                    MemoryRegionSection *section,
-                                   hwaddr start_addr,
-                                   hwaddr end_addr)
+                                   hwaddr first,
+                                   hwaddr last)
 {
     int i;
+    hwaddr start_addr;
+    hwaddr end_addr;
 
     if (!dev->log_enabled || !dev->started) {
         return 0;
     }
+    start_addr = section->offset_within_address_space;
+    end_addr = range_get_last(start_addr, section->size);
+    start_addr = MAX(first, start_addr);
+    end_addr = MIN(last, end_addr);
+
     for (i = 0; i < dev->mem->nregions; ++i) {
         struct vhost_memory_region *reg = dev->mem->regions + i;
         vhost_dev_sync_region(dev, section, start_addr, end_addr,
@@ -93,10 +104,18 @@ static void vhost_log_sync(MemoryListener *listener,
 {
     struct vhost_dev *dev = container_of(listener, struct vhost_dev,
                                          memory_listener);
-    hwaddr start_addr = section->offset_within_address_space;
-    hwaddr end_addr = start_addr + section->size;
+    vhost_sync_dirty_bitmap(dev, section, 0x0, ~0x0ULL);
+}
 
-    vhost_sync_dirty_bitmap(dev, section, start_addr, end_addr);
+static void vhost_log_sync_range(struct vhost_dev *dev,
+                                 hwaddr first, hwaddr last)
+{
+    int i;
+    /* FIXME: this is N^2 in number of sections */
+    for (i = 0; i < dev->n_mem_sections; ++i) {
+        MemoryRegionSection *section = &dev->mem_sections[i];
+        vhost_sync_dirty_bitmap(dev, section, first, last);
+    }
 }
 
 /* Assign/unassign. Keep an unsorted array of non-overlapping
@@ -268,16 +287,15 @@ static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size)
 {
     vhost_log_chunk_t *log;
     uint64_t log_base;
-    int r, i;
+    int r;
 
     log = g_malloc0(size * sizeof *log);
     log_base = (uint64_t)(unsigned long)log;
     r = ioctl(dev->control, VHOST_SET_LOG_BASE, &log_base);
     assert(r >= 0);
-    for (i = 0; i < dev->n_mem_sections; ++i) {
-        /* Sync only the range covered by the old log */
-        vhost_sync_dirty_bitmap(dev, &dev->mem_sections[i], 0,
-                                dev->log_size * VHOST_LOG_CHUNK - 1);
+    /* Sync only the range covered by the old log */
+    if (dev->log_size) {
+        vhost_log_sync_range(dev, 0, dev->log_size * VHOST_LOG_CHUNK - 1);
     }
     if (dev->log) {
         g_free(dev->log);
@@ -1014,10 +1032,7 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
                              hdev->vqs + i,
                              hdev->vq_index + i);
     }
-    for (i = 0; i < hdev->n_mem_sections; ++i) {
-        vhost_sync_dirty_bitmap(hdev, &hdev->mem_sections[i],
-                                0, (hwaddr)~0x0ull);
-    }
+    vhost_log_sync_range(hdev, 0, ~0x0ull);
 
     hdev->started = false;
     g_free(hdev->log);


More information about the Spice-commits mailing list